diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..38bbf744 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,5 @@ +[alias] +xtask = "run --quiet --package xtask --" + +[target.wasm32-unknown-unknown] +rustflags = ["-C", "target-feature=+simd128"] diff --git a/.changeset/config.json b/.changeset/config.json index 92dff1ee..12e6b9c0 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -7,13 +7,6 @@ "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", - "ignore": [ - "@latkit/colors-example", - "@latkit/linked-example", - "@latkit/monitor-example", - "@latkit/network-example", - "@latkit/video-example", - "@latkit/diagram-example", - "@latkit/benchmark" - ] + "privatePackages": { "version": false, "tag": false }, + "ignore": [] } diff --git a/.changeset/data-contract.md b/.changeset/data-contract.md new file mode 100644 index 00000000..75e4a31d --- /dev/null +++ b/.changeset/data-contract.md @@ -0,0 +1,10 @@ +--- +'latkit': minor +--- + +Patches are bytes written in TypeScript, datasets change in place, and types come from latkit's schema both ways. + +- Added: `Patch` without WebAssembly (`Patch.to(dataset)`, `fromBytes`, `stream`, `extend`), `Data.read` for latkit bytes and GeoJSON, `data.snapshot()`, queries' `ids`, `total`, and `contains`, `outputs.ts` (events, hits, stats, work, descriptions), and the documentation on Read the Docs. +- Changed: `data.apply(patch)` changes the dataset in place; selections, row fits, `select` and `delete` events, and `neighbors` are row sets `{ data, table, ids }`; `Hit.mark` is the mark's name; picks, locations, and layouts reject with `timeout` past a deadline; `view.arrange()` answers patches that name their datasets; field kinds name geometries (`point`, `path`, `parts`, `polygons`); pictures and videos no longer make the pipelines only input needs. +- Renamed: `put` to `replace`, a query's `where` to `filter`, vertices' `status` to `ring`, `rings` and (off plots) `trace` to `geometry`, `{ colormap: value, map }` to `{ colormap: map, value }`, `{ scale: value, range }` to `{ scale: [low, high], value }`, grid pitches to `{ lines: { pitch } }` and `{ dots: { pitch, snap } }`, the `'earth'` space to `'mercator'`, `forms.ts` to `inputs.ts`, and the error code `load` to `io`. +- Removed: `geojson()` (`Data.read`), `Data.fromBytes`, patch handles and their `destroy()`, `removeTiles` (`removeData`), and bare numbers as row counts (`{ count }`). diff --git a/.changeset/foundation.md b/.changeset/foundation.md new file mode 100644 index 00000000..c5941c88 --- /dev/null +++ b/.changeset/foundation.md @@ -0,0 +1,10 @@ +--- +'latkit': minor +--- + +Histories fetched in spans, and a frame's work follows what changed. + +- Added: time tiles. `view.setTiles(name, url)` opens a `frames.json` manifest, as `latkit tile` writes it, and fetches the spans of each sampled field's history its lines draw, at the detail they draw; a span still loading draws the coarser one above it. +- Added: `Patch.frames(table, field, { level, first }, at, values)`, a run of a sampled field's entries, as a time tile holds them. +- Changed: errors reading JSON (scenes, cameras, fits, queries, rows, budgets, shots) name the path to what could not be read, such as `scene.marks[2].vertices.color`. +- Changed: a patch evaluates only the pages it wrote; a transition evaluates once and blends each frame; rows drawn through tiles keep their places while the camera moves, so only arriving rows upload; the views of a `Gpu` share its budget, none planning past it together. diff --git a/.changeset/opening.md b/.changeset/opening.md new file mode 100644 index 00000000..4155aa2d --- /dev/null +++ b/.changeset/opening.md @@ -0,0 +1,24 @@ +--- +'latkit': minor +--- + +Views open in the time of their slowest pipeline with no frame held back and compile a third fewer pipelines, a patch costs the rows it changed, an edit of a diagram derives only what it reaches, text sets its fields on the GPU, geometry no longer answers the pointer unless asked, and diagrams draw what focus and drags mean. + +- Added: `gpu.step(now)` draws one frame now, and from the first no animation frames are asked for: a harness steps every frame itself; `gpu.done()` resolves once the GPU finished what was submitted, every readback landed, and every pipeline asked for compiled; `gpu.landed()` once work a view waits on lands after the call, or a view asks for a frame; `view.wantsFrame`. +- Added: `Work.late` counts pipelines made without being asked for ahead; `Waiting` names `compiling` while the pipelines a view draws with compile. +- Changed: a view asks for every pipeline its scene can use the first time it draws, and the browser compiles them off its GPU thread, the largest first: what it draws with all at once, the view drawing once that landed and keeping its last frame until then; what lights rows, probes, and answers picks a few at a time while frames draw, those waiting until it landed. No frame waits on a compile and nothing compiles where it is first used; `complete` waits for all of it. +- Changed: the wasm is built without wasm-opt: as small over the wire, and views open sooner, the browser no longer compiling one giant function before their first frame. +- Changed: one probe program per kind of mark answers the hover, picks, boxes, and `locate`, a step at a time: a page compiles about a third fewer pipelines and finishes opening sooner. +- Changed: `pick` lists every row within reach, however many: a mark with more than 1,024 asks again with room for all of them. +- Changed: text sets its distance fields on the GPU, every run set in a frame at once: the host only rasterizes, so labels fill in faster. +- Changed: an edit of the values a diagram sizes and places rows by derives only the rows it wrote and what they reach: their boxes, the groups around them, and the wires they move. A text column written over codes only the rows written. +- Changed: appends one after another to a table, as a stream of frames makes, write as one change. +- Changed: unless `pick` says, rows that are things answer the pointer (vertices, edges, faces, a plot's traces) and geometry does not (areas, and lines along paths: coasts, borders, roads); `pick: true` makes a map's states or cells answer it. +- Changed: a fit in a diagram frames its sheet, blocks and wires, at once without a readback; labels place once a fit has moved the camera; a mark with no rows no longer holds a fit back. +- Changed: a patch of values in a table drawn in part writes only the rows whose values changed. +- Changed: a `drag` event's `position` is where the dragged row goes: where it was grabbed, moved as the pointer moved, snapped to a diagram's dots when its grid snaps. +- Changed: error paths run through the mark's kind, as its JSON does: `marks[2].vertices.color`. +- Changed: the expression node types are named for what they are: `FieldNode`, `ColorNode`, … `ColormapNode`; a size in units is `Units`, your own colormap `CustomColormap`. +- Fixed: lines seen up close no longer break up or vanish: a stroke reaching behind the eye is cut at the near plane instead of dropped, and its pixels are placed on screen however differently deep its ends lie. +- Fixed: a hovered or selected group glows about its border instead of hiding what it holds; a lit block keeps its ports on top; wires stop at the rims of ports, so arrowheads show; rounded wires draw no stray junction dots; an unlabeled block makes room for its ports; great circles settle while their vertices animate. +- Fixed: ports and group borders read against light themes. diff --git a/.changeset/panel-text.md b/.changeset/panel-text.md new file mode 100644 index 00000000..95a728b8 --- /dev/null +++ b/.changeset/panel-text.md @@ -0,0 +1,6 @@ +--- +'latkit': patch +--- + +Keep font-atlas uploads in command order when several views render before one GPU submission. +Multi-panel pictures and videos now retain every panel's titles, axis labels, and legends. diff --git a/.changeset/release-contract.md b/.changeset/release-contract.md new file mode 100644 index 00000000..aa94f8de --- /dev/null +++ b/.changeset/release-contract.md @@ -0,0 +1,11 @@ +--- +'latkit': minor +--- + +Establish the LATK v1 format and tighten the npm, Rust, and CLI release contracts. + +- LATK now has a versioned header, 64-bit absolute sample indexes, explicit stored detail levels, and bounded decoding. Regenerate earlier unversioned files and time tiles from their source data. +- Added `latkit/core` for DOM-free builders and CPU-only Rust expressions, queries, and data loading. +- Fixed video cancellation and output cleanup, arbitrary query field names, URL resolution, and shared GPU device callback ownership. +- Public declarations and API/CLI references now come from checked sources. Packages include consistent MIT licensing and third-party notices. +- Releases verify the installed npm tarball and both Cargo artifacts, and resume missing publications safely before tagging. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5127d909..ef3877f8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,14 +1,70 @@ name: CI +# What a release depends on: the crates build, pass their tests, document, and package on every +# platform they ship to; the npm tarball works in a consumer; the docs build. Frame budgets and the +# benchmark need a GPU, which runners lack: run `cargo xtask check` and `cargo xtask bench` locally. on: pull_request: push: - branches: - - main + branches: [main] + +permissions: + contents: read + +# A new push to a pull request cancels its older run; every commit to main runs to the end, since +# the release waits on it. +concurrency: + group: ci-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: 0 jobs: - quality: + # What a pull request touched; a push to main checks everything. + changes: runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + pull-requests: read + outputs: + rust: ${{ github.event_name != 'pull_request' || steps.filter.outputs.rust == 'true' }} + npm: ${{ github.event_name != 'pull_request' || steps.filter.outputs.npm == 'true' }} + docs: ${{ github.event_name != 'pull_request' || steps.filter.outputs.docs == 'true' }} + steps: + - uses: dorny/paths-filter@v4 + id: filter + if: github.event_name == 'pull_request' + with: + filters: | + rust: &rust + - 'crates/**' + - 'xtask/**' + - '.cargo/**' + - '*.toml' + - 'Cargo.lock' + - 'docs/reference/**' + - '.github/workflows/ci.yml' + npm: + - *rust + - 'npm/**' + - 'benchmark/**' + - 'package.json' + - 'pnpm-*.yaml' + - '*.config.*' + - 'tsconfig*.json' + docs: + - 'docs/**' + - '.readthedocs.yaml' + - 'npm/test/consumer/quickstart.ts' + - '.github/workflows/ci.yml' + + # Prettier over every file: cheap, and any pull request can unformat one. + format: + runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v6 - uses: pnpm/action-setup@v6 @@ -20,30 +76,68 @@ jobs: cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm format:check - - run: pnpm build - - run: pnpm lint - - run: pnpm build:examples - - run: pnpm typecheck - - run: pnpm test:run - - run: pnpm -r --filter "./packages/**" exec npm pack --dry-run - bench: - if: github.event_name == 'pull_request' + rust: + needs: changes + if: needs.changes.outputs.rust == 'true' runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v6 - - uses: pnpm/action-setup@v6 + - run: rustup toolchain install + - uses: Swatinem/rust-cache@v2 with: - version: 10.30.0 - - uses: actions/setup-node@v6 + save-if: ${{ github.ref == 'refs/heads/main' }} + - run: cargo fmt --all --check + - run: cargo clippy --locked --workspace --all-targets --all-features -- -D warnings + - run: cargo clippy --locked -p latkit --no-default-features --all-targets -- -D warnings + - run: cargo clippy --locked -p latkit-js --target wasm32-unknown-unknown -- -D warnings + # Lavapipe, Vulkan on the CPU, runs the GPU tests instead of skipping; text tests need fonts. + - name: Install a software Vulkan driver and fonts for the GPU tests + run: sudo apt-get update && sudo apt-get install -y mesa-vulkan-drivers fonts-dejavu-core + - run: cargo test --locked --workspace + env: + LATKIT_REQUIRE_GPU: 1 + - run: cargo test --locked -p latkit --no-default-features + env: + LATKIT_REQUIRE_GPU: 1 + - name: Document the library + run: cargo doc --locked -p latkit --no-deps --all-features + env: + RUSTDOCFLAGS: -D warnings + - name: Verify the native package + run: cargo package --locked -p latkit + - name: Verify the browser-target package + run: cargo package --locked -p latkit --target wasm32-unknown-unknown --features web + - name: Keep native font code out of browser builds + run: cargo check --locked -p latkit --target wasm32-unknown-unknown --features native,web + + # The CLI's native code on the other platforms it installs on; Linux runs in `rust`. + native-cli: + needs: changes + if: needs.changes.outputs.rust == 'true' + strategy: + fail-fast: false + matrix: + os: [macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + steps: + - uses: actions/checkout@v6 + - run: rustup toolchain install + - uses: Swatinem/rust-cache@v2 with: - node-version: 24 - cache: pnpm - - run: pnpm install --frozen-lockfile - - run: pnpm bench:gate + save-if: ${{ github.ref == 'refs/heads/main' }} + - run: cargo test --locked --package latkit --features native --lib --test validation + - run: cargo test --locked --package latkit-cli - docs: + # The npm package: built from the crate, checked, tested, every pipeline compiled in Chrome on + # SwiftShader, and the packed tarball installed and drawn in a consumer. + npm: + needs: changes + if: needs.changes.outputs.npm == 'true' runs-on: ubuntu-latest + timeout-minutes: 40 steps: - uses: actions/checkout@v6 - uses: pnpm/action-setup@v6 @@ -53,9 +147,56 @@ jobs: with: node-version: 24 cache: pnpm + - run: rustup toolchain install + - uses: Swatinem/rust-cache@v2 + with: + save-if: ${{ github.ref == 'refs/heads/main' }} + - run: pnpm install --frozen-lockfile + - name: Read the WASM bindings generator's version + id: bindgen + run: | + echo "version=$(python3 -c 'import tomllib; print(next(p["version"] for p in tomllib.load(open("Cargo.lock", "rb"))["package"] if p["name"] == "wasm-bindgen"))')" >> "$GITHUB_OUTPUT" + - uses: actions/cache@v4 + id: bindgen-cache + with: + path: ~/.cargo/bin/wasm-bindgen + key: wasm-bindgen-cli-${{ steps.bindgen.outputs.version }} + - name: Install the matching WASM bindings generator + if: steps.bindgen-cache.outputs.cache-hit != 'true' + run: cargo install wasm-bindgen-cli --version "${{ steps.bindgen.outputs.version }}" --locked + - run: pnpm --dir npm/examples exec playwright-core install --with-deps chromium + - run: cargo xtask wasm --dev + - run: pnpm lint + - run: node npm/docs.mjs --check + - run: pnpm typecheck + - run: pnpm test + - run: cargo xtask browser + - run: cargo xtask package + - run: cargo xtask package-test + + # The docs as Read the Docs builds them: a warning fails. + docs: + needs: changes + if: needs.changes.outputs.docs == 'true' + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: python-version: '3.13' - - run: pnpm install --frozen-lockfile - - run: python -m pip install -r docs/requirements.txt - - run: pnpm docs:build + cache: pip + cache-dependency-path: docs/requirements.txt + - run: pip install -r docs/requirements.txt + - run: sphinx-build -W --keep-going -b html docs target/docs + + # The one check branch protection requires: every job above passed, or was not needed. + passed: + name: CI passed + if: always() + needs: [changes, format, rust, native-cli, npm, docs] + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: exit 1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 06834095..f3ec8441 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,74 +1,121 @@ name: Release +# Once CI passes on main, releases the commit it tested. on: - push: + workflow_dispatch: + workflow_run: + workflows: + - CI + types: + - completed branches: - main concurrency: ${{ github.workflow }}-${{ github.ref }} permissions: - contents: write - id-token: write - pull-requests: write + contents: read env: CI: true + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: 0 NPM_CONFIG_ACCESS: public NPM_CONFIG_PROVENANCE: true jobs: + # What the commit releases: pending changesets open or update the version PR, a version not yet + # tagged publishes, and a tagged one has nothing left to do. + plan: + # A push's run only: a pull request's run can come from a fork's branch named main. + if: (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push') + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + actions: read + contents: read + outputs: + step: ${{ steps.plan.outputs.step }} + steps: + - uses: actions/checkout@v6 + with: + ref: ${{ github.event.workflow_run.head_sha || github.sha }} + - name: Verify manual recovery uses a commit that passed CI + if: github.event_name == 'workflow_dispatch' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh run list --workflow ci.yml --branch main --commit "$(git rev-parse HEAD)" --json conclusion --jq 'any(.[]; .conclusion == "success")' | grep -qx true + - name: Decide what the commit releases + id: plan + run: | + version=$(jq -r .version npm/package.json) + if compgen -G '.changeset/*.md' > /dev/null; then + echo "step=version" >> "$GITHUB_OUTPUT" + elif git ls-remote --exit-code --tags origin "refs/tags/latkit@$version" > /dev/null; then + echo "step=none" >> "$GITHUB_OUTPUT" + else + echo "step=publish" >> "$GITHUB_OUTPUT" + fi + release: - name: Version or publish packages + name: Version or publish + needs: plan + if: needs.plan.outputs.step != 'none' runs-on: ubuntu-latest + timeout-minutes: 60 + permissions: + contents: write + id-token: write + pull-requests: write + env: + PUBLISH: ${{ needs.plan.outputs.step == 'publish' }} steps: - - name: Checkout repo - uses: actions/checkout@v6 + - uses: actions/checkout@v6 with: + ref: ${{ github.event.workflow_run.head_sha || github.sha }} fetch-depth: 0 - - - name: Setup pnpm - uses: pnpm/action-setup@v6 + - uses: pnpm/action-setup@v6 with: version: 10.30.0 - - - name: Setup Node.js - uses: actions/setup-node@v6 + - uses: actions/setup-node@v6 with: node-version: 24 cache: pnpm registry-url: https://registry.npmjs.org/ - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Check formatting - run: pnpm format:check - - - name: Build packages - run: pnpm build - - - name: Lint sources - run: pnpm lint - - - name: Build examples - run: pnpm build:examples - - - name: Typecheck packages - run: pnpm typecheck - - - name: Test packages - run: pnpm test:run - - - name: Check publish payloads - run: pnpm -r --filter "./packages/**" exec npm pack --dry-run - - - name: Create release PR or publish to npm + - run: rustup toolchain install + - uses: Swatinem/rust-cache@v2 + - run: pnpm install --frozen-lockfile + - name: Read the WASM bindings generator's version + if: env.PUBLISH == 'true' + id: bindgen + run: | + echo "version=$(python3 -c 'import tomllib; print(next(p["version"] for p in tomllib.load(open("Cargo.lock", "rb"))["package"] if p["name"] == "wasm-bindgen"))')" >> "$GITHUB_OUTPUT" + - uses: actions/cache@v4 + if: env.PUBLISH == 'true' + id: bindgen-cache + with: + path: ~/.cargo/bin/wasm-bindgen + key: wasm-bindgen-cli-${{ steps.bindgen.outputs.version }} + - name: Install the matching WASM bindings generator + if: env.PUBLISH == 'true' && steps.bindgen-cache.outputs.cache-hit != 'true' + run: cargo install wasm-bindgen-cli --version "${{ steps.bindgen.outputs.version }}" --locked + - if: env.PUBLISH == 'true' + run: pnpm --dir npm/examples exec playwright-core install --with-deps chromium + # The tarball a consumer installs, checked in Chrome; `pnpm release` publishes this file. + - if: env.PUBLISH == 'true' + run: cargo xtask package + - if: env.PUBLISH == 'true' + run: cargo xtask package-test + # One retryable release verifies npm and both crates before creating tags. + - name: Open a version pull request, or publish all distributions id: changesets uses: changesets/action@v1 with: + version: pnpm version-packages publish: pnpm release commit: 'chore: version packages' title: 'chore: version packages' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/.gitignore b/.gitignore index daf8bdbe..13cafb73 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,15 @@ node_modules/ dist/ coverage/ -docs/_build/ -docs/api/reference/ -.turbo/ .DS_Store *.log -output/ -.bench/ -benchmark/.results/ .playwright-cli/ +.playwright-mcp/ .impeccable/ +target/ +/npm/pkg/ + +# The CLI examples' videos: each example's README says how to render its own. +/crates/latkit-cli/examples/*/*.mp4 diff --git a/.prettierignore b/.prettierignore index 19de8ce2..a380b666 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,15 +1,17 @@ node_modules dist coverage -docs/_build -docs/api/reference pnpm-lock.yaml -packages/*/dist -examples/*/dist .impeccable/ -.bench/ -benchmark/.results/ -output/ .playwright-cli/ -packages/monitor/tests/browser/generated +target +npm/pkg +npm/dist +crates/latkit/colormaps +npm/test/scenes.js +# Written by the CLI examples' scripts, and by the bench. +crates/latkit-cli/examples/**/*.json +benchmark/baselines +# Written by the schema test: LATKIT_BLESS=1 cargo test -p latkit --test schema. +npm/schema.json diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 6e1f35cc..82447157 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -4,14 +4,6 @@ build: os: ubuntu-24.04 tools: python: '3.13' - nodejs: '24' - jobs: - post_install: - - corepack enable - - corepack prepare pnpm@10.30.0 --activate - - corepack pnpm install --frozen-lockfile - pre_build: - - corepack pnpm docs:api python: install: diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..22becc20 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,50 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "examples", + "detail": "Stop any running example server, build the wasm (--dev), serve the example suite at http://127.0.0.1:5200, and open it", + "type": "shell", + "command": "cargo xtask examples --open", + "dependsOn": "examples: stop", + "problemMatcher": [], + "options": { + "statusbar": { + "label": "$(play) Examples", + "detail": "Build and serve npm/examples, then open it in the browser", + "running": { "label": "$(sync~spin) Examples" } + } + } + }, + { + "label": "examples: stop", + "detail": "Stop whatever serves the example suite at http://127.0.0.1:5200", + "type": "process", + "command": "powershell.exe", + "args": [ + "-NoProfile", + "-Command", + "$ids = Get-NetTCPConnection -LocalPort 5200 -State Listen -ErrorAction SilentlyContinue | Select-Object -ExpandProperty OwningProcess -Unique; foreach ($id in $ids) { taskkill /PID $id /T /F | Out-Null }; if ($ids) { 'Stopped the example server.' } else { 'No example server was running.' }" + ], + "osx": { + "command": "sh", + "args": [ + "-c", + "pids=$(lsof -ti tcp:5200 -sTCP:LISTEN); if [ -n \"$pids\" ]; then kill $pids && echo 'Stopped the example server.'; else echo 'No example server was running.'; fi" + ] + }, + "linux": { + "command": "sh", + "args": [ + "-c", + "pids=$(lsof -ti tcp:5200 -sTCP:LISTEN); if [ -n \"$pids\" ]; then kill $pids && echo 'Stopped the example server.'; else echo 'No example server was running.'; fi" + ] + }, + "problemMatcher": [], + "presentation": { "reveal": "silent", "close": true }, + "options": { + "statusbar": { "label": "$(debug-stop)", "detail": "Stop the example server" } + } + } + ] +} diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..06a9b180 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2590 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aho-corasick" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android_system_properties" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" +dependencies = [ + "libc", +] + +[[package]] +name = "annotate-snippets" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f211a51805bc641f3ad5b7664c77d2547af685cc33b4cd8d31964027a46f13f1" +dependencies = [ + "anstyle", + "memchr", + "unicode-width", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "bit-set" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2f926cc3060f09db9ebc5b52823d85268d24bb917e472c0c4bea35780a7d" +dependencies = [ + "bit-vec 0.9.1", +] + +[[package]] +name = "bit-set" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56d87354e4229f54a44f7bf2435906a4656dba36026ab6eaca629a2c436a691c" +dependencies = [ + "bit-vec 0.10.1", +] + +[[package]] +name = "bit-vec" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" + +[[package]] +name = "bit-vec" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5727b15fa97d4f4fee0a3b7c3d550ed0269f54329207b86388de918604e31269" +dependencies = [ + "borsh", + "serde", +] + +[[package]] +name = "bitflags" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + +[[package]] +name = "borsh" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "553c5d846a6ba5150c65e3b1b8ec073bcf1abc20f9b7220de384a4443ea4e20a" +dependencies = [ + "borsh-derive", + "bytes", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cdfe656708a01f89b451a7d36466e6fe6c414de0aa18fc54f864f6f9ca9f56" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytemuck" +version = "1.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1f896587b6f2c069c73d2f0913e2d590c3990285cd2f0b6aa02b786b4c679c" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" + +[[package]] +name = "cfg-if" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" + +[[package]] +name = "cfg_aliases" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" + +[[package]] +name = "chacha20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core", +] + +[[package]] +name = "clap" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_derive" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "clap_lex" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" + +[[package]] +name = "codespan-reporting" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core_detect" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48" + +[[package]] +name = "core_maths" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30" +dependencies = [ + "libm", +] + +[[package]] +name = "cosmic-text" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be17b688510d934ce13f48a2beba700e11583e281e0fda99c22bb256a14eda73" +dependencies = [ + "bitflags", + "fontdb", + "harfrust", + "linebender_resource_handle", + "log", + "rangemap", + "rustc-hash 2.1.3", + "self_cell", + "skrifa", + "smol_str", + "swash", + "sys-locale", + "unicode-bidi", + "unicode-linebreak", + "unicode-script", + "unicode-segmentation", +] + +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.119", + "unicode-xid", +] + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags", + "objc2", +] + +[[package]] +name = "displaydoc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "either" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" +dependencies = [ + "crc32fast", + "miniz_oxide 0.9.1", + "zlib-rs", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "font-types" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b38ad915f6dadd993ced50848a8291a543bd41ca62bc10740d5e64e2ab4cfd7" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "fontconfig-parser" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" +dependencies = [ + "roxmltree", +] + +[[package]] +name = "fontdb" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "457e789b3d1202543297a350643cf459f836cade38934e7a4cf6a39e7cde2905" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2", + "slotmap", + "tinyvec", + "ttf-parser", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-core" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" + +[[package]] +name = "futures-task" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" + +[[package]] +name = "futures-util" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "rand_core", +] + +[[package]] +name = "glam" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc148d4ddd3930c52f9e5ae79b89805c6f07e9ff417e7b083e0348cea60a5aba" + +[[package]] +name = "glob" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" + +[[package]] +name = "gpu-allocator" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51255ea7cfaadb6c5f1528d43e92a82acb2b96c43365989a28b2d44ee38f8795" +dependencies = [ + "ash", + "hashbrown 0.16.1", + "log", + "presser", + "thiserror", + "windows", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", +] + +[[package]] +name = "harfrust" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9da2e5ae821f6e96664977bf974d6d6a2d6682f9ccee23e62ec1d134246845f9" +dependencies = [ + "bitflags", + "bytemuck", + "core_maths", + "read-fonts", + "smallvec", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "foldhash", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "icu_collections" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" + +[[package]] +name = "icu_properties" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" + +[[package]] +name = "icu_provider" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error 2.0.1", +] + +[[package]] +name = "indexmap" +version = "2.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jpeg-encoder" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0370574b86f7eca156b9f298392b5e69a23f8c86f3f865add60bbc2e79467a6" + +[[package]] +name = "js-sys" +version = "0.3.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "lalrpop-util" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884f3e747ed2dcee867cda1b0c31a048f9e20de2d916a248949319921a2e666e" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "latkit" +version = "0.1.0" +dependencies = [ + "bytemuck", + "cosmic-text", + "flate2", + "glam", + "hashbrown 0.17.1", + "image-webp", + "jpeg-encoder", + "js-sys", + "naga", + "png", + "pollster", + "proptest", + "rustc-hash 2.1.3", + "schemars", + "serde", + "serde_json", + "serde_path_to_error", + "thiserror", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "web-time", + "wesl", + "wgpu", + "windows", + "windows-core", +] + +[[package]] +name = "latkit-cli" +version = "0.1.0" +dependencies = [ + "clap", + "latkit", + "schemars", + "serde", + "serde_json", + "tempfile", +] + +[[package]] +name = "latkit-js" +version = "0.1.0" +dependencies = [ + "console_error_panic_hook", + "futures-util", + "js-sys", + "latkit", + "serde", + "serde_json", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "lexical" +version = "7.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc8a009b2ff1f419ccc62706f04fe0ca6e67b37460513964a3dfdb919bb37d6" +dependencies = [ + "lexical-core", +] + +[[package]] +name = "lexical-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d8d125a277f807e55a77304455eb7b1cb52f2b18c143b60e766c120bd64a594" +dependencies = [ + "lexical-parse-float", + "lexical-parse-integer", + "lexical-util", + "lexical-write-float", + "lexical-write-integer", +] + +[[package]] +name = "lexical-parse-float" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52a9f232fbd6f550bc0137dcb5f99ab674071ac2d690ac69704593cb4abbea56" +dependencies = [ + "lexical-parse-integer", + "lexical-util", +] + +[[package]] +name = "lexical-parse-integer" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a7a039f8fb9c19c996cd7b2fcce303c1b2874fe1aca544edc85c4a5f8489b34" +dependencies = [ + "lexical-util", +] + +[[package]] +name = "lexical-util" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2604dd126bb14f13fb5d1bd6a66155079cb9fa655b37f875b3a742c705dbed17" + +[[package]] +name = "lexical-write-float" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c438c87c013188d415fbabbb1dceb44249ab81664efbd31b14ae55dabb6361" +dependencies = [ + "lexical-util", + "lexical-write-integer", +] + +[[package]] +name = "lexical-write-integer" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "409851a618475d2d5796377cad353802345cba92c867d9fbcde9cf4eac4e14df" +dependencies = [ + "lexical-util", +] + +[[package]] +name = "libc" +version = "0.2.190" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "linebender_resource_handle" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a5ff6bcca6c4867b1c4fd4ef63e4db7436ef363e0ad7531d1558856bae64f4" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" + +[[package]] +name = "litrs" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4744e383959f0db86ede514b809b1c53251889093803c05267acc7d4e7030d70" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" + +[[package]] +name = "logos" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2c55a318a87600ea870ff8c2012148b44bf18b74fad48d0f835c38c7d07c5f" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-codegen" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58b3ffaa284e1350d017a57d04ada118c4583cf260c8fb01e0fe28a2e9cf8970" +dependencies = [ + "fnv", + "proc-macro2", + "quote", + "regex-automata", + "regex-syntax", + "syn 2.0.119", +] + +[[package]] +name = "logos-derive" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d3a9855747c17eaf4383823f135220716ab49bea5fbea7dd42cc9a92f8aa31" +dependencies = [ + "logos-codegen", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "memmap2" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" +dependencies = [ + "libc", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "miniz_oxide" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "naga" +version = "30.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a616d2fb8c89516ac2723a581f69d6c18576046bed761bd6b305e5618e6ae130" +dependencies = [ + "arrayvec", + "bit-set 0.10.0", + "bitflags", + "cfg-if", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.17.1", + "indexmap", + "libm", + "log", + "naga-types", + "num-traits", + "once_cell", + "rustc-hash 1.1.0", + "spirv", + "thiserror", + "unicode-ident", +] + +[[package]] +name = "naga-types" +version = "30.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "590afbf58a6f4f62873cd5cff4468061844bafa1cdf399cc954537c22d768d49" +dependencies = [ + "hashbrown 0.17.1", + "indexmap", + "rustc-hash 1.1.0", + "thiserror", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "objc2" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08849bbd4767dfae9457696856ae1c84fe4e0281bbe4a7abff2d0e06fb7981f8" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags", + "dispatch2", + "objc2", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "dispatch2", + "objc2", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" +dependencies = [ + "bitflags", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "ordered-float" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7c9e0d9b23589f26070720bac724174bfec1083e82f7854cdd0267518343c0" +dependencies = [ + "num-traits", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.9", +] + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "portable-atomic" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" + +[[package]] +name = "portable-atomic-util" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10ab3eb7f3becc3a1cbc4f2c6f20267996cfc1a6467a873763411b136a122715" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" +dependencies = [ + "zerovec", +] + +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" + +[[package]] +name = "proptest" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8530004ccb15eae51c7e40009fbe317f341f804db54dc033eec1c50be28cfa0" +dependencies = [ + "bit-set 0.11.1", + "bit-vec 0.10.1", + "bitflags", + "chacha20", + "core_detect", + "num-traits", + "rand", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" +dependencies = [ + "getrandom", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_xorshift" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60aa6af80be32871323012e02e6e65f8a7cc7890931ae421d217ad8fe0df2ccf" +dependencies = [ + "rand_core", +] + +[[package]] +name = "range-alloc" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" + +[[package]] +name = "rangemap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a611d15b50743feb4c76b7d03edcb0e64f399c26961e4efe6975bc398be6aa3d" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "raw-window-metal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" +dependencies = [ + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "read-fonts" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5" +dependencies = [ + "bytemuck", + "core_maths", + "font-types", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "regex-automata" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "rusty-fork" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" +dependencies = [ + "fnv", + "quick-error 1.2.3", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "schemars" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab508826f74a77ca9d5aba6ff19b522583ee3eaf28a19384ff3d0e5835fadf6e" +dependencies = [ + "dyn-clone", + "ref-cast", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1c3a92094fa7d61aa124645844facb6b554dfc797136d0f5fd1f890e2bffc69" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 3.0.9", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "self_cell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab42ca02749e120097e328d91d415325bdf43b1c72c4c8badf37375fe40a813" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "serde_derive_internals" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f852137cce035d6a4df67ccce505ff6b3e9fd3a10e3e52b24dc71e650bb1a9bd" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "serde_json" +version = "1.0.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6" +dependencies = [ + "foldhash", + "indexmap", + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_path_to_error" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +dependencies = [ + "itoa", + "serde", + "serde_core", +] + +[[package]] +name = "serde_spanned" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7523beb55eece201a2356bee0bbca0d1ab466c14c07703b2e0ee6d42cb0c2c" +dependencies = [ + "serde_core", +] + +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" + +[[package]] +name = "skrifa" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac" +dependencies = [ + "bytemuck", + "read-fonts", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b" + +[[package]] +name = "smol_str" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aaa7368fcf4852a4c2dd92df0cace6a71f2091ca0a23391ce7f3a31833f1523" + +[[package]] +name = "spirv" +version = "0.4.0+sdk-1.4.341.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9571ea910ebd84c86af4b3ed27f9dbdc6ad06f17c5f96146b2b671e2976744f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "swash" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c2499c2d826531388872b2268718aed907a39bd785ab0dcfe57fab26283f92e" +dependencies = [ + "skrifa", + "yazi", + "zeno", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "tinystr" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3ca314f692efd6c868f8408f53fe444634a845f96c028b97d35f6a1f79f0ee" + +[[package]] +name = "tokio" +version = "1.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e95f91fcc7a621e8b030f6aa23c71fe9838ae2fb4d8118b75602a328f5144044" +dependencies = [ + "pin-project-lite", +] + +[[package]] +name = "toml" +version = "1.1.8+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20489e00e4d8741d6be680764cc12e270655e375a20d1011e844a9c3379e678d" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b86d767906c6c42421dcba507eb9d203e779497710a47782a224bb871653053" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.17+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3641d5bbb5349a79e1020a242d251efbc546ad8048d133958323ce9c40a9c9c" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baa693a8032d7e1cada7d0041e96126df243179ff061456783ac7f12bda4744c" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06bdbd8cfc056b8d2e2e85f29b56a3bdbecb527cef81eb39e3e7b98af4652770" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" +dependencies = [ + "core_maths", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-ident" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563" + +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-script" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" + +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cbab34de2d982e9b48e18d216d04c4a6f641066ff19ffb699980f591ee3610e" +dependencies = [ + "js-sys", + "tokio", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 3.0.9", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88261b9deccee56594c11a3460c462c41f58d148598fe70ad77070126a68aba4" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wesl" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd8f9619baa4c7bde4df0899d6f626b70ee92d6e9c18c5f74473419b5bb6fa6" +dependencies = [ + "annotate-snippets", + "anstream", + "derive_more", + "glob", + "half", + "itertools", + "num-traits", + "serde", + "thiserror", + "toml", + "wesl-core", + "wesl-macros", + "wgsl-parse", + "wgsl-types", +] + +[[package]] +name = "wesl-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84dd3e600497eda0b47afcd21bd84c8953a9dfce7e93ed27a38ba97ac0747e03" + +[[package]] +name = "wesl-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac8767ec26e75262a8e581d5f188b1f63a288baaf885bb33c9f4f73a693e06fc" +dependencies = [ + "itertools", + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "wgpu" +version = "30.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527ccdf43dd5b2e8676eed9984ce00e2bbb0a1b85b70c1969dcb6cd2eb55ab9e" +dependencies = [ + "arrayvec", + "bitflags", + "bytemuck", + "cfg-if", + "cfg_aliases", + "document-features", + "hashbrown 0.17.1", + "js-sys", + "log", + "naga", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "30.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c018fce9b6270aa203c2fdd56f3cce996713534bd757e4ea58c8560b121f14" +dependencies = [ + "arrayvec", + "bit-set 0.10.0", + "bit-vec 0.9.1", + "bitflags", + "bytemuck", + "cfg_aliases", + "document-features", + "hashbrown 0.17.1", + "indexmap", + "log", + "naga", + "naga-types", + "once_cell", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "rustc-hash 1.1.0", + "smallvec", + "thiserror", + "wgpu-core-deps-apple", + "wgpu-core-deps-windows-linux-android", + "wgpu-hal", + "wgpu-naga-bridge", + "wgpu-types", +] + +[[package]] +name = "wgpu-core-deps-apple" +version = "30.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061f3d319a40d39d00b1ecc2c33b89fe21d4e6fe01859df3500a3a8ecccd6b68" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "30.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7586165fd5f6d881cb9ce4bb71f40d6caab2c0f1837e3fc1d9788a197fb6004f" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-hal" +version = "30.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b7fb58561a792bc237628ba0792e332de418fefe145f13b5ed8201e6d52f58" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set 0.10.0", + "bitflags", + "block2", + "bytemuck", + "cfg-if", + "cfg_aliases", + "gpu-allocator", + "hashbrown 0.17.1", + "libc", + "libloading", + "log", + "naga", + "naga-types", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation", + "objc2-metal", + "objc2-quartz-core", + "once_cell", + "ordered-float", + "parking_lot", + "portable-atomic", + "portable-atomic-util", + "profiling", + "range-alloc", + "raw-window-handle", + "raw-window-metal", + "renderdoc-sys", + "smallvec", + "static_assertions", + "thiserror", + "wgpu-naga-bridge", + "wgpu-types", + "windows", + "windows-core", +] + +[[package]] +name = "wgpu-naga-bridge" +version = "30.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f62e73117bb7a62bfd9c5a5841438a823f6566c6442a808ee269d2d055c081" +dependencies = [ + "naga", + "wgpu-types", +] + +[[package]] +name = "wgpu-types" +version = "30.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99dad6f1fbdbbdb4c278a6508b059d44688f5cebddf78d005a46a31340269286" +dependencies = [ + "bitflags", + "bytemuck", + "js-sys", + "log", + "naga-types", + "raw-window-handle", + "static_assertions", + "web-sys", +] + +[[package]] +name = "wgsl-parse" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37cee524ba5cfabfd65d10a316b646f8a4c50f3663e7e787471f21b783261f47" +dependencies = [ + "annotate-snippets", + "derive_more", + "itertools", + "lalrpop-util", + "lexical", + "logos", + "thiserror", + "wgsl-types", +] + +[[package]] +name = "wgsl-types" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e119dd12e57d937397535201959ddddb5dbf26505402db5ef305ebb1ca9a7e5f" +dependencies = [ + "half", + "itertools", + "num-traits", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +dependencies = [ + "memchr", +] + +[[package]] +name = "writeable" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" + +[[package]] +name = "xtask" +version = "0.1.0" +dependencies = [ + "serde_json", + "toml_edit", +] + +[[package]] +name = "yazi" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" + +[[package]] +name = "yoke" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", + "synstructure", +] + +[[package]] +name = "zeno" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" + +[[package]] +name = "zerocopy" +version = "0.8.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86502bf56ac7c77571a32e2647bb2a15894565e981fb2a48d7bde2d91c965a9d" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5457206954b06561e2608c7e19cf58b1926586d999c246eebe4502f7e2039d1a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "zlib-rs" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b268e58e7c693d7c271f93ffc4ba3b380412554231c85bf61ca7af91042a4112" + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..5d593867 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,105 @@ +[workspace] +members = ["crates/*", "xtask"] +default-members = ["crates/latkit"] +resolver = "3" + +[workspace.package] +version = "0.1.0" +edition = "2024" +rust-version = "1.99" +license = "MIT" +repository = "https://github.com/lukelowry/latkit" +homepage = "https://latkit.readthedocs.io" + +[workspace.dependencies] +url = "2" +futures-util = { version = "0.3", default-features = false, features = ["std"] } +toml_edit = "0.25" +latkit = { version = "0.1.0", path = "crates/latkit", default-features = false } + +thiserror = "2" +hashbrown = { version = "0.17", default-features = false, features = ["default-hasher", "inline-more"] } +rustc-hash = "2" + +# Match Gpu::new: primary native backends and browser WebGPU, without unused GLES. +wgpu = { version = "30", default-features = false, features = ["std", "parking_lot", "dx12", "metal", "vulkan", "wgsl", "webgpu"] } +bytemuck = { version = "1", features = ["derive"] } +glam = "0.34" +web-time = "1" + +wesl = "0.6" +naga = { version = "30", features = ["wgsl-in"] } + +serde = { version = "1", features = ["derive", "rc"] } +serde_json = "1" +serde_path_to_error = "0.1" +schemars = { version = "1", default-features = false, features = ["derive", "std", "preserve_order"] } +flate2 = "1" +image-webp = "0.2" +jpeg-encoder = "0.7" +png = "0.18" + +wasm-bindgen = "0.2" +wasm-bindgen-futures = "0.4" +js-sys = "0.3" +web-sys = "0.3" +console_error_panic_hook = "0.1" + +proptest = "1" +pollster = "0.4" +cosmic-text = { version = "0.19", default-features = false, features = ["std", "swash", "fontconfig"] } +clap = { version = "4", default-features = false, features = ["derive", "std", "help", "usage", "error-context"] } +tempfile = "3" +windows = { version = "0.62.2", features = [ + "Win32_Media_MediaFoundation", + "Win32_System_Com", + "Win32_System_Ole", + "Win32_System_Variant", +] } +# What `windows::core::implement` expands to: COM objects of ours, such as callbacks. +windows-core = "0.62.2" + +[workspace.lints.rust] +unsafe_code = "deny" +missing_docs = "warn" +unreachable_pub = "warn" + +[workspace.lints.clippy] +pedantic = { level = "warn", priority = -1 } +module_name_repetitions = "allow" +must_use_candidate = "allow" +missing_errors_doc = "allow" +missing_panics_doc = "allow" +cast_possible_truncation = "allow" +cast_precision_loss = "allow" +cast_sign_loss = "allow" +cast_possible_wrap = "allow" +similar_names = "allow" +many_single_char_names = "allow" +float_cmp = "allow" +struct_excessive_bools = "allow" + +[profile.release] +lto = "fat" +codegen-units = 1 + +# The executable: release speed for its CPU work (JSON, PNG, layout, text), without symbols. +[profile.cli] +inherits = "release" +strip = true + +[profile.wasm] +inherits = "release" +opt-level = 3 +panic = "abort" +strip = true + +[profile.wasm-dev] +inherits = "wasm" +opt-level = 2 +lto = false +codegen-units = 16 +incremental = true + +[profile.dev.package."*"] +opt-level = 2 diff --git a/README.md b/README.md index be9b98e6..05c77d09 100644 --- a/README.md +++ b/README.md @@ -1,73 +1,47 @@ -

- Latkit visualization banner -

- # Latkit [![CI](https://github.com/lukelowry/latkit/actions/workflows/ci.yml/badge.svg)](https://github.com/lukelowry/latkit/actions/workflows/ci.yml) -[![Documentation Status](https://readthedocs.org/projects/latkit/badge/?version=latest)](https://latkit.readthedocs.io/en/latest/) - -TypeScript tools for WebGPU network views, maps, time-series plots, block diagrams, and video -export. - -[Documentation](https://latkit.readthedocs.io/en/latest/) · [API reference](https://latkit.readthedocs.io/en/latest/api/index.html) · [Examples](examples) -## Install - -```sh -npm install @latkit/model @latkit/gpu @latkit/network -``` +Columnar data drawn as vertices, edges, lines, and areas on the GPU: networks on a plane, a map, or +a globe, plots of sampled fields, and block diagrams, from a scene and named data. One Rust crate +draws them, in the browser through the npm package and natively through the CLI. -Use an ESM bundler and a WebGPU-capable browser. +| Part | Use | +| --------------------------------- | ------------------------------------------------------------------------------------------ | +| [`latkit`](crates/latkit) | The library: data, expressions, scenes, views, pictures, and video | +| [npm `latkit`](npm) | The library in the browser, its scenes as JSON with generated types | +| [`latkit-cli`](crates/latkit-cli) | Scenes of JSON or binary data rendered to images and videos | +| [Examples](npm/examples) | Every feature on a page, and the browser gate that drives them | +| [Benchmark](benchmark) | Each scenario's phases up its sizes, held to committed work and times | +| [Docs](docs) | How-tos for the npm package and the CLI, on [Read the Docs](https://latkit.readthedocs.io) | -## Draw a network +The `@latkit/*` TypeScript packages, a lighter alternative without WebAssembly, are maintained on +the [`npm/js`](https://github.com/lukelowry/latkit/tree/npm/js) branch. ```ts -import { createGpu } from '@latkit/gpu'; -import { createNetwork } from '@latkit/network'; - -const gpu = await createGpu(); -const network = createNetwork(gpu, { - canvas, - source, - vertices: { Bus: { color: 'load', labels: 'name' } }, - edges: { Line: { ends: ['from', 'to'] } }, -}); -network.on('select', (items) => console.log(items)); -network.set({ at: 12 }); - -network.destroy(); // never closes the source or the GPU +import { loadLatkit, Patch, type Scene } from 'latkit'; + +const { Data, Gpu } = await loadLatkit(); +const gpu = await Gpu.create(); +const data = new Data('grid').apply(new Patch().replace('Bus', [1, 2], { x: [0, 30], y: [0, 20] })); +const scene: Scene = { + space: 'plane', + marks: [{ vertices: { of: ['grid', 'Bus'], position: ['x', 'y'], radius: 6 } }], +}; +const view = gpu.view(scene); +gpu.canvas(document.querySelector('canvas')!).show([view]); +view.setData(data); ``` -`source` is a `Data` from [`@latkit/model`](packages/model). `canvas` needs a CSS size; the network -draws on it and handles its input. Geographies, monitors, and diagrams work the same way; see -[views](https://latkit.readthedocs.io/en/latest/views.html). - -## Packages - -| Package | Use | -| ------------------------------- | -------------------------------------------------- | -| [model](packages/model) | Columnar data, bounded reads, the `Model` contract | -| [connect](packages/connect) | Carry a model across a WebSocket | -| [gpu](packages/gpu) | The shared GPU, compositions, and colors | -| [network](packages/network) | Vertices and edges, flat or on a globe | -| [geography](packages/geography) | The earth beneath: areas, lines, and vector tiles | -| [monitor](packages/monitor) | Time-series plots and live telemetry | -| [diagram](packages/diagram) | Block diagrams with layout, routing, and editing | -| [video](packages/video) | MP4 and WebM export | - ## Develop -Requires Node.js 24 and pnpm 10.30. +Requires Rust (pinned in `rust-toolchain.toml`), Node.js 24, and pnpm 10.30. ```sh pnpm install -pnpm --filter @latkit/network-example dev -pnpm quality -pnpm build:examples -pnpm docs:build +cargo xtask examples --open # the example pages at http://127.0.0.1:5200 +cargo xtask check # format, lint, test, typecheck, and the browser gate +cargo xtask bench --quick # every benchmark scenario once, at its smallest size ``` -See [release checks](docs/release-process.md) for browser tests and packaging. - Created by [Luke Lowery](https://lukelowry.github.io/). [MIT License](LICENSE). diff --git a/benchmark/README.md b/benchmark/README.md index f93a9d9d..30e9801f 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -1,31 +1,29 @@ -# Benchmarks +# Benchmark -Each `*.bench.ts` times one package, or several together, through public entry points only, at -several sizes, such as 10 thousand to a million buses. A null WebGPU device (`device.ts`) does no -GPU work, so the benchmarks time the JavaScript a frame costs and need no GPU. Real GPU timings come -from each package's browser check. Text goes through a fixed-metric rasterizer, so the benchmarks -count rasterizations rather than timing fonts. +Each scenario's phases, up its sizes, in Chrome: time, GPU time, and the work the GPU did, held to +committed baselines. The page steps every frame itself, each waiting for the GPU rather than the +clock, so a run draws the same frames on any device; how frames pace a page is the gate's to judge. ```sh -pnpm bench # build, then run every benchmark -pnpm bench:update # also record each benchmark's work per run in work.json -pnpm bench:gate # run, then check against .bench/base.json and work.json +cargo xtask bench --quick # each scenario once at its smallest size: phases and work +cargo xtask bench # every size while the last fits, 3 repeats +cargo xtask bench --only grid,labels # some scenarios +cargo xtask bench --software # SwiftShader on the CPU: work is judged, times only reported +cargo xtask bench --update # lay this run's results over the baselines ``` -## Gate +A run fails on: -The gate (`gate.ts`) fails when a benchmark does not complete, or when its work per run grows past -`work.json`. Work is exact on any machine: queries, uploads, and their cache hits; uploaded, staged, -and copied bytes; allocations, submissions, evictions, rasterizations, and vertices drawn. The null -device counts each draw's vertices times its instances; indirect draws count none. Commit -`work.json` with the change that moves it. CI gates every pull request. +- an error, a frame drawn while nothing changed, a pipeline compiled where it was first used + (`late`), or resident data over its budget; +- a phase growing with size faster than its order; +- more work than `baselines/work.json`: exactly for what the data sets (`uploaded`, `evaluated`, + `jobs`, `pipelines`, `late`, `resident`) in a phase that acts once, and within 2× for what moves + with the frame a job or a fetch lands in (`written`, `readbacks`, `texts`, every count of a phase + acting each frame, and all of a scenario fed by fetches); +- in a full sweep, on the machine `baselines/.json` was taken on, a phase over 1.25× slower, + and for a phase acting once, later by over a timer tick (16 ms). -Timings vary between runs, even on one machine, so the gate only reports them: - -- benchmarks whose fastest and median runs are both more than 25% slower than `.bench/base.json`; -- time per item that grows more than 3× from the smallest size to the largest: cache misses alone - can double it across a 100× range, while quadratic work multiplies it by a hundred. - -To record a base, run `pnpm bench --outputJson .bench/base.json` on the base branch. Without it, -the gate skips that comparison. Compare timings by running the base and the change alternately, -several times each. +On a machine with two GPUs, Chrome draws on the fast one. Reports and results land in +`target/bench/`. Scenarios are in `page/scenarios.ts`, the data they draw in `page/data.ts`, and how +a phase is measured in `page/stage.ts`. diff --git a/benchmark/baselines/nvidia-turing-nvidia-geforce-rtx-2080-super-chrome-156.json b/benchmark/baselines/nvidia-turing-nvidia-geforce-rtx-2080-super-chrome-156.json new file mode 100644 index 00000000..e1c98524 --- /dev/null +++ b/benchmark/baselines/nvidia-turing-nvidia-geforce-rtx-2080-super-chrome-156.json @@ -0,0 +1,1445 @@ +{ + "machine": "nvidia turing NVIDIA GeForce RTX 2080 SUPER · Chrome 156", + "times": { + "start": { + "10000": { + "init": { + "time": 280, + "gpu": 0 + }, + "data": { + "time": 20.799999952316284, + "gpu": 0 + }, + "load": { + "time": 353.30000001192093, + "gpu": 0.284448 + } + } + }, + "points": { + "1000": { + "init": { + "time": 142.4000000357628, + "gpu": 0 + }, + "data": { + "time": 14.100000023841858, + "gpu": 0 + }, + "load": { + "time": 350, + "gpu": 0.119456 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.073792 + }, + "zoom": { + "time": 0.099999994, + "gpu": 0.067584 + }, + "restyle": { + "time": 5.5, + "gpu": 0.070016 + }, + "one row": { + "time": 0.099999994, + "gpu": 0.085568 + }, + "every row": { + "time": 3.900000035762787, + "gpu": 0.085664 + }, + "first pick": { + "time": 9, + "gpu": 0.085824 + }, + "pick": { + "time": 8.300000011920929, + "gpu": 0.085728 + }, + "hover": { + "time": 13.699999988079071, + "gpu": 0.085856 + }, + "select": { + "time": 7.400000035762787, + "gpu": 0.085824 + } + }, + "10000": { + "init": { + "time": 177.70000004768372, + "gpu": 0 + }, + "data": { + "time": 17, + "gpu": 0 + }, + "load": { + "time": 354.0999999642372, + "gpu": 0.280032 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.145408 + }, + "zoom": { + "time": 0.099999994, + "gpu": 0.085152 + }, + "restyle": { + "time": 9.400000035762787, + "gpu": 0.106496 + }, + "one row": { + "time": 0.19999999, + "gpu": 0.168576 + }, + "every row": { + "time": 4.800000011920929, + "gpu": 0.168448 + }, + "first pick": { + "time": 13.199999988079071, + "gpu": 0.168448 + }, + "pick": { + "time": 8.900000035762787, + "gpu": 0.167968 + }, + "hover": { + "time": 15.599999964237213, + "gpu": 0.167904 + }, + "select": { + "time": 10, + "gpu": 0.167904 + } + }, + "100000": { + "init": { + "time": 149.5, + "gpu": 0 + }, + "data": { + "time": 15.900000035762787, + "gpu": 0 + }, + "load": { + "time": 363.5, + "gpu": 2.904192 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.859616 + }, + "zoom": { + "time": 0.099999994, + "gpu": 0.274432 + }, + "restyle": { + "time": 6.5, + "gpu": 0.479232 + }, + "one row": { + "time": 0.19999999, + "gpu": 0.988192 + }, + "every row": { + "time": 8.400000035762787, + "gpu": 0.98784 + }, + "first pick": { + "time": 10, + "gpu": 0.98784 + }, + "pick": { + "time": 8.800000011920929, + "gpu": 0.987296 + }, + "hover": { + "time": 13.599999964237213, + "gpu": 0.987136 + }, + "select": { + "time": 11.200000047683716, + "gpu": 0.987136 + } + }, + "1000000": { + "init": { + "time": 168.5, + "gpu": 0 + }, + "data": { + "time": 30, + "gpu": 0 + }, + "load": { + "time": 664, + "gpu": 1.245824 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.183392 + }, + "zoom": { + "time": 0.19999999, + "gpu": 0.497664 + }, + "restyle": { + "time": 5.800000011920929, + "gpu": 0.415648 + }, + "one row": { + "time": 0.19999999, + "gpu": 0.194976 + }, + "every row": { + "time": 28.399999976158142, + "gpu": 0.195392 + }, + "first pick": { + "time": 10.799999952316284, + "gpu": 0.195392 + }, + "pick": { + "time": 7.800000011920929, + "gpu": 0.195776 + }, + "hover": { + "time": 15.399999976158142, + "gpu": 0.196448 + }, + "select": { + "time": 11.300000011920929, + "gpu": 0.196608 + } + }, + "2000000": { + "init": { + "time": 166.30000001192093, + "gpu": 0 + }, + "data": { + "time": 87.20000004768372, + "gpu": 0 + }, + "load": { + "time": 1000.8999999761581, + "gpu": 1.283104 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.183488 + }, + "zoom": { + "time": 0.19999999, + "gpu": 0.503168 + }, + "restyle": { + "time": 7.5, + "gpu": 0.414432 + }, + "one row": { + "time": 0.099999994, + "gpu": 0.19504 + }, + "every row": { + "time": 50.30000001192093, + "gpu": 0.194848 + }, + "first pick": { + "time": 12.900000035762787, + "gpu": 0.194944 + }, + "pick": { + "time": 9.300000011920929, + "gpu": 0.195232 + }, + "hover": { + "time": 14.5, + "gpu": 0.196 + }, + "select": { + "time": 11.199999988079071, + "gpu": 0.196064 + } + } + }, + "grid": { + "1000": { + "init": { + "time": 142, + "gpu": 0 + }, + "data": { + "time": 14.699999988079071, + "gpu": 0 + }, + "load": { + "time": 526.4000000357628, + "gpu": 0.194464 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.121408 + }, + "zoom": { + "time": 0.099999994, + "gpu": 0.12304 + }, + "one row": { + "time": 0.099999994, + "gpu": 0.131072 + }, + "first pick": { + "time": 8.399999976158142, + "gpu": 0.131232 + }, + "pick": { + "time": 7.100000023841858, + "gpu": 0.131264 + }, + "hover": { + "time": 12, + "gpu": 0.131264 + } + }, + "10000": { + "init": { + "time": 163.69999998807907, + "gpu": 0 + }, + "data": { + "time": 16, + "gpu": 0 + }, + "load": { + "time": 586.6999999880791, + "gpu": 0.256 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.17808 + }, + "zoom": { + "time": 0.099999994, + "gpu": 0.173632 + }, + "one row": { + "time": 0.19999999, + "gpu": 0.187584 + }, + "first pick": { + "time": 10.5, + "gpu": 0.187712 + }, + "pick": { + "time": 9.800000011920929, + "gpu": 0.187712 + }, + "hover": { + "time": 12.700000047683716, + "gpu": 0.187584 + } + }, + "100000": { + "init": { + "time": 158.10000002384186, + "gpu": 0 + }, + "data": { + "time": 20.19999998807907, + "gpu": 0 + }, + "load": { + "time": 541.6000000238419, + "gpu": 0.94208 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.6024 + }, + "zoom": { + "time": 0.099999994, + "gpu": 0.524288 + }, + "one row": { + "time": 0.19999999, + "gpu": 0.636288 + }, + "first pick": { + "time": 14.300000011920929, + "gpu": 0.636224 + }, + "pick": { + "time": 6.699999988079071, + "gpu": 0.636896 + }, + "hover": { + "time": 17.69999998807907, + "gpu": 0.638496 + } + }, + "1000000": { + "init": { + "time": 161.30000001192093, + "gpu": 0 + }, + "data": { + "time": 63.799999952316284, + "gpu": 0 + }, + "load": { + "time": 1243.300000011921, + "gpu": 0.734304 + }, + "pan": { + "time": 0.19999999, + "gpu": 0.581312 + }, + "zoom": { + "time": 0.19999999, + "gpu": 1.359872 + }, + "one row": { + "time": 0.3, + "gpu": 0.597408 + }, + "first pick": { + "time": 14, + "gpu": 0.612096 + }, + "pick": { + "time": 7.099999964237213, + "gpu": 0.59712 + }, + "hover": { + "time": 17.099999964237213, + "gpu": 0.614208 + } + }, + "2000000": { + "init": { + "time": 165, + "gpu": 0 + }, + "data": { + "time": 108.89999997615814, + "gpu": 0 + }, + "load": { + "time": 1460.3999999761581, + "gpu": 0.755744 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.590656 + }, + "zoom": { + "time": 0.19999999, + "gpu": 1.616288 + }, + "one row": { + "time": 0.19999999, + "gpu": 0.599648 + }, + "first pick": { + "time": 16.799999952316284, + "gpu": 0.604096 + }, + "pick": { + "time": 6.699999988079071, + "gpu": 0.604096 + }, + "hover": { + "time": 16.100000023841858, + "gpu": 0.610304 + } + } + }, + "labels": { + "10000": { + "init": { + "time": 176.0999999642372, + "gpu": 0 + }, + "data": { + "time": 22, + "gpu": 0 + }, + "load": { + "time": 568.1999999880791, + "gpu": 0.321536 + }, + "pan": { + "time": 0.7, + "gpu": 0.32224 + }, + "zoom": { + "time": 1.2, + "gpu": 0.286304 + } + }, + "100000": { + "init": { + "time": 177.60000002384186, + "gpu": 0 + }, + "data": { + "time": 67.09999996423721, + "gpu": 0 + }, + "load": { + "time": 621.0999999642372, + "gpu": 1.501248 + }, + "pan": { + "time": 0.79999995, + "gpu": 1.465056 + }, + "zoom": { + "time": 1.5, + "gpu": 0.689888 + } + }, + "1000000": { + "init": { + "time": 164.30000001192093, + "gpu": 0 + }, + "data": { + "time": 510.19999998807907, + "gpu": 0 + }, + "load": { + "time": 780.6000000238419, + "gpu": 0.681568 + }, + "pan": { + "time": 1, + "gpu": 0.429344 + }, + "zoom": { + "time": 1.7, + "gpu": 1.60848 + } + } + }, + "lanes": { + "100": { + "init": { + "time": 161.10000002384186, + "gpu": 0 + }, + "data": { + "time": 14.600000023841858, + "gpu": 0 + }, + "load": { + "time": 535.3999999761581, + "gpu": 0.144448 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.080704 + }, + "first pick": { + "time": 10.400000035762787, + "gpu": 0.080768 + }, + "pick": { + "time": 5.699999988079071, + "gpu": 0.080928 + } + }, + "1000": { + "init": { + "time": 157, + "gpu": 0 + }, + "data": { + "time": 13.799999952316284, + "gpu": 0 + }, + "load": { + "time": 532.8000000119209, + "gpu": 0.18368 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.16784 + }, + "first pick": { + "time": 10.699999988079071, + "gpu": 0.166304 + }, + "pick": { + "time": 6.5, + "gpu": 0.167648 + } + }, + "10000": { + "init": { + "time": 150.4000000357628, + "gpu": 0 + }, + "data": { + "time": 14.799999952316284, + "gpu": 0 + }, + "load": { + "time": 534.7999999523163, + "gpu": 0.388384 + }, + "pan": { + "time": 0.099999994, + "gpu": 2.306144 + }, + "first pick": { + "time": 23.5, + "gpu": 2.270912 + }, + "pick": { + "time": 15.5, + "gpu": 2.29008 + } + }, + "100000": { + "init": { + "time": 190.30000001192093, + "gpu": 0 + }, + "data": { + "time": 20.19999998807907, + "gpu": 0 + }, + "load": { + "time": 816.3000000119209, + "gpu": 18.844288 + }, + "pan": { + "time": 0.19999999, + "gpu": 19.761152 + }, + "first pick": { + "time": 76.10000002384186, + "gpu": 19.828447 + }, + "pick": { + "time": 70.80000001192093, + "gpu": 19.762688 + } + } + }, + "areas": { + "100": { + "init": { + "time": 187.4000000357628, + "gpu": 0 + }, + "data": { + "time": 16.100000023841858, + "gpu": 0 + }, + "load": { + "time": 493.9000000357628, + "gpu": 0.32768 + }, + "pan": { + "time": 0.19999999, + "gpu": 0.141408 + }, + "zoom": { + "time": 0.099999994, + "gpu": 0.139264 + }, + "one row": { + "time": 0.19999999, + "gpu": 0.296896 + }, + "first pick": { + "time": 8.5, + "gpu": 0.296736 + }, + "pick": { + "time": 8.800000011920929, + "gpu": 0.296736 + } + }, + "1000": { + "init": { + "time": 148.0999999642372, + "gpu": 0 + }, + "data": { + "time": 18.19999998807907, + "gpu": 0 + }, + "load": { + "time": 396.0999999642372, + "gpu": 0.13952 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.219424 + }, + "zoom": { + "time": 0.099999994, + "gpu": 0.217728 + }, + "one row": { + "time": 0.19999999, + "gpu": 0.359136 + }, + "first pick": { + "time": 8.300000011920929, + "gpu": 0.358944 + }, + "pick": { + "time": 7.300000011920929, + "gpu": 0.35872 + } + }, + "10000": { + "init": { + "time": 159.79999995231628, + "gpu": 0 + }, + "data": { + "time": 29.899999976158142, + "gpu": 0 + }, + "load": { + "time": 474, + "gpu": 0.1344 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.604192 + }, + "zoom": { + "time": 0.099999994, + "gpu": 0.602112 + }, + "one row": { + "time": 0.099999994, + "gpu": 0.728768 + }, + "first pick": { + "time": 7.399999976158142, + "gpu": 0.72816 + }, + "pick": { + "time": 6.899999976158142, + "gpu": 0.728128 + } + }, + "30000": { + "init": { + "time": 150.19999998807907, + "gpu": 0 + }, + "data": { + "time": 59, + "gpu": 0 + }, + "load": { + "time": 779.6000000238419, + "gpu": 0.096448 + }, + "pan": { + "time": 0.099999994, + "gpu": 1.21536 + }, + "zoom": { + "time": 0.099999994, + "gpu": 1.213888 + }, + "one row": { + "time": 0.099999994, + "gpu": 1.741728 + }, + "first pick": { + "time": 7.100000023841858, + "gpu": 1.61152 + }, + "pick": { + "time": 6.200000047683716, + "gpu": 1.6112 + } + } + }, + "tiles": { + "16": { + "init": { + "time": 143.39999997615814, + "gpu": 0 + }, + "data": { + "time": 11.100000023841858, + "gpu": 0 + }, + "load": { + "time": 459.5, + "gpu": 0.121216 + }, + "pan": { + "time": 0.19999999, + "gpu": 0.1232 + }, + "zoom": { + "time": 0.19999999, + "gpu": 0.118432 + } + }, + "256": { + "init": { + "time": 144.5, + "gpu": 0 + }, + "data": { + "time": 11.800000011920929, + "gpu": 0 + }, + "load": { + "time": 441.4000000357628, + "gpu": 0.1216 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.13312 + }, + "zoom": { + "time": 0.19999999, + "gpu": 0.12288 + } + }, + "4096": { + "init": { + "time": 150.5999999642372, + "gpu": 0 + }, + "data": { + "time": 11.100000023841858, + "gpu": 0 + }, + "load": { + "time": 512.3000000119209, + "gpu": 0.122688 + }, + "pan": { + "time": 0.19999999, + "gpu": 0.171744 + }, + "zoom": { + "time": 2.8, + "gpu": 0.155648 + } + } + }, + "diagram": { + "100": { + "init": { + "time": 150.30000001192093, + "gpu": 0 + }, + "data": { + "time": 15.899999976158142, + "gpu": 0 + }, + "load": { + "time": 498.9000000357628, + "gpu": 1.456416 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.083968 + }, + "edit": { + "time": 0.39999998, + "gpu": 0.122656 + }, + "arrange": { + "time": 12, + "gpu": 0.12288 + } + }, + "1000": { + "init": { + "time": 155.39999997615814, + "gpu": 0 + }, + "data": { + "time": 15.5, + "gpu": 0 + }, + "load": { + "time": 503.4000000357628, + "gpu": 1.454784 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.096448 + }, + "edit": { + "time": 0.6, + "gpu": 0.142688 + }, + "arrange": { + "time": 16.19999998807907, + "gpu": 0.143424 + } + }, + "10000": { + "init": { + "time": 147.10000002384186, + "gpu": 0 + }, + "data": { + "time": 20.80000001192093, + "gpu": 0 + }, + "load": { + "time": 581.3999999761581, + "gpu": 1.478176 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.216224 + }, + "edit": { + "time": 3.4, + "gpu": 0.297088 + }, + "arrange": { + "time": 58.299999952316284, + "gpu": 0.297824 + } + } + }, + "traces": { + "10": { + "init": { + "time": 148.5, + "gpu": 0 + }, + "data": { + "time": 17.30000001192093, + "gpu": 0 + }, + "load": { + "time": 432.2999999523163, + "gpu": 1.408352 + }, + "stream": { + "time": 0.099999994, + "gpu": 0.097632 + }, + "scrub": { + "time": 0.099999994, + "gpu": 0.077824 + }, + "narrow": { + "time": 0.099999994, + "gpu": 0.090528 + }, + "hover": { + "time": 11.699999988079071, + "gpu": 0.08 + } + }, + "100": { + "init": { + "time": 147.30000001192093, + "gpu": 0 + }, + "data": { + "time": 18.899999976158142, + "gpu": 0 + }, + "load": { + "time": 462.89999997615814, + "gpu": 1.466368 + }, + "stream": { + "time": 0.099999994, + "gpu": 0.337184 + }, + "scrub": { + "time": 0.099999994, + "gpu": 0.279744 + }, + "narrow": { + "time": 0.099999994, + "gpu": 0.24784 + }, + "hover": { + "time": 12.5, + "gpu": 0.136704 + } + }, + "1000": { + "init": { + "time": 177.39999997615814, + "gpu": 0 + }, + "data": { + "time": 37.69999998807907, + "gpu": 0 + }, + "load": { + "time": 460, + "gpu": 1.582336 + }, + "stream": { + "time": 0.099999994, + "gpu": 2.24256 + }, + "scrub": { + "time": 0.099999994, + "gpu": 1.92512 + }, + "narrow": { + "time": 0.099999994, + "gpu": 1.506816 + }, + "hover": { + "time": 12.799999952316284, + "gpu": 0.538624 + } + }, + "10000": { + "init": { + "time": 187.70000004768372, + "gpu": 0 + }, + "data": { + "time": 233.0999999642372, + "gpu": 0 + }, + "load": { + "time": 547.7999999523163, + "gpu": 3.033696 + }, + "stream": { + "time": 0.3, + "gpu": 23.631264 + }, + "scrub": { + "time": 0.19999999, + "gpu": 20.68048 + }, + "narrow": { + "time": 0.19999999, + "gpu": 15.118592 + }, + "hover": { + "time": 19.600000023841858, + "gpu": 5.16896 + } + } + }, + "history": { + "1000": { + "init": { + "time": 147.5999999642372, + "gpu": 0 + }, + "data": { + "time": 16.399999976158142, + "gpu": 0 + }, + "load": { + "time": 437, + "gpu": 1.41152 + }, + "scrub": { + "time": 0.099999994, + "gpu": 0.058112 + }, + "narrow": { + "time": 0.099999994, + "gpu": 0.074688 + } + }, + "10000": { + "init": { + "time": 156.19999998807907, + "gpu": 0 + }, + "data": { + "time": 22.899999976158142, + "gpu": 0 + }, + "load": { + "time": 435.7000000476837, + "gpu": 1.40288 + }, + "scrub": { + "time": 0.099999994, + "gpu": 0.086016 + }, + "narrow": { + "time": 0.19999999, + "gpu": 0.092768 + } + }, + "100000": { + "init": { + "time": 161.80000001192093, + "gpu": 0 + }, + "data": { + "time": 60.80000001192093, + "gpu": 0 + }, + "load": { + "time": 442.89999997615814, + "gpu": 1.410528 + }, + "scrub": { + "time": 0.099999994, + "gpu": 0.286688 + }, + "narrow": { + "time": 0.19999999, + "gpu": 0.215744 + } + }, + "1000000": { + "init": { + "time": 159.89999997615814, + "gpu": 0 + }, + "data": { + "time": 394.4000000357628, + "gpu": 0 + }, + "load": { + "time": 440.89999997615814, + "gpu": 1.403584 + }, + "scrub": { + "time": 0.099999994, + "gpu": 0.405504 + }, + "narrow": { + "time": 0.19999999, + "gpu": 0.288896 + } + } + }, + "transition": { + "1000": { + "init": { + "time": 149.29999995231628, + "gpu": 0 + }, + "data": { + "time": 14.800000011920929, + "gpu": 0 + }, + "load": { + "time": 313.89999997615814, + "gpu": 0.124672 + }, + "move": { + "time": 0.099999994, + "gpu": 0.083392 + } + }, + "10000": { + "init": { + "time": 147.19999998807907, + "gpu": 0 + }, + "data": { + "time": 14.599999964237213, + "gpu": 0 + }, + "load": { + "time": 315, + "gpu": 0.279616 + }, + "move": { + "time": 0.099999994, + "gpu": 0.172128 + } + }, + "100000": { + "init": { + "time": 161.29999995231628, + "gpu": 0 + }, + "data": { + "time": 16.69999998807907, + "gpu": 0 + }, + "load": { + "time": 334.89999997615814, + "gpu": 1.939008 + }, + "move": { + "time": 0.099999994, + "gpu": 1.233024 + } + }, + "1000000": { + "init": { + "time": 148.4000000357628, + "gpu": 0 + }, + "data": { + "time": 31.19999998807907, + "gpu": 0 + }, + "load": { + "time": 816.6999999880791, + "gpu": 0.776192 + }, + "move": { + "time": 0.099999994, + "gpu": 0.223104 + } + } + }, + "views": { + "1": { + "init": { + "time": 159.5, + "gpu": 0 + }, + "data": { + "time": 23.600000023841858, + "gpu": 0 + }, + "load": { + "time": 544.7999999523163, + "gpu": 1.428128 + }, + "pan": { + "time": 0.099999994, + "gpu": 0.927744 + } + }, + "2": { + "init": { + "time": 155.70000004768372, + "gpu": 0 + }, + "data": { + "time": 21.80000001192093, + "gpu": 0 + }, + "load": { + "time": 559.7999999523163, + "gpu": 2.794816 + }, + "pan": { + "time": 0.099999994, + "gpu": 1.4248319999999999 + } + }, + "4": { + "init": { + "time": 157.5, + "gpu": 0 + }, + "data": { + "time": 19.899999976158142, + "gpu": 0 + }, + "load": { + "time": 562.7999999523163, + "gpu": 5.52096 + }, + "pan": { + "time": 0.299999982, + "gpu": 2.4928320000000004 + } + }, + "8": { + "init": { + "time": 167, + "gpu": 0 + }, + "data": { + "time": 24.900000035762787, + "gpu": 0 + }, + "load": { + "time": 679.1000000238419, + "gpu": 7.603104 + }, + "pan": { + "time": 0.49999997199999996, + "gpu": 2.757472 + } + } + }, + "budget": { + "100000": { + "init": { + "time": 162.69999998807907, + "gpu": 0 + }, + "data": { + "time": 22, + "gpu": 0 + }, + "load": { + "time": 779.6000000238419, + "gpu": 1.01232 + }, + "pan": { + "time": 0.19999999, + "gpu": 0.460448 + }, + "zoom": { + "time": 0.19999999, + "gpu": 0.18672 + } + }, + "1000000": { + "init": { + "time": 178.69999998807907, + "gpu": 0 + }, + "data": { + "time": 63.69999998807907, + "gpu": 0 + }, + "load": { + "time": 1287.199999988079, + "gpu": 1.517728 + }, + "pan": { + "time": 0.19999999, + "gpu": 0.590176 + }, + "zoom": { + "time": 0.19999999, + "gpu": 0.22128 + } + }, + "2000000": { + "init": { + "time": 164.29999995231628, + "gpu": 0 + }, + "data": { + "time": 123.60000002384186, + "gpu": 0 + }, + "load": { + "time": 1516.3999999761581, + "gpu": 1.424768 + }, + "pan": { + "time": 0.19999999, + "gpu": 0.592096 + }, + "zoom": { + "time": 0.099999994, + "gpu": 0.221536 + } + } + }, + "shots": { + "518400": { + "init": { + "time": 137.79999995231628, + "gpu": 0 + }, + "data": { + "time": 21.30000001192093, + "gpu": 0 + }, + "load": { + "time": 567.3000000119209, + "gpu": 2.792736 + }, + "image": { + "time": 30.69999998807907, + "gpu": 2.314368 + }, + "png": { + "time": 10.5, + "gpu": 2.314368 + }, + "video": { + "time": 247.80000001192093, + "gpu": 2.094336 + }, + "held": { + "time": 141.10000002384186, + "gpu": 2.127872 + } + }, + "2073600": { + "init": { + "time": 135.39999997615814, + "gpu": 0 + }, + "data": { + "time": 20.399999976158142, + "gpu": 0 + }, + "load": { + "time": 545.8000000119209, + "gpu": 3.086304 + }, + "image": { + "time": 46.80000001192093, + "gpu": 2.3137600000000003 + }, + "png": { + "time": 24.200000047683716, + "gpu": 2.313088 + }, + "video": { + "time": 286.60000002384186, + "gpu": 2.1913600000000004 + }, + "held": { + "time": 148.0999999642372, + "gpu": 2.199136 + } + }, + "8294400": { + "init": { + "time": 139.5, + "gpu": 0 + }, + "data": { + "time": 20.399999976158142, + "gpu": 0 + }, + "load": { + "time": 543, + "gpu": 2.79392 + }, + "image": { + "time": 87, + "gpu": 2.385632 + }, + "png": { + "time": 78.60000002384186, + "gpu": 2.385632 + }, + "video": { + "time": 646.6999999880791, + "gpu": 2.6850240000000003 + }, + "held": { + "time": 191, + "gpu": 2.7155199999999997 + } + } + } + } +} diff --git a/benchmark/baselines/work.json b/benchmark/baselines/work.json new file mode 100644 index 00000000..d4a0b5d7 --- /dev/null +++ b/benchmark/baselines/work.json @@ -0,0 +1,3738 @@ +{ + "start": { + "10000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 200000, + "written": 4004, + "evaluated": 10000, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 9, + "late": 0, + "resident": 327680 + } + } + }, + "points": { + "1000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 20000, + "written": 4004, + "evaluated": 1000, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 9, + "late": 0, + "resident": 20480 + }, + "pan": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 20480 + }, + "zoom": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 20480 + }, + "restyle": { + "uploaded": 0, + "written": 2788, + "evaluated": 1000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 20480 + }, + "one row": { + "uploaded": 160000, + "written": 64160, + "evaluated": 40000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 184320 + }, + "every row": { + "uploaded": 4000, + "written": 1604, + "evaluated": 1000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 188416 + }, + "first pick": { + "uploaded": 0, + "written": 2440, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 188416 + }, + "pick": { + "uploaded": 0, + "written": 2440, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 188416 + }, + "hover": { + "uploaded": 0, + "written": 3752, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 188416 + }, + "select": { + "uploaded": 0, + "written": 3284, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 188416 + } + }, + "10000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 200000, + "written": 4004, + "evaluated": 10000, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 9, + "late": 0, + "resident": 327680 + }, + "pan": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 327680 + }, + "zoom": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 327680 + }, + "restyle": { + "uploaded": 0, + "written": 2788, + "evaluated": 10000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 327680 + }, + "one row": { + "uploaded": 1600000, + "written": 64160, + "evaluated": 400000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 2949120 + }, + "every row": { + "uploaded": 40000, + "written": 1604, + "evaluated": 10000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 3014656 + }, + "first pick": { + "uploaded": 0, + "written": 2440, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 3014656 + }, + "pick": { + "uploaded": 0, + "written": 2440, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 3014656 + }, + "hover": { + "uploaded": 0, + "written": 3752, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 3014656 + }, + "select": { + "uploaded": 0, + "written": 3284, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 3014656 + } + }, + "100000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 2000000, + "written": 4032, + "evaluated": 100000, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 9, + "late": 0, + "resident": 2621440 + }, + "pan": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 2621440 + }, + "zoom": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 2621440 + }, + "restyle": { + "uploaded": 0, + "written": 2816, + "evaluated": 100000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 2621440 + }, + "one row": { + "uploaded": 10485760, + "written": 64960, + "evaluated": 2621440, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 13107200 + }, + "every row": { + "uploaded": 400000, + "written": 1628, + "evaluated": 100000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 13631488 + }, + "first pick": { + "uploaded": 0, + "written": 2440, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 13631488 + }, + "pick": { + "uploaded": 0, + "written": 2440, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 13631488 + }, + "hover": { + "uploaded": 0, + "written": 3752, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 13631488 + }, + "select": { + "uploaded": 0, + "written": 3284, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 13631488 + } + }, + "1000000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 1567520, + "written": 5608, + "evaluated": 78376, + "readbacks": 1, + "jobs": 1, + "texts": 0, + "pipelines": 9, + "late": 0, + "resident": 1638400 + }, + "pan": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 1638400 + }, + "zoom": { + "uploaded": 13309320, + "written": 51652, + "evaluated": 665466, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15319040 + }, + "restyle": { + "uploaded": 0, + "written": 2788, + "evaluated": 15876, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15319040 + }, + "one row": { + "uploaded": 0, + "written": 64000, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15319040 + }, + "every row": { + "uploaded": 63504, + "written": 1604, + "evaluated": 15876, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15384576 + }, + "first pick": { + "uploaded": 0, + "written": 2440, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15384576 + }, + "pick": { + "uploaded": 0, + "written": 2440, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15384576 + }, + "hover": { + "uploaded": 0, + "written": 3752, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15384576 + }, + "select": { + "uploaded": 319480, + "written": 3672, + "evaluated": 15974, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15712256 + } + }, + "2000000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 1607860, + "written": 5608, + "evaluated": 80393, + "readbacks": 1, + "jobs": 1, + "texts": 0, + "pipelines": 9, + "late": 0, + "resident": 1638400 + }, + "pan": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 1638400 + }, + "zoom": { + "uploaded": 13591040, + "written": 51652, + "evaluated": 679552, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15564800 + }, + "restyle": { + "uploaded": 0, + "written": 2788, + "evaluated": 15876, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15564800 + }, + "one row": { + "uploaded": 0, + "written": 64000, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15564800 + }, + "every row": { + "uploaded": 63504, + "written": 1604, + "evaluated": 15876, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15630336 + }, + "first pick": { + "uploaded": 0, + "written": 2440, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15630336 + }, + "pick": { + "uploaded": 0, + "written": 2440, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15630336 + }, + "hover": { + "uploaded": 0, + "written": 3752, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15630336 + }, + "select": { + "uploaded": 319500, + "written": 3672, + "evaluated": 15975, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 15958016 + } + } + }, + "grid": { + "1000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 36352, + "written": 5080, + "evaluated": 3008, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 36864 + }, + "pan": { + "uploaded": 0, + "written": 58880, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 36864 + }, + "zoom": { + "uploaded": 0, + "written": 58880, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 36864 + }, + "one row": { + "uploaded": 163840, + "written": 74400, + "evaluated": 40960, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 200704 + }, + "first pick": { + "uploaded": 0, + "written": 2960, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 200704 + }, + "pick": { + "uploaded": 0, + "written": 2960, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 200704 + }, + "hover": { + "uploaded": 0, + "written": 4536, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 200704 + } + }, + "10000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 358400, + "written": 5080, + "evaluated": 29800, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 589824 + }, + "pan": { + "uploaded": 0, + "written": 58880, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 589824 + }, + "zoom": { + "uploaded": 0, + "written": 58880, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 589824 + }, + "one row": { + "uploaded": 1600000, + "written": 74400, + "evaluated": 400000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 3211264 + }, + "first pick": { + "uploaded": 0, + "written": 2960, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 3211264 + }, + "pick": { + "uploaded": 0, + "written": 2960, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 3211264 + }, + "hover": { + "uploaded": 0, + "written": 4520, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 3211264 + } + }, + "100000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 3589760, + "written": 5152, + "evaluated": 298936, + "readbacks": 2, + "jobs": 1, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 4227072 + }, + "pan": { + "uploaded": 0, + "written": 58880, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4227072 + }, + "zoom": { + "uploaded": 0, + "written": 58880, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4227072 + }, + "one row": { + "uploaded": 10485760, + "written": 75200, + "evaluated": 2621440, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 14712832 + }, + "first pick": { + "uploaded": 0, + "written": 2960, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 14712832 + }, + "pick": { + "uploaded": 0, + "written": 2960, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 14712832 + }, + "hover": { + "uploaded": 0, + "written": 4520, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 14712832 + } + }, + "1000000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 16751128, + "written": 37956, + "evaluated": 983822, + "readbacks": 6, + "jobs": 2, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 18153472 + }, + "pan": { + "uploaded": 14622728, + "written": 77120, + "evaluated": 864442, + "readbacks": 6, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 33619968 + }, + "zoom": { + "uploaded": 31139892, + "written": 63588, + "evaluated": 1990386, + "readbacks": 5, + "jobs": 4, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 65830912 + }, + "one row": { + "uploaded": 4775696, + "written": 75916, + "evaluated": 1193924, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 70615040 + }, + "first pick": { + "uploaded": 0, + "written": 2960, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 70615040 + }, + "pick": { + "uploaded": 0, + "written": 2960, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 70615040 + }, + "hover": { + "uploaded": 0, + "written": 4520, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 70615040 + } + }, + "2000000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 17197752, + "written": 37956, + "evaluated": 1008054, + "readbacks": 6, + "jobs": 2, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 18481152 + }, + "pan": { + "uploaded": 14841448, + "written": 77120, + "evaluated": 875378, + "readbacks": 6, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 35258368 + }, + "zoom": { + "uploaded": 39083136, + "written": 64504, + "evaluated": 2388039, + "readbacks": 5, + "jobs": 4, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 76023040 + }, + "one row": { + "uploaded": 2883584, + "written": 75884, + "evaluated": 720896, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 78906624 + }, + "first pick": { + "uploaded": 0, + "written": 2960, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 78906624 + }, + "pick": { + "uploaded": 0, + "written": 2960, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 78906624 + }, + "hover": { + "uploaded": 0, + "written": 4520, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 78906624 + } + } + }, + "labels": { + "10000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 240000, + "written": 722428, + "evaluated": 10000, + "readbacks": 8, + "jobs": 0, + "texts": 207, + "pipelines": 20, + "late": 0, + "resident": 393216 + }, + "pan": { + "uploaded": 0, + "written": 2131648, + "evaluated": 0, + "readbacks": 40, + "jobs": 0, + "texts": 586, + "pipelines": 0, + "late": 0, + "resident": 393216 + }, + "zoom": { + "uploaded": 0, + "written": 4825740, + "evaluated": 0, + "readbacks": 41, + "jobs": 0, + "texts": 1297, + "pipelines": 0, + "late": 0, + "resident": 393216 + } + }, + "100000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 2400000, + "written": 1487188, + "evaluated": 100000, + "readbacks": 8, + "jobs": 0, + "texts": 216, + "pipelines": 20, + "late": 0, + "resident": 3145728 + }, + "pan": { + "uploaded": 0, + "written": 2831152, + "evaluated": 0, + "readbacks": 40, + "jobs": 0, + "texts": 739, + "pipelines": 0, + "late": 0, + "resident": 3145728 + }, + "zoom": { + "uploaded": 0, + "written": 6473928, + "evaluated": 0, + "readbacks": 41, + "jobs": 0, + "texts": 1641, + "pipelines": 0, + "late": 0, + "resident": 3145728 + } + }, + "1000000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 1881024, + "written": 2977136, + "evaluated": 78376, + "readbacks": 18, + "jobs": 1, + "texts": 392, + "pipelines": 20, + "late": 0, + "resident": 1966080 + }, + "pan": { + "uploaded": 0, + "written": 4540644, + "evaluated": 0, + "readbacks": 40, + "jobs": 0, + "texts": 867, + "pipelines": 0, + "late": 0, + "resident": 1966080 + }, + "zoom": { + "uploaded": 15971184, + "written": 11933216, + "evaluated": 927610, + "readbacks": 45, + "jobs": 0, + "texts": 1659, + "pipelines": 0, + "late": 0, + "resident": 18382848 + } + } + }, + "lanes": { + "100": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 1456, + "written": 5496, + "evaluated": 116, + "readbacks": 3, + "jobs": 0, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 2560 + }, + "pan": { + "uploaded": 0, + "written": 58880, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 2560 + }, + "first pick": { + "uploaded": 0, + "written": 2960, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 2560 + }, + "pick": { + "uploaded": 0, + "written": 2960, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 2560 + } + }, + "1000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 12256, + "written": 5496, + "evaluated": 1016, + "readbacks": 3, + "jobs": 0, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 13312 + }, + "pan": { + "uploaded": 0, + "written": 58880, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 13312 + }, + "first pick": { + "uploaded": 0, + "written": 2960, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 13312 + }, + "pick": { + "uploaded": 0, + "written": 2960, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 13312 + } + }, + "10000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 120256, + "written": 5496, + "evaluated": 10016, + "readbacks": 3, + "jobs": 0, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 197632 + }, + "pan": { + "uploaded": 0, + "written": 58880, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 197632 + }, + "first pick": { + "uploaded": 0, + "written": 4448, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 197632 + }, + "pick": { + "uploaded": 0, + "written": 4448, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 197632 + } + }, + "100000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 1200256, + "written": 7348, + "evaluated": 100016, + "readbacks": 3, + "jobs": 1, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 1573888 + }, + "pan": { + "uploaded": 0, + "written": 58880, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 1573888 + }, + "first pick": { + "uploaded": 0, + "written": 4448, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 1573888 + }, + "pick": { + "uploaded": 0, + "written": 4448, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 1573888 + } + } + }, + "areas": { + "100": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 1340368, + "written": 3852, + "evaluated": 100, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 14, + "late": 0, + "resident": 1344512 + }, + "pan": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 1344512 + }, + "zoom": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 1344512 + }, + "one row": { + "uploaded": 16000, + "written": 59680, + "evaluated": 4000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 1364992 + }, + "first pick": { + "uploaded": 0, + "written": 2432, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 1364992 + }, + "pick": { + "uploaded": 0, + "written": 2432, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 1364992 + } + }, + "1000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 4172168, + "written": 5348, + "evaluated": 1000, + "readbacks": 1, + "jobs": 1, + "texts": 0, + "pipelines": 14, + "late": 0, + "resident": 4206592 + }, + "pan": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4206592 + }, + "zoom": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4206592 + }, + "one row": { + "uploaded": 160000, + "written": 61280, + "evaluated": 40000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4370432 + }, + "first pick": { + "uploaded": 0, + "written": 2432, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4370432 + }, + "pick": { + "uploaded": 0, + "written": 2432, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4370432 + } + }, + "10000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 18104720, + "written": 5740, + "evaluated": 10000, + "readbacks": 1, + "jobs": 1, + "texts": 0, + "pipelines": 14, + "late": 0, + "resident": 18284544 + }, + "pan": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 18284544 + }, + "zoom": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 18284544 + }, + "one row": { + "uploaded": 1600000, + "written": 69760, + "evaluated": 400000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 20905984 + }, + "first pick": { + "uploaded": 0, + "written": 2432, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 20905984 + }, + "pick": { + "uploaded": 0, + "written": 2432, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 20905984 + } + }, + "30000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 40370040, + "written": 60880, + "evaluated": 30000, + "readbacks": 1, + "jobs": 1, + "texts": 0, + "pipelines": 14, + "late": 0, + "resident": 40501248 + }, + "pan": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 40501248 + }, + "zoom": { + "uploaded": 0, + "written": 48640, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 40501248 + }, + "one row": { + "uploaded": 4800000, + "written": 83200, + "evaluated": 1200000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 45744128 + }, + "first pick": { + "uploaded": 0, + "written": 2432, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 45744128 + }, + "pick": { + "uploaded": 0, + "written": 2432, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 45744128 + } + } + }, + "tiles": { + "16": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 336000, + "written": 5260, + "evaluated": 80, + "readbacks": 0, + "jobs": 4, + "texts": 0, + "pipelines": 14, + "late": 0, + "resident": 344576 + }, + "pan": { + "uploaded": 2160192, + "written": 50232, + "evaluated": 512, + "readbacks": 0, + "jobs": 8, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 2771968 + }, + "zoom": { + "uploaded": 2119824, + "written": 51004, + "evaluated": 1088, + "readbacks": 0, + "jobs": 23, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 5546752 + } + }, + "256": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 788640, + "written": 5264, + "evaluated": 1280, + "readbacks": 0, + "jobs": 4, + "texts": 0, + "pipelines": 14, + "late": 0, + "resident": 922624 + }, + "pan": { + "uploaded": 5062272, + "written": 50272, + "evaluated": 8192, + "readbacks": 0, + "jobs": 8, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 6333440 + }, + "zoom": { + "uploaded": 5673696, + "written": 51048, + "evaluated": 17152, + "readbacks": 0, + "jobs": 22, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 13184000 + } + }, + "4096": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 3344464, + "written": 6704, + "evaluated": 20480, + "readbacks": 0, + "jobs": 6, + "texts": 0, + "pipelines": 14, + "late": 0, + "resident": 3424256 + }, + "pan": { + "uploaded": 21165184, + "written": 52928, + "evaluated": 172032, + "readbacks": 0, + "jobs": 12, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 25509888 + }, + "zoom": { + "uploaded": 20321088, + "written": 55384, + "evaluated": 225280, + "readbacks": 0, + "jobs": 19, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 46465024 + } + } + }, + "diagram": { + "100": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 24240, + "written": 8108, + "evaluated": 300, + "readbacks": 1, + "jobs": 2, + "texts": 0, + "pipelines": 23, + "late": 0, + "resident": 33792 + }, + "pan": { + "uploaded": 0, + "written": 60352, + "evaluated": 0, + "readbacks": 39, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 33792 + }, + "edit": { + "uploaded": 371960, + "written": 105216, + "evaluated": 4000, + "readbacks": 40, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 537600 + }, + "arrange": { + "uploaded": 19000, + "written": 5836, + "evaluated": 100, + "readbacks": 1, + "jobs": 2, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 564736 + } + }, + "1000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 242960, + "written": 15308, + "evaluated": 3000, + "readbacks": 1, + "jobs": 2, + "texts": 0, + "pipelines": 23, + "late": 0, + "resident": 335872 + }, + "pan": { + "uploaded": 0, + "written": 60352, + "evaluated": 0, + "readbacks": 39, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 335872 + }, + "edit": { + "uploaded": 3463800, + "written": 112384, + "evaluated": 40000, + "readbacks": 40, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 6070272 + }, + "arrange": { + "uploaded": 178144, + "written": 5836, + "evaluated": 1000, + "readbacks": 1, + "jobs": 2, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 6352896 + } + }, + "10000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 2429800, + "written": 88800, + "evaluated": 30000, + "readbacks": 1, + "jobs": 2, + "texts": 0, + "pipelines": 23, + "late": 0, + "resident": 3014656 + }, + "pan": { + "uploaded": 0, + "written": 60352, + "evaluated": 0, + "readbacks": 39, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 3014656 + }, + "edit": { + "uploaded": 34375160, + "written": 104512, + "evaluated": 400000, + "readbacks": 40, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 42336256 + }, + "arrange": { + "uploaded": 1710032, + "written": 5852, + "evaluated": 10000, + "readbacks": 1, + "jobs": 2, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 44236800 + } + } + }, + "traces": { + "10": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 49152, + "written": 44096, + "evaluated": 10, + "readbacks": 1, + "jobs": 0, + "texts": 22, + "pipelines": 15, + "late": 0, + "resident": 524288 + }, + "stream": { + "uploaded": 48, + "written": 194816, + "evaluated": 0, + "readbacks": 40, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 524288 + }, + "scrub": { + "uploaded": 0, + "written": 179136, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 524288 + }, + "narrow": { + "uploaded": 1872, + "written": 210040, + "evaluated": 0, + "readbacks": 40, + "jobs": 0, + "texts": 19, + "pipelines": 0, + "late": 0, + "resident": 524288 + }, + "hover": { + "uploaded": 0, + "written": 11816, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 524288 + } + }, + "100": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 417792, + "written": 44108, + "evaluated": 100, + "readbacks": 1, + "jobs": 0, + "texts": 22, + "pipelines": 15, + "late": 0, + "resident": 786432 + }, + "stream": { + "uploaded": 408, + "written": 195296, + "evaluated": 0, + "readbacks": 40, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 786432 + }, + "scrub": { + "uploaded": 0, + "written": 179136, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 786432 + }, + "narrow": { + "uploaded": 15912, + "written": 210364, + "evaluated": 0, + "readbacks": 40, + "jobs": 0, + "texts": 19, + "pipelines": 0, + "late": 0, + "resident": 786432 + }, + "hover": { + "uploaded": 0, + "written": 11816, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 786432 + } + }, + "1000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 4104192, + "written": 44468, + "evaluated": 1000, + "readbacks": 1, + "jobs": 0, + "texts": 22, + "pipelines": 15, + "late": 0, + "resident": 4456448 + }, + "stream": { + "uploaded": 4008, + "written": 202016, + "evaluated": 0, + "readbacks": 40, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4456448 + }, + "scrub": { + "uploaded": 0, + "written": 179136, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4456448 + }, + "narrow": { + "uploaded": 156312, + "written": 214324, + "evaluated": 0, + "readbacks": 40, + "jobs": 0, + "texts": 19, + "pipelines": 0, + "late": 0, + "resident": 4718592 + }, + "hover": { + "uploaded": 0, + "written": 11816, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4718592 + } + }, + "10000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 40968192, + "written": 51748, + "evaluated": 10000, + "readbacks": 1, + "jobs": 0, + "texts": 22, + "pipelines": 15, + "late": 0, + "resident": 45088768 + }, + "stream": { + "uploaded": 40008, + "written": 275048, + "evaluated": 0, + "readbacks": 40, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 45088768 + }, + "scrub": { + "uploaded": 0, + "written": 179136, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 45088768 + }, + "narrow": { + "uploaded": 1560312, + "written": 255868, + "evaluated": 0, + "readbacks": 40, + "jobs": 0, + "texts": 19, + "pipelines": 0, + "late": 0, + "resident": 46923776 + }, + "hover": { + "uploaded": 0, + "written": 11816, + "evaluated": 0, + "readbacks": 2, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 46923776 + } + } + }, + "history": { + "1000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 12000, + "written": 53080, + "evaluated": 1, + "readbacks": 1, + "jobs": 0, + "texts": 26, + "pipelines": 15, + "late": 0, + "resident": 524288 + }, + "scrub": { + "uploaded": 0, + "written": 179200, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 524288 + }, + "narrow": { + "uploaded": 0, + "written": 211216, + "evaluated": 0, + "readbacks": 39, + "jobs": 0, + "texts": 19, + "pipelines": 0, + "late": 0, + "resident": 524288 + } + }, + "10000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 140000, + "written": 55252, + "evaluated": 1, + "readbacks": 1, + "jobs": 0, + "texts": 26, + "pipelines": 15, + "late": 0, + "resident": 1310720 + }, + "scrub": { + "uploaded": 0, + "written": 179200, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 1310720 + }, + "narrow": { + "uploaded": 0, + "written": 209620, + "evaluated": 0, + "readbacks": 39, + "jobs": 0, + "texts": 16, + "pipelines": 0, + "late": 0, + "resident": 1310720 + } + }, + "100000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 749280, + "written": 57492, + "evaluated": 1, + "readbacks": 1, + "jobs": 0, + "texts": 26, + "pipelines": 15, + "late": 0, + "resident": 2097152 + }, + "scrub": { + "uploaded": 0, + "written": 179200, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 2097152 + }, + "narrow": { + "uploaded": 0, + "written": 218196, + "evaluated": 0, + "readbacks": 39, + "jobs": 0, + "texts": 16, + "pipelines": 0, + "late": 0, + "resident": 2097152 + } + }, + "1000000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 805536, + "written": 59652, + "evaluated": 1, + "readbacks": 1, + "jobs": 0, + "texts": 26, + "pipelines": 15, + "late": 0, + "resident": 2097152 + }, + "scrub": { + "uploaded": 0, + "written": 179200, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 2097152 + }, + "narrow": { + "uploaded": 0, + "written": 224116, + "evaluated": 0, + "readbacks": 39, + "jobs": 0, + "texts": 16, + "pipelines": 0, + "late": 0, + "resident": 2097152 + } + } + }, + "transition": { + "1000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 20000, + "written": 4004, + "evaluated": 1000, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 9, + "late": 0, + "resident": 20480 + }, + "move": { + "uploaded": 20000, + "written": 74568, + "evaluated": 2000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 40960 + } + }, + "10000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 200000, + "written": 4004, + "evaluated": 10000, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 9, + "late": 0, + "resident": 327680 + }, + "move": { + "uploaded": 200000, + "written": 74568, + "evaluated": 20000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 655360 + } + }, + "100000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 2000000, + "written": 4032, + "evaluated": 100000, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 9, + "late": 0, + "resident": 2621440 + }, + "move": { + "uploaded": 2000000, + "written": 74596, + "evaluated": 200000, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 5242880 + } + }, + "1000000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 1567520, + "written": 388296, + "evaluated": 155802, + "readbacks": 1, + "jobs": 1, + "texts": 0, + "pipelines": 9, + "late": 0, + "resident": 1638400 + }, + "move": { + "uploaded": 952560, + "written": 298688, + "evaluated": 71468, + "readbacks": 0, + "jobs": 1, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 2621440 + } + } + }, + "views": { + "1": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 3589760, + "written": 5104, + "evaluated": 298936, + "readbacks": 1, + "jobs": 1, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 4227072 + }, + "pan": { + "uploaded": 0, + "written": 58880, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4227072 + } + }, + "2": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 3589760, + "written": 9184, + "evaluated": 597872, + "readbacks": 2, + "jobs": 2, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 4227072 + }, + "pan": { + "uploaded": 0, + "written": 117760, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4227072 + } + }, + "4": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 3589760, + "written": 17344, + "evaluated": 1195744, + "readbacks": 4, + "jobs": 4, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 4227072 + }, + "pan": { + "uploaded": 0, + "written": 235520, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4227072 + } + }, + "8": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 3589760, + "written": 33664, + "evaluated": 2391488, + "readbacks": 8, + "jobs": 8, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 4227072 + }, + "pan": { + "uploaded": 0, + "written": 471040, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4227072 + } + } + }, + "budget": { + "100000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 4764460, + "written": 12468, + "evaluated": 289253, + "readbacks": 1, + "jobs": 2, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 5636096 + }, + "pan": { + "uploaded": 6457376, + "written": 72224, + "evaluated": 416008, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 14417920 + }, + "zoom": { + "uploaded": 0, + "written": 58880, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 14417920 + } + }, + "1000000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 9351656, + "written": 22148, + "evaluated": 557254, + "readbacks": 1, + "jobs": 2, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 10092544 + }, + "pan": { + "uploaded": 8253296, + "written": 72320, + "evaluated": 505804, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 16646144 + }, + "zoom": { + "uploaded": 0, + "written": 58880, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 16646144 + } + }, + "2000000": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 9480488, + "written": 22148, + "evaluated": 564688, + "readbacks": 1, + "jobs": 2, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 10420224 + }, + "pan": { + "uploaded": 8270536, + "written": 72320, + "evaluated": 506666, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 16187392 + }, + "zoom": { + "uploaded": 0, + "written": 58880, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 16187392 + } + } + }, + "shots": { + "518400": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 3589760, + "written": 9184, + "evaluated": 597872, + "readbacks": 2, + "jobs": 2, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 4227072 + }, + "image": { + "uploaded": 0, + "written": 8928, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 6, + "late": 0, + "resident": 4227072 + }, + "png": { + "uploaded": 0, + "written": 2944, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4227072 + }, + "video": { + "uploaded": 0, + "written": 97248, + "evaluated": 0, + "readbacks": 30, + "jobs": 0, + "texts": 0, + "pipelines": 1, + "late": 0, + "resident": 4227072 + }, + "held": { + "uploaded": 0, + "written": 5984, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4227072 + } + }, + "2073600": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 3589760, + "written": 9184, + "evaluated": 597872, + "readbacks": 2, + "jobs": 2, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 4227072 + }, + "image": { + "uploaded": 0, + "written": 8928, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 6, + "late": 0, + "resident": 4227072 + }, + "png": { + "uploaded": 0, + "written": 2944, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4227072 + }, + "video": { + "uploaded": 0, + "written": 97248, + "evaluated": 0, + "readbacks": 30, + "jobs": 0, + "texts": 0, + "pipelines": 1, + "late": 0, + "resident": 4227072 + }, + "held": { + "uploaded": 0, + "written": 5984, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4227072 + } + }, + "8294400": { + "init": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "data": { + "uploaded": 0, + "written": 0, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 0 + }, + "load": { + "uploaded": 3589760, + "written": 9184, + "evaluated": 597872, + "readbacks": 2, + "jobs": 2, + "texts": 0, + "pipelines": 18, + "late": 0, + "resident": 4227072 + }, + "image": { + "uploaded": 0, + "written": 11872, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 6, + "late": 0, + "resident": 4227072 + }, + "png": { + "uploaded": 0, + "written": 2944, + "evaluated": 0, + "readbacks": 0, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4227072 + }, + "video": { + "uploaded": 0, + "written": 97248, + "evaluated": 0, + "readbacks": 30, + "jobs": 0, + "texts": 0, + "pipelines": 1, + "late": 0, + "resident": 4227072 + }, + "held": { + "uploaded": 0, + "written": 5984, + "evaluated": 0, + "readbacks": 1, + "jobs": 0, + "texts": 0, + "pipelines": 0, + "late": 0, + "resident": 4227072 + } + } + } +} diff --git a/benchmark/connect.bench.ts b/benchmark/connect.bench.ts deleted file mode 100644 index 1f8c6878..00000000 --- a/benchmark/connect.bench.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { afterAll, describe } from 'vitest'; -import { protocol } from '@latkit/connect'; -import { connected, schema, sizes, split, suite, voltages } from './harness.ts'; - -const bounds = { messageBytes: 64 << 20, metadataBytes: 64 << 10, publicationBatches: 64 }; - -describe.each(sizes)('connect %i buses', async (buses) => { - const frame = voltages(buses, 0), - payload = protocol.decode( - protocol.preparePublication(frame, 1, schema, bounds).encode(1), - bounds, - ).payload; - let blocks = 0; - const { model, close } = await connected(function* (_fields, context) { - const parts = split(frame, Math.floor((context.maxBlockBytes - 4096) / 4)); - blocks = parts.length; - for (let f = 0; !context.signal.aborted; f++) - for (const part of parts) yield { ...part, firstFrame: f, coordinates: Float64Array.of(f) }; - }); - const stream = model.monitor!([{ from: 'Bus', select: ['voltage'] }]); - await stream.next(); - afterAll(close); - const measure = suite(`connect ${buses} buses`, buses); - measure('encode frame', () => protocol.preparePublication(frame, 1, schema, bounds).encode(1)); - measure('decode frame', () => protocol.decodePublication({ bytes: payload }, schema, bounds)); - measure('stream frame', async () => { - for (let read = 0; read < blocks; read++) await stream.next(); - }); -}); diff --git a/benchmark/device.test.ts b/benchmark/device.test.ts deleted file mode 100644 index 7ec3ca00..00000000 --- a/benchmark/device.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { expect, it } from 'vitest'; -import { copyUpload } from './device.ts'; - -it('copies typed-array elements inside the supplied view, not its backing buffer', () => { - const data = Uint32Array.of(10, 20, 30, 40, 50); - expect(new Uint32Array(copyUpload(data.subarray(1, 4), 1, 1).buffer)).toEqual(Uint32Array.of(30)); - expect(new Uint32Array(copyUpload(data.subarray(1, 4), 1).buffer)).toEqual( - Uint32Array.of(30, 40), - ); - const copy = copyUpload(data); - data.fill(0); - expect(new Uint32Array(copy.buffer)).toEqual(Uint32Array.of(10, 20, 30, 40, 50)); -}); -it('uses bytes for buffers and DataViews, including a nonzero view offset', () => { - const buffer = Uint8Array.from({ length: 24 }, (_, i) => i).buffer; - expect([...copyUpload(buffer, 4, 4)]).toEqual([4, 5, 6, 7]); - expect([...copyUpload(new DataView(buffer, 8, 12), 4, 4)]).toEqual([12, 13, 14, 15]); - expect(copyUpload(buffer, 24)).toHaveLength(0); -}); -it('rejects ranges that slice would silently clamp', () => { - const data = new Uint32Array(4); - for (const [offset, count] of [ - [-1, 1], - [0.5, 1], - [3, 2], - [5, 0], - [0, -1], - ]) - expect(() => copyUpload(data, offset, count)).toThrow(RangeError); - expect(() => copyUpload(new Uint8Array(3))).toThrow(/four bytes/); -}); diff --git a/benchmark/device.ts b/benchmark/device.ts deleted file mode 100644 index 0b91bdf0..00000000 --- a/benchmark/device.ts +++ /dev/null @@ -1,133 +0,0 @@ -/** Copy exactly the source range accepted by queue.writeBuffer. */ -export function copyUpload( - data: Parameters[2], - dataOffset = 0, - size?: number, -): Uint8Array { - const view = ArrayBuffer.isView(data), - unit = view && 'BYTES_PER_ELEMENT' in data ? Number(data.BYTES_PER_ELEMENT) : 1, - bytes = view - ? new Uint8Array(data.buffer, data.byteOffset, data.byteLength) - : new Uint8Array(data), - elements = bytes.byteLength / unit, - count = size ?? elements - dataOffset; - if ( - !Number.isSafeInteger(dataOffset) || - !Number.isSafeInteger(count) || - dataOffset < 0 || - count < 0 || - dataOffset > elements || - count > elements - dataOffset - ) - throw new RangeError('Invalid upload source range'); - if ((count * unit) % 4) throw new RangeError('Upload size must be a multiple of four bytes'); - return bytes.slice(dataOffset * unit, (dataOffset + count) * unit); -} - -/** Vertices each null device was asked to draw: the GPU work its frames would cost. */ -const drawn = new WeakMap(); -export function drawnVertices(device: GPUDevice): number { - return drawn.get(device)?.vertices ?? 0; -} - -/** A WebGPU device that does no GPU work: benchmarks time the JavaScript a frame costs. */ -export function nullDevice(): GPUDevice { - Object.assign(globalThis, { - GPUBufferUsage: bits( - 'MAP_READ MAP_WRITE COPY_SRC COPY_DST INDEX VERTEX UNIFORM STORAGE INDIRECT QUERY_RESOLVE', - ), - GPUTextureUsage: bits('COPY_SRC COPY_DST TEXTURE_BINDING STORAGE_BINDING RENDER_ATTACHMENT'), - GPUShaderStage: bits('VERTEX FRAGMENT COMPUTE'), - GPUMapMode: bits('READ WRITE'), - }); - // Encoders and passes accept any call and count the vertices each draw asks for; everything else - // is a distinct object, as on a real device. - const work = { vertices: 0 }; - const sink: object = new Proxy( - {}, - { - get: (_, key) => - key === 'then' - ? undefined - : key === 'draw' - ? (vertices: number, instances = 1) => { - work.vertices += vertices * instances; - return sink; - } - : () => sink, - }, - ); - const done = Promise.resolve(); - const device = { - limits: { - maxBufferSize: 1 << 30, - maxStorageBufferBindingSize: 1 << 30, - maxStorageBuffersPerShaderStage: 10, - maxUniformBufferBindingSize: 65536, - minStorageBufferOffsetAlignment: 256, - minUniformBufferOffsetAlignment: 256, - maxTextureDimension1D: 8192, - maxTextureDimension2D: 8192, - maxTextureDimension3D: 2048, - maxTextureArrayLayers: 256, - maxComputeWorkgroupsPerDimension: 65535, - }, - features: new Set(), - lost: new Promise(() => {}), - queue: { - // Copies as a real queue does, so upload cost stays in the measurement. - writeBuffer: ( - _buffer: GPUBuffer, - _offset: number, - data: Parameters[2], - dataOffset = 0, - size?: number, - ) => void copyUpload(data, dataOffset, size), - writeTexture() {}, - copyExternalImageToTexture() {}, - submit() {}, - onSubmittedWorkDone: () => done, - }, - createBuffer: ({ size, usage }: GPUBufferDescriptor) => ({ - size, - usage, - destroy() {}, - mapAsync: () => done, - getMappedRange: () => new ArrayBuffer(size), - unmap() {}, - }), - createTexture: ({ size, format, usage, sampleCount }: GPUTextureDescriptor) => { - const [width, height = 1, depthOrArrayLayers = 1] = size as number[]; - return { - width, - height, - depthOrArrayLayers, - format, - usage, - sampleCount: sampleCount ?? 1, - destroy() {}, - createView: () => ({}), - }; - }, - createShaderModule: () => ({ getCompilationInfo: async () => ({ messages: [] }) }), - createRenderPipelineAsync: async () => ({ getBindGroupLayout: () => ({}) }), - createComputePipelineAsync: async () => ({ getBindGroupLayout: () => ({}) }), - createRenderPipeline: () => ({ getBindGroupLayout: () => ({}) }), - createComputePipeline: () => ({ getBindGroupLayout: () => ({}) }), - createBindGroup: () => ({}), - createBindGroupLayout: () => ({}), - createPipelineLayout: () => ({}), - createSampler: () => ({}), - createQuerySet: () => ({ destroy() {} }), - createCommandEncoder: () => sink, - pushErrorScope() {}, - popErrorScope: async () => null, - addEventListener() {}, - removeEventListener() {}, - destroy() {}, - } as unknown as GPUDevice; - drawn.set(device, work); - return device; -} -const bits = (names: string) => - Object.fromEntries(names.split(' ').map((name, i) => [name, 1 << i])); diff --git a/benchmark/diagram.bench.ts b/benchmark/diagram.bench.ts deleted file mode 100644 index c7480300..00000000 --- a/benchmark/diagram.bench.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { describe } from 'vitest'; -import { createDiagram, type Diagram } from '@latkit/diagram'; -import { busIndex, counters, draw, gpu, grid, suite } from './harness.ts'; - -interface DragControls { - preview(items: readonly unknown[], delta: readonly [number, number] | null): void; - move( - items: readonly unknown[], - delta: readonly [number, number], - ): Diagram.MoveProposal | undefined; -} - -/** Include the large routed scene, with fewer repetitions at forty thousand blocks. */ -describe.each([100, 1_000, 10_000, 40_000])('diagram %i blocks', async (blocks) => { - const device = await gpu(), - data = grid(blocks, true); - const config: Diagram.Config = { - source: data, - vertices: { Bus: {} }, - edges: { Branch: { ends: ['from', 'to'] } }, - // Large stress scenes explicitly opt into a larger picking budget. - ...(blocks >= 40_000 ? { limits: { pickingBytes: 128 * 1024 ** 2 } } : {}), - }; - const view = createDiagram(device, config); - await draw(device, view, 0, 'complete'); - const measure = suite( - `diagram ${blocks} blocks`, - blocks, - () => counters(device), - blocks >= 40_000 ? 3 : 8, - ); - measure('layout', async () => { - const fresh = createDiagram(device, config); - await draw(device, fresh, 0, 'complete'); - fresh.destroy(); - }); - measure('cached frame', () => draw(device, view)); - // Nothing is sampled, so playback must not read the scene again. - measure('playback frame', (i) => draw(device, view, i)); - measure('pick', () => view.pick([640, 360])); - // A drag previews one vertex moving; its gestures drive the view's controls. - const controls = (view as unknown as { readonly controls: DragControls }).controls, - dragged = await view.pick([640, 360], { radiusPx: 4000, limit: 1 }); - measure('drag frame', (i) => { - controls.preview(dragged, [8 * (1 + (i % 4)), 0]); - return draw(device, view); - }); - measure('drag end', () => { - controls.preview([], null); - return draw(device, view); - }); - // A block selected draws over the rest; clearing it draws as before. - measure('select', (i) => { - view.select(i % 2 ? [] : dragged); - return draw(device, view); - }); - measure('restyle', (i) => { - view.set({ edgeWidthPx: 1 + (i % 2) }); - return draw(device, view); - }); - // A sampled color restyles on the GPU at each coordinate and never rereads the scene. - const styled = createDiagram(device, { ...config, vertices: { Bus: { color: 'voltage' } } }); - await draw(device, styled, 0, 'complete'); - measure('styled playback', (i) => draw(device, styled, i)); -}); -/** Rings of four blocks, as a grid case's generators: parts that pack, and that route alone. */ -describe.each([1_000, 10_000])('diagram %i blocks in rings', async (blocks) => { - const device = await gpu(), - config: Diagram.Config = { - source: grid(blocks, true, 4), - vertices: { Bus: {} }, - edges: { Branch: { ends: ['from', 'to'] } }, - }; - const view = createDiagram(device, config); - await draw(device, view, 0, 'complete'); - const measure = suite(`diagram ${blocks} blocks in rings`, blocks, () => counters(device), 8); - measure('layout', async () => { - const fresh = createDiagram(device, config); - await draw(device, fresh, 0, 'complete'); - fresh.destroy(); - }); - // Accepting a move reads the positions again, and only the part that moved routes again. - const controls = (view as unknown as { readonly controls: DragControls }).controls, - moved = [{ kind: 'vertex', source: config.source, index: busIndex(blocks), row: 0 }]; - measure('move', (i) => { - const proposal = controls.move(moved, [8 * (1 + (i % 4)), 0])!; - view.set({ vertices: { Bus: proposal.positions.Bus } }); - return draw(device, view); - }); -}); diff --git a/benchmark/gate.ts b/benchmark/gate.ts deleted file mode 100644 index b53081ce..00000000 --- a/benchmark/gate.ts +++ /dev/null @@ -1,145 +0,0 @@ -/** - * The benchmark regression gate. - * - * node benchmark/gate.ts base.json head.json check head against benchmark/work.json - * node benchmark/gate.ts --update record this run's work as benchmark/work.json - * - * It fails only when exact work per run grows. Timings vary between runs, even on one machine, so it - * reports benchmarks that ran slower than the base branch, and time per item that grows faster than - * linearly with size, without failing. - */ -import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'; - -type Work = Record>; -interface Benchmark { - readonly name: string; - readonly min: number; - readonly median: number; -} -interface Report { - readonly files: readonly { - readonly groups: readonly { - readonly fullName: string; - readonly benchmarks: readonly Benchmark[]; - }[]; - }[]; -} - -const SLOWER = 1.25, - SLACK_MS = 0.02, - // Across a 100× size range, cache misses alone can double the time per item; quadratic work - // multiplies it by a hundred. - SUPERLINEAR = 3; -const committed = new URL('./work.json', import.meta.url), - results = new URL('./.results/work/', import.meta.url); - -/** This run's work, merged from every group's file. */ -function measured(): Work { - if (!existsSync(results)) return {}; - return Object.assign( - {}, - ...readdirSync(results).map( - (file) => JSON.parse(readFileSync(new URL(file, results), 'utf8')) as Work, - ), - ) as Work; -} -/** - * Timings in milliseconds by `group > benchmark`, and the benchmarks that did not complete: this - * run fails on one, while a base run's only goes uncompared. - */ -function timings(path: string): { - readonly times: Map; - readonly incomplete: readonly string[]; -} { - const report = JSON.parse(readFileSync(path, 'utf8')) as Report, - times = new Map(), - incomplete: string[] = []; - for (const file of report.files) - for (const group of file.groups) { - const name = group.fullName.split(' > ').at(-1)! + ' > '; - for (const benchmark of group.benchmarks) - if (Number.isFinite(benchmark.min) && Number.isFinite(benchmark.median)) - times.set(name + benchmark.name, benchmark); - else incomplete.push(name + benchmark.name); - } - return { times, incomplete }; -} - -if (process.argv[2] === '--update') { - const work = measured(); - writeFileSync(committed, JSON.stringify(sort(work), null, 2) + '\n'); - console.log('Recorded work for ' + Object.keys(work).length + ' benchmarks.'); - process.exit(0); -} - -const [basePath, headPath] = process.argv.slice(2), - failures: string[] = [], - notes: string[] = [], - timed: string[] = []; - -// 1. Exact work per run may not grow. -const expected = existsSync(committed) ? (JSON.parse(readFileSync(committed, 'utf8')) as Work) : {}, - work = measured(); -for (const [name, counters] of Object.entries(expected)) { - const now = work[name]; - if (!now) { - notes.push('no work recorded: ' + name); - continue; - } - for (const [counter, value] of Object.entries(counters)) { - const current = now[counter] ?? 0; - if (current > value) failures.push(`work ${name}: ${counter} ${value} → ${current}`); - else if (current < value) notes.push(`less work ${name}: ${counter} ${value} → ${current}`); - } -} -for (const name of Object.keys(work)) - if (!expected[name]) notes.push('new benchmark without recorded work: ' + name); - -// 2. Time against the base branch, measured on the same machine. Noise rarely slows both the fastest -// and the median run. -const { times: head, incomplete } = timings(headPath); -for (const name of incomplete) failures.push('did not complete: ' + name); -if (basePath && existsSync(basePath)) { - const { times: base, incomplete: uncompared } = timings(basePath); - for (const name of uncompared) notes.push('no base timing to compare: ' + name); - const slower = (now: number, before: number) => now > before * SLOWER + SLACK_MS; - for (const [name, time] of head) { - const before = base.get(name); - if (before && slower(time.min, before.min) && slower(time.median, before.median)) - timed.push(`slower ${name}: ${before.median.toFixed(3)} → ${time.median.toFixed(3)} ms`); - } -} else notes.push('no base timings; skipped the comparison against the base branch'); - -// 3. Time per item may grow at most 3× from the smallest to the largest size. -const scaled = new Map(); -for (const [name, { median: time }] of head) { - // Groups are named ` `, such as `network 100000 buses`. - const match = /^(.*?) (\d+) (\w+) > (.*)$/.exec(name); - if (!match) continue; - const key = match[1] + ' ' + match[3] + ' > ' + match[4], - size = Number(match[2]); - scaled.set(key, [...(scaled.get(key) ?? []), { size, perItem: time / size }]); -} -for (const [name, points] of scaled) { - if (points.length < 2) continue; - points.sort((a, b) => a.size - b.size); - const first = points[0], - last = points.at(-1)!; - if (last.perItem > first.perItem * SUPERLINEAR) - timed.push( - `superlinear ${name}: ${(first.perItem * 1e6).toFixed(1)} → ${(last.perItem * 1e6).toFixed(1)} ns per item`, - ); -} - -for (const note of notes) console.log(note); -if (timed.length) - console.log('Timings to check by hand; one run can differ by 2×:\n' + timed.join('\n')); -if (failures.length) { - console.error(failures.join('\n')); - process.exit(1); -} -console.log(`Benchmarks pass: ${head.size} timed, ${Object.keys(work).length} with recorded work.`); - -function sort(work: Work): Work { - return Object.fromEntries(Object.entries(work).sort(([a], [b]) => a.localeCompare(b))); -} diff --git a/benchmark/gpu.bench.ts b/benchmark/gpu.bench.ts deleted file mode 100644 index c3e71168..00000000 --- a/benchmark/gpu.bench.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { describe } from 'vitest'; -import { kit } from '@latkit/gpu'; -import type { Data, FieldInput } from '@latkit/model'; -import { counters, draw, frames, gpu, grid, sizes, suite } from './harness.ts'; - -/** A renderer that reads fields and uploads them each frame, as every view does. */ -function uploads(data: Data, fields: Readonly>): kit.Renderer { - return { - capture: () => ({ - prepare: async (frame) => { - for await (const block of frame.reader.fields({ source: data, from: 'Bus', fields })) - frame.upload(block, { select: Object.keys(fields), float64: 'relative' }); - return { encode() {}, submitted() {}, discard() {} }; - }, - release() {}, - }), - destroy() {}, - }; -} - -describe.each(sizes)('gpu %i buses', async (buses) => { - const device = await gpu(), - data = grid(buses); - const staticFields = uploads(data, { load: 'load', position: 'position' }), - sampled = uploads(data, { voltage: 'voltage' }); - const measure = suite(`gpu ${buses} buses`, buses, () => counters(device)); - measure('cold upload', () => { - device.trim(); - return draw(device, staticFields); - }); - measure('resident redraw', () => draw(device, staticFields)); - measure('playback frame', (i) => draw(device, sampled, i)); - measure('field scale', async () => { - const scope = device.reader.open(); - try { - return await kit.fieldScale(scope, { - source: data, - from: 'Bus', - field: 'voltage', - window: { kind: 'range', between: [0, frames - 1] }, - }); - } finally { - scope.close(); - } - }); -}); diff --git a/benchmark/harness.ts b/benchmark/harness.ts deleted file mode 100644 index 5b2c5515..00000000 --- a/benchmark/harness.ts +++ /dev/null @@ -1,350 +0,0 @@ -import { mkdirSync, writeFileSync } from 'node:fs'; -import type { AddressInfo } from 'node:net'; -import { bench } from 'vitest'; -import { WebSocketServer } from 'ws'; -import { acceptModel, connectModel, type ConnectedModel } from '@latkit/connect'; -import { createData, textColumn, type Data, type Index, type Model } from '@latkit/model'; -import type { Schema } from '@latkit/model'; -import { createGpu, kit, type Gpu, type TextRasterizer, type View } from '@latkit/gpu'; -import { drawnVertices, nullDevice } from './device.ts'; - -/** Every scalable benchmark runs at these sizes; the gate checks growth across them. */ -export const sizes = [10_000, 100_000, 1_000_000]; -/** Sampled frames in each grid: more than any benchmark runs, so playback always reaches a new one. */ -export const frames = 32; - -export const schema: Schema = { - axis: { name: 'time', unit: 's' }, - types: { - Bus: { - fields: { - position: { type: { kind: 'vector', items: 'float64', size: 2 } }, - load: { type: 'float32' }, - voltage: { type: 'float32', sampled: true }, - }, - }, - Branch: { - fields: { - from: { type: { kind: 'reference', to: 'Bus' } }, - to: { type: { kind: 'reference', to: 'Bus' } }, - }, - }, - }, -}; -export const busIndex = (buses: number): Index => ({ - source: 'grid', - type: 'Bus', - version: String(buses), -}); -export const branchIndex = (buses: number): Index => ({ - source: 'grid', - type: 'Branch', - version: String(buses), -}); - -/** - * Buses on a √n lattice, branches to their right and lower neighbours, `frames` of voltages. `ids` - * names every row, as views that propose edits need. With `ring`, branches instead close each run - * of that many buses into a loop, as a grid case's generators and their controllers are, with no - * branch between loops. - */ -export function grid(buses: number, ids = false, ring = 0): Data { - return createData(schema, batches(buses, ids, ring)); -} -/** Every batch of a grid: its rows, then each frame. */ -export function batches(buses: number, ids = false, ring = 0): Data.Batch[] { - return [ - ...topology(buses, ids, ring), - ...Array.from({ length: frames }, (_, f) => voltages(buses, f)), - ]; -} -/** The static rows of a grid. */ -export function topology(buses: number, ids = false, ring = 0): Data.Batch[] { - const width = Math.ceil(Math.sqrt(buses)), - from: number[] = [], - to: number[] = []; - for (let i = 0; i < buses; i++) { - if (ring) { - const first = i - (i % ring), - next = first + ((i - first + 1) % ring); - if (next !== i && next < buses) { - from.push(i); - to.push(next); - } - continue; - } - if ((i + 1) % width && i + 1 < buses) { - from.push(i); - to.push(i + 1); - } - if (i + width < buses) { - from.push(i); - to.push(i + width); - } - } - const position = new Float64Array(buses * 2); - for (let i = 0; i < buses; i++) { - position[i * 2] = i % width; - position[i * 2 + 1] = Math.floor(i / width); - } - const bus = busIndex(buses); - return [ - { - kind: 'rows', - index: bus, - rows: { kind: 'range', offset: 0, count: buses }, - ...(ids && { ids: names('bus', buses) }), - columns: { - position: { - kind: 'vector', - size: 2, - offset: 0, - length: buses, - values: { kind: 'numeric', offset: 0, length: buses * 2, values: position }, - }, - load: numbers(Float32Array.from({ length: buses }, (_, i) => (i % 97) / 97)), - }, - }, - { - kind: 'rows', - index: branchIndex(buses), - rows: { kind: 'range', offset: 0, count: from.length }, - ...(ids && { ids: names('branch', from.length) }), - columns: { - from: { - kind: 'reference', - index: bus, - offset: 0, - length: from.length, - values: Uint32Array.from(from), - }, - to: { - kind: 'reference', - index: bus, - offset: 0, - length: to.length, - values: Uint32Array.from(to), - }, - }, - }, - ]; -} -/** One frame of bus voltages at coordinate `frame`. */ -export function voltages(buses: number, frame: number): Data.SampleBatch { - const values = Float32Array.from( - { length: buses }, - (_, i) => 1 + Math.sin(i * 0.01 + frame * 0.2) / 20, - ); - return { - kind: 'samples', - index: busIndex(buses), - rows: { kind: 'range', offset: 0, count: buses }, - firstFrame: frame, - coordinates: Float64Array.of(frame), - columns: { voltage: { ...numbers(values), rowStride: 1, frameStride: buses } }, - }; -} -/** A frame cut into row ranges of at most `rows`, as a producer publishes one that is too big. */ -export function split(frame: Data.SampleBatch, rows: number): Data.SampleBatch[] { - const column = frame.columns.voltage; - return Array.from({ length: Math.ceil(column.length / rows) }, (_, b) => { - const offset = b * rows, - length = Math.min(rows, column.length - offset); - return { - ...frame, - rows: { kind: 'range', offset, count: length }, - columns: { - voltage: { ...column, values: column.values.subarray(offset, offset + length), length }, - }, - }; - }); -} -/** A model connected over a local WebSocket, and accepted at the other end. */ -export async function connected(monitor: Model['monitor']) { - const server = new WebSocketServer({ port: 0, host: '127.0.0.1', perMessageDeflate: false }); - await new Promise((resolve) => server.once('listening', resolve)); - const accepted = new Promise((resolve, reject) => - server.once('connection', (socket) => void acceptModel({ socket }).then(resolve, reject)), - ); - const connection = await connectModel( - { name: 'grid', schema, monitor }, - { url: 'http://127.0.0.1:' + (server.address() as AddressInfo).port }, - ); - const model = await accepted; - return { - model, - async close() { - await connection.close(); - await model.close(); - await new Promise((resolve) => server.close(resolve)); - }, - }; -} -function names(prefix: string, count: number) { - return textColumn(Array.from({ length: count }, (_, i) => prefix + i)); -} -function numbers(values: Float32Array) { - return { kind: 'numeric' as const, offset: 0, length: values.length, values }; -} - -/** Text with fixed metrics, so frames with labels need no canvas. */ -const rasterizer: TextRasterizer = { - rasterize: async (input) => ({ - width: 8, - height: 8, - coverage: new Uint8Array(64).fill(255), - advance: input.text.length * 0.55, - left: 0, - top: -0.75, - ascent: 0.75, - descent: 0.2, - }), -}; -const rasterizations = new WeakMap number>(); -export async function gpu(): Promise { - let count = 0; - const device = await createGpu({ - device: nullDevice(), - text: { - rasterizer: { - rasterize: (input, options) => { - count++; - return rasterizer.rasterize(input, options); - }, - }, - }, - budget: { cpuBytes: 512 * 1024 ** 2, gpuBytes: 2 * 1024 ** 3, entries: 100_000 }, - }); - rasterizations.set(device, () => count); - return device; -} -/** Work is scoped to each benchmark GPU, including its text rasterizer and the vertices it draws. */ -export function counters(device: Gpu) { - return { - ...device.stats(), - rasterized: rasterizations.get(device)?.() ?? 0, - vertices: drawnVertices(device.device), - }; -} - -const surfaces = new WeakMap(); -/** One offscreen 1280 × 720 frame of a view or renderer through the public render path. */ -export async function draw( - gpu: Gpu, - view: View | kit.Renderer, - at = 0, - completion: 'progressive' | 'complete' = 'progressive', -): Promise { - let target = surfaces.get(gpu); - if (!target) { - const texture = gpu.device.createTexture({ - size: [1280, 720], - format: 'rgba8unorm', - usage: GPUTextureUsage.RENDER_ATTACHMENT, - }); - target = { - device: gpu.device, - format: 'rgba8unorm', - width: 1280, - height: 720, - texture: () => texture, - }; - surfaces.set(gpu, target); - } - await gpu.render({ - timeMs: 0, - completion, - views: [ - { - renderer: 'capture' in view ? view : kit.rendererOf(view), - target, - at, - viewport: { width: 1280, height: 720, pixelRatio: 1 }, - }, - ], - }); - await gpu.idle(); -} - -/** Drain an async iterable, as a consumer of blocks would. */ -export async function drain(blocks: AsyncIterable): Promise { - let count = 0; - for await (const _ of blocks) count++; - return count; -} - -/** Counters that only grow; the gate compares their change per run. */ -const COUNTERS = [ - 'queries', - 'queryHits', - 'uploads', - 'uploadedBytes', - 'uploadHits', - 'gpuCopiedBytes', - 'allocations', - 'submissions', - 'evictions', - 'stagedBytes', - 'rasterized', - 'vertices', -] as const; -type Counters = Partial>; -const work: Record> = {}; - -/** - * Benchmarks in one group. Each records its deterministic work per run, from `stats`, for the gate; - * larger sizes run fewer iterations. - */ -export function suite( - group: string, - size: number, - stats?: () => Counters, - iterations = size >= 1_000_000 ? 6 : size >= 100_000 ? 12 : 24, -) { - return (name: string, run: (i: number) => unknown): void => { - let i = 0, - runs = 0, - before: Counters | undefined; - bench( - name, - async () => { - runs++; - await run(i++); - }, - { - iterations, - time: 0, - warmupIterations: 2, - warmupTime: 0, - setup: (_task, mode) => { - runs = 0; - if (mode === 'run') before = stats?.(); - }, - teardown: (_task, mode) => { - if (mode !== 'run' || !before || !stats) return; - const after = stats(); - work[group + ' > ' + name] = Object.fromEntries( - COUNTERS.filter((key) => after[key] !== undefined).map((key) => [ - key, - round(((after[key] ?? 0) - (before![key] ?? 0)) / Math.max(1, runs)), - ]), - ); - record(group); - }, - }, - ); - }; -} -const round = (value: number) => Math.round(value * 1000) / 1000; -/** Each group writes its own file, so benchmark files may run in parallel. */ -function record(group: string): void { - const entries = Object.fromEntries( - Object.entries(work).filter(([key]) => key.startsWith(group + ' > ')), - ); - const directory = new URL('./.results/work/', import.meta.url); - mkdirSync(directory, { recursive: true }); - writeFileSync( - new URL(group.replace(/[^\w-]+/g, '-') + '.json', directory), - JSON.stringify(entries, null, 2) + '\n', - ); -} diff --git a/benchmark/index.html b/benchmark/index.html new file mode 100644 index 00000000..723fc62a --- /dev/null +++ b/benchmark/index.html @@ -0,0 +1,34 @@ + + + + + + + latkit bench + + + +
+ + + diff --git a/benchmark/judge.ts b/benchmark/judge.ts new file mode 100644 index 00000000..b504c6ec --- /dev/null +++ b/benchmark/judge.ts @@ -0,0 +1,212 @@ +/** + * What the runs say. Rules that hold on any machine: no errors, nothing drawn idle, no pipeline + * compiled where it was first used, resident data within its budget, every phase growing no faster + * than its order, and no more work than the work baseline. Frames are stepped, each waiting for the + * GPU, so what the data and the frames drawn set (`EXACT`) is held exactly in a phase that acts once + * and settles, unless fetched data feeds it; the rest, and every count of a phase acting each frame, + * moves with the frame a job or a fetch lands in, and is held within `STEADY`. Then, on the machine + * the times baseline was taken on, no phase much slower. + */ +import type { Work } from 'latkit'; +import type { Listed, Run } from './page/main.ts'; + +/** A phase at a size, across repeats: times their medians, work its least. */ +export interface Summary { + /** A steady phase's CPU per frame, else its milliseconds. */ + time: number; + gpu: number; + steady: boolean; + /** Frames drawn, median. */ + frames: number; + work: Work & { resident: number }; +} + +type By = Record>>; +export type WorkBaseline = By; +export interface TimeBaseline { + machine: string; + times: By<{ time: number; gpu: number }>; +} +export type Growth = Partial>; +export interface Verdict { + failures: string[]; + notes: string[]; + summaries: By; + /** The exponent each measure grows by, by scenario and phase. */ + exponents: Record>; +} + +/** How far a fitted exponent may pass its order: noise, and a change of regime between sizes. */ +const SLACK = 0.2; +/** Milliseconds a phase acting once may land later than its baseline by: a timer tick, which is + * 15.6 ms on Windows, so readbacks answer one tick or the next. */ +const TICK = 16; +/** Bytes a changed row uploads at least: its page, 65,536 rows of four bytes. */ +const PAGE = 65536 * 4; +/** Below these a cost counts as these: too small to fit an exponent to, or to call slower. A frame's + * CPU time is read on a page's clock, which steps by 0.1 ms, so it counts from five steps; a phase + * acting once lands on a tick. */ +const FLOOR = { frame: 0.5, action: TICK, bytes: 64 * 1024 }; +/** How much slower than the baseline a median may be. */ +const SLOWER = 1.25; +/** Work the data and the frames drawn alone set, which repeats exactly once a phase settles. */ +const EXACT = new Set(['uploaded', 'evaluated', 'jobs', 'pipelines', 'late', 'resident']); +/** How much more of the rest a phase may do than the baseline: the frame a job or a fetch lands in + * moves label placements and tiles by up to about 1.7×, and a per-frame blowup by far more. */ +const STEADY = 2; +/** Below these, work counts as these when it is held within `STEADY`: bytes, and other counts. */ +const WORK_FLOOR = { bytes: 64 * 1024, count: 8 }; +const BYTES = new Set(['uploaded', 'written', 'resident']); + +const median = (xs: number[]) => + [...xs].sort((a, b) => a - b)[Math.floor((xs.length - 1) / 2)] ?? 0; +const sum = (xs: number[]) => xs.reduce((a, b) => a + b, 0); +const mib = (n: number) => `${(n / 2 ** 20).toFixed(1)} MiB`; + +/** The least-squares slope of log cost against log size: the exponent the cost grows by. */ +function slope(points: (readonly [number, number])[]): number { + const xs = points.map(([n]) => Math.log(n)); + const ys = points.map(([, c]) => Math.log(c)); + const [mx, my] = [sum(xs) / xs.length, sum(ys) / ys.length]; + return sum(xs.map((x, i) => (x - mx) * (ys[i]! - my))) / sum(xs.map((x) => (x - mx) ** 2)); +} + +function summarize(runs: Run[]): By { + const out: By = {}; + const groups = Map.groupBy(runs, (r) => `${r.scenario}\0${r.size}`); + for (const group of groups.values()) { + const { scenario, size, phases } = group[0]!; + for (const [phase, { steady }] of Object.entries(phases)) { + const costs = group.map((r) => r.phases[phase]!); + const work = costs.map((c) => ({ ...c.work, resident: c.resident })); + ((out[scenario] ??= {})[size] ??= {})[phase] = { + steady, + time: median(costs.map((c) => (steady ? c.cpu : c.ms))), + gpu: median(costs.map((c) => c.gpu)), + frames: median(costs.map((c) => c.frames)), + work: Object.fromEntries( + Object.keys(work[0]!).map((k) => [ + k, + Math.min(...work.map((w) => w[k as keyof typeof w])), + ]), + ) as unknown as Summary['work'], + }; + } + } + return out; +} + +export function judge( + runs: Run[], + list: Listed[], + base: { work?: WorkBaseline; times?: TimeBaseline }, +): Verdict { + const failures: string[] = []; + const notes: string[] = []; + for (const r of runs) { + const at = `${r.scenario} at ${r.size}`; + for (const error of r.errors) failures.push(`${at}: ${error}`); + if (r.idle) failures.push(`${at}: ${r.idle} frames drawn while nothing changed`); + for (const [phase, { work }] of Object.entries(r.phases)) + if (work.late) + failures.push( + `${at}, ${phase}: ${work.late} pipelines compiled where first used, not asked for ahead`, + ); + const resident = Math.max(...Object.values(r.phases).map((c) => c.resident)); + if (resident > r.budget) + failures.push(`${at}: ${mib(resident)} resident, over its ${mib(r.budget)} budget`); + } + const summaries = summarize(runs); + const exponents: Verdict['exponents'] = {}; + const sameMachine = !!base.times && base.times.machine === runs[0]?.machine; + for (const scenario of list) { + const bySize = summaries[scenario.name]; + if (!bySize) continue; + const sizes = Object.keys(bySize) + .map(Number) + .sort((a, b) => a - b); + for (const [phase, order] of Object.entries(scenario.orders)) { + const at = sizes.filter((n) => bySize[n]![phase]); + if (!at.length) continue; + const steady = bySize[at[0]!]![phase]!.steady; + const grows = (read: (s: Summary) => number, floor: number) => + at.length > 1 + ? slope(at.map((n) => [n, Math.max(read(bySize[n]![phase]!), floor)] as const)) + : undefined; + const fit: Growth = { + time: grows((s) => s.time, steady ? FLOOR.frame : FLOOR.action), + gpu: grows((s) => s.gpu, FLOOR.frame), + // Pages are what changes upload: below a page a frame drawn, bytes count as that. + uploaded: grows((s) => Math.max(s.work.uploaded, s.frames * PAGE), FLOOR.bytes), + resident: grows((s) => s.work.resident, FLOOR.bytes), + }; + (exponents[scenario.name] ??= {})[phase] = fit; + const past = (what: string, e: number | undefined, limit: number | undefined) => { + if (e !== undefined && limit !== undefined && e > limit + SLACK) + failures.push( + `${scenario.name} ${phase}: ${what} grows as n^${e.toFixed(2)}, past n^${limit}`, + ); + }; + past('time', fit.time, order.time); + past('uploaded bytes', fit.uploaded, order.bytes); + // What stays resident is the data's footprint, set by loading; later phases only add to it. + if (phase === 'load') past('resident bytes', fit.resident, order.bytes); + for (const n of at) { + const now = bySize[n]![phase]!; + const where = `${scenario.name} at ${n}, ${phase}`; + const baseline: Partial = base.work?.[scenario.name]?.[n]?.[phase] ?? {}; + for (const [k, was] of Object.entries(baseline) as [keyof Summary['work'], number][]) { + const is = now.work[k]; + const floor = BYTES.has(k) ? WORK_FLOOR.bytes : WORK_FLOOR.count; + const exact = !now.steady && !scenario.fetches && EXACT.has(k); + const most = exact ? was : Math.max(was, floor) * STEADY; + if (is > most) failures.push(`${where}: ${k} ${is}, was ${was}`); + else if (is < was) notes.push(`${where}: ${k} ${is}, was ${was}; --update keeps it`); + } + const then = sameMachine ? base.times!.times[scenario.name]?.[n]?.[phase] : undefined; + const floor = now.steady ? FLOOR.frame : TICK; + if (then && now.time > then.time * SLOWER + floor) + failures.push(`${where}: ${now.time.toFixed(2)} ms, was ${then.time.toFixed(2)}`); + else if (then && now.time < then.time / SLOWER) + notes.push( + `${where}: ${now.time.toFixed(2)} ms, was ${then.time.toFixed(2)}; --update keeps it`, + ); + } + } + } + return { failures, notes, summaries, exponents }; +} + +const map = (v: Verdict, read: (s: Summary) => T): By => + Object.fromEntries( + Object.entries(v.summaries).map(([s, bySize]) => [ + s, + Object.fromEntries( + Object.entries(bySize).map(([n, byPhase]) => [ + n, + Object.fromEntries(Object.entries(byPhase).map(([p, x]) => [p, read(x)])), + ]), + ), + ]), + ); + +/** `run` laid over `base`, scenario by size: each size this run measured replaces the base's, and + * the rest stays. */ +function over(run: By, base: By = {}): By { + const out = structuredClone(base); + for (const [scenario, bySize] of Object.entries(run)) + Object.assign((out[scenario] ??= {}), bySize); + return out; +} + +/** The work baseline: this run's laid over `base`. */ +export function work(v: Verdict, base?: WorkBaseline): WorkBaseline { + const measured = map(v, (s) => s.work); + return over(measured, base); +} + +/** The times baseline of `machine`: this run's laid over `base`, where `base` was taken on it. */ +export function times(v: Verdict, machine: string, base?: TimeBaseline): TimeBaseline { + const measured = map(v, (s) => ({ time: s.time, gpu: s.gpu })); + return { machine, times: over(measured, base?.machine === machine ? base.times : undefined) }; +} diff --git a/benchmark/model.bench.ts b/benchmark/model.bench.ts deleted file mode 100644 index 03f9f9f5..00000000 --- a/benchmark/model.bench.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { describe } from 'vitest'; -import { - appendData, - createData, - createMemory, - createReader, - read, - selectBatches, -} from '@latkit/model'; -import { batches, drain, frames, grid, schema, sizes, suite, voltages } from './harness.ts'; - -describe.each(sizes)('model %i buses', (buses) => { - const data = grid(buses), - input = batches(buses), - next = voltages(buses, frames), - reader = createReader({ memory: createMemory({ cpuBytes: 512 * 1024 ** 2 }) }), - window = { kind: 'range', between: [0, frames - 1] } as const; - const fields = () => { - const scope = reader.open(); - return drain(scope.fields({ source: data, from: 'Bus', fields: { load: 'load' } })).finally( - () => scope.close(), - ); - }; - const measure = suite(`model ${buses} buses`, buses, () => reader.stats()); - measure('createData', () => createData(schema, input)); - measure('appendData frame', () => appendData(data, [next])); - measure('read rows', () => drain(read(data, { kind: 'rows', from: 'Bus', select: ['load'] }))); - measure('read samples', () => - drain(read(data, { kind: 'samples', from: 'Bus', select: ['voltage'], window })), - ); - measure('read envelope', () => - drain(read(data, { kind: 'envelope', from: 'Bus', select: ['voltage'], window, buckets: 8 })), - ); - measure('selectBatches', () => - drain(selectBatches(data, [{ from: 'Bus', select: ['load', 'voltage'] }])), - ); - measure('reader fields, cold', () => { - reader.trim(); - return fields(); - }); - measure('reader fields, cached', fields); - measure('reader extent', async () => { - const scope = reader.open(); - try { - return await scope.extent({ source: data, from: 'Bus', field: 'voltage', window }); - } finally { - scope.close(); - } - }); -}); diff --git a/benchmark/monitor.bench.ts b/benchmark/monitor.bench.ts deleted file mode 100644 index 37b90512..00000000 --- a/benchmark/monitor.bench.ts +++ /dev/null @@ -1,289 +0,0 @@ -import { describe } from 'vitest'; -import { appendData, type Data, type Domain } from '@latkit/model'; -import { pulse, type RGBA, type Colormap } from '@latkit/gpu'; -import { createMonitor, type Monitor } from '@latkit/monitor'; -import { busIndex, counters, draw, frames, gpu, grid, suite, voltages } from './harness.ts'; - -/** A frame of voltages swinging wider than any before, as a disturbance grows: every frame is a new extreme. */ -function swelling(buses: number, frame: number): Data.SampleBatch { - const batch = voltages(buses, frame), - swing = 0.05 + frame * 0.01, - values = Float32Array.from( - { length: buses }, - (_, i) => 1 + Math.sin(i * 0.01 + frame * 0.2) * swing, - ); - return { - ...batch, - columns: { voltage: { ...batch.columns.voltage, values } }, - }; -} - -/** A trace per row: monitors scale with the rows they draw. */ -describe.each([100, 1_000, 10_000])('monitor %i rows', async (rows) => { - const device = await gpu(); - let data = grid(rows); - // A fixed window with room for the stream, as a run that declares its domain uses. - const config: Monitor.Config = { - source: data, - traces: { voltage: { from: 'Bus', y: 'voltage' } }, - camera: { x: [0, frames * 4] }, - }; - const view = createMonitor(device, config); - await draw(device, view, 0, 'complete'); - const measure = suite(`monitor ${rows} rows`, rows, () => counters(device), 12); - measure('first frame', async () => { - const fresh = createMonitor(device, config); - await draw(device, fresh, 0, 'complete'); - fresh.destroy(); - }); - measure('cached frame', () => draw(device, view)); - // Moving the playhead never reads history again. - measure('playhead', (i) => draw(device, view, i % frames)); - // A quarter in: inside the recorded frames of the wide window. - measure('pick', () => view.pick([280, 360], { radiusPx: 24 })); - // Each new frame draws alone, joined to the last. - measure('stream frame', async (i) => { - data = appendData(data, [voltages(rows, frames + i)]); - view.set({ source: data }); - await draw(device, view, frames + i, 'complete'); - }); - // A new window redraws history behind the shown image. - measure('change window', async (i) => { - view.set({ camera: { x: [0, frames * 4 + 1 + (i % 2)] } }); - await draw(device, view, 0, 'complete'); - }); - // Each new frame a new extreme, with the values fitted: the fit grows, history stands. - let swollen = grid(rows); - const growing = createMonitor(device, { ...config, source: swollen }); - await draw(device, growing, 0, 'complete'); - measure('stream frame, growing extremes', async (i) => { - swollen = appendData(swollen, [swelling(rows, frames + i)]); - growing.set({ source: swollen }); - await draw(device, growing, frames + i, 'complete'); - }); -}); - -/** How a scenario's traces look this iteration: mapped traces' domain and colormap, fixed traces' color. */ -interface Look { - readonly domain: Domain; - readonly colormap: Colormap.Name; - readonly color: RGBA; -} -const lookAt = (i: number): Look => ({ - domain: [0.95 - i * 1e-3, 1.05 + i * 1e-3], - colormap: i % 2 ? 'magma' : 'viridis', - color: [0.2 + (i % 5) * 0.15, 0.6, 0.9, 0.8], -}); -/** The `i`th of `n` equal row ranges. */ -const part = (rows: number, i: number, n: number) => { - const offset = Math.floor((rows * i) / n); - return { kind: 'range' as const, offset, count: Math.floor((rows * (i + 1)) / n) - offset }; -}; -const fixed = (color: RGBA, rows?: ReturnType) => ({ - from: 'Bus', - y: 'voltage', - color, - ...(rows && { rows }), -}); -const mapped = (look: Look, rows?: ReturnType, shift = 0) => ({ - from: 'Bus', - y: 'voltage', - color: { - field: 'voltage', - domain: [look.domain[0] - shift, look.domain[1] + shift] as const, - colormap: look.colormap, - }, - ...(rows && { rows }), -}); -/** - * Trace setups, each over every row: one trace, or four drawing a quarter each, so every setup draws - * the same segments. Fixed traces take a color; mapped traces color by what they plot. - */ -const SCENARIOS: Record< - string, - { traces(rows: number, look: Look): Monitor.Config['traces']; style?: Partial } -> = { - 'one fixed trace': { traces: (_, look) => ({ a: fixed(look.color) }) }, - 'one mapped trace': { traces: (_, look) => ({ a: mapped(look) }) }, - 'one trace colored by another field': { - traces: (_, look) => ({ - a: { - from: 'Bus', - y: 'voltage', - color: { - field: 'load', - domain: [look.domain[0] - 0.95, look.domain[1] - 0.05] as const, - colormap: look.colormap, - }, - }, - }), - }, - 'one following trace': { - traces: (_, look) => ({ - a: { from: 'Bus', y: 'voltage', color: { field: 'voltage', colormap: look.colormap } }, - }), - }, - 'four fixed traces': { - traces: (rows, look) => - Object.fromEntries( - ['a', 'b', 'c', 'd'].map((name, i) => [ - name, - fixed([look.color[0], look.color[1], i / 4, 0.8], part(rows, i, 4)), - ]), - ), - }, - 'four mapped traces, one look': { - traces: (rows, look) => - Object.fromEntries( - ['a', 'b', 'c', 'd'].map((name, i) => [name, mapped(look, part(rows, i, 4))]), - ), - }, - 'four mapped traces, four looks': { - traces: (rows, look) => - Object.fromEntries( - ['a', 'b', 'c', 'd'].map((name, i) => [name, mapped(look, part(rows, i, 4), i * 0.01)]), - ), - }, - // Past the looks an image keeps apart, the rest bake into its color layer. - 'eight traces colored by another field, eight looks': { - traces: (rows, look) => - Object.fromEntries( - Array.from({ length: 8 }, (_, i) => [ - 't' + i, - { - from: 'Bus', - y: 'voltage', - rows: part(rows, i, 8), - color: { - field: 'load', - domain: [look.domain[0] - 0.95 - i * 0.01, look.domain[1] - 0.05] as const, - colormap: look.colormap, - }, - }, - ]), - ), - }, - 'two fixed, two mapped traces': { - traces: (rows, look) => ({ - a: fixed(look.color, part(rows, 0, 4)), - b: mapped(look, part(rows, 1, 4)), - c: fixed([0.9, 0.4, 0.2, 0.8], part(rows, 2, 4)), - d: mapped(look, part(rows, 3, 4)), - }), - }, - 'one mapped trace, msaa': { traces: (_, look) => ({ a: mapped(look) }), style: { msaa: 4 } }, -}; - -/** Each setup through every change an application makes, at two sizes: what each costs. */ -describe.each( - Object.keys(SCENARIOS).flatMap((scenario) => - [1_000, 10_000].map((rows) => [scenario, rows] as const), - ), -)('monitor %s %i rows', async (scenario, rows) => { - const device = await gpu(), - { traces, style } = SCENARIOS[scenario], - configOf = (source: Data, i = 0): Monitor.Config => ({ - source, - traces: traces(rows, lookAt(i)), - camera: { x: [0, frames * 4] }, - // Large enough for every setup; the memory each holds is reported apart. - limits: { historyBytes: 1024 ** 3 }, - ...style, - }); - /** A monitor drawn whole, before anything is measured. */ - const ready = async (extra: Partial = {}) => { - const view = createMonitor(device, { ...configOf(grid(rows)), ...extra }); - await draw(device, view, 0, 'complete'); - return view; - }; - const measure = suite(`monitor ${scenario} ${rows} rows`, rows, () => counters(device), 12); - const at = (view: Monitor, i: number, set: Parameters[0]) => { - view.set(set); - return draw(device, view, i % frames, 'complete'); - }; - - measure('first frame', async () => { - const fresh = createMonitor(device, configOf(grid(rows))); - await draw(device, fresh, 0, 'complete'); - fresh.destroy(); - }); - const cached = await ready(); - measure('cached frame', () => draw(device, cached)); - measure('playhead', (i) => draw(device, cached, i % frames)); - measure('pick', () => cached.pick([280, 360], { radiusPx: 24 })); - // The pointer rests while the playhead moves: what was drawn stands, and so does its answer. - measure('pick during playback', async (i) => { - await draw(device, cached, i % frames); - return cached.pick([280, 360], { radiusPx: 24 }); - }); - - // A live run: each new frame draws alone, joined to the last. - let streamed = grid(rows); - const stream = await ready(); - measure('stream frame', async (i) => { - streamed = appendData(streamed, [voltages(rows, frames + i)]); - stream.set({ source: streamed }); - await draw(device, stream, frames + i, 'complete'); - }); - // As live extremes widen the domain, and a fixed color changes. - const recolor = await ready(); - measure('recolor', (i) => at(recolor, i, { traces: traces(rows, lookAt(i + 1)) })); - // A new colormap; for fixed traces, a new theme's trace color. - const palette = await ready(); - measure('palette', (i) => - at(palette, i, { - traces: traces(rows, { ...lookAt(0), colormap: i % 2 ? 'viridis' : 'magma' }), - traceColor: i % 2 ? [0.23, 0.72, 0.88, 0.7] : [0.88, 0.5, 0.2, 0.7], - }), - ); - // Both in one change, as a live run streams with a global domain. - let live = grid(rows); - const both = await ready(); - measure('stream frame, new look', async (i) => { - live = appendData(live, [voltages(rows, frames + i)]); - both.set({ source: live, traces: traces(rows, lookAt(i + 1)) }); - await draw(device, both, frames + i, 'complete'); - }); - // A live run of growing extremes with fitted values, as Studio streams one: mapped traces' global - // domain widens with each frame, and fixed colors stay as they are. - let swollen = grid(rows); - const growing = await ready(); - measure('stream frame, growing extremes', async (i) => { - swollen = appendData(swollen, [swelling(rows, frames + i)]); - growing.set({ - source: swollen, - traces: traces(rows, { ...lookAt(i + 1), color: lookAt(0).color }), - }); - await draw(device, growing, frames + i, 'complete'); - }); - // Selecting a row draws it over the rest; clearing removes it. - const select = await ready(); - measure('select', (i) => { - select.select(i % 2 ? [] : [{ source: select.config.source, index: busIndex(rows), row: 7 }]); - return draw(device, select, 0, 'complete'); - }); - // A new window draws history again, behind the shown image. - const windowed = await ready(); - measure('change window', (i) => - at(windowed, i, { camera: { x: [0, frames * 4 + 1 + (i % 2)] } }), - ); - // A new width moves every line's pixels. - const width = await ready(); - measure('trace width', (i) => at(width, i, { traceWidthPx: i % 2 ? 1.25 : 2 })); - // A small trace comes and goes beside the rest. - const adding = await ready(); - measure('add trace', (i) => - at(adding, i, { - traces: { - ...traces(rows, lookAt(0)), - extra: - i % 2 - ? null - : { from: 'Bus', y: 'voltage', rows: { kind: 'range', offset: 0, count: 16 } }, - }, - }), - ); - // A shade that moves every frame. - const shaded = await ready({ shade: pulse() }); - measure('animated shade', () => draw(device, shaded)); -}); diff --git a/benchmark/network.bench.ts b/benchmark/network.bench.ts deleted file mode 100644 index 3c414636..00000000 --- a/benchmark/network.bench.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { describe } from 'vitest'; -import { createNetwork, type Network } from '@latkit/network'; -import { branchIndex, busIndex, counters, draw, gpu, grid, sizes, suite } from './harness.ts'; - -describe.each(sizes)('network %i buses', async (buses) => { - const device = await gpu(), - data = grid(buses); - const config: Network.Config = { - source: data, - vertices: { - Bus: { - x: 'position', - y: { field: 'position', component: 1 }, - color: { field: 'voltage', domain: [0.95, 1.05] }, - radiusPx: 'load', - }, - }, - edges: { Branch: { ends: ['from', 'to'] } }, - }; - const view = createNetwork(device, config); - await draw(device, view); - const measure = suite(`network ${buses} buses`, buses, () => counters(device)); - measure('first frame', async () => { - const fresh = createNetwork(device, config); - await draw(device, fresh); - fresh.destroy(); - }); - measure('cached frame', () => draw(device, view)); - measure('playback frame', (i) => draw(device, view, i)); - // Before anything moves the fitted camera. - measure('pick', () => view.pick([640, 360])); - measure('restyle', (i) => { - view.set({ vertices: { Bus: { radiusPx: i % 2 ? 'load' : null } } }); - return draw(device, view); - }); - // A wider color domain, as a live run's extremes grow: the same reads, new uniforms. - measure('recolor', (i) => { - view.set({ - vertices: { - Bus: { color: { field: 'voltage', domain: [0.95 - i * 1e-3, 1.05 + i * 1e-3] } }, - }, - }); - return draw(device, view); - }); - measure('camera move', (i) => { - view.set({ camera: { scale: 1 + (i % 8) } }); - return draw(device, view); - }); - // A bus and a branch selected draw over the rest; clearing them draws as before. - measure('select', (i) => { - view.select( - i % 2 - ? [] - : [ - { kind: 'vertex', source: data, index: busIndex(buses), row: 7 }, - { kind: 'edge', source: data, index: branchIndex(buses), row: 7 }, - ], - ); - return draw(device, view); - }); -}); - -// Positions from layout alone: stress places every bus by its branches once, then frames reuse it. -describe.each(sizes.filter((buses) => buses <= 100_000))( - 'network %i buses unpositioned', - async (buses) => { - const device = await gpu(), - config: Network.Config = { - source: grid(buses), - vertices: { Bus: { radiusPx: 'load' } }, - edges: { Branch: { ends: ['from', 'to'] } }, - }; - const view = createNetwork(device, config); - await draw(device, view); - const measure = suite(`network ${buses} buses unpositioned`, buses, () => counters(device)); - measure('first frame', async () => { - const fresh = createNetwork(device, config); - await draw(device, fresh); - fresh.destroy(); - }); - measure('cached frame', () => draw(device, view)); - measure('restyle', (i) => { - view.set({ vertices: { Bus: { radiusPx: i % 2 ? 'load' : null } } }); - return draw(device, view); - }); - }, -); diff --git a/benchmark/package.json b/benchmark/package.json index 9cae5579..00314dcd 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -1,22 +1,18 @@ { - "name": "@latkit/benchmark", + "name": "latkit-bench", "private": true, "version": "0.0.0", "type": "module", "scripts": { - "typecheck": "tsc -p tsconfig.json --noEmit" + "bench": "node run.ts" }, "dependencies": { - "@latkit/connect": "workspace:*", - "@latkit/diagram": "workspace:*", - "@latkit/gpu": "workspace:*", - "@latkit/model": "workspace:*", - "@latkit/monitor": "workspace:*", - "@latkit/network": "workspace:*" + "latkit": "link:../npm" }, "devDependencies": { - "@types/ws": "^8.18.2", - "@webgpu/types": "^0.1.71", - "ws": "8.21.0" + "@types/node": "^26.1.1", + "playwright-core": "1.64.0", + "typescript": "^5.7.0", + "vite": "^7.0.0" } } diff --git a/benchmark/page/data.ts b/benchmark/page/data.ts new file mode 100644 index 00000000..b0326817 --- /dev/null +++ b/benchmark/page/data.ts @@ -0,0 +1,134 @@ +/** + * What the scenarios draw, made before anything is measured: deterministic, so every run counts the + * same work, and linear in size. Each returns a `Write` that only hands latkit the arrays. + */ +import { reference, type Values } from 'latkit'; +import type { Write } from './stage.ts'; + +/** Axis coordinates a second. */ +const RATE = 60; + +/** Numbers in [0, 1), the same every run. */ +function random(seed: number): () => number { + let s = seed >>> 0 || 1; + return () => (s = (Math.imul(s, 1664525) + 1013904223) >>> 0) / 2 ** 32; +} + +/** `n` points in the unit square, each with a value, and a name when `named`. */ +export function scatter(n: number, seed = 1, named = false): Write { + const next = random(seed); + const [x, y, v] = [new Float64Array(n), new Float64Array(n), new Float32Array(n)]; + for (let i = 0; i < n; i++) [x[i], y[i], v[i]] = [next(), next(), next()]; + const fields: Record = { x, y, v }; + if (named) fields.name = Array.from({ length: n }, (_, i) => `P${i}`); + return (p) => p.set('Point', { count: n }, fields); +} + +/** About `n` buses in a square lattice over most of the globe, each joined to its right and lower + * neighbours: a grid's shape at any size. */ +export function lattice(n: number): Write { + const side = Math.max(2, Math.round(Math.sqrt(n))); + const count = side * side; + const [lon, lat, load] = [ + new Float64Array(count), + new Float64Array(count), + new Float32Array(count), + ]; + for (let i = 0; i < count; i++) { + lon[i] = -170 + (340 * (i % side)) / (side - 1); + lat[i] = -75 + (150 * Math.floor(i / side)) / (side - 1); + load[i] = Math.hypot(lon[i]! / 170, lat[i]! / 75) / Math.SQRT2; + } + const lines = 2 * side * (side - 1); + const [from, to] = [new Uint32Array(lines), new Uint32Array(lines)]; + let e = 0; + for (let i = 0; i < count; i++) { + if (i % side < side - 1) { + from[e] = i; + to[e++] = i + 1; + } + if (i + side < count) { + from[e] = i; + to[e++] = i + side; + } + } + return (p) => + p + .set('Bus', { count }, { lon, lat, load }) + .set('Line', { count: lines }, { from: reference('Bus', from), to: reference('Bus', to) }); +} + +/** `n` edges among 16 vertices on a ring, each joining a vertex to the next: lanes by the thousand. */ +export function lanes(n: number): Write { + const k = 16; + const x = Float64Array.from({ length: k }, (_, i) => Math.cos((2 * Math.PI * i) / k)); + const y = Float64Array.from({ length: k }, (_, i) => Math.sin((2 * Math.PI * i) / k)); + const from = Uint32Array.from({ length: n }, (_, e) => e % k); + const to = Uint32Array.from({ length: n }, (_, e) => (e + 1) % k); + return (p) => + p + .set('Point', { count: k }, { x, y, v: new Float32Array(k) }) + .set('Link', { count: n }, { from: reference('Point', from), to: reference('Point', to) }); +} + +/** `n` regular 32-gons in a grid over the mercator world, each with a value. */ +export function polygons(n: number, sides = 32): Write { + const across = Math.ceil(Math.sqrt(2 * n)); + const [w, h] = [340 / across, 140 / Math.ceil(n / across)]; + const r = 0.4 * Math.min(w, h); + const rings = new Array<[number, number][][]>(n); + const v = new Float32Array(n); + for (let i = 0; i < n; i++) { + const [cx, cy] = [-170 + ((i % across) + 0.5) * w, -70 + (Math.floor(i / across) + 0.5) * h]; + const ring = Array.from({ length: sides + 1 }, (_, k): [number, number] => { + const a = (2 * Math.PI * (k % sides)) / sides; + return [cx + r * Math.cos(a), cy + r * Math.sin(a)]; + }); + rings[i] = [ring]; + v[i] = (i % 97) / 97; + } + return (p) => p.set('Region', { count: n }, { rings, v }); +} + +/** `n` blocks in trees of 64: each block's output is a net, which its two children's inputs name. */ +export function blocks(n: number): Write { + const input = new Array(n); + const name = new Array(n); + for (let i = 0; i < n; i++) { + const k = i % 64; + input[i] = k === 0 ? null : i - k + ((k - 1) >> 1); + name[i] = `Block ${i}`; + } + return (p) => + p + .set('Net', { count: n }, { k: new Float32Array(n) }) + .set( + 'Block', + { count: n }, + { name, in: reference('Net', input), out: reference('Net', { count: n }) }, + ); +} + +const wave = (r: number, f: number) => Math.sin(r * 0.37 + f * 0.05) + (r % 10) * 0.2; + +/** `rows` traces of `frames` samples at 60 a second, each its own wave. */ +export function traces(rows: number, frames: number): Write { + const all = new Float32Array(rows * frames); + for (let f = 0; f < frames; f++) for (let r = 0; r < rows; r++) all[f * rows + r] = wave(r, f); + const k = Float32Array.from({ length: rows }, (_, r) => r); + return (p) => { + p.axis('time', 's').set('Signal', { count: rows }, { k }); + for (let f = 0; f < frames; f++) + p.append(f / RATE, 'Signal', { v: all.subarray(f * rows, (f + 1) * rows) }); + return p; + }; +} + +/** `count` patches recording the frames from `from` on, each forgetting what falls `history` behind. */ +export function feed(rows: number, from: number, count: number, history: number): Write[] { + return Array.from({ length: count }, (_, i): Write => { + const f = from + i; + const v = Float32Array.from({ length: rows }, (_, r) => wave(r, f)); + return (p) => p.append(f / RATE, 'Signal', { v }).forget((f - history) / RATE); + }); +} diff --git a/benchmark/page/main.ts b/benchmark/page/main.ts new file mode 100644 index 00000000..85e3d2da --- /dev/null +++ b/benchmark/page/main.ts @@ -0,0 +1,137 @@ +/** + * The bench page, one implementation of the contract the runner drives: `bench.ready()` resolves + * once a GPU device can be made; `bench.list()` names the scenarios and the orders their phases + * keep; `bench.run(name, size)` builds one at a size on a fresh GPU and measures it; `bench.lost()` + * says whether that GPU's device was lost. The runner opens a fresh page for every run, so nothing + * carries over but the browser's shader cache. + */ +import { loadLatkit, type Gpu } from 'latkit'; +import { LOAD, scenarios, type Order } from './scenarios.ts'; +import { Stage, type Cost } from './stage.ts'; + +export interface Listed { + name: string; + about: string; + unit: string; + sizes: readonly number[]; + cold: boolean; + fetches: boolean; + orders: Record; +} + +export interface Run { + scenario: string; + size: number; + /** The adapter and browser: times compare only on the same machine. */ + machine: string; + /** Every phase in order: `init`, `data`, `load`, then the scenario's. */ + phases: Record; + /** Frames drawn over frames stepped once everything settled: none, for views that sleep. */ + idle: number; + /** Bytes the budget lets data take. */ + budget: number; + /** What the views told went wrong. */ + errors: string[]; +} + +/** What data may take unless a scenario sets it: fixed, so the work counted is every device's. */ +const BUDGET = { bytes: 256 * 2 ** 20, uploadPerFrame: 32 * 2 ** 20 }; + +/** The GPU of the run under way, which `lost` asks after. */ +let current: Gpu | undefined; + +/** Resolves once a GPU device can be made: a wedged driver hangs here, so the runner asks first. */ +async function ready(): Promise { + (await (await loadLatkit()).Gpu.create()).destroy(); +} + +/** Whether the run's device was lost: the runner asks after a failure, and stops the sweep if so. */ +function lost(): boolean { + return current?.lost ?? false; +} + +function list(): Listed[] { + return Object.entries(scenarios).map(([name, s]) => ({ + name, + about: s.about, + unit: s.unit, + sizes: s.sizes, + cold: !!s.cold, + fetches: !!s.fetches, + orders: { + init: { time: 0 }, + data: { time: 1 }, + load: s.load ?? LOAD, + ...Object.fromEntries(s.phases.map((p) => [p.name, p.order])), + }, + })); +} + +async function run(name: string, size: number): Promise { + const scenario = scenarios[name]; + if (!scenario) throw new Error(`no scenario ${name}`); + console.debug('phase init'); + const begun = performance.now(); + const latkit = await loadLatkit(); + const gpu = (current = await latkit.Gpu.create()); + const ms = performance.now() - begun; + gpu.budget = scenario.budget ?? BUDGET; + const built = scenario.build(size); + const stage = new Stage(latkit, gpu, await canvases(scenario.views?.(size) ?? 1), size); + const none = { frames: 0, cpu: 0, cpu95: 0, gpu: 0, resident: 0, steady: false }; + // Each phase says when it starts, so a page that stops answering is known by where it stopped. + const named = (phase: string, run: () => Promise) => { + console.debug(`phase ${phase}`); + return run().catch((error: unknown) => { + throw new Error(`${phase}: ${error instanceof Error ? error.message : String(error)}`); + }); + }; + const phases: Record = { + init: { ...none, ms, work: gpu.work }, + data: await named('data', () => stage.ingest(built.data)), + load: await named('load', () => stage.load(built.scene, built.tiles, built.camera)), + }; + for (const phase of scenario.phases) + phases[phase.name] = await named(phase.name, () => phase.run(stage)); + const idle = await named('idle', () => stage.idle()); + return { + scenario: name, + size, + machine: await machine(), + phases, + idle, + budget: gpu.budget.bytes, + errors: stage.errors, + }; +} + +/** `n` canvases filling the page in a grid, laid out before any view draws. */ +async function canvases(n: number): Promise { + const main = document.querySelector('main')!; + main.style.gridTemplateColumns = `repeat(${Math.ceil(Math.sqrt(n))}, minmax(0, 1fr))`; + const made = Array.from({ length: n }, () => main.appendChild(document.createElement('canvas'))); + await new Promise((resolve) => requestAnimationFrame(resolve)); + return made; +} + +/** The adapter, asked for as latkit asks for its own, and the browser. */ +async function machine(): Promise { + interface Adapter { + info?: { vendor?: string; architecture?: string; description?: string }; + } + interface Options { + powerPreference: 'high-performance'; + } + const gpu = (navigator as { gpu?: { requestAdapter(o: Options): Promise } }).gpu; + const info = (await gpu?.requestAdapter({ powerPreference: 'high-performance' }))?.info; + const chrome = /Chrome\/(\d+)/.exec(navigator.userAgent)?.[1]; + const adapter = [info?.vendor, info?.architecture, info?.description].filter(Boolean).join(' '); + return `${adapter || 'unknown adapter'} · Chrome ${chrome}`; +} + +declare global { + interface Window { + bench: { ready: typeof ready; list: typeof list; run: typeof run; lost: typeof lost }; + } +} +window.bench = { ready, list, run, lost }; diff --git a/benchmark/page/scenarios.ts b/benchmark/page/scenarios.ts new file mode 100644 index 00000000..8443d8e8 --- /dev/null +++ b/benchmark/page/scenarios.ts @@ -0,0 +1,511 @@ +/** + * Every scenario: what it sweeps, the scene and data at each size, and what it does. Each phase + * declares how its cost may grow with size, so the sweep checks the README's rules: CPU per frame + * stays flat in the rows, a one-row change costs the same at any size, restyling moves no data, + * views share pages, and loading grows no faster than the data. `init`, `data`, and `load` come + * first in every scenario, and idle frames are counted after the last. + */ +import { field, type Budget, type Camera, type ColormapName, type Scene, type Space } from 'latkit'; +import * as make from './data.ts'; +import { deadline, type Cost, type Stage, type Write } from './stage.ts'; + +export interface Scenario { + /** What it stresses. */ + about: string; + /** What a size counts, and the sizes swept, smallest first; `--quick` runs the smallest. */ + unit: string; + sizes: readonly number[]; + build(size: number): Built; + phases: readonly Phase[]; + /** How `load` may grow; with the data, in time and bytes, unless set. */ + load?: Order; + /** Views of one GPU drawing the scene; one unless set. */ + views?(size: number): number; + /** The GPU's budget, where the scenario is about it. */ + budget?: Budget; + /** Run in a fresh browser without a shader cache: what a first visit costs. */ + cold?: boolean; + /** Its data is fetched as the camera asks, so what it uploads moves with the frame a fetch lands in. */ + fetches?: boolean; +} + +export interface Built { + scene: Scene; + /** Each dataset, made beforehand, so `data` times latkit alone. */ + data: Record; + /** Vector tiles by dataset name: URL templates the bench server answers. */ + tiles?: Record; + /** Where the view looks; it fits everything unless set. */ + camera?: Camera; +} + +/** + * How a phase's cost may grow with size: 0 not at all, 1 no faster than linearly. `time` is a steady + * phase's CPU per frame or an action's milliseconds; `bytes` is what it uploaded and what stays + * resident. A measure left out is held only to the baselines. + */ +export interface Order { + time?: 0 | 1; + bytes?: 0 | 1; +} + +export interface Phase { + name: string; + order: Order; + run(stage: Stage): Promise; +} + +export const LOAD: Order = { time: 1, bytes: 1 }; +export const DECADES = [1e3, 1e4, 1e5, 1e6, 2e6]; +/** Frames a steady phase acts in: past its warm-up, enough for a steady median, and no more. */ +export const FRAMES = 40; +export const HISTORY = 1024; +type MapCamera = Extract; + +// Scenes. + +/** Dataset `d`'s points, colored by `v` through `colormap`, labeled by `label` when given. */ +const dots = (space: Space, colormap: ColormapName = 'viridis', label?: string): Scene => ({ + space, + ease: 0, + marks: [ + { + vertices: { + of: ['d', 'Point'], + position: ['x', 'y'], + color: field('v').colormap(colormap).domain(0, 1), + ...(label ? { label: field(label) } : {}), + }, + }, + ], +}); + +/** Dataset `g`'s buses, colored by load, and the lines between them. */ +const grid = (space: Space): Scene => ({ + space, + ease: 0, + marks: [ + { edges: { of: ['g', 'Line'], ends: ['from', 'to'], width: 0.6 } }, + { + vertices: { + of: ['g', 'Bus'], + position: ['lon', 'lat'], + color: field('load').colormap('viridis').domain(0, 1), + }, + }, + ], +}); + +const plot: Scene = { + space: 'plot', + ease: 0, + marks: [{ lines: { of: ['t', 'Signal'], trace: 'v' } }], +}; + +const sheet: Scene = { + space: 'diagram', + ease: 0, + layout: { layered: { flow: 'right' } }, + marks: [ + { edges: { of: ['d', 'Net'], route: 'orthogonal' } }, + { + vertices: { + of: ['d', 'Block'], + marker: 'block', + label: { text: 'name' }, + ports: [ + ['in', 'left'], + ['out', { side: 'right', output: true }], + ], + }, + }, + ], +}; + +// Phases. + +/** Pans and zooms gently about where the views looked, a frame at a time, back to where it began. */ +const pan = (order: Order = { time: 0 }): Phase => ({ + name: 'pan', + order, + run: (s) => { + const start = s.view.camera as MapCamera; + const reach = s.across(200); + return s.steady(FRAMES, (i) => { + const t = (2 * Math.PI * i) / FRAMES; + const center: [number, number] = [ + start.center[0] + reach * Math.sin(t), + start.center[1] + 0.5 * reach * Math.sin(2 * t), + ]; + for (const v of s.views) + v.camera = { ...start, center, zoom: start.zoom + 0.3 * Math.sin(2 * t) }; + }); + }, +}); + +/** Zooms two levels in and back: labels give way, tiles refine. */ +const zoom = (): Phase => ({ + name: 'zoom', + order: { time: 0 }, + run: (s) => { + const start = s.view.camera as MapCamera; + return s.steady(FRAMES, (i) => { + for (const v of s.views) + v.camera = { ...start, zoom: start.zoom + 2 * Math.sin((Math.PI * i) / FRAMES) }; + }); + }, +}); + +/** Recolors through `scene`'s colormap: the GPU evaluates again; no data moves. */ +const restyle = (scene: Scene): Phase => ({ + name: 'restyle', + order: { bytes: 0 }, + run: (s) => s.once(() => s.show(scene)), +}); + +/** Changes one row's value every frame: what one row costs at any size. */ +const one = (data: string, table: string, name: string): Phase => ({ + name: 'one row', + order: { time: 0, bytes: 0 }, + run: (s) => + s.steady(FRAMES, (i) => s.apply(data, (p) => p.set(table, [i], { [name]: [(i % 10) / 10] }))), +}); + +/** Changes every row's value at once. */ +const every = (data: string, table: string, name: string): Phase => ({ + name: 'every row', + order: { time: 1, bytes: 1 }, + run: (s) => { + const n = s.count(data, table); + const values = Float32Array.from({ length: n }, (_, i) => (i % 7) / 7); + return s.once(() => s.apply(data, (p) => p.set(table, { count: n }, { [name]: values }))); + }, +}); + +/** Asks what lies under the middle, as a click does: how long the answer takes. The first ask in a + * page makes the query's pipelines; later asks reuse them. */ +const pick = (): Phase[] => [ + { + name: 'first pick', + order: { time: 0, bytes: 0 }, + run: (s) => s.once(() => s.view.pick(s.middle, 6)), + }, + { + name: 'pick', + order: { time: 0, bytes: 0 }, + run: (s) => s.once(() => s.view.pick(s.middle, 6)), + }, +]; + +/** Moves the pointer onto a row near the middle and waits for the view to name it. */ +const hover = (): Phase => ({ + name: 'hover', + order: { time: 0, bytes: 0 }, + run: async (s) => { + const [hit] = await deadline(s.until(s.view.pick(s.middle, 40)), 10_000, 'a row to hover'); + if (!hit) { + const seen = { middle: s.middle, camera: s.view.camera, stats: s.view.stats }; + throw new Error(`nothing near the middle to hover: ${JSON.stringify(seen)}`); + } + const told: unknown[] = []; + try { + return await s.once( + () => + new Promise((resolve) => { + const stop = s.view.on('hover', ({ hit: h }) => { + told.push(h?.row ?? null); + if (!h) return; + stop(); + resolve(); + }); + s.pointer('pointermove', hit.point); + }), + ); + } catch (error) { + const seen = { + at: hit.point, + hit: hit.row, + told, + camera: s.view.camera, + stats: s.view.stats, + }; + throw new Error(`${String(error)}; ${JSON.stringify(seen)}`, { cause: error }); + } + }, +}); + +/** Selects a hundred rows: the glow, and what dims; a table drawn through tiles keeps them drawn. */ +const select = (data: string, table: string): Phase => ({ + name: 'select', + order: { time: 0 }, + run: (s) => + s.once(() => s.view.select([{ data, table, ids: Array.from({ length: 100 }, (_, id) => id) }])), +}); + +/** Moves every row to a new place at once, easing: CPU per frame while they fly. */ +const move = (): Phase => ({ + name: 'move', + order: { time: 0, bytes: 1 }, + run: (s) => { + const next = make.scatter(s.size, 2); + return s.steady(FRAMES, (i) => i === 0 && s.apply('d', next)); + }, +}); + +/** Records a frame of every trace each animation frame, as a live feed does, forgetting the oldest. */ +const stream = (): Phase => ({ + name: 'stream', + order: { time: 1, bytes: 1 }, + run: (s) => { + const feed = make.feed(s.size, HISTORY, FRAMES, HISTORY); + return s.steady(FRAMES, (i) => s.apply('t', feed[i]!)); + }, +}); + +/** Moves the coordinate shown across what was recorded: the playhead, and colors read at it. */ +const scrub = (): Phase => ({ + name: 'scrub', + order: { time: 0, bytes: 0 }, + run: (s) => { + const [a, b] = s.span('t'); + return s.steady(FRAMES, (i) => { + for (const v of s.views) v.at = a + ((b - a) * i) / FRAMES; + }); + }, +}); + +/** Narrows the window shown from everything to its last tenth: levels of detail give way, each + * trace's finer one uploading as it first draws. */ +const narrow = (order: Order = { time: 0, bytes: 0 }): Phase => ({ + name: 'narrow', + order, + run: (s) => { + const [a, b] = s.span('t'); + return s.steady(FRAMES, (i) => { + for (const v of s.views) v.camera = { x: [a + ((b - a) * 0.9 * i) / FRAMES, b], y: null }; + }); + }, +}); + +/** Renames a block every frame, so it resizes and its tree routes again: an edit at any size. */ +const edit = (): Phase => ({ + name: 'edit', + order: { time: 0, bytes: 0 }, + run: (s) => + s.steady(FRAMES, (i) => + s.apply('d', (p) => p.set('Block', [1 + (i % 63)], { name: [`Renamed block ${i}`] })), + ), +}); + +/** Lays every block out again. */ +const arrange = (): Phase => ({ + name: 'arrange', + order: { time: 1 }, + run: (s) => s.once(() => s.view.arrange()), +}); + +/** A shot of every view side by side, the scenario's size in pixels, at 16:9. */ +function shot(s: Stage) { + const width = Math.round(Math.sqrt((s.size * 16) / 9) / 4) * 4; + const height = Math.round((width * 9) / 16 / 2) * 2; + const n = s.views.length; + return new s.latkit.Shot([width, height]).panels(s.views.map((_, i) => [i / n, 0, 1 / n, 1])); +} + +const image = (): Phase => ({ + name: 'image', + order: { time: 1 }, + run: (s) => s.once(() => shot(s).image(s.views)), +}); + +const png = (): Phase => ({ + name: 'png', + order: { time: 1 }, + run: async (s) => { + const picture = await deadline(shot(s).image(s.views), 60_000, 'a picture'); + return s.once(() => picture.encode('png')); + }, +}); + +/** Thirty frames of video, turning; held, nothing moves, so frames after the first cost nothing. */ +const video = (moving: boolean): Phase => ({ + name: moving ? 'video' : 'held', + order: moving ? { time: 1 } : {}, + run: (s) => { + const start = s.view.camera as MapCamera; + return s.once(async () => { + const video = shot(s).video(s.gpu, 30, new WritableStream()); + for (let i = 0; i < 30; i++) { + if (moving) + for (const v of s.views) v.camera = { ...start, bearing: start.bearing + 2 * i }; + await video.frame(s.views); + } + await video.finish(); + }); + }, +}); + +// Scenarios. + +export const scenarios: Record = { + start: { + about: 'a first visit: latkit, the GPU, and pipelines made without a shader cache', + unit: 'rows', + sizes: [1e4], + cold: true, + build: (n) => ({ scene: dots('plane'), data: { d: make.scatter(n) } }), + phases: [], + }, + points: { + about: 'vertices on a plane, colored through a colormap', + unit: 'rows', + sizes: DECADES, + build: (n) => ({ scene: dots('plane'), data: { d: make.scatter(n) } }), + phases: [ + pan(), + zoom(), + restyle(dots('plane', 'magma')), + one('d', 'Point', 'v'), + every('d', 'Point', 'v'), + ...pick(), + hover(), + select('d', 'Point'), + ], + }, + grid: { + about: 'a lattice grid on the globe: buses, and the geodesic lines between them', + unit: 'buses', + sizes: DECADES, + build: (n) => ({ + scene: grid({ earth: { projection: 'globe' } }), + data: { g: make.lattice(n) }, + }), + phases: [pan(), zoom(), one('g', 'Bus', 'load'), ...pick(), hover()], + }, + labels: { + about: 'every vertex labeled: placement, collisions, and the texts set', + unit: 'rows', + // From ten thousand rows on, more labels show than a frame sets texts for, so a frame's CPU + // holds at the text budget however many rows are labeled. + sizes: [1e4, 1e5, 1e6], + build: (n) => ({ + scene: dots('plane', 'viridis', 'name'), + data: { d: make.scatter(n, 1, true) }, + }), + phases: [pan(), zoom()], + }, + lanes: { + about: 'edges by the thousand between the same sixteen pairs of vertices', + unit: 'edges', + sizes: [1e2, 1e3, 1e4, 1e5], + build: (n) => ({ + scene: { + space: 'plane', + ease: 0, + marks: [ + { edges: { of: ['d', 'Link'], ends: ['from', 'to'] } }, + { vertices: { of: ['d', 'Point'], position: ['x', 'y'] } }, + ], + }, + data: { d: make.lanes(n) }, + }), + phases: [pan(), ...pick()], + }, + areas: { + about: 'polygons of 33 points on the mercator map, triangulated in jobs', + unit: 'polygons', + sizes: [1e2, 1e3, 1e4, 3e4], + build: (n) => ({ + scene: { + space: 'mercator', + ease: 0, + marks: [ + { + areas: { + of: ['m', 'Region'], + geometry: 'rings', + color: field('v').colormap('viridis').domain(0, 1), + }, + }, + ], + }, + data: { m: make.polygons(n) }, + }), + phases: [pan(), zoom(), one('m', 'Region', 'v'), ...pick()], + }, + tiles: { + about: 'vector tiles fetched as the camera asks for them, from a local server', + unit: 'squares a tile', + sizes: [16, 256, 4096], + fetches: true, + build: (n) => ({ + scene: { + space: 'mercator', + ease: 0, + marks: [{ areas: { of: ['t', 'cells'], color: '#4a7fb5' } }], + }, + data: {}, + tiles: { t: `${location.origin}/tiles/${n}/{z}/{x}/{y}.mvt` }, + camera: { center: [0, 20], zoom: 3, pitch: 0, bearing: 0 }, + }), + phases: [pan(), zoom()], + }, + diagram: { + about: 'blocks with ports in trees of 64, laid out in layers, wires routed around them', + unit: 'blocks', + sizes: [1e2, 1e3, 1e4], + build: (n) => ({ scene: sheet, data: { d: make.blocks(n) } }), + phases: [pan(), edit(), arrange()], + }, + traces: { + about: 'a plot of traces 1,024 frames long, fed a frame every animation frame', + unit: 'traces', + sizes: [10, 1e2, 1e3, 1e4], + build: (n) => ({ scene: plot, data: { t: make.traces(n, HISTORY) } }), + // Every trace narrowed uploads its finer level. + phases: [stream(), scrub(), narrow({ time: 0, bytes: 1 }), hover()], + }, + history: { + about: 'one trace with a long history: levels of detail', + unit: 'frames', + sizes: [1e3, 1e4, 1e5, 1e6], + build: (n) => ({ scene: plot, data: { t: make.traces(1, n) } }), + phases: [scrub(), narrow()], + }, + transition: { + about: 'every row moving to a new place at once, easing over a second', + unit: 'rows', + sizes: [1e3, 1e4, 1e5, 1e6], + build: (n) => ({ scene: { ...dots('plane'), ease: 1 }, data: { d: make.scatter(n) } }), + phases: [move()], + }, + views: { + about: 'views of one GPU drawing one dataset: pages shared, not copied', + unit: 'views', + sizes: [1, 2, 4, 8], + views: (n) => n, + // Room for eight views' own rows, which the views' shares of a budget hold together, so the + // bytes that grow would be pages copied. + budget: { bytes: 1024 * 2 ** 20, uploadPerFrame: 32 * 2 ** 20 }, + load: { time: 1, bytes: 0 }, + build: () => ({ scene: grid('plane'), data: { g: make.lattice(1e5) } }), + phases: [pan({ time: 1, bytes: 0 })], + }, + budget: { + about: 'a 16 MiB budget: what draws fits, through tiles, and nothing fails', + unit: 'buses', + sizes: [1e5, 1e6, 2e6], + budget: { bytes: 16 * 2 ** 20, uploadPerFrame: 4 * 2 ** 20 }, + load: { time: 1 }, + build: (n) => ({ scene: grid('plane'), data: { g: make.lattice(n) } }), + phases: [pan(), zoom()], + }, + shots: { + about: 'pictures and video of two views of a 100,000-bus grid', + unit: 'pixels', + sizes: [960 * 540, 1920 * 1080, 3840 * 2160], + views: () => 2, + build: () => ({ scene: grid('plane'), data: { g: make.lattice(1e5) } }), + phases: [image(), png(), video(true), video(false)], + }, +}; diff --git a/benchmark/page/stage.ts b/benchmark/page/stage.ts new file mode 100644 index 00000000..6b9f264e --- /dev/null +++ b/benchmark/page/stage.ts @@ -0,0 +1,301 @@ +/** + * Where a run happens, and the one way anything in it is measured. The stage steps every frame + * itself, a sixtieth of a second apart on its own clock, and each frame waits for the GPU (its work + * done, its readbacks landed, the pipelines asked for compiled), never for time: a run draws the same + * frames however fast the device is, so what it counts repeats. A phase is an action, timed from when + * it starts until everything settled: no view wants a frame, every view is complete, and no tile is + * loading; work under way that wakes no frame is waited for as it lands. A steady phase acts before + * each of a number of frames, so each act shows in its own frame, and its CPU and GPU time are per + * frame. A lost device fails the phase at once, and every wait races a deadline. + */ +import { + Patch, + type Camera, + type Data, + type Gpu, + type Latkit, + type Scene, + type View, + type Work, +} from 'latkit'; + +/** Writes a dataset's rows into a patch, from arrays made beforehand. */ +export type Write = (patch: Patch) => Patch; + +/** What a phase cost. */ +export interface Cost { + /** Milliseconds from the action until everything settled. */ + ms: number; + /** Frames drawn meanwhile. */ + frames: number; + /** Milliseconds every view together took to record a frame on the CPU: median, 95th percentile. */ + cpu: number; + cpu95: number; + /** Milliseconds a frame took on the GPU, median; 0 where the device cannot measure. */ + gpu: number; + /** What the GPU did until everything settled. */ + work: Work; + /** Bytes of data pages on the GPU afterwards. */ + resident: number; + /** Whether it acted every frame, so `cpu` is its time; else `ms` is. */ + steady: boolean; +} + +/** Milliseconds between stepped frames: a display's sixtieth of a second. */ +const FRAME = 1000 / 60; +/** The most frames a phase may take to settle: ten seconds of a display's frames. */ +const MOST = 600; +/** Frames stepped once everything settled, in which nothing should draw. */ +const IDLE = 10; +/** Milliseconds a frame, or work landing, may take: past it, something hangs. */ +const DEADLINE = 30_000; +/** The longest a phase may take; the runner grows sizes within it. */ +export const LIMIT = 10_000; +/** Frames a steady phase takes before it measures. */ +export const WARM = 10; + +const quantile = (xs: number[], q: number) => + xs.length ? [...xs].sort((a, b) => a - b)[Math.floor(q * (xs.length - 1))]! : 0; + +/** `work`, or an error naming `what` once `ms` pass. */ +export function deadline(work: Promise, ms: number, what: string): Promise { + let timer: ReturnType | undefined; + const late = new Promise((_, reject) => { + timer = setTimeout(() => reject(new Error(`${what} took over ${ms} ms`)), ms); + }); + return Promise.race([work, late]).finally(() => clearTimeout(timer)); +} + +/** What the frames a phase stepped drew. */ +interface Drawn { + frames: number; + cpu: number[]; + gpu: number[]; +} + +export class Stage { + readonly latkit: Latkit; + readonly gpu: Gpu; + readonly canvases: readonly HTMLCanvasElement[]; + /** The scenario's size. */ + readonly size: number; + readonly views: View[] = []; + /** Errors the views told: a mark that does not fit its data fails the run. */ + readonly errors: string[] = []; + scene!: Scene; + readonly #data = new Map(); + /** The stepped frames' clock, milliseconds. */ + #now = performance.now(); + + constructor(latkit: Latkit, gpu: Gpu, canvases: readonly HTMLCanvasElement[], size: number) { + [this.latkit, this.gpu, this.canvases, this.size] = [latkit, gpu, canvases, size]; + } + + get view(): View { + return this.views[0]!; + } + + /** The middle of the first view, in its CSS pixels. */ + get middle(): [number, number] { + const canvas = this.canvases[0]!; + return [canvas.clientWidth / 2, canvas.clientHeight / 2]; + } + + /** Units across `px` CSS pixels at the middle of the first view. */ + across(px: number): number { + const [x, y] = this.middle; + const [a, b] = [this.view.ground([x, y]), this.view.ground([x + px, y])]; + return a && b ? Math.hypot(b[0] - a[0], b[1] - a[1]) : 1; + } + + /** Rows of `table` in dataset `name`. */ + count(name: string, table: string): number { + return this.#data.get(name)!.ids(table).length; + } + + /** The axis coordinates dataset `name` recorded. */ + span(name: string): [number, number] { + return this.#data.get(name)!.span ?? [0, 1]; + } + + /** Takes each dataset in: latkit's work alone, the arrays made beforehand. */ + ingest(data: Record): Promise { + const { Data } = this.latkit; + return this.once(() => { + for (const [name, write] of Object.entries(data)) + this.#data.set(name, new Data(name).apply(write(new Patch()))); + }); + } + + /** Opens a view on each canvas and draws `scene`: from nothing to everything drawn. */ + load(scene: Scene, tiles: Record = {}, camera?: Camera): Promise { + this.scene = scene; + return this.once(() => { + for (const canvas of this.canvases) { + const view = this.gpu.view(scene); + this.gpu.canvas(canvas).show([view]); + view.on('error', (error) => + this.errors.push(`${error.path ?? ''} ${error.message}`.trim()), + ); + for (const data of this.#data.values()) view.setData(data); + for (const [name, url] of Object.entries(tiles)) view.setTiles(name, url); + if (camera) view.camera = camera; + else view.fit('all'); + this.views.push(view); + } + }); + } + + /** Shows `scene` in every view. */ + show(scene: Scene): void { + this.scene = scene; + for (const view of this.views) view.show(scene); + } + + /** Writes a patch into dataset `name` and gives every view the next version. */ + apply(name: string, write: Write): void { + const data = this.#data.get(name)!.apply(write(new Patch())); + for (const view of this.views) view.setData(data); + } + + /** Sends a pointer event at `point`, CSS pixels in the first view, as a person's would arrive. */ + pointer(type: string, [x, y]: [number, number], buttons = 0): void { + const canvas = this.canvases[0]!; + const box = canvas.getBoundingClientRect(); + canvas.dispatchEvent( + new PointerEvent(type, { + clientX: box.left + x, + clientY: box.top + y, + buttons, + pointerId: 1, + pointerType: 'mouse', + isPrimary: true, + bubbles: true, + }), + ); + } + + /** Acts once, and measures until everything settled. */ + once(act: () => unknown): Promise { + return this.#phase(false, async (drawn) => { + await this.until(Promise.resolve().then(act), drawn, true); + await this.#settle(drawn, true); + }); + } + + /** `answer`, stepping frames until it comes: what waits on a frame, as a pick or a hover told + * does, gets one, and what waits on work landing is waited for. */ + async until( + answer: Promise, + drawn: Drawn = { frames: 0, cpu: [], gpu: [] }, + measuring = false, + ): Promise { + let came = false; + const coming = answer.then( + () => (came = true), + () => (came = true), + ); + const late = performance.now() + DEADLINE; + for (let frames = 0; !came;) { + if (this.gpu.lost) throw new Error('the GPU device was lost'); + if (frames > MOST || performance.now() > late) + throw new Error( + `no answer after ${frames} frames: waiting on ${this.#waiting() || 'nothing'}`, + ); + if (this.views.some((v) => v.wantsFrame)) { + await this.#frame(drawn, measuring); + frames++; + } else await Promise.race([coming, this.gpu.landed().catch(() => {})]); + } + return answer; + } + + /** Calls `act(i)` before each of `count` frames, and measures until everything settled. */ + steady(count: number, act: (i: number) => void): Promise { + return this.#phase(true, async (drawn) => { + for (let i = 0; i < count; i++) { + act(i); + await this.#frame(drawn, i >= WARM); + } + await this.#settle(drawn, false); + }); + } + + /** Frames drawn over `IDLE` frames stepped once everything settled: none, for views that sleep. */ + async idle(): Promise { + const drawn: Drawn = { frames: 0, cpu: [], gpu: [] }; + await this.#settle(drawn, false); + const before = drawn.frames; + for (let i = 0; i < IDLE; i++) await this.#frame(drawn, false); + return drawn.frames - before; + } + + async #phase(steady: boolean, drive: (drawn: Drawn) => Promise): Promise { + const before = this.gpu.work; + const drawn: Drawn = { frames: 0, cpu: [], gpu: [] }; + const begun = performance.now(); + await drive(drawn); + const ms = performance.now() - begun; + const after = this.gpu.work; + const work = Object.fromEntries( + Object.entries(after).map(([k, v]) => [k, v - before[k as keyof Work]]), + ) as unknown as Work; + return { + ms, + frames: drawn.frames, + cpu: quantile(drawn.cpu, 0.5), + cpu95: quantile(drawn.cpu, 0.95), + gpu: quantile(drawn.gpu, 0.5), + work, + resident: this.views[0]?.stats.resident ?? 0, + steady, + }; + } + + /** Steps one frame, once the GPU is done with the last, and counts what the views drew in it: + * their CPU and GPU time, when `measuring`. */ + async #frame(drawn: Drawn, measuring: boolean): Promise { + if (this.gpu.lost) throw new Error('the GPU device was lost'); + const before = this.views.map((v) => v.stats.frames); + this.gpu.step((this.#now += FRAME)); + await deadline(this.gpu.done(), DEADLINE, 'a frame'); + let [drew, cpu, gpu] = [false, 0, 0]; + this.views.forEach((view, i) => { + const stats = view.stats; + if (stats.frames === before[i]) return; + [drew, cpu, gpu] = [true, cpu + stats.cpuMs, gpu + stats.gpuMs]; + }); + if (!drew) return; + drawn.frames++; + if (measuring) { + drawn.cpu.push(cpu); + if (gpu) drawn.gpu.push(gpu); + } + } + + /** Steps frames until everything settled: no view wants a frame, every view is complete, and no + * tile is loading. Work under way that wakes no frame, as a layout or a fetch, is waited for as it + * lands. What a once phase draws is `measuring`. */ + async #settle(drawn: Drawn, measuring: boolean): Promise { + await deadline(this.gpu.done(), DEADLINE, 'the GPU'); + for (let frames = 0; frames < MOST;) { + if (this.gpu.lost) throw new Error('the GPU device was lost'); + if (this.views.some((v) => v.wantsFrame)) { + await this.#frame(drawn, measuring); + frames++; + continue; + } + if (this.views.every((v) => !v.stats.waiting.length && !v.stats.tilesLoading)) return; + await deadline(this.gpu.landed(), DEADLINE, `${this.#waiting()} landing`); + } + throw new Error( + `still drawing after ${MOST} frames: waiting on ${this.#waiting() || 'nothing'}`, + ); + } + + /** What the views wait on. */ + #waiting(): string { + const tiles = this.views.some((v) => v.stats.tilesLoading) ? ['tiles'] : []; + return [...new Set(this.views.flatMap((v) => v.stats.waiting)), ...tiles].join(', '); + } +} diff --git a/benchmark/pipeline.bench.ts b/benchmark/pipeline.bench.ts deleted file mode 100644 index 9dadce94..00000000 --- a/benchmark/pipeline.bench.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { afterAll, describe } from 'vitest'; -import { createComposition } from '@latkit/gpu'; -import { appendData, type Data } from '@latkit/model'; -import { createMonitor } from '@latkit/monitor'; -import { createNetwork } from '@latkit/network'; -import { - connected, - counters, - draw, - frames, - gpu, - grid, - sizes, - split, - suite, - voltages, -} from './harness.ts'; - -/** - * The integrated path for one published frame: a producer publishes it over a WebSocket, the host - * appends it to its data, and a network and a monitor composed on one canvas draw it. - */ -describe.each(sizes)('pipeline %i buses', async (buses) => { - const device = await gpu(), - frame = voltages(buses, 0); - let data = grid(buses), - blocks = 0; - const { model, close } = await connected(function* (_fields, context) { - const parts = split(frame, Math.floor((context.maxBlockBytes - 4096) / 4)); - blocks = parts.length; - for (let f = frames; !context.signal.aborted; f++) - for (const part of parts) yield { ...part, firstFrame: f, coordinates: Float64Array.of(f) }; - }); - const stream = model.monitor!([{ from: 'Bus', select: ['voltage'] }]); - const network = createNetwork(device, { - source: data, - vertices: { - Bus: { - x: 'position', - y: { field: 'position', component: 1 }, - color: { field: 'voltage', domain: [0.95, 1.05] }, - }, - }, - edges: { Branch: { ends: ['from', 'to'] } }, - }); - // A fixed window with room for the run, as a model that declares its domain gives. - const monitor = createMonitor(device, { - source: data, - traces: { - voltage: { from: 'Bus', y: 'voltage', rows: { kind: 'range', offset: 0, count: 100 } }, - }, - camera: { x: [0, frames * 4] }, - }); - const composition = createComposition(device, { - views: [ - { view: network, region: [0, 0, 1, 0.6] }, - { view: monitor, region: [0, 0.6, 1, 0.4] }, - ], - }); - await draw(device, composition, frames - 1, 'complete'); - afterAll(async () => { - composition.destroy(); - network.destroy(); - monitor.destroy(); - await close(); - }); - const measure = suite(`pipeline ${buses} buses`, buses, () => counters(device)); - measure('publication to frame', async () => { - const batches: Data.SampleBatch[] = []; - do batches.push(...((await stream.next()).value as Data.SampleBatch[])); - while (batches.length < blocks); - data = appendData(data, batches); - network.set({ source: data }); - monitor.set({ source: data }); - await draw(device, composition, batches[0].firstFrame); - }); -}); diff --git a/benchmark/report.ts b/benchmark/report.ts new file mode 100644 index 00000000..f8fe7101 --- /dev/null +++ b/benchmark/report.ts @@ -0,0 +1,50 @@ +/** + * The characterization: per scenario, a row per phase and measure, a column per size, and the + * exponent each grows by. + */ +import type { Listed } from './page/main.ts'; +import type { Summary, Verdict } from './judge.ts'; + +const ms = (v: number) => v.toFixed(v < 10 ? 2 : v < 100 ? 1 : 0); +const bytes = (v: number) => + v < 2 ** 20 ? `${(v / 1024).toFixed(0)}K` : `${(v / 2 ** 20).toFixed(v < 10 * 2 ** 20 ? 1 : 0)}M`; +const count = (n: number) => + n >= 1e6 ? `${+(n / 1e6).toFixed(1)}M` : n >= 1e3 ? `${+(n / 1e3).toFixed(1)}k` : `${n}`; + +/** Each scenario's phases at each size, and the exponent each grows by. */ +export function report(list: Listed[], { summaries, exponents }: Verdict): string { + const out: string[] = []; + for (const scenario of list) { + const bySize = summaries[scenario.name]; + if (!bySize) continue; + const sizes = Object.keys(bySize) + .map(Number) + .sort((a, b) => a - b); + out.push('', `${scenario.name}: ${scenario.about}`); + out.push( + `${scenario.unit.padEnd(26)}${sizes.map((n) => count(n).padStart(9)).join('')} grows`, + ); + for (const phase of Object.keys(bySize[sizes[0]!]!)) { + const e = exponents[scenario.name]?.[phase]; + const steady = bySize[sizes[0]!]![phase]!.steady; + type Row = [string, (s: Summary) => number, (v: number) => string, number | undefined]; + const rows: Row[] = [ + [steady ? 'cpu ms/frame' : 'ms', (s) => s.time, ms, e?.time], + ['gpu ms/frame', (s) => s.gpu, ms, e?.gpu], + ['uploaded', (s) => s.work.uploaded, bytes, e?.uploaded], + ...(phase === 'load' + ? [['resident', (s: Summary) => s.work.resident, bytes, e?.resident] as Row] + : []), + ]; + for (const [label, read, format, grows] of rows) { + const cells = sizes.map((n) => bySize[n]?.[phase]); + const time = label.includes('ms') && !label.startsWith('gpu'); + if (!time && cells.every((s) => !s || !read(s))) continue; + const values = cells.map((s) => (s ? format(read(s)) : '-').padStart(9)).join(''); + const exponent = grows === undefined ? '' : `n^${grows.toFixed(2)}`; + out.push(` ${`${phase} ${label}`.padEnd(24)}${values} ${exponent}`); + } + } + } + return out.join('\n'); +} diff --git a/benchmark/run.ts b/benchmark/run.ts new file mode 100644 index 00000000..9dd7a05a --- /dev/null +++ b/benchmark/run.ts @@ -0,0 +1,252 @@ +/** + * The benchmark: each scenario up its sizes, each run in a fresh page, judged and reported. + * + * cargo xtask bench [--quick] [--only a,b] [--repeats n] [--update] [--software] + * + * --quick runs each scenario once at its smallest size, a smoke test of every phase and the work + * gate in under a minute on a GPU; how phases grow, and their times, take the full sweep. --update lays this run's + * baselines over the committed ones, keeping what it did not run; --software draws with SwiftShader + * on the CPU, as Linux always does: its work counts the same, its times only report, and no shader + * can hang the GPU. + * + * A scenario climbs its sizes while the last one's phases, grown as their orders say, fit a phase's + * limit. A failure ends its scenario; a lost device, or a page that stopped answering, ends the + * sweep, since the next scenario would meet a resetting driver, and resets in a row are what wedge + * one. Every wait races a deadline. + */ +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { parseArgs } from 'node:util'; +import { createServer } from 'vite'; +import { STEP, deadline, launch, type Chrome } from '../npm/examples/gate/browser.ts'; +import { judge, times, work, type TimeBaseline, type WorkBaseline } from './judge.ts'; +import { report } from './report.ts'; +import type { Listed, Run } from './page/main.ts'; +import { LIMIT } from './page/stage.ts'; + +const { values: flags } = parseArgs({ + options: { + quick: { type: 'boolean' }, + only: { type: 'string' }, + repeats: { type: 'string' }, + update: { type: 'boolean' }, + software: { type: 'boolean' }, + }, +}); +const repeats = flags.quick ? 1 : Number(flags.repeats ?? 3); +if (!Number.isInteger(repeats) || repeats < 1) + throw new Error(`--repeats takes a count, not ${flags.repeats}`); +const only = flags.only?.split(','); +const software = flags.software || process.platform === 'linux'; +const here = path.dirname(fileURLToPath(import.meta.url)); +const baselines = path.join(here, 'baselines'); +const results = path.resolve(here, '../target/bench'); +/** Timestamps, for what a frame costs the GPU. The page steps its frames, each as soon as the GPU + * finished the last, so the display's pace never enters a run. */ +const FLAGS = ['--enable-webgpu-developer-features']; +/** The same page on every machine, so what it counts compares, and small enough that SwiftShader + * draws a frame quickly. */ +const PAGE = { viewport: { width: 800, height: 500 }, deviceScaleFactor: 2 }; +/** Milliseconds a page may say nothing: each phase says when it starts, then acts and settles + * within its limits. */ +const QUIET = 2 * LIMIT + 20_000; + +/** A failed run, and whether the sweep stops there. */ +class Failure extends Error { + readonly fatal: boolean; + constructor(message: string, fatal: boolean) { + super(message); + this.fatal = fatal; + } +} + +/** `work`, or an error once the page has said nothing for `QUIET` ms since `heard()`. */ +function watched(work: Promise, heard: () => number, what: string): Promise { + let timer: NodeJS.Timeout | undefined; + const silent = new Promise((_, reject) => { + timer = setInterval(() => { + if (performance.now() - heard() > QUIET) + reject(new Error(`${what} said nothing for ${QUIET} ms`)); + }, 1_000); + }); + return Promise.race([work, silent]).finally(() => clearInterval(timer)); +} + +/** The first phase of `last` that, grown to `size` as its order says (linearly where it says + * nothing), would pass a phase's limit. */ +function outgrown(last: Run, size: number, orders: Listed['orders']): string | undefined { + const grown = ([phase, cost]: [string, Run['phases'][string]]) => + cost.ms * (size / last.size) ** (orders[phase]?.time ?? 1); + return Object.entries(last.phases).find((entry) => grown(entry) > LIMIT)?.[0]; +} + +const server = await createServer({ + root: here, + configFile: path.join(here, 'vite.config.ts'), + logLevel: 'error', + server: { port: 5230, strictPort: false }, +}); +await deadline(server.listen(), STEP, 'serve the bench'); +const address = server.resolvedUrls?.local[0]; +if (!address) throw new Error('the bench has no address'); +const url = address; +const runs: Run[] = []; +const failures: string[] = []; +const notes: string[] = []; +let list: Listed[] = []; + +/** One run of `scenario` at `size`: in a fresh page of `warm`, or, for a cold scenario, of a fresh + * Chrome without a shader cache. */ +async function measure(warm: Chrome, scenario: Listed, size: number): Promise { + if (!scenario.cold) return visit(warm, scenario, size); + const cold = await launch([...FLAGS, '--disable-gpu-shader-disk-cache'], software); + try { + return await visit(cold, scenario, size); + } finally { + await cold.close(); + } +} + +/** One run in a fresh page of `chrome`; a failure is fatal when the device was lost, or the page + * cannot say. */ +async function visit(chrome: Chrome, scenario: Listed, size: number): Promise { + const page = await deadline(chrome.browser.newPage(PAGE), STEP, 'open a page'); + const errors: string[] = []; + let [phase, heard] = ['opening', performance.now()]; + page.on('pageerror', (e) => errors.push(e.message)); + page.on('console', (m) => { + if (m.type() === 'error') errors.push(m.text()); + if (m.type() === 'debug' && m.text().startsWith('phase ')) + [phase, heard] = [m.text().slice(6), performance.now()]; + }); + try { + await deadline(page.goto(url), STEP, 'open the bench page'); + const run = await watched( + page.evaluate(([name, n]) => window.bench.run(name, n), [scenario.name, size] as const), + () => heard, + `${scenario.name} at ${size}`, + ); + run.errors.push(...errors); + return run; + } catch (error) { + const lost = await deadline( + page.evaluate(() => window.bench.lost()), + 5_000, + 'ask after the device', + ).catch(() => true); + throw new Failure( + `${scenario.name} at ${size}, ${phase}: ${String(error).split('\n')[0]}`, + lost, + ); + } finally { + await deadline(page.close(), 5_000, 'close the page').catch(() => {}); + } +} + +const warm = await launch(FLAGS, software); +try { + const page = await deadline(warm.browser.newPage(PAGE), STEP, 'open a page'); + await deadline(page.goto(url), STEP, 'open the bench page'); + // Making a device is where a wedged driver hangs, so the sweep starts only once one is made. + await deadline( + page.evaluate(() => window.bench.ready()), + 15_000, + 'make a GPU device: a wedged driver hangs here, and needs a reset before benchmarking', + ); + list = await deadline( + page.evaluate(() => window.bench.list()), + STEP, + 'list the scenarios', + ); + await deadline(page.close(), 5_000, 'close the page').catch(() => {}); + const unknown = only?.filter((name) => !list.some((s) => s.name === name)) ?? []; + if (unknown.length) + throw new Error( + `no scenario ${unknown.join(', ')}; there are ${list.map((s) => s.name).join(', ')}`, + ); + for (const scenario of list.filter((s) => !only || only.includes(s.name))) { + const sizes = flags.quick ? scenario.sizes.slice(0, 1) : scenario.sizes; + try { + // A first run fills the shader cache, so the measured ones load warm; `start` alone loads cold. + if (!scenario.cold && !flags.quick) await measure(warm, scenario, sizes[0]!); + let last: Run | undefined; + for (const size of sizes) { + const phase = last && outgrown(last, size, scenario.orders); + if (last && phase) { + const ms = last.phases[phase]!.ms.toFixed(0); + notes.push( + `${scenario.name} stops before ${size}: its ${phase} took ${ms} ms at ${last.size}`, + ); + break; + } + for (let r = 0; r < repeats; r++) { + const run = await measure(warm, scenario, size); + console.log( + ` ${scenario.name} at ${size}: loaded in ${run.phases.load?.ms.toFixed(0)} ms` + + (run.errors.length ? `, ${run.errors.length} errors` : ''), + ); + runs.push((last = run)); + } + } + } catch (error) { + const failure = error instanceof Failure ? error : new Failure(String(error), true); + failures.push(failure.message.slice(0, 400)); + console.log(` ${failure.message.slice(0, 300)}`); + if (failure.fatal) { + failures.push( + 'the GPU lost its device or stopped answering, so the sweep stops: reset the driver before running again', + ); + break; + } + } + } +} finally { + await warm.close(); + await server.close(); +} + +const read = (file: string): T | undefined => + fs.existsSync(file) ? (JSON.parse(fs.readFileSync(file, 'utf8')) as T) : undefined; +const write = (file: string, value: unknown) => + fs.writeFileSync(file, `${JSON.stringify(value, null, 1)}\n`); +const machines = [...new Set(runs.map((r) => r.machine))]; +if (machines.length > 1) + failures.push( + `runs drew on different GPUs, so their times cannot compare: ${machines.join('; ')}`, + ); +if (!runs.length) failures.push('nothing ran'); +const machine = machines[0] ?? 'unknown'; +const slug = machine + .toLowerCase() + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-|-$/g, ''); +const workFile = path.join(baselines, 'work.json'); +const timesFile = path.join(baselines, `${slug}.json`); +// A quick run, once each without a warm-up, holds no times to the baselines its warm repeats took. +const verdict = judge(runs, list, { + work: read(workFile), + times: flags.quick ? undefined : read(timesFile), +}); +console.log(`\n${machine}`); +console.log(report(list, verdict)); +if (runs.length) { + fs.mkdirSync(results, { recursive: true }); + write(path.join(results, `${Date.now()}.json`), { machine, runs }); +} +// Baselines come only from runs that all completed without errors; what they measured, slower or +// faster, is what --update accepts. +if (flags.update) { + if (failures.length || runs.some((r) => r.errors.length)) { + failures.push('baselines not written: a run failed or reported errors'); + } else { + fs.mkdirSync(baselines, { recursive: true }); + write(workFile, work(verdict, read(workFile))); + write(timesFile, times(verdict, machine, read(timesFile))); + } +} +console.log(''); +for (const note of [...notes, ...verdict.notes]) console.log(`note ${note}`); +const failed = [...failures, ...verdict.failures]; +for (const failure of failed) console.error(`FAIL ${failure}`); +process.exit(failed.length ? 1 : 0); diff --git a/benchmark/text.bench.ts b/benchmark/text.bench.ts deleted file mode 100644 index 4b8be38b..00000000 --- a/benchmark/text.bench.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { describe } from 'vitest'; -import { kit } from '@latkit/gpu'; -import { counters, draw, gpu, suite } from './harness.ts'; - -describe('gpu text 1000 labels', async () => { - const device = await gpu(); - const runs = Array.from({ length: 1000 }, (_, i) => ({ - text: 'Bus ' + i, - size: 12, - position: [0, i * 16] as const, - })); - const text: kit.Renderer = { - capture: () => ({ - prepare: async (frame) => { - await frame.text({ runs }); - return { encode() {}, submitted() {}, discard() {} }; - }, - release() {}, - }), - destroy() {}, - }; - const measure = suite('gpu text 1000 labels', 1000, () => counters(device), 8); - measure('cold text', () => { - device.trim(); - return draw(device, text); - }); - measure('resident text', () => draw(device, text)); -}); diff --git a/benchmark/tiles.ts b/benchmark/tiles.ts new file mode 100644 index 00000000..eeb52baa --- /dev/null +++ b/benchmark/tiles.ts @@ -0,0 +1,74 @@ +/** + * Vector tiles made on request, so the tiles scenario fetches over HTTP as a map does, the same + * bytes every run and nothing from the network: `/tiles////.mvt`, one layer + * `cells` of that many squares in a grid over the tile. + */ +import type { Plugin } from 'vite'; + +export function tiles(): Plugin { + return { + name: 'bench-tiles', + configureServer(server) { + server.middlewares.use((req, res, next) => { + const match = /^\/tiles\/(\d+)\/\d+\/\d+\/\d+\.mvt$/.exec(req.url ?? ''); + if (!match) return next(); + res.setHeader('content-type', 'application/vnd.mapbox-vector-tile'); + res.end(tile(Number(match[1]))); + }); + }, + }; +} + +const varint = (n: number): number[] => { + const out: number[] = []; + for (; n > 127; n = Math.floor(n / 128)) out.push((n % 128) | 128); + return [...out, n]; +}; +const zigzag = (n: number) => (n << 1) ^ (n >> 31); +const key = (field: number, wire: number) => varint((field << 3) | wire); +const bytes = (field: number, payload: number[]) => [ + ...key(field, 2), + ...varint(payload.length), + ...payload, +]; + +/** A tile of `squares` squares, clockwise exterior rings in the tile's 4096 units. */ +function tile(squares: number): Uint8Array { + const side = Math.ceil(Math.sqrt(squares)); + const step = Math.floor(4096 / side); + const size = Math.floor(step * 0.8); + const features = Array.from({ length: squares }, (_, i) => { + const [x, y] = [(i % side) * step, Math.floor(i / side) * step]; + // MoveTo one point, LineTo three, ClosePath. + const path = [ + 9, + zigzag(x), + zigzag(y), + 26, + zigzag(size), + 0, + 0, + zigzag(size), + zigzag(-size), + 0, + 15, + ]; + return bytes(2, [ + ...key(1, 0), + ...varint(i + 1), + ...key(3, 0), + 3, + ...bytes(4, path.flatMap(varint)), + ]); + }); + const name = [...new TextEncoder().encode('cells')]; + const layer = [ + ...key(15, 0), + 2, + ...bytes(1, name), + ...features.flat(), + ...key(5, 0), + ...varint(4096), + ]; + return new Uint8Array(bytes(3, layer)); +} diff --git a/benchmark/tsconfig.json b/benchmark/tsconfig.json index 0be86ddb..97bf6c7e 100644 --- a/benchmark/tsconfig.json +++ b/benchmark/tsconfig.json @@ -1,10 +1,17 @@ { - "extends": "../tsconfig.base.json", "compilerOptions": { - "lib": ["ES2022", "DOM", "DOM.Iterable"], - "types": ["@webgpu/types", "node"], + "target": "ES2024", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "strict": true, + "noUncheckedIndexedAccess": true, + "erasableSyntaxOnly": true, "allowImportingTsExtensions": true, - "noEmit": true + "verbatimModuleSyntax": true, + "skipLibCheck": true, + "noEmit": true, + "types": ["node"], + "lib": ["ES2024", "DOM", "DOM.Iterable", "ESNext.Disposable"] }, - "include": ["*.ts"] + "include": ["*.ts", "page"] } diff --git a/benchmark/vite.config.ts b/benchmark/vite.config.ts new file mode 100644 index 00000000..b76f2314 --- /dev/null +++ b/benchmark/vite.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'vite'; +import { tiles } from './tiles.ts'; + +export default defineConfig({ + plugins: [tiles()], + // The package loads its wasm next to itself; prebundling would move it. + optimizeDeps: { exclude: ['latkit'] }, + build: { target: 'es2022' }, +}); diff --git a/benchmark/vitest.config.ts b/benchmark/vitest.config.ts deleted file mode 100644 index bb434559..00000000 --- a/benchmark/vitest.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { defineProject } from 'vitest/config'; - -export default defineProject({ - test: { - name: 'benchmark', - include: ['*.test.ts'], - benchmark: { include: ['*.bench.ts'] }, - }, -}); diff --git a/benchmark/work.json b/benchmark/work.json deleted file mode 100644 index 66ed9a1f..00000000 --- a/benchmark/work.json +++ /dev/null @@ -1,6038 +0,0 @@ -{ - "diagram 100 blocks > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 544, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 3843 - }, - "diagram 100 blocks > drag end": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 544, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 3843 - }, - "diagram 100 blocks > drag frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 544, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 3843 - }, - "diagram 100 blocks > layout": { - "queries": 0, - "queryHits": 3, - "uploads": 5, - "uploadedBytes": 36880, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 3843 - }, - "diagram 100 blocks > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "diagram 100 blocks > playback frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 544, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 3843 - }, - "diagram 100 blocks > restyle": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 544, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 3843 - }, - "diagram 100 blocks > select": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 548, - "uploadHits": 2, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 3843 - }, - "diagram 100 blocks > styled playback": { - "queries": 2, - "queryHits": 0, - "uploads": 4, - "uploadedBytes": 1196, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 3843 - }, - "diagram 1000 blocks > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 544, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 40851 - }, - "diagram 1000 blocks > drag end": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 544, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 40851 - }, - "diagram 1000 blocks > drag frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 544, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 40851 - }, - "diagram 1000 blocks > layout": { - "queries": 0, - "queryHits": 3, - "uploads": 5, - "uploadedBytes": 386064, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 1.25, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 40851 - }, - "diagram 1000 blocks > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "diagram 1000 blocks > playback frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 544, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 40851 - }, - "diagram 1000 blocks > restyle": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 544, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 40851 - }, - "diagram 1000 blocks > select": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 548, - "uploadHits": 2, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 40851 - }, - "diagram 1000 blocks > styled playback": { - "queries": 2, - "queryHits": 0, - "uploads": 4, - "uploadedBytes": 4796, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 40851 - }, - "diagram 1000 blocks in rings > layout": { - "queries": 0, - "queryHits": 3, - "uploads": 5, - "uploadedBytes": 232560, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 1.25, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 24003 - }, - "diagram 1000 blocks in rings > move": { - "queries": 0, - "queryHits": 0, - "uploads": 4, - "uploadedBytes": 128587.5, - "uploadHits": 2, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8250, - "rasterized": 0, - "vertices": 23984.25 - }, - "diagram 10000 blocks > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 1632, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 416403 - }, - "diagram 10000 blocks > drag end": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 1632, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 416403 - }, - "diagram 10000 blocks > drag frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 1632, - "uploadHits": 8, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 416403 - }, - "diagram 10000 blocks > layout": { - "queries": 0, - "queryHits": 3, - "uploads": 9, - "uploadedBytes": 3928848, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 1.125, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 416403 - }, - "diagram 10000 blocks > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "diagram 10000 blocks > playback frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 1632, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 416403 - }, - "diagram 10000 blocks > restyle": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 1632, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 416403 - }, - "diagram 10000 blocks > select": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 1636, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 416403 - }, - "diagram 10000 blocks > styled playback": { - "queries": 2, - "queryHits": 0, - "uploads": 4, - "uploadedBytes": 41884, - "uploadHits": 9, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 416403 - }, - "diagram 10000 blocks in rings > layout": { - "queries": 0, - "queryHits": 3, - "uploads": 7, - "uploadedBytes": 2321104, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 1.25, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 240003 - }, - "diagram 10000 blocks in rings > move": { - "queries": 0, - "queryHits": 0, - "uploads": 5.125, - "uploadedBytes": 1281102, - "uploadHits": 2.5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 82500, - "rasterized": 0, - "vertices": 239984.25 - }, - "diagram 40000 blocks > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 5168, - "uploadHits": 20, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1672803 - }, - "diagram 40000 blocks > drag end": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 5168, - "uploadHits": 20, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1672803 - }, - "diagram 40000 blocks > drag frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 5168, - "uploadHits": 21, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1672803 - }, - "diagram 40000 blocks > layout": { - "queries": 0, - "queryHits": 3, - "uploads": 22, - "uploadedBytes": 15779584, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 1.667, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1672803 - }, - "diagram 40000 blocks > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "diagram 40000 blocks > playback frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 5168, - "uploadHits": 20, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1672803 - }, - "diagram 40000 blocks > restyle": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 5168, - "uploadHits": 20, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1672803 - }, - "diagram 40000 blocks > select": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 5172, - "uploadHits": 19, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1672803 - }, - "diagram 40000 blocks > styled playback": { - "queries": 2, - "queryHits": 0, - "uploads": 4, - "uploadedBytes": 165420, - "uploadHits": 22, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1672803 - }, - "gpu 10000 buses > cold upload": { - "queries": 1, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 120156, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 80000, - "rasterized": 0, - "vertices": 0 - }, - "gpu 10000 buses > field scale": { - "queries": 0, - "queryHits": 1, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "gpu 10000 buses > playback frame": { - "queries": 1, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 40092, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0.042, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "gpu 10000 buses > resident redraw": { - "queries": 0, - "queryHits": 2, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 1, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "gpu 100000 buses > cold upload": { - "queries": 3, - "queryHits": 0, - "uploads": 9, - "uploadedBytes": 1200468, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 2, - "submissions": 1, - "evictions": 0, - "stagedBytes": 800000, - "rasterized": 0, - "vertices": 0 - }, - "gpu 100000 buses > field scale": { - "queries": 0, - "queryHits": 1, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "gpu 100000 buses > playback frame": { - "queries": 2, - "queryHits": 0, - "uploads": 4, - "uploadedBytes": 400184, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0.167, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "gpu 100000 buses > resident redraw": { - "queries": 0, - "queryHits": 6, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "gpu 1000000 buses > cold upload": { - "queries": 29, - "queryHits": 0, - "uploads": 87, - "uploadedBytes": 12004524, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8000000, - "rasterized": 0, - "vertices": 0 - }, - "gpu 1000000 buses > field scale": { - "queries": 0, - "queryHits": 1, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "gpu 1000000 buses > playback frame": { - "queries": 13, - "queryHits": 0, - "uploads": 26, - "uploadedBytes": 4001196, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0.167, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "gpu 1000000 buses > resident redraw": { - "queries": 0, - "queryHits": 58, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 29, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "gpu text 1000 labels > cold text": { - "queries": 0, - "queryHits": 0, - "uploads": 15, - "uploadedBytes": 449024, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 2, - "submissions": 1, - "evictions": 0, - "stagedBytes": 5307568, - "rasterized": 14, - "vertices": 0 - }, - "gpu text 1000 labels > resident text": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 1, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "model 10000 buses > appendData frame": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 10000 buses > createData": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 10000 buses > read envelope": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 10000 buses > read rows": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 10000 buses > read samples": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 10000 buses > reader extent": { - "queries": 0, - "queryHits": 1, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 10000 buses > reader fields, cached": { - "queries": 0, - "queryHits": 1, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 10000 buses > reader fields, cold": { - "queries": 1, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 10000 buses > selectBatches": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 100000 buses > appendData frame": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 100000 buses > createData": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 100000 buses > read envelope": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 100000 buses > read rows": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 100000 buses > read samples": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 100000 buses > reader extent": { - "queries": 0, - "queryHits": 1, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 100000 buses > reader fields, cached": { - "queries": 0, - "queryHits": 2, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 100000 buses > reader fields, cold": { - "queries": 2, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 100000 buses > selectBatches": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 1000000 buses > appendData frame": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 1000000 buses > createData": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 1000000 buses > read envelope": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 1000000 buses > read rows": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 1000000 buses > read samples": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 1000000 buses > reader extent": { - "queries": 0, - "queryHits": 1, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 1000000 buses > reader fields, cached": { - "queries": 0, - "queryHits": 13, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 1000000 buses > reader fields, cold": { - "queries": 13, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "model 1000000 buses > selectBatches": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0 - }, - "monitor 100 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor 100 rows > change window": { - "queries": 0, - "queryHits": 1, - "uploads": 6, - "uploadedBytes": 1600, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 27618 - }, - "monitor 100 rows > first frame": { - "queries": 0, - "queryHits": 1, - "uploads": 6, - "uploadedBytes": 6380, - "uploadHits": 2, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 19197 - }, - "monitor 100 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor 100 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor 100 rows > stream frame": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 1364, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 1197 - }, - "monitor 100 rows > stream frame, growing extremes": { - "queries": 1.083, - "queryHits": 0, - "uploads": 5.5, - "uploadedBytes": 3643, - "uploadHits": 2.75, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 23.333, - "rasterized": 0, - "vertices": 3581 - }, - "monitor 1000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor 1000 rows > change window": { - "queries": 0, - "queryHits": 1, - "uploads": 7, - "uploadedBytes": 2012, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 270762 - }, - "monitor 1000 rows > first frame": { - "queries": 0, - "queryHits": 1, - "uploads": 6, - "uploadedBytes": 6380, - "uploadHits": 2, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186597 - }, - "monitor 1000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor 1000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor 1000 rows > stream frame": { - "queries": 1.083, - "queryHits": 0, - "uploads": 5.667, - "uploadedBytes": 23635.333, - "uploadHits": 2.75, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1768.667, - "rasterized": 0, - "vertices": 25205 - }, - "monitor 1000 rows > stream frame, growing extremes": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 8564, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 6747 - }, - "monitor 10000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor 10000 rows > change window": { - "queries": 0, - "queryHits": 1, - "uploads": 21, - "uploadedBytes": 7780, - "uploadHits": 20, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 2700618 - }, - "monitor 10000 rows > first frame": { - "queries": 0, - "queryHits": 1, - "uploads": 16, - "uploadedBytes": 10500, - "uploadHits": 13, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor 10000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor 10000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor 10000 rows > stream frame": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 80564, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 60597 - }, - "monitor 10000 rows > stream frame, growing extremes": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 80564, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 60747 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > add trace": { - "queries": 0, - "queryHits": 8.5, - "uploads": 6.5, - "uploadedBytes": 2638, - "uploadHits": 32, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 95097 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > animated shade": { - "queries": 0, - "queryHits": 8, - "uploads": 6, - "uploadedBytes": 2720, - "uploadHits": 31, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 93609 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 528, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 609 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > change window": { - "queries": 0, - "queryHits": 16, - "uploads": 13, - "uploadedBytes": 5380, - "uploadHits": 41, - "gpuCopiedBytes": 0, - "allocations": 5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186630 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > first frame": { - "queries": 16, - "queryHits": 0, - "uploads": 37, - "uploadedBytes": 143184, - "uploadHits": 16, - "gpuCopiedBytes": 0, - "allocations": 5.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1024, - "rasterized": 0, - "vertices": 186609 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > palette": { - "queries": 0, - "queryHits": 8, - "uploads": 7, - "uploadedBytes": 3264, - "uploadHits": 30, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 93609 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 528, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 609 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 528, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 609 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > recolor": { - "queries": 0, - "queryHits": 8, - "uploads": 6, - "uploadedBytes": 2432, - "uploadHits": 31, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 93609 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > select": { - "queries": 0, - "queryHits": 1, - "uploads": 2.5, - "uploadedBytes": 814, - "uploadHits": 13.5, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 703.5 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > stream frame": { - "queries": 8.667, - "queryHits": 8.667, - "uploads": 28.25, - "uploadedBytes": 26106.667, - "uploadHits": 28.083, - "gpuCopiedBytes": 0, - "allocations": 0.417, - "submissions": 1, - "evictions": 0, - "stagedBytes": 165.333, - "rasterized": 0, - "vertices": 25217 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > stream frame, growing extremes": { - "queries": 8, - "queryHits": 8, - "uploads": 26, - "uploadedBytes": 90016, - "uploadHits": 27, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 680, - "rasterized": 0, - "vertices": 122331 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > stream frame, new look": { - "queries": 8.333, - "queryHits": 8.333, - "uploads": 27.25, - "uploadedBytes": 97180, - "uploadHits": 27.083, - "gpuCopiedBytes": 0, - "allocations": 0.417, - "submissions": 1, - "evictions": 0, - "stagedBytes": 730.667, - "rasterized": 0, - "vertices": 131467 - }, - "monitor eight traces colored by another field, eight looks 1000 rows > trace width": { - "queries": 0, - "queryHits": 16, - "uploads": 11, - "uploadedBytes": 5168, - "uploadHits": 42, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186609 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > add trace": { - "queries": 0, - "queryHits": 8.5, - "uploads": 14.5, - "uploadedBytes": 6446, - "uploadHits": 48, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 932097 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > animated shade": { - "queries": 0, - "queryHits": 8, - "uploads": 14, - "uploadedBytes": 6528, - "uploadHits": 47, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 930609 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 528, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 609 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > change window": { - "queries": 0, - "queryHits": 16, - "uploads": 29, - "uploadedBytes": 12996, - "uploadHits": 73, - "gpuCopiedBytes": 0, - "allocations": 5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860630 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > first frame": { - "queries": 16, - "queryHits": 0, - "uploads": 85, - "uploadedBytes": 1338800, - "uploadHits": 16, - "gpuCopiedBytes": 0, - "allocations": 5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1281024, - "rasterized": 0, - "vertices": 1860609 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > palette": { - "queries": 0, - "queryHits": 8, - "uploads": 15, - "uploadedBytes": 7072, - "uploadHits": 46, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 930609 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 528, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 609 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 528, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 609 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > recolor": { - "queries": 0, - "queryHits": 8, - "uploads": 14, - "uploadedBytes": 6240, - "uploadHits": 47, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 930609 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > select": { - "queries": 0, - "queryHits": 1, - "uploads": 2.5, - "uploadedBytes": 814, - "uploadHits": 13.5, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 703.5 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > stream frame": { - "queries": 8, - "queryHits": 8, - "uploads": 26, - "uploadedBytes": 84400, - "uploadHits": 27, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 64, - "rasterized": 0, - "vertices": 60609 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > stream frame, growing extremes": { - "queries": 8, - "queryHits": 8, - "uploads": 61, - "uploadedBytes": 879934.667, - "uploadHits": 23, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 810680, - "rasterized": 0, - "vertices": 1215831 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > stream frame, new look": { - "queries": 8, - "queryHits": 8, - "uploads": 61, - "uploadedBytes": 879934.667, - "uploadHits": 23, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 810680, - "rasterized": 0, - "vertices": 1215609 - }, - "monitor eight traces colored by another field, eight looks 10000 rows > trace width": { - "queries": 0, - "queryHits": 16, - "uploads": 27, - "uploadedBytes": 12784, - "uploadHits": 74, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860609 - }, - "monitor four fixed traces 1000 rows > add trace": { - "queries": 0, - "queryHits": 4.5, - "uploads": 6.5, - "uploadedBytes": 1998, - "uploadHits": 12, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 188085 - }, - "monitor four fixed traces 1000 rows > animated shade": { - "queries": 0, - "queryHits": 4, - "uploads": 6, - "uploadedBytes": 2080, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186597 - }, - "monitor four fixed traces 1000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four fixed traces 1000 rows > change window": { - "queries": 0, - "queryHits": 4, - "uploads": 9, - "uploadedBytes": 2836, - "uploadHits": 9, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186618 - }, - "monitor four fixed traces 1000 rows > first frame": { - "queries": 4, - "queryHits": 0, - "uploads": 17, - "uploadedBytes": 136128, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 1.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 512, - "rasterized": 0, - "vertices": 186597 - }, - "monitor four fixed traces 1000 rows > palette": { - "queries": 0, - "queryHits": 4, - "uploads": 7, - "uploadedBytes": 2624, - "uploadHits": 10, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186597 - }, - "monitor four fixed traces 1000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor four fixed traces 1000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four fixed traces 1000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four fixed traces 1000 rows > recolor": { - "queries": 0, - "queryHits": 4, - "uploads": 6, - "uploadedBytes": 1792, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186597 - }, - "monitor four fixed traces 1000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 691.5 - }, - "monitor four fixed traces 1000 rows > stream frame": { - "queries": 4.333, - "queryHits": 0, - "uploads": 15.25, - "uploadedBytes": 23300, - "uploadHits": 2.75, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 82.667, - "rasterized": 0, - "vertices": 25205 - }, - "monitor four fixed traces 1000 rows > stream frame, growing extremes": { - "queries": 4, - "queryHits": 0, - "uploads": 14, - "uploadedBytes": 9824, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 32, - "rasterized": 0, - "vertices": 6819 - }, - "monitor four fixed traces 1000 rows > stream frame, new look": { - "queries": 4, - "queryHits": 0, - "uploads": 14.25, - "uploadedBytes": 165061.333, - "uploadHits": 2.75, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 648, - "rasterized": 0, - "vertices": 237705 - }, - "monitor four fixed traces 1000 rows > trace width": { - "queries": 0, - "queryHits": 4, - "uploads": 7, - "uploadedBytes": 2624, - "uploadHits": 10, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186597 - }, - "monitor four fixed traces 10000 rows > add trace": { - "queries": 0, - "queryHits": 4.5, - "uploads": 14.5, - "uploadedBytes": 5294, - "uploadHits": 20, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1862085 - }, - "monitor four fixed traces 10000 rows > animated shade": { - "queries": 0, - "queryHits": 4, - "uploads": 14, - "uploadedBytes": 5376, - "uploadHits": 19, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor four fixed traces 10000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four fixed traces 10000 rows > change window": { - "queries": 0, - "queryHits": 4, - "uploads": 17, - "uploadedBytes": 6132, - "uploadHits": 17, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860618 - }, - "monitor four fixed traces 10000 rows > first frame": { - "queries": 4, - "queryHits": 0, - "uploads": 33, - "uploadedBytes": 1291424, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1280512, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor four fixed traces 10000 rows > palette": { - "queries": 0, - "queryHits": 4, - "uploads": 15, - "uploadedBytes": 5920, - "uploadHits": 18, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor four fixed traces 10000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor four fixed traces 10000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four fixed traces 10000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four fixed traces 10000 rows > recolor": { - "queries": 0, - "queryHits": 4, - "uploads": 14, - "uploadedBytes": 5088, - "uploadHits": 19, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor four fixed traces 10000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 691.5 - }, - "monitor four fixed traces 10000 rows > stream frame": { - "queries": 4, - "queryHits": 0, - "uploads": 14, - "uploadedBytes": 81824, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 32, - "rasterized": 0, - "vertices": 60597 - }, - "monitor four fixed traces 10000 rows > stream frame, growing extremes": { - "queries": 4, - "queryHits": 0, - "uploads": 14, - "uploadedBytes": 81824, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 32, - "rasterized": 0, - "vertices": 60819 - }, - "monitor four fixed traces 10000 rows > stream frame, new look": { - "queries": 4, - "queryHits": 0, - "uploads": 34.667, - "uploadedBytes": 1626697.333, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1620648, - "rasterized": 0, - "vertices": 2370597 - }, - "monitor four fixed traces 10000 rows > trace width": { - "queries": 0, - "queryHits": 4, - "uploads": 15, - "uploadedBytes": 5920, - "uploadHits": 18, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor four mapped traces, four looks 1000 rows > add trace": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 686, - "uploadHits": 12, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 2095.5 - }, - "monitor four mapped traces, four looks 1000 rows > animated shade": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 720, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 606 - }, - "monitor four mapped traces, four looks 1000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 606 - }, - "monitor four mapped traces, four looks 1000 rows > change window": { - "queries": 0, - "queryHits": 4, - "uploads": 9, - "uploadedBytes": 3124, - "uploadHits": 17, - "gpuCopiedBytes": 0, - "allocations": 4, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186627 - }, - "monitor four mapped traces, four looks 1000 rows > first frame": { - "queries": 4, - "queryHits": 0, - "uploads": 17, - "uploadedBytes": 136416, - "uploadHits": 8, - "gpuCopiedBytes": 0, - "allocations": 4.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 512, - "rasterized": 0, - "vertices": 186606 - }, - "monitor four mapped traces, four looks 1000 rows > palette": { - "queries": 0, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 1264, - "uploadHits": 10, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 606 - }, - "monitor four mapped traces, four looks 1000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor four mapped traces, four looks 1000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 606 - }, - "monitor four mapped traces, four looks 1000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 606 - }, - "monitor four mapped traces, four looks 1000 rows > recolor": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 606 - }, - "monitor four mapped traces, four looks 1000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 686, - "uploadHits": 13, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 700.5 - }, - "monitor four mapped traces, four looks 1000 rows > stream frame": { - "queries": 4.333, - "queryHits": 0, - "uploads": 15.25, - "uploadedBytes": 23588, - "uploadHits": 10.75, - "gpuCopiedBytes": 0, - "allocations": 0.333, - "submissions": 1, - "evictions": 0, - "stagedBytes": 82.667, - "rasterized": 0, - "vertices": 25214 - }, - "monitor four mapped traces, four looks 1000 rows > stream frame, growing extremes": { - "queries": 4, - "queryHits": 0, - "uploads": 14, - "uploadedBytes": 10112, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 32, - "rasterized": 0, - "vertices": 6828 - }, - "monitor four mapped traces, four looks 1000 rows > stream frame, new look": { - "queries": 4.333, - "queryHits": 0, - "uploads": 15.25, - "uploadedBytes": 23588, - "uploadHits": 10.75, - "gpuCopiedBytes": 0, - "allocations": 0.417, - "submissions": 1, - "evictions": 0, - "stagedBytes": 82.667, - "rasterized": 0, - "vertices": 25214 - }, - "monitor four mapped traces, four looks 1000 rows > trace width": { - "queries": 0, - "queryHits": 4, - "uploads": 7, - "uploadedBytes": 2912, - "uploadHits": 18, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186606 - }, - "monitor four mapped traces, four looks 10000 rows > add trace": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 686, - "uploadHits": 12, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 2095.5 - }, - "monitor four mapped traces, four looks 10000 rows > animated shade": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 720, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 606 - }, - "monitor four mapped traces, four looks 10000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 606 - }, - "monitor four mapped traces, four looks 10000 rows > change window": { - "queries": 0, - "queryHits": 4, - "uploads": 17, - "uploadedBytes": 6420, - "uploadHits": 25, - "gpuCopiedBytes": 0, - "allocations": 4, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860627 - }, - "monitor four mapped traces, four looks 10000 rows > first frame": { - "queries": 4, - "queryHits": 0, - "uploads": 33, - "uploadedBytes": 1291712, - "uploadHits": 8, - "gpuCopiedBytes": 0, - "allocations": 4, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1280512, - "rasterized": 0, - "vertices": 1860606 - }, - "monitor four mapped traces, four looks 10000 rows > palette": { - "queries": 0, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 1264, - "uploadHits": 10, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 606 - }, - "monitor four mapped traces, four looks 10000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor four mapped traces, four looks 10000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 606 - }, - "monitor four mapped traces, four looks 10000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 606 - }, - "monitor four mapped traces, four looks 10000 rows > recolor": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 606 - }, - "monitor four mapped traces, four looks 10000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 686, - "uploadHits": 13, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 700.5 - }, - "monitor four mapped traces, four looks 10000 rows > stream frame": { - "queries": 4, - "queryHits": 0, - "uploads": 14, - "uploadedBytes": 82112, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 32, - "rasterized": 0, - "vertices": 60606 - }, - "monitor four mapped traces, four looks 10000 rows > stream frame, growing extremes": { - "queries": 4, - "queryHits": 0, - "uploads": 14, - "uploadedBytes": 82112, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 32, - "rasterized": 0, - "vertices": 60828 - }, - "monitor four mapped traces, four looks 10000 rows > stream frame, new look": { - "queries": 4, - "queryHits": 0, - "uploads": 14, - "uploadedBytes": 82112, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 32, - "rasterized": 0, - "vertices": 60606 - }, - "monitor four mapped traces, four looks 10000 rows > trace width": { - "queries": 0, - "queryHits": 4, - "uploads": 15, - "uploadedBytes": 6208, - "uploadHits": 26, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860606 - }, - "monitor four mapped traces, one look 1000 rows > add trace": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 2086.5 - }, - "monitor four mapped traces, one look 1000 rows > animated shade": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four mapped traces, one look 1000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four mapped traces, one look 1000 rows > change window": { - "queries": 0, - "queryHits": 4, - "uploads": 9, - "uploadedBytes": 2836, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186618 - }, - "monitor four mapped traces, one look 1000 rows > first frame": { - "queries": 4, - "queryHits": 0, - "uploads": 17, - "uploadedBytes": 136128, - "uploadHits": 2, - "gpuCopiedBytes": 0, - "allocations": 1.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 512, - "rasterized": 0, - "vertices": 186597 - }, - "monitor four mapped traces, one look 1000 rows > palette": { - "queries": 0, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 976, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four mapped traces, one look 1000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor four mapped traces, one look 1000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four mapped traces, one look 1000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four mapped traces, one look 1000 rows > recolor": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four mapped traces, one look 1000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 691.5 - }, - "monitor four mapped traces, one look 1000 rows > stream frame": { - "queries": 4.333, - "queryHits": 0, - "uploads": 15.25, - "uploadedBytes": 23300, - "uploadHits": 4.75, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 82.667, - "rasterized": 0, - "vertices": 25205 - }, - "monitor four mapped traces, one look 1000 rows > stream frame, growing extremes": { - "queries": 4, - "queryHits": 0, - "uploads": 14, - "uploadedBytes": 9824, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 32, - "rasterized": 0, - "vertices": 6819 - }, - "monitor four mapped traces, one look 1000 rows > stream frame, new look": { - "queries": 4.333, - "queryHits": 0, - "uploads": 15.25, - "uploadedBytes": 23300, - "uploadHits": 4.75, - "gpuCopiedBytes": 0, - "allocations": 0.167, - "submissions": 1, - "evictions": 0, - "stagedBytes": 82.667, - "rasterized": 0, - "vertices": 25205 - }, - "monitor four mapped traces, one look 1000 rows > trace width": { - "queries": 0, - "queryHits": 4, - "uploads": 7, - "uploadedBytes": 2624, - "uploadHits": 12, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186597 - }, - "monitor four mapped traces, one look 10000 rows > add trace": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 2086.5 - }, - "monitor four mapped traces, one look 10000 rows > animated shade": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four mapped traces, one look 10000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four mapped traces, one look 10000 rows > change window": { - "queries": 0, - "queryHits": 4, - "uploads": 17, - "uploadedBytes": 6132, - "uploadHits": 19, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860618 - }, - "monitor four mapped traces, one look 10000 rows > first frame": { - "queries": 4, - "queryHits": 0, - "uploads": 33, - "uploadedBytes": 1291424, - "uploadHits": 2, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1280512, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor four mapped traces, one look 10000 rows > palette": { - "queries": 0, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 976, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four mapped traces, one look 10000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor four mapped traces, one look 10000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four mapped traces, one look 10000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four mapped traces, one look 10000 rows > recolor": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor four mapped traces, one look 10000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 691.5 - }, - "monitor four mapped traces, one look 10000 rows > stream frame": { - "queries": 4, - "queryHits": 0, - "uploads": 14, - "uploadedBytes": 81824, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 32, - "rasterized": 0, - "vertices": 60597 - }, - "monitor four mapped traces, one look 10000 rows > stream frame, growing extremes": { - "queries": 4, - "queryHits": 0, - "uploads": 14, - "uploadedBytes": 81824, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 32, - "rasterized": 0, - "vertices": 60819 - }, - "monitor four mapped traces, one look 10000 rows > stream frame, new look": { - "queries": 4, - "queryHits": 0, - "uploads": 14, - "uploadedBytes": 81824, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 32, - "rasterized": 0, - "vertices": 60597 - }, - "monitor four mapped traces, one look 10000 rows > trace width": { - "queries": 0, - "queryHits": 4, - "uploads": 15, - "uploadedBytes": 5920, - "uploadHits": 20, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor one fixed trace 1000 rows > add trace": { - "queries": 0, - "queryHits": 1.5, - "uploads": 3.5, - "uploadedBytes": 762, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 188085 - }, - "monitor one fixed trace 1000 rows > animated shade": { - "queries": 0, - "queryHits": 1, - "uploads": 3, - "uploadedBytes": 844, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186597 - }, - "monitor one fixed trace 1000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one fixed trace 1000 rows > change window": { - "queries": 0, - "queryHits": 1, - "uploads": 6, - "uploadedBytes": 1600, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186618 - }, - "monitor one fixed trace 1000 rows > first frame": { - "queries": 1, - "queryHits": 0, - "uploads": 8, - "uploadedBytes": 134508, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 1.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 128, - "rasterized": 0, - "vertices": 186597 - }, - "monitor one fixed trace 1000 rows > palette": { - "queries": 0, - "queryHits": 1, - "uploads": 4, - "uploadedBytes": 1388, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186597 - }, - "monitor one fixed trace 1000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor one fixed trace 1000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one fixed trace 1000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one fixed trace 1000 rows > recolor": { - "queries": 0, - "queryHits": 1, - "uploads": 3, - "uploadedBytes": 556, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186597 - }, - "monitor one fixed trace 1000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 691.5 - }, - "monitor one fixed trace 1000 rows > stream frame": { - "queries": 1.083, - "queryHits": 0, - "uploads": 5.667, - "uploadedBytes": 23635.333, - "uploadHits": 2.75, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1768.667, - "rasterized": 0, - "vertices": 25205 - }, - "monitor one fixed trace 1000 rows > stream frame, growing extremes": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 8564, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 6819 - }, - "monitor one fixed trace 1000 rows > stream frame, new look": { - "queries": 1, - "queryHits": 0, - "uploads": 7.25, - "uploadedBytes": 193985.667, - "uploadHits": 2.75, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 31137.333, - "rasterized": 0, - "vertices": 237705 - }, - "monitor one fixed trace 1000 rows > trace width": { - "queries": 0, - "queryHits": 1, - "uploads": 4, - "uploadedBytes": 1388, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186597 - }, - "monitor one fixed trace 10000 rows > add trace": { - "queries": 0, - "queryHits": 1.5, - "uploads": 13.5, - "uploadedBytes": 4882, - "uploadHits": 17, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1862085 - }, - "monitor one fixed trace 10000 rows > animated shade": { - "queries": 0, - "queryHits": 1, - "uploads": 13, - "uploadedBytes": 4964, - "uploadHits": 16, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor one fixed trace 10000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one fixed trace 10000 rows > change window": { - "queries": 0, - "queryHits": 1, - "uploads": 16, - "uploadedBytes": 5720, - "uploadHits": 14, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860618 - }, - "monitor one fixed trace 10000 rows > first frame": { - "queries": 1, - "queryHits": 0, - "uploads": 28, - "uploadedBytes": 1290628, - "uploadHits": 1, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1280128, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor one fixed trace 10000 rows > palette": { - "queries": 0, - "queryHits": 1, - "uploads": 14, - "uploadedBytes": 5508, - "uploadHits": 15, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor one fixed trace 10000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor one fixed trace 10000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one fixed trace 10000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one fixed trace 10000 rows > recolor": { - "queries": 0, - "queryHits": 1, - "uploads": 13, - "uploadedBytes": 4676, - "uploadHits": 16, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor one fixed trace 10000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 691.5 - }, - "monitor one fixed trace 10000 rows > stream frame": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 80564, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 60597 - }, - "monitor one fixed trace 10000 rows > stream frame, growing extremes": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 80564, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 60819 - }, - "monitor one fixed trace 10000 rows > stream frame, new look": { - "queries": 1, - "queryHits": 0, - "uploads": 30.5, - "uploadedBytes": 1628641, - "uploadHits": 4.417, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1587994.667, - "rasterized": 0, - "vertices": 2370597 - }, - "monitor one fixed trace 10000 rows > trace width": { - "queries": 0, - "queryHits": 1, - "uploads": 14, - "uploadedBytes": 5508, - "uploadHits": 15, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor one following trace 1000 rows > add trace": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 2086.5 - }, - "monitor one following trace 1000 rows > animated shade": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one following trace 1000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one following trace 1000 rows > change window": { - "queries": 0, - "queryHits": 1, - "uploads": 6, - "uploadedBytes": 1600, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186618 - }, - "monitor one following trace 1000 rows > first frame": { - "queries": 1, - "queryHits": 0, - "uploads": 8, - "uploadedBytes": 134508, - "uploadHits": 2, - "gpuCopiedBytes": 0, - "allocations": 1.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 128, - "rasterized": 0, - "vertices": 186597 - }, - "monitor one following trace 1000 rows > palette": { - "queries": 0, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 976, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one following trace 1000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor one following trace 1000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one following trace 1000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one following trace 1000 rows > recolor": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one following trace 1000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 691.5 - }, - "monitor one following trace 1000 rows > stream frame": { - "queries": 1.083, - "queryHits": 0, - "uploads": 5.667, - "uploadedBytes": 23635.333, - "uploadHits": 4.75, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1768.667, - "rasterized": 0, - "vertices": 25205 - }, - "monitor one following trace 1000 rows > stream frame, growing extremes": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 8564, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 6819 - }, - "monitor one following trace 1000 rows > stream frame, new look": { - "queries": 1.083, - "queryHits": 0, - "uploads": 5.667, - "uploadedBytes": 23635.333, - "uploadHits": 4.75, - "gpuCopiedBytes": 0, - "allocations": 0.167, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1768.667, - "rasterized": 0, - "vertices": 25205 - }, - "monitor one following trace 1000 rows > trace width": { - "queries": 0, - "queryHits": 1, - "uploads": 4, - "uploadedBytes": 1388, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186597 - }, - "monitor one following trace 10000 rows > add trace": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 2086.5 - }, - "monitor one following trace 10000 rows > animated shade": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one following trace 10000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one following trace 10000 rows > change window": { - "queries": 0, - "queryHits": 1, - "uploads": 16, - "uploadedBytes": 5720, - "uploadHits": 16, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860618 - }, - "monitor one following trace 10000 rows > first frame": { - "queries": 1, - "queryHits": 0, - "uploads": 28, - "uploadedBytes": 1290628, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1280128, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor one following trace 10000 rows > palette": { - "queries": 0, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 976, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one following trace 10000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor one following trace 10000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one following trace 10000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one following trace 10000 rows > recolor": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one following trace 10000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 691.5 - }, - "monitor one following trace 10000 rows > stream frame": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 80564, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 60597 - }, - "monitor one following trace 10000 rows > stream frame, growing extremes": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 80564, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 60819 - }, - "monitor one following trace 10000 rows > stream frame, new look": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 80564, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 60597 - }, - "monitor one following trace 10000 rows > trace width": { - "queries": 0, - "queryHits": 1, - "uploads": 14, - "uploadedBytes": 5508, - "uploadHits": 17, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor one mapped trace 1000 rows > add trace": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 2086.5 - }, - "monitor one mapped trace 1000 rows > animated shade": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace 1000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace 1000 rows > change window": { - "queries": 0, - "queryHits": 1, - "uploads": 6, - "uploadedBytes": 1600, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186618 - }, - "monitor one mapped trace 1000 rows > first frame": { - "queries": 1, - "queryHits": 0, - "uploads": 8, - "uploadedBytes": 134508, - "uploadHits": 2, - "gpuCopiedBytes": 0, - "allocations": 1.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 128, - "rasterized": 0, - "vertices": 186597 - }, - "monitor one mapped trace 1000 rows > palette": { - "queries": 0, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 976, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace 1000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor one mapped trace 1000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace 1000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace 1000 rows > recolor": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace 1000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 691.5 - }, - "monitor one mapped trace 1000 rows > stream frame": { - "queries": 1.083, - "queryHits": 0, - "uploads": 5.667, - "uploadedBytes": 23635.333, - "uploadHits": 4.75, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1768.667, - "rasterized": 0, - "vertices": 25205 - }, - "monitor one mapped trace 1000 rows > stream frame, growing extremes": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 8564, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 6819 - }, - "monitor one mapped trace 1000 rows > stream frame, new look": { - "queries": 1.083, - "queryHits": 0, - "uploads": 5.667, - "uploadedBytes": 23635.333, - "uploadHits": 4.75, - "gpuCopiedBytes": 0, - "allocations": 0.167, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1768.667, - "rasterized": 0, - "vertices": 25205 - }, - "monitor one mapped trace 1000 rows > trace width": { - "queries": 0, - "queryHits": 1, - "uploads": 4, - "uploadedBytes": 1388, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186597 - }, - "monitor one mapped trace 10000 rows > add trace": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 2086.5 - }, - "monitor one mapped trace 10000 rows > animated shade": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace 10000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace 10000 rows > change window": { - "queries": 0, - "queryHits": 1, - "uploads": 16, - "uploadedBytes": 5720, - "uploadHits": 16, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860618 - }, - "monitor one mapped trace 10000 rows > first frame": { - "queries": 1, - "queryHits": 0, - "uploads": 28, - "uploadedBytes": 1290628, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1280128, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor one mapped trace 10000 rows > palette": { - "queries": 0, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 976, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace 10000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor one mapped trace 10000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace 10000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace 10000 rows > recolor": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace 10000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 691.5 - }, - "monitor one mapped trace 10000 rows > stream frame": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 80564, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 60597 - }, - "monitor one mapped trace 10000 rows > stream frame, growing extremes": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 80564, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 60819 - }, - "monitor one mapped trace 10000 rows > stream frame, new look": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 80564, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 60597 - }, - "monitor one mapped trace 10000 rows > trace width": { - "queries": 0, - "queryHits": 1, - "uploads": 14, - "uploadedBytes": 5508, - "uploadHits": 17, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor one mapped trace, msaa 1000 rows > add trace": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 2086.5 - }, - "monitor one mapped trace, msaa 1000 rows > animated shade": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace, msaa 1000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace, msaa 1000 rows > change window": { - "queries": 0, - "queryHits": 1, - "uploads": 6, - "uploadedBytes": 1600, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 2, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186618 - }, - "monitor one mapped trace, msaa 1000 rows > first frame": { - "queries": 1, - "queryHits": 0, - "uploads": 8, - "uploadedBytes": 134508, - "uploadHits": 2, - "gpuCopiedBytes": 0, - "allocations": 2.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 128, - "rasterized": 0, - "vertices": 186597 - }, - "monitor one mapped trace, msaa 1000 rows > palette": { - "queries": 0, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 976, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace, msaa 1000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor one mapped trace, msaa 1000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace, msaa 1000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace, msaa 1000 rows > recolor": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace, msaa 1000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 691.5 - }, - "monitor one mapped trace, msaa 1000 rows > stream frame": { - "queries": 1.083, - "queryHits": 0, - "uploads": 5.667, - "uploadedBytes": 23635.333, - "uploadHits": 4.75, - "gpuCopiedBytes": 0, - "allocations": 0.167, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1768.667, - "rasterized": 0, - "vertices": 25205 - }, - "monitor one mapped trace, msaa 1000 rows > stream frame, growing extremes": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 8564, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 6819 - }, - "monitor one mapped trace, msaa 1000 rows > stream frame, new look": { - "queries": 1.083, - "queryHits": 0, - "uploads": 5.667, - "uploadedBytes": 23635.333, - "uploadHits": 4.75, - "gpuCopiedBytes": 0, - "allocations": 0.25, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1768.667, - "rasterized": 0, - "vertices": 25205 - }, - "monitor one mapped trace, msaa 1000 rows > trace width": { - "queries": 0, - "queryHits": 1, - "uploads": 4, - "uploadedBytes": 1388, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186597 - }, - "monitor one mapped trace, msaa 10000 rows > add trace": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 2086.5 - }, - "monitor one mapped trace, msaa 10000 rows > animated shade": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace, msaa 10000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace, msaa 10000 rows > change window": { - "queries": 0, - "queryHits": 1, - "uploads": 16, - "uploadedBytes": 5720, - "uploadHits": 16, - "gpuCopiedBytes": 0, - "allocations": 2, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860618 - }, - "monitor one mapped trace, msaa 10000 rows > first frame": { - "queries": 1, - "queryHits": 0, - "uploads": 28, - "uploadedBytes": 1290628, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 2, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1280128, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor one mapped trace, msaa 10000 rows > palette": { - "queries": 0, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 976, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace, msaa 10000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor one mapped trace, msaa 10000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace, msaa 10000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace, msaa 10000 rows > recolor": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one mapped trace, msaa 10000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 691.5 - }, - "monitor one mapped trace, msaa 10000 rows > stream frame": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 80564, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 60597 - }, - "monitor one mapped trace, msaa 10000 rows > stream frame, growing extremes": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 80564, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 60819 - }, - "monitor one mapped trace, msaa 10000 rows > stream frame, new look": { - "queries": 1, - "queryHits": 0, - "uploads": 5, - "uploadedBytes": 80564, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 60597 - }, - "monitor one mapped trace, msaa 10000 rows > trace width": { - "queries": 0, - "queryHits": 1, - "uploads": 14, - "uploadedBytes": 5508, - "uploadHits": 17, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor one trace colored by another field 1000 rows > add trace": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 2086.5 - }, - "monitor one trace colored by another field 1000 rows > animated shade": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one trace colored by another field 1000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one trace colored by another field 1000 rows > change window": { - "queries": 0, - "queryHits": 2, - "uploads": 7, - "uploadedBytes": 2140, - "uploadHits": 8, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186618 - }, - "monitor one trace colored by another field 1000 rows > first frame": { - "queries": 2, - "queryHits": 0, - "uploads": 12, - "uploadedBytes": 199560, - "uploadHits": 2, - "gpuCopiedBytes": 0, - "allocations": 1.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 62592, - "rasterized": 0, - "vertices": 186597 - }, - "monitor one trace colored by another field 1000 rows > palette": { - "queries": 0, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 976, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one trace colored by another field 1000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor one trace colored by another field 1000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one trace colored by another field 1000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one trace colored by another field 1000 rows > recolor": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one trace colored by another field 1000 rows > select": { - "queries": 0, - "queryHits": 1, - "uploads": 2.5, - "uploadedBytes": 430, - "uploadHits": 7.5, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 691.5 - }, - "monitor one trace colored by another field 1000 rows > stream frame": { - "queries": 1.083, - "queryHits": 1.083, - "uploads": 6.083, - "uploadedBytes": 22381, - "uploadHits": 5.75, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 12687.333, - "rasterized": 0, - "vertices": 25205 - }, - "monitor one trace colored by another field 1000 rows > stream frame, growing extremes": { - "queries": 1, - "queryHits": 1, - "uploads": 5, - "uploadedBytes": 8628, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 6819 - }, - "monitor one trace colored by another field 1000 rows > stream frame, new look": { - "queries": 1.083, - "queryHits": 1.083, - "uploads": 6.083, - "uploadedBytes": 22381, - "uploadHits": 5.75, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 12687.333, - "rasterized": 0, - "vertices": 25205 - }, - "monitor one trace colored by another field 1000 rows > trace width": { - "queries": 0, - "queryHits": 2, - "uploads": 5, - "uploadedBytes": 1928, - "uploadHits": 9, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186597 - }, - "monitor one trace colored by another field 10000 rows > add trace": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 398, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 2086.5 - }, - "monitor one trace colored by another field 10000 rows > animated shade": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 432, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one trace colored by another field 10000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one trace colored by another field 10000 rows > change window": { - "queries": 0, - "queryHits": 3, - "uploads": 25, - "uploadedBytes": 10708, - "uploadHits": 45, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860618 - }, - "monitor one trace colored by another field 10000 rows > first frame": { - "queries": 3, - "queryHits": 0, - "uploads": 66, - "uploadedBytes": 1335616, - "uploadHits": 3, - "gpuCopiedBytes": 0, - "allocations": 1, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1280128, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor one trace colored by another field 10000 rows > palette": { - "queries": 0, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 976, - "uploadHits": 4, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one trace colored by another field 10000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor one trace colored by another field 10000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one trace colored by another field 10000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one trace colored by another field 10000 rows > recolor": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 144, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 597 - }, - "monitor one trace colored by another field 10000 rows > select": { - "queries": 0, - "queryHits": 1, - "uploads": 2.5, - "uploadedBytes": 430, - "uploadHits": 7.5, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 691.5 - }, - "monitor one trace colored by another field 10000 rows > stream frame": { - "queries": 1, - "queryHits": 1, - "uploads": 7, - "uploadedBytes": 88336, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 14472, - "rasterized": 0, - "vertices": 60597 - }, - "monitor one trace colored by another field 10000 rows > stream frame, growing extremes": { - "queries": 1, - "queryHits": 1, - "uploads": 7, - "uploadedBytes": 88336, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 14472, - "rasterized": 0, - "vertices": 60819 - }, - "monitor one trace colored by another field 10000 rows > stream frame, new look": { - "queries": 1, - "queryHits": 1, - "uploads": 7, - "uploadedBytes": 88336, - "uploadHits": 7, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 14472, - "rasterized": 0, - "vertices": 60597 - }, - "monitor one trace colored by another field 10000 rows > trace width": { - "queries": 0, - "queryHits": 3, - "uploads": 23, - "uploadedBytes": 10496, - "uploadHits": 46, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860597 - }, - "monitor two fixed, two mapped traces 1000 rows > add trace": { - "queries": 0, - "queryHits": 2.5, - "uploads": 4.5, - "uploadedBytes": 1270, - "uploadHits": 10, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 95088 - }, - "monitor two fixed, two mapped traces 1000 rows > animated shade": { - "queries": 0, - "queryHits": 2, - "uploads": 4, - "uploadedBytes": 1352, - "uploadHits": 9, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 93600 - }, - "monitor two fixed, two mapped traces 1000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 240, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 600 - }, - "monitor two fixed, two mapped traces 1000 rows > change window": { - "queries": 0, - "queryHits": 4, - "uploads": 9, - "uploadedBytes": 2932, - "uploadHits": 11, - "gpuCopiedBytes": 0, - "allocations": 2, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186621 - }, - "monitor two fixed, two mapped traces 1000 rows > first frame": { - "queries": 4, - "queryHits": 0, - "uploads": 17, - "uploadedBytes": 136224, - "uploadHits": 2, - "gpuCopiedBytes": 0, - "allocations": 2.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 512, - "rasterized": 0, - "vertices": 186600 - }, - "monitor two fixed, two mapped traces 1000 rows > palette": { - "queries": 0, - "queryHits": 2, - "uploads": 5, - "uploadedBytes": 1896, - "uploadHits": 8, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 93600 - }, - "monitor two fixed, two mapped traces 1000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor two fixed, two mapped traces 1000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 240, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 600 - }, - "monitor two fixed, two mapped traces 1000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 240, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 600 - }, - "monitor two fixed, two mapped traces 1000 rows > recolor": { - "queries": 0, - "queryHits": 2, - "uploads": 4, - "uploadedBytes": 1064, - "uploadHits": 9, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 93600 - }, - "monitor two fixed, two mapped traces 1000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 494, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 694.5 - }, - "monitor two fixed, two mapped traces 1000 rows > stream frame": { - "queries": 4.333, - "queryHits": 0, - "uploads": 15.25, - "uploadedBytes": 23396, - "uploadHits": 4.75, - "gpuCopiedBytes": 0, - "allocations": 0.167, - "submissions": 1, - "evictions": 0, - "stagedBytes": 82.667, - "rasterized": 0, - "vertices": 25208 - }, - "monitor two fixed, two mapped traces 1000 rows > stream frame, growing extremes": { - "queries": 4, - "queryHits": 0, - "uploads": 14, - "uploadedBytes": 9920, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 32, - "rasterized": 0, - "vertices": 6822 - }, - "monitor two fixed, two mapped traces 1000 rows > stream frame, new look": { - "queries": 4.167, - "queryHits": 0, - "uploads": 14.75, - "uploadedBytes": 94276.667, - "uploadHits": 4.75, - "gpuCopiedBytes": 0, - "allocations": 0.25, - "submissions": 1, - "evictions": 0, - "stagedBytes": 365.333, - "rasterized": 0, - "vertices": 131458 - }, - "monitor two fixed, two mapped traces 1000 rows > trace width": { - "queries": 0, - "queryHits": 4, - "uploads": 7, - "uploadedBytes": 2720, - "uploadHits": 12, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 186600 - }, - "monitor two fixed, two mapped traces 10000 rows > add trace": { - "queries": 0, - "queryHits": 2.5, - "uploads": 8.5, - "uploadedBytes": 2918, - "uploadHits": 14, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 932088 - }, - "monitor two fixed, two mapped traces 10000 rows > animated shade": { - "queries": 0, - "queryHits": 2, - "uploads": 8, - "uploadedBytes": 3000, - "uploadHits": 13, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 930600 - }, - "monitor two fixed, two mapped traces 10000 rows > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 240, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 600 - }, - "monitor two fixed, two mapped traces 10000 rows > change window": { - "queries": 0, - "queryHits": 4, - "uploads": 17, - "uploadedBytes": 6228, - "uploadHits": 19, - "gpuCopiedBytes": 0, - "allocations": 2, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860621 - }, - "monitor two fixed, two mapped traces 10000 rows > first frame": { - "queries": 4, - "queryHits": 0, - "uploads": 33, - "uploadedBytes": 1291520, - "uploadHits": 2, - "gpuCopiedBytes": 0, - "allocations": 2, - "submissions": 1, - "evictions": 0, - "stagedBytes": 1280512, - "rasterized": 0, - "vertices": 1860600 - }, - "monitor two fixed, two mapped traces 10000 rows > palette": { - "queries": 0, - "queryHits": 2, - "uploads": 9, - "uploadedBytes": 3544, - "uploadHits": 12, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 930600 - }, - "monitor two fixed, two mapped traces 10000 rows > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "monitor two fixed, two mapped traces 10000 rows > pick during playback": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 240, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 600 - }, - "monitor two fixed, two mapped traces 10000 rows > playhead": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 240, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 600 - }, - "monitor two fixed, two mapped traces 10000 rows > recolor": { - "queries": 0, - "queryHits": 2, - "uploads": 8, - "uploadedBytes": 2712, - "uploadHits": 13, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 930600 - }, - "monitor two fixed, two mapped traces 10000 rows > select": { - "queries": 0, - "queryHits": 0.5, - "uploads": 2.5, - "uploadedBytes": 494, - "uploadHits": 6, - "gpuCopiedBytes": 0, - "allocations": 0.5, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 694.5 - }, - "monitor two fixed, two mapped traces 10000 rows > stream frame": { - "queries": 4, - "queryHits": 0, - "uploads": 14, - "uploadedBytes": 81920, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 32, - "rasterized": 0, - "vertices": 60600 - }, - "monitor two fixed, two mapped traces 10000 rows > stream frame, growing extremes": { - "queries": 4, - "queryHits": 0, - "uploads": 14, - "uploadedBytes": 81920, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 32, - "rasterized": 0, - "vertices": 60822 - }, - "monitor two fixed, two mapped traces 10000 rows > stream frame, new look": { - "queries": 4, - "queryHits": 0, - "uploads": 24.333, - "uploadedBytes": 854356.667, - "uploadHits": 5, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 810340, - "rasterized": 0, - "vertices": 1215600 - }, - "monitor two fixed, two mapped traces 10000 rows > trace width": { - "queries": 0, - "queryHits": 4, - "uploads": 15, - "uploadedBytes": 6016, - "uploadHits": 20, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1860600 - }, - "network 10000 buses > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 272, - "uploadHits": 14, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 178800 - }, - "network 10000 buses > camera move": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 272, - "uploadHits": 14, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 178800 - }, - "network 10000 buses > first frame": { - "queries": 0, - "queryHits": 6, - "uploads": 9, - "uploadedBytes": 325396, - "uploadHits": 9, - "gpuCopiedBytes": 0, - "allocations": 7.125, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 178800 - }, - "network 10000 buses > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "network 10000 buses > playback frame": { - "queries": 1, - "queryHits": 3, - "uploads": 3, - "uploadedBytes": 40492, - "uploadHits": 18, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 178800 - }, - "network 10000 buses > recolor": { - "queries": 0, - "queryHits": 4, - "uploads": 2, - "uploadedBytes": 528, - "uploadHits": 16, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 178800 - }, - "network 10000 buses > restyle": { - "queries": 0, - "queryHits": 3, - "uploads": 2, - "uploadedBytes": 528, - "uploadHits": 16, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 178800 - }, - "network 10000 buses > select": { - "queries": 0, - "queryHits": 0, - "uploads": 2, - "uploadedBytes": 2776, - "uploadHits": 13, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 178812 - }, - "network 10000 buses unpositioned > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 272, - "uploadHits": 14, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 178800 - }, - "network 10000 buses unpositioned > first frame": { - "queries": 0, - "queryHits": 4, - "uploads": 11, - "uploadedBytes": 405552, - "uploadHits": 9, - "gpuCopiedBytes": 0, - "allocations": 7.125, - "submissions": 1, - "evictions": 0, - "stagedBytes": 80000, - "rasterized": 0, - "vertices": 178800 - }, - "network 10000 buses unpositioned > restyle": { - "queries": 0, - "queryHits": 1, - "uploads": 2, - "uploadedBytes": 528, - "uploadHits": 16, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 178800 - }, - "network 100000 buses > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 272, - "uploadHits": 100, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1796202 - }, - "network 100000 buses > camera move": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 272, - "uploadHits": 100, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1796202 - }, - "network 100000 buses > first frame": { - "queries": 0, - "queryHits": 30, - "uploads": 61, - "uploadedBytes": 3271140, - "uploadHits": 60, - "gpuCopiedBytes": 0, - "allocations": 24.25, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1796202 - }, - "network 100000 buses > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "network 100000 buses > playback frame": { - "queries": 7, - "queryHits": 21, - "uploads": 15, - "uploadedBytes": 401812, - "uploadHits": 127, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1796202 - }, - "network 100000 buses > recolor": { - "queries": 0, - "queryHits": 28, - "uploads": 2, - "uploadedBytes": 2064, - "uploadHits": 119, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1796202 - }, - "network 100000 buses > restyle": { - "queries": 0, - "queryHits": 21, - "uploads": 2, - "uploadedBytes": 2064, - "uploadHits": 119, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1796202 - }, - "network 100000 buses > select": { - "queries": 0, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 360, - "uploadHits": 99, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1796214 - }, - "network 100000 buses unpositioned > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 272, - "uploadHits": 100, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1796202 - }, - "network 100000 buses unpositioned > first frame": { - "queries": 0, - "queryHits": 16, - "uploads": 75, - "uploadedBytes": 4072232, - "uploadHits": 60, - "gpuCopiedBytes": 0, - "allocations": 24.25, - "submissions": 1, - "evictions": 0, - "stagedBytes": 800000, - "rasterized": 0, - "vertices": 1796202 - }, - "network 100000 buses unpositioned > restyle": { - "queries": 0, - "queryHits": 7, - "uploads": 2, - "uploadedBytes": 2064, - "uploadHits": 119, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 1796202 - }, - "network 1000000 buses > cached frame": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 272, - "uploadHits": 921, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 17988000 - }, - "network 1000000 buses > camera move": { - "queries": 0, - "queryHits": 0, - "uploads": 1, - "uploadedBytes": 272, - "uploadHits": 921, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 17988000 - }, - "network 1000000 buses > first frame": { - "queries": 0, - "queryHits": 250, - "uploads": 554, - "uploadedBytes": 32774676, - "uploadHits": 552, - "gpuCopiedBytes": 0, - "allocations": 190.167, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 17988000 - }, - "network 1000000 buses > pick": { - "queries": 0, - "queryHits": 0, - "uploads": 0, - "uploadedBytes": 0, - "uploadHits": 0, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 0, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 0 - }, - "network 1000000 buses > playback frame": { - "queries": 62, - "queryHits": 186, - "uploads": 125, - "uploadedBytes": 4013912, - "uploadHits": 1167, - "gpuCopiedBytes": 0, - "allocations": 0.333, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 17988000 - }, - "network 1000000 buses > recolor": { - "queries": 0, - "queryHits": 248, - "uploads": 2, - "uploadedBytes": 16144, - "uploadHits": 1104, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 17988000 - }, - "network 1000000 buses > restyle": { - "queries": 0, - "queryHits": 186, - "uploads": 2, - "uploadedBytes": 16144, - "uploadHits": 1104, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 17988000 - }, - "network 1000000 buses > select": { - "queries": 0, - "queryHits": 0, - "uploads": 3, - "uploadedBytes": 528, - "uploadHits": 920, - "gpuCopiedBytes": 0, - "allocations": 0, - "submissions": 1, - "evictions": 0, - "stagedBytes": 0, - "rasterized": 0, - "vertices": 17988012 - }, - "pipeline 10000 buses > publication to frame": { - "queries": 2, - "queryHits": 1, - "uploads": 7, - "uploadedBytes": 41792, - "uploadHits": 20, - "gpuCopiedBytes": 0, - "allocations": 0.042, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 179853 - }, - "pipeline 100000 buses > publication to frame": { - "queries": 8, - "queryHits": 7, - "uploads": 19, - "uploadedBytes": 402728, - "uploadHits": 123, - "gpuCopiedBytes": 0, - "allocations": 0.083, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 1797255 - }, - "pipeline 1000000 buses > publication to frame": { - "queries": 63, - "queryHits": 62, - "uploads": 137, - "uploadedBytes": 4011932, - "uploadHits": 1112, - "gpuCopiedBytes": 0, - "allocations": 0.167, - "submissions": 1, - "evictions": 0, - "stagedBytes": 8, - "rasterized": 0, - "vertices": 17989053 - } -} diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 00000000..80c14b6c --- /dev/null +++ b/clippy.toml @@ -0,0 +1,7 @@ +# Names of formats and products that read as prose, not code. +doc-valid-idents = ["GeoJSON", "TileJSON", "PMTiles", "WebCodecs", "OKLab", ".."] +# Every write to the GPU is counted: through `gpu::work::Queue`, never the raw queue. +disallowed-methods = [ + { path = "wgpu::Queue::write_buffer", reason = "write through gpu::work::Queue, which counts" }, + { path = "wgpu::Queue::write_texture", reason = "write through gpu::work::Queue, which counts" }, +] diff --git a/crates/latkit-cli/Cargo.toml b/crates/latkit-cli/Cargo.toml new file mode 100644 index 00000000..61ba945c --- /dev/null +++ b/crates/latkit-cli/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "latkit-cli" +description = "Render latkit scenes of JSON or binary data to images and videos." +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +repository.workspace = true +homepage.workspace = true +keywords = ["visualization", "rendering", "video", "graph", "cli"] +categories = ["command-line-utilities", "visualization", "multimedia::video"] +readme = "README.md" +include = ["LICENSE", "src/**", "README.md"] + +[[bin]] +name = "latkit" +path = "src/main.rs" + +[dependencies] +latkit = { workspace = true, features = ["native"] } +clap.workspace = true +serde_json.workspace = true +serde.workspace = true +schemars.workspace = true +tempfile.workspace = true + +[lints] +workspace = true diff --git a/packages/diagram/LICENSE b/crates/latkit-cli/LICENSE similarity index 100% rename from packages/diagram/LICENSE rename to crates/latkit-cli/LICENSE diff --git a/crates/latkit-cli/README.md b/crates/latkit-cli/README.md new file mode 100644 index 00000000..628da428 --- /dev/null +++ b/crates/latkit-cli/README.md @@ -0,0 +1,20 @@ +# latkit CLI + +Draws latkit scenes of datasets into images, image sequences, raw frames, and videos, on the +machine's GPU, with the same renderer as the browser package. Inputs are latkit's JSON, so any +language can write them. The package is `latkit-cli`; the executable is `latkit`. + +```sh +cargo install latkit-cli +latkit validate scene.json -d grid.json +latkit render scene.json -d grid.json -o grid.png --size 2400x1350 --scale 2 +latkit render scene.json -d grid.json --frames frames.jsonl --fps 60 -o film.mp4 +latkit query grid.bin '{"of":"Branch","filter":{"op":"gt","args":["loading",90]},"limit":20}' +latkit tile history.bin -o history/ # time tiles a view fetches in spans: --tiles grid=history/frames.json +latkit schema scene > scene.schema.json +``` + +Commands, inputs, frames, outputs, and diagnostics are in +[the documentation](https://latkit.readthedocs.io/en/latest/cli.html). +[The gallery](examples/cli-gallery/README.md), [the 70,000-bus fault](examples/bus-fault/README.md), +and [the WECC240 fault](examples/wecc240-fault/README.md) are made with Python and this CLI alone. diff --git a/crates/latkit-cli/examples/branch-opening-orbit/README.md b/crates/latkit-cli/examples/branch-opening-orbit/README.md new file mode 100644 index 00000000..fcbb95d1 --- /dev/null +++ b/crates/latkit-cli/examples/branch-opening-orbit/README.md @@ -0,0 +1,48 @@ +# Line-opening orbit + +[Preview](preview.png) · The video is not in Git: [reproduce it](#reproduce) to write +`animation.mp4` here. + +A close 108° orbit around the network, starting farther toward the East Coast +and stopping before the far-western viewpoint. Magnification stays nearly +constant, with a higher viewing angle throughout and no late pullback or dip. +Centering and rotation change smoothly along the shorter arc. + +The saved simulation and visual scales come from the [original example](../branch-opening/README.md): +70,000 buses, the Little Rock–Newark 765 kV line opening at 1 s, 0.4× playback, +reduced height, no plot, 1920 × 1080 at 60 fps. The video is 23.517 seconds (1,411 frames). +The original example and its video remain separate. + +## Reproduce + +Run from the repository root with the saved study in `target/branch-opening/`: + +```powershell +python crates/latkit-cli/examples/branch-opening-orbit/render.py --cli target/cli/latkit.exe --preview +python crates/latkit-cli/examples/branch-opening-orbit/render.py --cli target/cli/latkit.exe +``` + +Python prepares the documents; Latkit draws and encodes the video. The shared +[data recipe](../branch-opening/render.py) and state boundaries are read from the +original example. Generated inputs go into `target/branch-opening-orbit/`. +No simulation rerun, duplicated frequency recording, or full image sequence is needed. + +Edit [camera.json](camera.json) to change the orbit. +`at` is simulation time in seconds, `center` is longitude/latitude, +`scale` is the plane's pixels per coordinate unit, and `pitch`/`bearing` are degrees. +The recipe writes native CLI `camera` values into every frame. Monotone cubic Hermite +interpolation gives continuous camera velocity without overshooting keyframes; +zoom interpolates in logarithmic space, with gentle starts and stops. + +`--preview --at 5.8` shows the matching camera at that simulation time. `--prepare-only` +writes the inputs and prints the complete CLI command. `--source`, `--work`, `--output`, +and `--limit` support alternate data, scratch directories, and short previews. +Each output's JSON records its camera path, source checksum, timing, and render command. + +Frequency and height retain the original example's interpretation: a filtered +voltage-angle frequency estimate and an exaggerated, nonlinear height encoding. +Close framing favors the network and response over peripheral state boundaries. + +The delivered video was decoded end to end (1,411 frames), with sample +brackets checked at every frame and framing inspected around the opening and +along the camera path. diff --git a/crates/latkit-cli/examples/branch-opening-orbit/animation.json b/crates/latkit-cli/examples/branch-opening-orbit/animation.json new file mode 100644 index 00000000..9b05172a --- /dev/null +++ b/crates/latkit-cli/examples/branch-opening-orbit/animation.json @@ -0,0 +1,158 @@ +{ + "buses": 70000, + "branches": 88207, + "event": { + "branch": "branch_59757_59774_1", + "action": "open", + "at_s": 1.0 + }, + "frames": 1411, + "fps": 60, + "resolution": [ + 1920, + 1080 + ], + "seconds": 23.516666666666666, + "playback_speed": 0.4, + "simulation_start_s": 0.6, + "simulation_end_s": 10.0, + "source_samples": 602, + "source_sample_hz": 60, + "frequency_sha256": "b72edd6eac9313d37344ebfeb952f45d2bbfd167a46ddc4727602a555d969862", + "source_statistics": { + "rows": 602, + "duplicate_times": 1, + "nonfinite": 0, + "pre_event_max_abs_hz": 4.79100583710488e-07, + "min_hz": -1.646875017187117, + "max_hz": 0.6834897947345193, + "post_1_1_max_abs_hz": 0.24483731315202817, + "bus_count": 70000, + "final_time_s": 10.0, + "peak_bus_id": 59774, + "buses_over_10_millihz_after_1_1": 70000, + "late_peak_quantiles_hz": [ + 0.06676637830185664, + 0.08986788489515062, + 0.11676234152644169 + ] + }, + "estimator": "Causal 20 ms filtered derivative of unwrapped bus voltage angle; both event sides retained, including the angle-jump impulse.", + "height_scale": 4.764463688617888, + "height_gain": 0.45, + "camera_bearings_degrees": [ + -70, + -48, + -12, + 15, + 38 + ], + "camera_start": { + "center": [ + -84.5, + 37.5 + ], + "zoom": 5.247927513443585, + "pitch": 50.0, + "bearing": -70.0 + }, + "camera_end": { + "center": [ + -87.0, + 37.5 + ], + "zoom": 5.247927513443585, + "pitch": 48.0, + "bearing": 38.0 + }, + "height_formula": "height_scale * asinh(df / 0.02) / asinh(0.35 / 0.02)", + "color_domain_hz": [ + -0.2, + 0.2 + ], + "shot": "orbit", + "camera_path": { + "title": "Orbit", + "keyframes": [ + { + "at": 0.6, + "center": [ + -84.5, + 37.5 + ], + "scale": 38, + "pitch": 50, + "bearing": -70 + }, + { + "at": 2.8, + "center": [ + -85, + 37.5 + ], + "scale": 40, + "pitch": 48, + "bearing": -48 + }, + { + "at": 5.8, + "center": [ + -86, + 37.5 + ], + "scale": 40, + "pitch": 46, + "bearing": -12 + }, + { + "at": 8.0, + "center": [ + -86.5, + 37.5 + ], + "scale": 38, + "pitch": 46, + "bearing": 15 + }, + { + "at": 10.0, + "center": [ + -87, + 37.5 + ], + "scale": 38, + "pitch": 48, + "bearing": 38 + } + ] + }, + "camera_interpolation": "monotone cubic Hermite; zoom interpolated logarithmically", + "render_seconds": 6.510786099999677, + "total_seconds": 7.860526299999037, + "output_bytes": 46677759, + "command": [ + "target/cli/latkit.exe", + "render", + "/target/branch-opening-orbit/map.json", + "--data", + "/target/branch-opening-orbit/grid.json", + "--data", + "states=/examples/branch-opening/states.geojson", + "--camera", + "/target/branch-opening-orbit/map-camera.json", + "--deadline", + "120", + "--frames", + "/target/branch-opening-orbit/frames.jsonl", + "--font", + "C:/Windows/Fonts/segoeui.ttf", + "--size", + "1920x1080", + "--fps", + "60", + "--bitrate", + "16000000", + "--output", + "/examples/branch-opening-orbit/animation.mp4" + ] +} diff --git a/crates/latkit-cli/examples/branch-opening-orbit/camera.json b/crates/latkit-cli/examples/branch-opening-orbit/camera.json new file mode 100644 index 00000000..3f7734e4 --- /dev/null +++ b/crates/latkit-cli/examples/branch-opening-orbit/camera.json @@ -0,0 +1,10 @@ +{ + "title": "Orbit", + "keyframes": [ + {"at": 0.6, "center": [-84.5, 37.5], "scale": 38, "pitch": 50, "bearing": -70}, + {"at": 2.8, "center": [-85, 37.5], "scale": 40, "pitch": 48, "bearing": -48}, + {"at": 5.8, "center": [-86, 37.5], "scale": 40, "pitch": 46, "bearing": -12}, + {"at": 8.0, "center": [-86.5, 37.5], "scale": 38, "pitch": 46, "bearing": 15}, + {"at": 10.0, "center": [-87, 37.5], "scale": 38, "pitch": 48, "bearing": 38} + ] +} diff --git a/crates/latkit-cli/examples/branch-opening-orbit/preview.json b/crates/latkit-cli/examples/branch-opening-orbit/preview.json new file mode 100644 index 00000000..f45cb50b --- /dev/null +++ b/crates/latkit-cli/examples/branch-opening-orbit/preview.json @@ -0,0 +1,158 @@ +{ + "buses": 70000, + "branches": 88207, + "event": { + "branch": "branch_59757_59774_1", + "action": "open", + "at_s": 1.0 + }, + "frames": 1, + "fps": 60, + "resolution": [ + 1920, + 1080 + ], + "seconds": 0.016666666666666666, + "playback_speed": 0.4, + "simulation_start_s": 1.3, + "simulation_end_s": 1.3, + "source_samples": 602, + "source_sample_hz": 60, + "frequency_sha256": "b72edd6eac9313d37344ebfeb952f45d2bbfd167a46ddc4727602a555d969862", + "source_statistics": { + "rows": 602, + "duplicate_times": 1, + "nonfinite": 0, + "pre_event_max_abs_hz": 4.79100583710488e-07, + "min_hz": -1.646875017187117, + "max_hz": 0.6834897947345193, + "post_1_1_max_abs_hz": 0.24483731315202817, + "bus_count": 70000, + "final_time_s": 10.0, + "peak_bus_id": 59774, + "buses_over_10_millihz_after_1_1": 70000, + "late_peak_quantiles_hz": [ + 0.06676637830185664, + 0.08986788489515062, + 0.11676234152644169 + ] + }, + "estimator": "Causal 20 ms filtered derivative of unwrapped bus voltage angle; both event sides retained, including the angle-jump impulse.", + "height_scale": 4.764463688617888, + "height_gain": 0.45, + "camera_bearings_degrees": [ + -70, + -48, + -12, + 15, + 38 + ], + "camera_start": { + "center": [ + -84.5789981472381, + 37.5 + ], + "zoom": 5.265635391121904, + "pitch": 49.639156421351686, + "bearing": -66.38449885908227 + }, + "camera_end": { + "center": [ + -84.5789981472381, + 37.5 + ], + "zoom": 5.265635391121904, + "pitch": 49.639156421351686, + "bearing": -66.38449885908227 + }, + "height_formula": "height_scale * asinh(df / 0.02) / asinh(0.35 / 0.02)", + "color_domain_hz": [ + -0.2, + 0.2 + ], + "shot": "orbit", + "camera_path": { + "title": "Orbit", + "keyframes": [ + { + "at": 0.6, + "center": [ + -84.5, + 37.5 + ], + "scale": 38, + "pitch": 50, + "bearing": -70 + }, + { + "at": 2.8, + "center": [ + -85, + 37.5 + ], + "scale": 40, + "pitch": 48, + "bearing": -48 + }, + { + "at": 5.8, + "center": [ + -86, + 37.5 + ], + "scale": 40, + "pitch": 46, + "bearing": -12 + }, + { + "at": 8.0, + "center": [ + -86.5, + 37.5 + ], + "scale": 38, + "pitch": 46, + "bearing": 15 + }, + { + "at": 10.0, + "center": [ + -87, + 37.5 + ], + "scale": 38, + "pitch": 48, + "bearing": 38 + } + ] + }, + "camera_interpolation": "monotone cubic Hermite; zoom interpolated logarithmically", + "render_seconds": 0.7592546000014408, + "total_seconds": 1.438417400000617, + "output_bytes": 1129145, + "command": [ + "target/cli/latkit.exe", + "render", + "/target/branch-opening-orbit/map.json", + "--data", + "/target/branch-opening-orbit/grid.json", + "--data", + "states=/examples/branch-opening/states.geojson", + "--camera", + "/target/branch-opening-orbit/map-camera.json", + "--deadline", + "120", + "--at", + "1.3", + "--font", + "C:/Windows/Fonts/segoeui.ttf", + "--size", + "1920x1080", + "--fps", + "60", + "--bitrate", + "16000000", + "--output", + "/examples/branch-opening-orbit/preview.png" + ] +} diff --git a/crates/latkit-cli/examples/branch-opening-orbit/preview.png b/crates/latkit-cli/examples/branch-opening-orbit/preview.png new file mode 100644 index 00000000..9d5515b4 Binary files /dev/null and b/crates/latkit-cli/examples/branch-opening-orbit/preview.png differ diff --git a/crates/latkit-cli/examples/branch-opening-orbit/render.py b/crates/latkit-cli/examples/branch-opening-orbit/render.py new file mode 100644 index 00000000..6288e221 --- /dev/null +++ b/crates/latkit-cli/examples/branch-opening-orbit/render.py @@ -0,0 +1,136 @@ +"""A close orbit of the saved line-opening recording, rendered by the Latkit CLI. + +Reuses the original example's data preparation without modifying it. Edit +camera.json to change the path; Python's standard library is sufficient. +""" + +import argparse +import bisect +import importlib.util +import json +import math +import os +import subprocess +import sys +import time +from pathlib import Path + +EXAMPLE = Path(__file__).resolve().parent +ROOT = EXAMPLE.parent.parent +BASE = EXAMPLE.parent / "branch-opening" + + +def load_recipe(): + # Loading the shared recipe should not create files in the original example. + sys.dont_write_bytecode = True + spec = importlib.util.spec_from_file_location("branch_opening", BASE / "render.py") + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def interpolate(times, values, at): + """Monotone cubic Hermite: continuous velocity, no overshoot, soft endpoints.""" + i = min(max(bisect.bisect_right(times, at) - 1, 0), len(times) - 2) + h = times[i + 1] - times[i] + u = min(1, max(0, (at - times[i]) / h)) + + def slope(k): + if k == 0 or k == len(times) - 1: + return 0.0 + before, after = times[k] - times[k - 1], times[k + 1] - times[k] + a = (values[k] - values[k - 1]) / before + b = (values[k + 1] - values[k]) / after + if a * b <= 0: + return 0.0 + w1, w2 = 2 * after + before, after + 2 * before + return (w1 + w2) / (w1 / a + w2 / b) + + return ((2 * u**3 - 3 * u**2 + 1) * values[i] + + (u**3 - 2 * u**2 + u) * h * slope(i) + + (-2 * u**3 + 3 * u**2) * values[i + 1] + + (u**3 - u**2) * h * slope(i + 1)) + + +def camera_at(path, at): + keys = path["keyframes"] + times = [k["at"] for k in keys] + sample = lambda values: interpolate(times, values, at) + return {"center": [sample([k["center"][axis] for k in keys]) for axis in range(2)], + "zoom": sample([math.log2(k["scale"]) for k in keys]), + "pitch": sample([k["pitch"] for k in keys]), + "bearing": sample([k["bearing"] for k in keys])} + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--source", type=Path, default=ROOT / "target/branch-opening") + parser.add_argument("--work", type=Path, default=ROOT / "target/branch-opening-orbit", help="generated CLI inputs") + parser.add_argument("--output", type=Path, default=EXAMPLE, help="defaults to this example directory") + parser.add_argument("--cli", default="latkit") + parser.add_argument("--font", type=Path) + parser.add_argument("--preview", action="store_true") + parser.add_argument("--at", type=float, default=1.3, help="preview time in simulation seconds") + parser.add_argument("--limit", type=int) + parser.add_argument("--prepare-only", action="store_true") + args = parser.parse_args() + if args.limit is not None and args.limit < 1: + parser.error("--limit must be positive") + + recipe = load_recipe() + path = recipe.read(EXAMPLE / "camera.json") + keys = path["keyframes"] + if len(keys) < 2 or any(b["at"] <= a["at"] for a, b in zip(keys, keys[1:])): + parser.error("camera keyframes must have strictly increasing times") + if any(k["scale"] <= 0 or not 0 <= k["pitch"] < 90 for k in keys): + parser.error("camera scale must be positive, and pitch must be in [0, 90)") + frames = [args.at] if args.preview else recipe.playback_times() + if args.limit is not None: + frames = frames[:args.limit] + if frames[0] < keys[0]["at"] or frames[-1] > keys[-1]["at"]: + parser.error("the camera path does not cover the requested simulation time") + job = args.work.resolve() + output = args.output.resolve() + started = time.perf_counter() + metadata = recipe.prepare(args.source.resolve(), job, frames) + + scene = recipe.read(job / "map.json") + scene["title"] = f"ACTIVSg70k / {path['title']}" + recipe.write(job / "map.json", scene) + recipe.write(job / "map-camera.json", camera_at(path, frames[0])) + sequence = [json.loads(line) for line in (job / "frames.jsonl").read_text().splitlines()] + with (job / "frames.jsonl").open("w", encoding="utf-8", newline="\n") as stream: + for frame in sequence: + frame["camera"] = camera_at(path, frame["at"]) + stream.write(json.dumps(frame, allow_nan=False) + "\n") + + metadata.update({"shot": "orbit", "camera_path": path, + "camera_bearings_degrees": [k["bearing"] for k in keys], + "camera_start": camera_at(path, frames[0]), "camera_end": camera_at(path, frames[-1]), + "camera_interpolation": "monotone cubic Hermite; zoom interpolated logarithmically"}) + output.mkdir(parents=True, exist_ok=True) + result = output / ("preview.png" if args.preview else "animation.mp4") + inputs = [str(job / "map.json"), "--data", str(job / "grid.json"), + "--data", f"states={BASE / 'states.geojson'}", "--camera", str(job / "map-camera.json"), + "--deadline", "120"] + inputs.extend(["--at", str(args.at)] if args.preview else ["--frames", str(job / "frames.jsonl")]) + font = args.font or (Path("C:/Windows/Fonts/segoeui.ttf") if os.name == "nt" else None) + if font: + inputs.extend(["--font", str(font)]) + render = [args.cli, "render", *inputs, "--size", f"{recipe.W}x{recipe.H}", + "--fps", str(recipe.FPS), "--bitrate", "16000000", "--output", str(result)] + print(subprocess.list2cmdline(render), flush=True) + if args.prepare_only: + return + subprocess.run([args.cli, "validate", *inputs], check=True) + render_started = time.perf_counter() + subprocess.run(render, check=True) + metadata.update({"render_seconds": time.perf_counter() - render_started, + "total_seconds": time.perf_counter() - started, "output_bytes": result.stat().st_size, + "command": [part.replace(str(ROOT), "").replace(os.sep, "/") for part in render]}) + recipe.write(output / ("preview.json" if args.preview else "animation.json"), metadata) + print(f"Saved {result} ({metadata['output_bytes'] / 1e6:.2f} MB; {metadata['render_seconds']:.1f} s rendering)", flush=True) + + +if __name__ == "__main__": + main() diff --git a/crates/latkit-cli/examples/branch-opening/README.md b/crates/latkit-cli/examples/branch-opening/README.md new file mode 100644 index 00000000..45b260e5 --- /dev/null +++ b/crates/latkit-cli/examples/branch-opening/README.md @@ -0,0 +1,84 @@ +# ACTIVSg70k line opening — Python + Latkit CLI + +[Preview](preview.png) · The video is not in Git: [render the saved study](#render-the-saved-study) +to write `animation.mp4` here. + +The synthetic 70,000-bus network responds to the Little Rock–Newark 765 kV line +(`branch_59757_59774_1`) opening at 1 s. It stays open. The video shows simulation +0.6–10 s at a constant 0.4× speed: **1,411 frames, 60 fps, 1920 × 1080, +23.517 seconds**. The map fills the frame, and a dashed gold line marks the disconnected +branch. A gentle 30° camera sweep reveals the response from changing angles. + +[`render.py`](render.py) uses Python's standard library and the Latkit CLI. Latkit +draws the network, state boundaries, labels, and frequency legend, and encodes H.264 +through its native Windows MP4 output. There is no Rust consumer, browser renderer, +Python imaging dependency, or external encoder in this recipe. + +## Render the saved study + +From the repository root, with Python 3.10+ and the saved study present: + +```powershell +cargo build --locked -p latkit-cli --profile cli +python crates/latkit-cli/examples/branch-opening/render.py --cli target/cli/latkit.exe --preview +python crates/latkit-cli/examples/branch-opening/render.py --cli target/cli/latkit.exe +``` + +An installed CLI works too: `python crates/latkit-cli/examples/branch-opening/render.py`. +Use `--preview --at 2.5` for a different still, `--limit 120 --output target/preview` +for a short movie, or `--prepare-only` to write the inputs and print the complete +CLI command. Scene and camera JSON are generated in `target/branch-opening/render/`; +edit those and run the printed CLI command directly to experiment with the view. +A recipe rerun regenerates its inputs. + +The optional positional argument selects another saved-study directory. Its files are: + +```text +target/branch-opening/ + buses.json + topology.json + runs/little-rock-60hz/ + frequency_metadata.json + frequency.f32 +``` + +The recording is local, ignored data; it is **not included in Git**. The small state +boundary asset is reused from the earlier bus-fault recording and included here. +`animation.json` and `preview.json` record the command, source checksum, scales, +dimensions, and render timing. Native MP4 output currently requires Windows. + +## Data and display + +The study used `ghcr.io/lukelowry/gridkit:develop-perf`, image ID +`sha256:befba9e16edce341888e73c05b9d2c35aedf1357fa18b54c56114dbe25ccd565`, +and the original ACTIVSg70k case, SHA-256 +`8c3d1edd9deaf409436b1f38e55f41c963d08eae7709474bcfb2c1dffadbdb15`. +The full simulation manifest remains beside the recording. + +Only bus voltage angles were monitored, at 60 Hz over 0–10 s, with both sides of +the event retained. Frequency is the causal 20 ms filtered derivative of unwrapped +voltage angle, expressed as Hz deviation from 60 Hz. The raw angles were streamed +and discarded. This is a bus voltage-frequency estimate, not generator rotor speed. +The switching angle jump produces a brief impulse (about −1.647 to +0.683 Hz). + +Colors saturate at ±0.20 Hz. Signed height is exaggerated by +`height_scale * asinh(df / 0.02) / asinh(0.35 / 0.02)`; it is a visual encoding of +frequency, not physical displacement. The height gain is 0.45 of the earlier view, +reducing displacement by 55% while preserving its sign and nonlinear scale. The +camera keeps a fixed center, zoom, and 48° pitch, with bearing easing from −10° to ++20° over the full recording. This keeps the initial peak in view and makes the +geography easier to follow. There is no bottom plot or trace legend. + +`HEIGHT_GAIN` and `BEARINGS` near the top of `render.py` control the exaggeration +and camera sweep. The camera path uses simulation time, so an arbitrary preview +matches that moment in the movie. + +For slow motion, Latkit interpolates between the original samples and computes the +height expression on the GPU. The recipe appends only samples needed for the next +picture and forgets older ones. Its timestamp comparison exactly matches Latkit's: +the retained lower sample must be **at or before** the requested time. Both event +sides remain distinct, so post-opening data never leaks into pre-opening pictures. +No dense interpolated cache, height cache, or full image sequence is written. + +The CLI validates the generated documents before rendering. The delivered MP4 was +also decoded end to end and checked around the event and sample boundaries. diff --git a/crates/latkit-cli/examples/branch-opening/animation.json b/crates/latkit-cli/examples/branch-opening/animation.json new file mode 100644 index 00000000..e9aa05e8 --- /dev/null +++ b/crates/latkit-cli/examples/branch-opening/animation.json @@ -0,0 +1,98 @@ +{ + "buses": 70000, + "branches": 88207, + "event": { + "branch": "branch_59757_59774_1", + "action": "open", + "at_s": 1.0 + }, + "frames": 1411, + "fps": 60, + "resolution": [ + 1920, + 1080 + ], + "seconds": 23.516666666666666, + "playback_speed": 0.4, + "simulation_start_s": 0.6, + "simulation_end_s": 10.0, + "source_samples": 602, + "source_sample_hz": 60, + "frequency_sha256": "b72edd6eac9313d37344ebfeb952f45d2bbfd167a46ddc4727602a555d969862", + "source_statistics": { + "rows": 602, + "duplicate_times": 1, + "nonfinite": 0, + "pre_event_max_abs_hz": 4.79100583710488e-07, + "min_hz": -1.646875017187117, + "max_hz": 0.6834897947345193, + "post_1_1_max_abs_hz": 0.24483731315202817, + "bus_count": 70000, + "final_time_s": 10.0, + "peak_bus_id": 59774, + "buses_over_10_millihz_after_1_1": 70000, + "late_peak_quantiles_hz": [ + 0.06676637830185664, + 0.08986788489515062, + 0.11676234152644169 + ] + }, + "estimator": "Causal 20 ms filtered derivative of unwrapped bus voltage angle; both event sides retained, including the angle-jump impulse.", + "height_scale": 4.764463688617888, + "height_gain": 0.45, + "camera_bearings_degrees": [ + -10, + 20 + ], + "camera_start": { + "center": [ + -92, + 36.5 + ], + "zoom": 5.087462841250339, + "pitch": 48, + "bearing": -10 + }, + "camera_end": { + "center": [ + -92, + 36.5 + ], + "zoom": 5.087462841250339, + "pitch": 48, + "bearing": 20 + }, + "height_formula": "height_scale * asinh(df / 0.02) / asinh(0.35 / 0.02)", + "color_domain_hz": [ + -0.2, + 0.2 + ], + "render_seconds": 6.544604299997445, + "total_seconds": 7.592458800005261, + "output_bytes": 46411083, + "command": [ + "target/cli/latkit.exe", + "render", + "/target/branch-opening/render/map.json", + "--data", + "/target/branch-opening/render/grid.json", + "--data", + "states=/examples/branch-opening/states.geojson", + "--camera", + "/target/branch-opening/render/map-camera.json", + "--frames", + "/target/branch-opening/render/frames.jsonl", + "--deadline", + "120", + "--font", + "C:/Windows/Fonts/segoeui.ttf", + "--size", + "1920x1080", + "--fps", + "60", + "--bitrate", + "16000000", + "--output", + "/examples/branch-opening/animation.mp4" + ] +} diff --git a/crates/latkit-cli/examples/branch-opening/preview.json b/crates/latkit-cli/examples/branch-opening/preview.json new file mode 100644 index 00000000..2519afb6 --- /dev/null +++ b/crates/latkit-cli/examples/branch-opening/preview.json @@ -0,0 +1,98 @@ +{ + "buses": 70000, + "branches": 88207, + "event": { + "branch": "branch_59757_59774_1", + "action": "open", + "at_s": 1.0 + }, + "frames": 1, + "fps": 60, + "resolution": [ + 1920, + 1080 + ], + "seconds": 0.016666666666666666, + "playback_speed": 0.4, + "simulation_start_s": 1.3, + "simulation_end_s": 1.3, + "source_samples": 602, + "source_sample_hz": 60, + "frequency_sha256": "b72edd6eac9313d37344ebfeb952f45d2bbfd167a46ddc4727602a555d969862", + "source_statistics": { + "rows": 602, + "duplicate_times": 1, + "nonfinite": 0, + "pre_event_max_abs_hz": 4.79100583710488e-07, + "min_hz": -1.646875017187117, + "max_hz": 0.6834897947345193, + "post_1_1_max_abs_hz": 0.24483731315202817, + "bus_count": 70000, + "final_time_s": 10.0, + "peak_bus_id": 59774, + "buses_over_10_millihz_after_1_1": 70000, + "late_peak_quantiles_hz": [ + 0.06676637830185664, + 0.08986788489515062, + 0.11676234152644169 + ] + }, + "estimator": "Causal 20 ms filtered derivative of unwrapped bus voltage angle; both event sides retained, including the angle-jump impulse.", + "height_scale": 4.764463688617888, + "height_gain": 0.45, + "camera_bearings_degrees": [ + -10, + 20 + ], + "camera_start": { + "center": [ + -92, + 36.5 + ], + "zoom": 5.087462841250339, + "pitch": 48, + "bearing": -9.525683133795017 + }, + "camera_end": { + "center": [ + -92, + 36.5 + ], + "zoom": 5.087462841250339, + "pitch": 48, + "bearing": -9.525683133795017 + }, + "height_formula": "height_scale * asinh(df / 0.02) / asinh(0.35 / 0.02)", + "color_domain_hz": [ + -0.2, + 0.2 + ], + "render_seconds": 0.93470410000009, + "total_seconds": 1.631355599995004, + "output_bytes": 892404, + "command": [ + "target/cli/latkit.exe", + "render", + "/target/branch-opening/render/map.json", + "--data", + "/target/branch-opening/render/grid.json", + "--data", + "states=/examples/branch-opening/states.geojson", + "--camera", + "/target/branch-opening/render/map-camera.json", + "--at", + "1.3", + "--deadline", + "120", + "--font", + "C:/Windows/Fonts/segoeui.ttf", + "--size", + "1920x1080", + "--fps", + "60", + "--bitrate", + "16000000", + "--output", + "/examples/branch-opening/preview.png" + ] +} diff --git a/crates/latkit-cli/examples/branch-opening/preview.png b/crates/latkit-cli/examples/branch-opening/preview.png new file mode 100644 index 00000000..6bbd2356 Binary files /dev/null and b/crates/latkit-cli/examples/branch-opening/preview.png differ diff --git a/crates/latkit-cli/examples/branch-opening/render.py b/crates/latkit-cli/examples/branch-opening/render.py new file mode 100644 index 00000000..375fb729 --- /dev/null +++ b/crates/latkit-cli/examples/branch-opening/render.py @@ -0,0 +1,240 @@ +"""Render the saved ACTIVSg70k line-opening study using Python and the Latkit CLI. + +Python prepares JSON and selects slices of the original float32 recording. Latkit +interpolates the samples, computes elevation, draws the map, and encodes the MP4. +Requires Python 3.10+; no third-party Python packages or external encoder. +""" + +import argparse +import bisect +import hashlib +import json +import math +import os +import subprocess +import time +from pathlib import Path + +EXAMPLE = Path(__file__).resolve().parent +ROOT = EXAMPLE.parent.parent +W, H, FPS = 1920, 1080, 60 +SPEED = 0.4 +HEIGHT_GAIN = 0.45 +BEARINGS = [-10, 20] +BRANCH = "branch_59757_59774_1" +EVENT = 1.0 +BACKGROUND = "#090d12" +PALETTE = ["#1f52f2", "#2ea6f2", "#4d6e7a", "#ffa13b", "#ff3b1c"] + + +def read(path): + return json.loads(path.read_text(encoding="utf-8-sig")) + + +def write(path, value): + path.write_text(json.dumps(value, ensure_ascii=False, allow_nan=False, indent=2) + "\n", + encoding="utf-8", newline="\n") + + +def op(name, *args): + return {"op": name, "args": list(args)} + + +def sha256(path): + digest = hashlib.sha256() + with path.open("rb") as stream: + for chunk in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +def playback_times(): + # 0.6--10 s at a constant 0.4x: 1,411 pictures, 23.517 s. + count = round((10 - 0.6) * FPS / SPEED) + 1 + return [round(0.6 + k * SPEED / FPS, 12) for k in range(count)] + + +def camera_at(at): + # A small arc with gentle starts and stops; previews follow the same path. + u = min(1, max(0, (at - 0.6) / (10 - 0.6))) + eased = u * u * (3 - 2 * u) + return {"center": [-92, 36.5], "zoom": math.log2(34), "pitch": 48, + "bearing": BEARINGS[0] + (BEARINGS[1] - BEARINGS[0]) * eased} + + +def prepare(source, job, frames): + recording = source / "runs/little-rock-60hz" + meta = read(recording / "frequency_metadata.json") + ids, times = meta["bus_ids"], meta["times"] + frequency = recording / "frequency.f32" + n = len(ids) + if (n != 70000 or len(set(ids)) != n or meta["dtype"] != "f32le" + or meta["layout"] != "frame-major" + or frequency.stat().st_size != n * len(times) * 4 + or any(b < a for a, b in zip(times, times[1:]))): + raise ValueError("Unexpected recording dimensions, format, or sample order") + if not times[0] <= min(frames) <= max(frames) <= times[-1]: + raise ValueError("Requested frames lie outside the recording") + job.mkdir(parents=True, exist_ok=True) + + def bracket(at): + # Match Latkit's exact <= comparison. An epsilon here can select a sample + # just AFTER `at`, then `forget` removes the last sample Latkit can read. + lower = bisect.bisect_right(times, at) - 1 + upper = min(lower + 1, len(times) - 1) + assert times[lower] <= at <= times[upper] + return lower, upper + + def append(start, end): + return {"append": {"at": times[start:end + 1], "table": "Bus", "fields": { + "df": {"file": os.path.relpath(frequency, job).replace(os.sep, "/"), + "dtype": "f32le", "offset": start * n * 4, "count": (end - start + 1) * n} + }}} + + buses = {b["bus_id"]: b for b in read(source / "buses.json")} + ordered = [buses[i] for i in ids] + lon = [b["longitude"] for b in ordered] + lat = [b["latitude"] for b in ordered] + branches = read(source / "topology.json") + selected = [e for e in branches if e["id"] == BRANCH] + if len(selected) != 1 or (selected[0]["bus1"], selected[0]["bus2"]) != (59757, 59774): + raise ValueError("The selected branch does not match the saved topology") + widths = [0.7 + min(1, max(0, (min(buses[e["bus1"]]["kv"], buses[e["bus2"]]["kv"]) - 69) / 696)) + for e in branches] + opened = frames[0] >= EVENT + lower, loaded = bracket(frames[0]) + write(job / "grid.json", {"name": "grid", "patch": [ + {"axis": {"name": "time", "unit": "s"}}, + {"replace": {"table": "Bus", "ids": ids, "fields": { + "lon": lon, "lat": lat, + "label": [{59757: "Little Rock", 59774: "Newark"}.get(i, "") for i in ids], + }}}, + {"replace": {"table": "Branch", "ids": [e["id"] for e in branches], "fields": { + "width": widths, "in_service": [not (opened and e["id"] == BRANCH) for e in branches], + "from": {"reference": "Bus", "ids": [e["bus1"] for e in branches]}, + "to": {"reference": "Bus", "ids": [e["bus2"] for e in branches]}, + }}}, + {"replace": {"table": "Outage", "ids": [BRANCH], "fields": { + "from": {"reference": "Bus", "ids": [59757]}, + "to": {"reference": "Bus", "ids": [59774]}, + "opened": [opened], "status": ["765 kV / OPEN" if opened else "765 kV / CLOSED"], + }}}, + append(lower, loaded), + ]}) + + # asinh(df / 0.02), expressed with the CLI's ordinary GPU expression operators. + # Use abs/sign to avoid cancellation in ln(x + sqrt(x*x+1)) for negative x. + x = op("div", op("abs", "df"), 0.02) + magnitude = op("ln", op("add", x, op("sqrt", op("add", op("mul", x, x), 1)))) + signed = {"when": [[op("lt", "df", 0), op("neg", magnitude)]], "otherwise": magnitude} + height_scale = HEIGHT_GAIN * 1.7 * 0.15 * max(max(lon) - min(lon), max(lat) - min(lat)) + elevation = op("mul", signed, height_scale / math.asinh(0.35 / 0.02)) + theme = {"background": BACKGROUND, "text": "#c9d4dc", "font": "Segoe UI, sans-serif", "fontSize": 15} + scenes = { + "map.json": { + "space": {"plane": {"grid": "off"}}, "ease": 0, + "theme": {**theme, "edge": None, "laneBow": 0}, + "title": "ACTIVSg70k / Line opening", + "subtitle": f"Little Rock - Newark, 765 kV / Opens at 1 s / Constant {SPEED:g}x speed", + "marks": [ + {"lines": {"of": ["states", "polygons"], "color": "#5c7a8f6b", "width": 0.75, + "visible": op("not", op("or", {"is": ["name", "Alaska"]}, + {"is": ["name", "Hawaii"]}))}}, + {"edges": {"of": ["grid", "Branch"], "ends": ["from", "to"], "width": "width", "visible": "in_service"}}, + {"edges": {"of": ["grid", "Outage"], "ends": ["from", "to"], "width": 2.5, + "color": "#ffde86", "dash": "opened", + "label": {"text": "status", "size": 13, "priority": 100}}}, + {"vertices": {"of": ["grid", "Bus"], "position": ["lon", "lat"], "radius": 0.8, + "elevation": elevation, + "color": {"colormap": {"kind": "diverging", "colors": PALETTE}, + "value": "df", "domain": [-0.2, 0.2]}, + "label": {"text": "label", "size": 14, "priority": 101}, + "legend": "Bus frequency deviation / Hz"}}, + ], + }, + "map-camera.json": camera_at(frames[0]), + } + for name, scene in scenes.items(): + write(job / name, scene) + + with (job / "frames.jsonl").open("w", encoding="utf-8", newline="\n") as stream: + for at in frames: + lower, upper = bracket(at) + patch = [] + if upper > loaded: + # At t < 1, only the pre-switch sample at 1 s has been appended. + # Append the second side only at/after the event, preventing anticipation. + patch.append(append(loaded + 1, upper)) + patch.append({"forget": {"before": times[lower]}}) + loaded = upper + if not opened and at >= EVENT: + patch.extend([ + {"set": {"table": "Branch", "ids": [BRANCH], "fields": {"in_service": [False]}}}, + {"set": {"table": "Outage", "ids": [BRANCH], "fields": {"opened": [True], "status": ["765 kV / OPEN"]}}}, + ]) + opened = True + frame = {"at": at, "camera": camera_at(at)} + if patch: + frame["patch"] = {"grid": patch} + stream.write(json.dumps(frame, allow_nan=False) + "\n") + return {"buses": n, "branches": len(branches), + "event": {"branch": BRANCH, "action": "open", "at_s": EVENT}, + "frames": len(frames), "fps": FPS, "resolution": [W, H], "seconds": len(frames) / FPS, + "playback_speed": SPEED, + "simulation_start_s": frames[0], "simulation_end_s": frames[-1], + "source_samples": len(times), "source_sample_hz": meta["nominal_sample_hz"], + "frequency_sha256": sha256(frequency), "source_statistics": meta["statistics"], + "estimator": meta["estimator"], "height_scale": height_scale, + "height_gain": HEIGHT_GAIN, "camera_bearings_degrees": BEARINGS, + "camera_start": camera_at(frames[0]), "camera_end": camera_at(frames[-1]), + "height_formula": "height_scale * asinh(df / 0.02) / asinh(0.35 / 0.02)", + "color_domain_hz": [-0.2, 0.2]} + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("source", nargs="?", type=Path, default=ROOT / "target/branch-opening") + parser.add_argument("--work", type=Path, default=ROOT / "target/branch-opening/render") + parser.add_argument("--output", type=Path, default=EXAMPLE) + parser.add_argument("--cli", default="latkit") + parser.add_argument("--font", type=Path, help="TTF/OTF fallback; defaults to Segoe UI on Windows") + parser.add_argument("--preview", action="store_true", help="render one PNG instead of the movie") + parser.add_argument("--at", type=float, default=1.3, help="preview simulation time, seconds") + parser.add_argument("--prepare-only", action="store_true", help="write CLI inputs and print the command") + parser.add_argument("--limit", type=int, help="render the first N movie frames for a quick check") + args = parser.parse_args() + if args.limit is not None and args.limit < 1: + parser.error("--limit must be positive") + frames = [args.at] if args.preview else playback_times() + if args.limit is not None: + frames = frames[:args.limit] + job, output = args.work.resolve(), args.output.resolve() + started = time.perf_counter() + metadata = prepare(args.source.resolve(), job, frames) + output.mkdir(parents=True, exist_ok=True) + result = output / ("preview.png" if args.preview else "animation.mp4") + inputs = [str(job / "map.json"), "--data", str(job / "grid.json"), + "--data", f"states={EXAMPLE / 'states.geojson'}", + "--camera", str(job / "map-camera.json")] + inputs.extend(["--at", str(args.at)] if args.preview else ["--frames", str(job / "frames.jsonl")]) + inputs.extend(["--deadline", "120"]) + font = args.font or (Path("C:/Windows/Fonts/segoeui.ttf") if os.name == "nt" else None) + if font: + inputs.extend(["--font", str(font)]) + render = [args.cli, "render", *inputs, "--size", f"{W}x{H}", "--fps", str(FPS), + "--bitrate", "16000000", "--output", str(result)] + print(subprocess.list2cmdline(render), flush=True) + if args.prepare_only: + return + subprocess.run([args.cli, "validate", *inputs], check=True) + render_started = time.perf_counter() + subprocess.run(render, check=True) + metadata.update({"render_seconds": time.perf_counter() - render_started, + "total_seconds": time.perf_counter() - started, "output_bytes": result.stat().st_size, + "command": [part.replace(str(ROOT), "").replace(os.sep, "/") for part in render]}) + write(output / ("preview.json" if args.preview else "animation.json"), metadata) + print(f"Saved {result} ({metadata['output_bytes'] / 1e6:.2f} MB; {metadata['render_seconds']:.1f} s rendering)", flush=True) + + +if __name__ == "__main__": + main() diff --git a/crates/latkit-cli/examples/branch-opening/states.geojson b/crates/latkit-cli/examples/branch-opening/states.geojson new file mode 100644 index 00000000..c5707288 --- /dev/null +++ b/crates/latkit-cli/examples/branch-opening/states.geojson @@ -0,0 +1 @@ +{"type": "FeatureCollection", "features": [{"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3563", "diss_me": 3563, "iso_3166_2": "US-AK", "wikipedia": "http://en.wikipedia.org/wiki/Alaska", "iso_a2": "US", "adm0_sr": 6, "name": "Alaska", "name_alt": "AK|Alaska", "name_local": null, "type": "State", "type_en": "State", "code_local": "US02", "code_hasc": "US.AK", "note": null, "hasc_maybe": null, "region": "West", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Alaska", "postal": "AK", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 6, "mapcolor9": 1, "mapcolor13": 1, "fips": "US02", "fips_alt": null, "woe_id": 2347560, "woe_label": "Alaska, US, United States", "woe_name": "Alaska", "latitude": 65.3609, "longitude": -151.604, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5879092, "gn_name": "Alaska", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.AK", "region_sub": "Pacific", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q797", "name_ar": "\u0623\u0644\u0627\u0633\u0643\u0627", "name_bn": "\u0986\u09b2\u09be\u09b8\u09cd\u0995\u09be", "name_de": "Alaska", "name_en": "Alaska", "name_es": "Alaska", "name_fr": "Alaska", "name_el": "\u0391\u03bb\u03ac\u03c3\u03ba\u03b1", "name_hi": "\u0905\u0932\u093e\u0938\u094d\u0915\u093e", "name_hu": "Alaszka", "name_id": "Alaska", "name_it": "Alaska", "name_ja": "\u30a2\u30e9\u30b9\u30ab\u5dde", "name_ko": "\uc54c\ub798\uc2a4\uce74", "name_nl": "Alaska", "name_pl": "Alaska", "name_pt": "Alasca", "name_ru": "\u0410\u043b\u044f\u0441\u043a\u0430", "name_sv": "Alaska", "name_tr": "Alaska", "name_vi": "Alaska", "name_zh": "\u963f\u62c9\u65af\u52a0\u5dde", "ne_id": 1159308731, "name_he": "\u05d0\u05dc\u05e1\u05e7\u05d4", "name_uk": "\u0410\u043b\u044f\u0441\u043a\u0430", "name_ur": "\u0627\u0644\u0627\u0633\u06a9\u0627", "name_fa": "\u0622\u0644\u0627\u0633\u06a9\u0627", "name_zht": "\u963f\u62c9\u65af\u52a0\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-178.194518, 51.603676, -130.014073, 71.407687], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-139.056519, 60.001582], [-139.043445, 59.993243], [-138.868754, 59.945749], [-138.705456, 59.901331], [-138.632257, 59.778285], [-138.453636, 59.683385], [-138.317625, 59.611117], [-138.187451, 59.541947], [-138.001134, 59.442938], [-137.870572, 59.373581], [-137.696626, 59.281131], [-137.593299, 59.226254], [-137.543696, 59.119445], [-137.484161, 58.991235], [-137.520877, 58.915374], [-137.438579, 58.903125], [-137.277558, 58.988214], [-137.126199, 59.040948], [-136.93931, 59.106108], [-136.81327, 59.150031], [-136.578739, 59.152251], [-136.466728, 59.279945], [-136.466344, 59.459088], [-136.347845, 59.456034], [-136.277983, 59.480324], [-136.247133, 59.532905], [-136.321829, 59.604832], [-136.097164, 59.638374], [-135.934644, 59.662642], [-135.70259, 59.728758], [-135.475937, 59.793281], [-135.367854, 59.743304], [-135.260781, 59.695008], [-135.05103, 59.578663], [-135.03666, 59.550703], [-135.050843, 59.496057], [-135.071311, 59.441433], [-134.94377, 59.288272], [-134.907241, 59.271211], [-134.802409, 59.249974], [-134.677225, 59.199283], [-134.621981, 59.155305], [-134.440756, 59.085333], [-134.410214, 59.056241], [-134.393059, 59.009165], [-134.363527, 58.968724], [-134.329651, 58.939709], [-134.296994, 58.898499], [-134.218519, 58.849896], [-134.069204, 58.795535], [-133.965745, 58.757863], [-133.820742, 58.705052], [-133.673926, 58.597144], [-133.546392, 58.503486], [-133.401103, 58.410882], [-133.422576, 58.337065], [-133.275299, 58.222851], [-133.120424, 58.077744], [-133.001409, 57.948973], [-132.916842, 57.87698], [-132.815532, 57.772697], [-132.691507, 57.645113], [-132.550481, 57.499907], [-132.44248, 57.406732], [-132.301663, 57.276324], [-132.232158, 57.19853], [-132.279415, 57.145345], [-132.337989, 57.07946], [-132.157017, 57.048193], [-132.03152, 57.02655], [-132.062913, 56.95337], [-132.104282, 56.856789], [-131.962509, 56.818699], [-131.866159, 56.792838], [-131.886, 56.742114], [-131.833085, 56.684809], [-131.824274, 56.589986], [-131.651519, 56.596083], [-131.575115, 56.598819], [-131.471893, 56.55673], [-131.3358, 56.501228], [-131.199404, 56.449218], [-131.082922, 56.404822], [-130.930217, 56.378598], [-130.741681, 56.340827], [-130.649072, 56.26367], [-130.477097, 56.230568], [-130.413146, 56.122518], [-130.214705, 56.082835], [-130.097866, 56.10929], [-130.055958, 56.065235], [-130.022884, 56.014511], [-130.014073, 55.950538], [-130.025081, 55.888212], [-130.07464, 55.836027], [-130.111977, 55.779799], [-130.137065, 55.719385], [-130.146518, 55.654489], [-130.140421, 55.585034], [-130.120426, 55.524411], [-130.059474, 55.412307], [-130.039264, 55.343598], [-130.036551, 55.297917], [-130.171842, 55.137], [-130.218506, 55.060261], [-130.21409, 55.025895], [-130.312533, 54.945948], [-130.493242, 54.834173], [-130.575331, 54.769683], [-130.615794, 54.79092], [-130.849605, 54.807608], [-130.934612, 54.950397], [-130.9797, 55.061184], [-131.047859, 55.157665], [-131.045898, 55.179583], [-130.983935, 55.243963], [-130.750388, 55.296983], [-130.748218, 55.318022], [-130.835059, 55.332073], [-130.855961, 55.355123], [-130.879812, 55.459504], [-130.873401, 55.55113], [-130.879653, 55.611829], [-130.918566, 55.735975], [-130.977014, 55.811945], [-131.127675, 55.960151], [-131.140364, 55.997515], [-131.074012, 56.044383], [-131.032769, 56.088098], [-131.287586, 56.012083], [-131.635265, 55.932246], [-131.784201, 55.876534], [-131.815463, 55.85421], [-131.826158, 55.835357], [-131.799055, 55.782821], [-131.803295, 55.765946], [-131.833601, 55.734898], [-131.869411, 55.64715], [-131.945013, 55.554129], [-131.983411, 55.535013], [-132.119009, 55.569785], [-132.15544, 55.599558], [-132.223423, 55.721044], [-132.207532, 55.753388], [-132.157972, 55.780656], [-132.090692, 55.839543], [-132.005735, 55.93007], [-131.843835, 56.160091], [-131.738026, 56.161223], [-131.551346, 56.206805], [-131.844247, 56.229645], [-131.887912, 56.241632], [-131.927292, 56.272998], [-131.962328, 56.323699], [-132.021934, 56.38007], [-132.133275, 56.399835], [-132.182027, 56.420643], [-132.255591, 56.48911], [-132.304991, 56.51986], [-132.332018, 56.557895], [-132.336671, 56.603104], [-132.357654, 56.6259], [-132.434443, 56.634118], [-132.475939, 56.649664], [-132.487128, 56.766405], [-132.63952, 56.79643], [-132.701944, 56.82227], [-132.8022, 56.895153], [-132.829869, 56.930639], [-132.838812, 56.960192], [-132.814263, 57.0407], [-132.824601, 57.055795], [-132.913409, 57.047479], [-133.465851, 57.172174], [-133.436655, 57.336859], [-133.538948, 57.554157], [-133.648713, 57.642301], [-133.626954, 57.676534], [-133.603389, 57.694672], [-133.554219, 57.695079], [-133.342348, 57.631105], [-133.142825, 57.555146], [-133.117062, 57.566198], [-133.435726, 57.727049], [-133.515465, 57.775125], [-133.535202, 57.832957], [-133.536444, 57.863862], [-133.51112, 57.880111], [-133.212045, 57.865697], [-133.194318, 57.877705], [-133.497404, 57.92466], [-133.559361, 57.924451], [-133.62574, 57.856984], [-133.65726, 57.840988], [-133.722321, 57.844251], [-133.744129, 57.854611], [-133.821363, 57.936361], [-133.894482, 57.993259], [-134.031092, 58.072163], [-134.056723, 58.128391], [-134.063337, 58.211074], [-134.045248, 58.289263], [-133.933627, 58.467857], [-133.888517, 58.498751], [-133.876734, 58.518186], [-133.911149, 58.515241], [-133.943861, 58.498289], [-134.036157, 58.415354], [-134.13121, 58.279332], [-134.208829, 58.232959], [-134.257641, 58.244198], [-134.331458, 58.299591], [-134.485454, 58.367211], [-134.663608, 58.384702], [-134.776135, 58.45385], [-134.942507, 58.646286], [-134.964776, 58.742175], [-134.986123, 58.765642], [-135.076452, 58.796777], [-135.131851, 58.842865], [-135.217374, 59.076599], [-135.330313, 59.239076], [-135.358449, 59.324912], [-135.348946, 59.410067], [-135.363668, 59.419427], [-135.402532, 59.35307], [-135.412733, 59.318452], [-135.4841, 59.308685], [-135.416951, 59.241503], [-135.400153, 59.207907], [-135.433744, 59.210698], [-135.502315, 59.202304], [-135.386146, 59.087552], [-135.33406, 58.909607], [-135.257012, 58.77776], [-135.207091, 58.670885], [-135.184558, 58.589762], [-135.151928, 58.512187], [-135.062038, 58.340888], [-135.049711, 58.306776], [-135.060484, 58.278925], [-135.090251, 58.245845], [-135.141535, 58.233398], [-135.30254, 58.255931], [-135.363151, 58.298272], [-135.449943, 58.376132], [-135.571793, 58.412047], [-135.873455, 58.394216], [-135.897537, 58.400203], [-135.896351, 58.463825], [-135.861727, 58.57705], [-135.889556, 58.622731], [-136.04549, 58.78913], [-136.043112, 58.821628], [-135.826379, 58.897961], [-135.931694, 58.90374], [-136.016602, 58.873978], [-136.049368, 58.893204], [-136.100631, 58.999859], [-136.133699, 59.039553], [-136.150031, 59.048078], [-136.159484, 58.946795], [-136.123521, 58.893457], [-136.118407, 58.862607], [-136.124191, 58.819617], [-136.146828, 58.788812], [-136.186308, 58.77019], [-136.225842, 58.765455], [-136.299011, 58.7869], [-136.380249, 58.827286], [-136.451149, 58.846336], [-136.477605, 58.862508], [-136.511168, 58.907102], [-136.566209, 58.940896], [-136.830969, 58.983819], [-136.988996, 59.034488], [-137.002125, 59.021151], [-136.952824, 58.966944], [-136.948072, 58.934908], [-136.987909, 58.925141], [-137.059018, 58.873714], [-137.038402, 58.866639], [-136.963057, 58.883536], [-136.879078, 58.881525], [-136.740123, 58.850203], [-136.613928, 58.809279], [-136.568198, 58.78634], [-136.549334, 58.752381], [-136.533525, 58.740241], [-136.410116, 58.700658], [-136.404172, 58.679773], [-136.483757, 58.617667], [-136.31989, 58.624489], [-136.2246, 58.602264], [-136.102905, 58.506298], [-136.061486, 58.452707], [-136.055982, 58.384163], [-136.081251, 58.36419], [-136.129618, 58.350391], [-136.462388, 58.327968], [-136.582612, 58.245208], [-136.607419, 58.243989], [-136.698913, 58.266467], [-136.864999, 58.332407], [-137.071937, 58.395194], [-137.544004, 58.581181], [-137.556923, 58.589959], [-137.564625, 58.625885], [-137.597073, 58.644221], [-137.661101, 58.659931], [-137.749986, 58.707063], [-137.863695, 58.78556], [-137.934007, 58.846875], [-137.96088, 58.891007], [-138.026919, 58.941467], [-138.240704, 59.046837], [-138.352479, 59.087299], [-138.451337, 59.110085], [-138.53717, 59.115095], [-138.560321, 59.129157], [-138.520685, 59.152251], [-138.514898, 59.165896], [-138.704215, 59.18755], [-138.884333, 59.2369], [-139.340971, 59.375658], [-139.576823, 59.462439], [-139.714463, 59.503967], [-139.773272, 59.527302], [-139.799109, 59.546264], [-139.766063, 59.566084], [-139.674104, 59.586804], [-139.611628, 59.610315], [-139.513056, 59.698117], [-139.505588, 59.72633], [-139.558503, 59.790205], [-139.582173, 59.848311], [-139.581138, 59.880534], [-139.569149, 59.912362], [-139.554112, 59.933324], [-139.512306, 59.953549], [-139.483005, 59.963778], [-139.446882, 59.956856], [-139.330974, 59.877019], [-139.314643, 59.847927], [-139.320018, 59.738734], [-139.286713, 59.610941], [-139.276248, 59.620345], [-139.265602, 59.662609], [-139.25873, 59.743326], [-139.245706, 59.782086], [-139.2208, 59.819868], [-139.178863, 59.839863], [-139.048304, 59.828239], [-138.988074, 59.835007], [-139.242504, 59.892784], [-139.402492, 60.000988], [-139.431433, 60.012249], [-139.51892, 60.017116], [-139.611653, 59.973446], [-139.850193, 59.830711], [-139.91688, 59.805673], [-140.216733, 59.726638], [-140.419848, 59.710719], [-140.648386, 59.723177], [-140.843154, 59.748863], [-141.331911, 59.873767], [-141.408288, 59.902804], [-141.294626, 59.980005], [-141.289949, 60.004141], [-141.32956, 60.082815], [-141.362167, 60.105293], [-141.408727, 60.117674], [-141.421697, 60.108841], [-141.422164, 60.085506], [-141.409708, 60.042275], [-141.447073, 60.019434], [-141.530192, 59.994792], [-141.670158, 59.969875], [-142.104113, 60.033442], [-142.548606, 60.086045], [-142.945635, 60.096954], [-143.506119, 60.055041], [-143.805068, 60.012898], [-143.979501, 60.008789], [-144.147215, 60.016391], [-144.160937, 60.045824], [-144.084299, 60.063028], [-144.088537, 60.084342], [-144.185484, 60.150743], [-144.332632, 60.191008], [-144.529985, 60.205235], [-144.642949, 60.224648], [-144.671576, 60.249246], [-144.741392, 60.272702], [-144.85242, 60.295081], [-144.901331, 60.335182], [-144.862469, 60.459206], [-144.824437, 60.533617], [-144.786557, 60.584626], [-144.691138, 60.669111], [-144.724415, 60.66286], [-144.86309, 60.600897], [-144.984014, 60.536923], [-145.096022, 60.45368], [-145.162709, 60.415382], [-145.248287, 60.380138], [-145.381766, 60.388564], [-145.56315, 60.440705], [-145.718439, 60.467578], [-145.847732, 60.469226], [-145.898892, 60.478169], [-145.810628, 60.524674], [-145.759833, 60.561983], [-145.690223, 60.62198], [-145.674928, 60.651126], [-146.149032, 60.660695], [-146.16642, 60.692292], [-146.167093, 60.71555], [-146.182337, 60.734743], [-146.251042, 60.749058], [-146.347187, 60.738127], [-146.502989, 60.700796], [-146.570478, 60.729162], [-146.546399, 60.745125], [-146.495524, 60.756804], [-146.391989, 60.810868], [-146.53193, 60.838872], [-146.603552, 60.870963], [-146.638434, 60.897319], [-146.636056, 60.992527], [-146.599109, 61.053534], [-146.284889, 61.112651], [-146.384392, 61.135854], [-146.582728, 61.127845], [-146.715896, 61.077539], [-146.874028, 61.004908], [-146.980169, 60.977805], [-147.034326, 60.996174], [-147.105952, 61.002535], [-147.19504, 60.996844], [-147.254907, 60.978299], [-147.285603, 60.946768], [-147.321081, 60.92551], [-147.361387, 60.914502], [-147.390558, 60.918039], [-147.433424, 60.950284], [-147.523289, 60.970334], [-147.567265, 60.994933], [-147.592588, 60.979431], [-147.623284, 60.933025], [-147.655686, 60.909514], [-147.807613, 60.885377], [-147.891123, 60.88987], [-147.990755, 60.948274], [-148.00512, 60.968576], [-147.971169, 61.019069], [-147.751855, 61.218955], [-147.773791, 61.217812], [-147.844821, 61.186391], [-147.986363, 61.106499], [-148.049408, 61.08268], [-148.157928, 61.079681], [-148.208674, 61.088261], [-148.270014, 61.081801], [-148.34187, 61.060411], [-148.388792, 61.036944], [-148.410754, 61.011467], [-148.395846, 61.007127], [-148.287378, 61.036252], [-148.225882, 61.044052], [-148.208674, 61.029924], [-148.29314, 60.939693], [-148.344427, 60.853549], [-148.393313, 60.831895], [-148.471061, 60.83551], [-148.556147, 60.826985], [-148.557386, 60.802902], [-148.398688, 60.734018], [-148.341277, 60.724328], [-148.267896, 60.699708], [-148.256734, 60.675318], [-148.284252, 60.609323], [-148.305, 60.58333], [-148.338434, 60.569839], [-148.467779, 60.572069], [-148.509587, 60.565246], [-148.596635, 60.523795], [-148.640121, 60.48943], [-148.624282, 60.486441], [-148.549143, 60.514808], [-148.439824, 60.530002], [-148.29637, 60.532068], [-148.189476, 60.547108], [-148.119196, 60.575167], [-148.050699, 60.567213], [-147.984012, 60.523333], [-147.964088, 60.484892], [-147.990961, 60.451867], [-148.045997, 60.428302], [-148.129196, 60.414217], [-148.1817, 60.393057], [-148.203557, 60.364922], [-148.215857, 60.32314], [-148.218647, 60.267692], [-148.197617, 60.167772], [-148.213764, 60.154259], [-148.245003, 60.146821], [-148.291357, 60.145481], [-148.333111, 60.122014], [-148.430703, 59.989134], [-148.465092, 59.974687], [-148.506071, 59.988947], [-148.542401, 59.987398], [-148.574077, 59.970084], [-148.643582, 59.956856], [-148.750863, 59.94776], [-148.842745, 59.95122], [-149.004258, 59.979983], [-149.070121, 60.000241], [-149.121589, 60.033519], [-149.266595, 59.998275], [-149.304937, 60.013645], [-149.395269, 60.105732], [-149.414852, 60.100261], [-149.432216, 60.001043], [-149.45971, 59.966261], [-149.54916, 59.894333], [-149.598047, 59.770462], [-149.612878, 59.766848], [-149.629621, 59.784668], [-149.684657, 59.895311], [-149.713854, 59.919602], [-149.794779, 59.855826], [-149.803667, 59.832733], [-149.782455, 59.750335], [-149.801291, 59.737954], [-149.965001, 59.782295], [-150.00531, 59.784415], [-150.015953, 59.776977], [-149.960142, 59.713048], [-149.966525, 59.690053], [-150.198062, 59.566545], [-150.258471, 59.570962], [-150.296505, 59.583266], [-150.338157, 59.581322], [-150.48533, 59.535278], [-150.526001, 59.537299], [-150.581554, 59.564578], [-150.607391, 59.563392], [-150.621162, 59.535069], [-150.622893, 59.479621], [-150.677464, 59.426964], [-150.852776, 59.341853], [-150.899311, 59.302686], [-150.934503, 59.249095], [-150.960755, 59.243986], [-151.06359, 59.278396], [-151.182756, 59.300775], [-151.199241, 59.289668], [-151.163016, 59.25695], [-151.170715, 59.2369], [-151.222287, 59.229408], [-151.287505, 59.232297], [-151.366362, 59.245579], [-151.477003, 59.23055], [-151.619369, 59.187297], [-151.7382, 59.188527], [-151.903849, 59.259763], [-151.949505, 59.265069], [-151.964051, 59.285119], [-151.931702, 59.342732], [-151.884626, 59.386347], [-151.84995, 59.406353], [-151.692596, 59.462186], [-151.512711, 59.482697], [-151.39959, 59.516316], [-151.262132, 59.585617], [-151.189422, 59.637681], [-151.046484, 59.771803], [-151.057339, 59.782163], [-151.08943, 59.789425], [-151.403672, 59.662247], [-151.450105, 59.650415], [-151.512607, 59.651294], [-151.763831, 59.700029], [-151.816928, 59.720903], [-151.853205, 59.782086], [-151.783469, 59.921151], [-151.734506, 59.988332], [-151.611876, 60.092043], [-151.451473, 60.202653], [-151.395973, 60.27446], [-151.312672, 60.466435], [-151.317528, 60.553568], [-151.355046, 60.65986], [-151.356466, 60.722966], [-151.321791, 60.742906], [-150.953779, 60.841201], [-150.779472, 60.914809], [-150.44125, 61.023563], [-150.349138, 61.022629], [-150.281492, 60.985221], [-150.202789, 60.95525], [-150.113053, 60.932816], [-149.997556, 60.935145], [-149.856275, 60.96227], [-149.632464, 60.951987], [-149.172826, 60.880422], [-149.075081, 60.876412], [-149.07131, 60.885531], [-149.142235, 60.935683], [-149.459114, 60.964753], [-149.59249, 60.993823], [-149.967739, 61.121748], [-150.053265, 61.171098], [-150.018537, 61.194246], [-149.92676, 61.213264], [-149.89529, 61.23171], [-149.882008, 61.263702], [-149.829196, 61.307527], [-149.7369, 61.363337], [-149.595978, 61.41728], [-149.329071, 61.497381], [-149.433535, 61.500798], [-149.625436, 61.48601], [-149.695251, 61.470717], [-149.823744, 61.413358], [-149.873688, 61.372994], [-149.945209, 61.294244], [-149.975699, 61.279358], [-150.108919, 61.26791], [-150.471792, 61.259978], [-150.533208, 61.300243], [-150.567239, 61.306801], [-150.61225, 61.301143], [-150.945484, 61.198224], [-151.064985, 61.145731], [-151.150148, 61.085833], [-151.281872, 61.041954], [-151.46013, 61.014104], [-151.593507, 60.97964], [-151.733962, 60.910722], [-151.781659, 60.857944], [-151.784425, 60.833137], [-151.750474, 60.75487], [-151.785123, 60.740225], [-151.866177, 60.734073], [-151.996219, 60.68224], [-152.270726, 60.528112], [-152.306589, 60.472225], [-152.305064, 60.452999], [-152.260314, 60.409438], [-152.291526, 60.381126], [-152.368834, 60.336346], [-152.540916, 60.265418], [-152.653932, 60.238447], [-152.727313, 60.237074], [-152.797903, 60.247181], [-152.923372, 60.292862], [-153.02502, 60.295653], [-153.031274, 60.289237], [-152.892937, 60.24038], [-152.752375, 60.177495], [-152.664759, 60.125266], [-152.630109, 60.08377], [-152.628559, 60.041088], [-152.660107, 59.99722], [-152.759456, 59.920887], [-152.856919, 59.898101], [-153.10605, 59.875052], [-153.186355, 59.856859], [-153.211211, 59.842708], [-153.040085, 59.810507], [-153.024633, 59.793995], [-153.048147, 59.730055], [-153.093622, 59.709126], [-153.236172, 59.670937], [-153.363993, 59.659874], [-153.383474, 59.667213], [-153.359625, 59.717497], [-153.366448, 59.729846], [-153.414403, 59.740129], [-153.482615, 59.720958], [-153.652529, 59.647009], [-153.670717, 59.634814], [-153.609378, 59.615017], [-153.62227, 59.598482], [-153.714333, 59.545254], [-153.752598, 59.509856], [-153.814146, 59.473733], [-154.088316, 59.363298], [-154.067488, 59.336381], [-154.138803, 59.240152], [-154.178335, 59.15559], [-154.129811, 59.119852], [-153.89954, 59.078049], [-153.787919, 59.06792], [-153.656377, 59.038674], [-153.418279, 58.959968], [-153.338955, 58.908552], [-153.32707, 58.884316], [-153.334409, 58.857883], [-153.362932, 58.822199], [-153.437606, 58.754842], [-153.617337, 58.654713], [-153.698573, 58.626346], [-153.82151, 58.604121], [-153.861948, 58.58785], [-154.019896, 58.492972], [-154.062451, 58.441754], [-154.055733, 58.39716], [-154.085888, 58.365838], [-154.289028, 58.304348], [-154.28179, 58.293449], [-154.20805, 58.288791], [-154.235129, 58.234639], [-154.247013, 58.159427], [-154.282282, 58.146782], [-154.409226, 58.147309], [-154.570585, 58.118053], [-154.581953, 58.109791], [-154.584925, 58.055683], [-155.006863, 58.016044], [-155.099261, 57.913311], [-155.147373, 57.881814], [-155.312736, 57.807117], [-155.41397, 57.777037], [-155.529623, 57.758898], [-155.59024, 57.733608], [-155.595846, 57.701077], [-155.628687, 57.673073], [-155.72894, 57.626612], [-155.77798, 57.56822], [-155.813688, 57.559024], [-156.00019, 57.544962], [-156.037343, 57.526516], [-156.055379, 57.447579], [-156.089898, 57.445074], [-156.155992, 57.463443], [-156.242188, 57.449205], [-156.435872, 57.359963], [-156.478402, 57.327872], [-156.4737, 57.310711], [-156.443573, 57.29366], [-156.397631, 57.240585], [-156.400498, 57.204825], [-156.475145, 57.105201], [-156.50132, 57.089798], [-156.59204, 57.065101], [-156.628987, 57.009982], [-156.71265, 57.016058], [-156.779881, 57.005621], [-156.823859, 56.968828], [-156.87171, 56.947635], [-156.923439, 56.942076], [-156.988448, 56.912929], [-157.066687, 56.860195], [-157.139137, 56.826555], [-157.205774, 56.812064], [-157.270577, 56.808493], [-157.333567, 56.815887], [-157.390232, 56.809812], [-157.440566, 56.790333], [-157.489658, 56.759736], [-157.528726, 56.673186], [-157.578387, 56.634448], [-157.609753, 56.627702], [-157.673885, 56.633448], [-157.770724, 56.651685], [-157.86909, 56.645225], [-158.027868, 56.59215], [-158.078303, 56.552028], [-157.978259, 56.543162], [-157.928702, 56.531693], [-157.929993, 56.520476], [-157.982186, 56.509577], [-158.070964, 56.510346], [-158.124374, 56.501052], [-158.189383, 56.478156], [-158.3525, 56.453503], [-158.414408, 56.435837], [-158.537397, 56.335422], [-158.552152, 56.312713], [-158.536364, 56.30767], [-158.467323, 56.318272], [-158.38614, 56.301573], [-158.343974, 56.280336], [-158.316997, 56.254134], [-158.291416, 56.203652], [-158.275656, 56.196258], [-158.431849, 56.111455], [-158.47611, 56.075496], [-158.504688, 56.062104], [-158.523343, 56.072442], [-158.542668, 56.166826], [-158.55445, 56.182855], [-158.591167, 56.184525], [-158.626746, 56.154708], [-158.704881, 56.04312], [-158.789863, 55.986914], [-159.429435, 55.84274], [-159.52323, 55.810001], [-159.541314, 55.748488], [-159.567621, 55.695205], [-159.610072, 55.652808], [-159.659653, 55.625903], [-159.670274, 55.64503], [-159.665339, 55.794894], [-159.678489, 55.824656], [-159.743034, 55.843773], [-159.771379, 55.841114], [-159.810421, 55.83272], [-159.87437, 55.800289], [-159.913542, 55.792203], [-159.962299, 55.794894], [-160.045652, 55.762924], [-160.243804, 55.660532], [-160.373204, 55.635109], [-160.407413, 55.613818], [-160.462682, 55.557799], [-160.499319, 55.537287], [-160.553501, 55.535496], [-160.625231, 55.552371], [-160.682898, 55.540429], [-160.726514, 55.499659], [-160.770827, 55.483542], [-160.896736, 55.513612], [-160.952184, 55.493045], [-161.024221, 55.440443], [-161.099516, 55.405715], [-161.178013, 55.388873], [-161.381926, 55.371295], [-161.46386, 55.382512], [-161.480526, 55.397805], [-161.476701, 55.464887], [-161.44381, 55.513304], [-161.413346, 55.536144], [-161.372728, 55.556304], [-161.3133, 55.558622], [-161.202092, 55.543538], [-161.214702, 55.559765], [-161.255113, 55.57898], [-161.357458, 55.612192], [-161.45877, 55.629133], [-161.516958, 55.61841], [-161.598761, 55.592834], [-161.654313, 55.563358], [-161.683563, 55.529948], [-161.720382, 55.420722], [-161.741569, 55.391136], [-161.980339, 55.198644], [-162.073977, 55.139318], [-162.166582, 55.143768], [-162.211489, 55.121334], [-162.274637, 55.073225], [-162.332928, 55.05023], [-162.386361, 55.052351], [-162.42791, 55.061502], [-162.457495, 55.077696], [-162.452378, 55.092813], [-162.412536, 55.106865], [-162.426824, 55.145416], [-162.495244, 55.208466], [-162.541882, 55.242722], [-162.630378, 55.246655], [-162.64415, 55.218002], [-162.614307, 55.071467], [-162.618906, 55.038453], [-162.674354, 54.996595], [-162.819566, 54.94998], [-162.865041, 54.954528], [-162.995885, 55.046462], [-163.119624, 55.064699], [-163.127815, 55.034783], [-163.10022, 54.973644], [-163.131123, 54.916548], [-163.220575, 54.863375], [-163.288632, 54.837579], [-163.335296, 54.839183], [-163.33788, 54.876393], [-163.296333, 54.949255], [-163.285687, 55.009976], [-163.305944, 55.058547], [-163.303644, 55.095867], [-163.278813, 55.121828], [-163.114483, 55.193942], [-163.045339, 55.20472], [-163.008235, 55.186867], [-162.961986, 55.183813], [-162.906588, 55.195546], [-162.871604, 55.218596], [-162.857133, 55.253005], [-162.786235, 55.297093], [-162.658981, 55.350783], [-162.513356, 55.450001], [-162.349362, 55.594746], [-162.157124, 55.71944], [-161.936622, 55.824195], [-161.697334, 55.907208], [-161.21563, 56.021411], [-161.178606, 56.014467], [-161.222582, 55.977432], [-161.192507, 55.954306], [-161.145145, 55.95134], [-160.968644, 55.96961], [-160.898647, 55.993637], [-160.877823, 55.970489], [-160.902369, 55.941287], [-161.008409, 55.911734], [-161.005385, 55.887158], [-160.851313, 55.771889], [-160.802841, 55.754432], [-160.762584, 55.756596], [-160.745506, 55.771483], [-160.758399, 55.854627], [-160.706334, 55.870436], [-160.599726, 55.874315], [-160.530248, 55.86346], [-160.497899, 55.837884], [-160.436919, 55.816691], [-160.347315, 55.799926], [-160.291708, 55.805068], [-160.270109, 55.832204], [-160.308506, 55.864471], [-160.479865, 55.935454], [-160.527458, 55.965062], [-160.539059, 56.006293], [-160.514719, 56.059116], [-160.460848, 56.137503], [-160.377492, 56.241478], [-160.302046, 56.31413], [-160.149289, 56.396352], [-160.046246, 56.437023], [-159.785073, 56.561608], [-159.283089, 56.688577], [-159.159039, 56.770074], [-158.990393, 56.860041], [-158.918021, 56.882156], [-158.918021, 56.84744], [-158.894895, 56.816425], [-158.782087, 56.79576], [-158.708836, 56.788575], [-158.675168, 56.794881], [-158.665918, 56.827928], [-158.681032, 56.887738], [-158.684803, 56.944229], [-158.677234, 56.99737], [-158.660801, 57.039415], [-158.585613, 57.114089], [-158.473734, 57.19909], [-158.320925, 57.297901], [-158.224498, 57.342648], [-158.133548, 57.366423], [-158.045696, 57.409467], [-157.894337, 57.511376], [-157.845761, 57.528065], [-157.737188, 57.54817], [-157.697396, 57.539282], [-157.674039, 57.513695], [-157.645541, 57.497808], [-157.535287, 57.483471], [-157.46191, 57.506202], [-157.473896, 57.518199], [-157.53348, 57.525889], [-157.571616, 57.540677], [-157.607583, 57.601442], [-157.68068, 57.638082], [-157.697215, 57.679423], [-157.683987, 57.743913], [-157.621173, 57.895228], [-157.610865, 58.050827], [-157.55503, 58.13997], [-157.442683, 58.172182], [-157.193706, 58.194177], [-157.339385, 58.23453], [-157.393591, 58.234815], [-157.488392, 58.253701], [-157.524438, 58.350754], [-157.523609, 58.421341], [-157.460899, 58.503013], [-157.228846, 58.640914], [-156.974649, 58.736341], [-157.009042, 58.744163], [-157.040485, 58.772541], [-156.923233, 58.963692], [-156.808899, 59.134277], [-156.963361, 58.988851], [-157.142032, 58.877647], [-157.66572, 58.748503], [-158.021927, 58.640189], [-158.190935, 58.61425], [-158.302578, 58.641793], [-158.389628, 58.745669], [-158.439314, 58.782616], [-158.503188, 58.850357], [-158.476266, 58.938369], [-158.425622, 58.999288], [-158.314493, 59.009318], [-158.189226, 58.979941], [-158.080528, 58.977436], [-158.220595, 59.037487], [-158.422807, 59.089826], [-158.514427, 59.07283], [-158.584476, 58.987796], [-158.678266, 58.929371], [-158.760587, 58.950124], [-158.809473, 58.973866], [-158.77555, 58.902553], [-158.837741, 58.793953], [-158.861381, 58.718763], [-158.772112, 58.520328], [-158.788624, 58.440952], [-158.950705, 58.404554], [-159.082687, 58.469769], [-159.358227, 58.721279], [-159.454214, 58.792899], [-159.670274, 58.911134], [-159.741433, 58.894292], [-159.832202, 58.835965], [-159.920208, 58.81987], [-160.152596, 58.905915], [-160.260809, 58.971547], [-160.363124, 59.051176], [-160.519913, 59.007308], [-160.656649, 58.955057], [-160.817079, 58.871704], [-160.924278, 58.872429], [-161.215916, 58.800963], [-161.246845, 58.799458], [-161.287875, 58.760961], [-161.328106, 58.743702], [-161.361334, 58.669544], [-161.755444, 58.612031], [-162.14493, 58.644221], [-162.008684, 58.685002], [-161.856471, 58.717093], [-161.724387, 58.794294], [-161.780534, 58.897412], [-161.790274, 58.94997], [-161.788672, 59.016394], [-161.644391, 59.109679], [-161.79446, 59.10947], [-161.89076, 59.076082], [-161.981037, 59.146153], [-162.02331, 59.283977], [-161.920137, 59.365473], [-161.872232, 59.42826], [-161.831693, 59.514503], [-161.828695, 59.588617], [-161.908638, 59.714135], [-162.138135, 59.980037], [-162.242495, 60.178319], [-162.421347, 60.283974], [-162.287789, 60.456877], [-162.138883, 60.614333], [-161.946595, 60.684821], [-161.961995, 60.695335], [-162.068267, 60.694874], [-162.13803, 60.685547], [-162.199913, 60.634306], [-162.265025, 60.595217], [-162.468708, 60.394683], [-162.599683, 60.296993], [-162.684974, 60.268956], [-162.547721, 60.231053], [-162.526948, 60.199116], [-162.500488, 60.126562], [-162.535654, 60.038408], [-162.570743, 59.989727], [-162.73262, 59.99365], [-162.877856, 59.922755], [-163.219386, 59.845598], [-163.680391, 59.801521], [-163.906889, 59.806794], [-164.142844, 59.896761], [-164.141113, 59.948902], [-164.131527, 59.994221], [-164.470498, 60.149304], [-164.66227, 60.303816], [-164.799961, 60.307221], [-164.919747, 60.348464], [-165.061134, 60.412536], [-165.048732, 60.464238], [-165.02651, 60.500647], [-165.113275, 60.526069], [-165.224509, 60.523564], [-165.353829, 60.541219], [-165.015995, 60.740017], [-164.8998, 60.873127], [-164.805155, 60.892046], [-164.682372, 60.871534], [-164.512924, 60.81903], [-164.370065, 60.795904], [-164.318517, 60.771273], [-164.265652, 60.724669], [-164.321412, 60.646633], [-164.372339, 60.591855], [-164.309681, 60.60672], [-164.131836, 60.69149], [-163.99957, 60.766054], [-163.936138, 60.758309], [-163.894925, 60.74518], [-163.82139, 60.668287], [-163.73, 60.589976], [-163.528695, 60.664563], [-163.420949, 60.75743], [-163.511875, 60.798145], [-163.62303, 60.822227], [-163.906527, 60.853802], [-163.837306, 60.880422], [-163.655432, 60.877478], [-163.586909, 60.902977], [-163.65892, 60.938221], [-163.749017, 60.969719], [-163.99461, 60.864712], [-164.44156, 60.869985], [-164.75397, 60.931322], [-165.065604, 60.920676], [-165.114825, 60.932816], [-165.175468, 60.965687], [-164.999923, 61.043668], [-164.875564, 61.086767], [-164.868975, 61.11175], [-164.941193, 61.11487], [-165.077076, 61.094205], [-165.137718, 61.130119], [-165.12777, 61.192445], [-165.150043, 61.186864], [-165.203761, 61.152828], [-165.279803, 61.169648], [-165.344889, 61.197707], [-165.310809, 61.227634], [-165.243939, 61.268767], [-165.273653, 61.274864], [-165.333676, 61.26613], [-165.392043, 61.212308], [-165.37928, 61.168769], [-165.380778, 61.106301], [-165.480463, 61.094875], [-165.565883, 61.102368], [-165.627585, 61.16521], [-165.69138, 61.299924], [-165.863953, 61.335684], [-165.906276, 61.4038], [-165.797109, 61.491185], [-165.845324, 61.53624], [-165.961311, 61.550874], [-166.09399, 61.506742], [-166.15272, 61.545963], [-166.163521, 61.589007], [-166.168094, 61.650816], [-166.131172, 61.65732], [-166.100502, 61.64507], [-165.834575, 61.679392], [-165.808918, 61.69608], [-166.019938, 61.748276], [-166.078823, 61.803098], [-165.991387, 61.834189], [-165.833852, 61.836793], [-165.612805, 61.869301], [-165.705798, 61.92743], [-165.725253, 61.959367], [-165.743934, 62.011695], [-165.70727, 62.100443], [-165.447648, 62.303899], [-165.194511, 62.473528], [-165.115601, 62.512672], [-164.999716, 62.53381], [-164.891867, 62.517583], [-164.779214, 62.481152], [-164.757871, 62.496731], [-164.796111, 62.511639], [-164.844402, 62.58104], [-164.687978, 62.608275], [-164.596305, 62.686695], [-164.589432, 62.709349], [-164.688986, 62.676764], [-164.792701, 62.623205], [-164.818668, 62.677049], [-164.84541, 62.800975], [-164.799651, 62.918067], [-164.764072, 62.970626], [-164.677462, 63.020471], [-164.428123, 63.040444], [-164.38425, 63.030468], [-164.375077, 63.053979], [-164.525197, 63.127621], [-164.463289, 63.185211], [-164.409055, 63.215061], [-164.1076, 63.26172], [-163.942856, 63.247196], [-163.736228, 63.192813], [-163.616312, 63.125171], [-163.633753, 63.09041], [-163.663571, 63.070316], [-163.725737, 63.047783], [-163.748991, 63.030337], [-163.737855, 63.016417], [-163.649359, 63.05677], [-163.504356, 63.105868], [-163.423172, 63.084521], [-163.358835, 63.045761], [-163.287857, 63.046432], [-163.062237, 63.07972], [-162.947723, 63.115008], [-162.807757, 63.206579], [-162.621489, 63.265807], [-162.3598, 63.452585], [-162.282803, 63.529193], [-162.193298, 63.540981], [-162.112476, 63.534181], [-162.056227, 63.471317], [-161.973984, 63.452948], [-161.505433, 63.468164], [-161.266016, 63.496981], [-161.099722, 63.557933], [-160.926709, 63.660556], [-160.826508, 63.729342], [-160.778553, 63.818946], [-160.840461, 63.934907], [-160.90397, 64.03118], [-160.987532, 64.251269], [-161.220102, 64.396564], [-161.385674, 64.439938], [-161.490706, 64.433763], [-161.414612, 64.526367], [-161.193048, 64.516424], [-161.048795, 64.534464], [-160.931952, 64.579112], [-160.893714, 64.612906], [-160.836017, 64.681944], [-160.855911, 64.755608], [-160.886969, 64.795554], [-160.967482, 64.839554], [-161.063239, 64.904], [-161.130184, 64.925445], [-161.186901, 64.92405], [-161.466366, 64.794862], [-161.634005, 64.792478], [-161.759371, 64.816252], [-161.868331, 64.742666], [-162.172266, 64.678066], [-162.334633, 64.612851], [-162.635726, 64.450847], [-162.71107, 64.377513], [-162.807008, 64.374206], [-162.876435, 64.516424], [-163.203883, 64.652018], [-163.302843, 64.605897], [-163.248299, 64.563292], [-163.174092, 64.532959], [-163.051748, 64.519731], [-163.104508, 64.478598], [-163.144352, 64.423821], [-163.267057, 64.475182], [-163.486191, 64.549812], [-163.713103, 64.588253], [-164.303971, 64.583913], [-164.691828, 64.507438], [-164.727484, 64.523302], [-164.764924, 64.529652], [-164.82952, 64.511382], [-164.85727, 64.480301], [-164.899491, 64.460669], [-164.978761, 64.453659], [-165.138158, 64.465217], [-165.446174, 64.512854], [-166.142774, 64.582782], [-166.325114, 64.625716], [-166.481383, 64.728087], [-166.478101, 64.797543], [-166.408674, 64.826953], [-166.415237, 64.926533], [-166.550862, 64.952988], [-166.826943, 65.096074], [-166.92841, 65.157059], [-166.906396, 65.163827], [-166.856786, 65.147292], [-166.762529, 65.134911], [-166.531018, 65.15473], [-166.451643, 65.247334], [-166.279665, 65.273789], [-166.121482, 65.260715], [-166.157037, 65.28583], [-166.197395, 65.305572], [-166.609385, 65.352759], [-166.665377, 65.33829], [-167.403988, 65.422104], [-167.987234, 65.567783], [-168.035009, 65.595611], [-168.088364, 65.65775], [-168.009687, 65.719142], [-167.930571, 65.748157], [-167.926979, 65.714341], [-167.91437, 65.681184], [-167.58005, 65.758308], [-167.405306, 65.859338], [-167.074215, 65.877059], [-166.997217, 65.904942], [-166.894458, 65.959182], [-166.747671, 66.05183], [-166.540113, 66.100642], [-166.398726, 66.144433], [-166.214577, 66.170273], [-166.057404, 66.127229], [-166.008931, 66.12134], [-165.723677, 66.112551], [-165.629911, 66.131206], [-165.589991, 66.145115], [-165.560225, 66.167076], [-165.840259, 66.245057], [-165.811863, 66.288464], [-165.776154, 66.31905], [-165.449404, 66.409896], [-165.198309, 66.439922], [-165.06395, 66.437834], [-164.674129, 66.555004], [-164.460499, 66.588446], [-164.058276, 66.61077], [-163.727675, 66.61645], [-163.638223, 66.574669], [-163.815706, 66.58348], [-163.89397, 66.575889], [-163.838237, 66.561573], [-163.775477, 66.531108], [-163.793718, 66.492634], [-163.902859, 66.378376], [-163.89397, 66.286915], [-163.964973, 66.257296], [-164.033754, 66.215548], [-163.695378, 66.083822], [-163.171456, 66.07545], [-162.886486, 66.099225], [-162.721768, 66.059795], [-162.586866, 66.050852], [-162.214279, 66.071056], [-161.933676, 66.042898], [-161.816319, 66.053642], [-161.556852, 66.250528], [-161.455411, 66.281411], [-161.345081, 66.247167], [-161.201084, 66.219371], [-161.109231, 66.23952], [-161.034301, 66.188807], [-161.069542, 66.294639], [-161.120291, 66.334321], [-161.544424, 66.407029], [-161.828153, 66.370829], [-161.916907, 66.411841], [-161.88758, 66.493074], [-162.191179, 66.693135], [-162.317735, 66.733707], [-162.467442, 66.735641], [-162.543639, 66.805118], [-162.607433, 66.894393], [-162.478319, 66.930802], [-162.361609, 66.947314], [-162.253553, 66.918629], [-162.131416, 66.80135], [-162.01765, 66.784112], [-162.050723, 66.667273], [-161.909596, 66.559607], [-161.591036, 66.45951], [-161.335935, 66.496359], [-161.155791, 66.495293], [-161.048122, 66.474232], [-160.784494, 66.384375], [-160.650549, 66.373103], [-160.231711, 66.420289], [-160.227322, 66.50852], [-160.262564, 66.57245], [-160.360878, 66.612528], [-160.643781, 66.60498], [-160.864024, 66.670865], [-161.051456, 66.652782], [-161.39805, 66.55185], [-161.571734, 66.591599], [-161.680901, 66.64552], [-161.856679, 66.70032], [-161.878745, 66.803932], [-161.731311, 66.922793], [-161.622196, 66.979318], [-161.719943, 67.02056], [-161.965431, 67.049553], [-162.391529, 67.01989], [-162.41158, 67.060298], [-162.409409, 67.103968], [-162.583119, 67.018495], [-162.761403, 67.036424], [-163.001698, 67.027284], [-163.531822, 67.102573], [-163.72057, 67.195539], [-163.799789, 67.270983], [-163.942701, 67.477591], [-164.12517, 67.606725], [-165.386023, 68.045585], [-165.959581, 68.155887], [-166.235946, 68.277956], [-166.409114, 68.307971], [-166.574479, 68.320254], [-166.7863, 68.359596], [-166.643905, 68.408024], [-166.5459, 68.424349], [-166.647859, 68.373812], [-166.570396, 68.361068], [-166.447044, 68.390248], [-166.380537, 68.425129], [-166.282945, 68.573236], [-166.182047, 68.797192], [-166.209075, 68.885358], [-165.509479, 68.867582], [-165.043951, 68.882457], [-164.889698, 68.902463], [-164.302368, 68.936488], [-164.150182, 68.961163], [-163.867925, 69.036661], [-163.535671, 69.17009], [-163.250547, 69.345377], [-163.205201, 69.392509], [-163.187113, 69.380468], [-163.161456, 69.38796], [-163.131018, 69.454362], [-163.093554, 69.610708], [-162.952116, 69.758123], [-162.350395, 70.094117], [-162.071162, 70.227184], [-161.977963, 70.287653], [-161.880967, 70.331752], [-161.812599, 70.289839], [-161.779939, 70.277369], [-161.761077, 70.257649], [-161.818386, 70.24842], [-161.911947, 70.205486], [-162.042378, 70.176647], [-162.073874, 70.161969], [-161.997393, 70.165232], [-161.768156, 70.196543], [-161.638991, 70.234523], [-160.996266, 70.304594], [-160.647656, 70.420565], [-160.634119, 70.446394], [-160.117146, 70.591194], [-160.045625, 70.585613], [-159.96315, 70.568145], [-160.106396, 70.472574], [-160.005552, 70.447537], [-160.09508, 70.333279], [-159.907546, 70.331466], [-159.865688, 70.278842], [-159.855224, 70.324182], [-159.857522, 70.389243], [-159.842641, 70.453008], [-159.814994, 70.497096], [-159.683296, 70.477167], [-159.386753, 70.524529], [-159.746214, 70.53045], [-159.961832, 70.634063], [-160.081594, 70.634865], [-159.680895, 70.786794], [-159.314507, 70.878519], [-159.231722, 70.876762], [-159.191723, 70.859656], [-159.183171, 70.831959], [-159.262212, 70.813843], [-159.339855, 70.781257], [-159.304147, 70.752528], [-159.251154, 70.748452], [-159.075065, 70.772062], [-158.996285, 70.801593], [-158.620934, 70.799033], [-158.510835, 70.820127], [-158.484377, 70.841056], [-157.998465, 70.845286], [-157.909374, 70.860117], [-157.605622, 70.941251], [-157.324734, 71.039623], [-157.19531, 71.09328], [-156.973358, 71.230016], [-156.783292, 71.31895], [-156.470237, 71.407687], [-156.395255, 71.396679], [-156.496695, 71.379078], [-156.567232, 71.341538], [-156.469979, 71.291561], [-155.811156, 71.188422], [-155.645584, 71.182786], [-155.579438, 71.121086], [-155.634578, 71.061585], [-155.804333, 70.995436], [-156.146588, 70.927815], [-156.041943, 70.902239], [-155.973523, 70.841979], [-155.872237, 70.83464], [-155.708036, 70.857283], [-155.579386, 70.894329], [-155.313382, 71.014991], [-155.229718, 71.082228], [-155.166855, 71.099224], [-154.943818, 71.083052], [-154.817522, 71.048478], [-154.673681, 70.987086], [-154.726314, 70.92776], [-154.785222, 70.894307], [-154.59862, 70.847977], [-154.392198, 70.838309], [-154.195235, 70.80111], [-153.918223, 70.877333], [-153.701363, 70.893604], [-153.497704, 70.891077], [-153.232915, 70.932572], [-152.784906, 70.876036], [-152.670829, 70.890714], [-152.49123, 70.880947], [-152.300414, 70.846791], [-152.232925, 70.81036], [-152.437255, 70.733258], [-152.470584, 70.653618], [-152.399192, 70.620472], [-152.269666, 70.61476], [-152.253363, 70.568254], [-152.172929, 70.556653], [-151.769025, 70.560136], [-151.799927, 70.53802], [-151.819617, 70.511301], [-151.944674, 70.452107], [-151.22482, 70.418752], [-151.12803, 70.451613], [-150.979075, 70.464686], [-150.662633, 70.509906], [-150.543519, 70.490142], [-150.403218, 70.443922], [-150.273637, 70.434309], [-150.15251, 70.443713], [-149.870098, 70.509653], [-149.544046, 70.512905], [-149.410617, 70.491405], [-149.269437, 70.500765], [-148.844785, 70.425212], [-148.688359, 70.416324], [-148.479199, 70.317931], [-148.371146, 70.314987], [-148.248774, 70.356735], [-148.142734, 70.355449], [-148.039073, 70.315503], [-147.869521, 70.303253], [-147.790587, 70.240159], [-147.705347, 70.217208], [-147.062929, 70.170396], [-146.744886, 70.191742], [-146.281247, 70.186161], [-146.057669, 70.156234], [-145.823136, 70.160057], [-145.440084, 70.050919], [-145.236815, 70.033945], [-145.197385, 70.008699], [-144.619177, 69.982134], [-144.416891, 70.039032], [-144.064096, 70.054127], [-143.746415, 70.101973], [-143.566426, 70.101478], [-143.357032, 70.089569], [-143.276442, 70.095304], [-143.218332, 70.116233], [-142.707872, 70.033813], [-142.422128, 69.939507], [-142.296994, 69.869897], [-141.699201, 69.770372], [-141.526369, 69.714716], [-141.407901, 69.653368], [-141.338629, 69.646754], [-141.289666, 69.664684], [-141.080816, 69.659421], [-141.002137, 69.650786], [-141.002137, 69.358583], [-141.002137, 69.066379], [-141.002137, 68.774176], [-141.002137, 68.481973], [-141.002137, 68.189736], [-141.002137, 67.897566], [-141.002137, 67.605351], [-141.002137, 67.313148], [-141.002137, 67.020945], [-141.002137, 66.728741], [-141.002137, 66.436538], [-141.002137, 66.144335], [-141.002137, 65.852131], [-141.002137, 65.559928], [-141.002137, 65.267724], [-141.002137, 64.975521], [-141.002137, 64.683318], [-141.002137, 64.391103], [-141.002137, 64.098878], [-141.002137, 63.806697], [-141.002137, 63.514471], [-141.002137, 63.22229], [-141.002137, 62.930086], [-141.002137, 62.637883], [-141.002137, 62.34568], [-141.002137, 62.053476], [-141.002137, 61.761273], [-141.002137, 61.469069], [-141.002137, 61.176855], [-141.002137, 60.884652], [-141.002137, 60.592448], [-141.002137, 60.300245], [-140.762745, 60.259112], [-140.525421, 60.218342], [-140.452818, 60.299729], [-140.196916, 60.237491], [-139.973284, 60.183153], [-139.830659, 60.252883], [-139.676302, 60.328337], [-139.467993, 60.333709], [-139.234777, 60.33973], [-139.079258, 60.343707], [-139.079258, 60.279448], [-139.13698, 60.172705], [-139.185169, 60.083573], [-139.056519, 60.001582]]], [[[-166.109856, 66.227457], [-166.148639, 66.221821], [-166.146468, 66.237169], [-166.032522, 66.277709], [-165.822198, 66.328092], [-165.829872, 66.317139], [-165.942295, 66.278181], [-166.109856, 66.227457]]], [[[-171.463043, 63.640023], [-171.447849, 63.615677], [-171.343361, 63.619632], [-171.196909, 63.609118], [-171.034879, 63.585498], [-170.874629, 63.594001], [-170.672522, 63.668829], [-170.551832, 63.688462], [-170.430419, 63.698855], [-170.299367, 63.680606], [-170.171312, 63.640924], [-170.121832, 63.617512], [-170.082404, 63.576665], [-170.056281, 63.527182], [-170.017369, 63.491729], [-169.777436, 63.448015], [-169.62411, 63.430547], [-169.587188, 63.406596], [-169.554528, 63.373495], [-169.427586, 63.348325], [-169.295062, 63.357531], [-169.221086, 63.348589], [-168.996036, 63.347292], [-168.716001, 63.310609], [-168.761347, 63.213764], [-168.852376, 63.171236], [-169.109052, 63.184925], [-169.36472, 63.171126], [-169.470839, 63.12126], [-169.559283, 63.05822], [-169.571298, 62.996773], [-169.622872, 62.968561], [-169.676356, 62.956102], [-169.719815, 62.990105], [-169.777797, 63.09375], [-169.818596, 63.122347], [-169.863426, 63.140387], [-169.988482, 63.173126], [-170.1154, 63.193868], [-170.189607, 63.196351], [-170.243091, 63.232287], [-170.272702, 63.284275], [-170.323526, 63.311125], [-170.424165, 63.349259], [-170.527104, 63.379284], [-170.848377, 63.444367], [-170.95403, 63.452948], [-171.061232, 63.445895], [-171.176006, 63.416209], [-171.287292, 63.372154], [-171.401186, 63.339239], [-171.519137, 63.331999], [-171.631818, 63.351203], [-171.737858, 63.394215], [-171.790982, 63.424713], [-171.819404, 63.47726], [-171.81793, 63.529819], [-171.80354, 63.58051], [-171.746385, 63.703084], [-171.646468, 63.726991], [-171.463043, 63.640023]]], [[[-147.930706, 60.826161], [-148.057417, 60.817943], [-148.115425, 60.830599], [-148.123797, 60.844354], [-148.099687, 60.894836], [-148.101678, 60.916128], [-148.03773, 60.924137], [-147.964399, 60.900164], [-147.94311, 60.875379], [-147.930706, 60.826161]]], [[[-172.742214, 60.457393], [-172.526053, 60.391761], [-172.387508, 60.398485], [-172.277541, 60.343652], [-172.232066, 60.299135], [-172.397172, 60.331128], [-172.635736, 60.328853], [-172.958378, 60.462766], [-173.07403, 60.493209], [-173.047649, 60.568289], [-172.923884, 60.60684], [-172.860219, 60.505689], [-172.742214, 60.457393]]], [[[-152.020741, 60.361746], [-152.069034, 60.358077], [-152.004514, 60.407395], [-151.959736, 60.503745], [-151.899405, 60.490363], [-151.887287, 60.472686], [-151.986892, 60.373985], [-152.020741, 60.361746]]], [[[-147.658268, 60.450472], [-147.658682, 60.424138], [-147.690048, 60.398902], [-147.659973, 60.352496], [-147.712013, 60.272757], [-147.732115, 60.222066], [-147.759916, 60.190228], [-147.787821, 60.177934], [-147.815831, 60.185163], [-147.82167, 60.20273], [-147.805287, 60.230636], [-147.871356, 60.229757], [-147.891433, 60.299421], [-147.854898, 60.321438], [-147.841695, 60.351255], [-147.837611, 60.371305], [-147.794539, 60.459876], [-147.779139, 60.466073], [-147.774179, 60.44499], [-147.760226, 60.438794], [-147.737281, 60.447418], [-147.702968, 60.486804], [-147.688576, 60.491396], [-147.658268, 60.450472]]], [[[-146.393928, 60.449648], [-146.371681, 60.422149], [-146.179546, 60.428763], [-146.124255, 60.423907], [-146.102238, 60.411196], [-146.128284, 60.392541], [-146.202389, 60.367998], [-146.419172, 60.32503], [-146.595335, 60.26844], [-146.618332, 60.273691], [-146.650448, 60.335643], [-146.683006, 60.360714], [-146.702874, 60.395595], [-146.702564, 60.408559], [-146.67024, 60.432641], [-146.605928, 60.46783], [-146.560299, 60.480542], [-146.393928, 60.449648]]], [[[-145.118528, 60.337093], [-145.150462, 60.312649], [-145.237641, 60.321328], [-145.284254, 60.336829], [-145.128138, 60.401121], [-145.10243, 60.388256], [-145.118528, 60.337093]]], [[[-166.135435, 60.383554], [-166.043632, 60.33394], [-165.994926, 60.33115], [-165.840931, 60.346245], [-165.784449, 60.335599], [-165.729697, 60.314198], [-165.695824, 60.281535], [-165.689364, 60.224132], [-165.714401, 60.172869], [-165.706934, 60.100568], [-165.712335, 60.069356], [-165.630583, 60.028377], [-165.605028, 59.97283], [-165.5918, 59.913142], [-165.769307, 59.893191], [-165.946739, 59.890037], [-166.099831, 59.84963], [-166.131198, 59.819758], [-166.106677, 59.77545], [-166.148716, 59.764134], [-166.187551, 59.773824], [-166.261603, 59.814902], [-166.342968, 59.834436], [-166.627654, 59.86467], [-166.985047, 59.983883], [-167.138863, 60.008536], [-167.295106, 60.095713], [-167.436415, 60.206663], [-167.344354, 60.224461], [-167.251724, 60.233536], [-166.836323, 60.217002], [-166.784387, 60.296422], [-166.730954, 60.316263], [-166.598973, 60.338741], [-166.475699, 60.382774], [-166.420379, 60.381687], [-166.363871, 60.364735], [-166.246953, 60.391146], [-166.184942, 60.396782], [-166.135435, 60.383554]]], [[[-147.735886, 59.813254], [-147.846318, 59.798829], [-147.872468, 59.828393], [-147.814331, 59.90198], [-147.768081, 59.943728], [-147.733664, 59.953604], [-147.606695, 60.03665], [-147.465825, 60.097009], [-147.33653, 60.185372], [-147.205246, 60.311308], [-147.180881, 60.358253], [-147.120006, 60.363087], [-147.019857, 60.332237], [-146.957873, 60.288874], [-146.986734, 60.254355], [-147.318471, 60.0753], [-147.346349, 60.051943], [-147.376529, 59.991167], [-147.403813, 59.969952], [-147.447583, 59.960273], [-147.479416, 59.933708], [-147.499312, 59.890191], [-147.540214, 59.867504], [-147.60207, 59.865593], [-147.644936, 59.853607], [-147.668759, 59.831546], [-147.735886, 59.813254]]], [[[-148.021761, 60.065324], [-148.07416, 60.034705], [-148.271873, 60.053261], [-148.230688, 60.113543], [-148.079588, 60.151655], [-147.914197, 60.092351], [-148.021761, 60.065324]]], [[[-144.565641, 59.818418], [-144.613596, 59.812628], [-144.541559, 59.878205], [-144.444926, 59.950704], [-144.353973, 59.996187], [-144.235738, 60.015205], [-144.248968, 59.982125], [-144.403246, 59.921096], [-144.565641, 59.818418]]], [[[-160.918983, 58.577094], [-160.992388, 58.561054], [-161.07024, 58.56914], [-161.131503, 58.668204], [-161.08458, 58.67128], [-160.986241, 58.736418], [-160.768605, 58.789229], [-160.715145, 58.795228], [-160.918983, 58.577094]]], [[[-152.486089, 58.485007], [-152.515518, 58.478602], [-152.588613, 58.509243], [-152.636621, 58.541696], [-152.604892, 58.566405], [-152.463169, 58.618491], [-152.395526, 58.61937], [-152.367928, 58.611097], [-152.356846, 58.59498], [-152.36227, 58.570843], [-152.392812, 58.540872], [-152.486089, 58.485007]]], [[[-152.416944, 58.360213], [-152.380771, 58.352094], [-152.343022, 58.411629], [-152.316279, 58.413486], [-152.197939, 58.363103], [-152.125232, 58.374265], [-152.07854, 58.312357], [-152.036633, 58.306677], [-151.997771, 58.314213], [-151.974387, 58.309852], [-151.9825, 58.244351], [-152.068905, 58.177917], [-152.109107, 58.161152], [-152.165461, 58.178258], [-152.186544, 58.184663], [-152.22357, 58.214018], [-152.251684, 58.251119], [-152.268375, 58.25169], [-152.334365, 58.208075], [-152.332659, 58.18653], [-152.305221, 58.154077], [-152.30925, 58.133873], [-152.381134, 58.12426], [-152.451619, 58.12927], [-152.537661, 58.101002], [-152.558228, 58.118624], [-152.571354, 58.168238], [-152.598226, 58.162602], [-152.638766, 58.101826], [-152.683052, 58.06333], [-152.763875, 58.031392], [-152.781522, 58.015946], [-152.840716, 58.013792], [-152.928437, 57.99372], [-152.982569, 57.997049], [-153.305468, 58.063066], [-153.381329, 58.087203], [-153.115817, 58.238518], [-152.976134, 58.297009], [-152.895365, 58.293856], [-152.814542, 58.275618], [-152.771857, 58.278563], [-152.768707, 58.34559], [-152.843922, 58.395611], [-152.841104, 58.416386], [-152.674655, 58.450598], [-152.61228, 58.445687], [-152.543577, 58.428186], [-152.478464, 58.399687], [-152.416944, 58.360213]]], [[[-134.680274, 58.161668], [-134.426127, 58.138828], [-134.240096, 58.143991], [-134.070159, 57.994544], [-133.965515, 57.873782], [-133.904123, 57.789188], [-133.869291, 57.707515], [-133.822731, 57.628678], [-133.826917, 57.61757], [-133.925024, 57.670799], [-133.99554, 57.778487], [-134.031658, 57.820609], [-134.067237, 57.839626], [-134.104728, 57.879364], [-134.17754, 57.982174], [-134.180281, 58.011134], [-134.212603, 58.037951], [-134.24994, 58.049168], [-134.292314, 58.04473], [-134.306887, 58.034392], [-134.3004, 57.963442], [-134.267095, 57.884527], [-134.083695, 57.71224], [-133.961142, 57.614187], [-133.937016, 57.581579], [-133.920866, 57.491964], [-133.973754, 57.45138], [-133.908825, 57.368719], [-133.911149, 57.352547], [-133.925305, 57.33676], [-134.100026, 57.30012], [-134.260146, 57.146795], [-134.435301, 57.056982], [-134.516018, 57.042568], [-134.554777, 57.057553], [-134.591521, 57.091962], [-134.613093, 57.137962], [-134.619531, 57.195531], [-134.575888, 57.231752], [-134.4892, 57.420168], [-134.486772, 57.482021], [-134.594801, 57.567802], [-134.659889, 57.638082], [-134.695133, 57.736014], [-134.754091, 57.995017], [-134.78148, 58.077854], [-134.820108, 58.146892], [-134.869981, 58.202076], [-134.907653, 58.262775], [-134.933125, 58.328946], [-134.923489, 58.354654], [-134.836983, 58.320157], [-134.733195, 58.225026], [-134.680274, 58.161668]]], [[[-134.312727, 58.228905], [-134.319857, 58.204097], [-134.45623, 58.206525], [-134.593999, 58.24311], [-134.661597, 58.290911], [-134.647974, 58.312412], [-134.519973, 58.332539], [-134.398898, 58.287187], [-134.312727, 58.228905]]], [[[-135.730369, 58.244252], [-135.587481, 58.146782], [-135.586295, 58.124414], [-135.615386, 58.057485], [-135.693104, 58.038522], [-135.671142, 58.011914], [-135.613244, 57.991864], [-135.572029, 58.008552], [-135.421187, 58.102375], [-135.374731, 58.122139], [-135.346617, 58.124106], [-135.162854, 58.095838], [-135.002091, 58.05108], [-134.95468, 58.015319], [-134.927983, 57.952763], [-134.970643, 57.817247], [-135.102578, 57.793659], [-135.164771, 57.796109], [-135.231222, 57.815797], [-135.338476, 57.768665], [-135.249542, 57.732553], [-134.978839, 57.724357], [-134.896617, 57.648002], [-134.873106, 57.589204], [-134.931499, 57.481142], [-135.084851, 57.511014], [-135.220219, 57.573647], [-135.497844, 57.662274], [-135.564223, 57.666427], [-135.608564, 57.650749], [-135.62066, 57.596949], [-135.617814, 57.480373], [-135.691945, 57.419904], [-135.910765, 57.446568], [-135.996656, 57.534887], [-136.076598, 57.674567], [-136.378233, 57.839989], [-136.459906, 57.873079], [-136.56861, 57.972176], [-136.525098, 58.050564], [-136.512283, 58.095992], [-136.454379, 58.108], [-136.369527, 58.143035], [-136.321983, 58.218874], [-136.245683, 58.157482], [-136.143725, 58.098475], [-136.142357, 58.153923], [-136.094374, 58.198154], [-135.994382, 58.196528], [-135.947404, 58.2058], [-135.881728, 58.247142], [-135.787059, 58.268488], [-135.730369, 58.244252]]], [[[-152.898051, 57.823916], [-152.890817, 57.768984], [-152.850148, 57.775697], [-152.696254, 57.832287], [-152.616027, 57.848876], [-152.511563, 57.851458], [-152.428779, 57.825673], [-152.411931, 57.805931], [-152.419166, 57.78231], [-152.485416, 57.73441], [-152.482625, 57.703297], [-152.411492, 57.646091], [-152.236515, 57.614912], [-152.215276, 57.597696], [-152.216234, 57.576998], [-152.336664, 57.48223], [-152.380875, 57.460114], [-152.412189, 57.454786], [-152.630935, 57.471815], [-152.831131, 57.502873], [-152.912161, 57.508168], [-152.940788, 57.498094], [-152.997453, 57.468947], [-152.956858, 57.460367], [-152.781366, 57.453391], [-152.71951, 57.410863], [-152.692536, 57.379595], [-152.679047, 57.345131], [-152.714058, 57.33097], [-152.789092, 57.320632], [-152.879034, 57.320819], [-152.990295, 57.281982], [-153.051607, 57.237641], [-153.274361, 57.226347], [-153.443704, 57.167208], [-153.503544, 57.138006], [-153.524423, 57.103081], [-153.588295, 57.077702], [-153.732576, 57.052335], [-153.646533, 57.029593], [-153.633045, 57.010367], [-153.631444, 56.983703], [-153.643328, 56.960764], [-153.757251, 56.858338], [-153.972715, 56.774205], [-154.027364, 56.777984], [-154.050797, 56.788476], [-154.070021, 56.804538], [-154.070847, 56.820666], [-153.79319, 56.989493], [-153.804198, 56.997788], [-153.879724, 57.0035], [-153.999381, 57.049951], [-154.083767, 57.02009], [-154.102991, 57.021221], [-154.08046, 57.061036], [-154.025424, 57.108475], [-154.035037, 57.121834], [-154.065319, 57.133667], [-154.134876, 57.140753], [-154.243758, 57.143027], [-154.324426, 57.131788], [-154.376825, 57.107036], [-154.381115, 57.096511], [-154.269543, 57.099466], [-154.23921, 57.086854], [-154.209135, 57.063343], [-154.19084, 57.036152], [-154.184331, 57.005302], [-154.207712, 56.963807], [-154.260941, 56.911776], [-154.338947, 56.920916], [-154.498781, 57.036569], [-154.569319, 57.205913], [-154.705951, 57.335365], [-154.712205, 57.366269], [-154.673214, 57.446107], [-154.535316, 57.559431], [-154.387083, 57.590467], [-154.281431, 57.638082], [-154.179343, 57.652452], [-154.116169, 57.65121], [-154.029844, 57.630699], [-153.995039, 57.587281], [-154.015864, 57.566879], [-154.007907, 57.556179], [-153.947342, 57.530075], [-153.881869, 57.439032], [-153.80544, 57.358205], [-153.754589, 57.325367], [-153.687718, 57.30513], [-153.756913, 57.366829], [-153.797815, 57.443261], [-153.818357, 57.595609], [-153.838149, 57.635863], [-153.799444, 57.646662], [-153.690149, 57.640719], [-153.693146, 57.663405], [-153.808488, 57.714722], [-153.879438, 57.757196], [-153.906105, 57.790792], [-153.904424, 57.819884], [-153.841535, 57.862829], [-153.805827, 57.875068], [-153.769006, 57.880396], [-153.695626, 57.871245], [-153.662656, 57.857808], [-153.56858, 57.761074], [-153.524473, 57.731026], [-153.487938, 57.730949], [-153.454039, 57.747022], [-153.422723, 57.779157], [-153.390426, 57.798383], [-153.357145, 57.804689], [-153.252396, 57.790473], [-153.217465, 57.795747], [-153.200307, 57.820037], [-153.20103, 57.863291], [-153.175192, 57.878847], [-153.168837, 57.910653], [-153.225938, 57.957597], [-153.160465, 57.971967], [-152.943268, 57.93602], [-152.850406, 57.896777], [-152.898051, 57.823916]]], [[[-153.240641, 57.850085], [-153.268571, 57.822366], [-153.294979, 57.829464], [-153.350842, 57.86195], [-153.465045, 57.909389], [-153.517084, 57.941887], [-153.520081, 57.955741], [-153.481066, 57.971033], [-153.346966, 57.93279], [-153.290044, 57.897908], [-153.240641, 57.850085]]], [[[-134.969764, 57.351438], [-134.884889, 57.241695], [-134.823184, 57.156562], [-134.768516, 57.054191], [-134.676835, 56.842265], [-134.634099, 56.76212], [-134.620717, 56.718295], [-134.610566, 56.603422], [-134.624332, 56.578714], [-134.651721, 56.556027], [-134.657098, 56.523244], [-134.631698, 56.43565], [-134.630045, 56.302452], [-134.654022, 56.22747], [-134.6819, 56.216154], [-134.750296, 56.240753], [-134.806469, 56.28127], [-134.847991, 56.323491], [-134.950153, 56.45681], [-134.980541, 56.518926], [-134.982398, 56.56363], [-134.966644, 56.596127], [-134.933179, 56.616342], [-134.875122, 56.670439], [-134.883444, 56.679074], [-134.927598, 56.666978], [-135.017796, 56.660156], [-135.09715, 56.702849], [-135.159031, 56.725371], [-135.146578, 56.802319], [-135.163112, 56.824127], [-135.284808, 56.800352], [-135.330599, 56.821853], [-135.340651, 56.850769], [-135.338377, 56.894], [-135.315147, 56.931826], [-135.199598, 57.027319], [-135.211254, 57.044941], [-135.267373, 57.048874], [-135.341371, 57.08158], [-135.375297, 57.188444], [-135.454931, 57.249429], [-135.501953, 57.243848], [-135.608927, 57.071451], [-135.66187, 57.033724], [-135.812327, 57.009543], [-135.781654, 57.05752], [-135.767701, 57.100389], [-135.821138, 57.230412], [-135.822737, 57.280433], [-135.787136, 57.317281], [-135.680887, 57.332574], [-135.624505, 57.354382], [-135.580582, 57.390011], [-135.56965, 57.424683], [-135.48728, 57.516485], [-135.44868, 57.534371], [-135.346282, 57.533129], [-135.130659, 57.431638], [-135.065235, 57.416707], [-134.969764, 57.351438]]], [[[-170.160565, 57.183951], [-170.263995, 57.136776], [-170.357994, 57.154211], [-170.385874, 57.188554], [-170.386622, 57.203023], [-170.116174, 57.241783], [-170.160565, 57.183951]]], [[[-153.007088, 57.124833], [-153.134213, 57.092589], [-153.156821, 57.093929], [-153.235422, 57.028615], [-153.295391, 57.000424], [-153.374586, 57.051917], [-153.35433, 57.131909], [-153.285212, 57.185039], [-152.935465, 57.167307], [-152.908414, 57.152431], [-152.907741, 57.139742], [-152.933425, 57.129228], [-153.007088, 57.124833]]], [[[-133.366221, 57.0035], [-133.299716, 56.972178], [-133.263538, 57.004973], [-133.195999, 57.003468], [-133.070788, 56.974277], [-132.996218, 56.93043], [-132.954152, 56.880278], [-132.950587, 56.850461], [-132.963325, 56.782576], [-132.953998, 56.713077], [-132.959167, 56.677053], [-132.975855, 56.647236], [-133.004123, 56.623725], [-133.034923, 56.620726], [-133.132383, 56.68326], [-133.244004, 56.795859], [-133.328961, 56.83007], [-133.3324, 56.818491], [-133.309065, 56.786246], [-133.239719, 56.725689], [-133.227261, 56.689259], [-133.178481, 56.644808], [-133.156619, 56.611124], [-133.144221, 56.566882], [-133.144737, 56.528232], [-133.158173, 56.495152], [-133.180805, 56.47397], [-133.212665, 56.464621], [-133.382756, 56.473894], [-133.484198, 56.451745], [-133.602795, 56.464094], [-133.631349, 56.484045], [-133.649279, 56.516806], [-133.65832, 56.596292], [-133.688165, 56.710023], [-133.68098, 56.797518], [-133.757543, 56.876685], [-133.823066, 56.924377], [-133.917296, 56.96707], [-133.979467, 57.009598], [-133.962362, 57.043447], [-133.865984, 57.068715], [-133.707726, 57.062827], [-133.366221, 57.0035]]], [[[-133.989597, 56.844957], [-133.924788, 56.77571], [-133.830872, 56.781291], [-133.778132, 56.728886], [-133.738367, 56.650444], [-133.767283, 56.600115], [-133.809009, 56.611322], [-133.855261, 56.582175], [-133.883579, 56.485495], [-133.870455, 56.388651], [-133.884611, 56.292125], [-133.93851, 56.193676], [-133.9497, 56.127714], [-133.970783, 56.107917], [-133.994013, 56.101127], [-134.024039, 56.119002], [-134.067468, 56.13301], [-134.122427, 56.077408], [-134.189581, 56.076968], [-134.245056, 56.203267], [-134.195469, 56.413513], [-134.084398, 56.456348], [-134.150491, 56.513499], [-134.290249, 56.58001], [-134.278389, 56.617111], [-134.384401, 56.72403], [-134.390603, 56.749486], [-134.373679, 56.838651], [-134.274434, 56.918181], [-134.143279, 56.932342], [-134.051812, 56.898284], [-134.000599, 56.869193], [-133.989597, 56.844957]]], [[[-132.746878, 56.525694], [-132.757628, 56.511016], [-132.884702, 56.512467], [-132.930795, 56.524453], [-132.948027, 56.567244], [-132.936249, 56.606828], [-132.906531, 56.637425], [-132.870645, 56.696389], [-132.842531, 56.794771], [-132.655878, 56.68471], [-132.598673, 56.635711], [-132.567977, 56.575825], [-132.634224, 56.553446], [-132.714479, 56.542547], [-132.746878, 56.525694]]], [[[-169.755214, 56.635041], [-169.623904, 56.615145], [-169.550498, 56.62812], [-169.485696, 56.617738], [-169.474327, 56.594062], [-169.586878, 56.542437], [-169.632611, 56.5457], [-169.766169, 56.607938], [-169.755214, 56.635041]]], [[[-154.208643, 56.514895], [-154.257788, 56.512675], [-154.332124, 56.539031], [-154.322204, 56.570606], [-154.216757, 56.60874], [-154.110382, 56.602928], [-154.102268, 56.581658], [-154.107176, 56.557785], [-154.115963, 56.543887], [-154.149809, 56.529572], [-154.208643, 56.514895]]], [[[-154.6828, 56.435782], [-154.75122, 56.412139], [-154.773931, 56.42028], [-154.777161, 56.439913], [-154.760934, 56.471125], [-154.729362, 56.502128], [-154.623734, 56.561301], [-154.517541, 56.600522], [-154.463356, 56.598204], [-154.444882, 56.573188], [-154.511182, 56.521431], [-154.6828, 56.435782]]], [[[-132.112346, 56.109389], [-132.132935, 55.943254], [-132.172623, 55.952636], [-132.210295, 55.952966], [-132.28732, 55.9294], [-132.36858, 55.939738], [-132.406588, 55.958184], [-132.420595, 55.979531], [-132.406049, 56.028881], [-132.451159, 56.056369], [-132.602963, 56.0664], [-132.659905, 56.078177], [-132.691381, 56.130065], [-132.699027, 56.19817], [-132.675203, 56.223625], [-132.598722, 56.241632], [-132.539011, 56.324183], [-132.505964, 56.335268], [-132.379847, 56.498778], [-132.316494, 56.487484], [-132.20562, 56.387926], [-132.066896, 56.244213], [-132.112346, 56.109389]]], [[[-132.779897, 56.247268], [-132.830956, 56.244169], [-132.891442, 56.259407], [-133.035028, 56.340904], [-133.037664, 56.364832], [-133.017092, 56.392012], [-132.935497, 56.44177], [-132.902038, 56.453767], [-132.70608, 56.448493], [-132.643343, 56.435156], [-132.62911, 56.411909], [-132.632263, 56.388288], [-132.65283, 56.36436], [-132.657581, 56.3393], [-132.646573, 56.313207], [-132.669392, 56.287313], [-132.779897, 56.247268]]], [[[-133.566107, 56.339201], [-133.376636, 56.317756], [-133.203003, 56.319843], [-133.143704, 56.278579], [-133.104478, 56.235095], [-133.081741, 56.194193], [-133.075435, 56.15585], [-133.080115, 56.128714], [-133.101226, 56.099776], [-133.096622, 56.090042], [-132.757573, 55.99501], [-132.597612, 55.895035], [-132.533765, 55.842487], [-132.496972, 55.798091], [-132.430153, 55.686987], [-132.288869, 55.558106], [-132.214766, 55.51883], [-132.1727, 55.480598], [-132.196342, 55.479147], [-132.295873, 55.50747], [-132.51126, 55.593922], [-132.528854, 55.590461], [-132.548339, 55.543692], [-132.581748, 55.502658], [-132.63128, 55.473182], [-132.591592, 55.464371], [-132.417854, 55.482916], [-132.272021, 55.39864], [-132.215283, 55.383544], [-132.160247, 55.322977], [-132.15839, 55.299829], [-132.190426, 55.255004], [-132.214871, 55.236789], [-132.206708, 55.224429], [-132.165981, 55.218024], [-132.005092, 55.230637], [-131.976434, 55.208598], [-132.000385, 55.03385], [-131.977599, 54.969459], [-131.977934, 54.940213], [-131.996561, 54.901398], [-131.997209, 54.868615], [-131.98274, 54.83492], [-131.980878, 54.804818], [-132.021703, 54.72632], [-132.064748, 54.713126], [-132.134308, 54.712554], [-132.18924, 54.734846], [-132.266314, 54.802335], [-132.341323, 54.907243], [-132.370212, 54.922228], [-132.468627, 54.937939], [-132.48648, 54.950397], [-132.549371, 54.952595], [-132.593866, 54.995738], [-132.588488, 55.052351], [-132.626962, 55.110051], [-132.622183, 55.135967], [-132.665332, 55.146767], [-132.701741, 55.13054], [-132.68285, 55.07395], [-132.704141, 55.030081], [-132.782303, 55.048472], [-132.912607, 55.188493], [-133.060582, 55.300916], [-133.118535, 55.327657], [-133.103005, 55.360242], [-133.03004, 55.377546], [-132.970818, 55.376151], [-132.958909, 55.395563], [-133.082466, 55.504108], [-133.078407, 55.534903], [-133.033402, 55.589681], [-133.089624, 55.612576], [-133.243773, 55.595416], [-133.298265, 55.606885], [-133.342809, 55.65082], [-133.369012, 55.688953], [-133.502726, 55.695875], [-133.553264, 55.691173], [-133.640495, 55.748796], [-133.680183, 55.785172], [-133.664418, 55.803826], [-133.584064, 55.836544], [-133.537141, 55.83194], [-133.446965, 55.797004], [-133.411721, 55.798355], [-133.322139, 55.84463], [-133.308472, 55.886455], [-133.241527, 55.92082], [-133.252172, 55.957075], [-133.289224, 56.018697], [-133.371231, 56.035913], [-133.538613, 55.999273], [-133.68421, 55.942792], [-133.742531, 55.964853], [-133.755187, 55.999471], [-133.599203, 56.093635], [-133.530862, 56.145666], [-133.54409, 56.176516], [-133.594424, 56.216363], [-133.59861, 56.316251], [-133.566107, 56.339201]]], [[[-130.979134, 55.489167], [-131.013911, 55.379282], [-131.08274, 55.266804], [-131.18788, 55.206291], [-131.261878, 55.219782], [-131.316321, 55.268518], [-131.366836, 55.265826], [-131.42068, 55.2759], [-131.450936, 55.316286], [-131.422361, 55.368427], [-131.44758, 55.408791], [-131.474502, 55.37347], [-131.521837, 55.341071], [-131.641285, 55.29895], [-131.723661, 55.218332], [-131.76252, 55.165828], [-131.810991, 55.223111], [-131.842, 55.358693], [-131.846082, 55.416251], [-131.759471, 55.503076], [-131.647564, 55.58555], [-131.62496, 55.831688], [-131.269217, 55.955394], [-131.23617, 55.948989], [-131.120671, 55.856638], [-130.997789, 55.727658], [-130.965956, 55.669518], [-130.965022, 55.568027], [-130.979134, 55.489167]]], [[[-155.566002, 55.821196], [-155.60489, 55.789566], [-155.680622, 55.79184], [-155.723202, 55.802178], [-155.737361, 55.829798], [-155.620626, 55.913074], [-155.593959, 55.924335], [-155.573239, 55.921083], [-155.563936, 55.886663], [-155.566002, 55.821196]]], [[[-133.305088, 55.543747], [-133.283203, 55.515633], [-133.281704, 55.497857], [-133.426476, 55.431445], [-133.429085, 55.417701], [-133.463088, 55.376667], [-133.493476, 55.361682], [-133.547375, 55.317242], [-133.650185, 55.269287], [-133.634991, 55.413306], [-133.737131, 55.496923], [-133.634238, 55.539243], [-133.5667, 55.527202], [-133.454771, 55.522291], [-133.345578, 55.559095], [-133.305088, 55.543747]]], [[[-160.684914, 55.314814], [-160.669722, 55.314243], [-160.638821, 55.321944], [-160.573966, 55.378271], [-160.552778, 55.380754], [-160.552468, 55.363362], [-160.583164, 55.307629], [-160.531177, 55.233196], [-160.482677, 55.197403], [-160.487539, 55.184846], [-160.609081, 55.159006], [-160.701789, 55.177617], [-160.750623, 55.171212], [-160.79509, 55.145218], [-160.825476, 55.174002], [-160.846534, 55.311353], [-160.839662, 55.33538], [-160.789199, 55.383083], [-160.723932, 55.404627], [-160.695664, 55.398321], [-160.672175, 55.379381], [-160.666336, 55.359407], [-160.684914, 55.314814]]], [[[-160.329278, 55.337709], [-160.343308, 55.258795], [-160.480741, 55.30898], [-160.517482, 55.333831], [-160.492939, 55.352332], [-160.3623, 55.356979], [-160.329278, 55.337709]]], [[[-132.862273, 54.894422], [-132.837724, 54.880942], [-132.812895, 54.890445], [-132.772306, 54.926052], [-132.700653, 54.91902], [-132.648875, 54.907067], [-132.617223, 54.892412], [-132.634016, 54.840479], [-132.646963, 54.756137], [-132.676648, 54.726221], [-132.705822, 54.684155], [-132.807286, 54.709116], [-132.889585, 54.762652], [-133.008929, 54.854838], [-133.075413, 54.92135], [-133.080555, 54.949442], [-133.122698, 54.969821], [-133.204629, 55.084497], [-133.251162, 55.175134], [-133.324852, 55.185516], [-133.417972, 55.210718], [-133.45381, 55.260344], [-133.429036, 55.303806], [-133.296563, 55.325723], [-133.097402, 55.21374], [-133.067064, 55.166191], [-132.995751, 55.110589], [-132.982189, 55.033026], [-132.946016, 55.002582], [-132.862273, 54.894422]]], [[[-159.872975, 55.128749], [-159.933954, 55.106843], [-159.953073, 55.078959], [-159.999427, 55.067204], [-160.038418, 55.044495], [-160.169597, 54.941685], [-160.227061, 54.92269], [-160.163577, 55.010438], [-160.153604, 55.038343], [-160.152415, 55.056899], [-160.172077, 55.123048], [-160.133735, 55.120147], [-160.10221, 55.133891], [-160.038753, 55.192547], [-159.981651, 55.197766], [-159.920466, 55.267529], [-159.887367, 55.273011], [-159.871063, 55.263552], [-159.898243, 55.221276], [-159.839411, 55.182374], [-159.854111, 55.144702], [-159.872975, 55.128749]]], [[[-131.339727, 55.079838], [-131.237461, 54.949518], [-131.232034, 54.903782], [-131.329521, 54.887764], [-131.406183, 54.894301], [-131.44569, 54.909341], [-131.456105, 54.930545], [-131.431326, 54.996485], [-131.481736, 55.035245], [-131.54003, 55.048472], [-131.59222, 55.025687], [-131.595115, 55.090748], [-131.555993, 55.137407], [-131.577828, 55.20082], [-131.578477, 55.248775], [-131.565452, 55.264123], [-131.512663, 55.262728], [-131.404634, 55.213322], [-131.339727, 55.079838]]], [[[-159.515117, 55.151876], [-159.520385, 55.072148], [-159.534986, 55.059634], [-159.561496, 55.080926], [-159.617718, 55.057316], [-159.648491, 55.074576], [-159.635417, 55.102316], [-159.639655, 55.12397], [-159.597954, 55.125706], [-159.588031, 55.165312], [-159.595268, 55.182011], [-159.574751, 55.217717], [-159.545088, 55.225978], [-159.515117, 55.151876]]], [[[-159.361998, 54.972403], [-159.394476, 54.967338], [-159.421349, 54.978138], [-159.458477, 55.034937], [-159.461916, 55.05881], [-159.390422, 55.040881], [-159.363187, 54.999506], [-159.361998, 54.972403]]], [[[-163.476037, 54.980731], [-163.378962, 54.815518], [-163.336898, 54.783218], [-163.274525, 54.765596], [-163.187089, 54.747766], [-163.13505, 54.723277], [-163.089265, 54.686066], [-163.083271, 54.669016], [-163.358085, 54.735681], [-163.53084, 54.63832], [-163.583033, 54.625663], [-164.073313, 54.621005], [-164.171266, 54.603021], [-164.234621, 54.571347], [-164.346682, 54.482413], [-164.403499, 54.447839], [-164.463495, 54.427327], [-164.590801, 54.404333], [-164.743788, 54.407475], [-164.823423, 54.419077], [-164.866184, 54.461374], [-164.903935, 54.544782], [-164.903701, 54.567985], [-164.887656, 54.607833], [-164.751488, 54.662918], [-164.706194, 54.691988], [-164.529796, 54.880832], [-164.478637, 54.906826], [-164.424299, 54.913187], [-164.273689, 54.900058], [-164.145066, 54.955143], [-163.867977, 55.039123], [-163.807153, 55.049099], [-163.607476, 55.050856], [-163.553009, 55.037827], [-163.510893, 55.014294], [-163.476037, 54.980731]]], [[[-162.29815, 54.847038], [-162.321921, 54.842391], [-162.390754, 54.872977], [-162.415766, 54.895872], [-162.433904, 54.931534], [-162.293654, 54.982851], [-162.264612, 54.983521], [-162.23836, 54.954737], [-162.233761, 54.93205], [-162.27257, 54.867198], [-162.29815, 54.847038]]], [[[-162.554413, 54.401356], [-162.641127, 54.379526], [-162.73311, 54.402311], [-162.81171, 54.444378], [-162.820548, 54.494553], [-162.64539, 54.462055], [-162.60795, 54.446652], [-162.554413, 54.401356]]], [[[-165.561155, 54.136695], [-165.604821, 54.129147], [-165.615364, 54.13954], [-165.620532, 54.183541], [-165.654147, 54.253304], [-165.590352, 54.278649], [-165.550613, 54.284538], [-165.533767, 54.273892], [-165.487671, 54.221883], [-165.44173, 54.208007], [-165.407857, 54.196845], [-165.467595, 54.180926], [-165.561155, 54.136695]]], [[[-165.841552, 54.070656], [-165.879379, 54.053034], [-165.909841, 54.049156], [-165.932889, 54.059153], [-166.036423, 54.047189], [-166.056654, 54.054319], [-166.102827, 54.113953], [-166.105825, 54.144814], [-166.087738, 54.169149], [-166.04128, 54.191242], [-165.966402, 54.211028], [-165.892866, 54.206974], [-165.76445, 54.152098], [-165.704247, 54.119897], [-165.692878, 54.099924], [-165.737914, 54.081093], [-165.841552, 54.070656]]], [[[-166.615355, 53.90095], [-166.572178, 53.853456], [-166.497481, 53.883537], [-166.442755, 53.924802], [-166.400044, 53.978096], [-166.37232, 53.998981], [-166.33563, 53.970922], [-166.230881, 53.932602], [-166.31899, 53.87377], [-166.488747, 53.785506], [-166.545617, 53.726487], [-166.549209, 53.700955], [-166.384723, 53.720522], [-166.338782, 53.717654], [-166.309455, 53.697494], [-166.354517, 53.673522], [-166.444177, 53.651813], [-166.522001, 53.609648], [-166.702196, 53.536677], [-166.770409, 53.47601], [-166.850999, 53.452862], [-166.960733, 53.44738], [-167.153642, 53.407851], [-167.270792, 53.370596], [-167.300455, 53.350491], [-167.337274, 53.340977], [-167.381302, 53.342021], [-167.428793, 53.325684], [-167.479823, 53.291989], [-167.522482, 53.276235], [-167.592194, 53.272719], [-167.628625, 53.259437], [-167.669424, 53.259953], [-167.780864, 53.300262], [-167.808769, 53.323773], [-167.710094, 53.370904], [-167.638702, 53.386559], [-167.530182, 53.39369], [-167.423521, 53.43725], [-167.204078, 53.494973], [-167.136097, 53.526448], [-167.092353, 53.635949], [-167.042408, 53.654604], [-167.015743, 53.698373], [-166.894149, 53.697132], [-166.838339, 53.648045], [-166.818727, 53.641376], [-166.808986, 53.646133], [-166.803663, 53.68541], [-166.741263, 53.712952], [-166.777256, 53.733156], [-166.889601, 53.758578], [-166.972929, 53.770565], [-167.027266, 53.769125], [-167.071501, 53.783386], [-167.105608, 53.813356], [-167.121164, 53.843118], [-167.118166, 53.872628], [-167.090468, 53.905652], [-167.038067, 53.942182], [-166.978097, 53.962935], [-166.848673, 53.977899], [-166.734055, 54.002178], [-166.673284, 54.005958], [-166.627394, 53.995674], [-166.615355, 53.90095]]], [[[-166.209746, 53.723279], [-166.223828, 53.720412], [-166.249433, 53.745142], [-166.250751, 53.767774], [-166.234369, 53.784188], [-166.187732, 53.822475], [-166.154555, 53.836142], [-166.113731, 53.843074], [-166.102672, 53.832791], [-166.138639, 53.787418], [-166.183753, 53.756898], [-166.209746, 53.723279]]], [[[-167.964367, 53.345119], [-168.27068, 53.238046], [-168.370131, 53.159758], [-168.445991, 53.084413], [-168.505627, 53.043171], [-168.549035, 53.036096], [-168.597404, 53.016089], [-168.698534, 52.963432], [-168.741013, 52.956873], [-169.065928, 52.833936], [-169.088898, 52.832024], [-169.07311, 52.86416], [-168.973867, 52.909687], [-168.909167, 52.951182], [-168.836097, 53.019737], [-168.795867, 53.044929], [-168.783024, 53.079349], [-168.777806, 53.148793], [-168.759615, 53.175051], [-168.689827, 53.227247], [-168.639029, 53.255767], [-168.572186, 53.265633], [-168.436638, 53.25691], [-168.380414, 53.283442], [-168.362973, 53.303569], [-168.397262, 53.321916], [-168.405323, 53.353798], [-168.396433, 53.408785], [-168.357212, 53.457564], [-168.287707, 53.500147], [-168.193061, 53.533326], [-168.073276, 53.55699], [-167.98571, 53.558177], [-167.828097, 53.507947], [-167.804688, 53.484953], [-167.843108, 53.43457], [-167.865148, 53.387306], [-167.964367, 53.345119]]], [[[-169.691962, 52.847372], [-169.708084, 52.807107], [-169.722762, 52.792331], [-169.877326, 52.813754], [-169.980549, 52.806031], [-169.991841, 52.829849], [-169.982564, 52.851042], [-169.820637, 52.883386], [-169.754904, 52.883649], [-169.710979, 52.866752], [-169.691962, 52.847372]]], [[[-170.733397, 52.581492], [-170.797347, 52.549764], [-170.81608, 52.561541], [-170.827035, 52.600718], [-170.791172, 52.63126], [-170.682083, 52.697563], [-170.608057, 52.685082], [-170.58462, 52.667581], [-170.586636, 52.642422], [-170.614025, 52.609606], [-170.649268, 52.593116], [-170.692263, 52.592962], [-170.733397, 52.581492]]], [[[-174.677394, 52.03501], [-175.213873, 51.99391], [-175.295548, 52.022145], [-175.214158, 52.038218], [-175.117652, 52.047106], [-174.915933, 52.094183], [-174.667757, 52.134953], [-174.474254, 52.184051], [-174.306151, 52.216142], [-174.258815, 52.269063], [-174.406507, 52.29598], [-174.435548, 52.317216], [-174.36545, 52.341924], [-174.306874, 52.377938], [-174.168898, 52.420191], [-174.045624, 52.367248], [-174.018339, 52.331795], [-174.030096, 52.289783], [-174.0549, 52.246014], [-174.163214, 52.223371], [-174.179389, 52.200333], [-174.120633, 52.135217], [-174.343539, 52.07778], [-174.677394, 52.03501]]], [[[-172.46479, 52.272293], [-172.539127, 52.257483], [-172.619846, 52.272831], [-172.582199, 52.325643], [-172.543675, 52.353812], [-172.470398, 52.388012], [-172.383115, 52.372928], [-172.31361, 52.329576], [-172.46479, 52.272293]]], [[[-173.553303, 52.136304], [-173.357242, 52.095633], [-173.113304, 52.10039], [-173.024317, 52.090513], [-173.022896, 52.079142], [-173.178881, 52.062509], [-173.232212, 52.06798], [-173.36843, 52.045612], [-173.461009, 52.041547], [-173.672572, 52.062663], [-173.835792, 52.048194], [-173.878942, 52.053665], [-173.930205, 52.072144], [-173.989581, 52.103587], [-173.9925, 52.123329], [-173.938913, 52.131283], [-173.794115, 52.104312], [-173.779, 52.118375], [-173.656837, 52.143742], [-173.553303, 52.136304]]], [[[-176.02155, 52.002436], [-176.045089, 51.973003], [-176.142861, 52.004314], [-176.177535, 52.029847], [-176.184511, 52.056049], [-176.155676, 52.099401], [-176.077412, 52.099972], [-176.031214, 52.082295], [-175.988063, 52.049479], [-175.975274, 52.028946], [-176.02155, 52.002436]]], [[[-176.593298, 51.8667], [-176.587924, 51.833191], [-176.473383, 51.837377], [-176.437467, 51.820096], [-176.437338, 51.75431], [-176.452351, 51.73571], [-176.469766, 51.731161], [-176.511003, 51.74563], [-176.557538, 51.712034], [-176.770961, 51.629944], [-176.837107, 51.675867], [-176.961622, 51.603676], [-176.874418, 51.790488], [-176.773623, 51.818744], [-176.736416, 51.839937], [-176.745123, 51.89466], [-176.698356, 51.986055], [-176.596812, 51.981793], [-176.54989, 51.944065], [-176.551595, 51.919566], [-176.593298, 51.8667]]], [[[-177.1482, 51.716736], [-177.176983, 51.703718], [-177.2299, 51.693533], [-177.382371, 51.704849], [-177.474665, 51.70129], [-177.577605, 51.694214], [-177.654887, 51.676592], [-177.670235, 51.701081], [-177.667625, 51.721186], [-177.3347, 51.776216], [-177.257288, 51.804957], [-177.209747, 51.841277], [-177.16639, 51.909437], [-177.131508, 51.929805], [-177.110037, 51.928773], [-177.063037, 51.9019], [-177.079522, 51.866546], [-177.121379, 51.835773], [-177.135125, 51.806912], [-177.1482, 51.716736]]], [[[-177.879034, 51.64972], [-177.901254, 51.616387], [-177.925362, 51.617365], [-178.058894, 51.672604], [-178.078479, 51.691259], [-178.000034, 51.717461], [-177.977245, 51.737775], [-177.986365, 51.764285], [-178.045122, 51.801078], [-178.153487, 51.848254], [-178.194518, 51.882212], [-178.168241, 51.903032], [-178.116616, 51.915853], [-177.953809, 51.918434], [-177.865856, 51.860405], [-177.799607, 51.840036], [-177.6445, 51.826292], [-177.724961, 51.801672], [-177.770642, 51.777897], [-177.826969, 51.685887], [-177.879034, 51.64972]]], [[[-176.008967, 51.812372], [-176.093355, 51.790488], [-176.204433, 51.834817], [-176.193659, 51.886288], [-176.071625, 51.843299], [-176.008967, 51.812372]]], [[[-176.286702, 51.791982], [-176.349644, 51.733282], [-176.396101, 51.759836], [-176.413722, 51.840585], [-176.378582, 51.861119], [-176.280217, 51.802836], [-176.286702, 51.791982]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3541", "diss_me": 3541, "iso_3166_2": "US-AL", "wikipedia": "http://en.wikipedia.org/wiki/Alabama", "iso_a2": "US", "adm0_sr": 5, "name": "Alabama", "name_alt": "AL|Ala.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US01", "code_hasc": "US.AL", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Ala.", "postal": "AL", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 7, "mapcolor9": 1, "mapcolor13": 1, "fips": "US01", "fips_alt": null, "woe_id": 2347559, "woe_label": "Alabama, US, United States", "woe_name": "Alabama", "latitude": 32.8551, "longitude": -86.7184, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4829764, "gn_name": "Alabama", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.AL", "region_sub": "East South Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q173", "name_ar": "\u0623\u0644\u0627\u0628\u0627\u0645\u0627", "name_bn": "\u0985\u09cd\u09af\u09be\u09b2\u09be\u09ac\u09be\u09ae\u09be", "name_de": "Alabama", "name_en": "Alabama", "name_es": "Alabama", "name_fr": "Alabama", "name_el": "\u0391\u03bb\u03b1\u03bc\u03c0\u03ac\u03bc\u03b1", "name_hi": "\u0905\u0932\u093e\u092c\u093e\u092e\u093e", "name_hu": "Alabama", "name_id": "Alabama", "name_it": "Alabama", "name_ja": "\u30a2\u30e9\u30d0\u30de\u5dde", "name_ko": "\uc568\ub77c\ubc30\ub9c8", "name_nl": "Alabama", "name_pl": "Alabama", "name_pt": "Alabama", "name_ru": "\u0410\u043b\u0430\u0431\u0430\u043c\u0430", "name_sv": "Alabama", "name_tr": "Alabama", "name_vi": "Alabama", "name_zh": "\u4e9a\u62c9\u5df4\u9a6c\u5dde", "ne_id": 1159315233, "name_he": "\u05d0\u05dc\u05d1\u05de\u05d4", "name_uk": "\u0410\u043b\u0430\u0431\u0430\u043c\u0430", "name_ur": "\u0627\u0644\u0627\u0628\u0627\u0645\u0627", "name_fa": "\u0622\u0644\u0627\u0628\u0627\u0645\u0627", "name_zht": "\u963f\u62c9\u5df4\u99ac\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-88.48619, 30.230916, -84.921533, 35.024999], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-87.489511, 30.377683], [-87.513252, 30.368125], [-87.622269, 30.264765], [-88.005934, 30.230916], [-87.985016, 30.254383], [-87.903981, 30.259085], [-87.790294, 30.291792], [-87.813289, 30.346877], [-87.857113, 30.40739], [-87.897631, 30.414135], [-87.924284, 30.449643], [-87.922998, 30.56155], [-87.948871, 30.626919], [-88.011317, 30.694177], [-88.032422, 30.681224], [-88.078367, 30.566197], [-88.116555, 30.415322], [-88.135441, 30.366598], [-88.249215, 30.363181], [-88.349927, 30.373464], [-88.399585, 30.370805], [-88.412758, 30.576579], [-88.423261, 30.764303], [-88.433742, 30.952015], [-88.444234, 31.139706], [-88.454726, 31.327385], [-88.465217, 31.515108], [-88.475709, 31.702821], [-88.48619, 31.890511], [-88.461779, 32.075246], [-88.437367, 32.25997], [-88.412977, 32.444684], [-88.388555, 32.62943], [-88.364132, 32.814176], [-88.339743, 32.998889], [-88.315331, 33.183613], [-88.290908, 33.368348], [-88.266519, 33.553094], [-88.242096, 33.737807], [-88.217684, 33.922532], [-88.193295, 34.107278], [-88.168883, 34.292013], [-88.144461, 34.476737], [-88.12006, 34.66145], [-88.095648, 34.846196], [-88.089474, 34.893064], [-88.088211, 34.909082], [-88.084772, 34.933109], [-88.173267, 34.999005], [-88.19079, 35.012046], [-88.203139, 35.024197], [-88.190427, 35.024999], [-88.029994, 35.023494], [-87.869594, 35.021966], [-87.70916, 35.02045], [-87.548738, 35.018945], [-87.388305, 35.017451], [-87.227871, 35.015946], [-87.067449, 35.014452], [-86.907015, 35.012925], [-86.746582, 35.011409], [-86.58616, 35.009903], [-86.425726, 35.008409], [-86.265293, 35.006904], [-86.104871, 35.00541], [-85.944437, 35.003861], [-85.784037, 35.002356], [-85.623604, 35.000862], [-85.59717, 34.873069], [-85.57077, 34.745265], [-85.544359, 34.617472], [-85.517948, 34.489679], [-85.491548, 34.36193], [-85.465115, 34.234137], [-85.438682, 34.106344], [-85.412271, 33.978551], [-85.38587, 33.850747], [-85.359459, 33.722954], [-85.333059, 33.595161], [-85.306626, 33.46739], [-85.280193, 33.339619], [-85.253782, 33.211826], [-85.227382, 33.084022], [-85.200971, 32.956229], [-85.176317, 32.898221], [-85.156531, 32.804277], [-85.015038, 32.526158], [-84.973905, 32.409286], [-84.985968, 32.360946], [-84.9685, 32.319813], [-84.921533, 32.285887], [-84.929696, 32.246556], [-84.992977, 32.201831], [-85.034627, 32.147372], [-85.064564, 32.051043], [-85.06441, 32.050527], [-85.124132, 31.880536], [-85.124824, 31.77677], [-85.067201, 31.635387], [-85.067047, 31.635178], [-85.054885, 31.572677], [-85.092601, 31.295711], [-85.067443, 31.117579], [-85.007282, 31.001673], [-85.330005, 31.001102], [-85.653399, 31.001058], [-85.976792, 31.001003], [-86.300175, 31.000948], [-86.623568, 31.000893], [-86.94694, 31.000849], [-87.2703, 31.000794], [-87.593694, 31.000739], [-87.607438, 30.929328], [-87.601055, 30.860598], [-87.566195, 30.795636], [-87.421659, 30.671589], [-87.408278, 30.641465], [-87.43381, 30.545938], [-87.429382, 30.477856], [-87.444807, 30.442557], [-87.480106, 30.411707], [-87.489511, 30.377683]]], [[[-88.071336, 30.25234], [-88.159314, 30.230916], [-88.289722, 30.232938], [-88.316254, 30.240453], [-88.263937, 30.254713], [-88.10937, 30.27373], [-88.071336, 30.25234]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3528", "diss_me": 3528, "iso_3166_2": "US-AR", "wikipedia": "http://en.wikipedia.org/wiki/Arkansas", "iso_a2": "US", "adm0_sr": 1, "name": "Arkansas", "name_alt": "AR|Ark.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US05", "code_hasc": "US.AR", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Ark.", "postal": "AR", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 8, "mapcolor9": 1, "mapcolor13": 1, "fips": "US05", "fips_alt": null, "woe_id": 2347562, "woe_label": "Arkansas, US, United States", "woe_name": "Arkansas", "latitude": 34.7563, "longitude": -92.1428, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4099753, "gn_name": "Arkansas", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.AR", "region_sub": "West South Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1612", "name_ar": "\u0623\u0631\u0643\u0646\u0633\u0627\u0633", "name_bn": "\u0986\u09b0\u09cd\u0995\u09be\u09a8\u09b8\u09be\u09b8", "name_de": "Arkansas", "name_en": "Arkansas", "name_es": "Arkansas", "name_fr": "Arkansas", "name_el": "\u0386\u03c1\u03ba\u03b1\u03bd\u03c3\u03bf", "name_hi": "\u0905\u0930\u0915\u093e\u0902\u0938\u093e\u0938", "name_hu": "Arkansas", "name_id": "Arkansas", "name_it": "Arkansas", "name_ja": "\u30a2\u30fc\u30ab\u30f3\u30bd\u30fc\u5dde", "name_ko": "\uc544\uce78\uc18c", "name_nl": "Arkansas", "name_pl": "Arkansas", "name_pt": "Arkansas", "name_ru": "\u0410\u0440\u043a\u0430\u043d\u0437\u0430\u0441", "name_sv": "Arkansas", "name_tr": "Arkansas", "name_vi": "Arkansas", "name_zh": "\u963f\u80af\u8272\u5dde", "ne_id": 1159315355, "name_he": "\u05d0\u05e8\u05e7\u05e0\u05e1\u05d5", "name_uk": "\u0410\u0440\u043a\u0430\u043d\u0437\u0430\u0441", "name_ur": "\u0622\u0631\u06a9\u0646\u0633\u0627\u0633", "name_fa": "\u0622\u0631\u06a9\u0627\u0646\u0632\u0627\u0633", "name_zht": "\u963f\u80af\u8272\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-94.61838, 33.011996, -89.688908, 36.500869], "geometry": {"type": "Polygon", "coordinates": [[[-89.704772, 36.001573], [-89.70932, 35.98305], [-89.689171, 35.943599], [-89.688908, 35.920956], [-89.703772, 35.906904], [-89.738214, 35.898741], [-89.763593, 35.888766], [-89.768932, 35.8721], [-89.769943, 35.864299], [-89.768108, 35.845249], [-89.763593, 35.828044], [-89.779655, 35.805742], [-89.894561, 35.750503], [-89.943505, 35.679136], [-89.92652, 35.591652], [-89.967345, 35.50331], [-90.066024, 35.414112], [-90.107882, 35.314203], [-90.092919, 35.203592], [-90.14227, 35.114296], [-90.255956, 35.046389], [-90.29376, 35.004476], [-90.293705, 35.001114], [-90.293419, 34.970067], [-90.282104, 34.945304], [-90.31994, 34.899161], [-90.41595, 34.851623], [-90.467575, 34.805261], [-90.47476, 34.760052], [-90.497216, 34.738091], [-90.53925, 34.72817], [-90.563848, 34.661164], [-90.584008, 34.503708], [-90.635424, 34.413873], [-90.718107, 34.391703], [-90.762338, 34.356426], [-90.768117, 34.308108], [-90.817215, 34.25222], [-90.90972, 34.188763], [-90.940251, 34.128558], [-90.908786, 34.071561], [-90.914729, 34.048622], [-90.943107, 34.029681], [-91.043148, 34.002864], [-91.060353, 33.989296], [-91.070175, 33.9742], [-91.05007, 33.945163], [-91.038183, 33.901394], [-91.052707, 33.827599], [-91.077151, 33.796694], [-91.100299, 33.767449], [-91.184125, 33.71567], [-91.207482, 33.675669], [-91.17037, 33.647456], [-91.172721, 33.616683], [-91.214579, 33.583406], [-91.202714, 33.546975], [-91.192958, 33.52253], [-91.15433, 33.500206], [-91.141015, 33.438507], [-91.168459, 33.35946], [-91.163339, 33.294454], [-91.117306, 33.240819], [-91.106781, 33.217923], [-91.152858, 33.040571], [-91.149958, 33.015918], [-91.346173, 33.015193], [-91.525855, 33.014984], [-91.705536, 33.014786], [-91.885207, 33.014544], [-92.064899, 33.014314], [-92.244569, 33.014105], [-92.424251, 33.013907], [-92.603927, 33.013699], [-92.783608, 33.01349], [-92.963284, 33.013281], [-93.142965, 33.013072], [-93.322619, 33.012842], [-93.502273, 33.012611], [-93.681949, 33.012402], [-93.861631, 33.012193], [-94.041307, 33.011996], [-94.042806, 33.147589], [-94.044306, 33.283215], [-94.045805, 33.418841], [-94.047327, 33.554435], [-94.098798, 33.57733], [-94.191534, 33.589009], [-94.238456, 33.581208], [-94.294679, 33.58746], [-94.33256, 33.565036], [-94.357674, 33.560972], [-94.377955, 33.566113], [-94.390122, 33.585603], [-94.432008, 33.599731], [-94.484149, 33.648434], [-94.481331, 33.75711], [-94.47854, 33.865787], [-94.475728, 33.974464], [-94.47291, 34.083141], [-94.470092, 34.191817], [-94.467279, 34.300494], [-94.464461, 34.409171], [-94.461643, 34.517837], [-94.458831, 34.626514], [-94.456013, 34.73519], [-94.453195, 34.843867], [-94.450377, 34.952544], [-94.447564, 35.061221], [-94.444746, 35.169897], [-94.441956, 35.278574], [-94.439138, 35.387251], [-94.461539, 35.526459], [-94.483968, 35.665655], [-94.506369, 35.804841], [-94.52877, 35.94406], [-94.551177, 36.083279], [-94.573578, 36.222465], [-94.595979, 36.361661], [-94.61838, 36.500869], [-94.339871, 36.500869], [-94.061357, 36.500869], [-93.782848, 36.500869], [-93.504339, 36.500869], [-93.22583, 36.500869], [-92.947321, 36.500869], [-92.668806, 36.500869], [-92.390298, 36.500869], [-92.111789, 36.500869], [-91.833285, 36.500869], [-91.55476, 36.500869], [-91.276256, 36.500869], [-90.997753, 36.500869], [-90.719239, 36.500869], [-90.440746, 36.500869], [-90.162243, 36.500869], [-90.118078, 36.422537], [-90.074473, 36.371835], [-90.067057, 36.334272], [-90.075659, 36.296721], [-90.149279, 36.215928], [-90.216164, 36.178409], [-90.25255, 36.137738], [-90.303043, 36.099374], [-90.381068, 35.99274], [-90.21679, 35.994938], [-90.052489, 35.997135], [-89.888178, 35.999332], [-89.704772, 36.001573]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3520", "diss_me": 3520, "iso_3166_2": "US-AZ", "wikipedia": "http://en.wikipedia.org/wiki/Arizona", "iso_a2": "US", "adm0_sr": 1, "name": "Arizona", "name_alt": "AZ|Ariz.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US04", "code_hasc": "US.AZ", "note": null, "hasc_maybe": null, "region": "West", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Ariz.", "postal": "AZ", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 7, "mapcolor9": 1, "mapcolor13": 1, "fips": "US04", "fips_alt": null, "woe_id": 2347561, "woe_label": "Arizona, US, United States", "woe_name": "Arizona", "latitude": 34.3046, "longitude": -111.935, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5551752, "gn_name": "Arizona", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.AZ", "region_sub": "Mountain", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q816", "name_ar": "\u0623\u0631\u064a\u0632\u0648\u0646\u0627", "name_bn": "\u0985\u09cd\u09af\u09be\u09b0\u09bf\u099c\u09cb\u09a8\u09be", "name_de": "Arizona", "name_en": "Arizona", "name_es": "Arizona", "name_fr": "Arizona", "name_el": "\u0391\u03c1\u03b9\u03b6\u03cc\u03bd\u03b1", "name_hi": "\u090f\u0930\u0940\u091c\u094b\u0928\u093e", "name_hu": "Arizona", "name_id": "Arizona", "name_it": "Arizona", "name_ja": "\u30a2\u30ea\u30be\u30ca\u5dde", "name_ko": "\uc560\ub9ac\uc870\ub098", "name_nl": "Arizona", "name_pl": "Arizona", "name_pt": "Arizona", "name_ru": "\u0410\u0440\u0438\u0437\u043e\u043d\u0430", "name_sv": "Arizona", "name_tr": "Arizona", "name_vi": "Arizona", "name_zh": "\u4e9a\u5229\u6851\u90a3\u5dde", "ne_id": 1159315341, "name_he": "\u05d0\u05e8\u05d9\u05d6\u05d5\u05e0\u05d4", "name_uk": "\u0410\u0440\u0438\u0437\u043e\u043d\u0430", "name_ur": "\u0627\u06cc\u0631\u06cc\u0632\u0648\u0646\u0627", "name_fa": "\u0622\u0631\u06cc\u0632\u0648\u0646\u0627", "name_zht": "\u4e9e\u5229\u6851\u90a3\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-114.835955, 31.32421, -109.04667, 37.004153], "geometry": {"type": "Polygon", "coordinates": [[[-109.047807, 31.327879], [-109.274774, 31.327473], [-109.628215, 31.326825], [-109.981651, 31.326155], [-110.335092, 31.325528], [-110.688533, 31.324858], [-111.041974, 31.32421], [-111.51621, 31.47224], [-111.990473, 31.620237], [-112.464731, 31.768244], [-112.938967, 31.916274], [-113.413203, 32.064293], [-113.887461, 32.212301], [-114.361724, 32.360298], [-114.835955, 32.508327], [-114.787999, 32.564808], [-114.724773, 32.715343], [-114.72095, 32.724483], [-114.7209, 32.724483], [-114.582176, 32.734723], [-114.516467, 32.772757], [-114.477531, 32.842004], [-114.469, 32.912306], [-114.490863, 32.983618], [-114.550546, 33.036792], [-114.648088, 33.07175], [-114.704388, 33.169781], [-114.719428, 33.330863], [-114.701702, 33.417809], [-114.651159, 33.430619], [-114.60261, 33.469895], [-114.556001, 33.535626], [-114.521559, 33.607608], [-114.499257, 33.685875], [-114.495098, 33.784653], [-114.509051, 33.903921], [-114.418282, 34.051149], [-114.32932, 34.142027], [-114.163514, 34.253363], [-114.125612, 34.286509], [-114.125018, 34.314084], [-114.125068, 34.317182], [-114.15879, 34.355217], [-114.308028, 34.43289], [-114.371024, 34.488492], [-114.376913, 34.5397], [-114.378879, 34.540633], [-114.398001, 34.589698], [-114.557473, 34.794571], [-114.610933, 34.907401], [-114.610543, 34.991117], [-114.610521, 34.99761], [-114.590987, 35.352776], [-114.648528, 35.475922], [-114.662063, 35.545355], [-114.645166, 35.630543], [-114.650126, 35.683508], [-114.677076, 35.729805], [-114.68369, 35.813597], [-114.687101, 35.917341], [-114.732321, 35.983666], [-114.741362, 36.013516], [-114.715759, 36.084982], [-114.669144, 36.12172], [-114.592975, 36.14756], [-114.505277, 36.156426], [-114.406087, 36.148307], [-114.331545, 36.116293], [-114.281573, 36.060328], [-114.232146, 36.031698], [-114.183207, 36.030303], [-114.119437, 36.076665], [-114.061924, 36.175212], [-114.042879, 36.181771], [-114.041171, 36.61249], [-114.04027, 37.004153], [-113.72817, 37.003944], [-113.41607, 37.003735], [-113.103971, 37.003527], [-112.791871, 37.003318], [-112.479772, 37.00312], [-112.167672, 37.002911], [-111.855572, 37.002703], [-111.543473, 37.002494], [-111.231373, 37.002285], [-110.919268, 37.002087], [-110.607168, 37.001879], [-110.295069, 37.00167], [-109.982969, 37.001461], [-109.67087, 37.001252], [-109.35877, 37.001055], [-109.04667, 37.000846], [-109.046698, 36.646339], [-109.046747, 36.291843], [-109.046802, 35.937336], [-109.046852, 35.582819], [-109.046906, 35.22829], [-109.046956, 34.873794], [-109.047005, 34.519287], [-109.04706, 34.164791], [-109.04711, 33.810284], [-109.047165, 33.455788], [-109.047214, 33.101293], [-109.047264, 32.746764], [-109.047318, 32.392235], [-109.047368, 32.037739], [-109.047423, 31.683232], [-109.047807, 31.327879]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3521", "diss_me": 3521, "iso_3166_2": "US-CA", "wikipedia": "http://en.wikipedia.org/wiki/California", "iso_a2": "US", "adm0_sr": 8, "name": "California", "name_alt": "CA|Calif.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US06", "code_hasc": "US.CA", "note": null, "hasc_maybe": null, "region": "West", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Calif.", "postal": "CA", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 10, "mapcolor9": 1, "mapcolor13": 1, "fips": "US06", "fips_alt": null, "woe_id": 2347563, "woe_label": "California, US, United States", "woe_name": "California", "latitude": 36.7496, "longitude": -119.591, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5332921, "gn_name": "California", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.CA", "region_sub": "Pacific", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q99", "name_ar": "\u0643\u0627\u0644\u064a\u0641\u0648\u0631\u0646\u064a\u0627", "name_bn": "\u0995\u09cd\u09af\u09be\u09b2\u09bf\u09ab\u09cb\u09b0\u09cd\u09a8\u09bf\u09af\u09bc\u09be", "name_de": "Kalifornien", "name_en": "California", "name_es": "California", "name_fr": "Californie", "name_el": "\u039a\u03b1\u03bb\u03b9\u03c6\u03cc\u03c1\u03bd\u03b9\u03b1", "name_hi": "\u0915\u0948\u0932\u093f\u092b\u093c\u094b\u0930\u094d\u0928\u093f\u092f\u093e", "name_hu": "Kalifornia", "name_id": "California", "name_it": "California", "name_ja": "\u30ab\u30ea\u30d5\u30a9\u30eb\u30cb\u30a2\u5dde", "name_ko": "\uce98\ub9ac\ud3ec\ub2c8\uc544", "name_nl": "Californi\u00eb", "name_pl": "Kalifornia", "name_pt": "Calif\u00f3rnia", "name_ru": "\u041a\u0430\u043b\u0438\u0444\u043e\u0440\u043d\u0438\u044f", "name_sv": "Kalifornien", "name_tr": "Kaliforniya", "name_vi": "California", "name_zh": "\u52a0\u5229\u798f\u5c3c\u4e9a\u5dde", "ne_id": 1159308415, "name_he": "\u05e7\u05dc\u05d9\u05e4\u05d5\u05e8\u05e0\u05d9\u05d4", "name_uk": "\u041a\u0430\u043b\u0456\u0444\u043e\u0440\u043d\u0456\u044f", "name_ur": "\u06a9\u06cc\u0644\u06cc \u0641\u0648\u0631\u0646\u06cc\u0627", "name_fa": "\u06a9\u0627\u0644\u06cc\u0641\u0631\u0646\u06cc\u0627", "name_zht": "\u52a0\u5229\u798f\u5c3c\u4e9e\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-124.371654, 32.533365, -114.125018, 42.000768], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-114.610543, 34.991117], [-114.610933, 34.907401], [-114.557473, 34.794571], [-114.398001, 34.589698], [-114.378879, 34.540633], [-114.376913, 34.5397], [-114.371024, 34.488492], [-114.308028, 34.43289], [-114.15879, 34.355217], [-114.125068, 34.317182], [-114.125018, 34.314084], [-114.125612, 34.286509], [-114.163514, 34.253363], [-114.32932, 34.142027], [-114.418282, 34.051149], [-114.509051, 33.903921], [-114.495098, 33.784653], [-114.499257, 33.685875], [-114.521559, 33.607608], [-114.556001, 33.535626], [-114.60261, 33.469895], [-114.651159, 33.430619], [-114.701702, 33.417809], [-114.719428, 33.330863], [-114.704388, 33.169781], [-114.648088, 33.07175], [-114.550546, 33.036792], [-114.490863, 32.983618], [-114.469, 32.912306], [-114.477531, 32.842004], [-114.516467, 32.772757], [-114.582176, 32.734723], [-114.7209, 32.724483], [-114.72095, 32.724483], [-114.724773, 32.715343], [-114.839058, 32.704719], [-115.125214, 32.683307], [-115.411374, 32.661883], [-115.697508, 32.64046], [-115.983663, 32.619048], [-116.269824, 32.597624], [-116.555958, 32.576201], [-116.842113, 32.554789], [-117.128274, 32.533365], [-117.130466, 32.53977], [-117.137393, 32.649172], [-117.183744, 32.687877], [-117.243482, 32.664026], [-117.27069, 32.806266], [-117.255759, 32.87337], [-117.262966, 32.938871], [-117.318826, 33.100051], [-117.467422, 33.295487], [-117.788514, 33.538472], [-117.952095, 33.619606], [-118.080514, 33.722152], [-118.161901, 33.750705], [-118.264403, 33.758616], [-118.294171, 33.712308], [-118.410439, 33.743938], [-118.392949, 33.858295], [-118.506196, 34.01741], [-118.598854, 34.035032], [-118.832045, 34.024463], [-119.143732, 34.112024], [-119.235842, 34.164121], [-119.267647, 34.257439], [-119.413688, 34.338573], [-119.606054, 34.418004], [-119.713203, 34.399657], [-119.853301, 34.411962], [-120.052977, 34.469266], [-120.169559, 34.476451], [-120.396471, 34.459554], [-120.481192, 34.471639], [-120.559821, 34.543885], [-120.644696, 34.579986], [-120.626716, 34.668943], [-120.63762, 34.749352], [-120.624904, 34.811985], [-120.663015, 34.949292], [-120.63361, 35.076459], [-120.659088, 35.122403], [-120.707043, 35.157648], [-120.857374, 35.20969], [-120.88489, 35.274949], [-120.860291, 35.365443], [-120.899589, 35.425121], [-121.02284, 35.480777], [-121.137949, 35.607131], [-121.283831, 35.676323], [-121.343855, 35.792229], [-121.433745, 35.86386], [-121.465012, 35.927394], [-121.664353, 36.154042], [-121.877411, 36.331064], [-121.910178, 36.432919], [-121.918648, 36.572346], [-121.835141, 36.657457], [-121.790004, 36.732285], [-121.794525, 36.800961], [-121.807445, 36.851234], [-121.880669, 36.938938], [-122.164215, 36.990969], [-122.3949, 37.207521], [-122.408468, 37.373173], [-122.499237, 37.542615], [-122.500451, 37.652764], [-122.514223, 37.771987], [-122.445624, 37.798003], [-122.384101, 37.788544], [-122.390275, 37.741083], [-122.369708, 37.655862], [-122.297594, 37.591866], [-122.228661, 37.563906], [-122.166, 37.501669], [-122.11905, 37.482827], [-122.070529, 37.478279], [-122.096544, 37.518203], [-122.124142, 37.543812], [-122.15804, 37.62644], [-122.222201, 37.732041], [-122.29599, 37.790356], [-122.333432, 37.896605], [-122.365473, 37.921204], [-122.385446, 37.960579], [-122.314233, 38.007347], [-122.217031, 38.040647], [-122.086728, 38.049612], [-121.716857, 38.034066], [-121.638101, 38.061268], [-121.573013, 38.052402], [-121.525343, 38.055918], [-121.625725, 38.083933], [-121.682206, 38.074781], [-121.748635, 38.080461], [-121.880773, 38.075012], [-121.934155, 38.086823], [-121.993119, 38.120133], [-122.031511, 38.123517], [-122.153778, 38.065531], [-122.208297, 38.072529], [-122.337129, 38.135887], [-122.393351, 38.144808], [-122.483889, 38.108839], [-122.494892, 37.95358], [-122.46691, 37.838213], [-122.521325, 37.826403], [-122.584189, 37.874072], [-122.680698, 37.90234], [-122.760382, 37.945648], [-122.872932, 38.026046], [-122.932, 38.055457], [-122.998791, 37.988616], [-123.001455, 38.019279], [-122.96815, 38.097007], [-122.977604, 38.227327], [-122.87681, 38.123363], [-122.908154, 38.196587], [-122.986547, 38.277095], [-123.046181, 38.305055], [-123.121162, 38.449283], [-123.289731, 38.535867], [-123.424786, 38.675624], [-123.701125, 38.907293], [-123.719522, 39.110968], [-123.820294, 39.3684], [-123.777788, 39.514957], [-123.783501, 39.618723], [-123.832928, 39.775509], [-123.884476, 39.860796], [-124.108515, 40.09453], [-124.324034, 40.251964], [-124.356537, 40.371078], [-124.371654, 40.491202], [-124.324522, 40.598088], [-124.283675, 40.710534], [-124.253908, 40.740307], [-124.242334, 40.727903], [-124.250601, 40.70392], [-124.220009, 40.696482], [-124.208435, 40.746096], [-124.190242, 40.771727], [-124.222487, 40.775034], [-124.21918, 40.790745], [-124.199904, 40.822056], [-124.133091, 40.969778], [-124.140013, 41.155886], [-124.068519, 41.384171], [-124.071903, 41.459516], [-124.117688, 41.621751], [-124.163243, 41.719002], [-124.244608, 41.787941], [-124.208743, 41.888554], [-124.211665, 41.984618], [-124.228409, 42.000768], [-123.955656, 42.000559], [-123.692007, 42.000559], [-123.428351, 42.000559], [-123.164701, 42.000559], [-122.901046, 42.000559], [-122.63739, 42.000559], [-122.37374, 42.000559], [-122.110063, 42.000559], [-121.84638, 42.000559], [-121.58273, 42.000559], [-121.319075, 42.000559], [-121.05542, 42.000559], [-120.79177, 42.000559], [-120.528114, 42.000559], [-120.264464, 42.000559], [-120.000809, 42.000559], [-120.000759, 41.813056], [-120.000704, 41.625519], [-120.000655, 41.438015], [-120.000628, 41.250501], [-120.0006, 41.062975], [-120.000551, 40.87546], [-120.000501, 40.687957], [-120.000446, 40.50042], [-120.000397, 40.312883], [-120.000342, 40.12538], [-120.000293, 39.937876], [-120.000243, 39.750339], [-120.000188, 39.562803], [-120.000139, 39.375299], [-120.000084, 39.187784], [-120.000062, 39.000259], [-119.765839, 38.836782], [-119.531616, 38.673295], [-119.297387, 38.509796], [-119.063164, 38.34632], [-118.828941, 38.182843], [-118.594718, 38.019333], [-118.360495, 37.855857], [-118.126272, 37.69238], [-117.942949, 37.554579], [-117.759603, 37.416788], [-117.576253, 37.278965], [-117.392935, 37.141174], [-117.209611, 37.003373], [-117.02626, 36.865549], [-116.842915, 36.727759], [-116.659592, 36.589968], [-116.405681, 36.391786], [-116.151743, 36.193625], [-115.897827, 35.995476], [-115.643917, 35.797294], [-115.390006, 35.599122], [-115.136096, 35.400962], [-114.88218, 35.202812], [-114.610543, 34.991117]]], [[[-119.882393, 34.07968], [-119.678865, 34.028462], [-119.569129, 34.052961], [-119.549287, 34.028154], [-119.562207, 34.00661], [-119.809581, 33.967795], [-119.885518, 33.994931], [-119.892418, 34.032164], [-119.918049, 34.067848], [-119.882393, 34.07968]]], [[[-120.306602, 34.024869], [-120.359705, 34.022265], [-120.441558, 34.032933], [-120.412928, 34.056323], [-120.367736, 34.073297], [-120.353322, 34.060586], [-120.306602, 34.024869]]], [[[-120.043573, 33.918862], [-120.113902, 33.904855], [-120.167131, 33.918082], [-120.251907, 34.013839], [-120.071841, 34.026506], [-119.994404, 33.984934], [-119.983939, 33.973332], [-120.043573, 33.918862]]], [[[-118.347965, 33.385762], [-118.297478, 33.312131], [-118.370234, 33.321217], [-118.446304, 33.317086], [-118.469353, 33.357142], [-118.49204, 33.412821], [-118.507333, 33.427004], [-118.559425, 33.43197], [-118.563325, 33.437079], [-118.569422, 33.464182], [-118.554849, 33.47708], [-118.391707, 33.415095], [-118.347965, 33.385762]]], [[[-119.438029, 33.217198], [-119.482496, 33.215342], [-119.543679, 33.224614], [-119.575177, 33.278326], [-119.525128, 33.282051], [-119.478799, 33.274635], [-119.442055, 33.232447], [-119.438029, 33.217198]]], [[[-118.350393, 32.827612], [-118.408582, 32.818515], [-118.473204, 32.838928], [-118.52891, 32.935608], [-118.59017, 33.011161], [-118.557101, 33.032661], [-118.507492, 32.959898], [-118.383182, 32.849464], [-118.350393, 32.827612]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3522", "diss_me": 3522, "iso_3166_2": "US-CO", "wikipedia": "http://en.wikipedia.org/wiki/Colorado", "iso_a2": "US", "adm0_sr": 1, "name": "Colorado", "name_alt": "CO|Colo.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US08", "code_hasc": "US.CO", "note": null, "hasc_maybe": null, "region": "West", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Colo.", "postal": "CO", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 8, "mapcolor9": 1, "mapcolor13": 1, "fips": "US08", "fips_alt": null, "woe_id": 2347564, "woe_label": "Colorado, US, United States", "woe_name": "Colorado", "latitude": 38.9998, "longitude": -105.543, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5417618, "gn_name": "Colorado", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.CO", "region_sub": "Mountain", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1261", "name_ar": "\u0643\u0648\u0644\u0648\u0631\u0627\u062f\u0648", "name_bn": "\u0995\u09b2\u09cb\u09b0\u09be\u09a1\u09cb", "name_de": "Colorado", "name_en": "Colorado", "name_es": "Colorado", "name_fr": "Colorado", "name_el": "\u039a\u03bf\u03bb\u03bf\u03c1\u03ac\u03bd\u03c4\u03bf", "name_hi": "\u0915\u0949\u0932\u0930\u093e\u0921\u094b", "name_hu": "Colorado", "name_id": "Colorado", "name_it": "Colorado", "name_ja": "\u30b3\u30ed\u30e9\u30c9\u5dde", "name_ko": "\ucf5c\ub85c\ub77c\ub3c4", "name_nl": "Colorado", "name_pl": "Kolorado", "name_pt": "Colorado", "name_ru": "\u041a\u043e\u043b\u043e\u0440\u0430\u0434\u043e", "name_sv": "Colorado", "name_tr": "Colorado", "name_vi": "Colorado", "name_zh": "\u79d1\u7f57\u62c9\u591a\u5dde", "ne_id": 1159315343, "name_he": "\u05e7\u05d5\u05dc\u05d5\u05e8\u05d3\u05d5", "name_uk": "\u041a\u043e\u043b\u043e\u0440\u0430\u0434\u043e", "name_ur": "\u06a9\u0648\u0644\u0648\u0631\u0627\u0688\u0648", "name_fa": "\u06a9\u0644\u0631\u0627\u062f\u0648", "name_zht": "\u79d1\u7f85\u62c9\u591a\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-109.04667, 37.000846, -102.012783, 41.000858], "geometry": {"type": "Polygon", "coordinates": [[[-109.04667, 37.000846], [-109.046648, 37.250851], [-109.046648, 37.500834], [-109.046621, 37.750828], [-109.046593, 38.000833], [-109.046593, 38.250848], [-109.046566, 38.500853], [-109.046544, 38.750869], [-109.046544, 39.000819], [-109.046516, 39.250835], [-109.046489, 39.50084], [-109.046489, 39.750856], [-109.046467, 40.000872], [-109.04644, 40.250877], [-109.04644, 40.500859], [-109.046412, 40.750842], [-109.04639, 41.000858], [-108.732351, 41.000858], [-108.418313, 41.000858], [-108.104274, 41.000858], [-107.790213, 41.000858], [-107.476147, 41.000858], [-107.162108, 41.000858], [-106.84807, 41.000858], [-106.534037, 41.000858], [-106.219998, 41.000858], [-105.905932, 41.000858], [-105.591871, 41.000858], [-105.277832, 41.000858], [-104.963794, 41.000858], [-104.649755, 41.000858], [-104.335722, 41.000858], [-104.021655, 41.000858], [-103.772084, 41.000836], [-103.522486, 41.000803], [-103.272915, 41.000781], [-103.023344, 41.000748], [-102.773746, 41.000726], [-102.524175, 41.000704], [-102.274604, 41.00065], [-102.025006, 41.000628], [-102.024956, 40.875691], [-102.024879, 40.750744], [-102.024802, 40.625818], [-102.024747, 40.500892], [-102.024698, 40.375934], [-102.024621, 40.251008], [-102.024544, 40.126083], [-102.024489, 40.001124], [-102.02377, 39.813588], [-102.023045, 39.626084], [-102.022319, 39.43858], [-102.021572, 39.251044], [-102.02082, 39.063529], [-102.0201, 38.876025], [-102.019375, 38.688489], [-102.01865, 38.500985], [-102.017925, 38.31347], [-102.017178, 38.125945], [-102.016431, 37.93843], [-102.015706, 37.750927], [-102.014981, 37.56339], [-102.014261, 37.375853], [-102.013536, 37.188372], [-102.012783, 37.000846], [-102.2598, 37.000846], [-102.506811, 37.000846], [-102.753828, 37.000846], [-103.000839, 37.000846], [-103.378724, 37.000846], [-103.756583, 37.000846], [-104.134441, 37.000846], [-104.512299, 37.000846], [-104.890158, 37.000846], [-105.268016, 37.000846], [-105.645874, 37.000846], [-106.023755, 37.000846], [-106.40164, 37.000846], [-106.779499, 37.000846], [-107.157357, 37.000846], [-107.535215, 37.000846], [-107.913073, 37.000846], [-108.290932, 37.000846], [-108.66879, 37.000846], [-109.04667, 37.000846]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3537", "diss_me": 3537, "iso_3166_2": "US-CT", "wikipedia": "http://en.wikipedia.org/wiki/Connecticut", "iso_a2": "US", "adm0_sr": 1, "name": "Connecticut", "name_alt": "CT|Conn.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US09", "code_hasc": "US.CT", "note": null, "hasc_maybe": null, "region": "Northeast", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Conn.", "postal": "CT", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 11, "mapcolor9": 1, "mapcolor13": 1, "fips": "US09", "fips_alt": null, "woe_id": 2347565, "woe_label": "Connecticut, US, United States", "woe_name": "Connecticut", "latitude": 41.6486, "longitude": -72.7594, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4831725, "gn_name": "Connecticut", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.CT", "region_sub": "New England", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q779", "name_ar": "\u0643\u0648\u0646\u064a\u062a\u064a\u0643\u062a", "name_bn": "\u0995\u09be\u09a8\u09c7\u099f\u09bf\u0995\u09be\u099f", "name_de": "Connecticut", "name_en": "Connecticut", "name_es": "Connecticut", "name_fr": "Connecticut", "name_el": "\u039a\u03bf\u03bd\u03ad\u03ba\u03c4\u03b9\u03ba\u03b1\u03c4", "name_hi": "\u0915\u0928\u0947\u0915\u094d\u091f\u093f\u0915\u091f", "name_hu": "Connecticut", "name_id": "Connecticut", "name_it": "Connecticut", "name_ja": "\u30b3\u30cd\u30c1\u30ab\u30c3\u30c8\u5dde", "name_ko": "\ucf54\ub124\ud2f0\ucef7", "name_nl": "Connecticut", "name_pl": "Connecticut", "name_pt": "Connecticut", "name_ru": "\u041a\u043e\u043d\u043d\u0435\u043a\u0442\u0438\u043a\u0443\u0442", "name_sv": "Connecticut", "name_tr": "Connecticut", "name_vi": "Connecticut", "name_zh": "\u5eb7\u6d85\u72c4\u683c\u5dde", "ne_id": 1159315301, "name_he": "\u05e7\u05d5\u05e0\u05d8\u05d9\u05e7\u05d8", "name_uk": "\u041a\u043e\u043d\u043d\u0435\u043a\u0442\u0438\u043a\u0443\u0442", "name_ur": "\u06a9\u0646\u06cc\u06a9\u0679\u06cc\u06a9\u0679", "name_fa": "\u06a9\u0627\u0646\u062a\u06cc\u06a9\u062a", "name_zht": "\u5eb7\u4e43\u72c4\u514b\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-73.723015, 40.99186, -71.795793, 42.055568], "geometry": {"type": "Polygon", "coordinates": [[[-71.800836, 42.011963], [-71.800319, 41.95824], [-71.799561, 41.883027], [-71.798968, 41.828502], [-71.798199, 41.753114], [-71.79732, 41.667586], [-71.796518, 41.588858], [-71.795793, 41.519951], [-71.799232, 41.47917], [-71.804527, 41.416746], [-71.829873, 41.392741], [-71.842353, 41.335513], [-71.929947, 41.341039], [-72.07389, 41.326109], [-72.265272, 41.291666], [-72.371059, 41.312156], [-72.479417, 41.27578], [-72.847152, 41.265849], [-72.924715, 41.285151], [-73.023724, 41.216476], [-73.182268, 41.175838], [-73.582994, 41.021886], [-73.630466, 40.99186], [-73.682113, 41.054702], [-73.723015, 41.104514], [-73.641881, 41.143406], [-73.579797, 41.173146], [-73.521756, 41.200919], [-73.484139, 41.218959], [-73.51445, 41.257455], [-73.544729, 41.295951], [-73.53672, 41.390906], [-73.528689, 41.485839], [-73.520647, 41.580794], [-73.512638, 41.675748], [-73.504629, 41.770703], [-73.496619, 41.865658], [-73.48861, 41.960613], [-73.480568, 42.055568], [-73.396468, 42.052887], [-73.312346, 42.050195], [-73.228234, 42.047515], [-73.144134, 42.044823], [-73.060034, 42.042132], [-72.975922, 42.039451], [-72.8918, 42.036759], [-72.8077, 42.034079], [-72.806458, 42.00803], [-72.763326, 42.011238], [-72.757624, 42.034079], [-72.638115, 42.03265], [-72.518638, 42.031233], [-72.39914, 42.029816], [-72.279642, 42.028388], [-72.160133, 42.02697], [-72.040634, 42.025553], [-71.921136, 42.024125], [-71.801638, 42.022708], [-71.800836, 42.011963]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3556", "diss_me": 3556, "iso_3166_2": "US-DC", "wikipedia": "http://en.wikipedia.org/wiki/Washington,_D.C.", "iso_a2": "US", "adm0_sr": 1, "name": "District of Columbia", "name_alt": "DC|D.C.", "name_local": null, "type": "Federal District", "type_en": "Federal District", "code_local": "US11", "code_hasc": "US.DC", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "D.C.", "postal": "DC", "area_sqkm": 0, "sameascity": 9, "labelrank": 9, "name_len": 20, "mapcolor9": 1, "mapcolor13": 1, "fips": "US11", "fips_alt": null, "woe_id": 2347567, "woe_label": "District of Columbia, US, United States", "woe_name": "District of Columbia", "latitude": 38.8922, "longitude": -77.0113, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4138106, "gn_name": "District of Columbia", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.DC", "region_sub": "South Atlantic", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q61", "name_ar": "\u0648\u0627\u0634\u0646\u0637\u0646", "name_bn": "\u0993\u09af\u09bc\u09be\u09b6\u09bf\u0982\u099f\u09a8", "name_de": "Washington", "name_en": "Washington", "name_es": "Washington D. C.", "name_fr": "Washington", "name_el": "\u039f\u03c5\u03ac\u03c3\u03b9\u03bd\u03b3\u03ba\u03c4\u03bf\u03bd", "name_hi": "\u0935\u0949\u0936\u093f\u0902\u0917\u091f\u0928 \u0921\u0940\u0970 \u0938\u0940\u0970", "name_hu": "Washington", "name_id": "Washington", "name_it": "Washington", "name_ja": "\u30ef\u30b7\u30f3\u30c8\u30f3D.C.", "name_ko": "\uc6cc\uc2f1\ud134 D.C.", "name_nl": "Washington D.C.", "name_pl": "Waszyngton", "name_pt": "Washington", "name_ru": "\u0412\u0430\u0448\u0438\u043d\u0433\u0442\u043e\u043d", "name_sv": "Washington", "name_tr": "Washington", "name_vi": "Washington", "name_zh": "\u534e\u76db\u987f\u54e5\u4f26\u6bd4\u4e9a\u7279\u533a", "ne_id": 1159315327, "name_he": "\u05d5\u05d5\u05e9\u05d9\u05e0\u05d2\u05d8\u05d5\u05df \u05d3\u05d9. \u05e1\u05d9.", "name_uk": "\u0412\u0430\u0448\u0438\u043d\u0433\u0442\u043e\u043d", "name_ur": "\u0648\u0627\u0634\u0646\u06af\u0679\u0646 \u0688\u06cc \u0633\u06cc", "name_fa": "\u0648\u0627\u0634\u06cc\u0646\u06af\u062a\u0646\u060c \u062f\u06cc. \u0633\u06cc.", "name_zht": "\u83ef\u76db\u9813\u54e5\u502b\u6bd4\u4e9e\u7279\u5340", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-77.122053, 38.806526, -76.931242, 39.011783], "geometry": {"type": "Polygon", "coordinates": [[[-77.030361, 38.889253], [-77.053048, 38.915302], [-77.101827, 38.935967], [-77.122053, 38.943536], [-77.042116, 39.011783], [-76.988789, 38.952347], [-76.931242, 38.88822], [-77.019737, 38.806526], [-77.030361, 38.889253]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3555", "diss_me": 3555, "iso_3166_2": "US-DE", "wikipedia": "http://en.wikipedia.org/wiki/Delaware", "iso_a2": "US", "adm0_sr": 1, "name": "Delaware", "name_alt": "DE|Del.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US10", "code_hasc": "US.DE", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Del.", "postal": "DE", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 8, "mapcolor9": 1, "mapcolor13": 1, "fips": "US10", "fips_alt": null, "woe_id": 2347566, "woe_label": "Delaware, US, United States", "woe_name": "Delaware", "latitude": 38.8657, "longitude": -75.4112, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4142224, "gn_name": "Delaware", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.DE", "region_sub": "South Atlantic", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1393", "name_ar": "\u062f\u064a\u0644\u0627\u0648\u064a\u0631", "name_bn": "\u09a1\u09c7\u09b2\u09be\u0993\u09af\u09bc\u09cd\u09af\u09be\u09b0", "name_de": "Delaware", "name_en": "Delaware", "name_es": "Delaware", "name_fr": "Delaware", "name_el": "\u039d\u03c4\u03ad\u03bb\u03b1\u03b3\u03bf\u03c5\u03b5\u03c1", "name_hi": "\u0921\u0947\u0932\u093e\u0935\u0947\u092f\u0930", "name_hu": "Delaware", "name_id": "Delaware", "name_it": "Delaware", "name_ja": "\u30c7\u30e9\u30a6\u30a7\u30a2\u5dde", "name_ko": "\ub378\ub77c\uc6e8\uc5b4", "name_nl": "Delaware", "name_pl": "Delaware", "name_pt": "Delaware", "name_ru": "\u0414\u0435\u043b\u0430\u0432\u044d\u0440", "name_sv": "Delaware", "name_tr": "Delaware", "name_vi": "Delaware", "name_zh": "\u7279\u62c9\u534e\u5dde", "ne_id": 1159315325, "name_he": "\u05d3\u05dc\u05d0\u05d5\u05d5\u05e8", "name_uk": "\u0414\u0435\u043b\u0430\u0432\u0435\u0440", "name_ur": "\u0688\u06cc\u0644\u0627\u0648\u06cc\u0626\u0631", "name_fa": "\u062f\u0644\u0627\u0648\u06cc\u0631", "name_zht": "\u7279\u62c9\u83ef\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-75.78472, 38.454865, -75.035881, 39.843438], "geometry": {"type": "Polygon", "coordinates": [[[-75.037661, 38.45559], [-75.144657, 38.454865], [-75.366273, 38.454919], [-75.587856, 38.454996], [-75.688601, 38.455018], [-75.690908, 38.455018], [-75.693226, 38.455018], [-75.695533, 38.455018], [-75.697829, 38.455018], [-75.700125, 38.455018], [-75.702433, 38.45504], [-75.704729, 38.455073], [-75.707025, 38.455073], [-75.716748, 38.613485], [-75.72646, 38.771897], [-75.736172, 38.930309], [-75.745883, 39.088721], [-75.755606, 39.247144], [-75.765318, 39.405555], [-75.77503, 39.563945], [-75.78472, 39.722357], [-75.709145, 39.802898], [-75.676823, 39.827233], [-75.634581, 39.839482], [-75.510446, 39.843438], [-75.421029, 39.815422], [-75.464403, 39.780936], [-75.50213, 39.717391], [-75.587603, 39.640784], [-75.581583, 39.589467], [-75.567268, 39.552992], [-75.573882, 39.476945], [-75.519807, 39.40282], [-75.412657, 39.281377], [-75.392168, 39.092753], [-75.310407, 38.966564], [-75.185064, 38.819391], [-75.088692, 38.777533], [-75.08399, 38.72281], [-75.128485, 38.632448], [-75.187108, 38.591128], [-75.110863, 38.599379], [-75.072883, 38.578735], [-75.035881, 38.503336], [-75.037661, 38.45559]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3542", "diss_me": 3542, "iso_3166_2": "US-FL", "wikipedia": "http://en.wikipedia.org/wiki/Florida", "iso_a2": "US", "adm0_sr": 5, "name": "Florida", "name_alt": "FL|Fla.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US12", "code_hasc": "US.FL", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 8, "abbrev": "Fla.", "postal": "FL", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 7, "mapcolor9": 1, "mapcolor13": 1, "fips": "US12", "fips_alt": null, "woe_id": 2347568, "woe_label": "Florida, US, United States", "woe_name": "Florida", "latitude": 28.1568, "longitude": -81.6228, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4155751, "gn_name": "Florida", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.FL", "region_sub": "South Atlantic", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q812", "name_ar": "\u0641\u0644\u0648\u0631\u064a\u062f\u0627", "name_bn": "\u09ab\u09cd\u09b2\u09cb\u09b0\u09bf\u09a1\u09be", "name_de": "Florida", "name_en": "Florida", "name_es": "Florida", "name_fr": "Floride", "name_el": "\u03a6\u03bb\u03cc\u03c1\u03b9\u03bd\u03c4\u03b1", "name_hi": "\u092b\u093c\u094d\u0932\u094b\u0930\u093f\u0921\u093e", "name_hu": "Florida", "name_id": "Florida", "name_it": "Florida", "name_ja": "\u30d5\u30ed\u30ea\u30c0\u5dde", "name_ko": "\ud50c\ub85c\ub9ac\ub2e4", "name_nl": "Florida", "name_pl": "Floryda", "name_pt": "Fl\u00f3rida", "name_ru": "\u0424\u043b\u043e\u0440\u0438\u0434\u0430", "name_sv": "Florida", "name_tr": "Florida", "name_vi": "Florida", "name_zh": "\u4f5b\u7f57\u91cc\u8fbe\u5dde", "ne_id": 1159315207, "name_he": "\u05e4\u05dc\u05d5\u05e8\u05d9\u05d3\u05d4", "name_uk": "\u0424\u043b\u043e\u0440\u0438\u0434\u0430", "name_ur": "\u0641\u0644\u0648\u0631\u06cc\u0688\u0627", "name_fa": "\u0641\u0644\u0648\u0631\u06cc\u062f\u0627", "name_zht": "\u4f5b\u7f85\u91cc\u9054\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-87.607438, 24.542349, -80.041307, 31.001673], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-87.489511, 30.377683], [-87.480106, 30.411707], [-87.444807, 30.442557], [-87.429382, 30.477856], [-87.43381, 30.545938], [-87.408278, 30.641465], [-87.421659, 30.671589], [-87.566195, 30.795636], [-87.601055, 30.860598], [-87.607438, 30.929328], [-87.593694, 31.000739], [-87.2703, 31.000794], [-86.94694, 31.000849], [-86.623568, 31.000893], [-86.300175, 31.000948], [-85.976792, 31.001003], [-85.653399, 31.001058], [-85.330005, 31.001102], [-85.007282, 31.001673], [-84.966335, 30.922638], [-84.886882, 30.75926], [-84.883938, 30.72094], [-84.790378, 30.715128], [-84.630978, 30.705779], [-84.471555, 30.696451], [-84.312166, 30.687124], [-84.152765, 30.677763], [-83.993342, 30.668414], [-83.833942, 30.659087], [-83.674552, 30.649759], [-83.515129, 30.640399], [-83.355707, 30.63105], [-83.196306, 30.621722], [-83.036916, 30.612395], [-82.877494, 30.603045], [-82.718093, 30.593685], [-82.558704, 30.584358], [-82.399281, 30.57503], [-82.23988, 30.565681], [-82.238924, 30.532612], [-82.212733, 30.480746], [-82.20624, 30.421606], [-82.194232, 30.393437], [-82.162624, 30.375716], [-82.112274, 30.371355], [-82.061759, 30.404599], [-82.029822, 30.477702], [-82.021835, 30.559869], [-82.04116, 30.65322], [-82.038193, 30.73197], [-82.012947, 30.778069], [-81.983053, 30.789494], [-81.957081, 30.81429], [-81.935592, 30.819509], [-81.880452, 30.806336], [-81.673359, 30.740243], [-81.503939, 30.731432], [-81.457192, 30.640761], [-81.385726, 30.269984], [-81.337101, 30.141213], [-81.249507, 29.793792], [-81.104531, 29.456963], [-80.900021, 29.049853], [-80.5643, 28.556402], [-80.524123, 28.48609], [-80.567816, 28.426456], [-80.581153, 28.36468], [-80.584977, 28.271604], [-80.572859, 28.180868], [-80.533165, 28.07007], [-80.456887, 27.900672], [-80.499547, 27.934466], [-80.610015, 28.177605], [-80.62288, 28.320361], [-80.606938, 28.522883], [-80.632877, 28.518027], [-80.653883, 28.452186], [-80.665484, 28.374908], [-80.693489, 28.344959], [-80.731754, 28.46292], [-80.729051, 28.516214], [-80.688457, 28.57854], [-80.700267, 28.600941], [-80.765943, 28.632823], [-80.779896, 28.682954], [-80.771008, 28.732458], [-80.80868, 28.758946], [-80.83819, 28.75765], [-80.818425, 28.635614], [-80.787213, 28.560632], [-80.748607, 28.381005], [-80.686359, 28.272175], [-80.650115, 28.180911], [-80.226108, 27.20705], [-80.12577, 27.083004], [-80.088647, 26.99396], [-80.050041, 26.807697], [-80.041307, 26.568613], [-80.110587, 26.131588], [-80.126374, 25.833518], [-80.136295, 25.842614], [-80.142909, 25.874024], [-80.158927, 25.878342], [-80.219077, 25.741738], [-80.300826, 25.618537], [-80.327754, 25.427078], [-80.36692, 25.331267], [-80.484639, 25.22983], [-80.557632, 25.232412], [-80.736544, 25.156342], [-80.862217, 25.176195], [-81.011971, 25.133249], [-81.110497, 25.13805], [-81.167395, 25.228533], [-81.158683, 25.268996], [-81.136029, 25.309646], [-81.097654, 25.319149], [-80.965367, 25.224304], [-80.940406, 25.264217], [-80.980353, 25.311656], [-81.05685, 25.338144], [-81.113309, 25.367236], [-81.227128, 25.583403], [-81.345077, 25.731817], [-81.364929, 25.831035], [-81.568242, 25.891547], [-81.715503, 25.983173], [-81.81149, 26.146101], [-81.866576, 26.434997], [-81.931483, 26.467451], [-81.958949, 26.489929], [-81.895514, 26.597166], [-81.82864, 26.687056], [-81.881561, 26.664677], [-81.920552, 26.631422], [-81.970188, 26.552045], [-82.006388, 26.539851], [-82.039611, 26.552045], [-82.077876, 26.704338], [-82.066923, 26.891567], [-82.013254, 26.961561], [-82.095685, 26.963418], [-82.181103, 26.936776], [-82.168623, 26.874351], [-82.180664, 26.840096], [-82.242858, 26.848874], [-82.290066, 26.870814], [-82.354039, 26.935743], [-82.44137, 27.059691], [-82.620458, 27.401069], [-82.655361, 27.449233], [-82.714589, 27.499583], [-82.686705, 27.515272], [-82.63585, 27.524577], [-82.520845, 27.678254], [-82.430515, 27.771121], [-82.400544, 27.83538], [-82.405763, 27.862901], [-82.445709, 27.902848], [-82.498136, 27.867911], [-82.520614, 27.877887], [-82.579611, 27.958449], [-82.635937, 27.981213], [-82.675203, 27.963767], [-82.633817, 27.897783], [-82.596551, 27.873239], [-82.610977, 27.777219], [-82.626006, 27.745985], [-82.660887, 27.718409], [-82.715336, 27.733109], [-82.742856, 27.709367], [-82.775299, 27.734383], [-82.807555, 27.776549], [-82.843513, 27.846004], [-82.748536, 28.236799], [-82.660635, 28.485859], [-82.650604, 28.769922], [-82.644023, 28.81201], [-82.651483, 28.887486], [-82.769333, 29.051556], [-83.29047, 29.451898], [-83.694371, 29.92598], [-84.04422, 30.103794], [-84.309683, 30.064759], [-84.355616, 30.029021], [-84.375337, 29.982274], [-84.358693, 29.929386], [-84.38283, 29.907369], [-84.454065, 29.91016], [-84.549976, 29.897866], [-84.800552, 29.773072], [-84.888926, 29.77761], [-84.96917, 29.745288], [-85.029298, 29.721085], [-85.18604, 29.707901], [-85.318942, 29.680205], [-85.376356, 29.69519], [-85.413798, 29.76759], [-85.413798, 29.842473], [-85.383442, 29.785058], [-85.33641, 29.740124], [-85.314888, 29.758076], [-85.306857, 29.797846], [-85.353626, 29.87575], [-85.504281, 29.975792], [-85.6758, 30.121932], [-85.623472, 30.117076], [-85.610277, 30.148398], [-85.663418, 30.189454], [-85.640973, 30.236893], [-85.603532, 30.286782], [-85.675899, 30.279289], [-85.740806, 30.244386], [-85.742948, 30.201253], [-85.755791, 30.166998], [-85.79075, 30.171986], [-85.855657, 30.214404], [-86.17515, 30.332518], [-86.454434, 30.399128], [-86.240079, 30.429099], [-86.123833, 30.405797], [-86.137709, 30.441557], [-86.165691, 30.464244], [-86.257394, 30.493017], [-86.374179, 30.482064], [-86.447952, 30.49561], [-86.523373, 30.467112], [-86.606078, 30.424682], [-86.679642, 30.402896], [-86.967605, 30.372354], [-87.201152, 30.339231], [-87.163722, 30.374189], [-87.123776, 30.396667], [-86.985798, 30.430857], [-86.965155, 30.501916], [-86.997576, 30.570328], [-87.033908, 30.553925], [-87.072019, 30.500433], [-87.118788, 30.538962], [-87.170588, 30.538786], [-87.184651, 30.453697], [-87.251074, 30.396667], [-87.281045, 30.339231], [-87.475767, 30.294275], [-87.500728, 30.30926], [-87.443731, 30.363829], [-87.448301, 30.394162], [-87.489511, 30.377683]]], [[[-84.907888, 29.642632], [-85.00827, 29.606618], [-85.116738, 29.632788], [-85.049326, 29.637776], [-85.000547, 29.627185], [-84.876984, 29.678678], [-84.812186, 29.717646], [-84.737172, 29.732445], [-84.907888, 29.642632]]], [[[-80.186755, 27.27844], [-80.170506, 27.204798], [-80.262462, 27.37557], [-80.376072, 27.643427], [-80.436892, 27.850553], [-80.395759, 27.794555], [-80.355505, 27.678617], [-80.186755, 27.27844]]], [[[-82.083765, 26.552331], [-82.085215, 26.493598], [-82.135598, 26.59197], [-82.169139, 26.700723], [-82.121129, 26.665534], [-82.083765, 26.552331]]], [[[-82.037183, 26.45363], [-82.072844, 26.427537], [-82.144958, 26.446654], [-82.184388, 26.480942], [-82.201384, 26.548046], [-82.138597, 26.476987], [-82.116064, 26.460914], [-82.037183, 26.45363]]], [[[-80.381828, 25.142291], [-80.580582, 24.954238], [-80.558566, 25.001314], [-80.481046, 25.10196], [-80.456019, 25.149322], [-80.403669, 25.179337], [-80.354934, 25.233653], [-80.351286, 25.296956], [-80.280491, 25.341242], [-80.257057, 25.347603], [-80.381828, 25.142291]]], [[[-80.638304, 24.903184], [-80.665144, 24.898449], [-80.62567, 24.941087], [-80.614607, 24.937934], [-80.638304, 24.903184]]], [[[-80.829401, 24.803681], [-80.848363, 24.803681], [-80.838882, 24.817886], [-80.799408, 24.846308], [-80.785192, 24.835278], [-80.786774, 24.82104], [-80.829401, 24.803681]]], [[[-81.044194, 24.716812], [-81.090007, 24.693115], [-81.137369, 24.710506], [-81.08525, 24.734204], [-80.930486, 24.759472], [-80.988922, 24.727875], [-81.044194, 24.716812]]], [[[-81.334794, 24.650488], [-81.364797, 24.629943], [-81.379036, 24.636271], [-81.379036, 24.666275], [-81.421662, 24.7326], [-81.420091, 24.749991], [-81.322313, 24.685084], [-81.319841, 24.667615], [-81.334794, 24.650488]]], [[[-81.566693, 24.599896], [-81.631501, 24.590019], [-81.57925, 24.629372], [-81.562298, 24.689138], [-81.531636, 24.642479], [-81.532229, 24.614156], [-81.566693, 24.599896]]], [[[-81.783838, 24.54458], [-81.809216, 24.542349], [-81.811413, 24.557807], [-81.767688, 24.576715], [-81.738651, 24.575429], [-81.739761, 24.5545], [-81.783838, 24.54458]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3543", "diss_me": 3543, "iso_3166_2": "US-GA", "wikipedia": "http://en.wikipedia.org/wiki/Georgia_(U.S._state)", "iso_a2": "US", "adm0_sr": 6, "name": "Georgia", "name_alt": "GA|Ga.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US13", "code_hasc": "US.GA", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Ga.", "postal": "GA", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 7, "mapcolor9": 1, "mapcolor13": 1, "fips": "US13", "fips_alt": null, "woe_id": 2347569, "woe_label": "Georgia, US, United States", "woe_name": "Georgia", "latitude": 32.8547, "longitude": -83.4078, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4197000, "gn_name": "Georgia", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.GA", "region_sub": "South Atlantic", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1428", "name_ar": "\u062c\u0648\u0631\u062c\u064a\u0627", "name_bn": "\u099c\u09b0\u09cd\u099c\u09bf\u09af\u09bc\u09be", "name_de": "Georgia", "name_en": "Georgia", "name_es": "Georgia", "name_fr": "G\u00e9orgie", "name_el": "\u03a4\u03b6\u03cc\u03c1\u03c4\u03b6\u03b9\u03b1", "name_hi": "\u091c\u0949\u0930\u094d\u091c\u093f\u092f\u093e", "name_hu": "Georgia", "name_id": "Georgia", "name_it": "Georgia", "name_ja": "\u30b8\u30e7\u30fc\u30b8\u30a2\u5dde", "name_ko": "\uc870\uc9c0\uc544", "name_nl": "Georgia", "name_pl": "Georgia", "name_pt": "Ge\u00f3rgia", "name_ru": "\u0414\u0436\u043e\u0440\u0434\u0436\u0438\u044f", "name_sv": "Georgia", "name_tr": "Georgia", "name_vi": "Georgia", "name_zh": "\u4f50\u6cbb\u4e9a\u5dde", "ne_id": 1159311857, "name_he": "\u05d2'\u05d5\u05e8\u05d2'\u05d9\u05d4", "name_uk": "\u0414\u0436\u043e\u0440\u0434\u0436\u0456\u044f", "name_ur": "\u0631\u06cc\u0627\u0633\u062a \u062c\u0627\u0631\u062c\u06cc\u0627", "name_fa": "\u062c\u0648\u0631\u062c\u06cc\u0627", "name_zht": "\u55ac\u6cbb\u4e9e\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-85.623604, 30.371355, -80.872346, 35.001477], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-85.007282, 31.001673], [-85.067443, 31.117579], [-85.092601, 31.295711], [-85.054885, 31.572677], [-85.067047, 31.635178], [-85.067201, 31.635387], [-85.124824, 31.77677], [-85.124132, 31.880536], [-85.06441, 32.050527], [-85.064564, 32.051043], [-85.034627, 32.147372], [-84.992977, 32.201831], [-84.929696, 32.246556], [-84.921533, 32.285887], [-84.9685, 32.319813], [-84.985968, 32.360946], [-84.973905, 32.409286], [-85.015038, 32.526158], [-85.156531, 32.804277], [-85.176317, 32.898221], [-85.200971, 32.956229], [-85.227382, 33.084022], [-85.253782, 33.211826], [-85.280193, 33.339619], [-85.306626, 33.46739], [-85.333059, 33.595161], [-85.359459, 33.722954], [-85.38587, 33.850747], [-85.412271, 33.978551], [-85.438682, 34.106344], [-85.465115, 34.234137], [-85.491548, 34.36193], [-85.517948, 34.489679], [-85.544359, 34.617472], [-85.57077, 34.745265], [-85.59717, 34.873069], [-85.623604, 35.000862], [-85.298892, 34.997654], [-84.974158, 34.994479], [-84.649424, 34.991304], [-84.32469, 34.988096], [-84.022225, 34.991457], [-83.719772, 34.994786], [-83.417307, 34.998126], [-83.114821, 35.001477], [-83.121357, 35.000554], [-83.1704, 34.932911], [-83.316716, 34.805657], [-83.355575, 34.708318], [-83.166522, 34.599597], [-83.165896, 34.598531], [-83.052781, 34.51086], [-82.975679, 34.476396], [-82.896819, 34.465806], [-82.847732, 34.436911], [-82.818607, 34.366072], [-82.818585, 34.366017], [-82.589268, 34.017377], [-82.589344, 34.017618], [-82.351897, 33.837728], [-82.256623, 33.749233], [-82.208361, 33.663584], [-82.005718, 33.522893], [-81.936394, 33.447285], [-81.932845, 33.38987], [-81.908741, 33.349254], [-81.864093, 33.325436], [-81.821279, 33.274096], [-81.780322, 33.195292], [-81.69932, 33.126759], [-81.57824, 33.068575], [-81.489778, 32.935663], [-81.433813, 32.728032], [-81.37697, 32.607468], [-81.290332, 32.557239], [-81.171504, 32.380139], [-81.132953, 32.27467], [-81.135018, 32.181858], [-81.074813, 32.109699], [-80.872346, 32.029565], [-80.923432, 31.944894], [-81.045535, 31.892038], [-81.082877, 31.894104], [-81.113287, 31.878624], [-81.095511, 31.840897], [-81.065046, 31.813464], [-81.066134, 31.787987], [-81.098401, 31.75338], [-81.162121, 31.743723], [-81.197904, 31.704216], [-81.186588, 31.666961], [-81.165527, 31.646153], [-81.169922, 31.610316], [-81.242399, 31.574325], [-81.25935, 31.538927], [-81.223414, 31.528468], [-81.195685, 31.538927], [-81.175426, 31.531302], [-81.21891, 31.472141], [-81.257933, 31.436018], [-81.294979, 31.371209], [-81.380947, 31.353258], [-81.377739, 31.332296], [-81.329136, 31.313751], [-81.288464, 31.263906], [-81.364874, 31.171895], [-81.412621, 31.179443], [-81.441767, 31.199724], [-81.460345, 31.127071], [-81.453215, 31.088279], [-81.471376, 31.009012], [-81.500599, 30.913772], [-81.520397, 30.874649], [-81.516233, 30.80181], [-81.503939, 30.731432], [-81.673359, 30.740243], [-81.880452, 30.806336], [-81.935592, 30.819509], [-81.957081, 30.81429], [-81.983053, 30.789494], [-82.012947, 30.778069], [-82.038193, 30.73197], [-82.04116, 30.65322], [-82.021835, 30.559869], [-82.029822, 30.477702], [-82.061759, 30.404599], [-82.112274, 30.371355], [-82.162624, 30.375716], [-82.194232, 30.393437], [-82.20624, 30.421606], [-82.212733, 30.480746], [-82.238924, 30.532612], [-82.23988, 30.565681], [-82.399281, 30.57503], [-82.558704, 30.584358], [-82.718093, 30.593685], [-82.877494, 30.603045], [-83.036916, 30.612395], [-83.196306, 30.621722], [-83.355707, 30.63105], [-83.515129, 30.640399], [-83.674552, 30.649759], [-83.833942, 30.659087], [-83.993342, 30.668414], [-84.152765, 30.677763], [-84.312166, 30.687124], [-84.471555, 30.696451], [-84.630978, 30.705779], [-84.790378, 30.715128], [-84.883938, 30.72094], [-84.886882, 30.75926], [-84.966335, 30.922638], [-85.007282, 31.001673]]], [[[-81.418982, 30.971439], [-81.463498, 30.727762], [-81.482725, 30.814093], [-81.484636, 30.897831], [-81.450941, 30.947412], [-81.418982, 30.971439]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3517", "diss_me": 3517, "iso_3166_2": "US-HI", "wikipedia": "http://en.wikipedia.org/wiki/Hawaii", "iso_a2": "US", "adm0_sr": 8, "name": "Hawaii", "name_alt": "HI|Hawaii", "name_local": null, "type": "State", "type_en": "State", "code_local": "US15", "code_hasc": "US.HI", "note": null, "hasc_maybe": null, "region": "West", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Hawaii", "postal": "HI", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 6, "mapcolor9": 1, "mapcolor13": 1, "fips": "US15", "fips_alt": null, "woe_id": 2347570, "woe_label": "Hawaii, US, United States", "woe_name": "Hawaii", "latitude": 21.4919, "longitude": -157.999, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5855797, "gn_name": "Hawaii", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.HI", "region_sub": "Pacific", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q782", "name_ar": "\u0647\u0627\u0648\u0627\u064a", "name_bn": "\u09b9\u09be\u0993\u09af\u09bc\u09be\u0987", "name_de": "Hawaii", "name_en": "Hawaii", "name_es": "Haw\u00e1i", "name_fr": "Hawa\u00ef", "name_el": "\u03a7\u03b1\u03b2\u03ac\u03b7", "name_hi": "\u0939\u0935\u093e\u0908", "name_hu": "Hawaii", "name_id": "Hawaii", "name_it": "Hawaii", "name_ja": "\u30cf\u30ef\u30a4\u5dde", "name_ko": "\ud558\uc640\uc774", "name_nl": "Hawa\u00ef", "name_pl": "Hawaje", "name_pt": "Hava\u00ed", "name_ru": "\u0413\u0430\u0432\u0430\u0439\u0438", "name_sv": "Hawaii", "name_tr": "Hawaii", "name_vi": "Hawaii", "name_zh": "\u590f\u5a01\u5937\u5dde", "ne_id": 1159308409, "name_he": "\u05d4\u05d5\u05d5\u05d0\u05d9", "name_uk": "\u0413\u0430\u0432\u0430\u0457", "name_ur": "\u06c1\u0648\u0627\u0626\u06cc", "name_fa": "\u0647\u0627\u0648\u0627\u0626\u06cc", "name_zht": "\u590f\u5a01\u5937\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-177.390485, 18.963909, -154.804188, 28.221176], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-177.371467, 28.2005], [-177.390485, 28.196369], [-177.388831, 28.208773], [-177.370641, 28.221176], [-177.354104, 28.217035], [-177.361546, 28.207114], [-177.371467, 28.2005]]], [[[-159.372773, 21.93236], [-159.460674, 21.876132], [-159.51186, 21.900368], [-159.608858, 21.90952], [-159.646373, 21.95174], [-159.748022, 21.989819], [-159.789182, 22.041806], [-159.726626, 22.1402], [-159.579222, 22.223135], [-159.352052, 22.219576], [-159.304792, 22.154053], [-159.300658, 22.105263], [-159.33019, 22.050694], [-159.34373, 21.973647], [-159.372773, 21.93236]]], [[[-160.18001, 21.841075], [-160.200241, 21.796888], [-160.234711, 21.803677], [-160.243445, 21.843063], [-160.220912, 21.89727], [-160.16386, 21.944039], [-160.100636, 22.015241], [-160.048728, 22.00465], [-160.076711, 21.95809], [-160.080042, 21.907443], [-160.153395, 21.878769], [-160.18001, 21.841075]]], [[[-157.799355, 21.456652], [-157.764989, 21.450939], [-157.720885, 21.457707], [-157.705537, 21.378078], [-157.65417, 21.333913], [-157.635411, 21.307645], [-157.690887, 21.279739], [-157.798786, 21.268621], [-157.849326, 21.290847], [-157.901753, 21.34056], [-157.958442, 21.326915], [-157.968311, 21.366916], [-157.97844, 21.378484], [-158.017274, 21.36774], [-157.98097, 21.316115], [-158.079157, 21.312237], [-158.110345, 21.318598], [-158.137835, 21.377144], [-158.239093, 21.489337], [-158.238681, 21.533051], [-158.273124, 21.585247], [-158.123108, 21.600255], [-158.02035, 21.691804], [-157.962496, 21.701362], [-157.851496, 21.553365], [-157.854338, 21.511913], [-157.829584, 21.471451], [-157.799355, 21.456652]]], [[[-157.213602, 21.215392], [-157.002296, 21.18796], [-156.952353, 21.199693], [-156.917213, 21.177314], [-156.742209, 21.163515], [-156.712161, 21.155088], [-156.747894, 21.103574], [-156.85985, 21.056332], [-157.020874, 21.097784], [-157.290314, 21.112582], [-157.27949, 21.152353], [-157.253807, 21.180566], [-157.249931, 21.229763], [-157.213602, 21.215392]]], [[[-156.486826, 20.932571], [-156.460833, 20.914741], [-156.354405, 20.941459], [-156.277537, 20.951281], [-156.148346, 20.885495], [-156.103516, 20.84033], [-156.018636, 20.792067], [-155.989854, 20.757131], [-156.013574, 20.714811], [-156.107133, 20.644784], [-156.234748, 20.628613], [-156.309963, 20.598796], [-156.408793, 20.605179], [-156.438223, 20.617868], [-156.448868, 20.706231], [-156.480056, 20.801241], [-156.543823, 20.790002], [-156.615449, 20.821829], [-156.689681, 20.901414], [-156.697769, 20.949062], [-156.656867, 21.024505], [-156.585423, 21.034327], [-156.532301, 20.992678], [-156.486826, 20.932571]]], [[[-156.849595, 20.772632], [-156.908866, 20.744474], [-156.973411, 20.757548], [-156.988448, 20.825707], [-157.050565, 20.912466], [-156.941784, 20.930045], [-156.880549, 20.90482], [-156.848276, 20.877794], [-156.80939, 20.831135], [-156.849595, 20.772632]]], [[[-155.581325, 19.012018], [-155.625611, 18.963909], [-155.680751, 18.967677], [-155.881306, 19.070521], [-155.905594, 19.125815], [-155.890738, 19.382543], [-155.965824, 19.590789], [-156.048686, 19.749959], [-155.988407, 19.831609], [-155.908877, 19.894704], [-155.820302, 20.01418], [-155.892754, 20.167396], [-155.874278, 20.259802], [-155.831621, 20.27582], [-155.622073, 20.163419], [-155.198789, 19.994383], [-155.086083, 19.875632], [-155.065929, 19.748201], [-154.989035, 19.731974], [-154.952577, 19.644644], [-154.841343, 19.568157], [-154.804188, 19.524443], [-154.850283, 19.454108], [-155.053476, 19.319185], [-155.309611, 19.260167], [-155.535229, 19.109072], [-155.581325, 19.012018]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3529", "diss_me": 3529, "iso_3166_2": "US-IA", "wikipedia": "http://en.wikipedia.org/wiki/Iowa", "iso_a2": "US", "adm0_sr": 1, "name": "Iowa", "name_alt": "IA|Iowa", "name_local": null, "type": "State", "type_en": "State", "code_local": "US19", "code_hasc": "US.IA", "note": null, "hasc_maybe": null, "region": "Midwest", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Iowa", "postal": "IA", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 4, "mapcolor9": 1, "mapcolor13": 1, "fips": "US19", "fips_alt": null, "woe_id": 2347574, "woe_label": "Iowa, US, United States", "woe_name": "Iowa", "latitude": 42.0423, "longitude": -93.3891, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4862182, "gn_name": "Iowa", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.IA", "region_sub": "West North Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1546", "name_ar": "\u0622\u064a\u0648\u0627", "name_bn": "\u0986\u0987\u0993\u09af\u09bc\u09be", "name_de": "Iowa", "name_en": "Iowa", "name_es": "Iowa", "name_fr": "Iowa", "name_el": "\u0386\u03b9\u03bf\u03b2\u03b1", "name_hi": "\u0906\u092f\u094b\u0935\u093e", "name_hu": "Iowa", "name_id": "Iowa", "name_it": "Iowa", "name_ja": "\u30a2\u30a4\u30aa\u30ef\u5dde", "name_ko": "\uc544\uc774\uc624\uc640", "name_nl": "Iowa", "name_pl": "Iowa", "name_pt": "Iowa", "name_ru": "\u0410\u0439\u043e\u0432\u0430", "name_sv": "Iowa", "name_tr": "Iowa", "name_vi": "Iowa", "name_zh": "\u827e\u5965\u74e6\u5dde", "ne_id": 1159315357, "name_he": "\u05d0\u05d9\u05d5\u05d5\u05d4", "name_uk": "\u0410\u0439\u043e\u0432\u0430", "name_ur": "\u0622\u0626\u06cc\u0648\u0648\u0627", "name_fa": "\u0622\u06cc\u0648\u0648\u0627", "name_zht": "\u611b\u8377\u83ef\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-96.626835, 40.37945, -90.149433, 43.502412], "geometry": {"type": "Polygon", "coordinates": [[[-91.441952, 40.37945], [-91.529931, 40.432316], [-91.545487, 40.469318], [-91.616855, 40.50688], [-91.627423, 40.530753], [-91.682047, 40.551869], [-91.73153, 40.624653], [-91.983787, 40.623203], [-92.236044, 40.621764], [-92.488301, 40.620314], [-92.740564, 40.618864], [-92.992821, 40.617413], [-93.245078, 40.615974], [-93.497335, 40.614524], [-93.749598, 40.613074], [-94.001855, 40.611635], [-94.254112, 40.610184], [-94.506369, 40.608734], [-94.758631, 40.607284], [-95.010888, 40.605845], [-95.263146, 40.604395], [-95.51543, 40.602944], [-95.765029, 40.601868], [-95.826107, 40.676179], [-95.859, 40.745108], [-95.838148, 40.777748], [-95.834017, 40.88949], [-95.846597, 41.080333], [-95.870887, 41.187824], [-95.906906, 41.21195], [-95.911169, 41.245183], [-95.883626, 41.287557], [-95.891943, 41.316166], [-95.936025, 41.330986], [-95.94972, 41.367428], [-95.932977, 41.425458], [-95.943567, 41.460933], [-95.98158, 41.473798], [-95.997367, 41.493639], [-95.990957, 41.52049], [-96.011397, 41.537881], [-96.058627, 41.54578], [-96.077771, 41.611281], [-96.068806, 41.734328], [-96.086637, 41.821372], [-96.13123, 41.872437], [-96.153763, 41.920436], [-96.154203, 41.965293], [-96.201384, 42.036122], [-96.295333, 42.132912], [-96.356104, 42.260133], [-96.383751, 42.417776], [-96.451004, 42.505985], [-96.480953, 42.511259], [-96.506326, 42.593579], [-96.53361, 42.630164], [-96.538702, 42.658585], [-96.62177, 42.729535], [-96.626835, 42.757001], [-96.616084, 42.791388], [-96.562576, 42.85857], [-96.513274, 42.969059], [-96.502112, 43.043294], [-96.462688, 43.099181], [-96.461293, 43.129767], [-96.468137, 43.17023], [-96.49028, 43.205529], [-96.55539, 43.231676], [-96.563454, 43.242685], [-96.569942, 43.283323], [-96.542526, 43.309031], [-96.534956, 43.338057], [-96.541647, 43.373455], [-96.581285, 43.434923], [-96.598622, 43.497501], [-96.453619, 43.501171], [-96.128418, 43.501226], [-95.80319, 43.50127], [-95.477967, 43.501325], [-95.152766, 43.50138], [-94.827565, 43.501424], [-94.502342, 43.501478], [-94.177114, 43.501533], [-93.851913, 43.501577], [-93.526712, 43.501632], [-93.20149, 43.501687], [-92.876261, 43.501742], [-92.551066, 43.501786], [-92.225838, 43.501841], [-91.900609, 43.501896], [-91.575414, 43.50194], [-91.245253, 43.502412], [-91.238277, 43.440241], [-91.218688, 43.395285], [-91.178357, 43.358931], [-91.117196, 43.331157], [-91.106968, 43.278028], [-91.147585, 43.199585], [-91.161328, 43.102334], [-91.148156, 42.986209], [-91.117592, 42.881652], [-91.069582, 42.788554], [-90.959949, 42.72034], [-90.788749, 42.676933], [-90.687873, 42.610322], [-90.657331, 42.520509], [-90.650585, 42.512984], [-90.589633, 42.444802], [-90.484735, 42.383257], [-90.425036, 42.325656], [-90.41049, 42.272075], [-90.346571, 42.214837], [-90.233214, 42.154016], [-90.167516, 42.100304], [-90.149433, 42.053711], [-90.152443, 41.98152], [-90.176613, 41.883643], [-90.217768, 41.81311], [-90.276006, 41.770011], [-90.319237, 41.709652], [-90.347527, 41.632034], [-90.43667, 41.560359], [-90.586732, 41.494727], [-90.754065, 41.449826], [-90.938756, 41.42559], [-91.048114, 41.369098], [-91.082106, 41.280318], [-91.066505, 41.205907], [-91.001334, 41.145966], [-90.963827, 41.082531], [-90.954005, 41.01558], [-91.000126, 40.904684], [-91.102134, 40.749788], [-91.215128, 40.649559], [-91.339043, 40.603977], [-91.394184, 40.536653], [-91.380539, 40.447554], [-91.390778, 40.397127], [-91.441952, 40.37945]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3518", "diss_me": 3518, "iso_3166_2": "US-ID", "wikipedia": "http://en.wikipedia.org/wiki/Idaho", "iso_a2": "US", "adm0_sr": 1, "name": "Idaho", "name_alt": "ID|Idaho", "name_local": null, "type": "State", "type_en": "State", "code_local": "US16", "code_hasc": "US.ID", "note": null, "hasc_maybe": null, "region": "West", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Idaho", "postal": "ID", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 5, "mapcolor9": 1, "mapcolor13": 1, "fips": "US16", "fips_alt": null, "woe_id": 2347571, "woe_label": "Idaho, US, United States", "woe_name": "Idaho", "latitude": 43.7825, "longitude": -114.133, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5596512, "gn_name": "Idaho", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.ID", "region_sub": "Mountain", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1221", "name_ar": "\u0623\u064a\u062f\u0627\u0647\u0648", "name_bn": "\u0986\u0987\u09a1\u09be\u09b9\u09cb", "name_de": "Idaho", "name_en": "Idaho", "name_es": "Idaho", "name_fr": "Idaho", "name_el": "\u0386\u03b9\u03bd\u03c4\u03b1\u03c7\u03bf", "name_hi": "\u0906\u092f\u0921\u093e\u0939\u094b", "name_hu": "Idaho", "name_id": "Idaho", "name_it": "Idaho", "name_ja": "\u30a2\u30a4\u30c0\u30db\u5dde", "name_ko": "\uc544\uc774\ub2e4\ud638", "name_nl": "Idaho", "name_pl": "Idaho", "name_pt": "Idaho", "name_ru": "\u0410\u0439\u0434\u0430\u0445\u043e", "name_sv": "Idaho", "name_tr": "Idaho", "name_vi": "Idaho", "name_zh": "\u7231\u8fbe\u8377\u5dde", "ne_id": 1159315339, "name_he": "\u05d0\u05d9\u05d9\u05d3\u05d4\u05d5", "name_uk": "\u0410\u0439\u0434\u0430\u0445\u043e", "name_ur": "\u0627\u06cc\u0688\u0627\u06c1\u0648", "name_fa": "\u0622\u06cc\u062f\u0627\u0647\u0648", "name_zht": "\u611b\u9054\u8377\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-117.201701, 42.000559, -111.050296, 48.993083], "geometry": {"type": "Polygon", "coordinates": [[[-117.039054, 48.993083], [-116.717028, 48.993083], [-116.290649, 48.993083], [-116.048494, 48.993083], [-116.048389, 48.746637], [-116.048598, 48.499313], [-116.048801, 48.251989], [-116.04901, 48.00472], [-115.941443, 47.904107], [-115.862149, 47.842408], [-115.811244, 47.775951], [-115.733757, 47.706342], [-115.718382, 47.68148], [-115.690867, 47.606652], [-115.710862, 47.552599], [-115.66968, 47.497854], [-115.676887, 47.470564], [-115.708022, 47.456798], [-115.714454, 47.45225], [-115.713317, 47.446746], [-115.702468, 47.437594], [-115.593325, 47.384915], [-115.485994, 47.311636], [-115.349467, 47.261176], [-115.306675, 47.231172], [-115.126636, 47.084593], [-115.033516, 46.990934], [-114.935694, 46.922819], [-114.886937, 46.844871], [-114.786066, 46.776756], [-114.760715, 46.742292], [-114.753689, 46.734568], [-114.740302, 46.733634], [-114.678032, 46.750169], [-114.661623, 46.745544], [-114.630648, 46.718572], [-114.624006, 46.677615], [-114.60155, 46.660334], [-114.562999, 46.650435], [-114.518664, 46.647743], [-114.380917, 46.667639], [-114.350897, 46.667639], [-114.336868, 46.659224], [-114.330122, 46.637647], [-114.332061, 46.601392], [-114.345805, 46.550591], [-114.387042, 46.499955], [-114.38022, 46.453033], [-114.41275, 46.343631], [-114.444248, 46.270714], [-114.446599, 46.199325], [-114.485359, 46.158214], [-114.463578, 46.109765], [-114.478306, 46.035585], [-114.464792, 46.016414], [-114.415903, 45.982159], [-114.396787, 45.89095], [-114.405131, 45.874251], [-114.492566, 45.838732], [-114.522537, 45.815133], [-114.533699, 45.78201], [-114.495796, 45.685846], [-114.532617, 45.633024], [-114.537346, 45.587398], [-114.529233, 45.575719], [-114.448434, 45.551253], [-114.350562, 45.497145], [-114.319191, 45.48573], [-114.297641, 45.487565], [-114.256146, 45.505648], [-114.210234, 45.542442], [-114.116619, 45.579103], [-114.006393, 45.658457], [-114.000708, 45.680628], [-113.991924, 45.69302], [-113.977818, 45.69235], [-113.942651, 45.681507], [-113.872915, 45.63354], [-113.812814, 45.606986], [-113.802273, 45.601098], [-113.796642, 45.587661], [-113.799614, 45.540189], [-113.76615, 45.502517], [-113.756097, 45.44084], [-113.721941, 45.379273], [-113.697112, 45.304983], [-113.606573, 45.209105], [-113.557404, 45.140419], [-113.503582, 45.109284], [-113.471079, 45.072853], [-113.447129, 45.029084], [-113.438136, 44.993971], [-113.469294, 44.929976], [-113.460796, 44.90362], [-113.432138, 44.874165], [-113.338891, 44.808072], [-113.320418, 44.802534], [-113.234269, 44.809873], [-113.18717, 44.798579], [-113.140709, 44.765489], [-113.09327, 44.715336], [-113.062706, 44.665073], [-113.05428, 44.605187], [-113.006379, 44.539137], [-112.999689, 44.48036], [-112.970075, 44.454499], [-112.910392, 44.419331], [-112.853856, 44.398325], [-112.831351, 44.396623], [-112.815514, 44.405972], [-112.810163, 44.438162], [-112.787142, 44.463079], [-112.715928, 44.498037], [-112.648236, 44.497104], [-112.392848, 44.467957], [-112.375385, 44.470022], [-112.36386, 44.479558], [-112.320036, 44.53315], [-112.285077, 44.553947], [-112.23131, 44.560692], [-112.074211, 44.547619], [-111.89208, 44.554925], [-111.797098, 44.539895], [-111.659302, 44.559605], [-111.499857, 44.54485], [-111.47934, 44.553716], [-111.474506, 44.564615], [-111.488821, 44.584544], [-111.491046, 44.624226], [-111.459109, 44.671017], [-111.4481, 44.711117], [-111.41557, 44.733551], [-111.372525, 44.74624], [-111.337463, 44.744812], [-111.304081, 44.723312], [-111.265118, 44.687552], [-111.197574, 44.590586], [-111.160934, 44.555836], [-111.11722, 44.525349], [-111.051434, 44.498883], [-111.051357, 44.342768], [-111.05128, 44.186652], [-111.051225, 44.030547], [-111.051148, 43.874398], [-111.051071, 43.718261], [-111.051022, 43.562145], [-111.050945, 43.406029], [-111.050862, 43.249892], [-111.050785, 43.093754], [-111.050708, 42.937638], [-111.050659, 42.781522], [-111.050582, 42.625385], [-111.050505, 42.469247], [-111.05045, 42.313131], [-111.050373, 42.157016], [-111.050296, 42.000878], [-111.237311, 42.0009], [-111.424331, 42.0009], [-111.611346, 42.000922], [-111.798367, 42.000955], [-111.985381, 42.000955], [-112.172396, 42.000977], [-112.359416, 42.000999], [-112.546431, 42.000999], [-112.733451, 42.000999], [-112.920466, 42.001032], [-113.107481, 42.001054], [-113.294501, 42.001054], [-113.481516, 42.001054], [-113.668536, 42.001076], [-113.855551, 42.001109], [-114.042593, 42.001109], [-114.414354, 42.001054], [-114.786115, 42.000977], [-115.157876, 42.0009], [-115.529637, 42.000845], [-115.901398, 42.000768], [-116.273153, 42.000691], [-116.644914, 42.000636], [-117.016675, 42.000559], [-117.017114, 42.223779], [-117.017581, 42.446967], [-117.018021, 42.670165], [-117.01846, 42.893352], [-117.0189, 43.11654], [-117.019339, 43.339727], [-117.0198, 43.562925], [-117.02024, 43.808437], [-117.020498, 43.813194], [-116.957634, 43.964135], [-116.943967, 44.037677], [-116.960683, 44.079118], [-116.949779, 44.119009], [-116.91131, 44.157406], [-116.91242, 44.199473], [-116.95319, 44.245308], [-117.028952, 44.275542], [-117.139744, 44.290264], [-117.197312, 44.3438], [-117.201701, 44.436206], [-117.118919, 44.578314], [-116.948955, 44.770114], [-116.855857, 44.90574], [-116.839553, 44.98516], [-116.737342, 45.168841], [-116.549157, 45.456737], [-116.477043, 45.641088], [-116.520917, 45.721914], [-116.616827, 45.79917], [-116.764725, 45.87291], [-116.869194, 45.958483], [-116.896479, 46.002099], [-116.930196, 46.055954], [-116.947845, 46.124322], [-116.92211, 46.163642], [-116.942962, 46.232108], [-117.010396, 46.329623], [-117.038999, 46.396552], [-117.032462, 46.419755], [-117.025046, 46.429159], [-117.025848, 46.589461], [-117.026678, 46.749751], [-117.027502, 46.910053], [-117.028331, 47.070354], [-117.029155, 47.230656], [-117.029985, 47.390957], [-117.030809, 47.551259], [-117.031638, 47.71156], [-117.032462, 47.871862], [-117.033292, 48.032163], [-117.034116, 48.192454], [-117.034918, 48.352756], [-117.03572, 48.513057], [-117.036544, 48.673359], [-117.037373, 48.83366], [-117.039054, 48.993083]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3546", "diss_me": 3546, "iso_3166_2": "US-IL", "wikipedia": "http://en.wikipedia.org/wiki/Illinois", "iso_a2": "US", "adm0_sr": 1, "name": "Illinois", "name_alt": "IL|Ill.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US17", "code_hasc": "US.IL", "note": null, "hasc_maybe": null, "region": "Midwest", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Ill.", "postal": "IL", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 8, "mapcolor9": 1, "mapcolor13": 1, "fips": "US17", "fips_alt": null, "woe_id": 2347572, "woe_label": "Illinois, US, United States", "woe_name": "Illinois", "latitude": 39.946, "longitude": -89.1991, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4896861, "gn_name": "Illinois", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.IL", "region_sub": "East North Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1204", "name_ar": "\u0625\u0644\u064a\u0646\u0648\u064a", "name_bn": "\u0987\u09b2\u09bf\u09a8\u09af\u09bc", "name_de": "Illinois", "name_en": "Illinois", "name_es": "Illinois", "name_fr": "Illinois", "name_el": "\u0399\u03bb\u03b9\u03bd\u03cc\u03b9", "name_hi": "\u0907\u0932\u093f\u0928\u0949\u092f", "name_hu": "Illinois", "name_id": "Illinois", "name_it": "Illinois", "name_ja": "\u30a4\u30ea\u30ce\u30a4\u5dde", "name_ko": "\uc77c\ub9ac\ub178\uc774", "name_nl": "Illinois", "name_pl": "Illinois", "name_pt": "Illinois", "name_ru": "\u0418\u043b\u043b\u0438\u043d\u043e\u0439\u0441", "name_sv": "Illinois", "name_tr": "Illinois", "name_vi": "Illinois", "name_zh": "\u4f0a\u5229\u8bfa\u4f0a\u5dde", "ne_id": 1159315309, "name_he": "\u05d0\u05d9\u05dc\u05d9\u05e0\u05d5\u05d9", "name_uk": "\u0406\u043b\u043b\u0456\u043d\u043e\u0439\u0441", "name_ur": "\u0627\u0644\u06cc\u0646\u0648\u0627\u0626\u06d2", "name_fa": "\u0627\u06cc\u0644\u06cc\u0646\u0648\u06cc", "name_zht": "\u4f0a\u5229\u8afe\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-91.501652, 36.992112, -87.039126, 42.512984], "geometry": {"type": "Polygon", "coordinates": [[[-91.441952, 40.37945], [-91.390778, 40.397127], [-91.380539, 40.447554], [-91.394184, 40.536653], [-91.339043, 40.603977], [-91.215128, 40.649559], [-91.102134, 40.749788], [-91.000126, 40.904684], [-90.954005, 41.01558], [-90.963827, 41.082531], [-91.001334, 41.145966], [-91.066505, 41.205907], [-91.082106, 41.280318], [-91.048114, 41.369098], [-90.938756, 41.42559], [-90.754065, 41.449826], [-90.586732, 41.494727], [-90.43667, 41.560359], [-90.347527, 41.632034], [-90.319237, 41.709652], [-90.276006, 41.770011], [-90.217768, 41.81311], [-90.176613, 41.883643], [-90.152443, 41.98152], [-90.149433, 42.053711], [-90.167516, 42.100304], [-90.233214, 42.154016], [-90.346571, 42.214837], [-90.41049, 42.272075], [-90.425036, 42.325656], [-90.484735, 42.383257], [-90.589633, 42.444802], [-90.650585, 42.512984], [-90.191049, 42.510303], [-89.740796, 42.507798], [-89.290521, 42.505315], [-88.840236, 42.50281], [-88.38995, 42.500305], [-87.939664, 42.497822], [-87.489412, 42.495318], [-87.039126, 42.492802], [-87.084675, 42.309791], [-87.130203, 42.126781], [-87.17573, 41.943749], [-87.221257, 41.760728], [-87.371408, 41.760761], [-87.521085, 41.760761], [-87.522536, 41.460988], [-87.524008, 41.161237], [-87.52548, 40.861486], [-87.52693, 40.561713], [-87.528369, 40.26194], [-87.529819, 39.962189], [-87.53127, 39.662438], [-87.532742, 39.379144], [-87.532918, 39.37486], [-87.579115, 39.343977], [-87.611052, 39.291353], [-87.602912, 39.234147], [-87.614985, 39.193289], [-87.647285, 39.168745], [-87.631696, 39.106705], [-87.568294, 39.00718], [-87.530281, 38.908897], [-87.51768, 38.811821], [-87.529457, 38.742289], [-87.583773, 38.67937], [-87.635958, 38.542612], [-87.680662, 38.487988], [-87.735231, 38.469905], [-87.784065, 38.419104], [-87.827164, 38.335564], [-87.872955, 38.295024], [-87.921427, 38.297507], [-87.957265, 38.282214], [-87.980413, 38.249189], [-87.97749, 38.21444], [-87.948552, 38.178009], [-87.958056, 38.144292], [-88.006022, 38.113278], [-88.005143, 38.098402], [-87.990256, 38.089305], [-87.996046, 38.074419], [-88.026127, 38.059587], [-88.044518, 38.013291], [-88.042496, 37.93665], [-88.059108, 37.898363], [-88.091122, 37.896649], [-88.095319, 37.875566], [-88.041991, 37.788851], [-88.073247, 37.770922], [-88.128959, 37.69951], [-88.140385, 37.620651], [-88.107514, 37.534353], [-88.190504, 37.464557], [-88.389335, 37.411262], [-88.494672, 37.364285], [-88.506603, 37.323591], [-88.492782, 37.261551], [-88.453275, 37.178143], [-88.446244, 37.120421], [-88.471666, 37.088385], [-88.613808, 37.110083], [-88.872602, 37.185537], [-89.046207, 37.182977], [-89.134603, 37.102469], [-89.165069, 37.041561], [-89.154313, 36.992112], [-89.224911, 37.052679], [-89.272394, 37.07998], [-89.281469, 37.077794], [-89.291675, 37.070653], [-89.295817, 37.051636], [-89.293246, 37.038177], [-89.285885, 37.022698], [-89.290016, 37.012777], [-89.300827, 37.012052], [-89.35188, 37.035519], [-89.413942, 37.102415], [-89.486913, 37.212739], [-89.502931, 37.300509], [-89.461974, 37.36568], [-89.461974, 37.434125], [-89.502931, 37.5058], [-89.523421, 37.575947], [-89.523421, 37.644524], [-89.623286, 37.747257], [-89.822963, 37.884092], [-89.969828, 37.968533], [-90.063871, 38.000525], [-90.173581, 38.069047], [-90.299, 38.173999], [-90.365775, 38.254254], [-90.373993, 38.309757], [-90.316601, 38.457809], [-90.150751, 38.780532], [-90.132195, 38.818644], [-90.126768, 38.832618], [-90.134206, 38.84667], [-90.149916, 38.859897], [-90.220075, 38.897679], [-90.35435, 38.93021], [-90.477968, 38.948118], [-90.577075, 38.909611], [-90.663527, 38.987493], [-90.737223, 39.181797], [-90.919376, 39.386901], [-91.209899, 39.602804], [-91.378737, 39.749406], [-91.425868, 39.826815], [-91.466814, 39.942864], [-91.501652, 40.097529], [-91.499784, 40.226025], [-91.441952, 40.37945]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3547", "diss_me": 3547, "iso_3166_2": "US-IN", "wikipedia": "http://en.wikipedia.org/wiki/Indiana", "iso_a2": "US", "adm0_sr": 1, "name": "Indiana", "name_alt": "IN|Ind.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US18", "code_hasc": "US.IN", "note": null, "hasc_maybe": null, "region": "Midwest", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Ind.", "postal": "IN", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 7, "mapcolor9": 1, "mapcolor13": 1, "fips": "US18", "fips_alt": null, "woe_id": 2347573, "woe_label": "Indiana, US, United States", "woe_name": "Indiana", "latitude": 39.8874, "longitude": -86.1396, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4921868, "gn_name": "Indiana", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.IN", "region_sub": "East North Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1415", "name_ar": "\u0625\u0646\u062f\u064a\u0627\u0646\u0627", "name_bn": "\u0987\u09a8\u09cd\u09a1\u09bf\u09af\u09bc\u09be\u09a8\u09be", "name_de": "Indiana", "name_en": "Indiana", "name_es": "Indiana", "name_fr": "Indiana", "name_el": "\u0399\u03bd\u03c4\u03b9\u03ac\u03bd\u03b1", "name_hi": "\u0907\u0902\u0921\u093f\u092f\u093e\u0928\u093e", "name_hu": "Indiana", "name_id": "Indiana", "name_it": "Indiana", "name_ja": "\u30a4\u30f3\u30c7\u30a3\u30a2\u30ca\u5dde", "name_ko": "\uc778\ub514\uc560\ub098", "name_nl": "Indiana", "name_pl": "Indiana", "name_pt": "Indiana", "name_ru": "\u0418\u043d\u0434\u0438\u0430\u043d\u0430", "name_sv": "Indiana", "name_tr": "Indiana", "name_vi": "Indiana", "name_zh": "\u5370\u7b2c\u5b89\u7eb3\u5dde", "ne_id": 1159315311, "name_he": "\u05d0\u05d9\u05e0\u05d3\u05d9\u05d0\u05e0\u05d4", "name_uk": "\u0406\u043d\u0434\u0456\u0430\u043d\u0430", "name_ur": "\u0627\u0646\u0688\u06cc\u0627\u0646\u0627", "name_fa": "\u0627\u06cc\u0646\u062f\u06cc\u0627\u0646\u0627", "name_zht": "\u5370\u7b2c\u5b89\u7eb3\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-88.095319, 37.788027, -84.78962, 41.760761], "geometry": {"type": "Polygon", "coordinates": [[[-88.041991, 37.788851], [-88.095319, 37.875566], [-88.091122, 37.896649], [-88.059108, 37.898363], [-88.042496, 37.93665], [-88.044518, 38.013291], [-88.026127, 38.059587], [-87.996046, 38.074419], [-87.990256, 38.089305], [-88.005143, 38.098402], [-88.006022, 38.113278], [-87.958056, 38.144292], [-87.948552, 38.178009], [-87.97749, 38.21444], [-87.980413, 38.249189], [-87.957265, 38.282214], [-87.921427, 38.297507], [-87.872955, 38.295024], [-87.827164, 38.335564], [-87.784065, 38.419104], [-87.735231, 38.469905], [-87.680662, 38.487988], [-87.635958, 38.542612], [-87.583773, 38.67937], [-87.529457, 38.742289], [-87.51768, 38.811821], [-87.530281, 38.908897], [-87.568294, 39.00718], [-87.631696, 39.106705], [-87.647285, 39.168745], [-87.614985, 39.193289], [-87.602912, 39.234147], [-87.611052, 39.291353], [-87.579115, 39.343977], [-87.532918, 39.37486], [-87.532742, 39.379144], [-87.53127, 39.662438], [-87.529819, 39.962189], [-87.528369, 40.26194], [-87.52693, 40.561713], [-87.52548, 40.861486], [-87.524008, 41.161237], [-87.522536, 41.460988], [-87.521085, 41.760761], [-87.371408, 41.760761], [-87.221257, 41.760728], [-86.918156, 41.760607], [-86.615043, 41.760497], [-86.31193, 41.760376], [-86.008828, 41.760244], [-85.705715, 41.760112], [-85.402614, 41.759981], [-85.099501, 41.75986], [-84.796399, 41.759728], [-84.796113, 41.701434], [-84.799552, 41.376052], [-84.802958, 41.05067], [-84.806397, 40.725321], [-84.809835, 40.399939], [-84.813263, 40.074557], [-84.816702, 39.749197], [-84.82014, 39.423826], [-84.821711, 39.091984], [-84.837422, 39.082678], [-84.860603, 39.039711], [-84.835488, 38.99604], [-84.836598, 38.960565], [-84.863888, 38.933231], [-84.854165, 38.912896], [-84.807451, 38.899536], [-84.78962, 38.868379], [-84.800739, 38.819391], [-84.901241, 38.769568], [-85.093898, 38.71356], [-85.135525, 38.697256], [-85.16989, 38.690378], [-85.186117, 38.693663], [-85.18604, 38.693663], [-85.211122, 38.704122], [-85.24663, 38.72704], [-85.306747, 38.737191], [-85.405426, 38.729962], [-85.444779, 38.683095], [-85.424828, 38.596588], [-85.458677, 38.530209], [-85.546326, 38.484011], [-85.608904, 38.423026], [-85.646422, 38.347297], [-85.706287, 38.301353], [-85.788453, 38.285214], [-85.854932, 38.215033], [-85.905678, 38.090909], [-85.961159, 38.014016], [-86.021331, 37.984353], [-86.103442, 37.991868], [-86.207527, 38.036571], [-86.267622, 38.082582], [-86.28375, 38.129867], [-86.3146, 38.163771], [-86.342659, 38.178734], [-86.361445, 38.178987], [-86.362522, 38.172109], [-86.354952, 38.15886], [-86.365137, 38.1446], [-86.429627, 38.139689], [-86.457378, 38.120155], [-86.448336, 38.085966], [-86.462542, 38.061763], [-86.499961, 38.047502], [-86.519857, 38.01484], [-86.522186, 37.963732], [-86.548641, 37.917062], [-86.599233, 37.874797], [-86.673128, 37.889036], [-86.770335, 37.959777], [-86.86908, 37.976135], [-86.96944, 37.938046], [-87.044268, 37.886443], [-87.093563, 37.821283], [-87.141035, 37.805243], [-87.209403, 37.854846], [-87.372385, 37.923478], [-87.457288, 37.938101], [-87.518449, 37.921566], [-87.561449, 37.929059], [-87.576171, 37.947758], [-87.587388, 37.95569], [-87.599407, 37.946472], [-87.600802, 37.886729], [-87.615392, 37.848936], [-87.643253, 37.833038], [-87.664567, 37.845541], [-87.67942, 37.886366], [-87.714456, 37.899604], [-87.769651, 37.885234], [-87.825253, 37.891431], [-87.874428, 37.915743], [-87.892116, 37.912986], [-87.906002, 37.901824], [-87.902069, 37.85511], [-87.912484, 37.81769], [-87.938115, 37.793817], [-87.974546, 37.788027], [-88.021776, 37.800431], [-88.041991, 37.788851]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3530", "diss_me": 3530, "iso_3166_2": "US-KS", "wikipedia": "http://en.wikipedia.org/wiki/Kansas", "iso_a2": "US", "adm0_sr": 1, "name": "Kansas", "name_alt": "KS|Kans.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US20", "code_hasc": "US.KS", "note": null, "hasc_maybe": null, "region": "Midwest", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Kans.", "postal": "KS", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 6, "mapcolor9": 1, "mapcolor13": 1, "fips": "US20", "fips_alt": null, "woe_id": 2347575, "woe_label": "Kansas, US, United States", "woe_name": "Kansas", "latitude": 38.5, "longitude": -98.3309, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4273857, "gn_name": "Kansas", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.KS", "region_sub": "West North Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1558", "name_ar": "\u0643\u0627\u0646\u0633\u0627\u0633", "name_bn": "\u0995\u09cd\u09af\u09be\u09a8\u09cd\u09b8\u09be\u09b8", "name_de": "Kansas", "name_en": "Kansas", "name_es": "Kansas", "name_fr": "Kansas", "name_el": "\u039a\u03ac\u03bd\u03c3\u03b1\u03c2", "name_hi": "\u0915\u0947\u0928\u094d\u0938\u093e\u0938", "name_hu": "Kansas", "name_id": "Kansas", "name_it": "Kansas", "name_ja": "\u30ab\u30f3\u30b6\u30b9\u5dde", "name_ko": "\uce94\uc790\uc2a4", "name_nl": "Kansas", "name_pl": "Kansas", "name_pt": "Kansas", "name_ru": "\u041a\u0430\u043d\u0437\u0430\u0441", "name_sv": "Kansas", "name_tr": "Kansas", "name_vi": "Kansas", "name_zh": "\u582a\u8428\u65af\u5dde", "ne_id": 1159315359, "name_he": "\u05e7\u05e0\u05d6\u05e1", "name_uk": "\u041a\u0430\u043d\u0437\u0430\u0441", "name_ur": "\u06a9\u0646\u0633\u0627\u0633", "name_fa": "\u06a9\u0627\u0646\u0632\u0627\u0633", "name_zht": "\u582a\u85a9\u65af\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-102.024489, 37.000846, -94.618067, 40.001487], "geometry": {"type": "Polygon", "coordinates": [[[-102.012783, 37.000846], [-102.013536, 37.188372], [-102.014261, 37.375853], [-102.014981, 37.56339], [-102.015706, 37.750927], [-102.016431, 37.93843], [-102.017178, 38.125945], [-102.017925, 38.31347], [-102.01865, 38.500985], [-102.019375, 38.688489], [-102.0201, 38.876025], [-102.02082, 39.063529], [-102.021572, 39.251044], [-102.022319, 39.43858], [-102.023045, 39.626084], [-102.02377, 39.813588], [-102.024489, 40.001124], [-101.814892, 40.001124], [-101.605289, 40.001124], [-101.395692, 40.001124], [-101.18609, 40.001124], [-100.976492, 40.001124], [-100.766895, 40.001124], [-100.557293, 40.001124], [-100.347695, 40.001124], [-100.138093, 40.001124], [-99.928495, 40.001124], [-99.718893, 40.001124], [-99.509296, 40.001124], [-99.299693, 40.001124], [-99.090096, 40.001124], [-98.880499, 40.001124], [-98.670896, 40.001124], [-98.461299, 40.001124], [-98.251696, 40.001124], [-98.042099, 40.001124], [-97.832496, 40.001124], [-97.622899, 40.001124], [-97.413296, 40.001124], [-97.203699, 40.001124], [-96.994102, 40.001124], [-96.784499, 40.001124], [-96.574902, 40.001124], [-96.3653, 40.001124], [-96.155702, 40.001124], [-95.9461, 40.001124], [-95.736503, 40.001124], [-95.526905, 40.001124], [-95.34668, 40.001487], [-95.116203, 39.87209], [-95.055537, 39.870794], [-94.984016, 39.891162], [-94.929936, 39.861499], [-94.893296, 39.781815], [-94.898597, 39.741144], [-94.945827, 39.739485], [-95.004764, 39.691552], [-95.075356, 39.597377], [-95.057937, 39.508959], [-94.952518, 39.426375], [-94.882294, 39.343131], [-94.847203, 39.259152], [-94.777852, 39.193992], [-94.622384, 39.124404], [-94.624527, 39.086062], [-94.624115, 38.955764], [-94.62373, 38.825433], [-94.62334, 38.695103], [-94.622928, 38.564783], [-94.622511, 38.434452], [-94.622099, 38.304121], [-94.621687, 38.17379], [-94.621297, 38.04347], [-94.620912, 37.91314], [-94.6205, 37.782809], [-94.620083, 37.652478], [-94.619671, 37.522158], [-94.619259, 37.391827], [-94.618869, 37.261497], [-94.618484, 37.131166], [-94.618067, 37.000846], [-94.849164, 37.000846], [-95.08024, 37.000846], [-95.31131, 37.000846], [-95.542407, 37.000846], [-95.773504, 37.000846], [-96.004574, 37.000846], [-96.235644, 37.000846], [-96.466742, 37.000846], [-96.697839, 37.000846], [-96.928909, 37.000846], [-97.159979, 37.000846], [-97.391077, 37.000846], [-97.622174, 37.000846], [-97.853244, 37.000846], [-98.084319, 37.000846], [-98.315417, 37.000846], [-98.546514, 37.000846], [-98.777584, 37.000846], [-99.008654, 37.000846], [-99.239752, 37.000846], [-99.470849, 37.000846], [-99.701919, 37.000846], [-99.932989, 37.000846], [-100.164086, 37.000846], [-100.395184, 37.000846], [-100.626254, 37.000846], [-100.857329, 37.000846], [-101.088421, 37.000846], [-101.319518, 37.000846], [-101.550616, 37.000846], [-101.781713, 37.000846], [-102.012783, 37.000846]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3548", "diss_me": 3548, "iso_3166_2": "US-KY", "wikipedia": "http://en.wikipedia.org/wiki/Kentucky", "iso_a2": "US", "adm0_sr": 1, "name": "Kentucky", "name_alt": "Commonwealth of Kentucky|KY", "name_local": null, "type": "State", "type_en": "State", "code_local": "US21", "code_hasc": "US.KY", "note": null, "hasc_maybe": "US.IN|USA-KEN", "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Ky.", "postal": "KY", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 8, "mapcolor9": 1, "mapcolor13": 1, "fips": "US21", "fips_alt": "US18", "woe_id": 2347576, "woe_label": "Kentucky, US, United States", "woe_name": "Kentucky", "latitude": 37.3994, "longitude": -85.5729, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 6254925, "gn_name": "Kentucky", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.KY", "region_sub": "East South Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1603", "name_ar": "\u0643\u0646\u062a\u0627\u0643\u064a", "name_bn": "\u0995\u09c7\u09a8\u09cd\u099f\u09be\u0995\u09bf", "name_de": "Kentucky", "name_en": "Kentucky", "name_es": "Kentucky", "name_fr": "Kentucky", "name_el": "\u039a\u03b5\u03bd\u03c4\u03ac\u03ba\u03b9", "name_hi": "\u0915\u0947\u0928\u094d\u091f\u0915\u0940", "name_hu": "Kentucky", "name_id": "Kentucky", "name_it": "Kentucky", "name_ja": "\u30b1\u30f3\u30bf\u30c3\u30ad\u30fc\u5dde", "name_ko": "\ucf04\ud130\ud0a4", "name_nl": "Kentucky", "name_pl": "Kentucky", "name_pt": "Kentucky", "name_ru": "\u041a\u0435\u043d\u0442\u0443\u043a\u043a\u0438", "name_sv": "Kentucky", "name_tr": "Kentucky", "name_vi": "Kentucky", "name_zh": "\u80af\u5854\u57fa\u5dde", "ne_id": 1159315313, "name_he": "\u05e7\u05e0\u05d8\u05e7\u05d9", "name_uk": "\u041a\u0435\u043d\u0442\u0443\u043a\u043a\u0456", "name_ur": "\u06a9\u06cc\u0646\u0679\u06a9\u06cc", "name_fa": "\u06a9\u0646\u062a\u0627\u06a9\u06cc", "name_zht": "\u80af\u5854\u57fa\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-89.560038, 36.499683, -81.965277, 39.128909], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-89.154313, 36.992112], [-89.165069, 37.041561], [-89.134603, 37.102469], [-89.046207, 37.182977], [-88.872602, 37.185537], [-88.613808, 37.110083], [-88.471666, 37.088385], [-88.446244, 37.120421], [-88.453275, 37.178143], [-88.492782, 37.261551], [-88.506603, 37.323591], [-88.494672, 37.364285], [-88.389335, 37.411262], [-88.190504, 37.464557], [-88.107514, 37.534353], [-88.140385, 37.620651], [-88.128959, 37.69951], [-88.073247, 37.770922], [-88.041991, 37.788851], [-88.021776, 37.800431], [-87.974546, 37.788027], [-87.938115, 37.793817], [-87.912484, 37.81769], [-87.902069, 37.85511], [-87.906002, 37.901824], [-87.892116, 37.912986], [-87.874428, 37.915743], [-87.825253, 37.891431], [-87.769651, 37.885234], [-87.714456, 37.899604], [-87.67942, 37.886366], [-87.664567, 37.845541], [-87.643253, 37.833038], [-87.615392, 37.848936], [-87.600802, 37.886729], [-87.599407, 37.946472], [-87.587388, 37.95569], [-87.576171, 37.947758], [-87.561449, 37.929059], [-87.518449, 37.921566], [-87.457288, 37.938101], [-87.372385, 37.923478], [-87.209403, 37.854846], [-87.141035, 37.805243], [-87.093563, 37.821283], [-87.044268, 37.886443], [-86.96944, 37.938046], [-86.86908, 37.976135], [-86.770335, 37.959777], [-86.673128, 37.889036], [-86.599233, 37.874797], [-86.548641, 37.917062], [-86.522186, 37.963732], [-86.519857, 38.01484], [-86.499961, 38.047502], [-86.462542, 38.061763], [-86.448336, 38.085966], [-86.457378, 38.120155], [-86.429627, 38.139689], [-86.365137, 38.1446], [-86.354952, 38.15886], [-86.362522, 38.172109], [-86.361445, 38.178987], [-86.342659, 38.178734], [-86.3146, 38.163771], [-86.28375, 38.129867], [-86.267622, 38.082582], [-86.207527, 38.036571], [-86.103442, 37.991868], [-86.021331, 37.984353], [-85.961159, 38.014016], [-85.905678, 38.090909], [-85.854932, 38.215033], [-85.788453, 38.285214], [-85.706287, 38.301353], [-85.646422, 38.347297], [-85.608904, 38.423026], [-85.546326, 38.484011], [-85.458677, 38.530209], [-85.424828, 38.596588], [-85.444779, 38.683095], [-85.405426, 38.729962], [-85.306747, 38.737191], [-85.24663, 38.72704], [-85.211122, 38.704122], [-85.18604, 38.693663], [-85.186117, 38.693663], [-85.16989, 38.690378], [-85.135525, 38.697256], [-85.093898, 38.71356], [-84.901241, 38.769568], [-84.800739, 38.819391], [-84.78962, 38.868379], [-84.807451, 38.899536], [-84.854165, 38.912896], [-84.863888, 38.933231], [-84.836598, 38.960565], [-84.835488, 38.99604], [-84.860603, 39.039711], [-84.837422, 39.082678], [-84.821711, 39.091984], [-84.765901, 39.124998], [-84.706948, 39.128909], [-84.660542, 39.094467], [-84.594547, 39.085776], [-84.508865, 39.102838], [-84.43006, 39.090896], [-84.358022, 39.049917], [-84.290435, 38.974705], [-84.227285, 38.865204], [-84.113236, 38.798385], [-83.948386, 38.774226], [-83.828086, 38.731226], [-83.752269, 38.669373], [-83.689878, 38.649531], [-83.616313, 38.682776], [-83.538387, 38.69986], [-83.460582, 38.679502], [-83.35697, 38.627405], [-83.203469, 38.638907], [-83.000068, 38.713999], [-82.880438, 38.710253], [-82.844623, 38.627668], [-82.758226, 38.541162], [-82.621282, 38.450679], [-82.612778, 38.448218], [-82.589498, 38.420345], [-82.578413, 38.272085], [-82.585389, 38.24273], [-82.619546, 38.182008], [-82.617711, 38.149873], [-82.588773, 38.099742], [-82.482195, 37.983551], [-82.47189, 37.938408], [-82.4299, 37.894177], [-82.393876, 37.828314], [-82.280244, 37.687184], [-82.103463, 37.570575], [-81.965277, 37.539725], [-82.343207, 37.296927], [-82.516505, 37.208839], [-82.681586, 37.13812], [-82.69489, 37.126156], [-82.731892, 37.048076], [-82.832021, 36.979269], [-82.894501, 36.906374], [-83.043816, 36.845554], [-83.150218, 36.762333], [-83.41689, 36.681012], [-83.566183, 36.652623], [-83.667521, 36.60503], [-83.675376, 36.602723], [-83.683231, 36.600449], [-83.691086, 36.598175], [-83.698942, 36.595901], [-83.706797, 36.593638], [-83.714652, 36.591363], [-83.722507, 36.589089], [-83.730385, 36.586815], [-84.07752, 36.596582], [-84.424688, 36.606316], [-84.771845, 36.616061], [-85.11898, 36.625828], [-85.466126, 36.635594], [-85.813283, 36.645339], [-86.160451, 36.655073], [-86.507586, 36.66484], [-86.84046, 36.659622], [-87.173357, 36.654403], [-87.506254, 36.649185], [-87.839151, 36.643966], [-87.868715, 36.675046], [-87.956298, 36.681968], [-88.091122, 36.6928], [-88.096297, 36.693009], [-88.056713, 36.59032], [-88.05601, 36.500946], [-88.059108, 36.499683], [-88.215509, 36.499737], [-88.388214, 36.499759], [-88.560919, 36.499792], [-88.733646, 36.499836], [-88.906373, 36.499891], [-89.079079, 36.499913], [-89.251784, 36.499946], [-89.450329, 36.500023], [-89.397462, 36.587793], [-89.351309, 36.611205], [-89.330534, 36.615907], [-89.280128, 36.600043], [-89.256123, 36.594407], [-89.203048, 36.62552], [-89.156334, 36.715718], [-89.129517, 36.811057], [-89.122486, 36.911593], [-89.154313, 36.992112]]], [[[-89.487221, 36.503066], [-89.557313, 36.501078], [-89.560038, 36.513097], [-89.55549, 36.540771], [-89.549645, 36.553065], [-89.535582, 36.555284], [-89.51952, 36.554823], [-89.496834, 36.528829], [-89.487221, 36.503066]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3535", "diss_me": 3535, "iso_3166_2": "US-LA", "wikipedia": "http://en.wikipedia.org/wiki/Louisiana", "iso_a2": "US", "adm0_sr": 5, "name": "Louisiana", "name_alt": "LA", "name_local": null, "type": "State", "type_en": "State", "code_local": "US22", "code_hasc": "US.LA", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "La.", "postal": "LA", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 9, "mapcolor9": 1, "mapcolor13": 1, "fips": "US22", "fips_alt": null, "woe_id": 2347577, "woe_label": "Louisiana, US, United States", "woe_name": "Louisiana", "latitude": 30.5274, "longitude": -91.9991, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4331987, "gn_name": "Louisiana", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.LA", "region_sub": "West South Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1588", "name_ar": "\u0644\u0648\u064a\u0632\u064a\u0627\u0646\u0627", "name_bn": "\u09b2\u09c1\u0987\u099c\u09bf\u09af\u09bc\u09be\u09a8\u09be", "name_de": "Louisiana", "name_en": "Louisiana", "name_es": "Luisiana", "name_fr": "Louisiane", "name_el": "\u039b\u03bf\u03c5\u03b9\u03b6\u03b9\u03ac\u03bd\u03b1", "name_hi": "\u0932\u0941\u0908\u091c\u093c\u093f\u092f\u093e\u0928\u093e", "name_hu": "Louisiana", "name_id": "Louisiana", "name_it": "Louisiana", "name_ja": "\u30eb\u30a4\u30b8\u30a2\u30ca\u5dde", "name_ko": "\ub8e8\uc774\uc9c0\uc560\ub098", "name_nl": "Louisiana", "name_pl": "Luizjana", "name_pt": "Luisiana", "name_ru": "\u041b\u0443\u0438\u0437\u0438\u0430\u043d\u0430", "name_sv": "Louisiana", "name_tr": "Louisiana", "name_vi": "Louisiana", "name_zh": "\u8def\u6613\u65af\u5b89\u90a3\u5dde", "ne_id": 1159315221, "name_he": "\u05dc\u05d5\u05d0\u05d9\u05d6\u05d9\u05d0\u05e0\u05d4", "name_uk": "\u041b\u0443\u0457\u0437\u0456\u0430\u043d\u0430", "name_ur": "\u0644\u0648\u0632\u06cc\u0627\u0646\u0627", "name_fa": "\u0644\u0648\u0626\u06cc\u0632\u06cc\u0627\u0646\u0627", "name_zht": "\u8def\u6613\u65af\u5b89\u90a3\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-94.043301, 28.981331, -88.812583, 33.015918], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-94.041307, 33.011996], [-93.861631, 33.012193], [-93.681949, 33.012402], [-93.502273, 33.012611], [-93.322619, 33.012842], [-93.142965, 33.013072], [-92.963284, 33.013281], [-92.783608, 33.01349], [-92.603927, 33.013699], [-92.424251, 33.013907], [-92.244569, 33.014105], [-92.064899, 33.014314], [-91.885207, 33.014544], [-91.705536, 33.014786], [-91.525855, 33.014984], [-91.346173, 33.015193], [-91.149958, 33.015918], [-91.144179, 32.966875], [-91.096081, 32.937684], [-91.093378, 32.885027], [-91.13606, 32.808847], [-91.135587, 32.755783], [-91.092082, 32.725857], [-91.094356, 32.69426], [-91.142421, 32.661026], [-91.14965, 32.625013], [-91.11612, 32.586231], [-91.100816, 32.541374], [-91.103815, 32.490497], [-91.059276, 32.423755], [-90.990019, 32.381051], [-90.9447, 32.330711], [-90.940437, 32.303092], [-90.937647, 32.277329], [-90.947721, 32.240074], [-91.004597, 32.185582], [-91.048158, 32.145921], [-91.074591, 32.131321], [-91.088698, 32.10414], [-91.092543, 32.045847], [-91.156527, 31.970689], [-91.286496, 31.883974], [-91.37253, 31.773716], [-91.414706, 31.639979], [-91.459091, 31.554978], [-91.505728, 31.518701], [-91.529008, 31.448751], [-91.528953, 31.345194], [-91.558693, 31.287911], [-91.61825, 31.276958], [-91.630807, 31.217599], [-91.596365, 31.109911], [-91.611043, 31.0649], [-91.652615, 31.029557], [-91.656449, 31.001805], [-91.417123, 31.001256], [-91.176885, 31.001234], [-90.936614, 31.001212], [-90.696343, 31.001212], [-90.456105, 31.001212], [-90.215834, 31.001157], [-89.975563, 31.001157], [-89.735314, 31.001157], [-89.764933, 30.886075], [-89.835366, 30.730816], [-89.838124, 30.690431], [-89.819733, 30.639861], [-89.819997, 30.611208], [-89.794003, 30.568933], [-89.736632, 30.526613], [-89.685766, 30.462684], [-89.640777, 30.348921], [-89.628988, 30.296186], [-89.591657, 30.223017], [-89.572486, 30.209164], [-89.545075, 30.200693], [-89.520861, 30.192629], [-89.588482, 30.165965], [-89.954249, 30.268742], [-90.045216, 30.351404], [-90.125966, 30.369102], [-90.225282, 30.379287], [-90.332003, 30.277586], [-90.413061, 30.140301], [-90.284982, 30.065089], [-90.175338, 30.029098], [-89.994196, 30.059255], [-89.894044, 30.125865], [-89.81224, 30.12369], [-89.773118, 30.137236], [-89.737434, 30.171986], [-89.66755, 30.14452], [-89.665067, 30.117054], [-89.714704, 30.078294], [-89.77726, 30.045709], [-89.815185, 30.007268], [-89.743817, 29.929858], [-89.63168, 29.903831], [-89.589514, 29.915049], [-89.563389, 30.002093], [-89.49445, 30.058167], [-89.400736, 30.04605], [-89.414052, 30.010882], [-89.400912, 29.977682], [-89.357846, 29.921014], [-89.362811, 29.839781], [-89.354462, 29.820226], [-89.455415, 29.784388], [-89.530661, 29.772215], [-89.590888, 29.725271], [-89.559313, 29.698036], [-89.62065, 29.674129], [-89.662123, 29.683687], [-89.682942, 29.674854], [-89.689215, 29.646048], [-89.720878, 29.619308], [-89.674801, 29.538668], [-89.580341, 29.486054], [-89.513676, 29.42007], [-89.245686, 29.333202], [-89.180779, 29.335706], [-89.116828, 29.248211], [-89.065335, 29.218142], [-89.015753, 29.202871], [-89.021378, 29.142721], [-89.109511, 29.098665], [-89.13334, 29.04614], [-89.15551, 29.016631], [-89.195248, 29.053984], [-89.236095, 29.08112], [-89.330556, 28.998701], [-89.376149, 28.981331], [-89.353539, 29.070244], [-89.389223, 29.105016], [-89.443144, 29.194137], [-89.521762, 29.249277], [-89.577155, 29.267514], [-89.620265, 29.302396], [-89.672472, 29.316502], [-89.716967, 29.31291], [-89.792377, 29.333202], [-89.797354, 29.380641], [-89.818283, 29.416137], [-89.877246, 29.458017], [-90.159068, 29.537141], [-90.160792, 29.504402], [-90.141259, 29.479748], [-90.100807, 29.463324], [-90.052335, 29.431408], [-90.052797, 29.336838], [-90.073748, 29.29676], [-90.082713, 29.239763], [-90.101367, 29.181788], [-90.135864, 29.136074], [-90.212802, 29.104939], [-90.246706, 29.131009], [-90.301615, 29.255814], [-90.379201, 29.295112], [-90.502511, 29.299759], [-90.586249, 29.271546], [-90.677501, 29.15062], [-90.751022, 29.130888], [-91.002763, 29.19351], [-91.290132, 29.288993], [-91.282716, 29.320743], [-91.237497, 29.330971], [-91.15076, 29.317898], [-91.155385, 29.350692], [-91.243979, 29.457325], [-91.260238, 29.505456], [-91.248845, 29.564189], [-91.277729, 29.562871], [-91.330924, 29.513575], [-91.514198, 29.555378], [-91.56479, 29.605322], [-91.672467, 29.74609], [-91.824386, 29.750693], [-91.893172, 29.836013], [-92.017328, 29.800296], [-92.080214, 29.760713], [-92.135475, 29.699475], [-92.113986, 29.667702], [-92.058878, 29.617187], [-92.084037, 29.59282], [-92.260824, 29.55685], [-92.671317, 29.597082], [-92.791332, 29.634655], [-92.952408, 29.714185], [-93.175705, 29.778961], [-93.283189, 29.789398], [-93.388455, 29.776577], [-93.694842, 29.769919], [-93.765901, 29.752704], [-93.826463, 29.725139], [-93.86574, 29.755626], [-93.883878, 29.810019], [-93.848321, 29.81883], [-93.808814, 29.850811], [-93.773081, 29.914038], [-93.769049, 29.952303], [-93.79401, 29.977264], [-93.726933, 30.077108], [-93.710629, 30.112813], [-93.720967, 30.282904], [-93.750394, 30.344713], [-93.746626, 30.380363], [-93.715205, 30.473253], [-93.720215, 30.558265], [-93.665206, 30.660768], [-93.624721, 30.714348], [-93.579194, 30.823805], [-93.568675, 30.894655], [-93.549196, 30.947719], [-93.562654, 31.004903], [-93.530591, 31.04619], [-93.551443, 31.104066], [-93.557749, 31.180421], [-93.596992, 31.209754], [-93.665882, 31.322584], [-93.663657, 31.372198], [-93.736057, 31.477667], [-93.737578, 31.513812], [-93.806902, 31.568799], [-93.820652, 31.603966], [-93.826798, 31.75026], [-93.845585, 31.792942], [-93.905065, 31.876998], [-94.043301, 31.999232], [-94.043064, 32.125838], [-94.042806, 32.252423], [-94.042548, 32.379007], [-94.04229, 32.505614], [-94.042032, 32.63222], [-94.041801, 32.758805], [-94.041565, 32.885378], [-94.041307, 33.011996]]], [[[-89.223955, 30.084051], [-89.22044, 30.037601], [-89.26945, 30.060727], [-89.342003, 30.062848], [-89.310055, 30.078712], [-89.287643, 30.094181], [-89.276481, 30.110825], [-89.184679, 30.168679], [-89.210673, 30.126228], [-89.223955, 30.084051]]], [[[-88.82747, 29.80769], [-88.855661, 29.775863], [-88.827986, 29.928353], [-88.866867, 30.056717], [-88.825888, 30.000368], [-88.812583, 29.933363], [-88.82747, 29.80769]]], [[[-88.889301, 29.712581], [-88.943584, 29.660232], [-88.941101, 29.680205], [-88.901155, 29.732632], [-88.872656, 29.752989], [-88.889301, 29.712581]]], [[[-91.79369, 29.500732], [-91.830846, 29.486472], [-91.996234, 29.57311], [-92.006649, 29.610288], [-91.925032, 29.643928], [-91.875231, 29.640984], [-91.796503, 29.59695], [-91.767675, 29.584712], [-91.754315, 29.566881], [-91.761885, 29.538997], [-91.79369, 29.500732]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3513", "diss_me": 3513, "iso_3166_2": "US-MA", "wikipedia": "http://en.wikipedia.org/wiki/Massachusetts", "iso_a2": "US", "adm0_sr": 6, "name": "Massachusetts", "name_alt": "Commonwealth of Massachusetts|MA|Mass.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US25", "code_hasc": "US.MA", "note": null, "hasc_maybe": null, "region": "Northeast", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Mass.", "postal": "MA", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 13, "mapcolor9": 1, "mapcolor13": 1, "fips": "US25", "fips_alt": null, "woe_id": 2347580, "woe_label": "Massachusetts, US, United States", "woe_name": "Massachusetts", "latitude": 42.3739, "longitude": -71.9993, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 6254926, "gn_name": "Massachusetts", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.MA", "region_sub": "New England", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q771", "name_ar": "\u0645\u0627\u0633\u0627\u062a\u0634\u0648\u0633\u062a\u0633", "name_bn": "\u09ae\u09cd\u09af\u09be\u09b8\u09be\u099a\u09c1\u09b8\u09c7\u099f\u09b8", "name_de": "Massachusetts", "name_en": "Massachusetts", "name_es": "Massachusetts", "name_fr": "Massachusetts", "name_el": "\u039c\u03b1\u03c3\u03b1\u03c7\u03bf\u03c5\u03c3\u03ad\u03c4\u03b7", "name_hi": "\u092e\u0948\u0938\u093e\u091a\u0942\u0938\u093f\u091f\u094d\u0938", "name_hu": "Massachusetts", "name_id": "Massachusetts", "name_it": "Massachusetts", "name_ja": "\u30de\u30b5\u30c1\u30e5\u30fc\u30bb\u30c3\u30c4\u5dde", "name_ko": "\ub9e4\uc0ac\ucd94\uc138\uce20", "name_nl": "Massachusetts", "name_pl": "Massachusetts", "name_pt": "Massachusetts", "name_ru": "\u041c\u0430\u0441\u0441\u0430\u0447\u0443\u0441\u0435\u0442\u0441", "name_sv": "Massachusetts", "name_tr": "Massachusetts", "name_vi": "Massachusetts", "name_zh": "\u9a6c\u8428\u8bf8\u585e\u5dde", "ne_id": 1159312157, "name_he": "\u05de\u05e1\u05e6'\u05d5\u05e1\u05d8\u05e1", "name_uk": "\u041c\u0430\u0441\u0441\u0430\u0447\u0443\u0441\u0435\u0442\u0441", "name_ur": "\u0645\u06cc\u0633\u0627\u0686\u0648\u0633\u0679\u0633", "name_fa": "\u0645\u0627\u0633\u0627\u0686\u0648\u0633\u062a", "name_zht": "\u9ebb\u85a9\u8af8\u585e\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-73.507287, 41.249468, -69.933841, 42.881564], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-71.800836, 42.011963], [-71.801638, 42.022708], [-71.921136, 42.024125], [-72.040634, 42.025553], [-72.160133, 42.02697], [-72.279642, 42.028388], [-72.39914, 42.029816], [-72.518638, 42.031233], [-72.638115, 42.03265], [-72.757624, 42.034079], [-72.763326, 42.011238], [-72.806458, 42.00803], [-72.8077, 42.034079], [-72.8918, 42.036759], [-72.975922, 42.039451], [-73.060034, 42.042132], [-73.144134, 42.044823], [-73.228234, 42.047515], [-73.312346, 42.050195], [-73.396468, 42.052887], [-73.480568, 42.055568], [-73.507287, 42.080012], [-73.475537, 42.164047], [-73.443808, 42.24807], [-73.412047, 42.332094], [-73.380296, 42.416117], [-73.348568, 42.500141], [-73.316806, 42.584175], [-73.285056, 42.668198], [-73.253327, 42.752222], [-73.155011, 42.749486], [-73.056694, 42.74674], [-72.95841, 42.744004], [-72.860094, 42.741268], [-72.761777, 42.738533], [-72.663493, 42.735786], [-72.565177, 42.733051], [-72.46686, 42.730315], [-72.324697, 42.726854], [-72.182545, 42.723361], [-72.040382, 42.719878], [-71.898241, 42.716406], [-71.75611, 42.712924], [-71.613947, 42.70943], [-71.471784, 42.705969], [-71.329621, 42.702487], [-71.242335, 42.729535], [-71.139294, 42.808131], [-71.076177, 42.825083], [-70.974082, 42.871676], [-70.923489, 42.881564], [-70.806112, 42.876763], [-70.829051, 42.825347], [-70.800278, 42.77403], [-70.781337, 42.72124], [-70.735678, 42.669286], [-70.696864, 42.664584], [-70.65483, 42.673955], [-70.62398, 42.671758], [-70.604139, 42.649719], [-70.61295, 42.623264], [-70.661444, 42.616651], [-70.75185, 42.570343], [-70.831171, 42.552567], [-70.870887, 42.496636], [-70.930444, 42.431981], [-71.046174, 42.331116], [-70.996724, 42.299981], [-70.817944, 42.264967], [-70.73826, 42.228866], [-70.617696, 42.040429], [-70.645239, 42.021565], [-70.656148, 41.987046], [-70.548922, 41.938629], [-70.514677, 41.803311], [-70.426677, 41.7573], [-70.295467, 41.728955], [-70.135012, 41.769857], [-70.001407, 41.826184], [-70.006109, 41.872327], [-70.090034, 41.979707], [-70.110238, 42.030145], [-70.172585, 42.062808], [-70.196228, 42.035111], [-70.236536, 42.071026], [-70.241085, 42.091229], [-70.203489, 42.101018], [-70.159852, 42.097118], [-70.108941, 42.078309], [-69.977896, 41.961261], [-69.941586, 41.807859], [-69.933841, 41.710421], [-69.94864, 41.677144], [-69.986751, 41.683966], [-70.059514, 41.677352], [-70.40466, 41.626892], [-70.481356, 41.582453], [-70.657126, 41.534234], [-70.668057, 41.558294], [-70.655346, 41.608106], [-70.666453, 41.710114], [-70.701126, 41.714849], [-70.974246, 41.548527], [-71.079792, 41.53809], [-71.16854, 41.489409], [-71.188414, 41.516403], [-71.204278, 41.641131], [-71.148731, 41.74572], [-71.178339, 41.744072], [-71.233765, 41.706554], [-71.267889, 41.75084], [-71.304737, 41.774658], [-71.340728, 41.797916], [-71.339487, 41.835171], [-71.33763, 41.891443], [-71.379071, 41.902407], [-71.383927, 41.971731], [-71.387135, 42.016863], [-71.462534, 42.015962], [-71.524134, 42.015237], [-71.623242, 42.014028], [-71.725821, 42.012864], [-71.800836, 42.011963]]], [[[-70.509898, 41.376338], [-70.785314, 41.327449], [-70.829183, 41.359002], [-70.760485, 41.373602], [-70.673715, 41.448529], [-70.615993, 41.457208], [-70.525356, 41.41479], [-70.509898, 41.376338]]], [[[-69.97794, 41.265596], [-70.055097, 41.249468], [-70.233076, 41.286338], [-70.086617, 41.317561], [-70.0627, 41.328482], [-70.043605, 41.374426], [-70.041199, 41.397476], [-69.985598, 41.298621], [-69.97794, 41.265596]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3557", "diss_me": 3557, "iso_3166_2": "US-MD", "wikipedia": "http://en.wikipedia.org/wiki/Maryland", "iso_a2": "US", "adm0_sr": 1, "name": "Maryland", "name_alt": "MD", "name_local": null, "type": "State", "type_en": "State", "code_local": "US24", "code_hasc": "US.MD", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Md.", "postal": "MD", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 8, "mapcolor9": 1, "mapcolor13": 1, "fips": "US24", "fips_alt": null, "woe_id": 2347579, "woe_label": "Maryland, US, United States", "woe_name": "Maryland", "latitude": 39.3874, "longitude": -77.0454, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4361885, "gn_name": "Maryland", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.MD", "region_sub": "South Atlantic", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1391", "name_ar": "\u0645\u0627\u0631\u064a\u0644\u0646\u062f", "name_bn": "\u09ae\u09c7\u09b0\u09bf\u09b2\u09cd\u09af\u09be\u09a8\u09cd\u09a1", "name_de": "Maryland", "name_en": "Maryland", "name_es": "Maryland", "name_fr": "Maryland", "name_el": "\u039c\u03ad\u03c1\u03b9\u03bb\u03b1\u03bd\u03c4", "name_hi": "\u092e\u0948\u0930\u0940\u0932\u0948\u0902\u0921", "name_hu": "Maryland", "name_id": "Maryland", "name_it": "Maryland", "name_ja": "\u30e1\u30ea\u30fc\u30e9\u30f3\u30c9\u5dde", "name_ko": "\uba54\ub9b4\ub79c\ub4dc", "name_nl": "Maryland", "name_pl": "Maryland", "name_pt": "Maryland", "name_ru": "\u041c\u044d\u0440\u0438\u043b\u0435\u043d\u0434", "name_sv": "Maryland", "name_tr": "Maryland", "name_vi": "Maryland", "name_zh": "\u9a6c\u91cc\u5170\u5dde", "ne_id": 1159315329, "name_he": "\u05de\u05e8\u05d9\u05dc\u05e0\u05d3", "name_uk": "\u041c\u0435\u0440\u0456\u043b\u0435\u043d\u0434", "name_ur": "\u0645\u06cc\u0631\u06cc \u0644\u06cc\u0646\u0688", "name_fa": "\u0645\u0631\u06cc\u0644\u0646\u062f", "name_zht": "\u99ac\u91cc\u862d\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-79.487981, 37.953965, -75.037661, 39.722797], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-77.030361, 38.889253], [-77.019737, 38.806526], [-76.931242, 38.88822], [-76.988789, 38.952347], [-77.042116, 39.011783], [-77.122053, 38.943536], [-77.1903, 38.969047], [-77.301086, 39.053378], [-77.480921, 39.112957], [-77.506454, 39.14262], [-77.502938, 39.175282], [-77.478856, 39.220864], [-77.53415, 39.265612], [-77.668821, 39.309535], [-77.726642, 39.346438], [-77.739045, 39.354337], [-77.744835, 39.400106], [-77.762358, 39.429242], [-77.791703, 39.441777], [-77.797438, 39.461465], [-77.779585, 39.488337], [-77.798141, 39.517275], [-77.853072, 39.548334], [-77.872167, 39.575778], [-77.855423, 39.599706], [-77.883252, 39.610714], [-77.955707, 39.608803], [-78.027195, 39.631226], [-78.097782, 39.677885], [-78.181135, 39.68574], [-78.325364, 39.639213], [-78.406761, 39.627864], [-78.442698, 39.601464], [-78.460265, 39.556134], [-78.495542, 39.533348], [-78.574962, 39.532854], [-78.587497, 39.534436], [-78.677673, 39.54952], [-78.741669, 39.577898], [-78.753402, 39.589522], [-78.746459, 39.613702], [-78.758214, 39.624766], [-78.77777, 39.626622], [-78.796172, 39.612626], [-78.814794, 39.570087], [-78.971481, 39.453643], [-79.046748, 39.476791], [-79.075345, 39.475989], [-79.293556, 39.311578], [-79.35977, 39.285354], [-79.487981, 39.210911], [-79.485344, 39.33889], [-79.48274, 39.466837], [-79.480126, 39.594817], [-79.4775, 39.722797], [-79.24671, 39.722775], [-79.015898, 39.722742], [-78.785086, 39.72272], [-78.554297, 39.722687], [-78.323507, 39.722665], [-78.092695, 39.722643], [-77.861883, 39.72261], [-77.631094, 39.722588], [-77.400304, 39.722566], [-77.169492, 39.722533], [-76.93868, 39.722511], [-76.707901, 39.722489], [-76.477112, 39.722456], [-76.246322, 39.722434], [-76.015532, 39.722379], [-75.78472, 39.722357], [-75.77503, 39.563945], [-75.765318, 39.405555], [-75.755606, 39.247144], [-75.745883, 39.088721], [-75.736172, 38.930309], [-75.72646, 38.771897], [-75.716748, 38.613485], [-75.707025, 38.455073], [-75.704729, 38.455073], [-75.702433, 38.45504], [-75.700125, 38.455018], [-75.697829, 38.455018], [-75.695533, 38.455018], [-75.693226, 38.455018], [-75.690908, 38.455018], [-75.688601, 38.455018], [-75.587856, 38.454996], [-75.366273, 38.454919], [-75.144657, 38.454865], [-75.037661, 38.45559], [-75.038748, 38.426366], [-75.051251, 38.383036], [-75.074355, 38.365721], [-75.073399, 38.410007], [-75.089747, 38.42541], [-75.116751, 38.406206], [-75.134242, 38.384321], [-75.141482, 38.298123], [-75.160005, 38.255056], [-75.225428, 38.24229], [-75.291786, 38.129197], [-75.35354, 38.065015], [-75.375963, 38.024991], [-75.469424, 38.014939], [-75.620002, 37.999207], [-75.659256, 37.953965], [-75.735161, 37.973707], [-75.850814, 37.971554], [-75.829039, 38.03277], [-75.795344, 38.086669], [-75.855626, 38.140359], [-75.89131, 38.147236], [-75.92807, 38.169242], [-75.88497, 38.213945], [-75.863921, 38.26123], [-75.876764, 38.318744], [-75.858702, 38.362074], [-75.888827, 38.355515], [-75.937276, 38.30968], [-75.967401, 38.291355], [-75.985715, 38.331949], [-76.006677, 38.322776], [-76.020311, 38.294871], [-76.051216, 38.279545], [-76.116485, 38.317689], [-76.211671, 38.361327], [-76.264647, 38.436418], [-76.29487, 38.494657], [-76.264175, 38.599972], [-76.198388, 38.618682], [-76.112948, 38.601576], [-76.000942, 38.60173], [-76.016927, 38.625109], [-76.05695, 38.621263], [-76.174987, 38.706682], [-76.212967, 38.758285], [-76.278314, 38.772468], [-76.308098, 38.722854], [-76.341178, 38.709648], [-76.30032, 38.818204], [-76.24697, 38.822643], [-76.168132, 38.852745], [-76.19105, 38.915554], [-76.240818, 38.943075], [-76.330664, 38.908611], [-76.329598, 38.952787], [-76.312756, 39.009356], [-76.245003, 39.009191], [-76.18571, 38.990745], [-76.135195, 39.082107], [-76.132943, 39.122965], [-76.216845, 39.063639], [-76.235698, 39.191619], [-76.153125, 39.315039], [-76.074364, 39.368861], [-75.975981, 39.367257], [-75.875984, 39.375991], [-75.938716, 39.398579], [-76.003106, 39.410851], [-75.954734, 39.459608], [-75.913447, 39.468342], [-75.872929, 39.510892], [-75.9704, 39.504564], [-75.958919, 39.58505], [-76.006314, 39.568691], [-76.063004, 39.561122], [-76.085064, 39.526998], [-76.080725, 39.470309], [-76.097259, 39.433098], [-76.141369, 39.403226], [-76.215813, 39.379946], [-76.223042, 39.420332], [-76.247662, 39.438602], [-76.256814, 39.352173], [-76.276369, 39.322741], [-76.330818, 39.403897], [-76.347198, 39.387549], [-76.345045, 39.364522], [-76.358976, 39.324685], [-76.405689, 39.303877], [-76.402778, 39.252824], [-76.420883, 39.224995], [-76.570407, 39.269336], [-76.573923, 39.254318], [-76.489383, 39.158693], [-76.427607, 39.126041], [-76.42006, 39.073889], [-76.47308, 39.030614], [-76.546248, 39.067979], [-76.558553, 39.06521], [-76.518783, 39.001182], [-76.493778, 38.945217], [-76.519508, 38.898328], [-76.515553, 38.840606], [-76.521112, 38.7883], [-76.536877, 38.742618], [-76.501314, 38.532175], [-76.458501, 38.47497], [-76.416412, 38.420236], [-76.394088, 38.368973], [-76.438736, 38.361536], [-76.509895, 38.403646], [-76.572429, 38.435792], [-76.646894, 38.538525], [-76.659188, 38.579559], [-76.677326, 38.611958], [-76.668548, 38.537515], [-76.641983, 38.454348], [-76.408766, 38.268262], [-76.365721, 38.196895], [-76.332905, 38.140776], [-76.341178, 38.087031], [-76.401943, 38.125066], [-76.454425, 38.173538], [-76.593589, 38.228315], [-76.769161, 38.262933], [-76.868115, 38.390298], [-76.867752, 38.337146], [-76.889747, 38.29208], [-76.95026, 38.347045], [-76.988393, 38.393879], [-77.001181, 38.445251], [-77.076712, 38.441758], [-77.155902, 38.397109], [-77.23252, 38.407711], [-77.241584, 38.494811], [-77.220919, 38.540953], [-77.134929, 38.650125], [-77.053894, 38.705803], [-77.018188, 38.777742], [-77.030361, 38.889253]]], [[[-75.225791, 38.040339], [-75.252476, 38.03745], [-75.225999, 38.072299], [-75.137395, 38.240093], [-75.097888, 38.298079], [-75.13623, 38.180536], [-75.203203, 38.072408], [-75.225791, 38.040339]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3561", "diss_me": 3561, "iso_3166_2": "US-ME", "wikipedia": "http://en.wikipedia.org/wiki/Maine", "iso_a2": "US", "adm0_sr": 6, "name": "Maine", "name_alt": "ME|Maine", "name_local": null, "type": "State", "type_en": "State", "code_local": "US23", "code_hasc": "US.ME", "note": null, "hasc_maybe": null, "region": "Northeast", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Maine", "postal": "ME", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 5, "mapcolor9": 1, "mapcolor13": 1, "fips": "US23", "fips_alt": null, "woe_id": 2347578, "woe_label": "Maine, US, United States", "woe_name": "Maine", "latitude": 45.148, "longitude": -69.1973, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4971068, "gn_name": "Maine", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.ME", "region_sub": "New England", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q724", "name_ar": "\u0645\u064a\u0646", "name_bn": "\u09ae\u09c7\u0987\u09a8", "name_de": "Maine", "name_en": "Maine", "name_es": "Maine", "name_fr": "Maine", "name_el": "\u039c\u03ad\u03b9\u03bd", "name_hi": "\u092e\u0947\u0928", "name_hu": "Maine", "name_id": "Maine", "name_it": "Maine", "name_ja": "\u30e1\u30a4\u30f3\u5dde", "name_ko": "\uba54\uc778", "name_nl": "Maine", "name_pl": "Maine", "name_pt": "Maine", "name_ru": "\u041c\u044d\u043d", "name_sv": "Maine", "name_tr": "Maine", "name_vi": "Maine", "name_zh": "\u7f05\u56e0\u5dde", "ne_id": 1159308501, "name_he": "\u05de\u05d9\u05d9\u05df", "name_uk": "\u041c\u0435\u043d", "name_ur": "\u0645\u06cc\u0646\u06d2", "name_fa": "\u0645\u06cc\u0646", "name_zht": "\u7f05\u56e0\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-71.084549, 43.070034, -66.987022, 47.462995], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-69.05366, 47.294585], [-69.048574, 47.273656], [-69.00309, 47.236446], [-68.937183, 47.211254], [-68.887415, 47.202827], [-68.828715, 47.203322], [-68.668546, 47.253442], [-68.480383, 47.285796], [-68.376902, 47.316151], [-68.358017, 47.344529], [-68.310886, 47.354472], [-68.235497, 47.345946], [-68.096795, 47.274843], [-67.934835, 47.167616], [-67.806789, 47.082813], [-67.802856, 46.935739], [-67.800351, 46.779854], [-67.797692, 46.61563], [-67.795836, 46.498406], [-67.792518, 46.337379], [-67.789914, 46.209323], [-67.786475, 46.042155], [-67.78464, 45.952803], [-67.767051, 45.926985], [-67.777609, 45.891796], [-67.782289, 45.874174], [-67.781125, 45.860144], [-67.774105, 45.842522], [-67.775258, 45.81788], [-67.791694, 45.795578], [-67.799911, 45.76976], [-67.802241, 45.727517], [-67.78464, 45.70171], [-67.755318, 45.686461], [-67.730665, 45.686461], [-67.698991, 45.67119], [-67.657935, 45.644186], [-67.595742, 45.62073], [-67.531197, 45.612534], [-67.486625, 45.618401], [-67.43265, 45.603108], [-67.413863, 45.56559], [-67.424432, 45.530401], [-67.454919, 45.513965], [-67.48779, 45.501045], [-67.493657, 45.474074], [-67.477221, 45.445905], [-67.453754, 45.421262], [-67.427947, 45.377954], [-67.438516, 45.340381], [-67.461972, 45.308708], [-67.472541, 45.275891], [-67.452601, 45.247678], [-67.399778, 45.21016], [-67.36694, 45.173784], [-67.315294, 45.153833], [-67.290662, 45.167918], [-67.270722, 45.186704], [-67.249584, 45.200778], [-67.213231, 45.192538], [-67.170988, 45.182002], [-67.124835, 45.169445], [-67.130372, 45.139002], [-67.102258, 45.08774], [-67.08045, 44.98917], [-67.113936, 44.94439], [-67.106729, 44.885042], [-67.014015, 44.867749], [-66.991461, 44.849611], [-66.987022, 44.827704], [-67.191247, 44.675565], [-67.364073, 44.696857], [-67.457786, 44.656526], [-67.556004, 44.644771], [-67.59907, 44.576787], [-67.652991, 44.562395], [-67.726786, 44.566482], [-67.790485, 44.585675], [-67.839056, 44.576249], [-67.907017, 44.45362], [-67.962696, 44.464309], [-67.984888, 44.420188], [-68.01398, 44.400885], [-68.056618, 44.384318], [-68.093719, 44.438843], [-68.117285, 44.490644], [-68.152034, 44.502014], [-68.198265, 44.515242], [-68.245748, 44.514781], [-68.277432, 44.507365], [-68.316752, 44.473878], [-68.373749, 44.445138], [-68.416849, 44.469066], [-68.450599, 44.507595], [-68.47946, 44.445655], [-68.521417, 44.380242], [-68.514473, 44.303909], [-68.532535, 44.258645], [-68.572349, 44.27084], [-68.612032, 44.310523], [-68.72329, 44.342306], [-68.811917, 44.339362], [-68.793889, 44.381736], [-68.710118, 44.442556], [-68.735881, 44.454499], [-68.777014, 44.44605], [-68.794943, 44.454499], [-68.765511, 44.509793], [-68.76272, 44.570767], [-68.800217, 44.549398], [-68.84737, 44.485041], [-68.961474, 44.433855], [-68.956168, 44.348096], [-69.063559, 44.172348], [-69.06836, 44.097564], [-69.137244, 44.037831], [-69.226058, 43.986459], [-69.344545, 44.000928], [-69.434952, 43.956312], [-69.480875, 43.905072], [-69.520733, 43.897371], [-69.541541, 43.962619], [-69.556702, 43.982768], [-69.58998, 43.886571], [-69.623939, 43.880628], [-69.636749, 43.948842], [-69.652877, 43.993875], [-69.699129, 43.955016], [-69.729847, 43.851997], [-69.762015, 43.860709], [-69.772276, 43.89903], [-69.795292, 43.910631], [-69.803258, 43.866829], [-69.791601, 43.805228], [-69.808344, 43.772313], [-69.840336, 43.789881], [-69.872526, 43.819544], [-69.925601, 43.797022], [-69.974326, 43.78787], [-69.974534, 43.818072], [-69.965229, 43.855106], [-70.062359, 43.834639], [-70.178814, 43.76637], [-70.269243, 43.671909], [-70.237877, 43.656199], [-70.202578, 43.626118], [-70.359682, 43.480242], [-70.520698, 43.348823], [-70.642327, 43.134425], [-70.691162, 43.109332], [-70.733096, 43.070034], [-70.812835, 43.163649], [-70.829029, 43.23907], [-70.919699, 43.328103], [-70.955635, 43.389396], [-70.967545, 43.458148], [-70.962436, 43.532152], [-70.970104, 43.643026], [-70.977751, 43.753867], [-70.985408, 43.864708], [-70.993077, 43.975561], [-71.000756, 44.086402], [-71.008403, 44.197254], [-71.016049, 44.308095], [-71.023718, 44.418947], [-71.031397, 44.529788], [-71.039044, 44.64064], [-71.04669, 44.751481], [-71.05437, 44.862322], [-71.062038, 44.973174], [-71.069685, 45.084015], [-71.077331, 45.194867], [-71.084549, 45.294008], [-71.060225, 45.309125], [-70.999877, 45.337228], [-70.960184, 45.333097], [-70.926236, 45.290701], [-70.89799, 45.262455], [-70.865053, 45.270695], [-70.836829, 45.310696], [-70.837818, 45.366177], [-70.79919, 45.404772], [-70.7533, 45.410694], [-70.710948, 45.409474], [-70.689788, 45.428338], [-70.692139, 45.455364], [-70.70741, 45.498925], [-70.702214, 45.551385], [-70.596383, 45.643988], [-70.466568, 45.706819], [-70.421096, 45.73824], [-70.407868, 45.801906], [-70.333458, 45.868054], [-70.296247, 45.906089], [-70.28715, 45.939158], [-70.306431, 45.979829], [-70.30452, 46.057393], [-70.278878, 46.149997], [-70.248292, 46.250873], [-70.17966, 46.341818], [-70.067215, 46.441046], [-70.038222, 46.571421], [-70.00768, 46.708937], [-69.871724, 46.842926], [-69.71752, 46.994856], [-69.629772, 47.081363], [-69.471492, 47.238665], [-69.358882, 47.350649], [-69.302149, 47.401988], [-69.242878, 47.462995], [-69.146286, 47.444757], [-69.050222, 47.426619], [-69.064284, 47.338146], [-69.05366, 47.294585]]], [[[-68.187256, 44.332484], [-68.24544, 44.313006], [-68.30926, 44.321509], [-68.307974, 44.268698], [-68.315104, 44.249702], [-68.38579, 44.276861], [-68.411707, 44.294351], [-68.409488, 44.364268], [-68.347042, 44.430362], [-68.299438, 44.456509], [-68.238046, 44.438404], [-68.190893, 44.364378], [-68.187256, 44.332484]]], [[[-68.623194, 44.196067], [-68.661174, 44.17627], [-68.701713, 44.182675], [-68.703032, 44.232003], [-68.690793, 44.248725], [-68.67673, 44.256217], [-68.655955, 44.242309], [-68.623194, 44.196067]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3562", "diss_me": 3562, "iso_3166_2": "US-MI", "wikipedia": "http://en.wikipedia.org/wiki/Michigan", "iso_a2": "US", "adm0_sr": 1, "name": "Michigan", "name_alt": "MI|Mich.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US26", "code_hasc": "US.MI", "note": null, "hasc_maybe": null, "region": "Midwest", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Mich.", "postal": "MI", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 8, "mapcolor9": 1, "mapcolor13": 1, "fips": "US26", "fips_alt": null, "woe_id": 2347581, "woe_label": "Michigan, US, United States", "woe_name": "Michigan", "latitude": 43.4343, "longitude": -84.9479, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5001836, "gn_name": "Michigan", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.MI", "region_sub": "East North Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1166", "name_ar": "\u0645\u064a\u0634\u064a\u063a\u0627\u0646", "name_bn": "\u09ae\u09bf\u09b6\u09bf\u0997\u09be\u09a8", "name_de": "Michigan", "name_en": "Michigan", "name_es": "M\u00edchigan", "name_fr": "Michigan", "name_el": "\u039c\u03af\u03c3\u03b9\u03b3\u03ba\u03b1\u03bd", "name_hi": "\u092e\u093f\u0936\u093f\u0917\u0928", "name_hu": "Michigan", "name_id": "Michigan", "name_it": "Michigan", "name_ja": "\u30df\u30b7\u30ac\u30f3\u5dde", "name_ko": "\ubbf8\uc2dc\uac04", "name_nl": "Michigan", "name_pl": "Michigan", "name_pt": "Michigan", "name_ru": "\u041c\u0438\u0447\u0438\u0433\u0430\u043d", "name_sv": "Michigan", "name_tr": "Michigan", "name_vi": "Michigan", "name_zh": "\u5bc6\u6b47\u6839\u5dde", "ne_id": 1159314665, "name_he": "\u05de\u05d9\u05e9\u05d9\u05d2\u05df", "name_uk": "\u041c\u0456\u0447\u0438\u0433\u0430\u043d", "name_ur": "\u0645\u0634\u06cc \u06af\u0646", "name_fa": "\u0645\u06cc\u0634\u06cc\u06af\u0627\u0646", "name_zht": "\u5bc6\u6b47\u6839\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-90.412588, 41.701434, -82.13785, 48.303097], "geometry": {"type": "Polygon", "coordinates": [[[-89.498383, 47.997897], [-89.455646, 47.996216], [-89.273174, 48.019969], [-89.185635, 48.047434], [-89.062599, 48.093808], [-88.898705, 48.155716], [-88.611764, 48.264008], [-88.378195, 48.303097], [-88.160665, 48.225402], [-87.987466, 48.156902], [-87.920493, 48.130392], [-87.743888, 48.06053], [-87.494246, 47.961752], [-87.20803, 47.848505], [-86.921825, 47.735225], [-86.672172, 47.636425], [-86.495567, 47.566585], [-86.428572, 47.540075], [-86.234498, 47.46005], [-86.040403, 47.380026], [-85.846329, 47.300013], [-85.652256, 47.219988], [-85.458193, 47.139964], [-85.26412, 47.059939], [-85.070046, 46.979926], [-84.875973, 46.899901], [-84.827062, 46.766857], [-84.779414, 46.637284], [-84.665782, 46.543252], [-84.561753, 46.457372], [-84.501581, 46.461866], [-84.440497, 46.498142], [-84.401715, 46.515611], [-84.336709, 46.5185], [-84.192173, 46.549558], [-84.14948, 46.542769], [-84.125222, 46.527234], [-84.123179, 46.502954], [-84.128145, 46.483597], [-84.150469, 46.444793], [-84.11517, 46.370811], [-84.107776, 46.288622], [-84.088407, 46.226527], [-84.029202, 46.146997], [-83.977786, 46.084914], [-83.913043, 46.072895], [-83.763201, 46.109073], [-83.669301, 46.12274], [-83.615951, 46.116829], [-83.524764, 46.058711], [-83.480149, 46.023753], [-83.46947, 45.994683], [-83.592693, 45.817155], [-83.397312, 45.729044], [-83.179288, 45.632771], [-82.919352, 45.517975], [-82.760424, 45.447718], [-82.551079, 45.347357], [-82.515242, 45.20437], [-82.485062, 45.083762], [-82.446588, 44.915507], [-82.407389, 44.743933], [-82.368278, 44.572986], [-82.326804, 44.391558], [-82.281222, 44.192233], [-82.240792, 44.015353], [-82.196605, 43.822213], [-82.13785, 43.570879], [-82.190376, 43.47409], [-82.304766, 43.263229], [-82.408191, 43.072638], [-82.417233, 43.017377], [-82.488347, 42.739511], [-82.545322, 42.624682], [-82.645133, 42.558049], [-82.744197, 42.493483], [-82.867749, 42.385213], [-83.003683, 42.331731], [-83.073138, 42.30031], [-83.109525, 42.250707], [-83.149669, 42.14192], [-83.141946, 41.975862], [-83.121665, 41.95], [-83.30395, 41.837808], [-83.464197, 41.739447], [-83.797181, 41.729955], [-84.130155, 41.720452], [-84.463129, 41.710938], [-84.796113, 41.701434], [-84.796399, 41.759728], [-85.099501, 41.75986], [-85.402614, 41.759981], [-85.705715, 41.760112], [-86.008828, 41.760244], [-86.31193, 41.760376], [-86.615043, 41.760497], [-86.918156, 41.760607], [-87.221257, 41.760728], [-87.17573, 41.943749], [-87.130203, 42.126781], [-87.084675, 42.309791], [-87.039126, 42.492802], [-87.079358, 42.782149], [-87.113855, 43.03055], [-87.15501, 43.326763], [-87.145188, 43.571264], [-87.141727, 43.657803], [-87.083203, 43.890142], [-87.03249, 44.091466], [-86.918749, 44.361587], [-86.822113, 44.591125], [-86.7147, 44.846205], [-86.535952, 45.041487], [-86.401469, 45.133366], [-86.264524, 45.226903], [-86.481823, 45.323001], [-86.77429, 45.452365], [-86.942337, 45.452365], [-87.115272, 45.452365], [-87.244384, 45.289789], [-87.419802, 45.183859], [-87.45954, 45.067997], [-87.653613, 45.121797], [-87.694208, 45.161073], [-87.71885, 45.201272], [-87.720916, 45.242768], [-87.66271, 45.345193], [-87.657568, 45.361804], [-87.664226, 45.371286], [-87.696394, 45.382832], [-87.768563, 45.364364], [-87.84182, 45.360794], [-87.86543, 45.367825], [-87.874911, 45.385392], [-87.874032, 45.412814], [-87.859135, 45.445498], [-87.815178, 45.505824], [-87.814662, 45.563239], [-87.794557, 45.596033], [-87.814091, 45.657029], [-87.809081, 45.686044], [-87.839832, 45.717981], [-87.922537, 45.759971], [-88.116116, 45.815804], [-88.096483, 45.878415], [-88.104415, 45.905155], [-88.151745, 45.945409], [-88.35475, 45.992288], [-88.492991, 46.013524], [-88.62954, 46.014041], [-88.727241, 46.031114], [-88.837335, 46.036618], [-88.907824, 46.064765], [-88.978312, 46.092901], [-89.0488, 46.121059], [-89.119289, 46.149195], [-89.244181, 46.173255], [-89.369085, 46.197337], [-89.493988, 46.221364], [-89.618925, 46.245446], [-89.743839, 46.269473], [-89.868754, 46.293555], [-89.993646, 46.317582], [-90.11855, 46.341664], [-90.14651, 46.383676], [-90.174459, 46.425721], [-90.20242, 46.467754], [-90.23038, 46.509766], [-90.28786, 46.527388], [-90.318227, 46.536639], [-90.34088, 46.558446], [-90.39234, 46.548965], [-90.412588, 46.585275], [-90.355712, 46.673012], [-90.298847, 46.760716], [-90.242003, 46.848463], [-90.185138, 46.9362], [-90.128273, 47.023948], [-90.07143, 47.111674], [-90.014553, 47.199389], [-89.957677, 47.287137], [-89.842958, 47.464489], [-89.728239, 47.641797], [-89.61352, 47.81915], [-89.498383, 47.997897]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3514", "diss_me": 3514, "iso_3166_2": "US-MN", "wikipedia": "http://en.wikipedia.org/wiki/Minnesota", "iso_a2": "US", "adm0_sr": 1, "name": "Minnesota", "name_alt": "MN|Minn.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US27", "code_hasc": "US.MN", "note": null, "hasc_maybe": null, "region": "Midwest", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Minn.", "postal": "MN", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 9, "mapcolor9": 1, "mapcolor13": 1, "fips": "US27", "fips_alt": null, "woe_id": 2347582, "woe_label": "Minnesota, US, United States", "woe_name": "Minnesota", "latitude": 46.0592, "longitude": -93.364, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5037779, "gn_name": "Minnesota", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.MN", "region_sub": "West North Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1527", "name_ar": "\u0645\u064a\u0646\u064a\u0633\u0648\u062a\u0627", "name_bn": "\u09ae\u09bf\u09a8\u09c7\u09b8\u09cb\u099f\u09be", "name_de": "Minnesota", "name_en": "Minnesota", "name_es": "Minnesota", "name_fr": "Minnesota", "name_el": "\u039c\u03b9\u03bd\u03b5\u03c3\u03cc\u03c4\u03b1", "name_hi": "\u092e\u093f\u0928\u0947\u0938\u094b\u091f\u093e", "name_hu": "Minnesota", "name_id": "Minnesota", "name_it": "Minnesota", "name_ja": "\u30df\u30cd\u30bd\u30bf\u5dde", "name_ko": "\ubbf8\ub124\uc18c\ud0c0", "name_nl": "Minnesota", "name_pl": "Minnesota", "name_pt": "Minnesota", "name_ru": "\u041c\u0438\u043d\u043d\u0435\u0441\u043e\u0442\u0430", "name_sv": "Minnesota", "name_tr": "Minnesota", "name_vi": "Minnesota", "name_zh": "\u660e\u5c3c\u82cf\u8fbe\u5dde", "ne_id": 1159315297, "name_he": "\u05de\u05d9\u05e0\u05e1\u05d5\u05d8\u05d4", "name_uk": "\u041c\u0456\u043d\u043d\u0435\u0441\u043e\u0442\u0430", "name_ur": "\u0645\u06cc\u0646\u06cc\u0633\u0648\u0679\u0627", "name_fa": "\u0645\u06cc\u0646\u0647\u0633\u0648\u062a\u0627", "name_zht": "\u660e\u5c3c\u8607\u9054\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-97.225738, 43.501171, -89.498383, 49.369672], "geometry": {"type": "Polygon", "coordinates": [[[-97.225738, 48.993182], [-97.103449, 48.993182], [-96.677064, 48.993182], [-96.250685, 48.993182], [-95.8243, 48.993182], [-95.39792, 48.993182], [-95.162044, 48.991764], [-95.158243, 49.203097], [-95.155298, 49.369672], [-94.93934, 49.349413], [-94.874795, 49.319036], [-94.854333, 49.304589], [-94.860403, 49.2586], [-94.842605, 49.119173], [-94.803461, 49.002948], [-94.712769, 48.863422], [-94.71256, 48.863016], [-94.705095, 48.808523], [-94.675355, 48.774444], [-94.620885, 48.742605], [-94.414155, 48.704109], [-94.055182, 48.659021], [-93.851628, 48.607287], [-93.803546, 48.548949], [-93.70774, 48.525461], [-93.564286, 48.536908], [-93.463618, 48.561276], [-93.377886, 48.616537], [-93.257943, 48.628864], [-93.155215, 48.625348], [-93.051707, 48.619877], [-92.996254, 48.611813], [-92.836733, 48.56778], [-92.732654, 48.531822], [-92.583256, 48.465102], [-92.500578, 48.43534], [-92.46089, 48.365884], [-92.414588, 48.276587], [-92.34844, 48.276587], [-92.298677, 48.328882], [-92.171785, 48.338396], [-92.005155, 48.301834], [-91.8584, 48.197574], [-91.647287, 48.104607], [-91.518307, 48.058311], [-91.38724, 48.058542], [-91.220655, 48.104607], [-91.043478, 48.193695], [-90.916048, 48.209153], [-90.840319, 48.200518], [-90.797318, 48.131062], [-90.744408, 48.104607], [-90.607101, 48.112594], [-90.320138, 48.09918], [-90.091776, 48.118099], [-90.039943, 48.078152], [-89.993646, 48.01531], [-89.901043, 47.995469], [-89.77537, 48.01531], [-89.550568, 47.999908], [-89.498383, 47.997897], [-89.61352, 47.81915], [-89.728239, 47.641797], [-89.842958, 47.464489], [-89.957677, 47.287137], [-90.131778, 47.292619], [-90.305856, 47.298123], [-90.479923, 47.303627], [-90.654024, 47.309098], [-90.8576, 47.213089], [-91.061188, 47.117068], [-91.264787, 47.021114], [-91.468363, 46.925093], [-91.59252, 46.876259], [-91.716643, 46.827425], [-91.840778, 46.77859], [-91.964923, 46.729778], [-92.093266, 46.761902], [-92.125346, 46.763012], [-92.194549, 46.706971], [-92.224003, 46.671023], [-92.291646, 46.660718], [-92.291904, 46.516643], [-92.29214, 46.372547], [-92.292371, 46.22845], [-92.292629, 46.084375], [-92.325473, 46.069588], [-92.367276, 46.035981], [-92.424613, 46.027807], [-92.693949, 45.909012], [-92.738081, 45.874668], [-92.786448, 45.795501], [-92.874712, 45.706094], [-92.89652, 45.658578], [-92.892488, 45.594759], [-92.757461, 45.543244], [-92.707022, 45.493761], [-92.682605, 45.433095], [-92.685808, 45.380536], [-92.753918, 45.277572], [-92.76614, 45.236461], [-92.759059, 45.11058], [-92.79304, 45.071359], [-92.765212, 44.96945], [-92.763404, 44.934261], [-92.784668, 44.822563], [-92.799214, 44.790032], [-92.7726, 44.732002], [-92.769809, 44.72585], [-92.643538, 44.645342], [-92.537031, 44.600792], [-92.441587, 44.586576], [-92.366941, 44.552266], [-92.313091, 44.497796], [-92.240307, 44.462145], [-92.148582, 44.445248], [-92.055121, 44.39982], [-91.912299, 44.288869], [-91.840976, 44.194156], [-91.716435, 44.126458], [-91.514846, 44.054212], [-91.382692, 43.990799], [-91.319916, 43.936284], [-91.278432, 43.797428], [-91.245253, 43.502412], [-91.575414, 43.50194], [-91.900609, 43.501896], [-92.225838, 43.501841], [-92.551066, 43.501786], [-92.876261, 43.501742], [-93.20149, 43.501687], [-93.526712, 43.501632], [-93.851913, 43.501577], [-94.177114, 43.501533], [-94.502342, 43.501478], [-94.827565, 43.501424], [-95.152766, 43.50138], [-95.477967, 43.501325], [-95.80319, 43.50127], [-96.128418, 43.501226], [-96.453619, 43.501171], [-96.453619, 43.725698], [-96.453619, 43.950215], [-96.453619, 44.174721], [-96.453641, 44.399259], [-96.453668, 44.623787], [-96.453668, 44.848292], [-96.453668, 45.072809], [-96.453668, 45.297337], [-96.529759, 45.371549], [-96.696109, 45.431776], [-96.737527, 45.467845], [-96.81491, 45.557427], [-96.845452, 45.595868], [-96.85106, 45.626004], [-96.813619, 45.659182], [-96.662672, 45.755653], [-96.614689, 45.799972], [-96.591052, 45.843269], [-96.556401, 45.942773], [-96.57048, 46.019237], [-96.560845, 46.138241], [-96.591904, 46.227538], [-96.598567, 46.271857], [-96.61743, 46.327096], [-96.730859, 46.472775], [-96.758198, 46.59034], [-96.786647, 46.648216], [-96.795997, 46.797091], [-96.792822, 46.839026], [-96.770135, 46.919666], [-96.818299, 46.974136], [-96.825325, 47.018861], [-96.847517, 47.373335], [-96.862947, 47.423927], [-96.858707, 47.588338], [-96.94635, 47.761526], [-96.988005, 47.820336], [-97.009032, 47.891549], [-97.007434, 47.925607], [-97.078516, 48.04337], [-97.125927, 48.173393], [-97.121609, 48.286047], [-97.136803, 48.371213], [-97.131019, 48.437427], [-97.143961, 48.536755], [-97.12913, 48.593367], [-97.128047, 48.681115], [-97.225738, 48.993182]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3531", "diss_me": 3531, "iso_3166_2": "US-MO", "wikipedia": "http://en.wikipedia.org/wiki/Missouri", "iso_a2": "US", "adm0_sr": 1, "name": "Missouri", "name_alt": "MO", "name_local": null, "type": "State", "type_en": "State", "code_local": "US29", "code_hasc": "US.MO", "note": null, "hasc_maybe": "US.IL|USA-MOS", "region": "Midwest", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Mo.", "postal": "MO", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 8, "mapcolor9": 1, "mapcolor13": 1, "fips": "US29", "fips_alt": "US17", "woe_id": 2347584, "woe_label": "Missouri, US, United States", "woe_name": "Missouri", "latitude": 38.5487, "longitude": -92.446, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4398678, "gn_name": "Missouri", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.MO", "region_sub": "West North Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1581", "name_ar": "\u0645\u064a\u0632\u0648\u0631\u064a", "name_bn": "\u09ae\u09bf\u09b8\u09cc\u09b0\u09bf", "name_de": "Missouri", "name_en": "Missouri", "name_es": "Misuri", "name_fr": "Missouri", "name_el": "\u039c\u03b9\u03b6\u03bf\u03cd\u03c1\u03b9", "name_hi": "\u092e\u093f\u0938\u094c\u0930\u0940", "name_hu": "Missouri", "name_id": "Missouri", "name_it": "Missouri", "name_ja": "\u30df\u30ba\u30fc\u30ea\u5dde", "name_ko": "\ubbf8\uc8fc\ub9ac", "name_nl": "Missouri", "name_pl": "Missouri", "name_pt": "Missouri", "name_ru": "\u041c\u0438\u0441\u0441\u0443\u0440\u0438", "name_sv": "Missouri", "name_tr": "Missouri", "name_vi": "Missouri", "name_zh": "\u5bc6\u82cf\u91cc\u5dde", "ne_id": 1159315361, "name_he": "\u05de\u05d9\u05d6\u05d5\u05e8\u05d9", "name_uk": "\u041c\u0456\u0441\u0441\u0443\u0440\u0456", "name_ur": "\u0645\u0633\u0648\u0631\u06cc", "name_fa": "\u0645\u06cc\u0632\u0648\u0631\u06cc", "name_zht": "\u5bc6\u8607\u91cc\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-95.765029, 35.99274, -89.122486, 40.624653], "geometry": {"type": "Polygon", "coordinates": [[[-89.704772, 36.001573], [-89.888178, 35.999332], [-90.052489, 35.997135], [-90.21679, 35.994938], [-90.381068, 35.99274], [-90.303043, 36.099374], [-90.25255, 36.137738], [-90.216164, 36.178409], [-90.149279, 36.215928], [-90.075659, 36.296721], [-90.067057, 36.334272], [-90.074473, 36.371835], [-90.118078, 36.422537], [-90.162243, 36.500869], [-90.440746, 36.500869], [-90.719239, 36.500869], [-90.997753, 36.500869], [-91.276256, 36.500869], [-91.55476, 36.500869], [-91.833285, 36.500869], [-92.111789, 36.500869], [-92.390298, 36.500869], [-92.668806, 36.500869], [-92.947321, 36.500869], [-93.22583, 36.500869], [-93.504339, 36.500869], [-93.782848, 36.500869], [-94.061357, 36.500869], [-94.339871, 36.500869], [-94.61838, 36.500869], [-94.618303, 36.625883], [-94.618226, 36.750863], [-94.618149, 36.875832], [-94.618067, 37.000846], [-94.618484, 37.131166], [-94.618869, 37.261497], [-94.619259, 37.391827], [-94.619671, 37.522158], [-94.620083, 37.652478], [-94.6205, 37.782809], [-94.620912, 37.91314], [-94.621297, 38.04347], [-94.621687, 38.17379], [-94.622099, 38.304121], [-94.622511, 38.434452], [-94.622928, 38.564783], [-94.62334, 38.695103], [-94.62373, 38.825433], [-94.624115, 38.955764], [-94.624527, 39.086062], [-94.622384, 39.124404], [-94.777852, 39.193992], [-94.847203, 39.259152], [-94.882294, 39.343131], [-94.952518, 39.426375], [-95.057937, 39.508959], [-95.075356, 39.597377], [-95.004764, 39.691552], [-94.945827, 39.739485], [-94.898597, 39.741144], [-94.893296, 39.781815], [-94.929936, 39.861499], [-94.984016, 39.891162], [-95.055537, 39.870794], [-95.116203, 39.87209], [-95.34668, 40.001487], [-95.362467, 40.01032], [-95.434296, 40.09598], [-95.463652, 40.198065], [-95.52122, 40.264577], [-95.607106, 40.29547], [-95.66157, 40.362761], [-95.684696, 40.466362], [-95.739551, 40.570853], [-95.765029, 40.601868], [-95.51543, 40.602944], [-95.263146, 40.604395], [-95.010888, 40.605845], [-94.758631, 40.607284], [-94.506369, 40.608734], [-94.254112, 40.610184], [-94.001855, 40.611635], [-93.749598, 40.613074], [-93.497335, 40.614524], [-93.245078, 40.615974], [-92.992821, 40.617413], [-92.740564, 40.618864], [-92.488301, 40.620314], [-92.236044, 40.621764], [-91.983787, 40.623203], [-91.73153, 40.624653], [-91.682047, 40.551869], [-91.627423, 40.530753], [-91.616855, 40.50688], [-91.545487, 40.469318], [-91.529931, 40.432316], [-91.441952, 40.37945], [-91.499784, 40.226025], [-91.501652, 40.097529], [-91.466814, 39.942864], [-91.425868, 39.826815], [-91.378737, 39.749406], [-91.209899, 39.602804], [-90.919376, 39.386901], [-90.737223, 39.181797], [-90.663527, 38.987493], [-90.577075, 38.909611], [-90.477968, 38.948118], [-90.35435, 38.93021], [-90.220075, 38.897679], [-90.149916, 38.859897], [-90.134206, 38.84667], [-90.126768, 38.832618], [-90.132195, 38.818644], [-90.150751, 38.780532], [-90.316601, 38.457809], [-90.373993, 38.309757], [-90.365775, 38.254254], [-90.299, 38.173999], [-90.173581, 38.069047], [-90.063871, 38.000525], [-89.969828, 37.968533], [-89.822963, 37.884092], [-89.623286, 37.747257], [-89.523421, 37.644524], [-89.523421, 37.575947], [-89.502931, 37.5058], [-89.461974, 37.434125], [-89.461974, 37.36568], [-89.502931, 37.300509], [-89.486913, 37.212739], [-89.413942, 37.102415], [-89.35188, 37.035519], [-89.300827, 37.012052], [-89.290016, 37.012777], [-89.285885, 37.022698], [-89.293246, 37.038177], [-89.295817, 37.051636], [-89.291675, 37.070653], [-89.281469, 37.077794], [-89.272394, 37.07998], [-89.224911, 37.052679], [-89.154313, 36.992112], [-89.122486, 36.911593], [-89.129517, 36.811057], [-89.156334, 36.715718], [-89.203048, 36.62552], [-89.256123, 36.594407], [-89.280128, 36.600043], [-89.330534, 36.615907], [-89.351309, 36.611205], [-89.397462, 36.587793], [-89.450329, 36.500023], [-89.451823, 36.497518], [-89.471488, 36.488883], [-89.485386, 36.498133], [-89.487221, 36.503066], [-89.496834, 36.528829], [-89.51952, 36.554823], [-89.535582, 36.555284], [-89.549645, 36.553065], [-89.55549, 36.540771], [-89.560038, 36.513097], [-89.557313, 36.501078], [-89.540603, 36.426667], [-89.55527, 36.372922], [-89.604093, 36.351916], [-89.611707, 36.321968], [-89.583549, 36.287657], [-89.583549, 36.272233], [-89.594623, 36.259445], [-89.627988, 36.255259], [-89.654081, 36.247964], [-89.674549, 36.220575], [-89.63413, 36.167917], [-89.641886, 36.104515], [-89.697697, 36.030303], [-89.704772, 36.001573]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3544", "diss_me": 3544, "iso_3166_2": "US-MS", "wikipedia": "http://en.wikipedia.org/wiki/Mississippi", "iso_a2": "US", "adm0_sr": 5, "name": "Mississippi", "name_alt": "MS|Miss.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US28", "code_hasc": "US.MS", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Miss.", "postal": "MS", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 11, "mapcolor9": 1, "mapcolor13": 1, "fips": "US28", "fips_alt": null, "woe_id": 2347583, "woe_label": "Mississippi, US, United States", "woe_name": "Mississippi", "latitude": 32.8657, "longitude": -89.7189, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4436296, "gn_name": "Mississippi", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.MS", "region_sub": "East South Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1494", "name_ar": "\u0645\u0633\u064a\u0633\u064a\u0628\u064a", "name_bn": "\u09ae\u09bf\u09b8\u09bf\u09b8\u09bf\u09aa\u09bf", "name_de": "Mississippi", "name_en": "Mississippi", "name_es": "Misisipi", "name_fr": "Mississippi", "name_el": "\u039c\u03b9\u03c3\u03b9\u03c3\u03af\u03c0\u03b9", "name_hi": "\u092e\u093f\u0938\u093f\u0938\u093f\u092a\u094d\u092a\u0940", "name_hu": "Mississippi", "name_id": "Mississippi", "name_it": "Mississippi", "name_ja": "\u30df\u30b7\u30b7\u30c3\u30d4\u5dde", "name_ko": "\ubbf8\uc2dc\uc2dc\ud53c", "name_nl": "Mississippi", "name_pl": "Missisipi", "name_pt": "Mississippi", "name_ru": "\u041c\u0438\u0441\u0441\u0438\u0441\u0438\u043f\u0438", "name_sv": "Mississippi", "name_tr": "Mississippi", "name_vi": "Mississippi", "name_zh": "\u5bc6\u897f\u897f\u6bd4\u5dde", "ne_id": 1159315231, "name_he": "\u05de\u05d9\u05e1\u05d9\u05e1\u05d9\u05e4\u05d9", "name_uk": "\u041c\u0456\u0441\u0441\u0456\u0441\u0456\u043f\u0456", "name_ur": "\u0645\u0633\u06cc\u0633\u067e\u06cc", "name_fa": "\u0645\u06cc\u0633\u06cc\u0633\u06cc\u067e\u06cc", "name_zht": "\u5bc6\u897f\u897f\u6bd4\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-91.656449, 30.192629, -88.084772, 35.001114], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-88.173267, 34.999005], [-88.084772, 34.933109], [-88.088211, 34.909082], [-88.089474, 34.893064], [-88.095648, 34.846196], [-88.12006, 34.66145], [-88.144461, 34.476737], [-88.168883, 34.292013], [-88.193295, 34.107278], [-88.217684, 33.922532], [-88.242096, 33.737807], [-88.266519, 33.553094], [-88.290908, 33.368348], [-88.315331, 33.183613], [-88.339743, 32.998889], [-88.364132, 32.814176], [-88.388555, 32.62943], [-88.412977, 32.444684], [-88.437367, 32.25997], [-88.461779, 32.075246], [-88.48619, 31.890511], [-88.475709, 31.702821], [-88.465217, 31.515108], [-88.454726, 31.327385], [-88.444234, 31.139706], [-88.433742, 30.952015], [-88.423261, 30.764303], [-88.412758, 30.576579], [-88.399585, 30.370805], [-88.692096, 30.355359], [-88.819889, 30.406489], [-88.872942, 30.416333], [-88.905209, 30.415146], [-89.054041, 30.368246], [-89.223637, 30.332364], [-89.263561, 30.343625], [-89.320536, 30.345328], [-89.443495, 30.223138], [-89.520861, 30.192629], [-89.545075, 30.200693], [-89.572486, 30.209164], [-89.591657, 30.223017], [-89.628988, 30.296186], [-89.640777, 30.348921], [-89.685766, 30.462684], [-89.736632, 30.526613], [-89.794003, 30.568933], [-89.819997, 30.611208], [-89.819733, 30.639861], [-89.838124, 30.690431], [-89.835366, 30.730816], [-89.764933, 30.886075], [-89.735314, 31.001157], [-89.975563, 31.001157], [-90.215834, 31.001157], [-90.456105, 31.001212], [-90.696343, 31.001212], [-90.936614, 31.001212], [-91.176885, 31.001234], [-91.417123, 31.001256], [-91.656449, 31.001805], [-91.652615, 31.029557], [-91.611043, 31.0649], [-91.596365, 31.109911], [-91.630807, 31.217599], [-91.61825, 31.276958], [-91.558693, 31.287911], [-91.528953, 31.345194], [-91.529008, 31.448751], [-91.505728, 31.518701], [-91.459091, 31.554978], [-91.414706, 31.639979], [-91.37253, 31.773716], [-91.286496, 31.883974], [-91.156527, 31.970689], [-91.092543, 32.045847], [-91.088698, 32.10414], [-91.074591, 32.131321], [-91.048158, 32.145921], [-91.004597, 32.185582], [-90.947721, 32.240074], [-90.937647, 32.277329], [-90.940437, 32.303092], [-90.9447, 32.330711], [-90.990019, 32.381051], [-91.059276, 32.423755], [-91.103815, 32.490497], [-91.100816, 32.541374], [-91.11612, 32.586231], [-91.14965, 32.625013], [-91.142421, 32.661026], [-91.094356, 32.69426], [-91.092082, 32.725857], [-91.135587, 32.755783], [-91.13606, 32.808847], [-91.093378, 32.885027], [-91.096081, 32.937684], [-91.144179, 32.966875], [-91.149958, 33.015918], [-91.152858, 33.040571], [-91.106781, 33.217923], [-91.117306, 33.240819], [-91.163339, 33.294454], [-91.168459, 33.35946], [-91.141015, 33.438507], [-91.15433, 33.500206], [-91.192958, 33.52253], [-91.202714, 33.546975], [-91.214579, 33.583406], [-91.172721, 33.616683], [-91.17037, 33.647456], [-91.207482, 33.675669], [-91.184125, 33.71567], [-91.100299, 33.767449], [-91.077151, 33.796694], [-91.052707, 33.827599], [-91.038183, 33.901394], [-91.05007, 33.945163], [-91.070175, 33.9742], [-91.060353, 33.989296], [-91.043148, 34.002864], [-90.943107, 34.029681], [-90.914729, 34.048622], [-90.908786, 34.071561], [-90.940251, 34.128558], [-90.90972, 34.188763], [-90.817215, 34.25222], [-90.768117, 34.308108], [-90.762338, 34.356426], [-90.718107, 34.391703], [-90.635424, 34.413873], [-90.584008, 34.503708], [-90.563848, 34.661164], [-90.53925, 34.72817], [-90.497216, 34.738091], [-90.47476, 34.760052], [-90.467575, 34.805261], [-90.41595, 34.851623], [-90.31994, 34.899161], [-90.282104, 34.945304], [-90.293419, 34.970067], [-90.293705, 35.001114], [-90.038635, 35.00084], [-89.772997, 35.000554], [-89.507348, 35.000268], [-89.241698, 34.999983], [-88.97606, 34.999697], [-88.710421, 34.999412], [-88.444772, 34.999126], [-88.173267, 34.999005]]], [[[-88.558107, 30.215909], [-88.570653, 30.204802], [-88.659236, 30.225599], [-88.713102, 30.244924], [-88.722847, 30.264249], [-88.573993, 30.229159], [-88.558107, 30.215909]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3515", "diss_me": 3515, "iso_3166_2": "US-MT", "wikipedia": "http://en.wikipedia.org/wiki/Montana", "iso_a2": "US", "adm0_sr": 1, "name": "Montana", "name_alt": "MT|Mont.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US30", "code_hasc": "US.MT", "note": null, "hasc_maybe": null, "region": "West", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Mont.", "postal": "MT", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 7, "mapcolor9": 1, "mapcolor13": 1, "fips": "US30", "fips_alt": null, "woe_id": 2347585, "woe_label": "Montana, US, United States", "woe_name": "Montana", "latitude": 46.9965, "longitude": -110.044, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5667009, "gn_name": "Montana", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.MT", "region_sub": "Mountain", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1212", "name_ar": "\u0645\u0648\u0646\u062a\u0627\u0646\u0627", "name_bn": "\u09ae\u09a8\u09cd\u099f\u09be\u09a8\u09be", "name_de": "Montana", "name_en": "Montana", "name_es": "Montana", "name_fr": "Montana", "name_el": "\u039c\u03bf\u03bd\u03c4\u03ac\u03bd\u03b1", "name_hi": "\u092e\u094b\u0928\u094d\u091f\u093e\u0928\u093e", "name_hu": "Montana", "name_id": "Montana", "name_it": "Montana", "name_ja": "\u30e2\u30f3\u30bf\u30ca\u5dde", "name_ko": "\ubaac\ud0dc\ub098", "name_nl": "Montana", "name_pl": "Montana", "name_pt": "Montana", "name_ru": "\u041c\u043e\u043d\u0442\u0430\u043d\u0430", "name_sv": "Montana", "name_tr": "Montana", "name_vi": "Montana", "name_zh": "\u8499\u5927\u62ff\u5dde", "ne_id": 1159315333, "name_he": "\u05de\u05d5\u05e0\u05d8\u05e0\u05d4", "name_uk": "\u041c\u043e\u043d\u0442\u0430\u043d\u0430", "name_ur": "\u0645\u0648\u0646\u0679\u0627\u0646\u0627", "name_fa": "\u0627\u06cc\u0627\u0644\u062a \u0645\u0648\u0646\u062a\u0627\u0646\u0627", "name_zht": "\u8499\u5927\u62ff\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-116.04901, 44.396623, -104.00478, 48.993138], "geometry": {"type": "Polygon", "coordinates": [[[-114.062517, 48.993083], [-113.732356, 48.993083], [-113.305971, 48.993083], [-112.879592, 48.993083], [-112.453207, 48.993083], [-112.026827, 48.993083], [-111.600442, 48.993083], [-111.174063, 48.993083], [-110.747678, 48.993083], [-110.321299, 48.993083], [-109.999432, 48.993083], [-109.894914, 48.993083], [-109.468534, 48.993083], [-109.042149, 48.993105], [-108.61577, 48.993138], [-108.189385, 48.993138], [-107.763006, 48.993138], [-107.336621, 48.993138], [-106.910241, 48.993138], [-106.483856, 48.993138], [-106.057477, 48.993138], [-105.631092, 48.993138], [-105.204707, 48.993138], [-104.778328, 48.993138], [-104.351943, 48.993138], [-104.033927, 48.993138], [-104.031911, 48.803327], [-104.030516, 48.612637], [-104.029121, 48.421958], [-104.027725, 48.231269], [-104.02633, 48.040579], [-104.024962, 47.8499], [-104.023595, 47.659211], [-104.022199, 47.468521], [-104.020804, 47.277842], [-104.019409, 47.087152], [-104.018013, 46.896463], [-104.01664, 46.705784], [-104.015272, 46.515094], [-104.013877, 46.324405], [-104.012482, 46.133726], [-104.011087, 45.943058], [-104.00951, 45.710642], [-104.007934, 45.47826], [-104.006357, 45.245866], [-104.00478, 45.013483], [-104.004962, 45.010352], [-104.005143, 45.007232], [-104.005302, 45.004101], [-104.005478, 45.00097], [-104.013416, 45.001024], [-104.021348, 45.001057], [-104.02928, 45.001079], [-104.037212, 45.001134], [-104.256395, 45.001134], [-104.475556, 45.001134], [-104.694738, 45.001134], [-104.913927, 45.001134], [-105.133087, 45.001134], [-105.35227, 45.001134], [-105.571458, 45.001134], [-105.790619, 45.001101], [-106.009802, 45.001079], [-106.22899, 45.001079], [-106.448151, 45.001079], [-106.667334, 45.001079], [-106.886522, 45.001079], [-107.105677, 45.001079], [-107.324865, 45.001079], [-107.544048, 45.001079], [-107.763209, 45.001079], [-107.982397, 45.001079], [-108.20158, 45.001079], [-108.420741, 45.001079], [-108.639929, 45.001079], [-108.859112, 45.001079], [-109.078272, 45.001079], [-109.297455, 45.001079], [-109.516643, 45.001079], [-109.735804, 45.001079], [-109.954987, 45.001079], [-110.174175, 45.001079], [-110.393336, 45.001079], [-110.612519, 45.001079], [-110.831707, 45.001079], [-111.050862, 45.001057], [-111.051022, 44.875506], [-111.051148, 44.749987], [-111.05128, 44.624457], [-111.051434, 44.498883], [-111.11722, 44.525349], [-111.160934, 44.555836], [-111.197574, 44.590586], [-111.265118, 44.687552], [-111.304081, 44.723312], [-111.337463, 44.744812], [-111.372525, 44.74624], [-111.41557, 44.733551], [-111.4481, 44.711117], [-111.459109, 44.671017], [-111.491046, 44.624226], [-111.488821, 44.584544], [-111.474506, 44.564615], [-111.47934, 44.553716], [-111.499857, 44.54485], [-111.659302, 44.559605], [-111.797098, 44.539895], [-111.89208, 44.554925], [-112.074211, 44.547619], [-112.23131, 44.560692], [-112.285077, 44.553947], [-112.320036, 44.53315], [-112.36386, 44.479558], [-112.375385, 44.470022], [-112.392848, 44.467957], [-112.648236, 44.497104], [-112.715928, 44.498037], [-112.787142, 44.463079], [-112.810163, 44.438162], [-112.815514, 44.405972], [-112.831351, 44.396623], [-112.853856, 44.398325], [-112.910392, 44.419331], [-112.970075, 44.454499], [-112.999689, 44.48036], [-113.006379, 44.539137], [-113.05428, 44.605187], [-113.062706, 44.665073], [-113.09327, 44.715336], [-113.140709, 44.765489], [-113.18717, 44.798579], [-113.234269, 44.809873], [-113.320418, 44.802534], [-113.338891, 44.808072], [-113.432138, 44.874165], [-113.460796, 44.90362], [-113.469294, 44.929976], [-113.438136, 44.993971], [-113.447129, 45.029084], [-113.471079, 45.072853], [-113.503582, 45.109284], [-113.557404, 45.140419], [-113.606573, 45.209105], [-113.697112, 45.304983], [-113.721941, 45.379273], [-113.756097, 45.44084], [-113.76615, 45.502517], [-113.799614, 45.540189], [-113.796642, 45.587661], [-113.802273, 45.601098], [-113.812814, 45.606986], [-113.872915, 45.63354], [-113.942651, 45.681507], [-113.977818, 45.69235], [-113.991924, 45.69302], [-114.000708, 45.680628], [-114.006393, 45.658457], [-114.116619, 45.579103], [-114.210234, 45.542442], [-114.256146, 45.505648], [-114.297641, 45.487565], [-114.319191, 45.48573], [-114.350562, 45.497145], [-114.448434, 45.551253], [-114.529233, 45.575719], [-114.537346, 45.587398], [-114.532617, 45.633024], [-114.495796, 45.685846], [-114.533699, 45.78201], [-114.522537, 45.815133], [-114.492566, 45.838732], [-114.405131, 45.874251], [-114.396787, 45.89095], [-114.415903, 45.982159], [-114.464792, 46.016414], [-114.478306, 46.035585], [-114.463578, 46.109765], [-114.485359, 46.158214], [-114.446599, 46.199325], [-114.444248, 46.270714], [-114.41275, 46.343631], [-114.38022, 46.453033], [-114.387042, 46.499955], [-114.345805, 46.550591], [-114.332061, 46.601392], [-114.330122, 46.637647], [-114.336868, 46.659224], [-114.350897, 46.667639], [-114.380917, 46.667639], [-114.518664, 46.647743], [-114.562999, 46.650435], [-114.60155, 46.660334], [-114.624006, 46.677615], [-114.630648, 46.718572], [-114.661623, 46.745544], [-114.678032, 46.750169], [-114.740302, 46.733634], [-114.753689, 46.734568], [-114.760715, 46.742292], [-114.786066, 46.776756], [-114.886937, 46.844871], [-114.935694, 46.922819], [-115.033516, 46.990934], [-115.126636, 47.084593], [-115.306675, 47.231172], [-115.349467, 47.261176], [-115.485994, 47.311636], [-115.593325, 47.384915], [-115.702468, 47.437594], [-115.713317, 47.446746], [-115.714454, 47.45225], [-115.708022, 47.456798], [-115.676887, 47.470564], [-115.66968, 47.497854], [-115.710862, 47.552599], [-115.690867, 47.606652], [-115.718382, 47.68148], [-115.733757, 47.706342], [-115.811244, 47.775951], [-115.862149, 47.842408], [-115.941443, 47.904107], [-116.04901, 48.00472], [-116.048801, 48.251989], [-116.048598, 48.499313], [-116.048389, 48.746637], [-116.048494, 48.993083], [-115.864264, 48.993083], [-115.437884, 48.993083], [-115.0115, 48.993083], [-114.58512, 48.993083], [-114.158735, 48.993083], [-114.062517, 48.993083]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3549", "diss_me": 3549, "iso_3166_2": "US-NC", "wikipedia": "http://en.wikipedia.org/wiki/North_Carolina", "iso_a2": "US", "adm0_sr": 5, "name": "North Carolina", "name_alt": "NC|N.C.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US37", "code_hasc": "US.NC", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "N.C.", "postal": "NC", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 14, "mapcolor9": 1, "mapcolor13": 1, "fips": "US37", "fips_alt": null, "woe_id": 2347592, "woe_label": "North Carolina, US, United States", "woe_name": "North Carolina", "latitude": 35.6152, "longitude": -78.866, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4482348, "gn_name": "North Carolina", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.NC", "region_sub": "South Atlantic", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1454", "name_ar": "\u0643\u0627\u0631\u0648\u0644\u0627\u064a\u0646\u0627 \u0627\u0644\u0634\u0645\u0627\u0644\u064a\u0629", "name_bn": "\u09a8\u09b0\u09cd\u09a5 \u0995\u09cd\u09af\u09be\u09b0\u09cb\u09b2\u09be\u0987\u09a8\u09be", "name_de": "North Carolina", "name_en": "North Carolina", "name_es": "Carolina del Norte", "name_fr": "Caroline du Nord", "name_el": "\u0392\u03cc\u03c1\u03b5\u03b9\u03b1 \u039a\u03b1\u03c1\u03bf\u03bb\u03af\u03bd\u03b1", "name_hi": "\u0909\u0924\u094d\u0924\u0930\u0940 \u0915\u0947\u0930\u094b\u0932\u093f\u0928\u093e", "name_hu": "\u00c9szak-Karolina", "name_id": "Carolina Utara", "name_it": "Carolina del Nord", "name_ja": "\u30ce\u30fc\u30b9\u30ab\u30ed\u30e9\u30a4\u30ca\u5dde", "name_ko": "\ub178\uc2a4\uce90\ub864\ub77c\uc774\ub098", "name_nl": "North Carolina", "name_pl": "Karolina P\u00f3\u0142nocna", "name_pt": "Carolina do Norte", "name_ru": "\u0421\u0435\u0432\u0435\u0440\u043d\u0430\u044f \u041a\u0430\u0440\u043e\u043b\u0438\u043d\u0430", "name_sv": "North Carolina", "name_tr": "Kuzey Karolina", "name_vi": "B\u1eafc Carolina", "name_zh": "\u5317\u5361\u7f57\u6765\u7eb3\u5dde", "ne_id": 1159314887, "name_he": "\u05e7\u05e8\u05d5\u05dc\u05d9\u05d9\u05e0\u05d4 \u05d4\u05e6\u05e4\u05d5\u05e0\u05d9\u05ea", "name_uk": "\u041f\u0456\u0432\u043d\u0456\u0447\u043d\u0430 \u041a\u0430\u0440\u043e\u043b\u0456\u043d\u0430", "name_ur": "\u0634\u0645\u0627\u0644\u06cc \u06a9\u06cc\u0631\u0648\u0644\u06cc\u0646\u0627", "name_fa": "\u06a9\u0627\u0631\u0648\u0644\u06cc\u0646\u0627\u06cc \u0634\u0645\u0627\u0644\u06cc", "name_zht": "\u5317\u5361\u7f85\u840a\u7d0d\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-84.32469, 33.876664, -75.456471, 36.610579], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-83.114821, 35.001477], [-83.417307, 34.998126], [-83.719772, 34.994786], [-84.022225, 34.991457], [-84.32469, 34.988096], [-84.286974, 35.200846], [-84.261101, 35.249581], [-84.232471, 35.260589], [-84.128584, 35.261413], [-84.062281, 35.286012], [-84.003735, 35.414069], [-83.871306, 35.51489], [-83.811705, 35.54029], [-83.722716, 35.559901], [-83.511119, 35.584082], [-83.284241, 35.682058], [-83.120369, 35.774618], [-82.990203, 35.800447], [-82.949476, 35.834526], [-82.920253, 35.8789], [-82.901862, 35.939171], [-82.887722, 35.951728], [-82.812817, 35.947444], [-82.75559, 35.999871], [-82.700087, 36.029841], [-82.644924, 36.046793], [-82.611097, 36.047364], [-82.598101, 36.031599], [-82.588751, 35.986951], [-82.576842, 35.972273], [-82.553408, 35.970987], [-82.52113, 35.981216], [-82.478426, 36.010055], [-82.368245, 36.099549], [-82.294944, 36.13397], [-82.182499, 36.153789], [-82.100618, 36.106526], [-82.051366, 36.122862], [-81.908247, 36.306411], [-81.851151, 36.3397], [-81.80826, 36.352718], [-81.734125, 36.355454], [-81.733323, 36.405914], [-81.707648, 36.481962], [-81.704418, 36.533993], [-81.65889, 36.610579], [-81.641631, 36.595077], [-81.27984, 36.592264], [-80.918049, 36.589452], [-80.556269, 36.586628], [-80.194479, 36.583816], [-79.832688, 36.580992], [-79.470908, 36.57818], [-79.109117, 36.575389], [-78.747337, 36.572577], [-78.385547, 36.569753], [-78.023756, 36.566963], [-77.661976, 36.56415], [-77.300185, 36.561338], [-76.938395, 36.558514], [-76.576615, 36.555702], [-76.214824, 36.552889], [-75.966445, 36.551362], [-75.992768, 36.473799], [-75.978486, 36.42915], [-75.924873, 36.382997], [-75.866579, 36.26786], [-75.820074, 36.112832], [-75.883015, 36.175696], [-75.950185, 36.208973], [-76.054731, 36.234528], [-76.147829, 36.279286], [-76.141062, 36.215104], [-76.150027, 36.145758], [-76.221745, 36.166885], [-76.27058, 36.189912], [-76.227381, 36.11604], [-76.321172, 36.138155], [-76.383684, 36.13353], [-76.424322, 36.067975], [-76.478814, 36.028193], [-76.559355, 36.01535], [-76.67893, 36.075314], [-76.717635, 36.148076], [-76.733631, 36.229155], [-76.740069, 36.133299], [-76.718778, 36.033511], [-76.726216, 35.957595], [-76.611156, 35.943642], [-76.503512, 35.956046], [-76.358327, 35.952893], [-76.263559, 35.967109], [-76.206562, 35.991213], [-76.069771, 35.970306], [-76.060027, 35.878658], [-76.075715, 35.787527], [-76.08357, 35.690539], [-76.045711, 35.691155], [-76.001195, 35.722191], [-75.978925, 35.895951], [-75.85389, 35.960155], [-75.81201, 35.955738], [-75.772218, 35.899873], [-75.758836, 35.843238], [-75.744752, 35.765466], [-75.773921, 35.647001], [-75.965951, 35.508397], [-76.10351, 35.380297], [-76.173845, 35.354149], [-76.275238, 35.369058], [-76.390221, 35.401247], [-76.446646, 35.407762], [-76.489482, 35.397018], [-76.51563, 35.43647], [-76.532483, 35.50843], [-76.577186, 35.532303], [-76.611057, 35.529667], [-76.634128, 35.453213], [-76.741388, 35.431482], [-76.887242, 35.463111], [-77.039996, 35.527392], [-76.974474, 35.458409], [-76.595445, 35.329704], [-76.552785, 35.305622], [-76.512949, 35.270433], [-76.565969, 35.215194], [-76.607519, 35.153], [-76.613408, 35.104166], [-76.628031, 35.07336], [-76.779137, 34.990348], [-76.86104, 35.004993], [-77.070274, 35.154648], [-76.974957, 35.025174], [-76.898657, 34.970243], [-76.744969, 34.940964], [-76.456754, 34.989337], [-76.362206, 34.936504], [-76.439802, 34.842911], [-76.516871, 34.777257], [-76.618, 34.76994], [-76.707066, 34.752142], [-76.733192, 34.706999], [-76.796649, 34.704165], [-76.895866, 34.701473], [-77.049499, 34.697364], [-77.133918, 34.707933], [-77.251769, 34.615637], [-77.29623, 34.602948], [-77.358369, 34.620262], [-77.384472, 34.694365], [-77.412268, 34.730796], [-77.412949, 34.592126], [-77.402062, 34.554795], [-77.379792, 34.526626], [-77.517671, 34.45138], [-77.649671, 34.357513], [-77.696957, 34.331959], [-77.750757, 34.284993], [-77.860829, 34.14918], [-77.888053, 34.050149], [-77.927845, 33.939736], [-77.932855, 33.989471], [-77.926043, 34.073165], [-77.953268, 34.168977], [-77.97056, 33.993426], [-78.013341, 33.911809], [-78.405882, 33.917566], [-78.564272, 33.876664], [-78.708237, 33.997821], [-78.843292, 34.111947], [-78.978347, 34.226073], [-79.11338, 34.340232], [-79.248413, 34.45438], [-79.383468, 34.568506], [-79.518523, 34.682643], [-79.653556, 34.796791], [-79.794862, 34.800768], [-79.936179, 34.804745], [-80.077507, 34.808733], [-80.218824, 34.81271], [-80.36013, 34.816687], [-80.501459, 34.820664], [-80.642776, 34.824641], [-80.784082, 34.828629], [-80.789278, 34.90717], [-80.79297, 34.962772], [-80.881695, 35.057914], [-80.933683, 35.113669], [-81.045249, 35.065615], [-81.051171, 35.088972], [-81.046853, 35.131083], [-81.05662, 35.145508], [-81.087316, 35.155714], [-81.245914, 35.161471], [-81.404513, 35.167206], [-81.5631, 35.172941], [-81.721699, 35.178675], [-81.880298, 35.184421], [-82.038885, 35.190156], [-82.197484, 35.195891], [-82.356083, 35.201626], [-82.392535, 35.210931], [-82.463957, 35.177961], [-82.651483, 35.128039], [-82.743966, 35.084061], [-82.777529, 35.086643], [-82.936974, 35.04417], [-83.09655, 35.001642], [-83.114821, 35.001477]]], [[[-75.889057, 36.550505], [-75.857428, 36.550582], [-75.757881, 36.229232], [-75.558687, 35.879361], [-75.534199, 35.81908], [-75.580495, 35.872001], [-75.728239, 36.103713], [-75.809791, 36.271046], [-75.889057, 36.550505]]], [[[-75.635691, 35.855895], [-75.650775, 35.835592], [-75.717176, 35.946125], [-75.648863, 35.910387], [-75.636668, 35.880658], [-75.635691, 35.855895]]], [[[-75.54412, 35.2401], [-75.678274, 35.212843], [-75.690106, 35.221566], [-75.536363, 35.278618], [-75.487892, 35.479514], [-75.481278, 35.572118], [-75.504327, 35.735386], [-75.503525, 35.769158], [-75.478487, 35.716478], [-75.456471, 35.564164], [-75.464743, 35.448642], [-75.509337, 35.280332], [-75.54412, 35.2401]]], [[[-75.781963, 35.1902], [-75.963676, 35.118844], [-75.984199, 35.123074], [-75.86492, 35.174127], [-75.781963, 35.1902]]], [[[-76.503644, 34.642949], [-76.528582, 34.631501], [-76.437033, 34.756328], [-76.25622, 34.914718], [-76.207386, 34.938899], [-76.357712, 34.803668], [-76.503644, 34.642949]]], [[[-76.546227, 34.654858], [-76.568496, 34.652562], [-76.607794, 34.66357], [-76.661957, 34.684653], [-76.673921, 34.700155], [-76.622274, 34.694552], [-76.546227, 34.654858]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3516", "diss_me": 3516, "iso_3166_2": "US-ND", "wikipedia": "http://en.wikipedia.org/wiki/North_Dakota", "iso_a2": "US", "adm0_sr": 1, "name": "North Dakota", "name_alt": "ND|N.D.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US38", "code_hasc": "US.ND", "note": null, "hasc_maybe": null, "region": "Midwest", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "N.D.", "postal": "ND", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 12, "mapcolor9": 1, "mapcolor13": 1, "fips": "US38", "fips_alt": null, "woe_id": 2347593, "woe_label": "North Dakota, US, United States", "woe_name": "North Dakota", "latitude": 47.4675, "longitude": -100.302, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5690763, "gn_name": "North Dakota", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.ND", "region_sub": "West North Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1207", "name_ar": "\u062f\u0627\u0643\u0648\u062a\u0627 \u0627\u0644\u0634\u0645\u0627\u0644\u064a\u0629", "name_bn": "\u09a8\u09b0\u09cd\u09a5 \u09a1\u09be\u0995\u09cb\u099f\u09be", "name_de": "North Dakota", "name_en": "North Dakota", "name_es": "Dakota del Norte", "name_fr": "Dakota du Nord", "name_el": "\u0392\u03cc\u03c1\u03b5\u03b9\u03b1 \u039d\u03c4\u03b1\u03ba\u03cc\u03c4\u03b1", "name_hi": "\u0909\u0924\u094d\u0924\u0930 \u0921\u0947\u0915\u094b\u091f\u093e", "name_hu": "\u00c9szak-Dakota", "name_id": "Dakota Utara", "name_it": "Dakota del Nord", "name_ja": "\u30ce\u30fc\u30b9\u30c0\u30b3\u30bf\u5dde", "name_ko": "\ub178\uc2a4\ub2e4\ucf54\ud0c0", "name_nl": "Noord-Dakota", "name_pl": "Dakota P\u00f3\u0142nocna", "name_pt": "Dakota do Norte", "name_ru": "\u0421\u0435\u0432\u0435\u0440\u043d\u0430\u044f \u0414\u0430\u043a\u043e\u0442\u0430", "name_sv": "North Dakota", "name_tr": "Kuzey Dakota", "name_vi": "B\u1eafc Dakota", "name_zh": "\u5317\u8fbe\u79d1\u4ed6\u5dde", "ne_id": 1159315337, "name_he": "\u05d3\u05e7\u05d5\u05d8\u05d4 \u05d4\u05e6\u05e4\u05d5\u05e0\u05d9\u05ea", "name_uk": "\u041f\u0456\u0432\u043d\u0456\u0447\u043d\u0430 \u0414\u0430\u043a\u043e\u0442\u0430", "name_ur": "\u0634\u0645\u0627\u0644\u06cc \u0688\u06a9\u0648\u0679\u0627", "name_fa": "\u062f\u0627\u06a9\u0648\u062a\u0627\u06cc \u0634\u0645\u0627\u0644\u06cc", "name_zht": "\u5317\u9054\u79d1\u4ed6\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-104.033927, 45.942773, -96.556401, 48.993182], "geometry": {"type": "Polygon", "coordinates": [[[-101.367271, 48.993138], [-100.940886, 48.993138], [-100.514506, 48.993138], [-100.088121, 48.993138], [-99.661742, 48.993138], [-99.235357, 48.993138], [-98.808978, 48.99316], [-98.382593, 48.993182], [-97.956213, 48.993182], [-97.529828, 48.993182], [-97.225738, 48.993182], [-97.128047, 48.681115], [-97.12913, 48.593367], [-97.143961, 48.536755], [-97.131019, 48.437427], [-97.136803, 48.371213], [-97.121609, 48.286047], [-97.125927, 48.173393], [-97.078516, 48.04337], [-97.007434, 47.925607], [-97.009032, 47.891549], [-96.988005, 47.820336], [-96.94635, 47.761526], [-96.858707, 47.588338], [-96.862947, 47.423927], [-96.847517, 47.373335], [-96.825325, 47.018861], [-96.818299, 46.974136], [-96.770135, 46.919666], [-96.792822, 46.839026], [-96.795997, 46.797091], [-96.786647, 46.648216], [-96.758198, 46.59034], [-96.730859, 46.472775], [-96.61743, 46.327096], [-96.598567, 46.271857], [-96.591904, 46.227538], [-96.560845, 46.138241], [-96.57048, 46.019237], [-96.556401, 45.942773], [-96.789355, 45.942773], [-97.022315, 45.942805], [-97.255275, 45.942827], [-97.488229, 45.942827], [-97.721188, 45.942827], [-97.954142, 45.942827], [-98.187102, 45.942827], [-98.420062, 45.94286], [-98.653016, 45.942882], [-98.885975, 45.942882], [-99.118929, 45.942882], [-99.351889, 45.942882], [-99.584849, 45.942882], [-99.817803, 45.942904], [-100.050762, 45.942937], [-100.283744, 45.942937], [-100.516725, 45.942937], [-100.749685, 45.942937], [-100.982645, 45.942937], [-101.215599, 45.942959], [-101.448558, 45.942981], [-101.681513, 45.942981], [-101.914472, 45.942981], [-102.147426, 45.942981], [-102.380386, 45.942981], [-102.613345, 45.943014], [-102.8463, 45.943036], [-103.079259, 45.943036], [-103.312213, 45.943036], [-103.545173, 45.943036], [-103.778132, 45.943036], [-104.011087, 45.943058], [-104.012482, 46.133726], [-104.013877, 46.324405], [-104.015272, 46.515094], [-104.01664, 46.705784], [-104.018013, 46.896463], [-104.019409, 47.087152], [-104.020804, 47.277842], [-104.022199, 47.468521], [-104.023595, 47.659211], [-104.024962, 47.8499], [-104.02633, 48.040579], [-104.027725, 48.231269], [-104.029121, 48.421958], [-104.030516, 48.612637], [-104.031911, 48.803327], [-104.033927, 48.993138], [-103.925564, 48.993138], [-103.499179, 48.993138], [-103.072799, 48.993138], [-102.646414, 48.993138], [-102.220035, 48.993138], [-101.79365, 48.993138], [-101.367271, 48.993138]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3532", "diss_me": 3532, "iso_3166_2": "US-NE", "wikipedia": "http://en.wikipedia.org/wiki/Nebraska", "iso_a2": "US", "adm0_sr": 1, "name": "Nebraska", "name_alt": "NE|Nebr.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US31", "code_hasc": "US.NE", "note": null, "hasc_maybe": null, "region": "Midwest", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Nebr.", "postal": "NE", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 8, "mapcolor9": 1, "mapcolor13": 1, "fips": "US31", "fips_alt": null, "woe_id": 2347586, "woe_label": "Nebraska, US, United States", "woe_name": "Nebraska", "latitude": 41.5002, "longitude": -99.6855, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5073708, "gn_name": "Nebraska", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.NE", "region_sub": "West North Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1553", "name_ar": "\u0646\u0628\u0631\u0627\u0633\u0643\u0627", "name_bn": "\u09a8\u09c7\u09ac\u09cd\u09b0\u09be\u09b8\u09cd\u0995\u09be", "name_de": "Nebraska", "name_en": "Nebraska", "name_es": "Nebraska", "name_fr": "Nebraska", "name_el": "\u039d\u03b5\u03bc\u03c0\u03c1\u03ac\u03c3\u03ba\u03b1", "name_hi": "\u0928\u0947\u092c\u094d\u0930\u093e\u0938\u094d\u0915\u093e", "name_hu": "Nebraska", "name_id": "Nebraska", "name_it": "Nebraska", "name_ja": "\u30cd\u30d6\u30e9\u30b9\u30ab\u5dde", "name_ko": "\ub124\ube0c\ub798\uc2a4\uce74", "name_nl": "Nebraska", "name_pl": "Nebraska", "name_pt": "Nebraska", "name_ru": "\u041d\u0435\u0431\u0440\u0430\u0441\u043a\u0430", "name_sv": "Nebraska", "name_tr": "Nebraska", "name_vi": "Nebraska", "name_zh": "\u5167\u5e03\u62c9\u65af\u52a0\u5dde", "ne_id": 1159315363, "name_he": "\u05e0\u05d1\u05e8\u05e1\u05e7\u05d4", "name_uk": "\u041d\u0435\u0431\u0440\u0430\u0441\u043a\u0430", "name_ur": "\u0646\u06cc\u0628\u0631\u0627\u0633\u06a9\u0627", "name_fa": "\u0646\u0628\u0631\u0627\u0633\u06a9\u0627", "name_zht": "\u5167\u5e03\u62c9\u65af\u52a0\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-104.028862, 40.001124, -95.34668, 43.001403], "geometry": {"type": "Polygon", "coordinates": [[[-102.024489, 40.001124], [-102.024544, 40.126083], [-102.024621, 40.251008], [-102.024698, 40.375934], [-102.024747, 40.500892], [-102.024802, 40.625818], [-102.024879, 40.750744], [-102.024956, 40.875691], [-102.025006, 41.000628], [-102.274604, 41.00065], [-102.524175, 41.000704], [-102.773746, 41.000726], [-103.023344, 41.000748], [-103.272915, 41.000781], [-103.522486, 41.000803], [-103.772084, 41.000836], [-104.021655, 41.000858], [-104.022562, 41.250918], [-104.023441, 41.500978], [-104.024342, 41.751049], [-104.025248, 42.001131], [-104.026149, 42.251223], [-104.027055, 42.501283], [-104.027962, 42.751343], [-104.028862, 43.001403], [-103.682738, 43.001403], [-103.33663, 43.001381], [-102.990528, 43.001359], [-102.644398, 43.001359], [-102.298274, 43.001359], [-101.952172, 43.001326], [-101.606064, 43.001304], [-101.25994, 43.001304], [-100.91381, 43.001304], [-100.567708, 43.001282], [-100.221605, 43.001249], [-99.875475, 43.001249], [-99.529373, 43.001249], [-99.183271, 43.001249], [-98.837141, 43.001249], [-98.441765, 43.001095], [-98.143283, 42.852263], [-97.964947, 42.805868], [-97.880918, 42.849583], [-97.698139, 42.874643], [-97.416658, 42.881004], [-97.23879, 42.860536], [-97.164478, 42.813196], [-97.019733, 42.760176], [-96.804527, 42.701421], [-96.675542, 42.637601], [-96.632778, 42.568673], [-96.55795, 42.524794], [-96.480953, 42.511259], [-96.451004, 42.505985], [-96.383751, 42.417776], [-96.356104, 42.260133], [-96.295333, 42.132912], [-96.201384, 42.036122], [-96.154203, 41.965293], [-96.153763, 41.920436], [-96.13123, 41.872437], [-96.086637, 41.821372], [-96.068806, 41.734328], [-96.077771, 41.611281], [-96.058627, 41.54578], [-96.011397, 41.537881], [-95.990957, 41.52049], [-95.997367, 41.493639], [-95.98158, 41.473798], [-95.943567, 41.460933], [-95.932977, 41.425458], [-95.94972, 41.367428], [-95.936025, 41.330986], [-95.891943, 41.316166], [-95.883626, 41.287557], [-95.911169, 41.245183], [-95.906906, 41.21195], [-95.870887, 41.187824], [-95.846597, 41.080333], [-95.834017, 40.88949], [-95.838148, 40.777748], [-95.859, 40.745108], [-95.826107, 40.676179], [-95.765029, 40.601868], [-95.739551, 40.570853], [-95.684696, 40.466362], [-95.66157, 40.362761], [-95.607106, 40.29547], [-95.52122, 40.264577], [-95.463652, 40.198065], [-95.434296, 40.09598], [-95.362467, 40.01032], [-95.34668, 40.001487], [-95.526905, 40.001124], [-95.736503, 40.001124], [-95.9461, 40.001124], [-96.155702, 40.001124], [-96.3653, 40.001124], [-96.574902, 40.001124], [-96.784499, 40.001124], [-96.994102, 40.001124], [-97.203699, 40.001124], [-97.413296, 40.001124], [-97.622899, 40.001124], [-97.832496, 40.001124], [-98.042099, 40.001124], [-98.251696, 40.001124], [-98.461299, 40.001124], [-98.670896, 40.001124], [-98.880499, 40.001124], [-99.090096, 40.001124], [-99.299693, 40.001124], [-99.509296, 40.001124], [-99.718893, 40.001124], [-99.928495, 40.001124], [-100.138093, 40.001124], [-100.347695, 40.001124], [-100.557293, 40.001124], [-100.766895, 40.001124], [-100.976492, 40.001124], [-101.18609, 40.001124], [-101.395692, 40.001124], [-101.605289, 40.001124], [-101.814892, 40.001124], [-102.024489, 40.001124]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3538", "diss_me": 3538, "iso_3166_2": "US-NH", "wikipedia": "http://en.wikipedia.org/wiki/New_Hampshire", "iso_a2": "US", "adm0_sr": 1, "name": "New Hampshire", "name_alt": "NH|N.H.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US33", "code_hasc": "US.NH", "note": null, "hasc_maybe": null, "region": "Northeast", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "N.H.", "postal": "NH", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 13, "mapcolor9": 1, "mapcolor13": 1, "fips": "US33", "fips_alt": null, "woe_id": 2347588, "woe_label": "New Hampshire, US, United States", "woe_name": "New Hampshire", "latitude": 43.5993, "longitude": -71.6301, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5090174, "gn_name": "New Hampshire", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.NH", "region_sub": "New England", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q759", "name_ar": "\u0646\u064a\u0648\u0647\u0627\u0645\u0628\u0634\u064a\u0631", "name_bn": "\u09a8\u09bf\u0989 \u09b9\u09cd\u09af\u09be\u09ae\u09cd\u09aa\u09cd\u09b6\u09be\u09af\u09bc\u09be\u09b0", "name_de": "New Hampshire", "name_en": "New Hampshire", "name_es": "Nuevo Hampshire", "name_fr": "New Hampshire", "name_el": "\u039d\u03b9\u03bf\u03c5 \u03a7\u03ac\u03bc\u03c3\u03b1\u03ca\u03c1", "name_hi": "\u0928\u092f\u093e \u0939\u0947\u092e\u094d\u092a\u0936\u093e\u092f\u0930", "name_hu": "New Hampshire", "name_id": "New Hampshire", "name_it": "New Hampshire", "name_ja": "\u30cb\u30e5\u30fc\u30cf\u30f3\u30d7\u30b7\u30e3\u30fc\u5dde", "name_ko": "\ub274\ud584\ud504\uc154", "name_nl": "New Hampshire", "name_pl": "New Hampshire", "name_pt": "Nova Hampshire", "name_ru": "\u041d\u044c\u044e-\u0413\u044d\u043c\u043f\u0448\u0438\u0440", "name_sv": "New Hampshire", "name_tr": "New Hampshire", "name_vi": "New Hampshire", "name_zh": "\u65b0\u7f55\u5e03\u4ec0\u5c14\u5dde", "ne_id": 1159315303, "name_he": "\u05e0\u05d9\u05d5 \u05d4\u05de\u05e4\u05e9\u05d9\u05d9\u05e8", "name_uk": "\u041d\u044c\u044e-\u0413\u0435\u043c\u043f\u0448\u0438\u0440", "name_ur": "\u0646\u06cc\u0648 \u06c1\u06cc\u0645\u067e\u0634\u0627\u0626\u0631", "name_fa": "\u0646\u06cc\u0648\u0647\u0645\u067e\u0634\u0627\u06cc\u0631", "name_zht": "\u65b0\u7f55\u5e03\u590f\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-72.552806, 42.702487, -70.733096, 45.294008], "geometry": {"type": "Polygon", "coordinates": [[[-71.51752, 45.007561], [-71.419017, 45.200338], [-71.327292, 45.290108], [-71.201619, 45.260335], [-71.134647, 45.262818], [-71.084549, 45.294008], [-71.077331, 45.194867], [-71.069685, 45.084015], [-71.062038, 44.973174], [-71.05437, 44.862322], [-71.04669, 44.751481], [-71.039044, 44.64064], [-71.031397, 44.529788], [-71.023718, 44.418947], [-71.016049, 44.308095], [-71.008403, 44.197254], [-71.000756, 44.086402], [-70.993077, 43.975561], [-70.985408, 43.864708], [-70.977751, 43.753867], [-70.970104, 43.643026], [-70.962436, 43.532152], [-70.967545, 43.458148], [-70.955635, 43.389396], [-70.919699, 43.328103], [-70.829029, 43.23907], [-70.812835, 43.163649], [-70.733096, 43.070034], [-70.777635, 42.940582], [-70.806112, 42.876763], [-70.923489, 42.881564], [-70.974082, 42.871676], [-71.076177, 42.825083], [-71.139294, 42.808131], [-71.242335, 42.729535], [-71.329621, 42.702487], [-71.471784, 42.705969], [-71.613947, 42.70943], [-71.75611, 42.712924], [-71.898241, 42.716406], [-72.040382, 42.719878], [-72.182545, 42.723361], [-72.324697, 42.726854], [-72.46686, 42.730315], [-72.483658, 42.766174], [-72.539622, 42.829632], [-72.552806, 42.856449], [-72.549807, 42.886684], [-72.519419, 42.966675], [-72.496479, 42.991669], [-72.473715, 43.038537], [-72.438186, 43.224645], [-72.407072, 43.332036], [-72.384957, 43.52923], [-72.362369, 43.586645], [-72.337672, 43.621988], [-72.296693, 43.714954], [-72.222381, 43.790869], [-72.173855, 43.884088], [-72.114924, 43.965431], [-72.106212, 44.013079], [-72.062233, 44.11635], [-72.031208, 44.300734], [-72.001776, 44.329496], [-71.867677, 44.354918], [-71.825511, 44.37409], [-71.683007, 44.45028], [-71.638205, 44.481679], [-71.609289, 44.514055], [-71.5878, 44.565263], [-71.571496, 44.579193], [-71.568442, 44.607637], [-71.618287, 44.727761], [-71.62066, 44.771894], [-71.510225, 44.908344], [-71.533483, 44.987973], [-71.51752, 45.007561]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3558", "diss_me": 3558, "iso_3166_2": "US-NJ", "wikipedia": "http://en.wikipedia.org/wiki/New_Jersey", "iso_a2": "US", "adm0_sr": 5, "name": "New Jersey", "name_alt": "NJ|N.J.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US34", "code_hasc": "US.NJ", "note": null, "hasc_maybe": null, "region": "Northeast", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "N.J.", "postal": "NJ", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 10, "mapcolor9": 1, "mapcolor13": 1, "fips": "US34", "fips_alt": null, "woe_id": 2347589, "woe_label": "New Jersey, US, United States", "woe_name": "New Jersey", "latitude": 40.0449, "longitude": -74.4653, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5101760, "gn_name": "New Jersey", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.NJ", "region_sub": "Middle Atlantic", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1408", "name_ar": "\u0646\u064a\u0648\u062c\u064a\u0631\u0633\u064a", "name_bn": "\u09a8\u09bf\u0989 \u099c\u09be\u09b0\u09cd\u09b8\u09bf", "name_de": "New Jersey", "name_en": "New Jersey", "name_es": "Nueva Jersey", "name_fr": "New Jersey", "name_el": "\u039d\u03b9\u03bf\u03c5 \u03a4\u03b6\u03ad\u03c1\u03c3\u03b5\u03ca", "name_hi": "\u0928\u094d\u092f\u0942 \u091c\u0930\u094d\u0938\u0940", "name_hu": "New Jersey", "name_id": "New Jersey", "name_it": "New Jersey", "name_ja": "\u30cb\u30e5\u30fc\u30b8\u30e3\u30fc\u30b8\u30fc\u5dde", "name_ko": "\ub274\uc800\uc9c0", "name_nl": "New Jersey", "name_pl": "New Jersey", "name_pt": "Nova J\u00e9rsia", "name_ru": "\u041d\u044c\u044e-\u0414\u0436\u0435\u0440\u0441\u0438", "name_sv": "New Jersey", "name_tr": "New Jersey", "name_vi": "New Jersey", "name_zh": "\u65b0\u6cfd\u897f\u5dde", "ne_id": 1159315267, "name_he": "\u05e0\u05d9\u05d5 \u05d2'\u05e8\u05d6\u05d9", "name_uk": "\u041d\u044c\u044e-\u0414\u0436\u0435\u0440\u0441\u0456", "name_ur": "\u0646\u06cc\u0648 \u062c\u0631\u0633\u06cc", "name_fa": "\u0646\u06cc\u0648\u062c\u0631\u0633\u06cc", "name_zht": "\u7d10\u6fa4\u897f\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-75.524245, 38.941141, -73.910079, 41.357299], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-75.074168, 39.98348], [-75.023532, 40.01745], [-74.909297, 40.079545], [-74.734889, 40.154504], [-74.976379, 40.405828], [-75.034046, 40.420374], [-75.097448, 40.543135], [-75.170518, 40.576797], [-75.189019, 40.595814], [-75.192282, 40.689868], [-75.185691, 40.743822], [-75.174737, 40.775518], [-75.111797, 40.802105], [-75.075564, 40.856267], [-75.074926, 40.884458], [-75.12275, 40.971766], [-75.123036, 40.999002], [-75.031541, 41.05178], [-74.912296, 41.155271], [-74.84139, 41.268595], [-74.812485, 41.30151], [-74.777779, 41.325076], [-74.699051, 41.357299], [-74.600064, 41.311585], [-74.501056, 41.265903], [-74.402047, 41.220222], [-74.30306, 41.174541], [-74.204073, 41.12886], [-74.105053, 41.083179], [-74.006045, 41.037498], [-73.910079, 40.992256], [-73.927218, 40.914242], [-74.025501, 40.756379], [-74.067337, 40.71963], [-74.116248, 40.687286], [-74.15314, 40.673257], [-74.187143, 40.647988], [-74.226705, 40.608009], [-74.26419, 40.528633], [-74.241515, 40.456266], [-74.049836, 40.429833], [-73.998453, 40.452157], [-73.972251, 40.400324], [-73.957595, 40.328363], [-73.971987, 40.250514], [-74.004001, 40.171347], [-74.028347, 40.073008], [-74.048913, 39.923066], [-74.079917, 39.78811], [-74.084004, 39.829089], [-74.064591, 39.993115], [-74.09599, 39.975988], [-74.117644, 39.938129], [-74.176135, 39.726598], [-74.256577, 39.613856], [-74.330603, 39.535886], [-74.407024, 39.548806], [-74.389874, 39.486843], [-74.410858, 39.454544], [-74.428831, 39.387186], [-74.474359, 39.34256], [-74.517172, 39.346845], [-74.578696, 39.316105], [-74.602987, 39.292561], [-74.604799, 39.247528], [-74.645932, 39.207867], [-74.794478, 39.001907], [-74.923436, 38.941141], [-74.954308, 38.949952], [-74.920327, 39.047181], [-74.897025, 39.145465], [-74.975291, 39.188257], [-75.050218, 39.210834], [-75.136109, 39.207867], [-75.231031, 39.284266], [-75.35343, 39.339824], [-75.524245, 39.490172], [-75.519257, 39.531876], [-75.523553, 39.601848], [-75.47161, 39.712382], [-75.421908, 39.789714], [-75.353177, 39.829738], [-75.15383, 39.870486], [-75.103831, 39.931823], [-75.074168, 39.98348]]], [[[-74.133222, 39.680785], [-74.250501, 39.529371], [-74.25316, 39.558485], [-74.106767, 39.746439], [-74.133222, 39.680785]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3524", "diss_me": 3524, "iso_3166_2": "US-NM", "wikipedia": "http://en.wikipedia.org/wiki/New_Mexico", "iso_a2": "US", "adm0_sr": 1, "name": "New Mexico", "name_alt": "NM|N.M.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US35", "code_hasc": "US.NM", "note": null, "hasc_maybe": null, "region": "West", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "N.M.", "postal": "NM", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 10, "mapcolor9": 1, "mapcolor13": 1, "fips": "US35", "fips_alt": null, "woe_id": 2347590, "woe_label": "New Mexico, US, United States", "woe_name": "New Mexico", "latitude": 34.5002, "longitude": -106.024, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5481136, "gn_name": "New Mexico", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.NM", "region_sub": "Mountain", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1522", "name_ar": "\u0646\u064a\u0648\u0645\u0643\u0633\u064a\u0643\u0648", "name_bn": "\u09a8\u09bf\u0989 \u09ae\u09c7\u0995\u09cd\u09b8\u09bf\u0995\u09cb", "name_de": "New Mexico", "name_en": "New Mexico", "name_es": "Nuevo M\u00e9xico", "name_fr": "Nouveau-Mexique", "name_el": "\u039d\u03ad\u03bf \u039c\u03b5\u03be\u03b9\u03ba\u03cc", "name_hi": "\u0928\u092f\u093e \u092e\u0947\u0915\u094d\u0938\u093f\u0915\u094b", "name_hu": "\u00daj-Mexik\u00f3", "name_id": "New Mexico", "name_it": "Nuovo Messico", "name_ja": "\u30cb\u30e5\u30fc\u30e1\u30ad\u30b7\u30b3\u5dde", "name_ko": "\ub274\uba55\uc2dc\ucf54", "name_nl": "New Mexico", "name_pl": "Nowy Meksyk", "name_pt": "Novo M\u00e9xico", "name_ru": "\u041d\u044c\u044e-\u041c\u0435\u043a\u0441\u0438\u043a\u043e", "name_sv": "New Mexico", "name_tr": "New Mexico", "name_vi": "New Mexico", "name_zh": "\u65b0\u58a8\u897f\u54e5\u5dde", "ne_id": 1159315347, "name_he": "\u05e0\u05d9\u05d5 \u05de\u05e7\u05e1\u05d9\u05e7\u05d5", "name_uk": "\u041d\u044c\u044e-\u041c\u0435\u043a\u0441\u0438\u043a\u043e", "name_ur": "\u0646\u06cc\u0648 \u0645\u06cc\u06a9\u0633\u06cc\u06a9\u0648", "name_fa": "\u0646\u06cc\u0648\u0645\u06a9\u0632\u06cc\u06a9\u0648", "name_zht": "\u65b0\u58a8\u897f\u54e5\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-109.047807, 31.327879, -103.000295, 37.000846], "geometry": {"type": "Polygon", "coordinates": [[[-109.047807, 31.327879], [-109.047423, 31.683232], [-109.047368, 32.037739], [-109.047318, 32.392235], [-109.047264, 32.746764], [-109.047214, 33.101293], [-109.047165, 33.455788], [-109.04711, 33.810284], [-109.04706, 34.164791], [-109.047005, 34.519287], [-109.046956, 34.873794], [-109.046906, 35.22829], [-109.046852, 35.582819], [-109.046802, 35.937336], [-109.046747, 36.291843], [-109.046698, 36.646339], [-109.04667, 37.000846], [-108.66879, 37.000846], [-108.290932, 37.000846], [-107.913073, 37.000846], [-107.535215, 37.000846], [-107.157357, 37.000846], [-106.779499, 37.000846], [-106.40164, 37.000846], [-106.023755, 37.000846], [-105.645874, 37.000846], [-105.268016, 37.000846], [-104.890158, 37.000846], [-104.512299, 37.000846], [-104.134441, 37.000846], [-103.756583, 37.000846], [-103.378724, 37.000846], [-103.000839, 37.000846], [-103.000712, 36.875942], [-103.000553, 36.751039], [-103.000427, 36.626135], [-103.000295, 36.501232], [-103.042153, 36.500616], [-103.043625, 36.219498], [-103.045103, 35.93838], [-103.046547, 35.657251], [-103.04802, 35.376133], [-103.049492, 35.095015], [-103.050942, 34.813896], [-103.052414, 34.532778], [-103.053886, 34.251682], [-103.055358, 33.970586], [-103.056831, 33.689468], [-103.058303, 33.408349], [-103.059775, 33.127231], [-103.061247, 32.846113], [-103.062719, 32.564984], [-103.064169, 32.283866], [-103.065642, 32.002748], [-103.290405, 32.002649], [-103.515202, 32.002572], [-103.739993, 32.002495], [-103.964785, 32.002385], [-104.189576, 32.002286], [-104.414373, 32.002209], [-104.639164, 32.002132], [-104.863928, 32.002022], [-105.088697, 32.001924], [-105.313488, 32.001847], [-105.53828, 32.00177], [-105.763076, 32.00166], [-105.987868, 32.001561], [-106.212659, 32.001484], [-106.43745, 32.001407], [-106.662219, 32.001297], [-106.668262, 32.000946], [-106.566281, 31.819529], [-106.566358, 31.819529], [-106.445382, 31.768398], [-106.45321, 31.770178], [-106.673047, 31.771343], [-106.892877, 31.772474], [-107.112708, 31.773617], [-107.332539, 31.774748], [-107.55237, 31.775891], [-107.772201, 31.777022], [-107.992032, 31.778165], [-108.211841, 31.77933], [-108.212484, 31.666852], [-108.213154, 31.554385], [-108.213802, 31.441906], [-108.21445, 31.329428], [-108.567892, 31.32878], [-108.921333, 31.32811], [-109.047807, 31.327879]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3523", "diss_me": 3523, "iso_3166_2": "US-NV", "wikipedia": "http://en.wikipedia.org/wiki/Nevada", "iso_a2": "US", "adm0_sr": 1, "name": "Nevada", "name_alt": "NV|Nev.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US32", "code_hasc": "US.NV", "note": null, "hasc_maybe": null, "region": "West", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Nev.", "postal": "NV", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 6, "mapcolor9": 1, "mapcolor13": 1, "fips": "US32", "fips_alt": null, "woe_id": 2347587, "woe_label": "Nevada, US, United States", "woe_name": "Nevada", "latitude": 39.4299, "longitude": -117.02, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5509151, "gn_name": "Nevada", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.NV", "region_sub": "Mountain", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1227", "name_ar": "\u0646\u064a\u0641\u0627\u062f\u0627", "name_bn": "\u09a8\u09c7\u09ad\u09be\u09a1\u09be", "name_de": "Nevada", "name_en": "Nevada", "name_es": "Nevada", "name_fr": "Nevada", "name_el": "\u039d\u03b5\u03b2\u03ac\u03b4\u03b1", "name_hi": "\u0928\u0947\u0935\u093e\u0921\u093e", "name_hu": "Nevada", "name_id": "Nevada", "name_it": "Nevada", "name_ja": "\u30cd\u30d0\u30c0\u5dde", "name_ko": "\ub124\ubc14\ub2e4", "name_nl": "Nevada", "name_pl": "Nevada", "name_pt": "Nevada", "name_ru": "\u041d\u0435\u0432\u0430\u0434\u0430", "name_sv": "Nevada", "name_tr": "Nevada", "name_vi": "Nevada", "name_zh": "\u5185\u534e\u8fbe\u5dde", "ne_id": 1159315345, "name_he": "\u05e0\u05d1\u05d3\u05d4", "name_uk": "\u041d\u0435\u0432\u0430\u0434\u0430", "name_ur": "\u0646\u06cc\u0648\u0627\u0688\u0627", "name_fa": "\u0646\u0648\u0627\u062f\u0627", "name_zht": "\u5167\u83ef\u9054\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-120.000809, 34.991117, -114.04027, 42.001109], "geometry": {"type": "Polygon", "coordinates": [[[-114.04027, 37.004153], [-114.041171, 36.61249], [-114.042879, 36.181771], [-114.061924, 36.175212], [-114.119437, 36.076665], [-114.183207, 36.030303], [-114.232146, 36.031698], [-114.281573, 36.060328], [-114.331545, 36.116293], [-114.406087, 36.148307], [-114.505277, 36.156426], [-114.592975, 36.14756], [-114.669144, 36.12172], [-114.715759, 36.084982], [-114.741362, 36.013516], [-114.732321, 35.983666], [-114.687101, 35.917341], [-114.68369, 35.813597], [-114.677076, 35.729805], [-114.650126, 35.683508], [-114.645166, 35.630543], [-114.662063, 35.545355], [-114.648528, 35.475922], [-114.590987, 35.352776], [-114.610521, 34.99761], [-114.610543, 34.991117], [-114.88218, 35.202812], [-115.136096, 35.400962], [-115.390006, 35.599122], [-115.643917, 35.797294], [-115.897827, 35.995476], [-116.151743, 36.193625], [-116.405681, 36.391786], [-116.659592, 36.589968], [-116.842915, 36.727759], [-117.02626, 36.865549], [-117.209611, 37.003373], [-117.392935, 37.141174], [-117.576253, 37.278965], [-117.759603, 37.416788], [-117.942949, 37.554579], [-118.126272, 37.69238], [-118.360495, 37.855857], [-118.594718, 38.019333], [-118.828941, 38.182843], [-119.063164, 38.34632], [-119.297387, 38.509796], [-119.531616, 38.673295], [-119.765839, 38.836782], [-120.000062, 39.000259], [-120.000084, 39.187784], [-120.000139, 39.375299], [-120.000188, 39.562803], [-120.000243, 39.750339], [-120.000293, 39.937876], [-120.000342, 40.12538], [-120.000397, 40.312883], [-120.000446, 40.50042], [-120.000501, 40.687957], [-120.000551, 40.87546], [-120.0006, 41.062975], [-120.000628, 41.250501], [-120.000655, 41.438015], [-120.000704, 41.625519], [-120.000759, 41.813056], [-120.000809, 42.000559], [-119.627807, 42.000559], [-119.254782, 42.000559], [-118.881758, 42.000559], [-118.508756, 42.000559], [-118.135731, 42.000559], [-117.762701, 42.000559], [-117.389705, 42.000559], [-117.016675, 42.000559], [-116.644914, 42.000636], [-116.273153, 42.000691], [-115.901398, 42.000768], [-115.529637, 42.000845], [-115.157876, 42.0009], [-114.786115, 42.000977], [-114.414354, 42.001054], [-114.042593, 42.001109], [-114.042516, 41.844938], [-114.042467, 41.6888], [-114.04239, 41.532662], [-114.042308, 41.376492], [-114.042231, 41.220321], [-114.042154, 41.064183], [-114.042077, 40.908046], [-114.042, 40.751875], [-114.041923, 40.595715], [-114.041846, 40.439578], [-114.041791, 40.283429], [-114.041714, 40.127269], [-114.041637, 39.971099], [-114.041588, 39.814939], [-114.041511, 39.658768], [-114.041429, 39.502631], [-114.041352, 39.346493], [-114.041275, 39.190322], [-114.041226, 39.034152], [-114.041149, 38.877992], [-114.041072, 38.721821], [-114.041017, 38.565684], [-114.04094, 38.409546], [-114.040863, 38.253375], [-114.040786, 38.097205], [-114.040709, 37.941067], [-114.040632, 37.784929], [-114.040555, 37.628759], [-114.040473, 37.472599], [-114.040396, 37.316461], [-114.040347, 37.160312], [-114.04027, 37.004153]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3559", "diss_me": 3559, "iso_3166_2": "US-NY", "wikipedia": "http://en.wikipedia.org/wiki/New_York", "iso_a2": "US", "adm0_sr": 3, "name": "New York", "name_alt": "NY|N.Y.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US36", "code_hasc": "US.NY", "note": null, "hasc_maybe": null, "region": "Northeast", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "N.Y.", "postal": "NY", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 8, "mapcolor9": 1, "mapcolor13": 1, "fips": "US36", "fips_alt": null, "woe_id": 2347591, "woe_label": "New York, US, United States", "woe_name": "New York", "latitude": 43.1988, "longitude": -75.3242, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5128638, "gn_name": "New York", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.NY", "region_sub": "Middle Atlantic", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1384", "name_ar": "\u0646\u064a\u0648\u064a\u0648\u0631\u0643", "name_bn": "\u09a8\u09bf\u0989 \u0987\u09af\u09bc\u09b0\u09cd\u0995", "name_de": "New York", "name_en": "New York", "name_es": "Nueva York", "name_fr": "\u00c9tat de New York", "name_el": "\u039d\u03ad\u03b1 \u03a5\u03cc\u03c1\u03ba\u03b7", "name_hi": "\u0928\u094d\u092f\u0942\u092f\u0949\u0930\u094d\u0915", "name_hu": "New York", "name_id": "New York", "name_it": "New York", "name_ja": "\u30cb\u30e5\u30fc\u30e8\u30fc\u30af\u5dde", "name_ko": "\ub274\uc695", "name_nl": "New York", "name_pl": "Nowy Jork", "name_pt": "Nova Iorque", "name_ru": "\u041d\u044c\u044e-\u0419\u043e\u0440\u043a", "name_sv": "New York", "name_tr": "New York", "name_vi": "New York", "name_zh": "\u7ebd\u7ea6\u5dde", "ne_id": 1159312155, "name_he": "\u05e0\u05d9\u05d5 \u05d9\u05d5\u05e8\u05e7", "name_uk": "\u0448\u0442\u0430\u0442 \u041d\u044c\u044e-\u0419\u043e\u0440\u043a", "name_ur": "\u0646\u06cc\u0648\u06cc\u0627\u0631\u06a9", "name_fa": "\u0646\u06cc\u0648\u06cc\u0648\u0631\u06a9", "name_zht": "\u7d10\u7d04\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-79.763035, 40.518712, -71.903206, 45.005419], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-79.762024, 42.538977], [-79.446233, 42.651455], [-79.173739, 42.74853], [-79.036695, 42.80232], [-78.939236, 42.863744], [-78.915077, 42.90914], [-78.920867, 42.93521], [-78.946003, 42.961303], [-78.980753, 42.980606], [-79.011679, 42.997041], [-79.026181, 43.017322], [-79.029071, 43.061762], [-79.048011, 43.087294], [-79.066051, 43.106102], [-79.059228, 43.278061], [-79.083047, 43.33141], [-79.171849, 43.466575], [-79.002484, 43.527165], [-78.845566, 43.583338], [-78.720432, 43.624932], [-78.458254, 43.631502], [-78.214786, 43.630667], [-77.879242, 43.629557], [-77.59652, 43.628601], [-77.266721, 43.627492], [-77.073351, 43.626843], [-76.819962, 43.628788], [-76.696498, 43.784794], [-76.586118, 43.924298], [-76.464609, 44.057595], [-76.248541, 44.214129], [-76.185787, 44.242232], [-76.151158, 44.303942], [-76.020234, 44.36262], [-75.875929, 44.41698], [-75.819316, 44.468012], [-75.79196, 44.497049], [-75.401253, 44.772278], [-75.179384, 44.899379], [-74.996143, 44.97012], [-74.856639, 45.003925], [-74.762464, 44.999058], [-74.708873, 45.00387], [-74.663236, 45.003925], [-74.430391, 45.004178], [-74.014262, 45.004694], [-73.598133, 45.005155], [-73.352182, 45.005419], [-73.345052, 44.938864], [-73.365805, 44.860366], [-73.348568, 44.775299], [-73.372078, 44.597332], [-73.309753, 44.45964], [-73.324639, 44.36786], [-73.320915, 44.268874], [-73.331825, 44.244583], [-73.38112, 44.187432], [-73.409751, 44.131413], [-73.426131, 44.074855], [-73.424945, 44.038292], [-73.38301, 43.875827], [-73.374968, 43.804152], [-73.375847, 43.762184], [-73.413365, 43.627854], [-73.415925, 43.589644], [-73.40495, 43.578811], [-73.391436, 43.578526], [-73.349238, 43.620384], [-73.330484, 43.62669], [-73.30616, 43.616253], [-73.247098, 43.553048], [-73.250328, 43.439669], [-73.252657, 43.357195], [-73.255239, 43.265371], [-73.259084, 43.127855], [-73.26193, 43.027067], [-73.264544, 42.93521], [-73.266555, 42.864777], [-73.2802, 42.813152], [-73.253327, 42.752222], [-73.285056, 42.668198], [-73.316806, 42.584175], [-73.348568, 42.500141], [-73.380296, 42.416117], [-73.412047, 42.332094], [-73.443808, 42.24807], [-73.475537, 42.164047], [-73.507287, 42.080012], [-73.480568, 42.055568], [-73.48861, 41.960613], [-73.496619, 41.865658], [-73.504629, 41.770703], [-73.512638, 41.675748], [-73.520647, 41.580794], [-73.528689, 41.485839], [-73.53672, 41.390906], [-73.544729, 41.295951], [-73.51445, 41.257455], [-73.484139, 41.218959], [-73.521756, 41.200919], [-73.579797, 41.173146], [-73.641881, 41.143406], [-73.723015, 41.104514], [-73.682113, 41.054702], [-73.630466, 40.99186], [-73.671412, 40.965867], [-73.779001, 40.878405], [-73.851247, 40.831405], [-73.910672, 40.816112], [-73.947213, 40.776946], [-73.987082, 40.751392], [-73.948586, 40.838744], [-73.90675, 40.912462], [-73.871967, 41.055164], [-73.882251, 41.170586], [-73.925328, 41.218058], [-73.969954, 41.249732], [-73.917649, 41.135781], [-73.909233, 40.996079], [-73.910079, 40.992256], [-74.006045, 41.037498], [-74.105053, 41.083179], [-74.204073, 41.12886], [-74.30306, 41.174541], [-74.402047, 41.220222], [-74.501056, 41.265903], [-74.600064, 41.311585], [-74.699051, 41.357299], [-74.720365, 41.394861], [-74.75662, 41.423909], [-74.935367, 41.474369], [-74.981257, 41.507702], [-75.02273, 41.552866], [-75.051361, 41.608369], [-75.066192, 41.666608], [-75.066906, 41.713212], [-75.053679, 41.765045], [-75.094768, 41.799487], [-75.095537, 41.83171], [-75.121893, 41.853364], [-75.238864, 41.892201], [-75.273977, 41.94666], [-75.351342, 41.998417], [-75.48921, 41.998494], [-75.627055, 41.998571], [-75.764901, 41.998648], [-75.902779, 41.998725], [-76.040647, 41.998801], [-76.178525, 41.998878], [-76.316393, 41.998966], [-76.454238, 41.999043], [-76.592094, 41.99912], [-76.729962, 41.999197], [-76.86784, 41.999274], [-77.005708, 41.999351], [-77.143575, 41.999428], [-77.281432, 41.999505], [-77.419277, 41.999581], [-77.557145, 41.999658], [-77.695023, 41.999735], [-77.832868, 41.999812], [-77.970714, 41.999889], [-78.108581, 41.999966], [-78.24646, 42.000043], [-78.384327, 42.00012], [-78.522206, 42.000197], [-78.660051, 42.000274], [-78.797897, 42.000329], [-78.935775, 42.000438], [-79.073642, 42.000515], [-79.211521, 42.000592], [-79.349388, 42.000669], [-79.487234, 42.000746], [-79.625079, 42.000801], [-79.762958, 42.0009], [-79.76298, 42.135515], [-79.763002, 42.270131], [-79.763035, 42.404746], [-79.762024, 42.538977]]], [[[-72.509783, 40.986027], [-72.580887, 40.921328], [-72.516573, 40.914813], [-72.461334, 40.933776], [-72.409017, 40.972151], [-72.287442, 41.024083], [-72.183852, 41.046792], [-72.151245, 41.051472], [-72.101894, 41.01502], [-72.003951, 41.044265], [-71.903206, 41.060701], [-72.33899, 40.894148], [-72.428078, 40.875383], [-72.555542, 40.82578], [-72.676106, 40.790635], [-72.762843, 40.777847], [-73.194287, 40.654207], [-73.22852, 40.651526], [-73.265522, 40.663567], [-73.620897, 40.599901], [-73.766729, 40.592716], [-73.899565, 40.570524], [-73.801325, 40.621786], [-73.799183, 40.640979], [-73.822672, 40.655964], [-73.875175, 40.651625], [-73.928997, 40.598814], [-74.014911, 40.581213], [-74.032038, 40.638683], [-74.003364, 40.683156], [-73.964571, 40.725343], [-73.879262, 40.791668], [-73.757193, 40.833679], [-73.695208, 40.870033], [-73.652241, 40.838019], [-73.642837, 40.881228], [-73.609768, 40.906189], [-73.573798, 40.919625], [-73.487391, 40.919955], [-73.440864, 40.926777], [-73.407246, 40.941093], [-73.372705, 40.943806], [-73.278156, 40.924196], [-73.185838, 40.929854], [-73.111296, 40.95688], [-73.033776, 40.965977], [-72.828783, 40.972052], [-72.625118, 40.991838], [-72.543676, 41.027006], [-72.372575, 41.125553], [-72.274138, 41.153041], [-72.427386, 41.03853], [-72.509783, 40.986027]]], [[[-74.188132, 40.522854], [-74.235879, 40.518712], [-74.188154, 40.614601], [-74.100483, 40.658447], [-74.068755, 40.649307], [-74.067414, 40.615458], [-74.079708, 40.586465], [-74.138518, 40.541838], [-74.188132, 40.522854]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3550", "diss_me": 3550, "iso_3166_2": "US-OH", "wikipedia": "http://en.wikipedia.org/wiki/Ohio", "iso_a2": "US", "adm0_sr": 1, "name": "Ohio", "name_alt": "OH|Ohio", "name_local": null, "type": "State", "type_en": "State", "code_local": "US39", "code_hasc": "US.OH", "note": null, "hasc_maybe": null, "region": "Midwest", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Ohio", "postal": "OH", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 4, "mapcolor9": 1, "mapcolor13": 1, "fips": "US39", "fips_alt": null, "woe_id": 2347594, "woe_label": "Ohio, US, United States", "woe_name": "Ohio", "latitude": 40.0924, "longitude": -82.6719, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5165418, "gn_name": "Ohio", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.OH", "region_sub": "East North Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1397", "name_ar": "\u0623\u0648\u0647\u0627\u064a\u0648", "name_bn": "\u0993\u09b9\u09be\u0987\u0993", "name_de": "Ohio", "name_en": "Ohio", "name_es": "Ohio", "name_fr": "Ohio", "name_el": "\u039f\u03c7\u03ac\u03b9\u03bf", "name_hi": "\u0913\u0939\u093e\u092f\u094b", "name_hu": "Ohio", "name_id": "Ohio", "name_it": "Ohio", "name_ja": "\u30aa\u30cf\u30a4\u30aa\u5dde", "name_ko": "\uc624\ud558\uc774\uc624", "name_nl": "Ohio", "name_pl": "Ohio", "name_pt": "Ohio", "name_ru": "\u041e\u0433\u0430\u0439\u043e", "name_sv": "Ohio", "name_tr": "Ohio", "name_vi": "Ohio", "name_zh": "\u4fc4\u4ea5\u4fc4\u5dde", "ne_id": 1159315315, "name_he": "\u05d0\u05d5\u05d4\u05d9\u05d5", "name_uk": "\u041e\u0433\u0430\u0439\u043e", "name_ur": "\u0627\u0648\u06c1\u0627\u0626\u06cc\u0648", "name_fa": "\u0627\u0648\u0647\u0627\u06cc\u0648", "name_zht": "\u4fc4\u4ea5\u4fc4\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-84.821711, 38.414973, -80.519081, 42.324392], "geometry": {"type": "Polygon", "coordinates": [[[-83.121665, 41.95], [-83.029962, 41.832974], [-82.8662, 41.753004], [-82.690012, 41.675177], [-82.439073, 41.67487], [-82.213326, 41.77869], [-81.974187, 41.88874], [-81.76092, 41.986815], [-81.507345, 42.103479], [-81.277643, 42.209179], [-81.028198, 42.247158], [-80.682645, 42.299772], [-80.520762, 42.324392], [-80.520278, 42.220473], [-80.520278, 42.115619], [-80.520278, 42.010766], [-80.520278, 41.905923], [-80.520278, 41.801069], [-80.520278, 41.696238], [-80.520278, 41.591417], [-80.520278, 41.486564], [-80.520278, 41.38171], [-80.520278, 41.276857], [-80.520278, 41.172014], [-80.520278, 41.067183], [-80.520278, 40.962362], [-80.520278, 40.857509], [-80.520278, 40.752655], [-80.519081, 40.646956], [-80.637524, 40.603263], [-80.659047, 40.562976], [-80.623187, 40.51156], [-80.604093, 40.445203], [-80.601819, 40.363893], [-80.668275, 40.185244], [-80.803517, 39.909136], [-80.872192, 39.735508], [-80.874313, 39.664294], [-80.963291, 39.57113], [-81.139127, 39.455994], [-81.262504, 39.386538], [-81.333354, 39.362819], [-81.392417, 39.364829], [-81.439647, 39.392559], [-81.492722, 39.373618], [-81.551631, 39.308041], [-81.606464, 39.274137], [-81.657209, 39.271973], [-81.700594, 39.229467], [-81.736663, 39.14663], [-81.770665, 39.098828], [-81.802602, 39.086062], [-81.804954, 39.04405], [-81.777685, 38.972793], [-81.780124, 38.946975], [-81.795033, 38.945942], [-81.809337, 38.950029], [-81.843757, 38.934319], [-81.88244, 38.894219], [-81.896678, 38.893549], [-81.907368, 38.900239], [-81.91853, 38.952347], [-81.949797, 38.989327], [-82.001092, 39.011102], [-82.072273, 38.962949], [-82.163328, 38.844912], [-82.203527, 38.768228], [-82.18764, 38.715208], [-82.180071, 38.637589], [-82.202494, 38.605839], [-82.252317, 38.594083], [-82.290868, 38.552017], [-82.318147, 38.479672], [-82.387064, 38.43399], [-82.497543, 38.414973], [-82.612778, 38.448218], [-82.621282, 38.450679], [-82.758226, 38.541162], [-82.844623, 38.627668], [-82.880438, 38.710253], [-83.000068, 38.713999], [-83.203469, 38.638907], [-83.35697, 38.627405], [-83.460582, 38.679502], [-83.538387, 38.69986], [-83.616313, 38.682776], [-83.689878, 38.649531], [-83.752269, 38.669373], [-83.828086, 38.731226], [-83.948386, 38.774226], [-84.113236, 38.798385], [-84.227285, 38.865204], [-84.290435, 38.974705], [-84.358022, 39.049917], [-84.43006, 39.090896], [-84.508865, 39.102838], [-84.594547, 39.085776], [-84.660542, 39.094467], [-84.706948, 39.128909], [-84.765901, 39.124998], [-84.821711, 39.091984], [-84.82014, 39.423826], [-84.816702, 39.749197], [-84.813263, 40.074557], [-84.809835, 40.399939], [-84.806397, 40.725321], [-84.802958, 41.05067], [-84.799552, 41.376052], [-84.796113, 41.701434], [-84.463129, 41.710938], [-84.130155, 41.720452], [-83.797181, 41.729955], [-83.464197, 41.739447], [-83.30395, 41.837808], [-83.121665, 41.95]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3533", "diss_me": 3533, "iso_3166_2": "US-OK", "wikipedia": "http://en.wikipedia.org/wiki/Oklahoma", "iso_a2": "US", "adm0_sr": 1, "name": "Oklahoma", "name_alt": "OK|Okla.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US40", "code_hasc": "US.OK", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Okla.", "postal": "OK", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 8, "mapcolor9": 1, "mapcolor13": 1, "fips": "US40", "fips_alt": null, "woe_id": 2347595, "woe_label": "Oklahoma, US, United States", "woe_name": "Oklahoma", "latitude": 35.452, "longitude": -97.1309, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4544379, "gn_name": "Oklahoma", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.OK", "region_sub": "West South Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1649", "name_ar": "\u0623\u0648\u0643\u0644\u0627\u0647\u0648\u0645\u0627", "name_bn": "\u0993\u0995\u09b2\u09be\u09b9\u09cb\u09ae\u09be", "name_de": "Oklahoma", "name_en": "Oklahoma", "name_es": "Oklahoma", "name_fr": "Oklahoma", "name_el": "\u039f\u03ba\u03bb\u03b1\u03c7\u03cc\u03bc\u03b1", "name_hi": "\u0913\u0915\u094d\u0932\u093e\u0939\u094b\u092e\u093e", "name_hu": "Oklahoma", "name_id": "Oklahoma", "name_it": "Oklahoma", "name_ja": "\u30aa\u30af\u30e9\u30db\u30de\u5dde", "name_ko": "\uc624\ud074\ub77c\ud638\ub9c8", "name_nl": "Oklahoma", "name_pl": "Oklahoma", "name_pt": "Oklahoma", "name_ru": "\u041e\u043a\u043b\u0430\u0445\u043e\u043c\u0430", "name_sv": "Oklahoma", "name_tr": "Oklahoma", "name_vi": "Oklahoma", "name_zh": "\u4fc4\u514b\u62c9\u8377\u9a6c\u5dde", "ne_id": 1159315365, "name_he": "\u05d0\u05d5\u05e7\u05dc\u05d4\u05d5\u05de\u05d4", "name_uk": "\u041e\u043a\u043b\u0430\u0445\u043e\u043c\u0430", "name_ur": "\u0627\u0648\u06a9\u0644\u0627\u06c1\u0648\u0645\u0627", "name_fa": "\u0627\u06a9\u0644\u0627\u0647\u0645\u0627", "name_zht": "\u5967\u514b\u62c9\u8377\u99ac\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-103.000839, 33.648434, -94.439138, 37.000846], "geometry": {"type": "Polygon", "coordinates": [[[-94.61838, 36.500869], [-94.595979, 36.361661], [-94.573578, 36.222465], [-94.551177, 36.083279], [-94.52877, 35.94406], [-94.506369, 35.804841], [-94.483968, 35.665655], [-94.461539, 35.526459], [-94.439138, 35.387251], [-94.441956, 35.278574], [-94.444746, 35.169897], [-94.447564, 35.061221], [-94.450377, 34.952544], [-94.453195, 34.843867], [-94.456013, 34.73519], [-94.458831, 34.626514], [-94.461643, 34.517837], [-94.464461, 34.409171], [-94.467279, 34.300494], [-94.470092, 34.191817], [-94.47291, 34.083141], [-94.475728, 33.974464], [-94.47854, 33.865787], [-94.481331, 33.75711], [-94.484149, 33.648434], [-94.709198, 33.699289], [-94.765734, 33.731611], [-94.869374, 33.768196], [-94.962389, 33.843408], [-95.146075, 33.936616], [-95.21586, 33.959039], [-95.238031, 33.956479], [-95.276016, 33.910622], [-95.373888, 33.874269], [-95.427117, 33.872785], [-95.523494, 33.886562], [-95.541836, 33.898164], [-95.555712, 33.926091], [-95.594471, 33.945163], [-95.622789, 33.930255], [-95.763166, 33.891473], [-95.783914, 33.864502], [-95.863082, 33.863304], [-95.941579, 33.882838], [-96.139344, 33.821963], [-96.207272, 33.774062], [-96.278562, 33.757627], [-96.315048, 33.711122], [-96.336752, 33.717713], [-96.41114, 33.775205], [-96.487204, 33.7923], [-96.59159, 33.849275], [-96.595364, 33.899405], [-96.606345, 33.905635], [-96.625132, 33.911446], [-96.648538, 33.906382], [-96.694016, 33.863799], [-96.720213, 33.85279], [-96.746283, 33.854186], [-96.847572, 33.883179], [-96.889996, 33.934617], [-96.911001, 33.950437], [-96.934051, 33.95348], [-96.977694, 33.938033], [-97.002161, 33.881597], [-97.02159, 33.866512], [-97.063838, 33.8568], [-97.061229, 33.8285], [-97.09895, 33.750442], [-97.119, 33.734764], [-97.145071, 33.737687], [-97.172383, 33.75688], [-97.192488, 33.784631], [-97.201013, 33.808164], [-97.186182, 33.870083], [-97.194762, 33.890616], [-97.214938, 33.897109], [-97.264679, 33.867776], [-97.308163, 33.869226], [-97.363611, 33.840178], [-97.398492, 33.831323], [-97.430171, 33.838508], [-97.481565, 33.885705], [-97.571247, 33.91594], [-97.605925, 33.971651], [-97.621789, 33.987768], [-97.640933, 33.991669], [-97.660362, 33.990043], [-97.691937, 33.972135], [-97.795291, 33.899065], [-97.842422, 33.875785], [-97.882858, 33.871116], [-97.92159, 33.878367], [-97.946238, 33.897076], [-97.951072, 33.971212], [-97.973962, 33.993734], [-98.069383, 34.040305], [-98.089587, 34.084097], [-98.098635, 34.145027], [-98.214079, 34.135337], [-98.355978, 34.141511], [-98.420419, 34.088052], [-98.453674, 34.078131], [-98.493851, 34.088777], [-98.608395, 34.161275], [-98.730118, 34.146576], [-98.798953, 34.154739], [-98.96884, 34.208605], [-99.102291, 34.213472], [-99.157508, 34.223282], [-99.186578, 34.235477], [-99.19991, 34.318314], [-99.252875, 34.388077], [-99.270316, 34.407226], [-99.360387, 34.456094], [-99.374938, 34.457873], [-99.38465, 34.446788], [-99.404986, 34.392065], [-99.432298, 34.38922], [-99.536168, 34.404744], [-99.632029, 34.388495], [-99.685615, 34.415829], [-99.867027, 34.543369], [-99.94069, 34.576339], [-99.999341, 34.586721], [-99.99955, 34.706362], [-99.999731, 34.825992], [-99.999912, 34.945622], [-100.000115, 35.065275], [-100.000324, 35.184938], [-100.000505, 35.304568], [-100.000687, 35.424198], [-100.000895, 35.543828], [-100.001099, 35.663458], [-100.00128, 35.783088], [-100.001461, 35.902718], [-100.00167, 36.022349], [-100.001873, 36.141979], [-100.002054, 36.261609], [-100.002236, 36.381239], [-100.002444, 36.500902], [-100.189822, 36.500924], [-100.377177, 36.500924], [-100.564527, 36.500946], [-100.751904, 36.500979], [-100.939287, 36.500979], [-101.126637, 36.501023], [-101.313992, 36.501056], [-101.50137, 36.501078], [-101.688747, 36.501111], [-101.876102, 36.501133], [-102.063452, 36.501133], [-102.250835, 36.501155], [-102.438212, 36.501188], [-102.625562, 36.501188], [-102.812918, 36.50121], [-103.000295, 36.501232], [-103.000427, 36.626135], [-103.000553, 36.751039], [-103.000712, 36.875942], [-103.000839, 37.000846], [-102.753828, 37.000846], [-102.506811, 37.000846], [-102.2598, 37.000846], [-102.012783, 37.000846], [-101.781713, 37.000846], [-101.550616, 37.000846], [-101.319518, 37.000846], [-101.088421, 37.000846], [-100.857329, 37.000846], [-100.626254, 37.000846], [-100.395184, 37.000846], [-100.164086, 37.000846], [-99.932989, 37.000846], [-99.701919, 37.000846], [-99.470849, 37.000846], [-99.239752, 37.000846], [-99.008654, 37.000846], [-98.777584, 37.000846], [-98.546514, 37.000846], [-98.315417, 37.000846], [-98.084319, 37.000846], [-97.853244, 37.000846], [-97.622174, 37.000846], [-97.391077, 37.000846], [-97.159979, 37.000846], [-96.928909, 37.000846], [-96.697839, 37.000846], [-96.466742, 37.000846], [-96.235644, 37.000846], [-96.004574, 37.000846], [-95.773504, 37.000846], [-95.542407, 37.000846], [-95.31131, 37.000846], [-95.08024, 37.000846], [-94.849164, 37.000846], [-94.618067, 37.000846], [-94.618149, 36.875832], [-94.618226, 36.750863], [-94.618303, 36.625883], [-94.61838, 36.500869]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3525", "diss_me": 3525, "iso_3166_2": "US-OR", "wikipedia": "http://en.wikipedia.org/wiki/Oregon", "iso_a2": "US", "adm0_sr": 6, "name": "Oregon", "name_alt": "OR|Ore.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US41", "code_hasc": "US.OR", "note": null, "hasc_maybe": null, "region": "West", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Ore.", "postal": "OR", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 6, "mapcolor9": 1, "mapcolor13": 1, "fips": "US41", "fips_alt": null, "woe_id": 2347596, "woe_label": "Oregon, US, United States", "woe_name": "Oregon", "latitude": 43.8333, "longitude": -120.386, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5744337, "gn_name": "Oregon", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.OR", "region_sub": "Pacific", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q824", "name_ar": "\u0623\u0648\u0631\u064a\u063a\u0648\u0646", "name_bn": "\u0985\u09b0\u09c7\u0997\u09a8", "name_de": "Oregon", "name_en": "Oregon", "name_es": "Oreg\u00f3n", "name_fr": "Oregon", "name_el": "\u038c\u03c1\u03b5\u03b3\u03ba\u03bf\u03bd", "name_hi": "\u0914\u0930\u093f\u0917\u0928", "name_hu": "Oregon", "name_id": "Oregon", "name_it": "Oregon", "name_ja": "\u30aa\u30ec\u30b4\u30f3\u5dde", "name_ko": "\uc624\ub9ac\uac74", "name_nl": "Oregon", "name_pl": "Oregon", "name_pt": "Oregon", "name_ru": "\u041e\u0440\u0435\u0433\u043e\u043d", "name_sv": "Oregon", "name_tr": "Oregon", "name_vi": "Oregon", "name_zh": "\u4fc4\u52d2\u5188\u5dde", "ne_id": 1159309549, "name_he": "\u05d0\u05d5\u05e8\u05d2\u05d5\u05df", "name_uk": "\u041e\u0440\u0435\u0433\u043e\u043d", "name_ur": "\u0627\u0648\u0631\u06cc\u06af\u0648\u0646", "name_fa": "\u0627\u0648\u0631\u06af\u0646", "name_zht": "\u5967\u52d2\u5ca1\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-124.539629, 42.000559, -116.477043, 46.225451], "geometry": {"type": "Polygon", "coordinates": [[[-120.000809, 42.000559], [-120.264464, 42.000559], [-120.528114, 42.000559], [-120.79177, 42.000559], [-121.05542, 42.000559], [-121.319075, 42.000559], [-121.58273, 42.000559], [-121.84638, 42.000559], [-122.110063, 42.000559], [-122.37374, 42.000559], [-122.63739, 42.000559], [-122.901046, 42.000559], [-123.164701, 42.000559], [-123.428351, 42.000559], [-123.692007, 42.000559], [-123.955656, 42.000559], [-124.228409, 42.000768], [-124.355273, 42.122881], [-124.409996, 42.304342], [-124.420515, 42.381005], [-124.406173, 42.583681], [-124.443795, 42.670209], [-124.539629, 42.812866], [-124.498573, 42.936858], [-124.454441, 43.012367], [-124.346588, 43.341649], [-124.320595, 43.368203], [-124.275485, 43.367379], [-124.196938, 43.423344], [-124.23316, 43.436363], [-124.287987, 43.409699], [-124.239208, 43.54003], [-124.184353, 43.651552], [-124.148719, 43.691729], [-124.130663, 44.055662], [-124.099165, 44.333781], [-124.047464, 44.425506], [-124.065443, 44.520076], [-124.044541, 44.648231], [-124.059192, 44.777727], [-123.948603, 45.40085], [-123.9631, 45.476084], [-123.929355, 45.576961], [-123.961216, 45.842995], [-123.947131, 46.140592], [-123.975245, 46.178341], [-123.989302, 46.219397], [-123.962946, 46.225451], [-123.911684, 46.182198], [-123.67361, 46.182604], [-123.521631, 46.22266], [-123.466358, 46.209433], [-123.402281, 46.154962], [-123.321564, 46.144009], [-123.220589, 46.153622], [-123.120904, 46.178781], [-123.042275, 46.160027], [-122.941997, 46.114862], [-122.843373, 45.978094], [-122.74643, 45.749688], [-122.725913, 45.67375], [-122.649849, 45.627443], [-122.560964, 45.62507], [-122.202535, 45.591067], [-122.149927, 45.593759], [-122.149905, 45.593858], [-122.085124, 45.602647], [-121.882014, 45.689461], [-121.662519, 45.718135], [-121.402121, 45.71184], [-121.242698, 45.687033], [-121.184278, 45.64378], [-121.045241, 45.639044], [-120.715777, 45.689823], [-120.351432, 45.725166], [-120.156046, 45.762168], [-119.934276, 45.837875], [-119.429113, 45.93417], [-119.177345, 45.94508], [-119.049909, 45.981488], [-119.01968, 46.000341], [-119.002421, 46.00055], [-118.736986, 46.000813], [-118.47155, 46.001044], [-118.206088, 46.001275], [-117.940653, 46.001538], [-117.675217, 46.001791], [-117.409755, 46.002022], [-117.14432, 46.002253], [-116.896479, 46.002099], [-116.869194, 45.958483], [-116.764725, 45.87291], [-116.616827, 45.79917], [-116.520917, 45.721914], [-116.477043, 45.641088], [-116.549157, 45.456737], [-116.737342, 45.168841], [-116.839553, 44.98516], [-116.855857, 44.90574], [-116.948955, 44.770114], [-117.118919, 44.578314], [-117.201701, 44.436206], [-117.197312, 44.3438], [-117.139744, 44.290264], [-117.028952, 44.275542], [-116.95319, 44.245308], [-116.91242, 44.199473], [-116.91131, 44.157406], [-116.949779, 44.119009], [-116.960683, 44.079118], [-116.943967, 44.037677], [-116.957634, 43.964135], [-117.020498, 43.813194], [-117.02024, 43.808437], [-117.0198, 43.562925], [-117.019339, 43.339727], [-117.0189, 43.11654], [-117.01846, 42.893352], [-117.018021, 42.670165], [-117.017581, 42.446967], [-117.017114, 42.223779], [-117.016675, 42.000559], [-117.389705, 42.000559], [-117.762701, 42.000559], [-118.135731, 42.000559], [-118.508756, 42.000559], [-118.881758, 42.000559], [-119.254782, 42.000559], [-119.627807, 42.000559], [-120.000809, 42.000559]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3560", "diss_me": 3560, "iso_3166_2": "US-PA", "wikipedia": "http://en.wikipedia.org/wiki/Pennsylvania", "iso_a2": "US", "adm0_sr": 1, "name": "Pennsylvania", "name_alt": "Commonwealth of Pennsylvania|PA", "name_local": null, "type": "State", "type_en": "State", "code_local": "US42", "code_hasc": "US.PA", "note": null, "hasc_maybe": null, "region": "Northeast", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Pa.", "postal": "PA", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 12, "mapcolor9": 1, "mapcolor13": 1, "fips": "US42", "fips_alt": null, "woe_id": 2347597, "woe_label": "Pennsylvania, US, United States", "woe_name": "Pennsylvania", "latitude": 40.8601, "longitude": -77.6094, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 6254927, "gn_name": "Pennsylvania", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.PA", "region_sub": "Middle Atlantic", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1400", "name_ar": "\u0628\u0646\u0633\u064a\u0644\u0641\u0627\u0646\u064a\u0627", "name_bn": "\u09aa\u09c7\u09a8\u09b8\u09bf\u09b2\u09ad\u09c7\u09a8\u09bf\u09af\u09bc\u09be", "name_de": "Pennsylvania", "name_en": "Pennsylvania", "name_es": "Pensilvania", "name_fr": "Pennsylvanie", "name_el": "\u03a0\u03b5\u03bd\u03c3\u03b9\u03bb\u03b2\u03ac\u03bd\u03b9\u03b1", "name_hi": "\u092a\u0947\u0928\u094d\u0938\u093f\u0932\u0935\u0947\u0928\u093f\u092f\u093e", "name_hu": "Pennsylvania", "name_id": "Pennsylvania", "name_it": "Pennsylvania", "name_ja": "\u30da\u30f3\u30b7\u30eb\u30d9\u30cb\u30a2\u5dde", "name_ko": "\ud39c\uc2e4\ubca0\uc774\ub2c8\uc544", "name_nl": "Pennsylvania", "name_pl": "Pensylwania", "name_pt": "Pensilv\u00e2nia", "name_ru": "\u041f\u0435\u043d\u0441\u0438\u043b\u044c\u0432\u0430\u043d\u0438\u044f", "name_sv": "Pennsylvania", "name_tr": "Pensilvanya", "name_vi": "Pennsylvania", "name_zh": "\u5bbe\u5915\u6cd5\u5c3c\u4e9a\u5dde", "ne_id": 1159315331, "name_he": "\u05e4\u05e0\u05e1\u05d9\u05dc\u05d1\u05e0\u05d9\u05d4", "name_uk": "\u041f\u0435\u043d\u0441\u0438\u043b\u044c\u0432\u0430\u043d\u0456\u044f", "name_ur": "\u067e\u0646\u0633\u0644\u0648\u0627\u0646\u06cc\u0627", "name_fa": "\u067e\u0646\u0633\u06cc\u0644\u0648\u0627\u0646\u06cc\u0627", "name_zht": "\u8cd3\u5915\u6cd5\u5c3c\u4e9e\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-80.520762, 39.722357, -74.699051, 42.538977], "geometry": {"type": "Polygon", "coordinates": [[[-80.520762, 42.324392], [-80.247576, 42.365997], [-80.035726, 42.441463], [-79.762024, 42.538977], [-79.763035, 42.404746], [-79.763002, 42.270131], [-79.76298, 42.135515], [-79.762958, 42.0009], [-79.625079, 42.000801], [-79.487234, 42.000746], [-79.349388, 42.000669], [-79.211521, 42.000592], [-79.073642, 42.000515], [-78.935775, 42.000438], [-78.797897, 42.000329], [-78.660051, 42.000274], [-78.522206, 42.000197], [-78.384327, 42.00012], [-78.24646, 42.000043], [-78.108581, 41.999966], [-77.970714, 41.999889], [-77.832868, 41.999812], [-77.695023, 41.999735], [-77.557145, 41.999658], [-77.419277, 41.999581], [-77.281432, 41.999505], [-77.143575, 41.999428], [-77.005708, 41.999351], [-76.86784, 41.999274], [-76.729962, 41.999197], [-76.592094, 41.99912], [-76.454238, 41.999043], [-76.316393, 41.998966], [-76.178525, 41.998878], [-76.040647, 41.998801], [-75.902779, 41.998725], [-75.764901, 41.998648], [-75.627055, 41.998571], [-75.48921, 41.998494], [-75.351342, 41.998417], [-75.273977, 41.94666], [-75.238864, 41.892201], [-75.121893, 41.853364], [-75.095537, 41.83171], [-75.094768, 41.799487], [-75.053679, 41.765045], [-75.066906, 41.713212], [-75.066192, 41.666608], [-75.051361, 41.608369], [-75.02273, 41.552866], [-74.981257, 41.507702], [-74.935367, 41.474369], [-74.75662, 41.423909], [-74.720365, 41.394861], [-74.699051, 41.357299], [-74.777779, 41.325076], [-74.812485, 41.30151], [-74.84139, 41.268595], [-74.912296, 41.155271], [-75.031541, 41.05178], [-75.123036, 40.999002], [-75.12275, 40.971766], [-75.074926, 40.884458], [-75.075564, 40.856267], [-75.111797, 40.802105], [-75.174737, 40.775518], [-75.185691, 40.743822], [-75.192282, 40.689868], [-75.189019, 40.595814], [-75.170518, 40.576797], [-75.097448, 40.543135], [-75.034046, 40.420374], [-74.976379, 40.405828], [-74.734889, 40.154504], [-74.909297, 40.079545], [-75.023532, 40.01745], [-75.074168, 39.98348], [-75.172924, 39.894777], [-75.320877, 39.864696], [-75.400638, 39.831572], [-75.421029, 39.815422], [-75.510446, 39.843438], [-75.634581, 39.839482], [-75.676823, 39.827233], [-75.709145, 39.802898], [-75.78472, 39.722357], [-76.015532, 39.722379], [-76.246322, 39.722434], [-76.477112, 39.722456], [-76.707901, 39.722489], [-76.93868, 39.722511], [-77.169492, 39.722533], [-77.400304, 39.722566], [-77.631094, 39.722588], [-77.861883, 39.72261], [-78.092695, 39.722643], [-78.323507, 39.722665], [-78.554297, 39.722687], [-78.785086, 39.72272], [-79.015898, 39.722742], [-79.24671, 39.722775], [-79.4775, 39.722797], [-79.607743, 39.722742], [-79.737997, 39.72272], [-79.868218, 39.722687], [-79.998472, 39.722643], [-80.128725, 39.72261], [-80.258946, 39.722588], [-80.3892, 39.722533], [-80.519443, 39.722511], [-80.519553, 39.838186], [-80.519652, 39.953839], [-80.519762, 40.069492], [-80.519861, 40.185145], [-80.51996, 40.300798], [-80.520069, 40.416473], [-80.520168, 40.532149], [-80.519081, 40.646956], [-80.520278, 40.752655], [-80.520278, 40.857509], [-80.520278, 40.962362], [-80.520278, 41.067183], [-80.520278, 41.172014], [-80.520278, 41.276857], [-80.520278, 41.38171], [-80.520278, 41.486564], [-80.520278, 41.591417], [-80.520278, 41.696238], [-80.520278, 41.801069], [-80.520278, 41.905923], [-80.520278, 42.010766], [-80.520278, 42.115619], [-80.520278, 42.220473], [-80.520762, 42.324392]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3539", "diss_me": 3539, "iso_3166_2": "US-RI", "wikipedia": "http://en.wikipedia.org/wiki/Rhode_Island", "iso_a2": "US", "adm0_sr": 6, "name": "Rhode Island", "name_alt": "State of Rhode Island and Providence Plantations|RI|R.I.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US44", "code_hasc": "US.RI", "note": null, "hasc_maybe": null, "region": "Northeast", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "R.I.", "postal": "RI", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 12, "mapcolor9": 1, "mapcolor13": 1, "fips": "US44", "fips_alt": null, "woe_id": 2347598, "woe_label": "Rhode Island, US, United States", "woe_name": "Rhode Island", "latitude": 41.6242, "longitude": -71.5082, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5224323, "gn_name": "Rhode Island", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.RI", "region_sub": "New England", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1387", "name_ar": "\u0631\u0648\u062f \u0622\u064a\u0644\u0627\u0646\u062f", "name_bn": "\u09b0\u09cb\u09a1 \u0986\u0987\u09b2\u09cd\u09af\u09be\u09a8\u09cd\u09a1", "name_de": "Rhode Island", "name_en": "Rhode Island", "name_es": "Rhode Island", "name_fr": "Rhode Island", "name_el": "\u03a1\u03cc\u03bf\u03c5\u03bd\u03c4 \u0386\u03b9\u03bb\u03b1\u03bd\u03c4", "name_hi": "\u0930\u094b\u0921 \u0906\u0907\u0932\u0948\u0902\u0921", "name_hu": "Rhode Island", "name_id": "Rhode Island", "name_it": "Rhode Island", "name_ja": "\u30ed\u30fc\u30c9\u30a2\u30a4\u30e9\u30f3\u30c9\u5dde", "name_ko": "\ub85c\ub4dc\uc544\uc77c\ub79c\ub4dc", "name_nl": "Rhode Island", "name_pl": "Rhode Island", "name_pt": "Rhode Island", "name_ru": "\u0420\u043e\u0434-\u0410\u0439\u043b\u0435\u043d\u0434", "name_sv": "Rhode Island", "name_tr": "Rhode Island", "name_vi": "Rhode Island", "name_zh": "\u7f57\u5f97\u5c9b\u5dde", "ne_id": 1159312213, "name_he": "\u05e8\u05d5\u05d3 \u05d0\u05d9\u05d9\u05dc\u05e0\u05d3", "name_uk": "\u0420\u043e\u0434-\u0410\u0439\u043b\u0435\u043d\u0434", "name_ur": "\u0631\u06c1\u0648\u0688 \u0622\u0626\u06cc \u0644\u06cc\u0646\u0688", "name_fa": "\u0631\u0648\u062f \u0622\u06cc\u0644\u0646\u062f", "name_zht": "\u7f85\u5fb7\u5cf6\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-71.842353, 41.33091, -71.232052, 42.016863], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-71.842353, 41.335513], [-71.829873, 41.392741], [-71.804527, 41.416746], [-71.799232, 41.47917], [-71.795793, 41.519951], [-71.796518, 41.588858], [-71.79732, 41.667586], [-71.798199, 41.753114], [-71.798968, 41.828502], [-71.799561, 41.883027], [-71.800319, 41.95824], [-71.800836, 42.011963], [-71.725821, 42.012864], [-71.623242, 42.014028], [-71.524134, 42.015237], [-71.462534, 42.015962], [-71.387135, 42.016863], [-71.383927, 41.971731], [-71.379071, 41.902407], [-71.33763, 41.891443], [-71.339487, 41.835171], [-71.340728, 41.797916], [-71.304737, 41.774658], [-71.267889, 41.75084], [-71.233765, 41.706554], [-71.271075, 41.681231], [-71.310758, 41.719881], [-71.330599, 41.762255], [-71.359152, 41.786238], [-71.390156, 41.795335], [-71.363679, 41.702731], [-71.426542, 41.633297], [-71.443802, 41.453693], [-71.52286, 41.378975], [-71.769283, 41.33091], [-71.842353, 41.335513]]], [[[-71.241379, 41.491969], [-71.290938, 41.464602], [-71.346232, 41.469403], [-71.318151, 41.506306], [-71.307473, 41.560491], [-71.280194, 41.620048], [-71.264483, 41.63823], [-71.232052, 41.654303], [-71.241379, 41.491969]]], [[[-71.36536, 41.485267], [-71.393078, 41.466745], [-71.403383, 41.51504], [-71.383981, 41.570532], [-71.364316, 41.571807], [-71.354472, 41.542297], [-71.36536, 41.485267]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3545", "diss_me": 3545, "iso_3166_2": "US-SC", "wikipedia": "http://en.wikipedia.org/wiki/South_Carolina", "iso_a2": "US", "adm0_sr": 1, "name": "South Carolina", "name_alt": "SC|S.C.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US45", "code_hasc": "US.SC", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "S.C.", "postal": "SC", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 14, "mapcolor9": 1, "mapcolor13": 1, "fips": "US45", "fips_alt": null, "woe_id": 2347599, "woe_label": "South Carolina, US, United States", "woe_name": "South Carolina", "latitude": 33.8578, "longitude": -80.6471, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4597040, "gn_name": "South Carolina", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.SC", "region_sub": "South Atlantic", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1456", "name_ar": "\u0643\u0627\u0631\u0648\u0644\u0627\u064a\u0646\u0627 \u0627\u0644\u062c\u0646\u0648\u0628\u064a\u0629", "name_bn": "\u09b8\u09be\u0989\u09a5 \u0995\u09cd\u09af\u09be\u09b0\u09cb\u09b2\u09be\u0987\u09a8\u09be", "name_de": "South Carolina", "name_en": "South Carolina", "name_es": "Carolina del Sur", "name_fr": "Caroline du Sud", "name_el": "\u039d\u03cc\u03c4\u03b9\u03b1 \u039a\u03b1\u03c1\u03bf\u03bb\u03af\u03bd\u03b1", "name_hi": "\u0926\u0915\u094d\u0937\u093f\u0923\u0940 \u0915\u0947\u0930\u094b\u0932\u093e\u0907\u0928\u093e", "name_hu": "D\u00e9l-Karolina", "name_id": "Carolina Selatan", "name_it": "Carolina del Sud", "name_ja": "\u30b5\u30a6\u30b9\u30ab\u30ed\u30e9\u30a4\u30ca\u5dde", "name_ko": "\uc0ac\uc6b0\uc2a4\uce90\ub864\ub77c\uc774\ub098", "name_nl": "South Carolina", "name_pl": "Karolina Po\u0142udniowa", "name_pt": "Carolina do Sul", "name_ru": "\u042e\u0436\u043d\u0430\u044f \u041a\u0430\u0440\u043e\u043b\u0438\u043d\u0430", "name_sv": "South Carolina", "name_tr": "G\u00fcney Karolina", "name_vi": "Nam Carolina", "name_zh": "\u5357\u5361\u7f57\u6765\u7eb3\u5dde", "ne_id": 1159315307, "name_he": "\u05e7\u05e8\u05d5\u05dc\u05d9\u05d9\u05e0\u05d4 \u05d4\u05d3\u05e8\u05d5\u05de\u05d9\u05ea", "name_uk": "\u041f\u0456\u0432\u0434\u0435\u043d\u043d\u0430 \u041a\u0430\u0440\u043e\u043b\u0456\u043d\u0430", "name_ur": "\u062c\u0646\u0648\u0628\u06cc \u06a9\u06cc\u0631\u0648\u0644\u06cc\u0646\u0627", "name_fa": "\u06a9\u0627\u0631\u0648\u0644\u06cc\u0646\u0627\u06cc \u062c\u0646\u0648\u0628\u06cc", "name_zht": "\u5357\u5361\u7f85\u840a\u7d0d\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-83.355575, 32.029565, -78.564272, 35.210931], "geometry": {"type": "Polygon", "coordinates": [[[-80.872346, 32.029565], [-81.074813, 32.109699], [-81.135018, 32.181858], [-81.132953, 32.27467], [-81.171504, 32.380139], [-81.290332, 32.557239], [-81.37697, 32.607468], [-81.433813, 32.728032], [-81.489778, 32.935663], [-81.57824, 33.068575], [-81.69932, 33.126759], [-81.780322, 33.195292], [-81.821279, 33.274096], [-81.864093, 33.325436], [-81.908741, 33.349254], [-81.932845, 33.38987], [-81.936394, 33.447285], [-82.005718, 33.522893], [-82.208361, 33.663584], [-82.256623, 33.749233], [-82.351897, 33.837728], [-82.589344, 34.017618], [-82.589268, 34.017377], [-82.818585, 34.366017], [-82.818607, 34.366072], [-82.847732, 34.436911], [-82.896819, 34.465806], [-82.975679, 34.476396], [-83.052781, 34.51086], [-83.165896, 34.598531], [-83.166522, 34.599597], [-83.355575, 34.708318], [-83.316716, 34.805657], [-83.1704, 34.932911], [-83.121357, 35.000554], [-83.114821, 35.001477], [-83.09655, 35.001642], [-82.936974, 35.04417], [-82.777529, 35.086643], [-82.743966, 35.084061], [-82.651483, 35.128039], [-82.463957, 35.177961], [-82.392535, 35.210931], [-82.356083, 35.201626], [-82.197484, 35.195891], [-82.038885, 35.190156], [-81.880298, 35.184421], [-81.721699, 35.178675], [-81.5631, 35.172941], [-81.404513, 35.167206], [-81.245914, 35.161471], [-81.087316, 35.155714], [-81.05662, 35.145508], [-81.046853, 35.131083], [-81.051171, 35.088972], [-81.045249, 35.065615], [-80.933683, 35.113669], [-80.881695, 35.057914], [-80.79297, 34.962772], [-80.789278, 34.90717], [-80.784082, 34.828629], [-80.642776, 34.824641], [-80.501459, 34.820664], [-80.36013, 34.816687], [-80.218824, 34.81271], [-80.077507, 34.808733], [-79.936179, 34.804745], [-79.794862, 34.800768], [-79.653556, 34.796791], [-79.518523, 34.682643], [-79.383468, 34.568506], [-79.248413, 34.45438], [-79.11338, 34.340232], [-78.978347, 34.226073], [-78.843292, 34.111947], [-78.708237, 33.997821], [-78.564272, 33.876664], [-78.577709, 33.873225], [-78.841435, 33.724097], [-78.920295, 33.658695], [-79.138187, 33.405921], [-79.193822, 33.244148], [-79.23836, 33.312153], [-79.22733, 33.363163], [-79.226473, 33.404889], [-79.281328, 33.315438], [-79.229242, 33.185129], [-79.276011, 33.135394], [-79.419931, 33.042527], [-79.498681, 33.027311], [-79.587121, 33.000877], [-79.614928, 32.909263], [-79.735019, 32.824789], [-79.804991, 32.78738], [-79.933103, 32.810034], [-79.89364, 32.728702], [-79.940727, 32.667157], [-80.021752, 32.619894], [-80.122551, 32.589099], [-80.180317, 32.592889], [-80.229668, 32.576509], [-80.268351, 32.537342], [-80.362844, 32.500725], [-80.460974, 32.521346], [-80.572233, 32.533695], [-80.634195, 32.511733], [-80.530012, 32.475379], [-80.474278, 32.422777], [-80.485726, 32.351827], [-80.513631, 32.324405], [-80.579341, 32.287326], [-80.608224, 32.292809], [-80.625846, 32.326273], [-80.647214, 32.395926], [-80.677778, 32.381128], [-80.683052, 32.348641], [-80.709331, 32.33704], [-80.802561, 32.448045], [-80.797881, 32.363396], [-80.765328, 32.298313], [-80.73383, 32.265321], [-80.702047, 32.245908], [-80.694214, 32.21574], [-80.758011, 32.142175], [-80.790795, 32.125838], [-80.849242, 32.113929], [-80.882058, 32.068611], [-80.872346, 32.029565]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3534", "diss_me": 3534, "iso_3166_2": "US-SD", "wikipedia": "http://en.wikipedia.org/wiki/South_Dakota", "iso_a2": "US", "adm0_sr": 1, "name": "South Dakota", "name_alt": "SD|S.D.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US46", "code_hasc": "US.SD", "note": null, "hasc_maybe": null, "region": "Midwest", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "S.D.", "postal": "SD", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 12, "mapcolor9": 1, "mapcolor13": 1, "fips": "US46", "fips_alt": null, "woe_id": 2347600, "woe_label": "South Dakota, US, United States", "woe_name": "South Dakota", "latitude": 44.4711, "longitude": -100.255, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5769223, "gn_name": "South Dakota", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.SD", "region_sub": "West North Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1211", "name_ar": "\u062f\u0627\u0643\u0648\u062a\u0627 \u0627\u0644\u062c\u0646\u0648\u0628\u064a\u0629", "name_bn": "\u09a6\u0995\u09cd\u09b7\u09bf\u09a3 \u09a1\u09be\u0995\u09cb\u099f\u09be", "name_de": "South Dakota", "name_en": "South Dakota", "name_es": "Dakota del Sur", "name_fr": "Dakota du Sud", "name_el": "\u039d\u03cc\u03c4\u03b9\u03b1 \u039d\u03c4\u03b1\u03ba\u03cc\u03c4\u03b1", "name_hi": "\u0926\u0915\u094d\u0937\u093f\u0923 \u0921\u0915\u094b\u091f\u093e", "name_hu": "D\u00e9l-Dakota", "name_id": "Dakota Selatan", "name_it": "Dakota del Sud", "name_ja": "\u30b5\u30a6\u30b9\u30c0\u30b3\u30bf\u5dde", "name_ko": "\uc0ac\uc6b0\uc2a4\ub2e4\ucf54\ud0c0", "name_nl": "South Dakota", "name_pl": "Dakota Po\u0142udniowa", "name_pt": "Dakota do Sul", "name_ru": "\u042e\u0436\u043d\u0430\u044f \u0414\u0430\u043a\u043e\u0442\u0430", "name_sv": "South Dakota", "name_tr": "G\u00fcney Dakota", "name_vi": "Nam Dakota", "name_zh": "\u5357\u8fbe\u79d1\u4ed6\u5dde", "ne_id": 1159315367, "name_he": "\u05d3\u05e7\u05d5\u05d8\u05d4 \u05d4\u05d3\u05e8\u05d5\u05de\u05d9\u05ea", "name_uk": "\u041f\u0456\u0432\u0434\u0435\u043d\u043d\u0430 \u0414\u0430\u043a\u043e\u0442\u0430", "name_ur": "\u062c\u0646\u0648\u0628\u06cc \u0688\u06a9\u0648\u0679\u0627", "name_fa": "\u062f\u0627\u06a9\u0648\u062a\u0627\u06cc \u062c\u0646\u0648\u0628\u06cc", "name_zht": "\u5357\u9054\u79d1\u4ed6\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-104.037212, 42.511259, -96.453619, 45.943058], "geometry": {"type": "Polygon", "coordinates": [[[-96.453619, 43.501171], [-96.598622, 43.497501], [-96.581285, 43.434923], [-96.541647, 43.373455], [-96.534956, 43.338057], [-96.542526, 43.309031], [-96.569942, 43.283323], [-96.563454, 43.242685], [-96.55539, 43.231676], [-96.49028, 43.205529], [-96.468137, 43.17023], [-96.461293, 43.129767], [-96.462688, 43.099181], [-96.502112, 43.043294], [-96.513274, 42.969059], [-96.562576, 42.85857], [-96.616084, 42.791388], [-96.626835, 42.757001], [-96.62177, 42.729535], [-96.538702, 42.658585], [-96.53361, 42.630164], [-96.506326, 42.593579], [-96.480953, 42.511259], [-96.55795, 42.524794], [-96.632778, 42.568673], [-96.675542, 42.637601], [-96.804527, 42.701421], [-97.019733, 42.760176], [-97.164478, 42.813196], [-97.23879, 42.860536], [-97.416658, 42.881004], [-97.698139, 42.874643], [-97.880918, 42.849583], [-97.964947, 42.805868], [-98.143283, 42.852263], [-98.441765, 43.001095], [-98.837141, 43.001249], [-99.183271, 43.001249], [-99.529373, 43.001249], [-99.875475, 43.001249], [-100.221605, 43.001249], [-100.567708, 43.001282], [-100.91381, 43.001304], [-101.25994, 43.001304], [-101.606064, 43.001304], [-101.952172, 43.001326], [-102.298274, 43.001359], [-102.644398, 43.001359], [-102.990528, 43.001359], [-103.33663, 43.001381], [-103.682738, 43.001403], [-104.028862, 43.001403], [-104.029895, 43.251364], [-104.030955, 43.501325], [-104.032016, 43.751286], [-104.033048, 44.001269], [-104.034081, 44.251251], [-104.035119, 44.501212], [-104.036152, 44.751173], [-104.037212, 45.001134], [-104.02928, 45.001079], [-104.021348, 45.001057], [-104.013416, 45.001024], [-104.005478, 45.00097], [-104.005302, 45.004101], [-104.005143, 45.007232], [-104.004962, 45.010352], [-104.00478, 45.013483], [-104.006357, 45.245866], [-104.007934, 45.47826], [-104.00951, 45.710642], [-104.011087, 45.943058], [-103.778132, 45.943036], [-103.545173, 45.943036], [-103.312213, 45.943036], [-103.079259, 45.943036], [-102.8463, 45.943036], [-102.613345, 45.943014], [-102.380386, 45.942981], [-102.147426, 45.942981], [-101.914472, 45.942981], [-101.681513, 45.942981], [-101.448558, 45.942981], [-101.215599, 45.942959], [-100.982645, 45.942937], [-100.749685, 45.942937], [-100.516725, 45.942937], [-100.283744, 45.942937], [-100.050762, 45.942937], [-99.817803, 45.942904], [-99.584849, 45.942882], [-99.351889, 45.942882], [-99.118929, 45.942882], [-98.885975, 45.942882], [-98.653016, 45.942882], [-98.420062, 45.94286], [-98.187102, 45.942827], [-97.954142, 45.942827], [-97.721188, 45.942827], [-97.488229, 45.942827], [-97.255275, 45.942827], [-97.022315, 45.942805], [-96.789355, 45.942773], [-96.556401, 45.942773], [-96.591052, 45.843269], [-96.614689, 45.799972], [-96.662672, 45.755653], [-96.813619, 45.659182], [-96.85106, 45.626004], [-96.845452, 45.595868], [-96.81491, 45.557427], [-96.737527, 45.467845], [-96.696109, 45.431776], [-96.529759, 45.371549], [-96.453668, 45.297337], [-96.453668, 45.072809], [-96.453668, 44.848292], [-96.453668, 44.623787], [-96.453641, 44.399259], [-96.453619, 44.174721], [-96.453619, 43.950215], [-96.453619, 43.725698], [-96.453619, 43.501171]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3551", "diss_me": 3551, "iso_3166_2": "US-TN", "wikipedia": "http://en.wikipedia.org/wiki/Tennessee", "iso_a2": "US", "adm0_sr": 1, "name": "Tennessee", "name_alt": "TN|Tenn.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US47", "code_hasc": "US.TN", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Tenn.", "postal": "TN", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 9, "mapcolor9": 1, "mapcolor13": 1, "fips": "US47", "fips_alt": null, "woe_id": 2347601, "woe_label": "Tennessee, US, United States", "woe_name": "Tennessee", "latitude": 35.7514, "longitude": -86.3415, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4662168, "gn_name": "Tennessee", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.TN", "region_sub": "East South Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1509", "name_ar": "\u062a\u064a\u0646\u064a\u0633\u064a", "name_bn": "\u099f\u09c7\u09a8\u09c7\u09b8\u09c0", "name_de": "Tennessee", "name_en": "Tennessee", "name_es": "Tennessee", "name_fr": "Tennessee", "name_el": "\u03a4\u03b5\u03bd\u03b5\u03c3\u03af", "name_hi": "\u091f\u0947\u0928\u0947\u0938\u0940", "name_hu": "Tennessee", "name_id": "Tennessee", "name_it": "Tennessee", "name_ja": "\u30c6\u30cd\u30b7\u30fc\u5dde", "name_ko": "\ud14c\ub124\uc2dc", "name_nl": "Tennessee", "name_pl": "Tennessee", "name_pt": "Tennessee", "name_ru": "\u0422\u0435\u043d\u043d\u0435\u0441\u0441\u0438", "name_sv": "Tennessee", "name_tr": "Tennessee", "name_vi": "Tennessee", "name_zh": "\u7530\u7eb3\u897f\u5dde", "ne_id": 1159315319, "name_he": "\u05d8\u05e0\u05e1\u05d9", "name_uk": "\u0422\u0435\u043d\u043d\u0435\u0441\u0441\u0456", "name_ur": "\u0679\u06cc\u0646\u06cc\u0633\u06cc", "name_fa": "\u062a\u0646\u0633\u06cc", "name_zht": "\u7530\u7d0d\u897f\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-90.29376, 34.988096, -81.65889, 36.693009], "geometry": {"type": "Polygon", "coordinates": [[[-85.623604, 35.000862], [-85.784037, 35.002356], [-85.944437, 35.003861], [-86.104871, 35.00541], [-86.265293, 35.006904], [-86.425726, 35.008409], [-86.58616, 35.009903], [-86.746582, 35.011409], [-86.907015, 35.012925], [-87.067449, 35.014452], [-87.227871, 35.015946], [-87.388305, 35.017451], [-87.548738, 35.018945], [-87.70916, 35.02045], [-87.869594, 35.021966], [-88.029994, 35.023494], [-88.190427, 35.024999], [-88.203139, 35.024197], [-88.19079, 35.012046], [-88.173267, 34.999005], [-88.444772, 34.999126], [-88.710421, 34.999412], [-88.97606, 34.999697], [-89.241698, 34.999983], [-89.507348, 35.000268], [-89.772997, 35.000554], [-90.038635, 35.00084], [-90.293705, 35.001114], [-90.29376, 35.004476], [-90.255956, 35.046389], [-90.14227, 35.114296], [-90.092919, 35.203592], [-90.107882, 35.314203], [-90.066024, 35.414112], [-89.967345, 35.50331], [-89.92652, 35.591652], [-89.943505, 35.679136], [-89.894561, 35.750503], [-89.779655, 35.805742], [-89.763593, 35.828044], [-89.768108, 35.845249], [-89.769943, 35.864299], [-89.768932, 35.8721], [-89.763593, 35.888766], [-89.738214, 35.898741], [-89.703772, 35.906904], [-89.688908, 35.920956], [-89.689171, 35.943599], [-89.70932, 35.98305], [-89.704772, 36.001573], [-89.697697, 36.030303], [-89.641886, 36.104515], [-89.63413, 36.167917], [-89.674549, 36.220575], [-89.654081, 36.247964], [-89.627988, 36.255259], [-89.594623, 36.259445], [-89.583549, 36.272233], [-89.583549, 36.287657], [-89.611707, 36.321968], [-89.604093, 36.351916], [-89.55527, 36.372922], [-89.540603, 36.426667], [-89.557313, 36.501078], [-89.487221, 36.503066], [-89.485386, 36.498133], [-89.471488, 36.488883], [-89.451823, 36.497518], [-89.450329, 36.500023], [-89.251784, 36.499946], [-89.079079, 36.499913], [-88.906373, 36.499891], [-88.733646, 36.499836], [-88.560919, 36.499792], [-88.388214, 36.499759], [-88.215509, 36.499737], [-88.059108, 36.499683], [-88.05601, 36.500946], [-88.056713, 36.59032], [-88.096297, 36.693009], [-88.091122, 36.6928], [-87.956298, 36.681968], [-87.868715, 36.675046], [-87.839151, 36.643966], [-87.506254, 36.649185], [-87.173357, 36.654403], [-86.84046, 36.659622], [-86.507586, 36.66484], [-86.160451, 36.655073], [-85.813283, 36.645339], [-85.466126, 36.635594], [-85.11898, 36.625828], [-84.771845, 36.616061], [-84.424688, 36.606316], [-84.07752, 36.596582], [-83.730385, 36.586815], [-83.722507, 36.589089], [-83.714652, 36.591363], [-83.706797, 36.593638], [-83.698942, 36.595901], [-83.691086, 36.598175], [-83.683231, 36.600449], [-83.675376, 36.602723], [-83.667521, 36.60503], [-83.440763, 36.604119], [-82.955837, 36.60213], [-82.611779, 36.600713], [-82.329386, 36.599548], [-82.162185, 36.598856], [-81.952511, 36.598021], [-81.905336, 36.618544], [-81.800713, 36.615182], [-81.65889, 36.610579], [-81.704418, 36.533993], [-81.707648, 36.481962], [-81.733323, 36.405914], [-81.734125, 36.355454], [-81.80826, 36.352718], [-81.851151, 36.3397], [-81.908247, 36.306411], [-82.051366, 36.122862], [-82.100618, 36.106526], [-82.182499, 36.153789], [-82.294944, 36.13397], [-82.368245, 36.099549], [-82.478426, 36.010055], [-82.52113, 35.981216], [-82.553408, 35.970987], [-82.576842, 35.972273], [-82.588751, 35.986951], [-82.598101, 36.031599], [-82.611097, 36.047364], [-82.644924, 36.046793], [-82.700087, 36.029841], [-82.75559, 35.999871], [-82.812817, 35.947444], [-82.887722, 35.951728], [-82.901862, 35.939171], [-82.920253, 35.8789], [-82.949476, 35.834526], [-82.990203, 35.800447], [-83.120369, 35.774618], [-83.284241, 35.682058], [-83.511119, 35.584082], [-83.722716, 35.559901], [-83.811705, 35.54029], [-83.871306, 35.51489], [-84.003735, 35.414069], [-84.062281, 35.286012], [-84.128584, 35.261413], [-84.232471, 35.260589], [-84.261101, 35.249581], [-84.286974, 35.200846], [-84.32469, 34.988096], [-84.649424, 34.991304], [-84.974158, 34.994479], [-85.298892, 34.997654], [-85.623604, 35.000862]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3536", "diss_me": 3536, "iso_3166_2": "US-TX", "wikipedia": "http://en.wikipedia.org/wiki/Texas", "iso_a2": "US", "adm0_sr": 4, "name": "Texas", "name_alt": "TX|Tex.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US48", "code_hasc": "US.TX", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Tex.", "postal": "TX", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 5, "mapcolor9": 1, "mapcolor13": 1, "fips": "US48", "fips_alt": null, "woe_id": 2347602, "woe_label": "Texas, US, United States", "woe_name": "Texas", "latitude": 31.131, "longitude": -98.7607, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4736286, "gn_name": "Texas", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.TX", "region_sub": "West South Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1439", "name_ar": "\u062a\u0643\u0633\u0627\u0633", "name_bn": "\u099f\u09c7\u0995\u09cd\u09b8\u09be\u09b8", "name_de": "Texas", "name_en": "Texas", "name_es": "Texas", "name_fr": "Texas", "name_el": "\u03a4\u03ad\u03be\u03b1\u03c2", "name_hi": "\u091f\u0945\u0915\u094d\u0938\u0938", "name_hu": "Texas", "name_id": "Texas", "name_it": "Texas", "name_ja": "\u30c6\u30ad\u30b5\u30b9\u5dde", "name_ko": "\ud14d\uc0ac\uc2a4", "name_nl": "Texas", "name_pl": "Teksas", "name_pt": "Texas", "name_ru": "\u0422\u0435\u0445\u0430\u0441", "name_sv": "Texas", "name_tr": "Teksas", "name_vi": "Texas", "name_zh": "\u5f97\u514b\u8428\u65af\u5dde", "ne_id": 1159315211, "name_he": "\u05d8\u05e7\u05e1\u05e1", "name_uk": "\u0422\u0435\u0445\u0430\u0441", "name_ur": "\u0679\u06cc\u06a9\u0633\u0627\u0633", "name_fa": "\u062a\u06af\u0632\u0627\u0633", "name_zht": "\u5fb7\u514b\u85a9\u65af\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-106.668262, 25.87052, -93.530591, 36.501232], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-94.484149, 33.648434], [-94.432008, 33.599731], [-94.390122, 33.585603], [-94.377955, 33.566113], [-94.357674, 33.560972], [-94.33256, 33.565036], [-94.294679, 33.58746], [-94.238456, 33.581208], [-94.191534, 33.589009], [-94.098798, 33.57733], [-94.047327, 33.554435], [-94.045805, 33.418841], [-94.044306, 33.283215], [-94.042806, 33.147589], [-94.041307, 33.011996], [-94.041565, 32.885378], [-94.041801, 32.758805], [-94.042032, 32.63222], [-94.04229, 32.505614], [-94.042548, 32.379007], [-94.042806, 32.252423], [-94.043064, 32.125838], [-94.043301, 31.999232], [-93.905065, 31.876998], [-93.845585, 31.792942], [-93.826798, 31.75026], [-93.820652, 31.603966], [-93.806902, 31.568799], [-93.737578, 31.513812], [-93.736057, 31.477667], [-93.663657, 31.372198], [-93.665882, 31.322584], [-93.596992, 31.209754], [-93.557749, 31.180421], [-93.551443, 31.104066], [-93.530591, 31.04619], [-93.562654, 31.004903], [-93.549196, 30.947719], [-93.568675, 30.894655], [-93.579194, 30.823805], [-93.624721, 30.714348], [-93.665206, 30.660768], [-93.720215, 30.558265], [-93.715205, 30.473253], [-93.746626, 30.380363], [-93.750394, 30.344713], [-93.720967, 30.282904], [-93.710629, 30.112813], [-93.726933, 30.077108], [-93.79401, 29.977264], [-93.841449, 29.979747], [-93.946302, 29.815007], [-93.886383, 29.722634], [-93.890464, 29.689356], [-94.099677, 29.670383], [-94.574457, 29.484527], [-94.759609, 29.384255], [-94.750128, 29.418027], [-94.526265, 29.547962], [-94.605334, 29.567804], [-94.732638, 29.53535], [-94.778291, 29.547863], [-94.724365, 29.655299], [-94.741938, 29.74999], [-94.832322, 29.752605], [-94.889913, 29.676953], [-94.929859, 29.68015], [-94.982286, 29.712603], [-95.022875, 29.70232], [-94.992827, 29.530934], [-94.935907, 29.460478], [-94.888287, 29.370555], [-95.018332, 29.25945], [-95.139044, 29.167835], [-95.152145, 29.079231], [-95.273506, 28.963863], [-95.387637, 28.89844], [-95.655863, 28.744598], [-95.732394, 28.711705], [-95.853419, 28.640349], [-96.020411, 28.586834], [-96.180531, 28.501877], [-96.234535, 28.48899], [-96.132291, 28.560896], [-96.011034, 28.631944], [-96.115031, 28.622232], [-96.27536, 28.655125], [-96.37344, 28.657037], [-96.374111, 28.631098], [-96.448735, 28.594481], [-96.526041, 28.648303], [-96.559708, 28.684448], [-96.575704, 28.715715], [-96.608515, 28.723307], [-96.64004, 28.708761], [-96.524645, 28.488704], [-96.475476, 28.47919], [-96.42111, 28.457339], [-96.488808, 28.406065], [-96.561697, 28.367163], [-96.676339, 28.34129], [-96.773546, 28.421622], [-96.794579, 28.320855], [-96.806901, 28.220188], [-96.839508, 28.194403], [-96.8916, 28.157555], [-96.919867, 28.185339], [-96.933276, 28.224275], [-96.966636, 28.189547], [-97.01547, 28.163454], [-97.096033, 28.158258], [-97.156491, 28.14436], [-97.155074, 28.102656], [-97.141275, 28.060765], [-97.034329, 28.093845], [-97.073088, 27.986091], [-97.171454, 27.879567], [-97.251578, 27.85442], [-97.37413, 27.870031], [-97.404386, 27.859309], [-97.431517, 27.837215], [-97.288733, 27.670608], [-97.380458, 27.419361], [-97.439109, 27.328285], [-97.47978, 27.316573], [-97.523863, 27.313969], [-97.682148, 27.394917], [-97.768446, 27.457495], [-97.692377, 27.287141], [-97.485103, 27.237406], [-97.474512, 27.172938], [-97.475671, 27.117885], [-97.516524, 27.053209], [-97.554712, 26.967351], [-97.526494, 26.907508], [-97.49381, 26.75961], [-97.465828, 26.691759], [-97.435082, 26.485853], [-97.402316, 26.396534], [-97.213933, 26.067867], [-97.150372, 26.065307], [-97.140187, 26.029733], [-97.146235, 25.961464], [-97.281785, 25.941623], [-97.33865, 25.91118], [-97.349735, 25.88478], [-97.358162, 25.87052], [-97.375624, 25.871805], [-97.440273, 25.890822], [-97.587243, 25.984206], [-97.801416, 26.042049], [-98.082792, 26.064428], [-98.275031, 26.111197], [-98.378121, 26.182356], [-98.48587, 26.224576], [-98.598293, 26.237858], [-98.691413, 26.276453], [-98.76523, 26.340405], [-98.873209, 26.38123], [-99.015268, 26.398962], [-99.107767, 26.446917], [-99.172081, 26.564141], [-99.172367, 26.565921], [-99.22993, 26.761928], [-99.302462, 26.884711], [-99.443537, 27.036674], [-99.456506, 27.056615], [-99.456534, 27.05667], [-99.45772, 27.081707], [-99.440258, 27.170125], [-99.455139, 27.233714], [-99.499814, 27.285515], [-99.51007, 27.340326], [-99.485834, 27.398048], [-99.484258, 27.467393], [-99.505319, 27.548341], [-99.595313, 27.63588], [-99.754269, 27.729934], [-99.889631, 27.867296], [-100.001412, 28.047845], [-100.111945, 28.172957], [-100.221265, 28.242622], [-100.296043, 28.327678], [-100.336275, 28.428137], [-100.348157, 28.48643], [-100.331727, 28.502547], [-100.398903, 28.614223], [-100.549695, 28.821338], [-100.636306, 28.972806], [-100.65863, 29.068541], [-100.754596, 29.182513], [-100.924142, 29.314701], [-101.016334, 29.400658], [-101.038631, 29.460291], [-101.038972, 29.460401], [-101.303528, 29.634084], [-101.380344, 29.742552], [-101.44039, 29.776841], [-101.509302, 29.773116], [-101.544623, 29.783531], [-101.546381, 29.808075], [-101.568705, 29.809239], [-101.611596, 29.78697], [-101.752336, 29.782476], [-101.990899, 29.795704], [-102.163087, 29.825257], [-102.268919, 29.871169], [-102.343076, 29.864973], [-102.385659, 29.806657], [-102.476247, 29.769084], [-102.614944, 29.752341], [-102.73419, 29.64395], [-102.834, 29.443966], [-102.877825, 29.315316], [-102.865679, 29.258033], [-102.892008, 29.216384], [-102.956811, 29.190368], [-103.022828, 29.132207], [-103.090009, 29.041866], [-103.168298, 28.998173], [-103.257699, 29.001129], [-103.422933, 29.070683], [-103.663979, 29.206903], [-103.852905, 29.29108], [-103.989746, 29.323171], [-104.110617, 29.386112], [-104.21552, 29.479902], [-104.312205, 29.542436], [-104.400623, 29.573747], [-104.503977, 29.677667], [-104.622212, 29.854272], [-104.68133, 29.990525], [-104.68133, 30.134358], [-104.835896, 30.447655], [-104.917854, 30.583358], [-104.978834, 30.645936], [-105.098151, 30.720555], [-105.275816, 30.80727], [-105.513994, 30.980766], [-105.812707, 31.241043], [-106.02409, 31.397774], [-106.148065, 31.450926], [-106.255703, 31.544662], [-106.346967, 31.678991], [-106.436027, 31.764465], [-106.445382, 31.768398], [-106.566358, 31.819529], [-106.566281, 31.819529], [-106.668262, 32.000946], [-106.662219, 32.001297], [-106.43745, 32.001407], [-106.212659, 32.001484], [-105.987868, 32.001561], [-105.763076, 32.00166], [-105.53828, 32.00177], [-105.313488, 32.001847], [-105.088697, 32.001924], [-104.863928, 32.002022], [-104.639164, 32.002132], [-104.414373, 32.002209], [-104.189576, 32.002286], [-103.964785, 32.002385], [-103.739993, 32.002495], [-103.515202, 32.002572], [-103.290405, 32.002649], [-103.065642, 32.002748], [-103.064169, 32.283866], [-103.062719, 32.564984], [-103.061247, 32.846113], [-103.059775, 33.127231], [-103.058303, 33.408349], [-103.056831, 33.689468], [-103.055358, 33.970586], [-103.053886, 34.251682], [-103.052414, 34.532778], [-103.050942, 34.813896], [-103.049492, 35.095015], [-103.04802, 35.376133], [-103.046547, 35.657251], [-103.045103, 35.93838], [-103.043625, 36.219498], [-103.042153, 36.500616], [-103.000295, 36.501232], [-102.812918, 36.50121], [-102.625562, 36.501188], [-102.438212, 36.501188], [-102.250835, 36.501155], [-102.063452, 36.501133], [-101.876102, 36.501133], [-101.688747, 36.501111], [-101.50137, 36.501078], [-101.313992, 36.501056], [-101.126637, 36.501023], [-100.939287, 36.500979], [-100.751904, 36.500979], [-100.564527, 36.500946], [-100.377177, 36.500924], [-100.189822, 36.500924], [-100.002444, 36.500902], [-100.002236, 36.381239], [-100.002054, 36.261609], [-100.001873, 36.141979], [-100.00167, 36.022349], [-100.001461, 35.902718], [-100.00128, 35.783088], [-100.001099, 35.663458], [-100.000895, 35.543828], [-100.000687, 35.424198], [-100.000505, 35.304568], [-100.000324, 35.184938], [-100.000115, 35.065275], [-99.999912, 34.945622], [-99.999731, 34.825992], [-99.99955, 34.706362], [-99.999341, 34.586721], [-99.94069, 34.576339], [-99.867027, 34.543369], [-99.685615, 34.415829], [-99.632029, 34.388495], [-99.536168, 34.404744], [-99.432298, 34.38922], [-99.404986, 34.392065], [-99.38465, 34.446788], [-99.374938, 34.457873], [-99.360387, 34.456094], [-99.270316, 34.407226], [-99.252875, 34.388077], [-99.19991, 34.318314], [-99.186578, 34.235477], [-99.157508, 34.223282], [-99.102291, 34.213472], [-98.96884, 34.208605], [-98.798953, 34.154739], [-98.730118, 34.146576], [-98.608395, 34.161275], [-98.493851, 34.088777], [-98.453674, 34.078131], [-98.420419, 34.088052], [-98.355978, 34.141511], [-98.214079, 34.135337], [-98.098635, 34.145027], [-98.089587, 34.084097], [-98.069383, 34.040305], [-97.973962, 33.993734], [-97.951072, 33.971212], [-97.946238, 33.897076], [-97.92159, 33.878367], [-97.882858, 33.871116], [-97.842422, 33.875785], [-97.795291, 33.899065], [-97.691937, 33.972135], [-97.660362, 33.990043], [-97.640933, 33.991669], [-97.621789, 33.987768], [-97.605925, 33.971651], [-97.571247, 33.91594], [-97.481565, 33.885705], [-97.430171, 33.838508], [-97.398492, 33.831323], [-97.363611, 33.840178], [-97.308163, 33.869226], [-97.264679, 33.867776], [-97.214938, 33.897109], [-97.194762, 33.890616], [-97.186182, 33.870083], [-97.201013, 33.808164], [-97.192488, 33.784631], [-97.172383, 33.75688], [-97.145071, 33.737687], [-97.119, 33.734764], [-97.09895, 33.750442], [-97.061229, 33.8285], [-97.063838, 33.8568], [-97.02159, 33.866512], [-97.002161, 33.881597], [-96.977694, 33.938033], [-96.934051, 33.95348], [-96.911001, 33.950437], [-96.889996, 33.934617], [-96.847572, 33.883179], [-96.746283, 33.854186], [-96.720213, 33.85279], [-96.694016, 33.863799], [-96.648538, 33.906382], [-96.625132, 33.911446], [-96.606345, 33.905635], [-96.595364, 33.899405], [-96.59159, 33.849275], [-96.487204, 33.7923], [-96.41114, 33.775205], [-96.336752, 33.717713], [-96.315048, 33.711122], [-96.278562, 33.757627], [-96.207272, 33.774062], [-96.139344, 33.821963], [-95.941579, 33.882838], [-95.863082, 33.863304], [-95.783914, 33.864502], [-95.763166, 33.891473], [-95.622789, 33.930255], [-95.594471, 33.945163], [-95.555712, 33.926091], [-95.541836, 33.898164], [-95.523494, 33.886562], [-95.427117, 33.872785], [-95.373888, 33.874269], [-95.276016, 33.910622], [-95.238031, 33.956479], [-95.21586, 33.959039], [-95.146075, 33.936616], [-94.962389, 33.843408], [-94.869374, 33.768196], [-94.765734, 33.731611], [-94.709198, 33.699289], [-94.484149, 33.648434]]], [[[-95.039695, 29.145918], [-95.089666, 29.136305], [-94.87167, 29.290146], [-94.825989, 29.341309], [-94.767618, 29.339035], [-94.864952, 29.252892], [-95.039695, 29.145918]]], [[[-96.7644, 28.152567], [-96.801116, 28.148414], [-96.755611, 28.202434], [-96.68164, 28.229702], [-96.519322, 28.333468], [-96.453124, 28.340598], [-96.418633, 28.376325], [-96.403565, 28.381577], [-96.413332, 28.337807], [-96.543893, 28.275592], [-96.7644, 28.152567]]], [[[-97.014355, 27.901628], [-97.036009, 27.899178], [-96.987642, 27.981026], [-96.978672, 28.013842], [-96.899301, 28.117454], [-96.857416, 28.132912], [-96.839766, 28.088802], [-96.92134, 28.01604], [-97.014355, 27.901628]]], [[[-97.353613, 27.300061], [-97.384825, 27.242525], [-97.376223, 27.328252], [-97.29504, 27.523072], [-97.130008, 27.77913], [-97.060558, 27.822021], [-97.250907, 27.541189], [-97.353613, 27.300061]]], [[[-97.170702, 26.159383], [-97.184501, 26.112933], [-97.267316, 26.329759], [-97.402085, 26.820507], [-97.407177, 27.100208], [-97.38599, 27.196503], [-97.351235, 26.801468], [-97.202227, 26.299788], [-97.170702, 26.159383]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3526", "diss_me": 3526, "iso_3166_2": "US-UT", "wikipedia": "http://en.wikipedia.org/wiki/Utah", "iso_a2": "US", "adm0_sr": 1, "name": "Utah", "name_alt": "UT", "name_local": null, "type": "State", "type_en": "State", "code_local": "US49", "code_hasc": "US.UT", "note": null, "hasc_maybe": null, "region": "West", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Utah", "postal": "UT", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 4, "mapcolor9": 1, "mapcolor13": 1, "fips": "US49", "fips_alt": null, "woe_id": 2347603, "woe_label": "Utah, US, United States", "woe_name": "Utah", "latitude": 39.5007, "longitude": -111.544, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5549030, "gn_name": "Utah", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.UT", "region_sub": "Mountain", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q829", "name_ar": "\u064a\u0648\u062a\u0627", "name_bn": "\u0987\u0989\u099f\u09be", "name_de": "Utah", "name_en": "Utah", "name_es": "Utah", "name_fr": "Utah", "name_el": "\u0393\u03b9\u03bf\u03cd\u03c4\u03b1", "name_hi": "\u092f\u0942\u091f\u093e\u0939", "name_hu": "Utah", "name_id": "Utah", "name_it": "Utah", "name_ja": "\u30e6\u30bf\u5dde", "name_ko": "\uc720\ud0c0", "name_nl": "Utah", "name_pl": "Utah", "name_pt": "Utah", "name_ru": "\u042e\u0442\u0430", "name_sv": "Utah", "name_tr": "Utah", "name_vi": "Utah", "name_zh": "\u72b9\u4ed6\u5dde", "ne_id": 1159315349, "name_he": "\u05d9\u05d5\u05d8\u05d4", "name_uk": "\u042e\u0442\u0430", "name_ur": "\u06cc\u0648\u0679\u0627\u06c1", "name_fa": "\u06cc\u0648\u062a\u0627", "name_zht": "\u7336\u4ed6\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-114.042593, 37.000846, -109.04639, 42.001109], "geometry": {"type": "Polygon", "coordinates": [[[-109.04667, 37.000846], [-109.35877, 37.001055], [-109.67087, 37.001252], [-109.982969, 37.001461], [-110.295069, 37.00167], [-110.607168, 37.001879], [-110.919268, 37.002087], [-111.231373, 37.002285], [-111.543473, 37.002494], [-111.855572, 37.002703], [-112.167672, 37.002911], [-112.479772, 37.00312], [-112.791871, 37.003318], [-113.103971, 37.003527], [-113.41607, 37.003735], [-113.72817, 37.003944], [-114.04027, 37.004153], [-114.040347, 37.160312], [-114.040396, 37.316461], [-114.040473, 37.472599], [-114.040555, 37.628759], [-114.040632, 37.784929], [-114.040709, 37.941067], [-114.040786, 38.097205], [-114.040863, 38.253375], [-114.04094, 38.409546], [-114.041017, 38.565684], [-114.041072, 38.721821], [-114.041149, 38.877992], [-114.041226, 39.034152], [-114.041275, 39.190322], [-114.041352, 39.346493], [-114.041429, 39.502631], [-114.041511, 39.658768], [-114.041588, 39.814939], [-114.041637, 39.971099], [-114.041714, 40.127269], [-114.041791, 40.283429], [-114.041846, 40.439578], [-114.041923, 40.595715], [-114.042, 40.751875], [-114.042077, 40.908046], [-114.042154, 41.064183], [-114.042231, 41.220321], [-114.042308, 41.376492], [-114.04239, 41.532662], [-114.042467, 41.6888], [-114.042516, 41.844938], [-114.042593, 42.001109], [-113.855551, 42.001109], [-113.668536, 42.001076], [-113.481516, 42.001054], [-113.294501, 42.001054], [-113.107481, 42.001054], [-112.920466, 42.001032], [-112.733451, 42.000999], [-112.546431, 42.000999], [-112.359416, 42.000999], [-112.172396, 42.000977], [-111.985381, 42.000955], [-111.798367, 42.000955], [-111.611346, 42.000922], [-111.424331, 42.0009], [-111.237311, 42.0009], [-111.050296, 42.000878], [-111.050247, 41.875897], [-111.05022, 41.750884], [-111.050192, 41.625881], [-111.050143, 41.500879], [-111.050088, 41.375877], [-111.050066, 41.250863], [-111.050038, 41.125861], [-111.049989, 41.000858], [-110.799539, 41.000858], [-110.549089, 41.000858], [-110.298639, 41.000858], [-110.048189, 41.000858], [-109.79774, 41.000858], [-109.54729, 41.000858], [-109.29684, 41.000858], [-109.04639, 41.000858], [-109.046412, 40.750842], [-109.04644, 40.500859], [-109.04644, 40.250877], [-109.046467, 40.000872], [-109.046489, 39.750856], [-109.046489, 39.50084], [-109.046516, 39.250835], [-109.046544, 39.000819], [-109.046544, 38.750869], [-109.046566, 38.500853], [-109.046593, 38.250848], [-109.046593, 38.000833], [-109.046621, 37.750828], [-109.046648, 37.500834], [-109.046648, 37.250851], [-109.04667, 37.000846]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3552", "diss_me": 3552, "iso_3166_2": "US-VA", "wikipedia": "http://en.wikipedia.org/wiki/Virginia", "iso_a2": "US", "adm0_sr": 6, "name": "Virginia", "name_alt": "VA", "name_local": null, "type": "State", "type_en": "State", "code_local": "US51", "code_hasc": "US.VA", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Va.", "postal": "VA", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 8, "mapcolor9": 1, "mapcolor13": 1, "fips": "US51", "fips_alt": null, "woe_id": 2347605, "woe_label": "Virginia, US, United States", "woe_name": "Virginia", "latitude": 37.7403, "longitude": -78.2431, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 6254928, "gn_name": "Virginia", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.VA", "region_sub": "South Atlantic", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1370", "name_ar": "\u0641\u0631\u062c\u064a\u0646\u064a\u0627", "name_bn": "\u09ad\u09be\u09b0\u09cd\u099c\u09bf\u09a8\u09bf\u09af\u09bc\u09be", "name_de": "Virginia", "name_en": "Virginia", "name_es": "Virginia", "name_fr": "Virginie", "name_el": "\u0392\u03b9\u03c1\u03c4\u03b6\u03af\u03bd\u03b9\u03b1", "name_hi": "\u0935\u0930\u094d\u091c\u0940\u0928\u093f\u092f\u093e", "name_hu": "Virginia", "name_id": "Virginia", "name_it": "Virginia", "name_ja": "\u30d0\u30fc\u30b8\u30cb\u30a2\u5dde", "name_ko": "\ubc84\uc9c0\ub2c8\uc544", "name_nl": "Virginia", "name_pl": "Wirginia", "name_pt": "Virg\u00ednia", "name_ru": "\u0412\u0438\u0440\u0433\u0438\u043d\u0438\u044f", "name_sv": "Virginia", "name_tr": "Virjinya", "name_vi": "Virginia", "name_zh": "\u5f17\u5409\u5c3c\u4e9a\u5dde", "ne_id": 1159315259, "name_he": "\u05d5\u05d9\u05e8\u05d2'\u05d9\u05e0\u05d9\u05d4", "name_uk": "\u0412\u0456\u0440\u0434\u0436\u0438\u043d\u0456\u044f", "name_ur": "\u0648\u0631\u062c\u06cc\u0646\u06cc\u0627", "name_fa": "\u0648\u06cc\u0631\u062c\u06cc\u0646\u06cc\u0627", "name_zht": "\u7dad\u5409\u5c3c\u4e9e\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-83.667521, 36.550505, -75.225791, 39.451852], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-77.122053, 38.943536], [-77.101827, 38.935967], [-77.053048, 38.915302], [-77.030361, 38.889253], [-77.045599, 38.775797], [-77.091906, 38.719547], [-77.164669, 38.67658], [-77.260393, 38.599994], [-77.283805, 38.52922], [-77.313698, 38.396626], [-77.273258, 38.351769], [-77.231916, 38.340035], [-77.109913, 38.370138], [-77.046764, 38.35668], [-76.906336, 38.197048], [-76.644873, 38.133954], [-76.549511, 38.094502], [-76.471761, 38.011171], [-76.354944, 37.963215], [-76.264284, 37.893551], [-76.261801, 37.848079], [-76.293222, 37.794333], [-76.305626, 37.721571], [-76.344144, 37.675681], [-76.436616, 37.670419], [-76.492481, 37.682218], [-76.792804, 37.937991], [-76.828641, 37.961512], [-76.939977, 38.095458], [-77.070637, 38.167209], [-77.1111, 38.165682], [-76.925123, 38.033022], [-76.849175, 37.940243], [-76.715416, 37.810176], [-76.619835, 37.75509], [-76.549457, 37.669144], [-76.484055, 37.628868], [-76.305571, 37.571509], [-76.367633, 37.530288], [-76.268569, 37.495154], [-76.254408, 37.430631], [-76.263482, 37.357023], [-76.400987, 37.386147], [-76.405459, 37.331908], [-76.393132, 37.299949], [-76.45393, 37.273538], [-76.538393, 37.309353], [-76.757691, 37.505437], [-76.755879, 37.479213], [-76.738103, 37.44877], [-76.610903, 37.322581], [-76.497392, 37.246874], [-76.401119, 37.212695], [-76.326939, 37.14926], [-76.300759, 37.110885], [-76.283302, 37.052679], [-76.338277, 37.013118], [-76.400888, 36.991332], [-76.462016, 37.030784], [-76.506852, 37.072312], [-76.602301, 37.142844], [-76.630898, 37.221704], [-76.703507, 37.217672], [-77.006971, 37.31767], [-77.25089, 37.329194], [-77.22706, 37.309067], [-77.196211, 37.295708], [-77.001961, 37.271055], [-76.925167, 37.225011], [-76.765415, 37.184142], [-76.671855, 37.172947], [-76.633919, 37.047428], [-76.504632, 36.96102], [-76.487856, 36.897025], [-76.399548, 36.88984], [-76.244256, 36.952627], [-76.144006, 36.93061], [-75.999415, 36.912659], [-75.966335, 36.861957], [-75.941561, 36.76553], [-75.890431, 36.657018], [-75.857428, 36.550582], [-75.889057, 36.550505], [-75.966445, 36.551362], [-76.214824, 36.552889], [-76.576615, 36.555702], [-76.938395, 36.558514], [-77.300185, 36.561338], [-77.661976, 36.56415], [-78.023756, 36.566963], [-78.385547, 36.569753], [-78.747337, 36.572577], [-79.109117, 36.575389], [-79.470908, 36.57818], [-79.832688, 36.580992], [-80.194479, 36.583816], [-80.556269, 36.586628], [-80.918049, 36.589452], [-81.27984, 36.592264], [-81.641631, 36.595077], [-81.65889, 36.610579], [-81.800713, 36.615182], [-81.905336, 36.618544], [-81.952511, 36.598021], [-82.162185, 36.598856], [-82.329386, 36.599548], [-82.611779, 36.600713], [-82.955837, 36.60213], [-83.440763, 36.604119], [-83.667521, 36.60503], [-83.566183, 36.652623], [-83.41689, 36.681012], [-83.150218, 36.762333], [-83.043816, 36.845554], [-82.894501, 36.906374], [-82.832021, 36.979269], [-82.731892, 37.048076], [-82.69489, 37.126156], [-82.681586, 37.13812], [-82.516505, 37.208839], [-82.343207, 37.296927], [-81.965277, 37.539725], [-81.957707, 37.507634], [-81.971396, 37.47306], [-81.939382, 37.432598], [-81.913059, 37.368965], [-81.87564, 37.329612], [-81.829266, 37.298597], [-81.752164, 37.270769], [-81.660769, 37.221759], [-81.589017, 37.20807], [-81.564836, 37.209795], [-81.485537, 37.257003], [-81.419366, 37.282272], [-81.350043, 37.333688], [-81.227128, 37.263276], [-81.178118, 37.263331], [-81.057345, 37.293719], [-80.94368, 37.301904], [-80.915369, 37.311363], [-80.873071, 37.34062], [-80.871852, 37.399419], [-80.862425, 37.414569], [-80.843485, 37.421721], [-80.821084, 37.423094], [-80.77003, 37.401594], [-80.719845, 37.401023], [-80.507402, 37.469061], [-80.491417, 37.46392], [-80.464512, 37.432729], [-80.371183, 37.472599], [-80.316075, 37.5097], [-80.291971, 37.565895], [-80.245818, 37.620782], [-80.255376, 37.645271], [-80.285303, 37.677054], [-80.245928, 37.751025], [-80.188074, 37.824227], [-79.971731, 38.046151], [-79.902693, 38.180745], [-79.812879, 38.267042], [-79.783447, 38.336036], [-79.715255, 38.404042], [-79.668651, 38.54426], [-79.639603, 38.572451], [-79.597745, 38.577131], [-79.555272, 38.559377], [-79.524675, 38.533461], [-79.504834, 38.49135], [-79.395871, 38.454392], [-79.304169, 38.449899], [-79.240272, 38.476519], [-79.20294, 38.525814], [-79.152502, 38.618319], [-79.104239, 38.672932], [-79.073313, 38.741948], [-79.041189, 38.789673], [-78.991992, 38.819699], [-78.868725, 38.817941], [-78.805499, 38.860183], [-78.756786, 38.908215], [-78.727309, 38.923882], [-78.692757, 38.921652], [-78.581477, 38.999017], [-78.435238, 39.160758], [-78.403707, 39.262645], [-78.365782, 39.335847], [-78.35105, 39.410928], [-78.322221, 39.451852], [-78.193, 39.370388], [-78.118348, 39.323334], [-77.948598, 39.216316], [-77.835791, 39.145212], [-77.791758, 39.226621], [-77.726642, 39.346438], [-77.668821, 39.309535], [-77.53415, 39.265612], [-77.478856, 39.220864], [-77.502938, 39.175282], [-77.506454, 39.14262], [-77.480921, 39.112957], [-77.301086, 39.053378], [-77.1903, 38.969047], [-77.122053, 38.943536]]], [[[-75.659256, 37.953965], [-75.620002, 37.999207], [-75.469424, 38.014939], [-75.375963, 38.024991], [-75.59636, 37.631187], [-75.587109, 37.558721], [-75.631549, 37.535331], [-75.69884, 37.516368], [-75.766867, 37.473005], [-75.812054, 37.425215], [-75.854, 37.296642], [-75.934376, 37.151897], [-75.984507, 37.212201], [-75.997372, 37.263826], [-75.975047, 37.398441], [-75.888156, 37.619156], [-75.792367, 37.756354], [-75.719351, 37.821382], [-75.659256, 37.953965]]], [[[-75.252476, 38.03745], [-75.225791, 38.040339], [-75.225846, 38.040262], [-75.33305, 37.888278], [-75.378545, 37.872051], [-75.252476, 38.03745]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3540", "diss_me": 3540, "iso_3166_2": "US-VT", "wikipedia": "http://en.wikipedia.org/wiki/Vermont", "iso_a2": "US", "adm0_sr": 1, "name": "Vermont", "name_alt": "VT", "name_local": null, "type": "State", "type_en": "State", "code_local": "US50", "code_hasc": "US.VT", "note": null, "hasc_maybe": null, "region": "Northeast", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Vt.", "postal": "VT", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 7, "mapcolor9": 1, "mapcolor13": 1, "fips": "US50", "fips_alt": null, "woe_id": 2347604, "woe_label": "Vermont, US, United States", "woe_name": "Vermont", "latitude": 44.0886, "longitude": -72.7317, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5242283, "gn_name": "Vermont", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.VT", "region_sub": "New England", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q16551", "name_ar": "\u0641\u064a\u0631\u0645\u0648\u0646\u062a", "name_bn": "\u09ad\u09be\u09b0\u09cd\u09ae\u09a8\u09cd\u099f", "name_de": "Vermont", "name_en": "Vermont", "name_es": "Vermont", "name_fr": "Vermont", "name_el": "\u0392\u03b5\u03c1\u03bc\u03cc\u03bd\u03c4", "name_hi": "\u0935\u0930\u094d\u092e\u093e\u0902\u091f", "name_hu": "Vermont", "name_id": "Vermont", "name_it": "Vermont", "name_ja": "\u30d0\u30fc\u30e2\u30f3\u30c8\u5dde", "name_ko": "\ubc84\ubaac\ud2b8", "name_nl": "Vermont", "name_pl": "Vermont", "name_pt": "Vermont", "name_ru": "\u0412\u0435\u0440\u043c\u043e\u043d\u0442", "name_sv": "Vermont", "name_tr": "Vermont", "name_vi": "Vermont", "name_zh": "\u4f5b\u8499\u7279\u5dde", "ne_id": 1159315305, "name_he": "\u05d5\u05e8\u05de\u05d5\u05e0\u05d8", "name_uk": "\u0412\u0435\u0440\u043c\u043e\u043d\u0442", "name_ur": "\u0648\u0631\u0645\u0648\u0646\u0679", "name_fa": "\u0648\u0631\u0645\u0648\u0646\u062a", "name_zht": "\u4f5b\u8499\u7279\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-73.426131, 42.730315, -71.510225, 45.007561], "geometry": {"type": "Polygon", "coordinates": [[[-73.352182, 45.005419], [-73.182015, 45.005628], [-72.765886, 45.006111], [-72.349768, 45.006605], [-71.933638, 45.007067], [-71.51752, 45.007561], [-71.533483, 44.987973], [-71.510225, 44.908344], [-71.62066, 44.771894], [-71.618287, 44.727761], [-71.568442, 44.607637], [-71.571496, 44.579193], [-71.5878, 44.565263], [-71.609289, 44.514055], [-71.638205, 44.481679], [-71.683007, 44.45028], [-71.825511, 44.37409], [-71.867677, 44.354918], [-72.001776, 44.329496], [-72.031208, 44.300734], [-72.062233, 44.11635], [-72.106212, 44.013079], [-72.114924, 43.965431], [-72.173855, 43.884088], [-72.222381, 43.790869], [-72.296693, 43.714954], [-72.337672, 43.621988], [-72.362369, 43.586645], [-72.384957, 43.52923], [-72.407072, 43.332036], [-72.438186, 43.224645], [-72.473715, 43.038537], [-72.496479, 42.991669], [-72.519419, 42.966675], [-72.549807, 42.886684], [-72.552806, 42.856449], [-72.539622, 42.829632], [-72.483658, 42.766174], [-72.46686, 42.730315], [-72.565177, 42.733051], [-72.663493, 42.735786], [-72.761777, 42.738533], [-72.860094, 42.741268], [-72.95841, 42.744004], [-73.056694, 42.74674], [-73.155011, 42.749486], [-73.253327, 42.752222], [-73.2802, 42.813152], [-73.266555, 42.864777], [-73.264544, 42.93521], [-73.26193, 43.027067], [-73.259084, 43.127855], [-73.255239, 43.265371], [-73.252657, 43.357195], [-73.250328, 43.439669], [-73.247098, 43.553048], [-73.30616, 43.616253], [-73.330484, 43.62669], [-73.349238, 43.620384], [-73.391436, 43.578526], [-73.40495, 43.578811], [-73.415925, 43.589644], [-73.413365, 43.627854], [-73.375847, 43.762184], [-73.374968, 43.804152], [-73.38301, 43.875827], [-73.424945, 44.038292], [-73.426131, 44.074855], [-73.409751, 44.131413], [-73.38112, 44.187432], [-73.331825, 44.244583], [-73.320915, 44.268874], [-73.324639, 44.36786], [-73.309753, 44.45964], [-73.372078, 44.597332], [-73.348568, 44.775299], [-73.365805, 44.860366], [-73.345052, 44.938864], [-73.352182, 45.005419]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3519", "diss_me": 3519, "iso_3166_2": "US-WA", "wikipedia": "http://en.wikipedia.org/wiki/Washington_(state)", "iso_a2": "US", "adm0_sr": 6, "name": "Washington", "name_alt": "WA|Wash.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US53", "code_hasc": "US.WA", "note": null, "hasc_maybe": null, "region": "West", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Wash.", "postal": "WA", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 10, "mapcolor9": 1, "mapcolor13": 1, "fips": "US53", "fips_alt": null, "woe_id": 2347606, "woe_label": "Washington, US, United States", "woe_name": "Washington", "latitude": 47.4865, "longitude": -120.361, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5815135, "gn_name": "Washington", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.WA", "region_sub": "Pacific", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1223", "name_ar": "\u0648\u0627\u0634\u0646\u0637\u0646", "name_bn": "\u0993\u09af\u09bc\u09be\u09b6\u09bf\u0982\u099f\u09a8", "name_de": "Washington", "name_en": "Washington", "name_es": "Washington", "name_fr": "Washington", "name_el": "\u039f\u03c5\u03ac\u03c3\u03b9\u03bd\u03b3\u03ba\u03c4\u03bf\u03bd", "name_hi": "\u0935\u0949\u0936\u093f\u0902\u0917\u091f\u0928 \u0930\u093e\u091c\u094d\u092f", "name_hu": "Washington", "name_id": "Washington", "name_it": "Washington", "name_ja": "\u30ef\u30b7\u30f3\u30c8\u30f3\u5dde", "name_ko": "\uc6cc\uc2f1\ud134", "name_nl": "Washington", "name_pl": "Waszyngton", "name_pt": "Washington", "name_ru": "\u0412\u0430\u0448\u0438\u043d\u0433\u0442\u043e\u043d", "name_sv": "Washington", "name_tr": "Va\u015fington", "name_vi": "Washington", "name_zh": "\u534e\u76db\u987f\u5dde", "ne_id": 1159309547, "name_he": "\u05d5\u05d5\u05e9\u05d9\u05e0\u05d2\u05d8\u05d5\u05df", "name_uk": "\u0412\u0430\u0448\u0438\u043d\u0433\u0442\u043e\u043d", "name_ur": "\u0631\u06cc\u0627\u0633\u062a \u0648\u0627\u0634\u0646\u06af\u0679\u0646", "name_fa": "\u0627\u06cc\u0627\u0644\u062a \u0648\u0627\u0634\u06cc\u0646\u06af\u062a\u0646", "name_zht": "\u83ef\u76db\u9813\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-124.709978, 45.591067, -116.896479, 48.993083], "geometry": {"type": "MultiPolygon", "coordinates": [[[[-122.788777, 48.993028], [-122.686384, 48.993028], [-122.259999, 48.993028], [-121.83362, 48.993028], [-121.407235, 48.993028], [-120.980855, 48.993028], [-120.55447, 48.993028], [-120.128091, 48.993028], [-119.701706, 48.993028], [-119.275321, 48.993061], [-118.848942, 48.993083], [-118.422557, 48.993083], [-117.996177, 48.993083], [-117.569793, 48.993083], [-117.143413, 48.993083], [-117.039054, 48.993083], [-117.037373, 48.83366], [-117.036544, 48.673359], [-117.03572, 48.513057], [-117.034918, 48.352756], [-117.034116, 48.192454], [-117.033292, 48.032163], [-117.032462, 47.871862], [-117.031638, 47.71156], [-117.030809, 47.551259], [-117.029985, 47.390957], [-117.029155, 47.230656], [-117.028331, 47.070354], [-117.027502, 46.910053], [-117.026678, 46.749751], [-117.025848, 46.589461], [-117.025046, 46.429159], [-117.032462, 46.419755], [-117.038999, 46.396552], [-117.010396, 46.329623], [-116.942962, 46.232108], [-116.92211, 46.163642], [-116.947845, 46.124322], [-116.930196, 46.055954], [-116.896479, 46.002099], [-117.14432, 46.002253], [-117.409755, 46.002022], [-117.675217, 46.001791], [-117.940653, 46.001538], [-118.206088, 46.001275], [-118.47155, 46.001044], [-118.736986, 46.000813], [-119.002421, 46.00055], [-119.01968, 46.000341], [-119.049909, 45.981488], [-119.177345, 45.94508], [-119.429113, 45.93417], [-119.934276, 45.837875], [-120.156046, 45.762168], [-120.351432, 45.725166], [-120.715777, 45.689823], [-121.045241, 45.639044], [-121.184278, 45.64378], [-121.242698, 45.687033], [-121.402121, 45.71184], [-121.662519, 45.718135], [-121.882014, 45.689461], [-122.085124, 45.602647], [-122.149905, 45.593858], [-122.149927, 45.593759], [-122.202535, 45.591067], [-122.560964, 45.62507], [-122.649849, 45.627443], [-122.725913, 45.67375], [-122.74643, 45.749688], [-122.843373, 45.978094], [-122.941997, 46.114862], [-123.042275, 46.160027], [-123.120904, 46.178781], [-123.220589, 46.153622], [-123.251334, 46.167256], [-123.298696, 46.170849], [-123.404736, 46.221001], [-123.464859, 46.271099], [-123.65033, 46.267715], [-123.688365, 46.299861], [-123.895715, 46.26777], [-123.959743, 46.30074], [-124.07276, 46.279449], [-124.045135, 46.372876], [-124.050172, 46.490551], [-124.04436, 46.605061], [-124.016405, 46.521368], [-123.946126, 46.432565], [-123.912381, 46.533332], [-123.889151, 46.660015], [-123.957727, 46.708695], [-124.0717, 46.744796], [-124.112547, 46.862669], [-123.842876, 46.963183], [-123.986017, 46.984496], [-124.042218, 47.029683], [-124.111695, 47.035187], [-124.116787, 47.000338], [-124.139238, 46.954701], [-124.163551, 47.015324], [-124.170505, 47.086691], [-124.19885, 47.20854], [-124.309279, 47.404602], [-124.376021, 47.658639], [-124.460044, 47.784213], [-124.621071, 47.904129], [-124.663083, 47.974123], [-124.701661, 48.15164], [-124.67998, 48.285893], [-124.709978, 48.380375], [-124.632618, 48.375036], [-124.429041, 48.300768], [-124.175515, 48.242431], [-124.098775, 48.200002], [-123.975761, 48.168482], [-123.294433, 48.119549], [-123.249911, 48.124196], [-123.161883, 48.154551], [-123.124392, 48.150915], [-123.024219, 48.081613], [-122.973885, 48.073296], [-122.908901, 48.076889], [-122.860891, 48.090039], [-122.778598, 48.137577], [-122.767512, 48.12001], [-122.769089, 48.075977], [-122.739739, 48.013245], [-122.679485, 47.931803], [-122.656644, 47.881134], [-122.778444, 47.738433], [-122.801773, 47.735335], [-122.805366, 47.783642], [-122.821384, 47.793156], [-123.050647, 47.551929], [-123.131034, 47.437726], [-123.139043, 47.386101], [-123.136356, 47.355823], [-123.10421, 47.348374], [-123.03091, 47.360185], [-122.922156, 47.407646], [-122.916883, 47.417984], [-123.01822, 47.401065], [-123.066775, 47.399637], [-123.060133, 47.453645], [-123.048636, 47.47932], [-122.98246, 47.559367], [-122.912906, 47.607355], [-122.814051, 47.65854], [-122.757152, 47.70053], [-122.717876, 47.762098], [-122.608145, 47.835475], [-122.587913, 47.855943], [-122.592665, 47.916401], [-122.585716, 47.927881], [-122.532801, 47.919707], [-122.510811, 47.815733], [-122.523913, 47.769338], [-122.618428, 47.712802], [-122.630183, 47.692796], [-122.613621, 47.615617], [-122.628272, 47.608157], [-122.66429, 47.617254], [-122.67548, 47.612343], [-122.585821, 47.528418], [-122.557448, 47.463203], [-122.553548, 47.40491], [-122.577888, 47.29319], [-122.603904, 47.274612], [-122.648657, 47.281457], [-122.707697, 47.316393], [-122.720876, 47.305121], [-122.767798, 47.218362], [-122.7833, 47.225954], [-122.812551, 47.328951], [-122.828465, 47.336597], [-122.919519, 47.289674], [-122.956186, 47.244554], [-122.987629, 47.172571], [-123.027575, 47.138909], [-122.914147, 47.131493], [-122.811958, 47.146006], [-122.729868, 47.111806], [-122.701935, 47.110872], [-122.627058, 47.144259], [-122.60414, 47.167023], [-122.542177, 47.275568], [-122.51107, 47.294992], [-122.464872, 47.295827], [-122.420119, 47.312098], [-122.353817, 47.371578], [-122.351131, 47.39522], [-122.375262, 47.528363], [-122.368341, 47.603916], [-122.380744, 47.627845], [-122.410506, 47.652652], [-122.406787, 47.676778], [-122.383634, 47.716471], [-122.38198, 47.752331], [-122.401827, 47.784268], [-122.392884, 47.820545], [-122.330306, 47.898625], [-122.318474, 47.933045], [-122.242014, 48.010762], [-122.261268, 48.042029], [-122.31749, 48.080163], [-122.352965, 48.113803], [-122.388649, 48.166361], [-122.415802, 48.183929], [-122.424695, 48.17592], [-122.386633, 48.08993], [-122.394774, 48.084151], [-122.494019, 48.130447], [-122.517013, 48.159649], [-122.529159, 48.199331], [-122.52032, 48.229093], [-122.467042, 48.258504], [-122.403376, 48.269194], [-122.408545, 48.293902], [-122.48841, 48.374311], [-122.541661, 48.41095], [-122.582591, 48.428671], [-122.63778, 48.433318], [-122.662483, 48.446392], [-122.668993, 48.465256], [-122.657265, 48.490008], [-122.627964, 48.497918], [-122.542694, 48.487975], [-122.496754, 48.505542], [-122.501094, 48.537502], [-122.514816, 48.555146], [-122.512723, 48.669436], [-122.545122, 48.762293], [-122.562024, 48.777981], [-122.580163, 48.779585], [-122.599438, 48.767105], [-122.653024, 48.763875], [-122.685944, 48.794285], [-122.72248, 48.85304], [-122.788777, 48.993028]]], [[[-123.086435, 48.993028], [-123.049202, 48.993028], [-123.063259, 48.977735], [-123.077316, 48.980218], [-123.086435, 48.993028]]], [[[-122.782141, 48.672688], [-122.768831, 48.650979], [-122.808958, 48.629853], [-122.837611, 48.626546], [-122.883089, 48.660647], [-122.903034, 48.664679], [-122.887016, 48.61233], [-122.892542, 48.594499], [-122.985668, 48.6267], [-123.002851, 48.652199], [-122.976676, 48.679148], [-122.91802, 48.706999], [-122.897711, 48.710361], [-122.782141, 48.672688]]], [[[-123.013134, 48.500862], [-122.98675, 48.468002], [-123.094444, 48.489085], [-123.139922, 48.507948], [-123.153435, 48.52634], [-123.169585, 48.586698], [-123.162141, 48.606386], [-123.114186, 48.613263], [-123.024164, 48.538479], [-123.013134, 48.500862]]], [[[-122.820923, 48.431363], [-122.836578, 48.421541], [-122.890037, 48.43467], [-122.921612, 48.456939], [-122.932285, 48.484745], [-122.912235, 48.537963], [-122.885517, 48.551608], [-122.868905, 48.548609], [-122.861902, 48.501851], [-122.814616, 48.452336], [-122.820923, 48.431363]]], [[[-122.572769, 48.15665], [-122.523836, 48.02544], [-122.502852, 48.080064], [-122.366737, 47.985439], [-122.366583, 47.938835], [-122.383145, 47.923201], [-122.41144, 47.917752], [-122.437588, 47.931342], [-122.461615, 47.963993], [-122.492261, 47.981308], [-122.557525, 47.99247], [-122.591347, 48.029626], [-122.603184, 48.055048], [-122.60631, 48.12859], [-122.622663, 48.151431], [-122.657265, 48.156496], [-122.690388, 48.173854], [-122.741519, 48.22527], [-122.748704, 48.239025], [-122.724517, 48.280927], [-122.668993, 48.350998], [-122.628634, 48.384231], [-122.60352, 48.380617], [-122.572461, 48.359578], [-122.535564, 48.321214], [-122.542436, 48.294001], [-122.692146, 48.24109], [-122.697002, 48.228687], [-122.624394, 48.213746], [-122.597625, 48.200419], [-122.572769, 48.15665]]], [[[-122.497271, 47.594589], [-122.502649, 47.57544], [-122.557838, 47.598313], [-122.575922, 47.619473], [-122.573752, 47.666857], [-122.560113, 47.697762], [-122.549774, 47.703958], [-122.517216, 47.690577], [-122.507867, 47.682644], [-122.497271, 47.594589]]], [[[-122.394126, 47.395242], [-122.398723, 47.372511], [-122.437121, 47.354812], [-122.456962, 47.359328], [-122.458203, 47.386156], [-122.468542, 47.390232], [-122.509932, 47.357987], [-122.506834, 47.421675], [-122.486471, 47.48878], [-122.468591, 47.489966], [-122.442081, 47.446153], [-122.394126, 47.395242]]], [[[-122.85309, 47.204717], [-122.862627, 47.185074], [-122.876733, 47.186117], [-122.907973, 47.226108], [-122.9119, 47.25432], [-122.885105, 47.274711], [-122.84919, 47.216297], [-122.85309, 47.204717]]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3553", "diss_me": 3553, "iso_3166_2": "US-WI", "wikipedia": "http://en.wikipedia.org/wiki/Wisconsin", "iso_a2": "US", "adm0_sr": 1, "name": "Wisconsin", "name_alt": "WI|Wis.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US55", "code_hasc": "US.WI", "note": null, "hasc_maybe": null, "region": "Midwest", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Wis.", "postal": "WI", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 9, "mapcolor9": 1, "mapcolor13": 1, "fips": "US55", "fips_alt": null, "woe_id": 2347608, "woe_label": "Wisconsin, US, United States", "woe_name": "Wisconsin", "latitude": 44.3709, "longitude": -89.5831, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5279468, "gn_name": "Wisconsin", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.WI", "region_sub": "East North Central", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1537", "name_ar": "\u0648\u064a\u0633\u0643\u0648\u0646\u0633\u0646", "name_bn": "\u0989\u0987\u09b8\u0995\u09a8\u09b8\u09bf\u09a8", "name_de": "Wisconsin", "name_en": "Wisconsin", "name_es": "Wisconsin", "name_fr": "Wisconsin", "name_el": "\u039f\u03c5\u03b9\u03c3\u03ba\u03cc\u03bd\u03c3\u03b9\u03bd", "name_hi": "\u0935\u093f\u0938\u094d\u0915\u0949\u0928\u094d\u0938\u093f\u0928", "name_hu": "Wisconsin", "name_id": "Wisconsin", "name_it": "Wisconsin", "name_ja": "\u30a6\u30a3\u30b9\u30b3\u30f3\u30b7\u30f3\u5dde", "name_ko": "\uc704\uc2a4\ucf58\uc2e0", "name_nl": "Wisconsin", "name_pl": "Wisconsin", "name_pt": "Wisconsin", "name_ru": "\u0412\u0438\u0441\u043a\u043e\u043d\u0441\u0438\u043d", "name_sv": "Wisconsin", "name_tr": "Wisconsin", "name_vi": "Wisconsin", "name_zh": "\u5a01\u65af\u5eb7\u661f\u5dde", "ne_id": 1159315321, "name_he": "\u05d5\u05d9\u05e1\u05e7\u05d5\u05e0\u05e1\u05d9\u05df", "name_uk": "\u0412\u0456\u0441\u043a\u043e\u043d\u0441\u0438\u043d", "name_ur": "\u0648\u0633\u06a9\u0648\u0646\u0633\u0646", "name_fa": "\u0648\u06cc\u0633\u06a9\u0627\u0646\u0633\u06cc\u0646", "name_zht": "\u5a01\u65af\u5eb7\u8f9b\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-92.89652, 42.492802, -86.264524, 47.309098], "geometry": {"type": "Polygon", "coordinates": [[[-90.650585, 42.512984], [-90.657331, 42.520509], [-90.687873, 42.610322], [-90.788749, 42.676933], [-90.959949, 42.72034], [-91.069582, 42.788554], [-91.117592, 42.881652], [-91.148156, 42.986209], [-91.161328, 43.102334], [-91.147585, 43.199585], [-91.106968, 43.278028], [-91.117196, 43.331157], [-91.178357, 43.358931], [-91.218688, 43.395285], [-91.238277, 43.440241], [-91.245253, 43.502412], [-91.278432, 43.797428], [-91.319916, 43.936284], [-91.382692, 43.990799], [-91.514846, 44.054212], [-91.716435, 44.126458], [-91.840976, 44.194156], [-91.912299, 44.288869], [-92.055121, 44.39982], [-92.148582, 44.445248], [-92.240307, 44.462145], [-92.313091, 44.497796], [-92.366941, 44.552266], [-92.441587, 44.586576], [-92.537031, 44.600792], [-92.643538, 44.645342], [-92.769809, 44.72585], [-92.7726, 44.732002], [-92.799214, 44.790032], [-92.784668, 44.822563], [-92.763404, 44.934261], [-92.765212, 44.96945], [-92.79304, 45.071359], [-92.759059, 45.11058], [-92.76614, 45.236461], [-92.753918, 45.277572], [-92.685808, 45.380536], [-92.682605, 45.433095], [-92.707022, 45.493761], [-92.757461, 45.543244], [-92.892488, 45.594759], [-92.89652, 45.658578], [-92.874712, 45.706094], [-92.786448, 45.795501], [-92.738081, 45.874668], [-92.693949, 45.909012], [-92.424613, 46.027807], [-92.367276, 46.035981], [-92.325473, 46.069588], [-92.292629, 46.084375], [-92.292371, 46.22845], [-92.29214, 46.372547], [-92.291904, 46.516643], [-92.291646, 46.660718], [-92.224003, 46.671023], [-92.194549, 46.706971], [-92.125346, 46.763012], [-92.093266, 46.761902], [-91.964923, 46.729778], [-91.840778, 46.77859], [-91.716643, 46.827425], [-91.59252, 46.876259], [-91.468363, 46.925093], [-91.264787, 47.021114], [-91.061188, 47.117068], [-90.8576, 47.213089], [-90.654024, 47.309098], [-90.479923, 47.303627], [-90.305856, 47.298123], [-90.131778, 47.292619], [-89.957677, 47.287137], [-90.014553, 47.199389], [-90.07143, 47.111674], [-90.128273, 47.023948], [-90.185138, 46.9362], [-90.242003, 46.848463], [-90.298847, 46.760716], [-90.355712, 46.673012], [-90.412588, 46.585275], [-90.39234, 46.548965], [-90.34088, 46.558446], [-90.318227, 46.536639], [-90.28786, 46.527388], [-90.23038, 46.509766], [-90.20242, 46.467754], [-90.174459, 46.425721], [-90.14651, 46.383676], [-90.11855, 46.341664], [-89.993646, 46.317582], [-89.868754, 46.293555], [-89.743839, 46.269473], [-89.618925, 46.245446], [-89.493988, 46.221364], [-89.369085, 46.197337], [-89.244181, 46.173255], [-89.119289, 46.149195], [-89.0488, 46.121059], [-88.978312, 46.092901], [-88.907824, 46.064765], [-88.837335, 46.036618], [-88.727241, 46.031114], [-88.62954, 46.014041], [-88.492991, 46.013524], [-88.35475, 45.992288], [-88.151745, 45.945409], [-88.104415, 45.905155], [-88.096483, 45.878415], [-88.116116, 45.815804], [-87.922537, 45.759971], [-87.839832, 45.717981], [-87.809081, 45.686044], [-87.814091, 45.657029], [-87.794557, 45.596033], [-87.814662, 45.563239], [-87.815178, 45.505824], [-87.859135, 45.445498], [-87.874032, 45.412814], [-87.874911, 45.385392], [-87.86543, 45.367825], [-87.84182, 45.360794], [-87.768563, 45.364364], [-87.696394, 45.382832], [-87.664226, 45.371286], [-87.657568, 45.361804], [-87.66271, 45.345193], [-87.720916, 45.242768], [-87.71885, 45.201272], [-87.694208, 45.161073], [-87.653613, 45.121797], [-87.45954, 45.067997], [-87.419802, 45.183859], [-87.244384, 45.289789], [-87.115272, 45.452365], [-86.942337, 45.452365], [-86.77429, 45.452365], [-86.481823, 45.323001], [-86.264524, 45.226903], [-86.401469, 45.133366], [-86.535952, 45.041487], [-86.7147, 44.846205], [-86.822113, 44.591125], [-86.918749, 44.361587], [-87.03249, 44.091466], [-87.083203, 43.890142], [-87.141727, 43.657803], [-87.145188, 43.571264], [-87.15501, 43.326763], [-87.113855, 43.03055], [-87.079358, 42.782149], [-87.039126, 42.492802], [-87.489412, 42.495318], [-87.939664, 42.497822], [-88.38995, 42.500305], [-88.840236, 42.50281], [-89.290521, 42.505315], [-89.740796, 42.507798], [-90.191049, 42.510303], [-90.650585, 42.512984]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3554", "diss_me": 3554, "iso_3166_2": "US-WV", "wikipedia": "http://en.wikipedia.org/wiki/West_Virginia", "iso_a2": "US", "adm0_sr": 1, "name": "West Virginia", "name_alt": "WV|W.Va.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US54", "code_hasc": "US.WV", "note": null, "hasc_maybe": null, "region": "South", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "W.Va.", "postal": "WV", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 13, "mapcolor9": 1, "mapcolor13": 1, "fips": "US54", "fips_alt": null, "woe_id": 2347607, "woe_label": "West Virginia, US, United States", "woe_name": "West Virginia", "latitude": 38.6422, "longitude": -80.7128, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 4826850, "gn_name": "West Virginia", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.WV", "region_sub": "South Atlantic", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1371", "name_ar": "\u0641\u064a\u0631\u062c\u064a\u0646\u064a\u0627 \u0627\u0644\u063a\u0631\u0628\u064a\u0629", "name_bn": "\u09aa\u09b6\u09cd\u099a\u09bf\u09ae \u09ad\u09be\u09b0\u09cd\u099c\u09bf\u09a8\u09bf\u09af\u09bc\u09be", "name_de": "West Virginia", "name_en": "West Virginia", "name_es": "Virginia Occidental", "name_fr": "Virginie-Occidentale", "name_el": "\u0394\u03c5\u03c4\u03b9\u03ba\u03ae \u0392\u03b9\u03c1\u03c4\u03b6\u03af\u03bd\u03b9\u03b1", "name_hi": "\u092a\u0936\u094d\u091a\u093f\u092e\u0940 \u0935\u0930\u094d\u091c\u0940\u0928\u093f\u092f\u093e", "name_hu": "Nyugat-Virginia", "name_id": "Virginia Barat", "name_it": "Virginia Occidentale", "name_ja": "\u30a6\u30a7\u30b9\u30c8\u30d0\u30fc\u30b8\u30cb\u30a2\u5dde", "name_ko": "\uc6e8\uc2a4\ud2b8\ubc84\uc9c0\ub2c8\uc544", "name_nl": "West Virginia", "name_pl": "Wirginia Zachodnia", "name_pt": "Virg\u00ednia Ocidental", "name_ru": "\u0417\u0430\u043f\u0430\u0434\u043d\u0430\u044f \u0412\u0438\u0440\u0433\u0438\u043d\u0438\u044f", "name_sv": "West Virginia", "name_tr": "Bat\u0131 Virginia", "name_vi": "T\u00e2y Virginia", "name_zh": "\u897f\u7dad\u5409\u5c3c\u4e9e\u5dde", "ne_id": 1159315323, "name_he": "\u05d5\u05d9\u05e8\u05d2'\u05d9\u05e0\u05d9\u05d4 \u05d4\u05de\u05e2\u05e8\u05d1\u05d9\u05ea", "name_uk": "\u0417\u0430\u0445\u0456\u0434\u043d\u0430 \u0412\u0456\u0440\u0434\u0436\u0438\u043d\u0456\u044f", "name_ur": "\u0645\u063a\u0631\u0628\u06cc \u0648\u0631\u062c\u06cc\u0646\u06cc\u0627", "name_fa": "\u0648\u06cc\u0631\u062c\u06cc\u0646\u06cc\u0627\u06cc \u063a\u0631\u0628\u06cc", "name_zht": "\u897f\u7dad\u5409\u5c3c\u4e9e\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-82.619546, 37.20807, -77.726642, 40.646956], "geometry": {"type": "Polygon", "coordinates": [[[-81.965277, 37.539725], [-82.103463, 37.570575], [-82.280244, 37.687184], [-82.393876, 37.828314], [-82.4299, 37.894177], [-82.47189, 37.938408], [-82.482195, 37.983551], [-82.588773, 38.099742], [-82.617711, 38.149873], [-82.619546, 38.182008], [-82.585389, 38.24273], [-82.578413, 38.272085], [-82.589498, 38.420345], [-82.612778, 38.448218], [-82.497543, 38.414973], [-82.387064, 38.43399], [-82.318147, 38.479672], [-82.290868, 38.552017], [-82.252317, 38.594083], [-82.202494, 38.605839], [-82.180071, 38.637589], [-82.18764, 38.715208], [-82.203527, 38.768228], [-82.163328, 38.844912], [-82.072273, 38.962949], [-82.001092, 39.011102], [-81.949797, 38.989327], [-81.91853, 38.952347], [-81.907368, 38.900239], [-81.896678, 38.893549], [-81.88244, 38.894219], [-81.843757, 38.934319], [-81.809337, 38.950029], [-81.795033, 38.945942], [-81.780124, 38.946975], [-81.777685, 38.972793], [-81.804954, 39.04405], [-81.802602, 39.086062], [-81.770665, 39.098828], [-81.736663, 39.14663], [-81.700594, 39.229467], [-81.657209, 39.271973], [-81.606464, 39.274137], [-81.551631, 39.308041], [-81.492722, 39.373618], [-81.439647, 39.392559], [-81.392417, 39.364829], [-81.333354, 39.362819], [-81.262504, 39.386538], [-81.139127, 39.455994], [-80.963291, 39.57113], [-80.874313, 39.664294], [-80.872192, 39.735508], [-80.803517, 39.909136], [-80.668275, 40.185244], [-80.601819, 40.363893], [-80.604093, 40.445203], [-80.623187, 40.51156], [-80.659047, 40.562976], [-80.637524, 40.603263], [-80.519081, 40.646956], [-80.520168, 40.532149], [-80.520069, 40.416473], [-80.51996, 40.300798], [-80.519861, 40.185145], [-80.519762, 40.069492], [-80.519652, 39.953839], [-80.519553, 39.838186], [-80.519443, 39.722511], [-80.3892, 39.722533], [-80.258946, 39.722588], [-80.128725, 39.72261], [-79.998472, 39.722643], [-79.868218, 39.722687], [-79.737997, 39.72272], [-79.607743, 39.722742], [-79.4775, 39.722797], [-79.480126, 39.594817], [-79.48274, 39.466837], [-79.485344, 39.33889], [-79.487981, 39.210911], [-79.35977, 39.285354], [-79.293556, 39.311578], [-79.075345, 39.475989], [-79.046748, 39.476791], [-78.971481, 39.453643], [-78.814794, 39.570087], [-78.796172, 39.612626], [-78.77777, 39.626622], [-78.758214, 39.624766], [-78.746459, 39.613702], [-78.753402, 39.589522], [-78.741669, 39.577898], [-78.677673, 39.54952], [-78.587497, 39.534436], [-78.574962, 39.532854], [-78.495542, 39.533348], [-78.460265, 39.556134], [-78.442698, 39.601464], [-78.406761, 39.627864], [-78.325364, 39.639213], [-78.181135, 39.68574], [-78.097782, 39.677885], [-78.027195, 39.631226], [-77.955707, 39.608803], [-77.883252, 39.610714], [-77.855423, 39.599706], [-77.872167, 39.575778], [-77.853072, 39.548334], [-77.798141, 39.517275], [-77.779585, 39.488337], [-77.797438, 39.461465], [-77.791703, 39.441777], [-77.762358, 39.429242], [-77.744835, 39.400106], [-77.739045, 39.354337], [-77.726642, 39.346438], [-77.791758, 39.226621], [-77.835791, 39.145212], [-77.948598, 39.216316], [-78.118348, 39.323334], [-78.193, 39.370388], [-78.322221, 39.451852], [-78.35105, 39.410928], [-78.365782, 39.335847], [-78.403707, 39.262645], [-78.435238, 39.160758], [-78.581477, 38.999017], [-78.692757, 38.921652], [-78.727309, 38.923882], [-78.756786, 38.908215], [-78.805499, 38.860183], [-78.868725, 38.817941], [-78.991992, 38.819699], [-79.041189, 38.789673], [-79.073313, 38.741948], [-79.104239, 38.672932], [-79.152502, 38.618319], [-79.20294, 38.525814], [-79.240272, 38.476519], [-79.304169, 38.449899], [-79.395871, 38.454392], [-79.504834, 38.49135], [-79.524675, 38.533461], [-79.555272, 38.559377], [-79.597745, 38.577131], [-79.639603, 38.572451], [-79.668651, 38.54426], [-79.715255, 38.404042], [-79.783447, 38.336036], [-79.812879, 38.267042], [-79.902693, 38.180745], [-79.971731, 38.046151], [-80.188074, 37.824227], [-80.245928, 37.751025], [-80.285303, 37.677054], [-80.255376, 37.645271], [-80.245818, 37.620782], [-80.291971, 37.565895], [-80.316075, 37.5097], [-80.371183, 37.472599], [-80.464512, 37.432729], [-80.491417, 37.46392], [-80.507402, 37.469061], [-80.719845, 37.401023], [-80.77003, 37.401594], [-80.821084, 37.423094], [-80.843485, 37.421721], [-80.862425, 37.414569], [-80.871852, 37.399419], [-80.873071, 37.34062], [-80.915369, 37.311363], [-80.94368, 37.301904], [-81.057345, 37.293719], [-81.178118, 37.263331], [-81.227128, 37.263276], [-81.350043, 37.333688], [-81.419366, 37.282272], [-81.485537, 37.257003], [-81.564836, 37.209795], [-81.589017, 37.20807], [-81.660769, 37.221759], [-81.752164, 37.270769], [-81.829266, 37.298597], [-81.87564, 37.329612], [-81.913059, 37.368965], [-81.939382, 37.432598], [-81.971396, 37.47306], [-81.957707, 37.507634], [-81.965277, 37.539725]]]}}, {"type": "Feature", "properties": {"featurecla": "Admin-1 scale rank", "scalerank": 2, "adm1_code": "USA-3527", "diss_me": 3527, "iso_3166_2": "US-WY", "wikipedia": "http://en.wikipedia.org/wiki/Wyoming", "iso_a2": "US", "adm0_sr": 1, "name": "Wyoming", "name_alt": "WY|Wyo.", "name_local": null, "type": "State", "type_en": "State", "code_local": "US56", "code_hasc": "US.WY", "note": null, "hasc_maybe": null, "region": "West", "region_cod": null, "provnum_ne": 0, "gadm_level": 1, "check_me": 20, "datarank": 1, "abbrev": "Wyo.", "postal": "WY", "area_sqkm": 0, "sameascity": -99, "labelrank": 0, "name_len": 7, "mapcolor9": 1, "mapcolor13": 1, "fips": "US56", "fips_alt": null, "woe_id": 2347609, "woe_label": "Wyoming, US, United States", "woe_name": "Wyoming", "latitude": 42.9999, "longitude": -107.552, "sov_a3": "US1", "adm0_a3": "USA", "adm0_label": 2, "admin": "United States of America", "geonunit": "United States of America", "gu_a3": "USA", "gn_id": 5843591, "gn_name": "Wyoming", "gns_id": -1, "gns_name": null, "gn_level": 1, "gn_region": null, "gn_a1_code": "US.WY", "region_sub": "Mountain", "sub_code": null, "gns_level": -1, "gns_lang": null, "gns_adm1": null, "gns_region": null, "min_label": 3.5, "max_label": 7.5, "min_zoom": 2, "wikidataid": "Q1214", "name_ar": "\u0648\u0627\u064a\u0648\u0645\u0646\u063a", "name_bn": "\u0993\u09af\u09bc\u09be\u0987\u09af\u09bc\u09cb\u09ae\u09bf\u0982", "name_de": "Wyoming", "name_en": "Wyoming", "name_es": "Wyoming", "name_fr": "Wyoming", "name_el": "\u039f\u03c5\u03b1\u03ca\u03cc\u03bc\u03b9\u03bd\u03b3\u03ba", "name_hi": "\u0935\u093e\u092f\u094b\u092e\u093f\u0902\u0917", "name_hu": "Wyoming", "name_id": "Wyoming", "name_it": "Wyoming", "name_ja": "\u30ef\u30a4\u30aa\u30df\u30f3\u30b0\u5dde", "name_ko": "\uc640\uc774\uc624\ubc0d", "name_nl": "Wyoming", "name_pl": "Wyoming", "name_pt": "Wyoming", "name_ru": "\u0412\u0430\u0439\u043e\u043c\u0438\u043d\u0433", "name_sv": "Wyoming", "name_tr": "Wyoming", "name_vi": "Wyoming", "name_zh": "\u6000\u4fc4\u660e\u5dde", "ne_id": 1159315351, "name_he": "\u05d5\u05d9\u05d5\u05de\u05d9\u05e0\u05d2", "name_uk": "\u0412\u0430\u0439\u043e\u043c\u0456\u043d\u0433", "name_ur": "\u0648\u0627\u0626\u06cc\u0648\u0645\u0646\u06af", "name_fa": "\u0648\u0627\u06cc\u0648\u0645\u06cc\u0646\u06af", "name_zht": "\u61f7\u4fc4\u660e\u5dde", "FCLASS_ISO": null, "FCLASS_US": null, "FCLASS_FR": null, "FCLASS_RU": null, "FCLASS_ES": null, "FCLASS_CN": null, "FCLASS_TW": null, "FCLASS_IN": null, "FCLASS_NP": null, "FCLASS_PK": null, "FCLASS_DE": null, "FCLASS_GB": null, "FCLASS_BR": null, "FCLASS_IL": null, "FCLASS_PS": null, "FCLASS_SA": null, "FCLASS_EG": null, "FCLASS_MA": null, "FCLASS_PT": null, "FCLASS_AR": null, "FCLASS_JP": null, "FCLASS_KO": null, "FCLASS_VN": null, "FCLASS_TR": null, "FCLASS_ID": null, "FCLASS_PL": null, "FCLASS_GR": null, "FCLASS_IT": null, "FCLASS_NL": null, "FCLASS_SE": null, "FCLASS_BD": null, "FCLASS_UA": null, "FCLASS_TLC": null}, "bbox": [-111.051434, 41.000858, -104.021655, 45.001134], "geometry": {"type": "Polygon", "coordinates": [[[-104.021655, 41.000858], [-104.335722, 41.000858], [-104.649755, 41.000858], [-104.963794, 41.000858], [-105.277832, 41.000858], [-105.591871, 41.000858], [-105.905932, 41.000858], [-106.219998, 41.000858], [-106.534037, 41.000858], [-106.84807, 41.000858], [-107.162108, 41.000858], [-107.476147, 41.000858], [-107.790213, 41.000858], [-108.104274, 41.000858], [-108.418313, 41.000858], [-108.732351, 41.000858], [-109.04639, 41.000858], [-109.29684, 41.000858], [-109.54729, 41.000858], [-109.79774, 41.000858], [-110.048189, 41.000858], [-110.298639, 41.000858], [-110.549089, 41.000858], [-110.799539, 41.000858], [-111.049989, 41.000858], [-111.050038, 41.125861], [-111.050066, 41.250863], [-111.050088, 41.375877], [-111.050143, 41.500879], [-111.050192, 41.625881], [-111.05022, 41.750884], [-111.050247, 41.875897], [-111.050296, 42.000878], [-111.050373, 42.157016], [-111.05045, 42.313131], [-111.050505, 42.469247], [-111.050582, 42.625385], [-111.050659, 42.781522], [-111.050708, 42.937638], [-111.050785, 43.093754], [-111.050862, 43.249892], [-111.050945, 43.406029], [-111.051022, 43.562145], [-111.051071, 43.718261], [-111.051148, 43.874398], [-111.051225, 44.030547], [-111.05128, 44.186652], [-111.051357, 44.342768], [-111.051434, 44.498883], [-111.05128, 44.624457], [-111.051148, 44.749987], [-111.051022, 44.875506], [-111.050862, 45.001057], [-110.831707, 45.001079], [-110.612519, 45.001079], [-110.393336, 45.001079], [-110.174175, 45.001079], [-109.954987, 45.001079], [-109.735804, 45.001079], [-109.516643, 45.001079], [-109.297455, 45.001079], [-109.078272, 45.001079], [-108.859112, 45.001079], [-108.639929, 45.001079], [-108.420741, 45.001079], [-108.20158, 45.001079], [-107.982397, 45.001079], [-107.763209, 45.001079], [-107.544048, 45.001079], [-107.324865, 45.001079], [-107.105677, 45.001079], [-106.886522, 45.001079], [-106.667334, 45.001079], [-106.448151, 45.001079], [-106.22899, 45.001079], [-106.009802, 45.001079], [-105.790619, 45.001101], [-105.571458, 45.001134], [-105.35227, 45.001134], [-105.133087, 45.001134], [-104.913927, 45.001134], [-104.694738, 45.001134], [-104.475556, 45.001134], [-104.256395, 45.001134], [-104.037212, 45.001134], [-104.036152, 44.751173], [-104.035119, 44.501212], [-104.034081, 44.251251], [-104.033048, 44.001269], [-104.032016, 43.751286], [-104.030955, 43.501325], [-104.029895, 43.251364], [-104.028862, 43.001403], [-104.027962, 42.751343], [-104.027055, 42.501283], [-104.026149, 42.251223], [-104.025248, 42.001131], [-104.024342, 41.751049], [-104.023441, 41.500978], [-104.022562, 41.250918], [-104.021655, 41.000858]]]}}]} \ No newline at end of file diff --git a/crates/latkit-cli/examples/bus-fault/README.md b/crates/latkit-cli/examples/bus-fault/README.md new file mode 100644 index 00000000..844d6bf6 --- /dev/null +++ b/crates/latkit-cli/examples/bus-fault/README.md @@ -0,0 +1,28 @@ +# 70,000-bus fault — Python + latkit CLI + +[Preview](preview.png) · The animation is not in Git: [`render.py`](render.py), run as below, +writes `animation.mp4` here. + +The saved ACTIVSg70k recording: simulation 0.6–1.4 s at 0.1×, then 1.4–10 s at 1×, 997 frames at +60 fps and 1920 × 1080. The fault is on bus 56923 at 1 s and clears at 1.15 s. Every bus keeps its +frequency-dependent color and signed height; a plot below traces six buses with a playhead. + +[`render.py`](render.py) uses only Python's standard library. It writes the grid and the traced +buses as latkit JSON, whose frame columns are slices of the saved float32 caches, and a frame per +output frame that appends them. latkit reads the states' GeoJSON, draws the map with its title and +legend over the plot, and encodes the MP4: 5.5 s for the 997 frames on an RTX 2080 SUPER. + +```sh +python crates/latkit-cli/examples/bus-fault/render.py --cli target/cli/latkit --preview +python crates/latkit-cli/examples/bus-fault/render.py --cli target/cli/latkit +``` + +`` is the recording's directory: `buses.json`, `topology.json`, `usa-states.geojson`, +`depth-metadata.json`, and the frame-major caches `depth-frequency.f32` and `depth-height.f32` in +the metadata's bus order. They are not in this repository. Frequency comes from a causal 20 ms +filtered derivative of bus voltage angle; height is `asinh(df / 0.02) / asinh(0.35 / 0.02)`; colors +clip to ±0.05 Hz. + +The recipe writes its JSON to `target/bus-fault/` and keeps existing scenes and cameras there, so +edits survive a rerun. `--prepare-only` prints the command without rendering; `--limit N` renders the +first N frames. `animation.json` and `preview.json` record the command and timings. diff --git a/crates/latkit-cli/examples/bus-fault/animation.json b/crates/latkit-cli/examples/bus-fault/animation.json new file mode 100644 index 00000000..fd927c95 --- /dev/null +++ b/crates/latkit-cli/examples/bus-fault/animation.json @@ -0,0 +1 @@ +{"buses": 70000, "branches": 88207, "traced": [56923, 65829, 56291, 38205, 14472, 1373], "frames": 997, "fps": 60, "simulation_start_s": 0.6, "simulation_end_s": 10.0, "height_scale": 10.58769708581753, "resolution": [1920, 1080], "seconds": 16.616666666666667, "render_seconds": 4.656766100000823, "total_seconds": 6.257235100001708, "command": ["target/cli/latkit.exe", "render", "target/bus-fault/map.json", "target/bus-fault/plot.json", "--data", "target/bus-fault/grid.json", "--data", "target/bus-fault/trace.json", "--data", "states=/usa-states.geojson", "--panel", "0,0,1,0.84", "--panel", "0,0.84,1,0.16", "--camera", "target/bus-fault/map-camera.json", "--camera", "target/bus-fault/plot-camera.json", "--frames", "target/bus-fault/frames.jsonl", "--font", "C:/Windows/Fonts/segoeui.ttf", "--size", "1920x1080", "--fps", "60", "--output", "examples/bus-fault/animation.mp4"]} \ No newline at end of file diff --git a/crates/latkit-cli/examples/bus-fault/preview.json b/crates/latkit-cli/examples/bus-fault/preview.json new file mode 100644 index 00000000..0ccbd4f0 --- /dev/null +++ b/crates/latkit-cli/examples/bus-fault/preview.json @@ -0,0 +1 @@ +{"buses": 70000, "branches": 88207, "traced": [56923, 65829, 56291, 38205, 14472, 1373], "frames": 1, "fps": 60, "simulation_start_s": 1.3, "simulation_end_s": 1.3, "height_scale": 10.58769708581753, "resolution": [1920, 1080], "seconds": 0.016666666666666666, "render_seconds": 0.9005362000025343, "total_seconds": 1.7516155999983312, "command": ["target/cli/latkit.exe", "render", "target/bus-fault/map.json", "target/bus-fault/plot.json", "--data", "target/bus-fault/grid.json", "--data", "target/bus-fault/trace.json", "--data", "states=/usa-states.geojson", "--panel", "0,0,1,0.84", "--panel", "0,0.84,1,0.16", "--camera", "target/bus-fault/map-camera.json", "--camera", "target/bus-fault/plot-camera.json", "--frames", "target/bus-fault/frames.jsonl", "--font", "C:/Windows/Fonts/segoeui.ttf", "--size", "1920x1080", "--fps", "60", "--output", "examples/bus-fault/preview.png"]} \ No newline at end of file diff --git a/crates/latkit-cli/examples/bus-fault/preview.png b/crates/latkit-cli/examples/bus-fault/preview.png new file mode 100644 index 00000000..5322c626 Binary files /dev/null and b/crates/latkit-cli/examples/bus-fault/preview.png differ diff --git a/crates/latkit-cli/examples/bus-fault/render.py b/crates/latkit-cli/examples/bus-fault/render.py new file mode 100644 index 00000000..0b5eaf91 --- /dev/null +++ b/crates/latkit-cli/examples/bus-fault/render.py @@ -0,0 +1,178 @@ +"""Reproduce the 70k-bus fault recording with Python and the latkit CLI. + +Python writes latkit's JSON documents: the grid, whose frame columns are slices of the saved float32 +caches, a frame per output frame that appends them, and a few buses' traces for a plot. latkit +reads the states' GeoJSON itself, draws the map with its title and legend over the plot, and +encodes the MP4. No Rust, browser, NumPy, Pillow, or FFmpeg is used. +""" + +import argparse +import json +import math +import os +import struct +import subprocess +import time +from pathlib import Path + +W, H, FPS = 1920, 1080, 60 +PALETTE = ["#1f52f2", "#2ea6f2", "#4d6e7a", "#ffa13b", "#ff3b1c"] +FAULT = 56923 +BACKGROUND = "#090d12" + + +def read(path): + return json.loads(path.read_text(encoding="utf-8-sig")) + + +def write(path, value): + path.write_text(json.dumps(value, ensure_ascii=False, allow_nan=False), encoding="utf-8", newline="\n") + + +def relative(path): + """`path` from the working directory when it lies under it.""" + path = Path(path).resolve() + return path.relative_to(Path.cwd()).as_posix() if path.is_relative_to(Path.cwd()) else path.as_posix() + + +def prepare(source, job, indices): + meta = read(source / "depth-metadata.json") + ids, times = meta["bus_ids"], meta["simulation_times"] + n = len(ids) + assert n == 70_000 and len(set(ids)) == n and len(times) == 997 and meta["fps"] == FPS + for name in ("depth-frequency.f32", "depth-height.f32"): + assert (source / name).stat().st_size == n * len(times) * 4 + job.mkdir(parents=True, exist_ok=True) + + def frame(k): + """Frame k of the saved caches: one value per bus, in the metadata's order.""" + return { + field: {"file": str(source / name), "dtype": "f32le", "offset": k * n * 4, "count": n} + for field, name in (("df", "depth-frequency.f32"), ("height", "depth-height.f32")) + } + + buses = {b["bus_id"]: b for b in read(source / "buses.json")} + ordered = [buses[i] for i in ids] + lon = [b["longitude"] for b in ordered] + lat = [b["latitude"] for b in ordered] + edges = read(source / "topology.json") + kv = lambda e: min(buses[e["bus1"]]["kv"], buses[e["bus2"]]["kv"]) + widths = [0.7 + min(1, max(0, (kv(e) - 69) / 696)) for e in edges] + first = indices[0] + write(job / "grid.json", {"name": "grid", "patch": [ + {"axis": {"name": "time", "unit": "s"}}, + {"replace": {"table": "Bus", "ids": ids, "fields": {"lon": lon, "lat": lat}}}, + {"replace": {"table": "Branch", "ids": {"count": len(edges)}, "fields": { + "width": widths, + "from": {"reference": "Bus", "ids": [e["bus1"] for e in edges]}, + "to": {"reference": "Bus", "ids": [e["bus2"] for e in edges]}, + }}}, + {"append": {"at": times[first], "table": "Bus", "fields": frame(first)}}, + ]}) + + # The fault bus and five across the grid, west to east, traced over the whole recording. + west_to_east = sorted(range(n), key=lambda i: lon[i]) + traced = [ids.index(FAULT)] + [west_to_east[round(q * (n - 1))] for q in (0.05, 0.3, 0.5, 0.7, 0.95)] + values = [] + with (source / "depth-frequency.f32").open("rb") as f: + for k in range(len(times)): + for i in traced: + f.seek((k * n + i) * 4) + values.append(struct.unpack(" and other files from the working directory. + command = [relative(part) if os.path.isabs(part) else part for part in + (part.replace(str(source), "").replace(os.sep, "/") for part in render)] + metadata.update({"resolution": [W, H], "seconds": len(indices) / FPS, + "render_seconds": time.perf_counter() - render_started, + "total_seconds": time.perf_counter() - started, "command": command}) + write(output / ("preview.json" if args.preview else "animation.json"), metadata) + print(f"Saved {relative(result)} ({metadata['render_seconds']:.1f} s rendering)", flush=True) + + +if __name__ == "__main__": + main() diff --git a/crates/latkit-cli/examples/cli-gallery/README.md b/crates/latkit-cli/examples/cli-gallery/README.md new file mode 100644 index 00000000..f283eca4 --- /dev/null +++ b/crates/latkit-cli/examples/cli-gallery/README.md @@ -0,0 +1,35 @@ +# CLI gallery + +1600 × 1000 PNGs drawn by the `latkit` CLI, titles included, with no postprocessing. The data is +synthetic and generated locally. + +## Helios + +480 buses and 896 branches, with flowing edges, data-driven colors, and labels. + +![Helios transmission network](helios.png) + +## Interference + +33,600 particles colored and sized by the interaction of two radial waves. + +![Particle interference field](interference.png) + +## Tidal forms + +100 closed contours of 48,100 coordinates, with harmonic deformations and a continuous palette. + +![Tidal contour artwork](tides.png) + +## Reproduce + +[`gallery.py`](gallery.py) writes each picture's scene (`NAME.json`) and dataset (`NAME.data.json`) +as latkit JSON, then renders them, every picture framing the same box with `--fit`: + +```sh +cargo build --locked -p latkit-cli --profile cli +python crates/latkit-cli/examples/cli-gallery/gallery.py --cli target/cli/latkit --font C:/Windows/Fonts/segoeui.ttf +latkit render crates/latkit-cli/examples/cli-gallery/helios.json -d crates/latkit-cli/examples/cli-gallery/helios.data.json -o helios.png --size 1600x1000 +``` + +These renders use Segoe UI; without `--font` the CLI uses system fonts, so text can differ. diff --git a/crates/latkit-cli/examples/cli-gallery/gallery.py b/crates/latkit-cli/examples/cli-gallery/gallery.py new file mode 100644 index 00000000..8650fe47 --- /dev/null +++ b/crates/latkit-cli/examples/cli-gallery/gallery.py @@ -0,0 +1,131 @@ +"""Write the CLI gallery's datasets and scenes as latkit JSON, and render each with the CLI. + + python crates/latkit-cli/examples/cli-gallery/gallery.py --cli target/cli/latkit + +Every picture is drawn by latkit, titles included, with no postprocessing. The data is synthetic. +""" + +import argparse +import json +import math +import subprocess +from pathlib import Path + +HERE = Path(__file__).resolve().parent +TAU = 2 * math.pi +# Every picture frames the same box, whatever its geometry. +FRAME = {"bounds": {"min": [-760, -460, 0], "max": [760, 460, 0]}} + + +def rounded(values, digits=3): + return [round(v, digits) for v in values] + + +def put(table, count, fields): + return {"replace": {"table": table, "ids": {"count": count}, "fields": fields}} + + +def scene(title, subtitle, marks): + return { + "space": {"plane": {"grid": "off"}}, "ease": 0, + "theme": {"background": "#080f1c", "text": "#c7d5e4", "font": "sans-serif", "fontSize": 13, + "halo": 0, "flow": "#d9fff0a0", "flowSpacing": 100}, + "title": title, "subtitle": subtitle, "marks": marks, + } + + +def helios(): + x, y, heat, radius, names, start, end = [], [], [], [], [], [], [] + for ring in range(5): + for node in range(96): + angle = node * TAU / 96 + ring * 0.075 + r = 92 + ring * 55 + 8 * math.sin(angle * 6) + x.append(190 + r * math.cos(angle)) + y.append(-35 + r * math.sin(angle)) + heat.append(0.25 + 0.7 * math.sin(angle * 0.5 + ring * 0.3) ** 2) + radius.append(5 if node % 12 == 0 else 2.3) + names.append(f"S{node // 12 + 1:02}" if ring == 4 and node % 12 == 0 else "") + here = ring * 96 + node + start.append(here) + end.append(ring * 96 + (node + 1) % 96) + if ring > 0: + start.append(here) + end.append((ring - 1) * 96 + (node + 3) % 96) + if ring == 0 and node % 3 == 0: + start.append(here) + end.append((node + 37) % 96) + notes = ["480 BUSES", "896 BRANCHES", "Five concentric regions", "One connected system", "Synthetic topology / 01"] + data = [ + put("Bus", len(x), {"x": rounded(x), "y": rounded(y), "heat": rounded(heat), "radius": radius, "name": names}), + put("Branch", len(start), {"from": {"reference": "Bus", "ids": start}, "to": {"reference": "Bus", "ids": end}}), + put("Note", len(notes), {"x": [-660] * 5, "y": [200, 155, 80, 35, -40], "text": notes}), + ] + marks = [ + {"edges": {"of": ["art", "Branch"], "ends": ["from", "to"], "width": 0.85, "flow": 18}}, + {"vertices": {"of": ["art", "Bus"], "position": ["x", "y"], "radius": "radius", + "color": {"colormap": "viridis", "value": "heat", "domain": [0, 1]}, + "label": {"text": "name", "size": 13, "color": "#c0e5dd"}}}, + {"vertices": {"of": ["art", "Note"], "position": ["x", "y"], "radius": 0, "color": "#00000000", + "label": {"text": "text", "size": 17, "color": "#9dcabf"}}}, + ] + return data, scene("01 / HELIOS", "Flow through a synthetic transmission network", marks) + + +def interference(): + x, y, heat, radius = [], [], [], [] + for row in range(140): + for column in range(240): + px = column / 239 * 1280 - 640 + py = row / 139 * 560 - 315 + a = math.sin(math.hypot(px + 260, py + 20) * 0.035) + b = math.cos(math.hypot(px - 240, py - 10) * 0.045) + value = (a + b + 2) * 0.25 + x.append(px + 9 * math.sin(py * 0.022)) + y.append(py + 13 * math.sin(px * 0.016 + py * 0.01)) + heat.append(0.18 + value * 0.82) + radius.append(0.8 + value * 1.7) + data = [put("Particle", len(x), {"x": rounded(x, 2), "y": rounded(y, 2), "heat": rounded(heat), "radius": rounded(radius)})] + marks = [{"vertices": {"of": ["art", "Particle"], "position": ["x", "y"], "radius": "radius", + "color": {"colormap": "magma", "value": "heat", "domain": [0, 1]}}}] + return data, scene("02 / INTERFERENCE", "33,600 particles / two wave sources / one interference field", marks) + + +def tides(): + paths, levels = [], [] + for contour in range(100): + level = contour / 99 + r = 55 + 250 * level + path = [] + for step in range(481): + a = step / 480 * TAU + ripple = 1 + 0.12 * math.sin(a * 3 + level * 5) + 0.07 * math.cos(a * 7 - level * 4) + path.append([round(95 + 1.65 * r * ripple * math.cos(a), 2), round(-35 + 0.83 * r * ripple * math.sin(a), 2)]) + paths.append(path) + levels.append(round(level, 4)) + data = [put("Contour", len(paths), {"geometry": paths, "level": levels})] + marks = [{"lines": {"of": ["art", "Contour"], "width": 1.15, + "color": {"colormap": "turbo", "value": "level", "domain": [0, 1]}}}] + return data, scene("03 / TIDAL FORMS", "100 closed contours / 48,100 coordinates / harmonic geometry", marks) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument("--cli", default="latkit", help="the latkit executable") + parser.add_argument("--font", help="a font file for every text; system fonts otherwise") + args = parser.parse_args() + for name, make in (("helios", helios), ("interference", interference), ("tides", tides)): + patch, picture = make() + data, scene_path, image = HERE / f"{name}.data.json", HERE / f"{name}.json", HERE / f"{name}.png" + document = json.dumps({"name": "art", "patch": patch}, separators=(",", ":")) + data.write_text(document + "\n", encoding="utf-8", newline="\n") + scene_path.write_text(json.dumps(picture, indent=2) + "\n", encoding="utf-8", newline="\n") + command = [args.cli, "render", str(scene_path), "--data", str(data), "--output", str(image), + "--size", "1600x1000", "--elapsed", "1.25", "--fit", json.dumps(FRAME)] + if args.font: + command += ["--font", args.font] + subprocess.run(command, check=True) + print(image.relative_to(HERE.parents[1]).as_posix()) + + +if __name__ == "__main__": + main() diff --git a/crates/latkit-cli/examples/cli-gallery/helios.data.json b/crates/latkit-cli/examples/cli-gallery/helios.data.json new file mode 100644 index 00000000..60e3e8f8 --- /dev/null +++ b/crates/latkit-cli/examples/cli-gallery/helios.data.json @@ -0,0 +1 @@ +{"name":"art","patch":[{"replace":{"table":"Bus","ids":{"count": 480},"fields":{"x":[282.0,284.858,286.821,287.481,286.593,284.116,280.223,275.258,269.674,263.95,258.501,253.612,249.397,245.787,242.562,239.412,236.0,232.045,227.372,221.948,215.882,209.39,202.747,196.217,190.0,184.183,178.73,173.494,168.259,162.803,156.958,150.663,144.0,137.187,130.55,124.467,119.289,115.274,112.524,110.959,110.326,110.233,110.229,109.881,108.862,107.017,104.396,101.252,98.0,95.142,93.179,92.519,93.407,95.884,99.777,104.742,110.326,116.05,121.499,126.388,130.603,134.213,137.438,140.588,144.0,147.955,152.628,158.052,164.118,170.61,177.253,183.783,190.0,195.817,201.27,206.506,211.741,217.197,223.042,229.337,236.0,242.813,249.45,255.533,260.711,264.726,267.476,269.041,269.674,269.767,269.771,270.119,271.138,272.983,275.604,278.748,340.057,341.465,341.29,339.316,335.54,330.166,323.564,316.203,308.566,301.06,293.958,287.354,281.166,275.17,269.056,262.506,255.264,247.187,238.28,228.682,218.638,208.439,198.36,188.601,179.246,170.258,161.491,152.74,143.802,134.535,124.915,115.055,105.207,95.722,86.99,79.366,73.098,68.274,64.796,62.397,60.68,59.197,57.533,55.386,52.636,49.365,45.859,42.549,39.943,38.535,38.71,40.684,44.46,49.834,56.436,63.797,71.434,78.94,86.042,92.646,98.834,104.83,110.944,117.494,124.736,132.813,141.72,151.318,161.362,171.561,181.64,191.399,200.754,209.742,218.509,227.26,236.198,245.465,255.085,264.945,274.793,284.278,293.01,300.634,306.902,311.726,315.204,317.603,319.32,320.803,322.467,324.614,327.364,330.635,334.141,337.451,395.928,394.845,391.719,386.582,379.67,371.38,362.193,352.593,342.982,333.614,324.57,315.754,306.935,297.812,288.083,277.518,266.011,253.599,240.455,226.85,213.091,199.461,186.159,173.269,160.75,148.46,136.205,123.801,111.138,98.223,85.205,72.367,60.083,48.754,38.736,30.268,23.421,18.081,13.967,10.676,7.768,4.845,1.635,-1.952,-5.797,-9.589,-12.878,-15.151,-15.928,-14.845,-11.719,-6.582,0.33,8.62,17.807,27.407,37.018,46.386,55.43,64.246,73.065,82.188,91.917,102.482,113.989,126.401,139.545,153.15,166.909,180.539,193.841,206.731,219.25,231.54,243.795,256.199,268.862,281.777,294.795,307.633,319.917,331.246,341.264,349.732,356.579,361.919,366.033,369.324,372.232,375.155,378.365,381.952,385.797,389.589,392.878,395.151,448.131,443.788,437.23,428.725,418.694,407.631,396.02,384.253,372.57,361.034,349.538,337.849,325.67,312.721,298.801,283.837,267.901,251.199,234.025,216.702,199.52,182.677,166.254,150.209,134.403,118.657,102.807,86.773,70.595,54.459,38.676,23.643,9.77,-2.589,-13.205,-22.023,-29.174,-34.954,-39.766,-44.045,-48.167,-52.378,-56.731,-61.076,-65.075,-68.262,-70.125,-70.194,-68.131,-63.788,-57.23,-48.725,-38.694,-27.631,-16.02,-4.253,7.43,18.966,30.462,42.151,54.33,67.279,81.199,96.163,112.099,128.801,145.975,163.298,180.48,197.323,213.746,229.791,245.597,261.343,277.193,293.227,309.405,325.541,341.324,356.357,370.23,382.589,393.205,402.023,409.174,414.954,419.766,424.045,428.167,432.378,436.731,441.076,445.075,448.262,450.125,450.194,495.508,487.469,477.318,465.495,452.507,438.836,424.864,410.815,396.736,382.51,367.9,352.622,336.415,319.107,300.66,281.183,260.91,240.161,219.272,198.536,178.154,158.201,138.635,119.324,100.1,80.824,61.445,42.04,22.826,4.146,-13.587,-29.952,-44.597,-57.308,-68.046,-76.959,-84.353,-90.635,-96.228,-101.491,-106.636,-111.685,-116.455,-120.583,-123.589,-124.961,-124.247,-121.134,-115.508,-107.469,-97.318,-85.495,-72.507,-58.836,-44.864,-30.815,-16.736,-2.51,12.1,27.378,43.585,60.893,79.34,98.817,119.09,139.839,160.728,181.464,201.846,221.799,241.365,260.676,279.9,299.176,318.555,337.96,357.174,375.854,393.587,409.952,424.597,437.308,448.046,456.959,464.353,470.635,476.228,481.491,486.636,491.685,496.455,500.583,503.589,504.961,504.247,501.134],"y":[-35.0,-28.783,-22.253,-15.61,-9.118,-3.052,2.372,7.045,11.0,14.412,17.562,20.787,24.397,28.612,33.501,38.95,44.674,50.258,55.223,59.116,61.593,62.481,61.821,59.858,57.0,53.748,50.604,47.983,46.138,45.119,44.771,44.767,44.674,44.041,42.476,39.726,35.711,30.533,24.45,17.813,11.0,4.337,-1.958,-7.803,-13.259,-18.494,-23.73,-29.183,-35.0,-41.217,-47.747,-54.39,-60.882,-66.948,-72.372,-77.045,-81.0,-84.412,-87.562,-90.787,-94.397,-98.612,-103.501,-108.95,-114.674,-120.258,-125.223,-129.116,-131.593,-132.481,-131.821,-129.858,-127.0,-123.748,-120.604,-117.983,-116.138,-115.119,-114.771,-114.767,-114.674,-114.041,-112.476,-109.726,-105.711,-100.533,-94.45,-87.813,-81.0,-74.337,-68.042,-62.197,-56.741,-51.506,-46.27,-40.817,-23.725,-13.586,-3.402,6.541,15.959,24.633,32.46,39.48,45.872,51.917,57.94,64.231,70.98,78.218,85.797,93.401,100.591,106.88,111.82,115.082,116.521,116.203,114.399,111.535,108.117,104.64,101.5,98.927,96.942,95.368,93.863,91.993,89.315,85.466,80.222,73.541,65.562,56.57,46.94,37.056,27.245,17.722,8.56,-0.305,-9.038,-17.85,-26.934,-36.408,-46.275,-56.414,-66.598,-76.541,-85.959,-94.633,-102.46,-109.48,-115.872,-121.917,-127.94,-134.231,-140.98,-148.218,-155.797,-163.401,-170.591,-176.88,-181.82,-185.082,-186.521,-186.203,-184.399,-181.535,-178.117,-174.64,-171.5,-168.927,-166.942,-165.368,-163.863,-161.993,-159.315,-155.466,-150.222,-143.541,-135.562,-126.57,-116.94,-107.056,-97.245,-87.722,-78.56,-69.695,-60.962,-52.15,-43.066,-33.592,-3.877,9.83,23.202,35.946,47.843,58.795,68.85,78.192,87.099,95.883,104.811,114.043,123.574,133.221,142.635,151.36,158.9,164.815,168.795,170.718,170.681,168.977,166.049,162.406,158.536,154.815,151.447,148.428,145.556,142.478,138.76,133.973,127.777,119.986,110.593,99.772,87.838,75.182,62.198,49.214,36.436,23.933,11.635,-0.616,-13.018,-25.743,-38.875,-52.387,-66.123,-79.83,-93.202,-105.946,-117.843,-128.795,-138.85,-148.192,-157.099,-165.883,-174.811,-184.043,-193.574,-203.221,-212.635,-221.36,-228.9,-234.815,-238.795,-240.718,-240.681,-238.977,-236.049,-232.406,-228.536,-224.815,-221.447,-218.428,-215.556,-212.478,-208.76,-203.973,-197.777,-189.986,-180.593,-169.772,-157.838,-145.182,-132.198,-119.214,-106.436,-93.933,-81.635,-69.384,-56.982,-44.257,-31.125,-17.613,24.08,40.858,56.902,71.995,86.044,99.105,111.365,123.099,134.605,146.127,157.791,169.557,181.206,192.363,202.55,211.269,218.088,222.715,225.058,225.239,223.577,220.527,216.601,212.278,207.913,203.684,199.56,195.319,190.597,184.961,177.999,169.4,159.008,146.858,133.156,118.245,102.533,86.421,70.236,54.178,38.308,22.557,6.769,-9.238,-25.609,-42.401,-59.55,-76.87,-94.08,-110.858,-126.902,-141.995,-156.044,-169.105,-181.365,-193.099,-204.605,-216.127,-227.791,-239.557,-251.206,-262.363,-272.55,-281.269,-288.088,-292.715,-295.058,-295.239,-293.577,-290.527,-286.601,-282.278,-277.913,-273.684,-269.56,-265.319,-260.597,-254.961,-247.999,-239.4,-229.008,-216.858,-203.156,-188.245,-172.533,-156.421,-140.236,-124.178,-108.308,-92.557,-76.769,-60.762,-44.391,-27.599,-10.45,6.87,59.505,78.823,97.083,114.2,130.237,145.384,159.909,174.097,188.167,202.211,216.153,229.74,242.568,254.146,263.972,271.623,276.83,279.527,279.866,278.186,274.956,270.69,265.853,260.78,255.622,250.324,244.643,238.205,230.583,221.383,210.32,197.278,182.325,165.704,147.783,128.985,109.719,90.306,70.943,51.683,32.455,13.113,-6.51,-26.535,-46.985,-67.763,-88.652,-109.345,-129.505,-148.823,-167.083,-184.2,-200.237,-215.384,-229.909,-244.097,-258.167,-272.211,-286.153,-299.74,-312.568,-324.146,-333.972,-341.623,-346.83,-349.527,-349.866,-348.186,-344.956,-340.69,-335.853,-330.78,-325.622,-320.324,-314.643,-308.205,-300.583,-291.383,-280.32,-267.278,-252.325,-235.704,-217.783,-198.985,-179.719,-160.306,-140.943,-121.683,-102.455,-83.113,-63.49,-43.465,-23.015,-2.237,18.652,39.345],"heat":[0.25,0.251,0.253,0.257,0.262,0.269,0.277,0.286,0.297,0.309,0.322,0.337,0.353,0.369,0.387,0.406,0.425,0.445,0.466,0.487,0.509,0.532,0.554,0.577,0.6,0.623,0.646,0.668,0.691,0.713,0.734,0.755,0.775,0.794,0.813,0.831,0.847,0.863,0.878,0.891,0.903,0.914,0.923,0.931,0.938,0.943,0.947,0.949,0.95,0.949,0.947,0.943,0.938,0.931,0.923,0.914,0.903,0.891,0.878,0.863,0.847,0.831,0.813,0.794,0.775,0.755,0.734,0.713,0.691,0.668,0.646,0.623,0.6,0.577,0.554,0.532,0.509,0.487,0.466,0.445,0.425,0.406,0.387,0.369,0.353,0.337,0.322,0.309,0.297,0.286,0.277,0.269,0.262,0.257,0.253,0.251,0.327,0.342,0.358,0.375,0.393,0.412,0.431,0.452,0.473,0.494,0.516,0.539,0.561,0.584,0.607,0.63,0.653,0.675,0.697,0.719,0.741,0.761,0.781,0.8,0.819,0.836,0.853,0.868,0.882,0.895,0.907,0.917,0.926,0.934,0.94,0.945,0.948,0.95,0.95,0.949,0.946,0.942,0.936,0.929,0.921,0.911,0.899,0.887,0.873,0.858,0.842,0.825,0.807,0.788,0.769,0.748,0.727,0.706,0.684,0.661,0.639,0.616,0.593,0.57,0.547,0.525,0.503,0.481,0.459,0.439,0.419,0.4,0.381,0.364,0.347,0.332,0.318,0.305,0.293,0.283,0.274,0.266,0.26,0.255,0.252,0.25,0.25,0.251,0.254,0.258,0.264,0.271,0.279,0.289,0.301,0.313,0.523,0.546,0.569,0.591,0.614,0.637,0.66,0.682,0.704,0.726,0.747,0.768,0.787,0.806,0.824,0.841,0.857,0.872,0.886,0.899,0.91,0.92,0.929,0.936,0.942,0.946,0.949,0.95,0.95,0.948,0.945,0.94,0.934,0.927,0.918,0.907,0.896,0.883,0.869,0.853,0.837,0.82,0.802,0.782,0.762,0.742,0.721,0.699,0.677,0.654,0.631,0.609,0.586,0.563,0.54,0.518,0.496,0.474,0.453,0.432,0.413,0.394,0.376,0.359,0.343,0.328,0.314,0.301,0.29,0.28,0.271,0.264,0.258,0.254,0.251,0.25,0.25,0.252,0.255,0.26,0.266,0.273,0.282,0.293,0.304,0.317,0.331,0.347,0.363,0.38,0.398,0.418,0.438,0.458,0.479,0.501,0.754,0.774,0.793,0.812,0.83,0.847,0.862,0.877,0.89,0.902,0.913,0.923,0.931,0.938,0.943,0.947,0.949,0.95,0.949,0.947,0.944,0.938,0.932,0.924,0.915,0.904,0.892,0.879,0.864,0.848,0.832,0.814,0.796,0.776,0.756,0.735,0.714,0.692,0.67,0.647,0.624,0.601,0.578,0.556,0.533,0.511,0.489,0.467,0.446,0.426,0.407,0.388,0.37,0.353,0.338,0.323,0.31,0.298,0.287,0.277,0.269,0.262,0.257,0.253,0.251,0.25,0.251,0.253,0.256,0.262,0.268,0.276,0.285,0.296,0.308,0.321,0.336,0.352,0.368,0.386,0.404,0.424,0.444,0.465,0.486,0.508,0.53,0.553,0.576,0.599,0.622,0.644,0.667,0.689,0.711,0.733,0.916,0.926,0.933,0.94,0.944,0.948,0.95,0.95,0.949,0.946,0.942,0.937,0.93,0.921,0.911,0.9,0.888,0.874,0.859,0.843,0.826,0.808,0.79,0.77,0.75,0.729,0.707,0.685,0.663,0.64,0.617,0.594,0.571,0.549,0.526,0.504,0.482,0.461,0.44,0.42,0.401,0.382,0.365,0.348,0.333,0.319,0.306,0.294,0.284,0.274,0.267,0.26,0.256,0.252,0.25,0.25,0.251,0.254,0.258,0.263,0.27,0.279,0.289,0.3,0.312,0.326,0.341,0.357,0.374,0.392,0.41,0.43,0.45,0.471,0.493,0.515,0.537,0.56,0.583,0.606,0.629,0.651,0.674,0.696,0.718,0.739,0.76,0.78,0.799,0.818,0.835,0.852,0.867,0.881,0.894,0.906],"radius":[5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,5,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3,2.3],"name":["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","S01","","","","","","","","","","","","S02","","","","","","","","","","","","S03","","","","","","","","","","","","S04","","","","","","","","","","","","S05","","","","","","","","","","","","S06","","","","","","","","","","","","S07","","","","","","","","","","","","S08","","","","","","","","","","",""]}}},{"replace":{"table":"Branch","ids":{"count": 896},"fields":{"from":{"reference":"Bus","ids":[0,0,1,2,3,3,4,5,6,6,7,8,9,9,10,11,12,12,13,14,15,15,16,17,18,18,19,20,21,21,22,23,24,24,25,26,27,27,28,29,30,30,31,32,33,33,34,35,36,36,37,38,39,39,40,41,42,42,43,44,45,45,46,47,48,48,49,50,51,51,52,53,54,54,55,56,57,57,58,59,60,60,61,62,63,63,64,65,66,66,67,68,69,69,70,71,72,72,73,74,75,75,76,77,78,78,79,80,81,81,82,83,84,84,85,86,87,87,88,89,90,90,91,92,93,93,94,95,96,96,97,97,98,98,99,99,100,100,101,101,102,102,103,103,104,104,105,105,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,127,127,128,128,129,129,130,130,131,131,132,132,133,133,134,134,135,135,136,136,137,137,138,138,139,139,140,140,141,141,142,142,143,143,144,144,145,145,146,146,147,147,148,148,149,149,150,150,151,151,152,152,153,153,154,154,155,155,156,156,157,157,158,158,159,159,160,160,161,161,162,162,163,163,164,164,165,165,166,166,167,167,168,168,169,169,170,170,171,171,172,172,173,173,174,174,175,175,176,176,177,177,178,178,179,179,180,180,181,181,182,182,183,183,184,184,185,185,186,186,187,187,188,188,189,189,190,190,191,191,192,192,193,193,194,194,195,195,196,196,197,197,198,198,199,199,200,200,201,201,202,202,203,203,204,204,205,205,206,206,207,207,208,208,209,209,210,210,211,211,212,212,213,213,214,214,215,215,216,216,217,217,218,218,219,219,220,220,221,221,222,222,223,223,224,224,225,225,226,226,227,227,228,228,229,229,230,230,231,231,232,232,233,233,234,234,235,235,236,236,237,237,238,238,239,239,240,240,241,241,242,242,243,243,244,244,245,245,246,246,247,247,248,248,249,249,250,250,251,251,252,252,253,253,254,254,255,255,256,256,257,257,258,258,259,259,260,260,261,261,262,262,263,263,264,264,265,265,266,266,267,267,268,268,269,269,270,270,271,271,272,272,273,273,274,274,275,275,276,276,277,277,278,278,279,279,280,280,281,281,282,282,283,283,284,284,285,285,286,286,287,287,288,288,289,289,290,290,291,291,292,292,293,293,294,294,295,295,296,296,297,297,298,298,299,299,300,300,301,301,302,302,303,303,304,304,305,305,306,306,307,307,308,308,309,309,310,310,311,311,312,312,313,313,314,314,315,315,316,316,317,317,318,318,319,319,320,320,321,321,322,322,323,323,324,324,325,325,326,326,327,327,328,328,329,329,330,330,331,331,332,332,333,333,334,334,335,335,336,336,337,337,338,338,339,339,340,340,341,341,342,342,343,343,344,344,345,345,346,346,347,347,348,348,349,349,350,350,351,351,352,352,353,353,354,354,355,355,356,356,357,357,358,358,359,359,360,360,361,361,362,362,363,363,364,364,365,365,366,366,367,367,368,368,369,369,370,370,371,371,372,372,373,373,374,374,375,375,376,376,377,377,378,378,379,379,380,380,381,381,382,382,383,383,384,384,385,385,386,386,387,387,388,388,389,389,390,390,391,391,392,392,393,393,394,394,395,395,396,396,397,397,398,398,399,399,400,400,401,401,402,402,403,403,404,404,405,405,406,406,407,407,408,408,409,409,410,410,411,411,412,412,413,413,414,414,415,415,416,416,417,417,418,418,419,419,420,420,421,421,422,422,423,423,424,424,425,425,426,426,427,427,428,428,429,429,430,430,431,431,432,432,433,433,434,434,435,435,436,436,437,437,438,438,439,439,440,440,441,441,442,442,443,443,444,444,445,445,446,446,447,447,448,448,449,449,450,450,451,451,452,452,453,453,454,454,455,455,456,456,457,457,458,458,459,459,460,460,461,461,462,462,463,463,464,464,465,465,466,466,467,467,468,468,469,469,470,470,471,471,472,472,473,473,474,474,475,475,476,476,477,477,478,478,479,479]},"to":{"reference":"Bus","ids":[1,37,2,3,4,40,5,6,7,43,8,9,10,46,11,12,13,49,14,15,16,52,17,18,19,55,20,21,22,58,23,24,25,61,26,27,28,64,29,30,31,67,32,33,34,70,35,36,37,73,38,39,40,76,41,42,43,79,44,45,46,82,47,48,49,85,50,51,52,88,53,54,55,91,56,57,58,94,59,60,61,1,62,63,64,4,65,66,67,7,68,69,70,10,71,72,73,13,74,75,76,16,77,78,79,19,80,81,82,22,83,84,85,25,86,87,88,28,89,90,91,31,92,93,94,34,95,0,97,3,98,4,99,5,100,6,101,7,102,8,103,9,104,10,105,11,106,12,107,13,108,14,109,15,110,16,111,17,112,18,113,19,114,20,115,21,116,22,117,23,118,24,119,25,120,26,121,27,122,28,123,29,124,30,125,31,126,32,127,33,128,34,129,35,130,36,131,37,132,38,133,39,134,40,135,41,136,42,137,43,138,44,139,45,140,46,141,47,142,48,143,49,144,50,145,51,146,52,147,53,148,54,149,55,150,56,151,57,152,58,153,59,154,60,155,61,156,62,157,63,158,64,159,65,160,66,161,67,162,68,163,69,164,70,165,71,166,72,167,73,168,74,169,75,170,76,171,77,172,78,173,79,174,80,175,81,176,82,177,83,178,84,179,85,180,86,181,87,182,88,183,89,184,90,185,91,186,92,187,93,188,94,189,95,190,0,191,1,96,2,193,99,194,100,195,101,196,102,197,103,198,104,199,105,200,106,201,107,202,108,203,109,204,110,205,111,206,112,207,113,208,114,209,115,210,116,211,117,212,118,213,119,214,120,215,121,216,122,217,123,218,124,219,125,220,126,221,127,222,128,223,129,224,130,225,131,226,132,227,133,228,134,229,135,230,136,231,137,232,138,233,139,234,140,235,141,236,142,237,143,238,144,239,145,240,146,241,147,242,148,243,149,244,150,245,151,246,152,247,153,248,154,249,155,250,156,251,157,252,158,253,159,254,160,255,161,256,162,257,163,258,164,259,165,260,166,261,167,262,168,263,169,264,170,265,171,266,172,267,173,268,174,269,175,270,176,271,177,272,178,273,179,274,180,275,181,276,182,277,183,278,184,279,185,280,186,281,187,282,188,283,189,284,190,285,191,286,96,287,97,192,98,289,195,290,196,291,197,292,198,293,199,294,200,295,201,296,202,297,203,298,204,299,205,300,206,301,207,302,208,303,209,304,210,305,211,306,212,307,213,308,214,309,215,310,216,311,217,312,218,313,219,314,220,315,221,316,222,317,223,318,224,319,225,320,226,321,227,322,228,323,229,324,230,325,231,326,232,327,233,328,234,329,235,330,236,331,237,332,238,333,239,334,240,335,241,336,242,337,243,338,244,339,245,340,246,341,247,342,248,343,249,344,250,345,251,346,252,347,253,348,254,349,255,350,256,351,257,352,258,353,259,354,260,355,261,356,262,357,263,358,264,359,265,360,266,361,267,362,268,363,269,364,270,365,271,366,272,367,273,368,274,369,275,370,276,371,277,372,278,373,279,374,280,375,281,376,282,377,283,378,284,379,285,380,286,381,287,382,192,383,193,288,194,385,291,386,292,387,293,388,294,389,295,390,296,391,297,392,298,393,299,394,300,395,301,396,302,397,303,398,304,399,305,400,306,401,307,402,308,403,309,404,310,405,311,406,312,407,313,408,314,409,315,410,316,411,317,412,318,413,319,414,320,415,321,416,322,417,323,418,324,419,325,420,326,421,327,422,328,423,329,424,330,425,331,426,332,427,333,428,334,429,335,430,336,431,337,432,338,433,339,434,340,435,341,436,342,437,343,438,344,439,345,440,346,441,347,442,348,443,349,444,350,445,351,446,352,447,353,448,354,449,355,450,356,451,357,452,358,453,359,454,360,455,361,456,362,457,363,458,364,459,365,460,366,461,367,462,368,463,369,464,370,465,371,466,372,467,373,468,374,469,375,470,376,471,377,472,378,473,379,474,380,475,381,476,382,477,383,478,288,479,289,384,290]}}}},{"replace":{"table":"Note","ids":{"count": 5},"fields":{"x":[-660,-660,-660,-660,-660],"y":[200,155,80,35,-40],"text":["480 BUSES","896 BRANCHES","Five concentric regions","One connected system","Synthetic topology / 01"]}}}]} diff --git a/crates/latkit-cli/examples/cli-gallery/helios.json b/crates/latkit-cli/examples/cli-gallery/helios.json new file mode 100644 index 00000000..1f89c0bc --- /dev/null +++ b/crates/latkit-cli/examples/cli-gallery/helios.json @@ -0,0 +1,80 @@ +{ + "space": { + "plane": { + "grid": "off" + } + }, + "ease": 0, + "theme": { + "background": "#080f1c", + "text": "#c7d5e4", + "font": "sans-serif", + "fontSize": 13, + "halo": 0, + "flow": "#d9fff0a0", + "flowSpacing": 100 + }, + "title": "01 / HELIOS", + "subtitle": "Flow through a synthetic transmission network", + "marks": [ + { + "edges": { + "of": [ + "art", + "Branch" + ], + "ends": [ + "from", + "to" + ], + "width": 0.85, + "flow": 18 + } + }, + { + "vertices": { + "of": [ + "art", + "Bus" + ], + "position": [ + "x", + "y" + ], + "radius": "radius", + "color": { + "colormap": "viridis", + "value": "heat", + "domain": [ + 0, + 1 + ] + }, + "label": { + "text": "name", + "size": 13, + "color": "#c0e5dd" + } + } + }, + { + "vertices": { + "of": [ + "art", + "Note" + ], + "position": [ + "x", + "y" + ], + "radius": 0, + "color": "#00000000", + "label": { + "text": "text", + "size": 17, + "color": "#9dcabf" + } + } + } + ] +} diff --git a/crates/latkit-cli/examples/cli-gallery/helios.png b/crates/latkit-cli/examples/cli-gallery/helios.png new file mode 100644 index 00000000..10394733 Binary files /dev/null and b/crates/latkit-cli/examples/cli-gallery/helios.png differ diff --git a/crates/latkit-cli/examples/cli-gallery/interference.data.json b/crates/latkit-cli/examples/cli-gallery/interference.data.json new file mode 100644 index 00000000..7df41cf4 --- /dev/null +++ b/crates/latkit-cli/examples/cli-gallery/interference.data.json @@ -0,0 +1 @@ +{"name":"art","patch":[{"replace":{"table":"Particle","ids":{"count": 33600},"fields":{"x":[-645.42,-640.07,-634.71,-629.36,-624.0,-618.65,-613.29,-607.93,-602.58,-597.22,-591.87,-586.51,-581.16,-575.8,-570.44,-565.09,-559.73,-554.38,-549.02,-543.67,-538.31,-532.96,-527.6,-522.24,-516.89,-511.53,-506.18,-500.82,-495.47,-490.11,-484.75,-479.4,-474.04,-468.69,-463.33,-457.98,-452.62,-447.26,-441.91,-436.55,-431.2,-425.84,-420.49,-415.13,-409.78,-404.42,-399.06,-393.71,-388.35,-383.0,-377.64,-372.29,-366.93,-361.57,-356.22,-350.86,-345.51,-340.15,-334.8,-329.44,-324.08,-318.73,-313.37,-308.02,-302.66,-297.31,-291.95,-286.6,-281.24,-275.88,-270.53,-265.17,-259.82,-254.46,-249.11,-243.75,-238.39,-233.04,-227.68,-222.33,-216.97,-211.62,-206.26,-200.9,-195.55,-190.19,-184.84,-179.48,-174.13,-168.77,-163.42,-158.06,-152.7,-147.35,-141.99,-136.64,-131.28,-125.93,-120.57,-115.21,-109.86,-104.5,-99.15,-93.79,-88.44,-83.08,-77.73,-72.37,-67.01,-61.66,-56.3,-50.95,-45.59,-40.24,-34.88,-29.52,-24.17,-18.81,-13.46,-8.1,-2.75,2.61,7.97,13.32,18.68,24.03,29.39,34.74,40.1,45.45,50.81,56.17,61.52,66.88,72.23,77.59,82.94,88.3,93.66,99.01,104.37,109.72,115.08,120.43,125.79,131.15,136.5,141.86,147.21,152.57,157.92,163.28,168.63,173.99,179.35,184.7,190.06,195.41,200.77,206.12,211.48,216.84,222.19,227.55,232.9,238.26,243.61,248.97,254.33,259.68,265.04,270.39,275.75,281.1,286.46,291.81,297.17,302.53,307.88,313.24,318.59,323.95,329.3,334.66,340.02,345.37,350.73,356.08,361.44,366.79,372.15,377.51,382.86,388.22,393.57,398.93,404.28,409.64,414.99,420.35,425.71,431.06,436.42,441.77,447.13,452.48,457.84,463.2,468.55,473.91,479.26,484.62,489.97,495.33,500.68,506.04,511.4,516.75,522.11,527.46,532.82,538.17,543.53,548.89,554.24,559.6,564.95,570.31,575.66,581.02,586.38,591.73,597.09,602.44,607.8,613.15,618.51,623.86,629.22,634.58,-644.77,-639.41,-634.06,-628.7,-623.34,-617.99,-612.63,-607.28,-601.92,-596.57,-591.21,-585.85,-580.5,-575.14,-569.79,-564.43,-559.08,-553.72,-548.37,-543.01,-537.65,-532.3,-526.94,-521.59,-516.23,-510.88,-505.52,-500.16,-494.81,-489.45,-484.1,-478.74,-473.39,-468.03,-462.67,-457.32,-451.96,-446.61,-441.25,-435.9,-430.54,-425.19,-419.83,-414.47,-409.12,-403.76,-398.41,-393.05,-387.7,-382.34,-376.98,-371.63,-366.27,-360.92,-355.56,-350.21,-344.85,-339.49,-334.14,-328.78,-323.43,-318.07,-312.72,-307.36,-302.01,-296.65,-291.29,-285.94,-280.58,-275.23,-269.87,-264.52,-259.16,-253.8,-248.45,-243.09,-237.74,-232.38,-227.03,-221.67,-216.31,-210.96,-205.6,-200.25,-194.89,-189.54,-184.18,-178.83,-173.47,-168.11,-162.76,-157.4,-152.05,-146.69,-141.34,-135.98,-130.62,-125.27,-119.91,-114.56,-109.2,-103.85,-98.49,-93.14,-87.78,-82.42,-77.07,-71.71,-66.36,-61.0,-55.65,-50.29,-44.93,-39.58,-34.22,-28.87,-23.51,-18.16,-12.8,-7.44,-2.09,3.27,8.62,13.98,19.33,24.69,30.04,35.4,40.76,46.11,51.47,56.82,62.18,67.53,72.89,78.25,83.6,88.96,94.31,99.67,105.02,110.38,115.74,121.09,126.45,131.8,137.16,142.51,147.87,153.22,158.58,163.94,169.29,174.65,180.0,185.36,190.71,196.07,201.43,206.78,212.14,217.49,222.85,228.2,233.56,238.92,244.27,249.63,254.98,260.34,265.69,271.05,276.4,281.76,287.12,292.47,297.83,303.18,308.54,313.89,319.25,324.61,329.96,335.32,340.67,346.03,351.38,356.74,362.1,367.45,372.81,378.16,383.52,388.87,394.23,399.58,404.94,410.3,415.65,421.01,426.36,431.72,437.07,442.43,447.79,453.14,458.5,463.85,469.21,474.56,479.92,485.28,490.63,495.99,501.34,506.7,512.05,517.41,522.76,528.12,533.48,538.83,544.19,549.54,554.9,560.25,565.61,570.97,576.32,581.68,587.03,592.39,597.74,603.1,608.45,613.81,619.17,624.52,629.88,635.23,-644.07,-638.72,-633.36,-628.01,-622.65,-617.29,-611.94,-606.58,-601.23,-595.87,-590.52,-585.16,-579.8,-574.45,-569.09,-563.74,-558.38,-553.03,-547.67,-542.32,-536.96,-531.6,-526.25,-520.89,-515.54,-510.18,-504.83,-499.47,-494.11,-488.76,-483.4,-478.05,-472.69,-467.34,-461.98,-456.62,-451.27,-445.91,-440.56,-435.2,-429.85,-424.49,-419.14,-413.78,-408.42,-403.07,-397.71,-392.36,-387.0,-381.65,-376.29,-370.93,-365.58,-360.22,-354.87,-349.51,-344.16,-338.8,-333.44,-328.09,-322.73,-317.38,-312.02,-306.67,-301.31,-295.96,-290.6,-285.24,-279.89,-274.53,-269.18,-263.82,-258.47,-253.11,-247.75,-242.4,-237.04,-231.69,-226.33,-220.98,-215.62,-210.26,-204.91,-199.55,-194.2,-188.84,-183.49,-178.13,-172.78,-167.42,-162.06,-156.71,-151.35,-146.0,-140.64,-135.29,-129.93,-124.57,-119.22,-113.86,-108.51,-103.15,-97.8,-92.44,-87.08,-81.73,-76.37,-71.02,-65.66,-60.31,-54.95,-49.6,-44.24,-38.88,-33.53,-28.17,-22.82,-17.46,-12.11,-6.75,-1.39,3.96,9.32,14.67,20.03,25.38,30.74,36.1,41.45,46.81,52.16,57.52,62.87,68.23,73.58,78.94,84.3,89.65,95.01,100.36,105.72,111.07,116.43,121.79,127.14,132.5,137.85,143.21,148.56,153.92,159.27,164.63,169.99,175.34,180.7,186.05,191.41,196.76,202.12,207.48,212.83,218.19,223.54,228.9,234.25,239.61,244.97,250.32,255.68,261.03,266.39,271.74,277.1,282.45,287.81,293.17,298.52,303.88,309.23,314.59,319.94,325.3,330.66,336.01,341.37,346.72,352.08,357.43,362.79,368.15,373.5,378.86,384.21,389.57,394.92,400.28,405.63,410.99,416.35,421.7,427.06,432.41,437.77,443.12,448.48,453.84,459.19,464.55,469.9,475.26,480.61,485.97,491.33,496.68,502.04,507.39,512.75,518.1,523.46,528.81,534.17,539.53,544.88,550.24,555.59,560.95,566.3,571.66,577.02,582.37,587.73,593.08,598.44,603.79,609.15,614.51,619.86,625.22,630.57,635.93,-643.35,-637.99,-632.63,-627.28,-621.92,-616.57,-611.21,-605.86,-600.5,-595.15,-589.79,-584.43,-579.08,-573.72,-568.37,-563.01,-557.66,-552.3,-546.94,-541.59,-536.23,-530.88,-525.52,-520.17,-514.81,-509.45,-504.1,-498.74,-493.39,-488.03,-482.68,-477.32,-471.97,-466.61,-461.25,-455.9,-450.54,-445.19,-439.83,-434.48,-429.12,-423.76,-418.41,-413.05,-407.7,-402.34,-396.99,-391.63,-386.27,-380.92,-375.56,-370.21,-364.85,-359.5,-354.14,-348.79,-343.43,-338.07,-332.72,-327.36,-322.01,-316.65,-311.3,-305.94,-300.58,-295.23,-289.87,-284.52,-279.16,-273.81,-268.45,-263.09,-257.74,-252.38,-247.03,-241.67,-236.32,-230.96,-225.61,-220.25,-214.89,-209.54,-204.18,-198.83,-193.47,-188.12,-182.76,-177.4,-172.05,-166.69,-161.34,-155.98,-150.63,-145.27,-139.91,-134.56,-129.2,-123.85,-118.49,-113.14,-107.78,-102.43,-97.07,-91.71,-86.36,-81.0,-75.65,-70.29,-64.94,-59.58,-54.22,-48.87,-43.51,-38.16,-32.8,-27.45,-22.09,-16.74,-11.38,-6.02,-0.67,4.69,10.04,15.4,20.75,26.11,31.47,36.82,42.18,47.53,52.89,58.24,63.6,68.96,74.31,79.67,85.02,90.38,95.73,101.09,106.44,111.8,117.16,122.51,127.87,133.22,138.58,143.93,149.29,154.65,160.0,165.36,170.71,176.07,181.42,186.78,192.14,197.49,202.85,208.2,213.56,218.91,224.27,229.62,234.98,240.34,245.69,251.05,256.4,261.76,267.11,272.47,277.83,283.18,288.54,293.89,299.25,304.6,309.96,315.32,320.67,326.03,331.38,336.74,342.09,347.45,352.8,358.16,363.52,368.87,374.23,379.58,384.94,390.29,395.65,401.01,406.36,411.72,417.07,422.43,427.78,433.14,438.5,443.85,449.21,454.56,459.92,465.27,470.63,475.98,481.34,486.7,492.05,497.41,502.76,508.12,513.47,518.83,524.19,529.54,534.9,540.25,545.61,550.96,556.32,561.67,567.03,572.39,577.74,583.1,588.45,593.81,599.16,604.52,609.88,615.23,620.59,625.94,631.3,636.65,-642.59,-637.24,-631.88,-626.53,-621.17,-615.82,-610.46,-605.1,-599.75,-594.39,-589.04,-583.68,-578.33,-572.97,-567.61,-562.26,-556.9,-551.55,-546.19,-540.84,-535.48,-530.12,-524.77,-519.41,-514.06,-508.7,-503.35,-497.99,-492.64,-487.28,-481.92,-476.57,-471.21,-465.86,-460.5,-455.15,-449.79,-444.43,-439.08,-433.72,-428.37,-423.01,-417.66,-412.3,-406.94,-401.59,-396.23,-390.88,-385.52,-380.17,-374.81,-369.46,-364.1,-358.74,-353.39,-348.03,-342.68,-337.32,-331.97,-326.61,-321.25,-315.9,-310.54,-305.19,-299.83,-294.48,-289.12,-283.76,-278.41,-273.05,-267.7,-262.34,-256.99,-251.63,-246.28,-240.92,-235.56,-230.21,-224.85,-219.5,-214.14,-208.79,-203.43,-198.07,-192.72,-187.36,-182.01,-176.65,-171.3,-165.94,-160.58,-155.23,-149.87,-144.52,-139.16,-133.81,-128.45,-123.1,-117.74,-112.38,-107.03,-101.67,-96.32,-90.96,-85.61,-80.25,-74.89,-69.54,-64.18,-58.83,-53.47,-48.12,-42.76,-37.4,-32.05,-26.69,-21.34,-15.98,-10.63,-5.27,0.08,5.44,10.8,16.15,21.51,26.86,32.22,37.57,42.93,48.29,53.64,59.0,64.35,69.71,75.06,80.42,85.77,91.13,96.49,101.84,107.2,112.55,117.91,123.26,128.62,133.98,139.33,144.69,150.04,155.4,160.75,166.11,171.47,176.82,182.18,187.53,192.89,198.24,203.6,208.95,214.31,219.67,225.02,230.38,235.73,241.09,246.44,251.8,257.16,262.51,267.87,273.22,278.58,283.93,289.29,294.65,300.0,305.36,310.71,316.07,321.42,326.78,332.13,337.49,342.85,348.2,353.56,358.91,364.27,369.62,374.98,380.34,385.69,391.05,396.4,401.76,407.11,412.47,417.83,423.18,428.54,433.89,439.25,444.6,449.96,455.31,460.67,466.03,471.38,476.74,482.09,487.45,492.8,498.16,503.52,508.87,514.23,519.58,524.94,530.29,535.65,541.01,546.36,551.72,557.07,562.43,567.78,573.14,578.49,583.85,589.21,594.56,599.92,605.27,610.63,615.98,621.34,626.7,632.05,637.41,-641.82,-636.46,-631.11,-625.75,-620.4,-615.04,-609.69,-604.33,-598.98,-593.62,-588.26,-582.91,-577.55,-572.2,-566.84,-561.49,-556.13,-550.77,-545.42,-540.06,-534.71,-529.35,-524.0,-518.64,-513.28,-507.93,-502.57,-497.22,-491.86,-486.51,-481.15,-475.8,-470.44,-465.08,-459.73,-454.37,-449.02,-443.66,-438.31,-432.95,-427.59,-422.24,-416.88,-411.53,-406.17,-400.82,-395.46,-390.1,-384.75,-379.39,-374.04,-368.68,-363.33,-357.97,-352.62,-347.26,-341.9,-336.55,-331.19,-325.84,-320.48,-315.13,-309.77,-304.41,-299.06,-293.7,-288.35,-282.99,-277.64,-272.28,-266.92,-261.57,-256.21,-250.86,-245.5,-240.15,-234.79,-229.44,-224.08,-218.72,-213.37,-208.01,-202.66,-197.3,-191.95,-186.59,-181.23,-175.88,-170.52,-165.17,-159.81,-154.46,-149.1,-143.74,-138.39,-133.03,-127.68,-122.32,-116.97,-111.61,-106.26,-100.9,-95.54,-90.19,-84.83,-79.48,-74.12,-68.77,-63.41,-58.05,-52.7,-47.34,-41.99,-36.63,-31.28,-25.92,-20.56,-15.21,-9.85,-4.5,0.86,6.21,11.57,16.92,22.28,27.64,32.99,38.35,43.7,49.06,54.41,59.77,65.13,70.48,75.84,81.19,86.55,91.9,97.26,102.61,107.97,113.33,118.68,124.04,129.39,134.75,140.1,145.46,150.82,156.17,161.53,166.88,172.24,177.59,182.95,188.31,193.66,199.02,204.37,209.73,215.08,220.44,225.79,231.15,236.51,241.86,247.22,252.57,257.93,263.28,268.64,274.0,279.35,284.71,290.06,295.42,300.77,306.13,311.49,316.84,322.2,327.55,332.91,338.26,343.62,348.97,354.33,359.69,365.04,370.4,375.75,381.11,386.46,391.82,397.18,402.53,407.89,413.24,418.6,423.95,429.31,434.67,440.02,445.38,450.73,456.09,461.44,466.8,472.15,477.51,482.87,488.22,493.58,498.93,504.29,509.64,515.0,520.36,525.71,531.07,536.42,541.78,547.13,552.49,557.85,563.2,568.56,573.91,579.27,584.62,589.98,595.33,600.69,606.05,611.4,616.76,622.11,627.47,632.82,638.18,-641.03,-635.68,-630.32,-624.97,-619.61,-614.25,-608.9,-603.54,-598.19,-592.83,-587.48,-582.12,-576.77,-571.41,-566.05,-560.7,-555.34,-549.99,-544.63,-539.28,-533.92,-528.56,-523.21,-517.85,-512.5,-507.14,-501.79,-496.43,-491.07,-485.72,-480.36,-475.01,-469.65,-464.3,-458.94,-453.59,-448.23,-442.87,-437.52,-432.16,-426.81,-421.45,-416.1,-410.74,-405.38,-400.03,-394.67,-389.32,-383.96,-378.61,-373.25,-367.89,-362.54,-357.18,-351.83,-346.47,-341.12,-335.76,-330.41,-325.05,-319.69,-314.34,-308.98,-303.63,-298.27,-292.92,-287.56,-282.2,-276.85,-271.49,-266.14,-260.78,-255.43,-250.07,-244.71,-239.36,-234.0,-228.65,-223.29,-217.94,-212.58,-207.23,-201.87,-196.51,-191.16,-185.8,-180.45,-175.09,-169.74,-164.38,-159.02,-153.67,-148.31,-142.96,-137.6,-132.25,-126.89,-121.53,-116.18,-110.82,-105.47,-100.11,-94.76,-89.4,-84.05,-78.69,-73.33,-67.98,-62.62,-57.27,-51.91,-46.56,-41.2,-35.84,-30.49,-25.13,-19.78,-14.42,-9.07,-3.71,1.64,7.0,12.36,17.71,23.07,28.42,33.78,39.13,44.49,49.85,55.2,60.56,65.91,71.27,76.62,81.98,87.34,92.69,98.05,103.4,108.76,114.11,119.47,124.82,130.18,135.54,140.89,146.25,151.6,156.96,162.31,167.67,173.03,178.38,183.74,189.09,194.45,199.8,205.16,210.52,215.87,221.23,226.58,231.94,237.29,242.65,248.0,253.36,258.72,264.07,269.43,274.78,280.14,285.49,290.85,296.21,301.56,306.92,312.27,317.63,322.98,328.34,333.7,339.05,344.41,349.76,355.12,360.47,365.83,371.18,376.54,381.9,387.25,392.61,397.96,403.32,408.67,414.03,419.39,424.74,430.1,435.45,440.81,446.16,451.52,456.88,462.23,467.59,472.94,478.3,483.65,489.01,494.36,499.72,505.08,510.43,515.79,521.14,526.5,531.85,537.21,542.57,547.92,553.28,558.63,563.99,569.34,574.7,580.06,585.41,590.77,596.12,601.48,606.83,612.19,617.54,622.9,628.26,633.61,638.97,-640.24,-634.88,-629.53,-624.17,-618.81,-613.46,-608.1,-602.75,-597.39,-592.04,-586.68,-581.33,-575.97,-570.61,-565.26,-559.9,-554.55,-549.19,-543.84,-538.48,-533.12,-527.77,-522.41,-517.06,-511.7,-506.35,-500.99,-495.63,-490.28,-484.92,-479.57,-474.21,-468.86,-463.5,-458.15,-452.79,-447.43,-442.08,-436.72,-431.37,-426.01,-420.66,-415.3,-409.94,-404.59,-399.23,-393.88,-388.52,-383.17,-377.81,-372.45,-367.1,-361.74,-356.39,-351.03,-345.68,-340.32,-334.97,-329.61,-324.25,-318.9,-313.54,-308.19,-302.83,-297.48,-292.12,-286.76,-281.41,-276.05,-270.7,-265.34,-259.99,-254.63,-249.28,-243.92,-238.56,-233.21,-227.85,-222.5,-217.14,-211.79,-206.43,-201.07,-195.72,-190.36,-185.01,-179.65,-174.3,-168.94,-163.58,-158.23,-152.87,-147.52,-142.16,-136.81,-131.45,-126.1,-120.74,-115.38,-110.03,-104.67,-99.32,-93.96,-88.61,-83.25,-77.89,-72.54,-67.18,-61.83,-56.47,-51.12,-45.76,-40.4,-35.05,-29.69,-24.34,-18.98,-13.63,-8.27,-2.92,2.44,7.8,13.15,18.51,23.86,29.22,34.57,39.93,45.29,50.64,56.0,61.35,66.71,72.06,77.42,82.78,88.13,93.49,98.84,104.2,109.55,114.91,120.26,125.62,130.98,136.33,141.69,147.04,152.4,157.75,163.11,168.47,173.82,179.18,184.53,189.89,195.24,200.6,205.96,211.31,216.67,222.02,227.38,232.73,238.09,243.44,248.8,254.16,259.51,264.87,270.22,275.58,280.93,286.29,291.65,297.0,302.36,307.71,313.07,318.42,323.78,329.13,334.49,339.85,345.2,350.56,355.91,361.27,366.62,371.98,377.34,382.69,388.05,393.4,398.76,404.11,409.47,414.83,420.18,425.54,430.89,436.25,441.6,446.96,452.31,457.67,463.03,468.38,473.74,479.09,484.45,489.8,495.16,500.52,505.87,511.23,516.58,521.94,527.29,532.65,538.01,543.36,548.72,554.07,559.43,564.78,570.14,575.49,580.85,586.21,591.56,596.92,602.27,607.63,612.98,618.34,623.7,629.05,634.41,639.76,-639.44,-634.08,-628.73,-623.37,-618.02,-612.66,-607.31,-601.95,-596.59,-591.24,-585.88,-580.53,-575.17,-569.82,-564.46,-559.11,-553.75,-548.39,-543.04,-537.68,-532.33,-526.97,-521.62,-516.26,-510.9,-505.55,-500.19,-494.84,-489.48,-484.13,-478.77,-473.42,-468.06,-462.7,-457.35,-451.99,-446.64,-441.28,-435.93,-430.57,-425.21,-419.86,-414.5,-409.15,-403.79,-398.44,-393.08,-387.72,-382.37,-377.01,-371.66,-366.3,-360.95,-355.59,-350.24,-344.88,-339.52,-334.17,-328.81,-323.46,-318.1,-312.75,-307.39,-302.03,-296.68,-291.32,-285.97,-280.61,-275.26,-269.9,-264.54,-259.19,-253.83,-248.48,-243.12,-237.77,-232.41,-227.06,-221.7,-216.34,-210.99,-205.63,-200.28,-194.92,-189.57,-184.21,-178.85,-173.5,-168.14,-162.79,-157.43,-152.08,-146.72,-141.36,-136.01,-130.65,-125.3,-119.94,-114.59,-109.23,-103.88,-98.52,-93.16,-87.81,-82.45,-77.1,-71.74,-66.39,-61.03,-55.67,-50.32,-44.96,-39.61,-34.25,-28.9,-23.54,-18.18,-12.83,-7.47,-2.12,3.24,8.59,13.95,19.3,24.66,30.02,35.37,40.73,46.08,51.44,56.79,62.15,67.51,72.86,78.22,83.57,88.93,94.28,99.64,105.0,110.35,115.71,121.06,126.42,131.77,137.13,142.48,147.84,153.2,158.55,163.91,169.26,174.62,179.97,185.33,190.69,196.04,201.4,206.75,212.11,217.46,222.82,228.17,233.53,238.89,244.24,249.6,254.95,260.31,265.66,271.02,276.38,281.73,287.09,292.44,297.8,303.15,308.51,313.87,319.22,324.58,329.93,335.29,340.64,346.0,351.35,356.71,362.07,367.42,372.78,378.13,383.49,388.84,394.2,399.56,404.91,410.27,415.62,420.98,426.33,431.69,437.05,442.4,447.76,453.11,458.47,463.82,469.18,474.53,479.89,485.25,490.6,495.96,501.31,506.67,512.02,517.38,522.74,528.09,533.45,538.8,544.16,549.51,554.87,560.23,565.58,570.94,576.29,581.65,587.0,592.36,597.71,603.07,608.43,613.78,619.14,624.49,629.85,635.2,640.56,-638.65,-633.29,-627.94,-622.58,-617.22,-611.87,-606.51,-601.16,-595.8,-590.45,-585.09,-579.74,-574.38,-569.02,-563.67,-558.31,-552.96,-547.6,-542.25,-536.89,-531.53,-526.18,-520.82,-515.47,-510.11,-504.76,-499.4,-494.04,-488.69,-483.33,-477.98,-472.62,-467.27,-461.91,-456.56,-451.2,-445.84,-440.49,-435.13,-429.78,-424.42,-419.07,-413.71,-408.35,-403.0,-397.64,-392.29,-386.93,-381.58,-376.22,-370.86,-365.51,-360.15,-354.8,-349.44,-344.09,-338.73,-333.38,-328.02,-322.66,-317.31,-311.95,-306.6,-301.24,-295.89,-290.53,-285.17,-279.82,-274.46,-269.11,-263.75,-258.4,-253.04,-247.68,-242.33,-236.97,-231.62,-226.26,-220.91,-215.55,-210.2,-204.84,-199.48,-194.13,-188.77,-183.42,-178.06,-172.71,-167.35,-161.99,-156.64,-151.28,-145.93,-140.57,-135.22,-129.86,-124.5,-119.15,-113.79,-108.44,-103.08,-97.73,-92.37,-87.02,-81.66,-76.3,-70.95,-65.59,-60.24,-54.88,-49.53,-44.17,-38.81,-33.46,-28.1,-22.75,-17.39,-12.04,-6.68,-1.33,4.03,9.39,14.74,20.1,25.45,30.81,36.16,41.52,46.88,52.23,57.59,62.94,68.3,73.65,79.01,84.37,89.72,95.08,100.43,105.79,111.14,116.5,121.85,127.21,132.57,137.92,143.28,148.63,153.99,159.34,164.7,170.06,175.41,180.77,186.12,191.48,196.83,202.19,207.55,212.9,218.26,223.61,228.97,234.32,239.68,245.03,250.39,255.75,261.1,266.46,271.81,277.17,282.52,287.88,293.24,298.59,303.95,309.3,314.66,320.01,325.37,330.73,336.08,341.44,346.79,352.15,357.5,362.86,368.21,373.57,378.93,384.28,389.64,394.99,400.35,405.7,411.06,416.42,421.77,427.13,432.48,437.84,443.19,448.55,453.91,459.26,464.62,469.97,475.33,480.68,486.04,491.39,496.75,502.11,507.46,512.82,518.17,523.53,528.88,534.24,539.6,544.95,550.31,555.66,561.02,566.37,571.73,577.09,582.44,587.8,593.15,598.51,603.86,609.22,614.57,619.93,625.29,630.64,636.0,641.35,-637.86,-632.51,-627.15,-621.8,-616.44,-611.09,-605.73,-600.38,-595.02,-589.66,-584.31,-578.95,-573.6,-568.24,-562.89,-557.53,-552.17,-546.82,-541.46,-536.11,-530.75,-525.4,-520.04,-514.68,-509.33,-503.97,-498.62,-493.26,-487.91,-482.55,-477.2,-471.84,-466.48,-461.13,-455.77,-450.42,-445.06,-439.71,-434.35,-428.99,-423.64,-418.28,-412.93,-407.57,-402.22,-396.86,-391.51,-386.15,-380.79,-375.44,-370.08,-364.73,-359.37,-354.02,-348.66,-343.3,-337.95,-332.59,-327.24,-321.88,-316.53,-311.17,-305.81,-300.46,-295.1,-289.75,-284.39,-279.04,-273.68,-268.33,-262.97,-257.61,-252.26,-246.9,-241.55,-236.19,-230.84,-225.48,-220.12,-214.77,-209.41,-204.06,-198.7,-193.35,-187.99,-182.63,-177.28,-171.92,-166.57,-161.21,-155.86,-150.5,-145.15,-139.79,-134.43,-129.08,-123.72,-118.37,-113.01,-107.66,-102.3,-96.94,-91.59,-86.23,-80.88,-75.52,-70.17,-64.81,-59.45,-54.1,-48.74,-43.39,-38.03,-32.68,-27.32,-21.97,-16.61,-11.25,-5.9,-0.54,4.81,10.17,15.52,20.88,26.24,31.59,36.95,42.3,47.66,53.01,58.37,63.73,69.08,74.44,79.79,85.15,90.5,95.86,101.21,106.57,111.93,117.28,122.64,127.99,133.35,138.7,144.06,149.42,154.77,160.13,165.48,170.84,176.19,181.55,186.9,192.26,197.62,202.97,208.33,213.68,219.04,224.39,229.75,235.11,240.46,245.82,251.17,256.53,261.88,267.24,272.6,277.95,283.31,288.66,294.02,299.37,304.73,310.08,315.44,320.8,326.15,331.51,336.86,342.22,347.57,352.93,358.29,363.64,369.0,374.35,379.71,385.06,390.42,395.78,401.13,406.49,411.84,417.2,422.55,427.91,433.26,438.62,443.98,449.33,454.69,460.04,465.4,470.75,476.11,481.47,486.82,492.18,497.53,502.89,508.24,513.6,518.96,524.31,529.67,535.02,540.38,545.73,551.09,556.44,561.8,567.16,572.51,577.87,583.22,588.58,593.93,599.29,604.65,610.0,615.36,620.71,626.07,631.42,636.78,642.14,-637.1,-631.74,-626.39,-621.03,-615.68,-610.32,-604.97,-599.61,-594.25,-588.9,-583.54,-578.19,-572.83,-567.48,-562.12,-556.76,-551.41,-546.05,-540.7,-535.34,-529.99,-524.63,-519.28,-513.92,-508.56,-503.21,-497.85,-492.5,-487.14,-481.79,-476.43,-471.07,-465.72,-460.36,-455.01,-449.65,-444.3,-438.94,-433.58,-428.23,-422.87,-417.52,-412.16,-406.81,-401.45,-396.1,-390.74,-385.38,-380.03,-374.67,-369.32,-363.96,-358.61,-353.25,-347.89,-342.54,-337.18,-331.83,-326.47,-321.12,-315.76,-310.4,-305.05,-299.69,-294.34,-288.98,-283.63,-278.27,-272.92,-267.56,-262.2,-256.85,-251.49,-246.14,-240.78,-235.43,-230.07,-224.71,-219.36,-214.0,-208.65,-203.29,-197.94,-192.58,-187.22,-181.87,-176.51,-171.16,-165.8,-160.45,-155.09,-149.74,-144.38,-139.02,-133.67,-128.31,-122.96,-117.6,-112.25,-106.89,-101.53,-96.18,-90.82,-85.47,-80.11,-74.76,-69.4,-64.04,-58.69,-53.33,-47.98,-42.62,-37.27,-31.91,-26.56,-21.2,-15.84,-10.49,-5.13,0.22,5.58,10.93,16.29,21.65,27.0,32.36,37.71,43.07,48.42,53.78,59.13,64.49,69.85,75.2,80.56,85.91,91.27,96.62,101.98,107.34,112.69,118.05,123.4,128.76,134.11,139.47,144.83,150.18,155.54,160.89,166.25,171.6,176.96,182.31,187.67,193.03,198.38,203.74,209.09,214.45,219.8,225.16,230.52,235.87,241.23,246.58,251.94,257.29,262.65,268.01,273.36,278.72,284.07,289.43,294.78,300.14,305.49,310.85,316.21,321.56,326.92,332.27,337.63,342.98,348.34,353.7,359.05,364.41,369.76,375.12,380.47,385.83,391.19,396.54,401.9,407.25,412.61,417.96,423.32,428.67,434.03,439.39,444.74,450.1,455.45,460.81,466.16,471.52,476.88,482.23,487.59,492.94,498.3,503.65,509.01,514.37,519.72,525.08,530.43,535.79,541.14,546.5,551.85,557.21,562.57,567.92,573.28,578.63,583.99,589.34,594.7,600.06,605.41,610.77,616.12,621.48,626.83,632.19,637.54,642.9,-636.36,-631.0,-625.65,-620.29,-614.93,-609.58,-604.22,-598.87,-593.51,-588.16,-582.8,-577.44,-572.09,-566.73,-561.38,-556.02,-550.67,-545.31,-539.95,-534.6,-529.24,-523.89,-518.53,-513.18,-507.82,-502.47,-497.11,-491.75,-486.4,-481.04,-475.69,-470.33,-464.98,-459.62,-454.26,-448.91,-443.55,-438.2,-432.84,-427.49,-422.13,-416.78,-411.42,-406.06,-400.71,-395.35,-390.0,-384.64,-379.29,-373.93,-368.57,-363.22,-357.86,-352.51,-347.15,-341.8,-336.44,-331.08,-325.73,-320.37,-315.02,-309.66,-304.31,-298.95,-293.6,-288.24,-282.88,-277.53,-272.17,-266.82,-261.46,-256.11,-250.75,-245.39,-240.04,-234.68,-229.33,-223.97,-218.62,-213.26,-207.9,-202.55,-197.19,-191.84,-186.48,-181.13,-175.77,-170.42,-165.06,-159.7,-154.35,-148.99,-143.64,-138.28,-132.93,-127.57,-122.21,-116.86,-111.5,-106.15,-100.79,-95.44,-90.08,-84.72,-79.37,-74.01,-68.66,-63.3,-57.95,-52.59,-47.24,-41.88,-36.52,-31.17,-25.81,-20.46,-15.1,-9.75,-4.39,0.97,6.32,11.68,17.03,22.39,27.74,33.1,38.46,43.81,49.17,54.52,59.88,65.23,70.59,75.94,81.3,86.66,92.01,97.37,102.72,108.08,113.43,118.79,124.15,129.5,134.86,140.21,145.57,150.92,156.28,161.64,166.99,172.35,177.7,183.06,188.41,193.77,199.12,204.48,209.84,215.19,220.55,225.9,231.26,236.61,241.97,247.33,252.68,258.04,263.39,268.75,274.1,279.46,284.81,290.17,295.53,300.88,306.24,311.59,316.95,322.3,327.66,333.02,338.37,343.73,349.08,354.44,359.79,365.15,370.51,375.86,381.22,386.57,391.93,397.28,402.64,407.99,413.35,418.71,424.06,429.42,434.77,440.13,445.48,450.84,456.2,461.55,466.91,472.26,477.62,482.97,488.33,493.69,499.04,504.4,509.75,515.11,520.46,525.82,531.17,536.53,541.89,547.24,552.6,557.95,563.31,568.66,574.02,579.38,584.73,590.09,595.44,600.8,606.15,611.51,616.87,622.22,627.58,632.93,638.29,643.64,-635.64,-630.29,-624.93,-619.58,-614.22,-608.86,-603.51,-598.15,-592.8,-587.44,-582.09,-576.73,-571.37,-566.02,-560.66,-555.31,-549.95,-544.6,-539.24,-533.89,-528.53,-523.17,-517.82,-512.46,-507.11,-501.75,-496.4,-491.04,-485.68,-480.33,-474.97,-469.62,-464.26,-458.91,-453.55,-448.19,-442.84,-437.48,-432.13,-426.77,-421.42,-416.06,-410.71,-405.35,-399.99,-394.64,-389.28,-383.93,-378.57,-373.22,-367.86,-362.5,-357.15,-351.79,-346.44,-341.08,-335.73,-330.37,-325.01,-319.66,-314.3,-308.95,-303.59,-298.24,-292.88,-287.53,-282.17,-276.81,-271.46,-266.1,-260.75,-255.39,-250.04,-244.68,-239.32,-233.97,-228.61,-223.26,-217.9,-212.55,-207.19,-201.83,-196.48,-191.12,-185.77,-180.41,-175.06,-169.7,-164.35,-158.99,-153.63,-148.28,-142.92,-137.57,-132.21,-126.86,-121.5,-116.14,-110.79,-105.43,-100.08,-94.72,-89.37,-84.01,-78.66,-73.3,-67.94,-62.59,-57.23,-51.88,-46.52,-41.17,-35.81,-30.45,-25.1,-19.74,-14.39,-9.03,-3.68,1.68,7.04,12.39,17.75,23.1,28.46,33.81,39.17,44.52,49.88,55.24,60.59,65.95,71.3,76.66,82.01,87.37,92.73,98.08,103.44,108.79,114.15,119.5,124.86,130.22,135.57,140.93,146.28,151.64,156.99,162.35,167.7,173.06,178.42,183.77,189.13,194.48,199.84,205.19,210.55,215.91,221.26,226.62,231.97,237.33,242.68,248.04,253.4,258.75,264.11,269.46,274.82,280.17,285.53,290.88,296.24,301.6,306.95,312.31,317.66,323.02,328.37,333.73,339.09,344.44,349.8,355.15,360.51,365.86,371.22,376.58,381.93,387.29,392.64,398.0,403.35,408.71,414.06,419.42,424.78,430.13,435.49,440.84,446.2,451.55,456.91,462.27,467.62,472.98,478.33,483.69,489.04,494.4,499.76,505.11,510.47,515.82,521.18,526.53,531.89,537.24,542.6,547.96,553.31,558.67,564.02,569.38,574.73,580.09,585.45,590.8,596.16,601.51,606.87,612.22,617.58,622.93,628.29,633.65,639.0,644.36,-634.96,-629.61,-624.25,-618.9,-613.54,-608.18,-602.83,-597.47,-592.12,-586.76,-581.41,-576.05,-570.69,-565.34,-559.98,-554.63,-549.27,-543.92,-538.56,-533.21,-527.85,-522.49,-517.14,-511.78,-506.43,-501.07,-495.72,-490.36,-485.0,-479.65,-474.29,-468.94,-463.58,-458.23,-452.87,-447.51,-442.16,-436.8,-431.45,-426.09,-420.74,-415.38,-410.03,-404.67,-399.31,-393.96,-388.6,-383.25,-377.89,-372.54,-367.18,-361.82,-356.47,-351.11,-345.76,-340.4,-335.05,-329.69,-324.33,-318.98,-313.62,-308.27,-302.91,-297.56,-292.2,-286.85,-281.49,-276.13,-270.78,-265.42,-260.07,-254.71,-249.36,-244.0,-238.64,-233.29,-227.93,-222.58,-217.22,-211.87,-206.51,-201.15,-195.8,-190.44,-185.09,-179.73,-174.38,-169.02,-163.67,-158.31,-152.95,-147.6,-142.24,-136.89,-131.53,-126.18,-120.82,-115.46,-110.11,-104.75,-99.4,-94.04,-88.69,-83.33,-77.98,-72.62,-67.26,-61.91,-56.55,-51.2,-45.84,-40.49,-35.13,-29.77,-24.42,-19.06,-13.71,-8.35,-3.0,2.36,7.72,13.07,18.43,23.78,29.14,34.49,39.85,45.2,50.56,55.92,61.27,66.63,71.98,77.34,82.69,88.05,93.41,98.76,104.12,109.47,114.83,120.18,125.54,130.9,136.25,141.61,146.96,152.32,157.67,163.03,168.38,173.74,179.1,184.45,189.81,195.16,200.52,205.87,211.23,216.59,221.94,227.3,232.65,238.01,243.36,248.72,254.08,259.43,264.79,270.14,275.5,280.85,286.21,291.56,296.92,302.28,307.63,312.99,318.34,323.7,329.05,334.41,339.77,345.12,350.48,355.83,361.19,366.54,371.9,377.26,382.61,387.97,393.32,398.68,404.03,409.39,414.74,420.1,425.46,430.81,436.17,441.52,446.88,452.23,457.59,462.95,468.3,473.66,479.01,484.37,489.72,495.08,500.43,505.79,511.15,516.5,521.86,527.21,532.57,537.92,543.28,548.64,553.99,559.35,564.7,570.06,575.41,580.77,586.13,591.48,596.84,602.19,607.55,612.9,618.26,623.61,628.97,634.33,639.68,645.04,-634.32,-628.97,-623.61,-618.26,-612.9,-607.54,-602.19,-596.83,-591.48,-586.12,-580.77,-575.41,-570.05,-564.7,-559.34,-553.99,-548.63,-543.28,-537.92,-532.56,-527.21,-521.85,-516.5,-511.14,-505.79,-500.43,-495.08,-489.72,-484.36,-479.01,-473.65,-468.3,-462.94,-457.59,-452.23,-446.87,-441.52,-436.16,-430.81,-425.45,-420.1,-414.74,-409.38,-404.03,-398.67,-393.32,-387.96,-382.61,-377.25,-371.9,-366.54,-361.18,-355.83,-350.47,-345.12,-339.76,-334.41,-329.05,-323.69,-318.34,-312.98,-307.63,-302.27,-296.92,-291.56,-286.2,-280.85,-275.49,-270.14,-264.78,-259.43,-254.07,-248.72,-243.36,-238.0,-232.65,-227.29,-221.94,-216.58,-211.23,-205.87,-200.51,-195.16,-189.8,-184.45,-179.09,-173.74,-168.38,-163.03,-157.67,-152.31,-146.96,-141.6,-136.25,-130.89,-125.54,-120.18,-114.82,-109.47,-104.11,-98.76,-93.4,-88.05,-82.69,-77.33,-71.98,-66.62,-61.27,-55.91,-50.56,-45.2,-39.85,-34.49,-29.13,-23.78,-18.42,-13.07,-7.71,-2.36,3.0,8.36,13.71,19.07,24.42,29.78,35.13,40.49,45.85,51.2,56.56,61.91,67.27,72.62,77.98,83.33,88.69,94.05,99.4,104.76,110.11,115.47,120.82,126.18,131.54,136.89,142.25,147.6,152.96,158.31,163.67,169.03,174.38,179.74,185.09,190.45,195.8,201.16,206.51,211.87,217.23,222.58,227.94,233.29,238.65,244.0,249.36,254.72,260.07,265.43,270.78,276.14,281.49,286.85,292.21,297.56,302.92,308.27,313.63,318.98,324.34,329.69,335.05,340.41,345.76,351.12,356.47,361.83,367.18,372.54,377.9,383.25,388.61,393.96,399.32,404.67,410.03,415.38,420.74,426.1,431.45,436.81,442.16,447.52,452.87,458.23,463.59,468.94,474.3,479.65,485.01,490.36,495.72,501.08,506.43,511.79,517.14,522.5,527.85,533.21,538.56,543.92,549.28,554.63,559.99,565.34,570.7,576.05,581.41,586.77,592.12,597.48,602.83,608.19,613.54,618.9,624.26,629.61,634.97,640.32,645.68,-633.73,-628.37,-623.01,-617.66,-612.3,-606.95,-601.59,-596.24,-590.88,-585.53,-580.17,-574.81,-569.46,-564.1,-558.75,-553.39,-548.04,-542.68,-537.32,-531.97,-526.61,-521.26,-515.9,-510.55,-505.19,-499.84,-494.48,-489.12,-483.77,-478.41,-473.06,-467.7,-462.35,-456.99,-451.63,-446.28,-440.92,-435.57,-430.21,-424.86,-419.5,-414.14,-408.79,-403.43,-398.08,-392.72,-387.37,-382.01,-376.66,-371.3,-365.94,-360.59,-355.23,-349.88,-344.52,-339.17,-333.81,-328.45,-323.1,-317.74,-312.39,-307.03,-301.68,-296.32,-290.96,-285.61,-280.25,-274.9,-269.54,-264.19,-258.83,-253.48,-248.12,-242.76,-237.41,-232.05,-226.7,-221.34,-215.99,-210.63,-205.27,-199.92,-194.56,-189.21,-183.85,-178.5,-173.14,-167.78,-162.43,-157.07,-151.72,-146.36,-141.01,-135.65,-130.3,-124.94,-119.58,-114.23,-108.87,-103.52,-98.16,-92.81,-87.45,-82.09,-76.74,-71.38,-66.03,-60.67,-55.32,-49.96,-44.6,-39.25,-33.89,-28.54,-23.18,-17.83,-12.47,-7.12,-1.76,3.6,8.95,14.31,19.66,25.02,30.37,35.73,41.09,46.44,51.8,57.15,62.51,67.86,73.22,78.57,83.93,89.29,94.64,100.0,105.35,110.71,116.06,121.42,126.78,132.13,137.49,142.84,148.2,153.55,158.91,164.27,169.62,174.98,180.33,185.69,191.04,196.4,201.75,207.11,212.47,217.82,223.18,228.53,233.89,239.24,244.6,249.96,255.31,260.67,266.02,271.38,276.73,282.09,287.45,292.8,298.16,303.51,308.87,314.22,319.58,324.93,330.29,335.65,341.0,346.36,351.71,357.07,362.42,367.78,373.14,378.49,383.85,389.2,394.56,399.91,405.27,410.63,415.98,421.34,426.69,432.05,437.4,442.76,448.11,453.47,458.83,464.18,469.54,474.89,480.25,485.6,490.96,496.32,501.67,507.03,512.38,517.74,523.09,528.45,533.81,539.16,544.52,549.87,555.23,560.58,565.94,571.29,576.65,582.01,587.36,592.72,598.07,603.43,608.78,614.14,619.5,624.85,630.21,635.56,640.92,646.27,-633.18,-627.82,-622.47,-617.11,-611.76,-606.4,-601.05,-595.69,-590.33,-584.98,-579.62,-574.27,-568.91,-563.56,-558.2,-552.84,-547.49,-542.13,-536.78,-531.42,-526.07,-520.71,-515.36,-510.0,-504.64,-499.29,-493.93,-488.58,-483.22,-477.87,-472.51,-467.15,-461.8,-456.44,-451.09,-445.73,-440.38,-435.02,-429.67,-424.31,-418.95,-413.6,-408.24,-402.89,-397.53,-392.18,-386.82,-381.46,-376.11,-370.75,-365.4,-360.04,-354.69,-349.33,-343.97,-338.62,-333.26,-327.91,-322.55,-317.2,-311.84,-306.49,-301.13,-295.77,-290.42,-285.06,-279.71,-274.35,-269.0,-263.64,-258.28,-252.93,-247.57,-242.22,-236.86,-231.51,-226.15,-220.79,-215.44,-210.08,-204.73,-199.37,-194.02,-188.66,-183.31,-177.95,-172.59,-167.24,-161.88,-156.53,-151.17,-145.82,-140.46,-135.1,-129.75,-124.39,-119.04,-113.68,-108.33,-102.97,-97.61,-92.26,-86.9,-81.55,-76.19,-70.84,-65.48,-60.13,-54.77,-49.41,-44.06,-38.7,-33.35,-27.99,-22.64,-17.28,-11.92,-6.57,-1.21,4.14,9.5,14.85,20.21,25.57,30.92,36.28,41.63,46.99,52.34,57.7,63.05,68.41,73.77,79.12,84.48,89.83,95.19,100.54,105.9,111.26,116.61,121.97,127.32,132.68,138.03,143.39,148.74,154.1,159.46,164.81,170.17,175.52,180.88,186.23,191.59,196.95,202.3,207.66,213.01,218.37,223.72,229.08,234.44,239.79,245.15,250.5,255.86,261.21,266.57,271.92,277.28,282.64,287.99,293.35,298.7,304.06,309.41,314.77,320.13,325.48,330.84,336.19,341.55,346.9,352.26,357.62,362.97,368.33,373.68,379.04,384.39,389.75,395.1,400.46,405.82,411.17,416.53,421.88,427.24,432.59,437.95,443.31,448.66,454.02,459.37,464.73,470.08,475.44,480.8,486.15,491.51,496.86,502.22,507.57,512.93,518.28,523.64,529.0,534.35,539.71,545.06,550.42,555.77,561.13,566.49,571.84,577.2,582.55,587.91,593.26,598.62,603.98,609.33,614.69,620.04,625.4,630.75,636.11,641.46,646.82,-632.69,-627.33,-621.98,-616.62,-611.26,-605.91,-600.55,-595.2,-589.84,-584.49,-579.13,-573.77,-568.42,-563.06,-557.71,-552.35,-547.0,-541.64,-536.29,-530.93,-525.57,-520.22,-514.86,-509.51,-504.15,-498.8,-493.44,-488.08,-482.73,-477.37,-472.02,-466.66,-461.31,-455.95,-450.59,-445.24,-439.88,-434.53,-429.17,-423.82,-418.46,-413.11,-407.75,-402.39,-397.04,-391.68,-386.33,-380.97,-375.62,-370.26,-364.9,-359.55,-354.19,-348.84,-343.48,-338.13,-332.77,-327.41,-322.06,-316.7,-311.35,-305.99,-300.64,-295.28,-289.93,-284.57,-279.21,-273.86,-268.5,-263.15,-257.79,-252.44,-247.08,-241.72,-236.37,-231.01,-225.66,-220.3,-214.95,-209.59,-204.23,-198.88,-193.52,-188.17,-182.81,-177.46,-172.1,-166.75,-161.39,-156.03,-150.68,-145.32,-139.97,-134.61,-129.26,-123.9,-118.54,-113.19,-107.83,-102.48,-97.12,-91.77,-86.41,-81.05,-75.7,-70.34,-64.99,-59.63,-54.28,-48.92,-43.57,-38.21,-32.85,-27.5,-22.14,-16.79,-11.43,-6.08,-0.72,4.64,9.99,15.35,20.7,26.06,31.41,36.77,42.13,47.48,52.84,58.19,63.55,68.9,74.26,79.61,84.97,90.33,95.68,101.04,106.39,111.75,117.1,122.46,127.82,133.17,138.53,143.88,149.24,154.59,159.95,165.3,170.66,176.02,181.37,186.73,192.08,197.44,202.79,208.15,213.51,218.86,224.22,229.57,234.93,240.28,245.64,251.0,256.35,261.71,267.06,272.42,277.77,283.13,288.48,293.84,299.2,304.55,309.91,315.26,320.62,325.97,331.33,336.69,342.04,347.4,352.75,358.11,363.46,368.82,374.18,379.53,384.89,390.24,395.6,400.95,406.31,411.66,417.02,422.38,427.73,433.09,438.44,443.8,449.15,454.51,459.87,465.22,470.58,475.93,481.29,486.64,492.0,497.36,502.71,508.07,513.42,518.78,524.13,529.49,534.84,540.2,545.56,550.91,556.27,561.62,566.98,572.33,577.69,583.05,588.4,593.76,599.11,604.47,609.82,615.18,620.54,625.89,631.25,636.6,641.96,647.31,-632.25,-626.9,-621.54,-616.18,-610.83,-605.47,-600.12,-594.76,-589.41,-584.05,-578.69,-573.34,-567.98,-562.63,-557.27,-551.92,-546.56,-541.21,-535.85,-530.49,-525.14,-519.78,-514.43,-509.07,-503.72,-498.36,-493.0,-487.65,-482.29,-476.94,-471.58,-466.23,-460.87,-455.51,-450.16,-444.8,-439.45,-434.09,-428.74,-423.38,-418.03,-412.67,-407.31,-401.96,-396.6,-391.25,-385.89,-380.54,-375.18,-369.82,-364.47,-359.11,-353.76,-348.4,-343.05,-337.69,-332.33,-326.98,-321.62,-316.27,-310.91,-305.56,-300.2,-294.85,-289.49,-284.13,-278.78,-273.42,-268.07,-262.71,-257.36,-252.0,-246.64,-241.29,-235.93,-230.58,-225.22,-219.87,-214.51,-209.15,-203.8,-198.44,-193.09,-187.73,-182.38,-177.02,-171.67,-166.31,-160.95,-155.6,-150.24,-144.89,-139.53,-134.18,-128.82,-123.46,-118.11,-112.75,-107.4,-102.04,-96.69,-91.33,-85.97,-80.62,-75.26,-69.91,-64.55,-59.2,-53.84,-48.49,-43.13,-37.77,-32.42,-27.06,-21.71,-16.35,-11.0,-5.64,-0.28,5.07,10.43,15.78,21.14,26.49,31.85,37.2,42.56,47.92,53.27,58.63,63.98,69.34,74.69,80.05,85.41,90.76,96.12,101.47,106.83,112.18,117.54,122.9,128.25,133.61,138.96,144.32,149.67,155.03,160.38,165.74,171.1,176.45,181.81,187.16,192.52,197.87,203.23,208.59,213.94,219.3,224.65,230.01,235.36,240.72,246.08,251.43,256.79,262.14,267.5,272.85,278.21,283.56,288.92,294.28,299.63,304.99,310.34,315.7,321.05,326.41,331.77,337.12,342.48,347.83,353.19,358.54,363.9,369.26,374.61,379.97,385.32,390.68,396.03,401.39,406.74,412.1,417.46,422.81,428.17,433.52,438.88,444.23,449.59,454.95,460.3,465.66,471.01,476.37,481.72,487.08,492.44,497.79,503.15,508.5,513.86,519.21,524.57,529.92,535.28,540.64,545.99,551.35,556.7,562.06,567.41,572.77,578.13,583.48,588.84,594.19,599.55,604.9,610.26,615.62,620.97,626.33,631.68,637.04,642.39,647.75,-631.88,-626.52,-621.17,-615.81,-610.45,-605.1,-599.74,-594.39,-589.03,-583.68,-578.32,-572.96,-567.61,-562.25,-556.9,-551.54,-546.19,-540.83,-535.47,-530.12,-524.76,-519.41,-514.05,-508.7,-503.34,-497.99,-492.63,-487.27,-481.92,-476.56,-471.21,-465.85,-460.5,-455.14,-449.78,-444.43,-439.07,-433.72,-428.36,-423.01,-417.65,-412.29,-406.94,-401.58,-396.23,-390.87,-385.52,-380.16,-374.81,-369.45,-364.09,-358.74,-353.38,-348.03,-342.67,-337.32,-331.96,-326.6,-321.25,-315.89,-310.54,-305.18,-299.83,-294.47,-289.11,-283.76,-278.4,-273.05,-267.69,-262.34,-256.98,-251.63,-246.27,-240.91,-235.56,-230.2,-224.85,-219.49,-214.14,-208.78,-203.42,-198.07,-192.71,-187.36,-182.0,-176.65,-171.29,-165.93,-160.58,-155.22,-149.87,-144.51,-139.16,-133.8,-128.45,-123.09,-117.73,-112.38,-107.02,-101.67,-96.31,-90.96,-85.6,-80.24,-74.89,-69.53,-64.18,-58.82,-53.47,-48.11,-42.75,-37.4,-32.04,-26.69,-21.33,-15.98,-10.62,-5.27,0.09,5.45,10.8,16.16,21.51,26.87,32.22,37.58,42.94,48.29,53.65,59.0,64.36,69.71,75.07,80.42,85.78,91.14,96.49,101.85,107.2,112.56,117.91,123.27,128.63,133.98,139.34,144.69,150.05,155.4,160.76,166.12,171.47,176.83,182.18,187.54,192.89,198.25,203.6,208.96,214.32,219.67,225.03,230.38,235.74,241.09,246.45,251.81,257.16,262.52,267.87,273.23,278.58,283.94,289.3,294.65,300.01,305.36,310.72,316.07,321.43,326.78,332.14,337.5,342.85,348.21,353.56,358.92,364.27,369.63,374.99,380.34,385.7,391.05,396.41,401.76,407.12,412.48,417.83,423.19,428.54,433.9,439.25,444.61,449.96,455.32,460.68,466.03,471.39,476.74,482.1,487.45,492.81,498.17,503.52,508.88,514.23,519.59,524.94,530.3,535.66,541.01,546.37,551.72,557.08,562.43,567.79,573.14,578.5,583.86,589.21,594.57,599.92,605.28,610.63,615.99,621.35,626.7,632.06,637.41,642.77,648.12,-631.57,-626.21,-620.85,-615.5,-610.14,-604.79,-599.43,-594.08,-588.72,-583.36,-578.01,-572.65,-567.3,-561.94,-556.59,-551.23,-545.87,-540.52,-535.16,-529.81,-524.45,-519.1,-513.74,-508.39,-503.03,-497.67,-492.32,-486.96,-481.61,-476.25,-470.9,-465.54,-460.18,-454.83,-449.47,-444.12,-438.76,-433.41,-428.05,-422.7,-417.34,-411.98,-406.63,-401.27,-395.92,-390.56,-385.21,-379.85,-374.49,-369.14,-363.78,-358.43,-353.07,-347.72,-342.36,-337.0,-331.65,-326.29,-320.94,-315.58,-310.23,-304.87,-299.52,-294.16,-288.8,-283.45,-278.09,-272.74,-267.38,-262.03,-256.67,-251.31,-245.96,-240.6,-235.25,-229.89,-224.54,-219.18,-213.82,-208.47,-203.11,-197.76,-192.4,-187.05,-181.69,-176.34,-170.98,-165.62,-160.27,-154.91,-149.56,-144.2,-138.85,-133.49,-128.13,-122.78,-117.42,-112.07,-106.71,-101.36,-96.0,-90.64,-85.29,-79.93,-74.58,-69.22,-63.87,-58.51,-53.16,-47.8,-42.44,-37.09,-31.73,-26.38,-21.02,-15.67,-10.31,-4.95,0.4,5.76,11.11,16.47,21.82,27.18,32.54,37.89,43.25,48.6,53.96,59.31,64.67,70.02,75.38,80.74,86.09,91.45,96.8,102.16,107.51,112.87,118.23,123.58,128.94,134.29,139.65,145.0,150.36,155.72,161.07,166.43,171.78,177.14,182.49,187.85,193.2,198.56,203.92,209.27,214.63,219.98,225.34,230.69,236.05,241.41,246.76,252.12,257.47,262.83,268.18,273.54,278.89,284.25,289.61,294.96,300.32,305.67,311.03,316.38,321.74,327.1,332.45,337.81,343.16,348.52,353.87,359.23,364.59,369.94,375.3,380.65,386.01,391.36,396.72,402.07,407.43,412.79,418.14,423.5,428.85,434.21,439.56,444.92,450.28,455.63,460.99,466.34,471.7,477.05,482.41,487.77,493.12,498.48,503.83,509.19,514.54,519.9,525.25,530.61,535.97,541.32,546.68,552.03,557.39,562.74,568.1,573.46,578.81,584.17,589.52,594.88,600.23,605.59,610.95,616.3,621.66,627.01,632.37,637.72,643.08,648.43,-631.32,-625.96,-620.61,-615.25,-609.9,-604.54,-599.19,-593.83,-588.48,-583.12,-577.76,-572.41,-567.05,-561.7,-556.34,-550.99,-545.63,-540.27,-534.92,-529.56,-524.21,-518.85,-513.5,-508.14,-502.78,-497.43,-492.07,-486.72,-481.36,-476.01,-470.65,-465.3,-459.94,-454.58,-449.23,-443.87,-438.52,-433.16,-427.81,-422.45,-417.09,-411.74,-406.38,-401.03,-395.67,-390.32,-384.96,-379.61,-374.25,-368.89,-363.54,-358.18,-352.83,-347.47,-342.12,-336.76,-331.4,-326.05,-320.69,-315.34,-309.98,-304.63,-299.27,-293.91,-288.56,-283.2,-277.85,-272.49,-267.14,-261.78,-256.43,-251.07,-245.71,-240.36,-235.0,-229.65,-224.29,-218.94,-213.58,-208.22,-202.87,-197.51,-192.16,-186.8,-181.45,-176.09,-170.73,-165.38,-160.02,-154.67,-149.31,-143.96,-138.6,-133.25,-127.89,-122.53,-117.18,-111.82,-106.47,-101.11,-95.76,-90.4,-85.04,-79.69,-74.33,-68.98,-63.62,-58.27,-52.91,-47.55,-42.2,-36.84,-31.49,-26.13,-20.78,-15.42,-10.07,-4.71,0.65,6.0,11.36,16.71,22.07,27.42,32.78,38.14,43.49,48.85,54.2,59.56,64.91,70.27,75.63,80.98,86.34,91.69,97.05,102.4,107.76,113.11,118.47,123.83,129.18,134.54,139.89,145.25,150.6,155.96,161.32,166.67,172.03,177.38,182.74,188.09,193.45,198.81,204.16,209.52,214.87,220.23,225.58,230.94,236.29,241.65,247.01,252.36,257.72,263.07,268.43,273.78,279.14,284.5,289.85,295.21,300.56,305.92,311.27,316.63,321.98,327.34,332.7,338.05,343.41,348.76,354.12,359.47,364.83,370.19,375.54,380.9,386.25,391.61,396.96,402.32,407.68,413.03,418.39,423.74,429.1,434.45,439.81,445.16,450.52,455.88,461.23,466.59,471.94,477.3,482.65,488.01,493.37,498.72,504.08,509.43,514.79,520.14,525.5,530.86,536.21,541.57,546.92,552.28,557.63,562.99,568.34,573.7,579.06,584.41,589.77,595.12,600.48,605.83,611.19,616.55,621.9,627.26,632.61,637.97,643.32,648.68,-631.14,-625.79,-620.43,-615.08,-609.72,-604.37,-599.01,-593.65,-588.3,-582.94,-577.59,-572.23,-566.88,-561.52,-556.16,-550.81,-545.45,-540.1,-534.74,-529.39,-524.03,-518.68,-513.32,-507.96,-502.61,-497.25,-491.9,-486.54,-481.19,-475.83,-470.47,-465.12,-459.76,-454.41,-449.05,-443.7,-438.34,-432.98,-427.63,-422.27,-416.92,-411.56,-406.21,-400.85,-395.5,-390.14,-384.78,-379.43,-374.07,-368.72,-363.36,-358.01,-352.65,-347.29,-341.94,-336.58,-331.23,-325.87,-320.52,-315.16,-309.8,-304.45,-299.09,-293.74,-288.38,-283.03,-277.67,-272.32,-266.96,-261.6,-256.25,-250.89,-245.54,-240.18,-234.83,-229.47,-224.11,-218.76,-213.4,-208.05,-202.69,-197.34,-191.98,-186.63,-181.27,-175.91,-170.56,-165.2,-159.85,-154.49,-149.14,-143.78,-138.42,-133.07,-127.71,-122.36,-117.0,-111.65,-106.29,-100.93,-95.58,-90.22,-84.87,-79.51,-74.16,-68.8,-63.45,-58.09,-52.73,-47.38,-42.02,-36.67,-31.31,-25.96,-20.6,-15.24,-9.89,-4.53,0.82,6.18,11.53,16.89,22.25,27.6,32.96,38.31,43.67,49.02,54.38,59.73,65.09,70.45,75.8,81.16,86.51,91.87,97.22,102.58,107.94,113.29,118.65,124.0,129.36,134.71,140.07,145.43,150.78,156.14,161.49,166.85,172.2,177.56,182.91,188.27,193.63,198.98,204.34,209.69,215.05,220.4,225.76,231.12,236.47,241.83,247.18,252.54,257.89,263.25,268.61,273.96,279.32,284.67,290.03,295.38,300.74,306.09,311.45,316.81,322.16,327.52,332.87,338.23,343.58,348.94,354.3,359.65,365.01,370.36,375.72,381.07,386.43,391.78,397.14,402.5,407.85,413.21,418.56,423.92,429.27,434.63,439.99,445.34,450.7,456.05,461.41,466.76,472.12,477.48,482.83,488.19,493.54,498.9,504.25,509.61,514.96,520.32,525.68,531.03,536.39,541.74,547.1,552.45,557.81,563.17,568.52,573.88,579.23,584.59,589.94,595.3,600.66,606.01,611.37,616.72,622.08,627.43,632.79,638.14,643.5,648.86,-631.04,-625.68,-620.33,-614.97,-609.61,-604.26,-598.9,-593.55,-588.19,-582.84,-577.48,-572.12,-566.77,-561.41,-556.06,-550.7,-545.35,-539.99,-534.64,-529.28,-523.92,-518.57,-513.21,-507.86,-502.5,-497.15,-491.79,-486.43,-481.08,-475.72,-470.37,-465.01,-459.66,-454.3,-448.94,-443.59,-438.23,-432.88,-427.52,-422.17,-416.81,-411.46,-406.1,-400.74,-395.39,-390.03,-384.68,-379.32,-373.97,-368.61,-363.25,-357.9,-352.54,-347.19,-341.83,-336.48,-331.12,-325.76,-320.41,-315.05,-309.7,-304.34,-298.99,-293.63,-288.28,-282.92,-277.56,-272.21,-266.85,-261.5,-256.14,-250.79,-245.43,-240.07,-234.72,-229.36,-224.01,-218.65,-213.3,-207.94,-202.58,-197.23,-191.87,-186.52,-181.16,-175.81,-170.45,-165.1,-159.74,-154.38,-149.03,-143.67,-138.32,-132.96,-127.61,-122.25,-116.89,-111.54,-106.18,-100.83,-95.47,-90.12,-84.76,-79.4,-74.05,-68.69,-63.34,-57.98,-52.63,-47.27,-41.92,-36.56,-31.2,-25.85,-20.49,-15.14,-9.78,-4.43,0.93,6.29,11.64,17.0,22.35,27.71,33.06,38.42,43.77,49.13,54.49,59.84,65.2,70.55,75.91,81.26,86.62,91.98,97.33,102.69,108.04,113.4,118.75,124.11,129.47,134.82,140.18,145.53,150.89,156.24,161.6,166.95,172.31,177.67,183.02,188.38,193.73,199.09,204.44,209.8,215.16,220.51,225.87,231.22,236.58,241.93,247.29,252.65,258.0,263.36,268.71,274.07,279.42,284.78,290.13,295.49,300.85,306.2,311.56,316.91,322.27,327.62,332.98,338.34,343.69,349.05,354.4,359.76,365.11,370.47,375.83,381.18,386.54,391.89,397.25,402.6,407.96,413.31,418.67,424.03,429.38,434.74,440.09,445.45,450.8,456.16,461.52,466.87,472.23,477.58,482.94,488.29,493.65,499.01,504.36,509.72,515.07,520.43,525.78,531.14,536.49,541.85,547.21,552.56,557.92,563.27,568.63,573.98,579.34,584.7,590.05,595.41,600.76,606.12,611.47,616.83,622.18,627.54,632.9,638.25,643.61,648.96,-631.0,-625.64,-620.29,-614.93,-609.58,-604.22,-598.87,-593.51,-588.15,-582.8,-577.44,-572.09,-566.73,-561.38,-556.02,-550.67,-545.31,-539.95,-534.6,-529.24,-523.89,-518.53,-513.18,-507.82,-502.46,-497.11,-491.75,-486.4,-481.04,-475.69,-470.33,-464.97,-459.62,-454.26,-448.91,-443.55,-438.2,-432.84,-427.49,-422.13,-416.77,-411.42,-406.06,-400.71,-395.35,-390.0,-384.64,-379.28,-373.93,-368.57,-363.22,-357.86,-352.51,-347.15,-341.79,-336.44,-331.08,-325.73,-320.37,-315.02,-309.66,-304.31,-298.95,-293.59,-288.24,-282.88,-277.53,-272.17,-266.82,-261.46,-256.1,-250.75,-245.39,-240.04,-234.68,-229.33,-223.97,-218.62,-213.26,-207.9,-202.55,-197.19,-191.84,-186.48,-181.13,-175.77,-170.41,-165.06,-159.7,-154.35,-148.99,-143.64,-138.28,-132.92,-127.57,-122.21,-116.86,-111.5,-106.15,-100.79,-95.44,-90.08,-84.72,-79.37,-74.01,-68.66,-63.3,-57.95,-52.59,-47.23,-41.88,-36.52,-31.17,-25.81,-20.46,-15.1,-9.74,-4.39,0.97,6.32,11.68,17.03,22.39,27.74,33.1,38.46,43.81,49.17,54.52,59.88,65.23,70.59,75.95,81.3,86.66,92.01,97.37,102.72,108.08,113.44,118.79,124.15,129.5,134.86,140.21,145.57,150.92,156.28,161.64,166.99,172.35,177.7,183.06,188.41,193.77,199.13,204.48,209.84,215.19,220.55,225.9,231.26,236.62,241.97,247.33,252.68,258.04,263.39,268.75,274.1,279.46,284.82,290.17,295.53,300.88,306.24,311.59,316.95,322.31,327.66,333.02,338.37,343.73,349.08,354.44,359.79,365.15,370.51,375.86,381.22,386.57,391.93,397.28,402.64,408.0,413.35,418.71,424.06,429.42,434.77,440.13,445.49,450.84,456.2,461.55,466.91,472.26,477.62,482.97,488.33,493.69,499.04,504.4,509.75,515.11,520.46,525.82,531.18,536.53,541.89,547.24,552.6,557.95,563.31,568.67,574.02,579.38,584.73,590.09,595.44,600.8,606.15,611.51,616.87,622.22,627.58,632.93,638.29,643.64,649.0,-631.03,-625.68,-620.32,-614.97,-609.61,-604.26,-598.9,-593.54,-588.19,-582.83,-577.48,-572.12,-566.77,-561.41,-556.05,-550.7,-545.34,-539.99,-534.63,-529.28,-523.92,-518.57,-513.21,-507.85,-502.5,-497.14,-491.79,-486.43,-481.08,-475.72,-470.36,-465.01,-459.65,-454.3,-448.94,-443.59,-438.23,-432.87,-427.52,-422.16,-416.81,-411.45,-406.1,-400.74,-395.39,-390.03,-384.67,-379.32,-373.96,-368.61,-363.25,-357.9,-352.54,-347.18,-341.83,-336.47,-331.12,-325.76,-320.41,-315.05,-309.7,-304.34,-298.98,-293.63,-288.27,-282.92,-277.56,-272.21,-266.85,-261.49,-256.14,-250.78,-245.43,-240.07,-234.72,-229.36,-224.0,-218.65,-213.29,-207.94,-202.58,-197.23,-191.87,-186.52,-181.16,-175.8,-170.45,-165.09,-159.74,-154.38,-149.03,-143.67,-138.31,-132.96,-127.6,-122.25,-116.89,-111.54,-106.18,-100.82,-95.47,-90.11,-84.76,-79.4,-74.05,-68.69,-63.34,-57.98,-52.62,-47.27,-41.91,-36.56,-31.2,-25.85,-20.49,-15.13,-9.78,-4.42,0.93,6.29,11.64,17.0,22.36,27.71,33.07,38.42,43.78,49.13,54.49,59.84,65.2,70.56,75.91,81.27,86.62,91.98,97.33,102.69,108.05,113.4,118.76,124.11,129.47,134.82,140.18,145.54,150.89,156.25,161.6,166.96,172.31,177.67,183.02,188.38,193.74,199.09,204.45,209.8,215.16,220.51,225.87,231.23,236.58,241.94,247.29,252.65,258.0,263.36,268.72,274.07,279.43,284.78,290.14,295.49,300.85,306.2,311.56,316.92,322.27,327.63,332.98,338.34,343.69,349.05,354.41,359.76,365.12,370.47,375.83,381.18,386.54,391.89,397.25,402.61,407.96,413.32,418.67,424.03,429.38,434.74,440.1,445.45,450.81,456.16,461.52,466.87,472.23,477.59,482.94,488.3,493.65,499.01,504.36,509.72,515.07,520.43,525.79,531.14,536.5,541.85,547.21,552.56,557.92,563.28,568.63,573.99,579.34,584.7,590.05,595.41,600.77,606.12,611.48,616.83,622.19,627.54,632.9,638.25,643.61,648.97,-631.14,-625.78,-620.43,-615.07,-609.72,-604.36,-599.0,-593.65,-588.29,-582.94,-577.58,-572.23,-566.87,-561.51,-556.16,-550.8,-545.45,-540.09,-534.74,-529.38,-524.03,-518.67,-513.31,-507.96,-502.6,-497.25,-491.89,-486.54,-481.18,-475.82,-470.47,-465.11,-459.76,-454.4,-449.05,-443.69,-438.33,-432.98,-427.62,-422.27,-416.91,-411.56,-406.2,-400.85,-395.49,-390.13,-384.78,-379.42,-374.07,-368.71,-363.36,-358.0,-352.64,-347.29,-341.93,-336.58,-331.22,-325.87,-320.51,-315.15,-309.8,-304.44,-299.09,-293.73,-288.38,-283.02,-277.67,-272.31,-266.95,-261.6,-256.24,-250.89,-245.53,-240.18,-234.82,-229.46,-224.11,-218.75,-213.4,-208.04,-202.69,-197.33,-191.98,-186.62,-181.26,-175.91,-170.55,-165.2,-159.84,-154.49,-149.13,-143.77,-138.42,-133.06,-127.71,-122.35,-117.0,-111.64,-106.28,-100.93,-95.57,-90.22,-84.86,-79.51,-74.15,-68.8,-63.44,-58.08,-52.73,-47.37,-42.02,-36.66,-31.31,-25.95,-20.59,-15.24,-9.88,-4.53,0.83,6.18,11.54,16.9,22.25,27.61,32.96,38.32,43.67,49.03,54.38,59.74,65.1,70.45,75.81,81.16,86.52,91.87,97.23,102.59,107.94,113.3,118.65,124.01,129.36,134.72,140.08,145.43,150.79,156.14,161.5,166.85,172.21,177.56,182.92,188.28,193.63,198.99,204.34,209.7,215.05,220.41,225.77,231.12,236.48,241.83,247.19,252.54,257.9,263.26,268.61,273.97,279.32,284.68,290.03,295.39,300.74,306.1,311.46,316.81,322.17,327.52,332.88,338.23,343.59,348.95,354.3,359.66,365.01,370.37,375.72,381.08,386.44,391.79,397.15,402.5,407.86,413.21,418.57,423.92,429.28,434.64,439.99,445.35,450.7,456.06,461.41,466.77,472.13,477.48,482.84,488.19,493.55,498.9,504.26,509.61,514.97,520.33,525.68,531.04,536.39,541.75,547.1,552.46,557.82,563.17,568.53,573.88,579.24,584.59,589.95,595.31,600.66,606.02,611.37,616.73,622.08,627.44,632.79,638.15,643.51,648.86,-631.31,-625.96,-620.6,-615.25,-609.89,-604.53,-599.18,-593.82,-588.47,-583.11,-577.76,-572.4,-567.04,-561.69,-556.33,-550.98,-545.62,-540.27,-534.91,-529.55,-524.2,-518.84,-513.49,-508.13,-502.78,-497.42,-492.07,-486.71,-481.35,-476.0,-470.64,-465.29,-459.93,-454.58,-449.22,-443.86,-438.51,-433.15,-427.8,-422.44,-417.09,-411.73,-406.37,-401.02,-395.66,-390.31,-384.95,-379.6,-374.24,-368.89,-363.53,-358.17,-352.82,-347.46,-342.11,-336.75,-331.4,-326.04,-320.68,-315.33,-309.97,-304.62,-299.26,-293.91,-288.55,-283.19,-277.84,-272.48,-267.13,-261.77,-256.42,-251.06,-245.71,-240.35,-234.99,-229.64,-224.28,-218.93,-213.57,-208.22,-202.86,-197.5,-192.15,-186.79,-181.44,-176.08,-170.73,-165.37,-160.02,-154.66,-149.3,-143.95,-138.59,-133.24,-127.88,-122.53,-117.17,-111.81,-106.46,-101.1,-95.75,-90.39,-85.04,-79.68,-74.32,-68.97,-63.61,-58.26,-52.9,-47.55,-42.19,-36.84,-31.48,-26.12,-20.77,-15.41,-10.06,-4.7,0.65,6.01,11.37,16.72,22.08,27.43,32.79,38.14,43.5,48.86,54.21,59.57,64.92,70.28,75.63,80.99,86.34,91.7,97.06,102.41,107.77,113.12,118.48,123.83,129.19,134.55,139.9,145.26,150.61,155.97,161.32,166.68,172.04,177.39,182.75,188.1,193.46,198.81,204.17,209.52,214.88,220.24,225.59,230.95,236.3,241.66,247.01,252.37,257.73,263.08,268.44,273.79,279.15,284.5,289.86,295.22,300.57,305.93,311.28,316.64,321.99,327.35,332.7,338.06,343.42,348.77,354.13,359.48,364.84,370.19,375.55,380.91,386.26,391.62,396.97,402.33,407.68,413.04,418.4,423.75,429.11,434.46,439.82,445.17,450.53,455.88,461.24,466.6,471.95,477.31,482.66,488.02,493.37,498.73,504.09,509.44,514.8,520.15,525.51,530.86,536.22,541.57,546.93,552.29,557.64,563.0,568.35,573.71,579.06,584.42,589.78,595.13,600.49,605.84,611.2,616.55,621.91,627.27,632.62,637.98,643.33,648.69,-631.55,-626.2,-620.84,-615.49,-610.13,-604.78,-599.42,-594.06,-588.71,-583.35,-578.0,-572.64,-567.29,-561.93,-556.58,-551.22,-545.86,-540.51,-535.15,-529.8,-524.44,-519.09,-513.73,-508.37,-503.02,-497.66,-492.31,-486.95,-481.6,-476.24,-470.88,-465.53,-460.17,-454.82,-449.46,-444.11,-438.75,-433.4,-428.04,-422.68,-417.33,-411.97,-406.62,-401.26,-395.91,-390.55,-385.19,-379.84,-374.48,-369.13,-363.77,-358.42,-353.06,-347.7,-342.35,-336.99,-331.64,-326.28,-320.93,-315.57,-310.22,-304.86,-299.5,-294.15,-288.79,-283.44,-278.08,-272.73,-267.37,-262.01,-256.66,-251.3,-245.95,-240.59,-235.24,-229.88,-224.52,-219.17,-213.81,-208.46,-203.1,-197.75,-192.39,-187.04,-181.68,-176.32,-170.97,-165.61,-160.26,-154.9,-149.55,-144.19,-138.83,-133.48,-128.12,-122.77,-117.41,-112.06,-106.7,-101.34,-95.99,-90.63,-85.28,-79.92,-74.57,-69.21,-63.86,-58.5,-53.14,-47.79,-42.43,-37.08,-31.72,-26.37,-21.01,-15.65,-10.3,-4.94,0.41,5.77,11.12,16.48,21.83,27.19,32.55,37.9,43.26,48.61,53.97,59.32,64.68,70.04,75.39,80.75,86.1,91.46,96.81,102.17,107.53,112.88,118.24,123.59,128.95,134.3,139.66,145.01,150.37,155.73,161.08,166.44,171.79,177.15,182.5,187.86,193.22,198.57,203.93,209.28,214.64,219.99,225.35,230.71,236.06,241.42,246.77,252.13,257.48,262.84,268.19,273.55,278.91,284.26,289.62,294.97,300.33,305.68,311.04,316.4,321.75,327.11,332.46,337.82,343.17,348.53,353.89,359.24,364.6,369.95,375.31,380.66,386.02,391.37,396.73,402.09,407.44,412.8,418.15,423.51,428.86,434.22,439.58,444.93,450.29,455.64,461.0,466.35,471.71,477.07,482.42,487.78,493.13,498.49,503.84,509.2,514.55,519.91,525.27,530.62,535.98,541.33,546.69,552.04,557.4,562.76,568.11,573.47,578.82,584.18,589.53,594.89,600.25,605.6,610.96,616.31,621.67,627.02,632.38,637.73,643.09,648.45,-631.86,-626.51,-621.15,-615.8,-610.44,-605.08,-599.73,-594.37,-589.02,-583.66,-578.31,-572.95,-567.59,-562.24,-556.88,-551.53,-546.17,-540.82,-535.46,-530.11,-524.75,-519.39,-514.04,-508.68,-503.33,-497.97,-492.62,-487.26,-481.9,-476.55,-471.19,-465.84,-460.48,-455.13,-449.77,-444.41,-439.06,-433.7,-428.35,-422.99,-417.64,-412.28,-406.93,-401.57,-396.21,-390.86,-385.5,-380.15,-374.79,-369.44,-364.08,-358.72,-353.37,-348.01,-342.66,-337.3,-331.95,-326.59,-321.23,-315.88,-310.52,-305.17,-299.81,-294.46,-289.1,-283.75,-278.39,-273.03,-267.68,-262.32,-256.97,-251.61,-246.26,-240.9,-235.54,-230.19,-224.83,-219.48,-214.12,-208.77,-203.41,-198.06,-192.7,-187.34,-181.99,-176.63,-171.28,-165.92,-160.57,-155.21,-149.85,-144.5,-139.14,-133.79,-128.43,-123.08,-117.72,-112.36,-107.01,-101.65,-96.3,-90.94,-85.59,-80.23,-74.88,-69.52,-64.16,-58.81,-53.45,-48.1,-42.74,-37.39,-32.03,-26.67,-21.32,-15.96,-10.61,-5.25,0.1,5.46,10.82,16.17,21.53,26.88,32.24,37.59,42.95,48.3,53.66,59.02,64.37,69.73,75.08,80.44,85.79,91.15,96.51,101.86,107.22,112.57,117.93,123.28,128.64,134.0,139.35,144.71,150.06,155.42,160.77,166.13,171.48,176.84,182.2,187.55,192.91,198.26,203.62,208.97,214.33,219.69,225.04,230.4,235.75,241.11,246.46,251.82,257.18,262.53,267.89,273.24,278.6,283.95,289.31,294.66,300.02,305.38,310.73,316.09,321.44,326.8,332.15,337.51,342.87,348.22,353.58,358.93,364.29,369.64,375.0,380.36,385.71,391.07,396.42,401.78,407.13,412.49,417.84,423.2,428.56,433.91,439.27,444.62,449.98,455.33,460.69,466.05,471.4,476.76,482.11,487.47,492.82,498.18,503.53,508.89,514.25,519.6,524.96,530.31,535.67,541.02,546.38,551.74,557.09,562.45,567.8,573.16,578.51,583.87,589.23,594.58,599.94,605.29,610.65,616.0,621.36,626.71,632.07,637.43,642.78,648.14,-632.23,-626.88,-621.52,-616.17,-610.81,-605.46,-600.1,-594.75,-589.39,-584.03,-578.68,-573.32,-567.97,-562.61,-557.26,-551.9,-546.54,-541.19,-535.83,-530.48,-525.12,-519.77,-514.41,-509.05,-503.7,-498.34,-492.99,-487.63,-482.28,-476.92,-471.57,-466.21,-460.85,-455.5,-450.14,-444.79,-439.43,-434.08,-428.72,-423.36,-418.01,-412.65,-407.3,-401.94,-396.59,-391.23,-385.87,-380.52,-375.16,-369.81,-364.45,-359.1,-353.74,-348.39,-343.03,-337.67,-332.32,-326.96,-321.61,-316.25,-310.9,-305.54,-300.18,-294.83,-289.47,-284.12,-278.76,-273.41,-268.05,-262.7,-257.34,-251.98,-246.63,-241.27,-235.92,-230.56,-225.21,-219.85,-214.49,-209.14,-203.78,-198.43,-193.07,-187.72,-182.36,-177.0,-171.65,-166.29,-160.94,-155.58,-150.23,-144.87,-139.52,-134.16,-128.8,-123.45,-118.09,-112.74,-107.38,-102.03,-96.67,-91.31,-85.96,-80.6,-75.25,-69.89,-64.54,-59.18,-53.82,-48.47,-43.11,-37.76,-32.4,-27.05,-21.69,-16.34,-10.98,-5.62,-0.27,5.09,10.44,15.8,21.15,26.51,31.87,37.22,42.58,47.93,53.29,58.64,64.0,69.36,74.71,80.07,85.42,90.78,96.13,101.49,106.84,112.2,117.56,122.91,128.27,133.62,138.98,144.33,149.69,155.05,160.4,165.76,171.11,176.47,181.82,187.18,192.54,197.89,203.25,208.6,213.96,219.31,224.67,230.02,235.38,240.74,246.09,251.45,256.8,262.16,267.51,272.87,278.23,283.58,288.94,294.29,299.65,305.0,310.36,315.71,321.07,326.43,331.78,337.14,342.49,347.85,353.2,358.56,363.92,369.27,374.63,379.98,385.34,390.69,396.05,401.41,406.76,412.12,417.47,422.83,428.18,433.54,438.89,444.25,449.61,454.96,460.32,465.67,471.03,476.38,481.74,487.1,492.45,497.81,503.16,508.52,513.87,519.23,524.59,529.94,535.3,540.65,546.01,551.36,556.72,562.07,567.43,572.79,578.14,583.5,588.85,594.21,599.56,604.92,610.28,615.63,620.99,626.34,631.7,637.05,642.41,647.77,-632.67,-627.31,-621.96,-616.6,-611.25,-605.89,-600.53,-595.18,-589.82,-584.47,-579.11,-573.76,-568.4,-563.04,-557.69,-552.33,-546.98,-541.62,-536.27,-530.91,-525.56,-520.2,-514.84,-509.49,-504.13,-498.78,-493.42,-488.07,-482.71,-477.35,-472.0,-466.64,-461.29,-455.93,-450.58,-445.22,-439.86,-434.51,-429.15,-423.8,-418.44,-413.09,-407.73,-402.38,-397.02,-391.66,-386.31,-380.95,-375.6,-370.24,-364.89,-359.53,-354.17,-348.82,-343.46,-338.11,-332.75,-327.4,-322.04,-316.68,-311.33,-305.97,-300.62,-295.26,-289.91,-284.55,-279.2,-273.84,-268.48,-263.13,-257.77,-252.42,-247.06,-241.71,-236.35,-230.99,-225.64,-220.28,-214.93,-209.57,-204.22,-198.86,-193.5,-188.15,-182.79,-177.44,-172.08,-166.73,-161.37,-156.02,-150.66,-145.3,-139.95,-134.59,-129.24,-123.88,-118.53,-113.17,-107.81,-102.46,-97.1,-91.75,-86.39,-81.04,-75.68,-70.32,-64.97,-59.61,-54.26,-48.9,-43.55,-38.19,-32.84,-27.48,-22.12,-16.77,-11.41,-6.06,-0.7,4.65,10.01,15.37,20.72,26.08,31.43,36.79,42.14,47.5,52.85,58.21,63.57,68.92,74.28,79.63,84.99,90.34,95.7,101.06,106.41,111.77,117.12,122.48,127.83,133.19,138.55,143.9,149.26,154.61,159.97,165.32,170.68,176.03,181.39,186.75,192.1,197.46,202.81,208.17,213.52,218.88,224.24,229.59,234.95,240.3,245.66,251.01,256.37,261.73,267.08,272.44,277.79,283.15,288.5,293.86,299.21,304.57,309.93,315.28,320.64,325.99,331.35,336.7,342.06,347.42,352.77,358.13,363.48,368.84,374.19,379.55,384.91,390.26,395.62,400.97,406.33,411.68,417.04,422.39,427.75,433.11,438.46,443.82,449.17,454.53,459.88,465.24,470.6,475.95,481.31,486.66,492.02,497.37,502.73,508.09,513.44,518.8,524.15,529.51,534.86,540.22,545.57,550.93,556.29,561.64,567.0,572.35,577.71,583.06,588.42,593.78,599.13,604.49,609.84,615.2,620.55,625.91,631.27,636.62,641.98,647.33,-633.16,-627.8,-622.45,-617.09,-611.74,-606.38,-601.02,-595.67,-590.31,-584.96,-579.6,-574.25,-568.89,-563.54,-558.18,-552.82,-547.47,-542.11,-536.76,-531.4,-526.05,-520.69,-515.33,-509.98,-504.62,-499.27,-493.91,-488.56,-483.2,-477.85,-472.49,-467.13,-461.78,-456.42,-451.07,-445.71,-440.36,-435.0,-429.64,-424.29,-418.93,-413.58,-408.22,-402.87,-397.51,-392.15,-386.8,-381.44,-376.09,-370.73,-365.38,-360.02,-354.67,-349.31,-343.95,-338.6,-333.24,-327.89,-322.53,-317.18,-311.82,-306.46,-301.11,-295.75,-290.4,-285.04,-279.69,-274.33,-268.97,-263.62,-258.26,-252.91,-247.55,-242.2,-236.84,-231.49,-226.13,-220.77,-215.42,-210.06,-204.71,-199.35,-194.0,-188.64,-183.28,-177.93,-172.57,-167.22,-161.86,-156.51,-151.15,-145.79,-140.44,-135.08,-129.73,-124.37,-119.02,-113.66,-108.31,-102.95,-97.59,-92.24,-86.88,-81.53,-76.17,-70.82,-65.46,-60.1,-54.75,-49.39,-44.04,-38.68,-33.33,-27.97,-22.61,-17.26,-11.9,-6.55,-1.19,4.16,9.52,14.87,20.23,25.59,30.94,36.3,41.65,47.01,52.36,57.72,63.08,68.43,73.79,79.14,84.5,89.85,95.21,100.57,105.92,111.28,116.63,121.99,127.34,132.7,138.05,143.41,148.77,154.12,159.48,164.83,170.19,175.54,180.9,186.26,191.61,196.97,202.32,207.68,213.03,218.39,223.74,229.1,234.46,239.81,245.17,250.52,255.88,261.23,266.59,271.95,277.3,282.66,288.01,293.37,298.72,304.08,309.44,314.79,320.15,325.5,330.86,336.21,341.57,346.92,352.28,357.64,362.99,368.35,373.7,379.06,384.41,389.77,395.13,400.48,405.84,411.19,416.55,421.9,427.26,432.62,437.97,443.33,448.68,454.04,459.39,464.75,470.1,475.46,480.82,486.17,491.53,496.88,502.24,507.59,512.95,518.31,523.66,529.02,534.37,539.73,545.08,550.44,555.8,561.15,566.51,571.86,577.22,582.57,587.93,593.28,598.64,604.0,609.35,614.71,620.06,625.42,630.77,636.13,641.49,646.84,-633.7,-628.35,-622.99,-617.64,-612.28,-606.93,-601.57,-596.21,-590.86,-585.5,-580.15,-574.79,-569.44,-564.08,-558.72,-553.37,-548.01,-542.66,-537.3,-531.95,-526.59,-521.23,-515.88,-510.52,-505.17,-499.81,-494.46,-489.1,-483.75,-478.39,-473.03,-467.68,-462.32,-456.97,-451.61,-446.26,-440.9,-435.54,-430.19,-424.83,-419.48,-414.12,-408.77,-403.41,-398.05,-392.7,-387.34,-381.99,-376.63,-371.28,-365.92,-360.57,-355.21,-349.85,-344.5,-339.14,-333.79,-328.43,-323.08,-317.72,-312.36,-307.01,-301.65,-296.3,-290.94,-285.59,-280.23,-274.87,-269.52,-264.16,-258.81,-253.45,-248.1,-242.74,-237.39,-232.03,-226.67,-221.32,-215.96,-210.61,-205.25,-199.9,-194.54,-189.18,-183.83,-178.47,-173.12,-167.76,-162.41,-157.05,-151.69,-146.34,-140.98,-135.63,-130.27,-124.92,-119.56,-114.21,-108.85,-103.49,-98.14,-92.78,-87.43,-82.07,-76.72,-71.36,-66.0,-60.65,-55.29,-49.94,-44.58,-39.23,-33.87,-28.52,-23.16,-17.8,-12.45,-7.09,-1.74,3.62,8.97,14.33,19.69,25.04,30.4,35.75,41.11,46.46,51.82,57.18,62.53,67.89,73.24,78.6,83.95,89.31,94.66,100.02,105.38,110.73,116.09,121.44,126.8,132.15,137.51,142.87,148.22,153.58,158.93,164.29,169.64,175.0,180.36,185.71,191.07,196.42,201.78,207.13,212.49,217.84,223.2,228.56,233.91,239.27,244.62,249.98,255.33,260.69,266.05,271.4,276.76,282.11,287.47,292.82,298.18,303.54,308.89,314.25,319.6,324.96,330.31,335.67,341.02,346.38,351.74,357.09,362.45,367.8,373.16,378.51,383.87,389.23,394.58,399.94,405.29,410.65,416.0,421.36,426.72,432.07,437.43,442.78,448.14,453.49,458.85,464.2,469.56,474.92,480.27,485.63,490.98,496.34,501.69,507.05,512.41,517.76,523.12,528.47,533.83,539.18,544.54,549.9,555.25,560.61,565.96,571.32,576.67,582.03,587.38,592.74,598.1,603.45,608.81,614.16,619.52,624.87,630.23,635.59,640.94,646.3,-634.3,-628.94,-623.59,-618.23,-612.87,-607.52,-602.16,-596.81,-591.45,-586.1,-580.74,-575.39,-570.03,-564.67,-559.32,-553.96,-548.61,-543.25,-537.9,-532.54,-527.18,-521.83,-516.47,-511.12,-505.76,-500.41,-495.05,-489.69,-484.34,-478.98,-473.63,-468.27,-462.92,-457.56,-452.21,-446.85,-441.49,-436.14,-430.78,-425.43,-420.07,-414.72,-409.36,-404.0,-398.65,-393.29,-387.94,-382.58,-377.23,-371.87,-366.51,-361.16,-355.8,-350.45,-345.09,-339.74,-334.38,-329.03,-323.67,-318.31,-312.96,-307.6,-302.25,-296.89,-291.54,-286.18,-280.82,-275.47,-270.11,-264.76,-259.4,-254.05,-248.69,-243.33,-237.98,-232.62,-227.27,-221.91,-216.56,-211.2,-205.85,-200.49,-195.13,-189.78,-184.42,-179.07,-173.71,-168.36,-163.0,-157.64,-152.29,-146.93,-141.58,-136.22,-130.87,-125.51,-120.15,-114.8,-109.44,-104.09,-98.73,-93.38,-88.02,-82.67,-77.31,-71.95,-66.6,-61.24,-55.89,-50.53,-45.18,-39.82,-34.46,-29.11,-23.75,-18.4,-13.04,-7.69,-2.33,3.02,8.38,13.74,19.09,24.45,29.8,35.16,40.51,45.87,51.23,56.58,61.94,67.29,72.65,78.0,83.36,88.72,94.07,99.43,104.78,110.14,115.49,120.85,126.2,131.56,136.92,142.27,147.63,152.98,158.34,163.69,169.05,174.41,179.76,185.12,190.47,195.83,201.18,206.54,211.9,217.25,222.61,227.96,233.32,238.67,244.03,249.38,254.74,260.1,265.45,270.81,276.16,281.52,286.87,292.23,297.59,302.94,308.3,313.65,319.01,324.36,329.72,335.08,340.43,345.79,351.14,356.5,361.85,367.21,372.56,377.92,383.28,388.63,393.99,399.34,404.7,410.05,415.41,420.77,426.12,431.48,436.83,442.19,447.54,452.9,458.26,463.61,468.97,474.32,479.68,485.03,490.39,495.74,501.1,506.46,511.81,517.17,522.52,527.88,533.23,538.59,543.95,549.3,554.66,560.01,565.37,570.72,576.08,581.43,586.79,592.15,597.5,602.86,608.21,613.57,618.92,624.28,629.64,634.99,640.35,645.7,-634.94,-629.58,-624.22,-618.87,-613.51,-608.16,-602.8,-597.45,-592.09,-586.74,-581.38,-576.02,-570.67,-565.31,-559.96,-554.6,-549.25,-543.89,-538.53,-533.18,-527.82,-522.47,-517.11,-511.76,-506.4,-501.04,-495.69,-490.33,-484.98,-479.62,-474.27,-468.91,-463.56,-458.2,-452.84,-447.49,-442.13,-436.78,-431.42,-426.07,-420.71,-415.35,-410.0,-404.64,-399.29,-393.93,-388.58,-383.22,-377.86,-372.51,-367.15,-361.8,-356.44,-351.09,-345.73,-340.38,-335.02,-329.66,-324.31,-318.95,-313.6,-308.24,-302.89,-297.53,-292.17,-286.82,-281.46,-276.11,-270.75,-265.4,-260.04,-254.68,-249.33,-243.97,-238.62,-233.26,-227.91,-222.55,-217.2,-211.84,-206.48,-201.13,-195.77,-190.42,-185.06,-179.71,-174.35,-168.99,-163.64,-158.28,-152.93,-147.57,-142.22,-136.86,-131.5,-126.15,-120.79,-115.44,-110.08,-104.73,-99.37,-94.02,-88.66,-83.3,-77.95,-72.59,-67.24,-61.88,-56.53,-51.17,-45.81,-40.46,-35.1,-29.75,-24.39,-19.04,-13.68,-8.33,-2.97,2.39,7.74,13.1,18.45,23.81,29.16,34.52,39.88,45.23,50.59,55.94,61.3,66.65,72.01,77.37,82.72,88.08,93.43,98.79,104.14,109.5,114.85,120.21,125.57,130.92,136.28,141.63,146.99,152.34,157.7,163.06,168.41,173.77,179.12,184.48,189.83,195.19,200.55,205.9,211.26,216.61,221.97,227.32,232.68,238.03,243.39,248.75,254.1,259.46,264.81,270.17,275.52,280.88,286.24,291.59,296.95,302.3,307.66,313.01,318.37,323.73,329.08,334.44,339.79,345.15,350.5,355.86,361.21,366.57,371.93,377.28,382.64,387.99,393.35,398.7,404.06,409.42,414.77,420.13,425.48,430.84,436.19,441.55,446.91,452.26,457.62,462.97,468.33,473.68,479.04,484.39,489.75,495.11,500.46,505.82,511.17,516.53,521.88,527.24,532.6,537.95,543.31,548.66,554.02,559.37,564.73,570.08,575.44,580.8,586.15,591.51,596.86,602.22,607.57,612.93,618.29,623.64,629.0,634.35,639.71,645.06,-635.61,-630.26,-624.9,-619.55,-614.19,-608.84,-603.48,-598.12,-592.77,-587.41,-582.06,-576.7,-571.35,-565.99,-560.64,-555.28,-549.92,-544.57,-539.21,-533.86,-528.5,-523.15,-517.79,-512.43,-507.08,-501.72,-496.37,-491.01,-485.66,-480.3,-474.94,-469.59,-464.23,-458.88,-453.52,-448.17,-442.81,-437.46,-432.1,-426.74,-421.39,-416.03,-410.68,-405.32,-399.97,-394.61,-389.25,-383.9,-378.54,-373.19,-367.83,-362.48,-357.12,-351.77,-346.41,-341.05,-335.7,-330.34,-324.99,-319.63,-314.28,-308.92,-303.56,-298.21,-292.85,-287.5,-282.14,-276.79,-271.43,-266.07,-260.72,-255.36,-250.01,-244.65,-239.3,-233.94,-228.59,-223.23,-217.87,-212.52,-207.16,-201.81,-196.45,-191.1,-185.74,-180.38,-175.03,-169.67,-164.32,-158.96,-153.61,-148.25,-142.89,-137.54,-132.18,-126.83,-121.47,-116.12,-110.76,-105.41,-100.05,-94.69,-89.34,-83.98,-78.63,-73.27,-67.92,-62.56,-57.2,-51.85,-46.49,-41.14,-35.78,-30.43,-25.07,-19.71,-14.36,-9.0,-3.65,1.71,7.06,12.42,17.77,23.13,28.49,33.84,39.2,44.55,49.91,55.26,60.62,65.98,71.33,76.69,82.04,87.4,92.75,98.11,103.47,108.82,114.18,119.53,124.89,130.24,135.6,140.95,146.31,151.67,157.02,162.38,167.73,173.09,178.44,183.8,189.16,194.51,199.87,205.22,210.58,215.93,221.29,226.65,232.0,237.36,242.71,248.07,253.42,258.78,264.13,269.49,274.85,280.2,285.56,290.91,296.27,301.62,306.98,312.34,317.69,323.05,328.4,333.76,339.11,344.47,349.82,355.18,360.54,365.89,371.25,376.6,381.96,387.31,392.67,398.03,403.38,408.74,414.09,419.45,424.8,430.16,435.52,440.87,446.23,451.58,456.94,462.29,467.65,473.0,478.36,483.72,489.07,494.43,499.78,505.14,510.49,515.85,521.21,526.56,531.92,537.27,542.63,547.98,553.34,558.7,564.05,569.41,574.76,580.12,585.47,590.83,596.18,601.54,606.9,612.25,617.61,622.96,628.32,633.67,639.03,644.39,-636.33,-630.97,-625.62,-620.26,-614.9,-609.55,-604.19,-598.84,-593.48,-588.13,-582.77,-577.42,-572.06,-566.7,-561.35,-555.99,-550.64,-545.28,-539.93,-534.57,-529.21,-523.86,-518.5,-513.15,-507.79,-502.44,-497.08,-491.72,-486.37,-481.01,-475.66,-470.3,-464.95,-459.59,-454.24,-448.88,-443.52,-438.17,-432.81,-427.46,-422.1,-416.75,-411.39,-406.03,-400.68,-395.32,-389.97,-384.61,-379.26,-373.9,-368.54,-363.19,-357.83,-352.48,-347.12,-341.77,-336.41,-331.06,-325.7,-320.34,-314.99,-309.63,-304.28,-298.92,-293.57,-288.21,-282.85,-277.5,-272.14,-266.79,-261.43,-256.08,-250.72,-245.36,-240.01,-234.65,-229.3,-223.94,-218.59,-213.23,-207.88,-202.52,-197.16,-191.81,-186.45,-181.1,-175.74,-170.39,-165.03,-159.67,-154.32,-148.96,-143.61,-138.25,-132.9,-127.54,-122.19,-116.83,-111.47,-106.12,-100.76,-95.41,-90.05,-84.7,-79.34,-73.98,-68.63,-63.27,-57.92,-52.56,-47.21,-41.85,-36.49,-31.14,-25.78,-20.43,-15.07,-9.72,-4.36,0.99,6.35,11.71,17.06,22.42,27.77,33.13,38.48,43.84,49.2,54.55,59.91,65.26,70.62,75.97,81.33,86.69,92.04,97.4,102.75,108.11,113.46,118.82,124.17,129.53,134.89,140.24,145.6,150.95,156.31,161.66,167.02,172.38,177.73,183.09,188.44,193.8,199.15,204.51,209.87,215.22,220.58,225.93,231.29,236.64,242.0,247.35,252.71,258.07,263.42,268.78,274.13,279.49,284.84,290.2,295.56,300.91,306.27,311.62,316.98,322.33,327.69,333.05,338.4,343.76,349.11,354.47,359.82,365.18,370.53,375.89,381.25,386.6,391.96,397.31,402.67,408.02,413.38,418.74,424.09,429.45,434.8,440.16,445.51,450.87,456.23,461.58,466.94,472.29,477.65,483.0,488.36,493.71,499.07,504.43,509.78,515.14,520.49,525.85,531.2,536.56,541.92,547.27,552.63,557.98,563.34,568.69,574.05,579.4,584.76,590.12,595.47,600.83,606.18,611.54,616.89,622.25,627.61,632.96,638.32,643.67,-637.07,-631.71,-626.36,-621.0,-615.65,-610.29,-604.94,-599.58,-594.22,-588.87,-583.51,-578.16,-572.8,-567.45,-562.09,-556.73,-551.38,-546.02,-540.67,-535.31,-529.96,-524.6,-519.24,-513.89,-508.53,-503.18,-497.82,-492.47,-487.11,-481.76,-476.4,-471.04,-465.69,-460.33,-454.98,-449.62,-444.27,-438.91,-433.55,-428.2,-422.84,-417.49,-412.13,-406.78,-401.42,-396.06,-390.71,-385.35,-380.0,-374.64,-369.29,-363.93,-358.58,-353.22,-347.86,-342.51,-337.15,-331.8,-326.44,-321.09,-315.73,-310.37,-305.02,-299.66,-294.31,-288.95,-283.6,-278.24,-272.88,-267.53,-262.17,-256.82,-251.46,-246.11,-240.75,-235.4,-230.04,-224.68,-219.33,-213.97,-208.62,-203.26,-197.91,-192.55,-187.19,-181.84,-176.48,-171.13,-165.77,-160.42,-155.06,-149.7,-144.35,-138.99,-133.64,-128.28,-122.93,-117.57,-112.22,-106.86,-101.5,-96.15,-90.79,-85.44,-80.08,-74.73,-69.37,-64.01,-58.66,-53.3,-47.95,-42.59,-37.24,-31.88,-26.53,-21.17,-15.81,-10.46,-5.1,0.25,5.61,10.96,16.32,21.68,27.03,32.39,37.74,43.1,48.45,53.81,59.17,64.52,69.88,75.23,80.59,85.94,91.3,96.65,102.01,107.37,112.72,118.08,123.43,128.79,134.14,139.5,144.86,150.21,155.57,160.92,166.28,171.63,176.99,182.35,187.7,193.06,198.41,203.77,209.12,214.48,219.83,225.19,230.55,235.9,241.26,246.61,251.97,257.32,262.68,268.04,273.39,278.75,284.1,289.46,294.81,300.17,305.53,310.88,316.24,321.59,326.95,332.3,337.66,343.01,348.37,353.73,359.08,364.44,369.79,375.15,380.5,385.86,391.22,396.57,401.93,407.28,412.64,417.99,423.35,428.71,434.06,439.42,444.77,450.13,455.48,460.84,466.19,471.55,476.91,482.26,487.62,492.97,498.33,503.68,509.04,514.4,519.75,525.11,530.46,535.82,541.17,546.53,551.88,557.24,562.6,567.95,573.31,578.66,584.02,589.37,594.73,600.09,605.44,610.8,616.15,621.51,626.86,632.22,637.58,642.93,-637.83,-632.48,-627.12,-621.77,-616.41,-611.06,-605.7,-600.34,-594.99,-589.63,-584.28,-578.92,-573.57,-568.21,-562.85,-557.5,-552.14,-546.79,-541.43,-536.08,-530.72,-525.37,-520.01,-514.65,-509.3,-503.94,-498.59,-493.23,-487.88,-482.52,-477.16,-471.81,-466.45,-461.1,-455.74,-450.39,-445.03,-439.67,-434.32,-428.96,-423.61,-418.25,-412.9,-407.54,-402.19,-396.83,-391.47,-386.12,-380.76,-375.41,-370.05,-364.7,-359.34,-353.98,-348.63,-343.27,-337.92,-332.56,-327.21,-321.85,-316.49,-311.14,-305.78,-300.43,-295.07,-289.72,-284.36,-279.01,-273.65,-268.29,-262.94,-257.58,-252.23,-246.87,-241.52,-236.16,-230.8,-225.45,-220.09,-214.74,-209.38,-204.03,-198.67,-193.31,-187.96,-182.6,-177.25,-171.89,-166.54,-161.18,-155.83,-150.47,-145.11,-139.76,-134.4,-129.05,-123.69,-118.34,-112.98,-107.62,-102.27,-96.91,-91.56,-86.2,-80.85,-75.49,-70.13,-64.78,-59.42,-54.07,-48.71,-43.36,-38.0,-32.65,-27.29,-21.93,-16.58,-11.22,-5.87,-0.51,4.84,10.2,15.56,20.91,26.27,31.62,36.98,42.33,47.69,53.04,58.4,63.76,69.11,74.47,79.82,85.18,90.53,95.89,101.25,106.6,111.96,117.31,122.67,128.02,133.38,138.74,144.09,149.45,154.8,160.16,165.51,170.87,176.22,181.58,186.94,192.29,197.65,203.0,208.36,213.71,219.07,224.43,229.78,235.14,240.49,245.85,251.2,256.56,261.92,267.27,272.63,277.98,283.34,288.69,294.05,299.4,304.76,310.12,315.47,320.83,326.18,331.54,336.89,342.25,347.61,352.96,358.32,363.67,369.03,374.38,379.74,385.1,390.45,395.81,401.16,406.52,411.87,417.23,422.58,427.94,433.3,438.65,444.01,449.36,454.72,460.07,465.43,470.79,476.14,481.5,486.85,492.21,497.56,502.92,508.28,513.63,518.99,524.34,529.7,535.05,540.41,545.76,551.12,556.48,561.83,567.19,572.54,577.9,583.25,588.61,593.97,599.32,604.68,610.03,615.39,620.74,626.1,631.45,636.81,642.17,-638.62,-633.26,-627.9,-622.55,-617.19,-611.84,-606.48,-601.13,-595.77,-590.41,-585.06,-579.7,-574.35,-568.99,-563.64,-558.28,-552.93,-547.57,-542.21,-536.86,-531.5,-526.15,-520.79,-515.44,-510.08,-504.72,-499.37,-494.01,-488.66,-483.3,-477.95,-472.59,-467.23,-461.88,-456.52,-451.17,-445.81,-440.46,-435.1,-429.75,-424.39,-419.03,-413.68,-408.32,-402.97,-397.61,-392.26,-386.9,-381.54,-376.19,-370.83,-365.48,-360.12,-354.77,-349.41,-344.05,-338.7,-333.34,-327.99,-322.63,-317.28,-311.92,-306.57,-301.21,-295.85,-290.5,-285.14,-279.79,-274.43,-269.08,-263.72,-258.36,-253.01,-247.65,-242.3,-236.94,-231.59,-226.23,-220.87,-215.52,-210.16,-204.81,-199.45,-194.1,-188.74,-183.39,-178.03,-172.67,-167.32,-161.96,-156.61,-151.25,-145.9,-140.54,-135.18,-129.83,-124.47,-119.12,-113.76,-108.41,-103.05,-97.69,-92.34,-86.98,-81.63,-76.27,-70.92,-65.56,-60.21,-54.85,-49.49,-44.14,-38.78,-33.43,-28.07,-22.72,-17.36,-12.0,-6.65,-1.29,4.06,9.42,14.77,20.13,25.48,30.84,36.2,41.55,46.91,52.26,57.62,62.97,68.33,73.69,79.04,84.4,89.75,95.11,100.46,105.82,111.18,116.53,121.89,127.24,132.6,137.95,143.31,148.66,154.02,159.38,164.73,170.09,175.44,180.8,186.15,191.51,196.87,202.22,207.58,212.93,218.29,223.64,229.0,234.36,239.71,245.07,250.42,255.78,261.13,266.49,271.84,277.2,282.56,287.91,293.27,298.62,303.98,309.33,314.69,320.05,325.4,330.76,336.11,341.47,346.82,352.18,357.54,362.89,368.25,373.6,378.96,384.31,389.67,395.02,400.38,405.74,411.09,416.45,421.8,427.16,432.51,437.87,443.23,448.58,453.94,459.29,464.65,470.0,475.36,480.72,486.07,491.43,496.78,502.14,507.49,512.85,518.2,523.56,528.92,534.27,539.63,544.98,550.34,555.69,561.05,566.41,571.76,577.12,582.47,587.83,593.18,598.54,603.89,609.25,614.61,619.96,625.32,630.67,636.03,641.38,-639.41,-634.05,-628.7,-623.34,-617.99,-612.63,-607.27,-601.92,-596.56,-591.21,-585.85,-580.5,-575.14,-569.78,-564.43,-559.07,-553.72,-548.36,-543.01,-537.65,-532.3,-526.94,-521.58,-516.23,-510.87,-505.52,-500.16,-494.81,-489.45,-484.09,-478.74,-473.38,-468.03,-462.67,-457.32,-451.96,-446.6,-441.25,-435.89,-430.54,-425.18,-419.83,-414.47,-409.12,-403.76,-398.4,-393.05,-387.69,-382.34,-376.98,-371.63,-366.27,-360.91,-355.56,-350.2,-344.85,-339.49,-334.14,-328.78,-323.42,-318.07,-312.71,-307.36,-302.0,-296.65,-291.29,-285.94,-280.58,-275.22,-269.87,-264.51,-259.16,-253.8,-248.45,-243.09,-237.73,-232.38,-227.02,-221.67,-216.31,-210.96,-205.6,-200.24,-194.89,-189.53,-184.18,-178.82,-173.47,-168.11,-162.76,-157.4,-152.04,-146.69,-141.33,-135.98,-130.62,-125.27,-119.91,-114.55,-109.2,-103.84,-98.49,-93.13,-87.78,-82.42,-77.06,-71.71,-66.35,-61.0,-55.64,-50.29,-44.93,-39.58,-34.22,-28.86,-23.51,-18.15,-12.8,-7.44,-2.09,3.27,8.63,13.98,19.34,24.69,30.05,35.4,40.76,46.11,51.47,56.83,62.18,67.54,72.89,78.25,83.6,88.96,94.32,99.67,105.03,110.38,115.74,121.09,126.45,131.81,137.16,142.52,147.87,153.23,158.58,163.94,169.29,174.65,180.01,185.36,190.72,196.07,201.43,206.78,212.14,217.5,222.85,228.21,233.56,238.92,244.27,249.63,254.99,260.34,265.7,271.05,276.41,281.76,287.12,292.47,297.83,303.19,308.54,313.9,319.25,324.61,329.96,335.32,340.68,346.03,351.39,356.74,362.1,367.45,372.81,378.17,383.52,388.88,394.23,399.59,404.94,410.3,415.65,421.01,426.37,431.72,437.08,442.43,447.79,453.14,458.5,463.86,469.21,474.57,479.92,485.28,490.63,495.99,501.35,506.7,512.06,517.41,522.77,528.12,533.48,538.83,544.19,549.55,554.9,560.26,565.61,570.97,576.32,581.68,587.04,592.39,597.75,603.1,608.46,613.81,619.17,624.52,629.88,635.24,640.59,-640.21,-634.85,-629.49,-624.14,-618.78,-613.43,-608.07,-602.72,-597.36,-592.0,-586.65,-581.29,-575.94,-570.58,-565.23,-559.87,-554.51,-549.16,-543.8,-538.45,-533.09,-527.74,-522.38,-517.03,-511.67,-506.31,-500.96,-495.6,-490.25,-484.89,-479.54,-474.18,-468.82,-463.47,-458.11,-452.76,-447.4,-442.05,-436.69,-431.34,-425.98,-420.62,-415.27,-409.91,-404.56,-399.2,-393.85,-388.49,-383.13,-377.78,-372.42,-367.07,-361.71,-356.36,-351.0,-345.64,-340.29,-334.93,-329.58,-324.22,-318.87,-313.51,-308.16,-302.8,-297.44,-292.09,-286.73,-281.38,-276.02,-270.67,-265.31,-259.95,-254.6,-249.24,-243.89,-238.53,-233.18,-227.82,-222.46,-217.11,-211.75,-206.4,-201.04,-195.69,-190.33,-184.98,-179.62,-174.26,-168.91,-163.55,-158.2,-152.84,-147.49,-142.13,-136.77,-131.42,-126.06,-120.71,-115.35,-110.0,-104.64,-99.28,-93.93,-88.57,-83.22,-77.86,-72.51,-67.15,-61.8,-56.44,-51.08,-45.73,-40.37,-35.02,-29.66,-24.31,-18.95,-13.59,-8.24,-2.88,2.47,7.83,13.18,18.54,23.9,29.25,34.61,39.96,45.32,50.67,56.03,61.38,66.74,72.1,77.45,82.81,88.16,93.52,98.87,104.23,109.59,114.94,120.3,125.65,131.01,136.36,141.72,147.08,152.43,157.79,163.14,168.5,173.85,179.21,184.56,189.92,195.28,200.63,205.99,211.34,216.7,222.05,227.41,232.77,238.12,243.48,248.83,254.19,259.54,264.9,270.25,275.61,280.97,286.32,291.68,297.03,302.39,307.74,313.1,318.46,323.81,329.17,334.52,339.88,345.23,350.59,355.95,361.3,366.66,372.01,377.37,382.72,388.08,393.43,398.79,404.15,409.5,414.86,420.21,425.57,430.92,436.28,441.64,446.99,452.35,457.7,463.06,468.41,473.77,479.13,484.48,489.84,495.19,500.55,505.9,511.26,516.61,521.97,527.33,532.68,538.04,543.39,548.75,554.1,559.46,564.82,570.17,575.53,580.88,586.24,591.59,596.95,602.31,607.66,613.02,618.37,623.73,629.08,634.44,639.79,-641.0,-635.65,-630.29,-624.93,-619.58,-614.22,-608.87,-603.51,-598.16,-592.8,-587.44,-582.09,-576.73,-571.38,-566.02,-560.67,-555.31,-549.95,-544.6,-539.24,-533.89,-528.53,-523.18,-517.82,-512.47,-507.11,-501.75,-496.4,-491.04,-485.69,-480.33,-474.98,-469.62,-464.26,-458.91,-453.55,-448.2,-442.84,-437.49,-432.13,-426.78,-421.42,-416.06,-410.71,-405.35,-400.0,-394.64,-389.29,-383.93,-378.57,-373.22,-367.86,-362.51,-357.15,-351.8,-346.44,-341.08,-335.73,-330.37,-325.02,-319.66,-314.31,-308.95,-303.6,-298.24,-292.88,-287.53,-282.17,-276.82,-271.46,-266.11,-260.75,-255.39,-250.04,-244.68,-239.33,-233.97,-228.62,-223.26,-217.9,-212.55,-207.19,-201.84,-196.48,-191.13,-185.77,-180.42,-175.06,-169.7,-164.35,-158.99,-153.64,-148.28,-142.93,-137.57,-132.21,-126.86,-121.5,-116.15,-110.79,-105.44,-100.08,-94.72,-89.37,-84.01,-78.66,-73.3,-67.95,-62.59,-57.24,-51.88,-46.52,-41.17,-35.81,-30.46,-25.1,-19.75,-14.39,-9.03,-3.68,1.68,7.03,12.39,17.74,23.1,28.46,33.81,39.17,44.52,49.88,55.23,60.59,65.94,71.3,76.66,82.01,87.37,92.72,98.08,103.43,108.79,114.15,119.5,124.86,130.21,135.57,140.92,146.28,151.64,156.99,162.35,167.7,173.06,178.41,183.77,189.12,194.48,199.84,205.19,210.55,215.9,221.26,226.61,231.97,237.33,242.68,248.04,253.39,258.75,264.1,269.46,274.81,280.17,285.53,290.88,296.24,301.59,306.95,312.3,317.66,323.02,328.37,333.73,339.08,344.44,349.79,355.15,360.51,365.86,371.22,376.57,381.93,387.28,392.64,397.99,403.35,408.71,414.06,419.42,424.77,430.13,435.48,440.84,446.2,451.55,456.91,462.26,467.62,472.97,478.33,483.69,489.04,494.4,499.75,505.11,510.46,515.82,521.17,526.53,531.89,537.24,542.6,547.95,553.31,558.66,564.02,569.38,574.73,580.09,585.44,590.8,596.15,601.51,606.87,612.22,617.58,622.93,628.29,633.64,639.0,-641.79,-636.43,-631.08,-625.72,-620.37,-615.01,-609.65,-604.3,-598.94,-593.59,-588.23,-582.88,-577.52,-572.17,-566.81,-561.45,-556.1,-550.74,-545.39,-540.03,-534.68,-529.32,-523.96,-518.61,-513.25,-507.9,-502.54,-497.19,-491.83,-486.47,-481.12,-475.76,-470.41,-465.05,-459.7,-454.34,-448.99,-443.63,-438.27,-432.92,-427.56,-422.21,-416.85,-411.5,-406.14,-400.78,-395.43,-390.07,-384.72,-379.36,-374.01,-368.65,-363.3,-357.94,-352.58,-347.23,-341.87,-336.52,-331.16,-325.81,-320.45,-315.09,-309.74,-304.38,-299.03,-293.67,-288.32,-282.96,-277.6,-272.25,-266.89,-261.54,-256.18,-250.83,-245.47,-240.12,-234.76,-229.4,-224.05,-218.69,-213.34,-207.98,-202.63,-197.27,-191.91,-186.56,-181.2,-175.85,-170.49,-165.14,-159.78,-154.42,-149.07,-143.71,-138.36,-133.0,-127.65,-122.29,-116.94,-111.58,-106.22,-100.87,-95.51,-90.16,-84.8,-79.45,-74.09,-68.73,-63.38,-58.02,-52.67,-47.31,-41.96,-36.6,-31.24,-25.89,-20.53,-15.18,-9.82,-4.47,0.89,6.24,11.6,16.96,22.31,27.67,33.02,38.38,43.73,49.09,54.45,59.8,65.16,70.51,75.87,81.22,86.58,91.94,97.29,102.65,108.0,113.36,118.71,124.07,129.42,134.78,140.14,145.49,150.85,156.2,161.56,166.91,172.27,177.63,182.98,188.34,193.69,199.05,204.4,209.76,215.12,220.47,225.83,231.18,236.54,241.89,247.25,252.6,257.96,263.32,268.67,274.03,279.38,284.74,290.09,295.45,300.81,306.16,311.52,316.87,322.23,327.58,332.94,338.29,343.65,349.01,354.36,359.72,365.07,370.43,375.78,381.14,386.5,391.85,397.21,402.56,407.92,413.27,418.63,423.99,429.34,434.7,440.05,445.41,450.76,456.12,461.47,466.83,472.19,477.54,482.9,488.25,493.61,498.96,504.32,509.68,515.03,520.39,525.74,531.1,536.45,541.81,547.17,552.52,557.88,563.23,568.59,573.94,579.3,584.65,590.01,595.37,600.72,606.08,611.43,616.79,622.14,627.5,632.86,638.21,-642.56,-637.21,-631.85,-626.5,-621.14,-615.78,-610.43,-605.07,-599.72,-594.36,-589.01,-583.65,-578.29,-572.94,-567.58,-562.23,-556.87,-551.52,-546.16,-540.81,-535.45,-530.09,-524.74,-519.38,-514.03,-508.67,-503.32,-497.96,-492.6,-487.25,-481.89,-476.54,-471.18,-465.83,-460.47,-455.11,-449.76,-444.4,-439.05,-433.69,-428.34,-422.98,-417.63,-412.27,-406.91,-401.56,-396.2,-390.85,-385.49,-380.14,-374.78,-369.42,-364.07,-358.71,-353.36,-348.0,-342.65,-337.29,-331.93,-326.58,-321.22,-315.87,-310.51,-305.16,-299.8,-294.45,-289.09,-283.73,-278.38,-273.02,-267.67,-262.31,-256.96,-251.6,-246.24,-240.89,-235.53,-230.18,-224.82,-219.47,-214.11,-208.75,-203.4,-198.04,-192.69,-187.33,-181.98,-176.62,-171.27,-165.91,-160.55,-155.2,-149.84,-144.49,-139.13,-133.78,-128.42,-123.06,-117.71,-112.35,-107.0,-101.64,-96.29,-90.93,-85.58,-80.22,-74.86,-69.51,-64.15,-58.8,-53.44,-48.09,-42.73,-37.37,-32.02,-26.66,-21.31,-15.95,-10.6,-5.24,0.12,5.47,10.83,16.18,21.54,26.89,32.25,37.6,42.96,48.32,53.67,59.03,64.38,69.74,75.09,80.45,85.81,91.16,96.52,101.87,107.23,112.58,117.94,123.3,128.65,134.01,139.36,144.72,150.07,155.43,160.78,166.14,171.5,176.85,182.21,187.56,192.92,198.27,203.63,208.99,214.34,219.7,225.05,230.41,235.76,241.12,246.48,251.83,257.19,262.54,267.9,273.25,278.61,283.96,289.32,294.68,300.03,305.39,310.74,316.1,321.45,326.81,332.17,337.52,342.88,348.23,353.59,358.94,364.3,369.66,375.01,380.37,385.72,391.08,396.43,401.79,407.14,412.5,417.86,423.21,428.57,433.92,439.28,444.63,449.99,455.35,460.7,466.06,471.41,476.77,482.12,487.48,492.84,498.19,503.55,508.9,514.26,519.61,524.97,530.32,535.68,541.04,546.39,551.75,557.1,562.46,567.81,573.17,578.53,583.88,589.24,594.59,599.95,605.3,610.66,616.01,621.37,626.73,632.08,637.44,-643.32,-637.96,-632.6,-627.25,-621.89,-616.54,-611.18,-605.83,-600.47,-595.12,-589.76,-584.4,-579.05,-573.69,-568.34,-562.98,-557.63,-552.27,-546.91,-541.56,-536.2,-530.85,-525.49,-520.14,-514.78,-509.42,-504.07,-498.71,-493.36,-488.0,-482.65,-477.29,-471.94,-466.58,-461.22,-455.87,-450.51,-445.16,-439.8,-434.45,-429.09,-423.73,-418.38,-413.02,-407.67,-402.31,-396.96,-391.6,-386.24,-380.89,-375.53,-370.18,-364.82,-359.47,-354.11,-348.76,-343.4,-338.04,-332.69,-327.33,-321.98,-316.62,-311.27,-305.91,-300.55,-295.2,-289.84,-284.49,-279.13,-273.78,-268.42,-263.07,-257.71,-252.35,-247.0,-241.64,-236.29,-230.93,-225.58,-220.22,-214.86,-209.51,-204.15,-198.8,-193.44,-188.09,-182.73,-177.37,-172.02,-166.66,-161.31,-155.95,-150.6,-145.24,-139.89,-134.53,-129.17,-123.82,-118.46,-113.11,-107.75,-102.4,-97.04,-91.68,-86.33,-80.97,-75.62,-70.26,-64.91,-59.55,-54.19,-48.84,-43.48,-38.13,-32.77,-27.42,-22.06,-16.71,-11.35,-5.99,-0.64,4.72,10.07,15.43,20.78,26.14,31.5,36.85,42.21,47.56,52.92,58.27,63.63,68.99,74.34,79.7,85.05,90.41,95.76,101.12,106.47,111.83,117.19,122.54,127.9,133.25,138.61,143.96,149.32,154.68,160.03,165.39,170.74,176.1,181.45,186.81,192.17,197.52,202.88,208.23,213.59,218.94,224.3,229.65,235.01,240.37,245.72,251.08,256.43,261.79,267.14,272.5,277.86,283.21,288.57,293.92,299.28,304.63,309.99,315.34,320.7,326.06,331.41,336.77,342.12,347.48,352.83,358.19,363.55,368.9,374.26,379.61,384.97,390.32,395.68,401.04,406.39,411.75,417.1,422.46,427.81,433.17,438.52,443.88,449.24,454.59,459.95,465.3,470.66,476.01,481.37,486.73,492.08,497.44,502.79,508.15,513.5,518.86,524.22,529.57,534.93,540.28,545.64,550.99,556.35,561.7,567.06,572.42,577.77,583.13,588.48,593.84,599.19,604.55,609.91,615.26,620.62,625.97,631.33,636.68,-644.04,-638.69,-633.33,-627.98,-622.62,-617.27,-611.91,-606.55,-601.2,-595.84,-590.49,-585.13,-579.78,-574.42,-569.06,-563.71,-558.35,-553.0,-547.64,-542.29,-536.93,-531.58,-526.22,-520.86,-515.51,-510.15,-504.8,-499.44,-494.09,-488.73,-483.37,-478.02,-472.66,-467.31,-461.95,-456.6,-451.24,-445.88,-440.53,-435.17,-429.82,-424.46,-419.11,-413.75,-408.4,-403.04,-397.68,-392.33,-386.97,-381.62,-376.26,-370.91,-365.55,-360.19,-354.84,-349.48,-344.13,-338.77,-333.42,-328.06,-322.7,-317.35,-311.99,-306.64,-301.28,-295.93,-290.57,-285.22,-279.86,-274.5,-269.15,-263.79,-258.44,-253.08,-247.73,-242.37,-237.01,-231.66,-226.3,-220.95,-215.59,-210.24,-204.88,-199.52,-194.17,-188.81,-183.46,-178.1,-172.75,-167.39,-162.04,-156.68,-151.32,-145.97,-140.61,-135.26,-129.9,-124.55,-119.19,-113.83,-108.48,-103.12,-97.77,-92.41,-87.06,-81.7,-76.34,-70.99,-65.63,-60.28,-54.92,-49.57,-44.21,-38.86,-33.5,-28.14,-22.79,-17.43,-12.08,-6.72,-1.37,3.99,9.35,14.7,20.06,25.41,30.77,36.12,41.48,46.83,52.19,57.55,62.9,68.26,73.61,78.97,84.32,89.68,95.04,100.39,105.75,111.1,116.46,121.81,127.17,132.53,137.88,143.24,148.59,153.95,159.3,164.66,170.01,175.37,180.73,186.08,191.44,196.79,202.15,207.5,212.86,218.22,223.57,228.93,234.28,239.64,244.99,250.35,255.71,261.06,266.42,271.77,277.13,282.48,287.84,293.19,298.55,303.91,309.26,314.62,319.97,325.33,330.68,336.04,341.4,346.75,352.11,357.46,362.82,368.17,373.53,378.89,384.24,389.6,394.95,400.31,405.66,411.02,416.37,421.73,427.09,432.44,437.8,443.15,448.51,453.86,459.22,464.58,469.93,475.29,480.64,486.0,491.35,496.71,502.07,507.42,512.78,518.13,523.49,528.84,534.2,539.55,544.91,550.27,555.62,560.98,566.33,571.69,577.04,582.4,587.76,593.11,598.47,603.82,609.18,614.53,619.89,625.25,630.6,635.96,-644.74,-639.38,-634.03,-628.67,-623.32,-617.96,-612.61,-607.25,-601.89,-596.54,-591.18,-585.83,-580.47,-575.12,-569.76,-564.4,-559.05,-553.69,-548.34,-542.98,-537.63,-532.27,-526.92,-521.56,-516.2,-510.85,-505.49,-500.14,-494.78,-489.43,-484.07,-478.71,-473.36,-468.0,-462.65,-457.29,-451.94,-446.58,-441.22,-435.87,-430.51,-425.16,-419.8,-414.45,-409.09,-403.74,-398.38,-393.02,-387.67,-382.31,-376.96,-371.6,-366.25,-360.89,-355.53,-350.18,-344.82,-339.47,-334.11,-328.76,-323.4,-318.04,-312.69,-307.33,-301.98,-296.62,-291.27,-285.91,-280.56,-275.2,-269.84,-264.49,-259.13,-253.78,-248.42,-243.07,-237.71,-232.35,-227.0,-221.64,-216.29,-210.93,-205.58,-200.22,-194.87,-189.51,-184.15,-178.8,-173.44,-168.09,-162.73,-157.38,-152.02,-146.66,-141.31,-135.95,-130.6,-125.24,-119.89,-114.53,-109.17,-103.82,-98.46,-93.11,-87.75,-82.4,-77.04,-71.69,-66.33,-60.97,-55.62,-50.26,-44.91,-39.55,-34.2,-28.84,-23.48,-18.13,-12.77,-7.42,-2.06,3.29,8.65,14.01,19.36,24.72,30.07,35.43,40.78,46.14,51.49,56.85,62.21,67.56,72.92,78.27,83.63,88.98,94.34,99.7,105.05,110.41,115.76,121.12,126.47,131.83,137.19,142.54,147.9,153.25,158.61,163.96,169.32,174.67,180.03,185.39,190.74,196.1,201.45,206.81,212.16,217.52,222.88,228.23,233.59,238.94,244.3,249.65,255.01,260.37,265.72,271.08,276.43,281.79,287.14,292.5,297.85,303.21,308.57,313.92,319.28,324.63,329.99,335.34,340.7,346.06,351.41,356.77,362.12,367.48,372.83,378.19,383.54,388.9,394.26,399.61,404.97,410.32,415.68,421.03,426.39,431.75,437.1,442.46,447.81,453.17,458.52,463.88,469.24,474.59,479.95,485.3,490.66,496.01,501.37,506.72,512.08,517.44,522.79,528.15,533.5,538.86,544.21,549.57,554.93,560.28,565.64,570.99,576.35,581.7,587.06,592.42,597.77,603.13,608.48,613.84,619.19,624.55,629.9,635.26,-645.4,-640.04,-634.69,-629.33,-623.98,-618.62,-613.26,-607.91,-602.55,-597.2,-591.84,-586.49,-581.13,-575.77,-570.42,-565.06,-559.71,-554.35,-549.0,-543.64,-538.29,-532.93,-527.57,-522.22,-516.86,-511.51,-506.15,-500.8,-495.44,-490.08,-484.73,-479.37,-474.02,-468.66,-463.31,-457.95,-452.59,-447.24,-441.88,-436.53,-431.17,-425.82,-420.46,-415.11,-409.75,-404.39,-399.04,-393.68,-388.33,-382.97,-377.62,-372.26,-366.9,-361.55,-356.19,-350.84,-345.48,-340.13,-334.77,-329.41,-324.06,-318.7,-313.35,-307.99,-302.64,-297.28,-291.93,-286.57,-281.21,-275.86,-270.5,-265.15,-259.79,-254.44,-249.08,-243.72,-238.37,-233.01,-227.66,-222.3,-216.95,-211.59,-206.23,-200.88,-195.52,-190.17,-184.81,-179.46,-174.1,-168.75,-163.39,-158.03,-152.68,-147.32,-141.97,-136.61,-131.26,-125.9,-120.54,-115.19,-109.83,-104.48,-99.12,-93.77,-88.41,-83.06,-77.7,-72.34,-66.99,-61.63,-56.28,-50.92,-45.57,-40.21,-34.85,-29.5,-24.14,-18.79,-13.43,-8.08,-2.72,2.64,7.99,13.35,18.7,24.06,29.41,34.77,40.12,45.48,50.84,56.19,61.55,66.9,72.26,77.61,82.97,88.33,93.68,99.04,104.39,109.75,115.1,120.46,125.82,131.17,136.53,141.88,147.24,152.59,157.95,163.3,168.66,174.02,179.37,184.73,190.08,195.44,200.79,206.15,211.51,216.86,222.22,227.57,232.93,238.28,243.64,249.0,254.35,259.71,265.06,270.42,275.77,281.13,286.48,291.84,297.2,302.55,307.91,313.26,318.62,323.97,329.33,334.69,340.04,345.4,350.75,356.11,361.46,366.82,372.18,377.53,382.89,388.24,393.6,398.95,404.31,409.66,415.02,420.38,425.73,431.09,436.44,441.8,447.15,452.51,457.87,463.22,468.58,473.93,479.29,484.64,490.0,495.35,500.71,506.07,511.42,516.78,522.13,527.49,532.84,538.2,543.56,548.91,554.27,559.62,564.98,570.33,575.69,581.05,586.4,591.76,597.11,602.47,607.82,613.18,618.53,623.89,629.25,634.6,-646.01,-640.66,-635.3,-629.95,-624.59,-619.24,-613.88,-608.52,-603.17,-597.81,-592.46,-587.1,-581.75,-576.39,-571.04,-565.68,-560.32,-554.97,-549.61,-544.26,-538.9,-533.55,-528.19,-522.83,-517.48,-512.12,-506.77,-501.41,-496.06,-490.7,-485.34,-479.99,-474.63,-469.28,-463.92,-458.57,-453.21,-447.86,-442.5,-437.14,-431.79,-426.43,-421.08,-415.72,-410.37,-405.01,-399.65,-394.3,-388.94,-383.59,-378.23,-372.88,-367.52,-362.17,-356.81,-351.45,-346.1,-340.74,-335.39,-330.03,-324.68,-319.32,-313.96,-308.61,-303.25,-297.9,-292.54,-287.19,-281.83,-276.47,-271.12,-265.76,-260.41,-255.05,-249.7,-244.34,-238.99,-233.63,-228.27,-222.92,-217.56,-212.21,-206.85,-201.5,-196.14,-190.78,-185.43,-180.07,-174.72,-169.36,-164.01,-158.65,-153.29,-147.94,-142.58,-137.23,-131.87,-126.52,-121.16,-115.81,-110.45,-105.09,-99.74,-94.38,-89.03,-83.67,-78.32,-72.96,-67.6,-62.25,-56.89,-51.54,-46.18,-40.83,-35.47,-30.11,-24.76,-19.4,-14.05,-8.69,-3.34,2.02,7.37,12.73,18.09,23.44,28.8,34.15,39.51,44.86,50.22,55.58,60.93,66.29,71.64,77.0,82.35,87.71,93.07,98.42,103.78,109.13,114.49,119.84,125.2,130.55,135.91,141.27,146.62,151.98,157.33,162.69,168.04,173.4,178.76,184.11,189.47,194.82,200.18,205.53,210.89,216.24,221.6,226.96,232.31,237.67,243.02,248.38,253.73,259.09,264.45,269.8,275.16,280.51,285.87,291.22,296.58,301.94,307.29,312.65,318.0,323.36,328.71,334.07,339.42,344.78,350.14,355.49,360.85,366.2,371.56,376.91,382.27,387.63,392.98,398.34,403.69,409.05,414.4,419.76,425.12,430.47,435.83,441.18,446.54,451.89,457.25,462.6,467.96,473.32,478.67,484.03,489.38,494.74,500.09,505.45,510.81,516.16,521.52,526.87,532.23,537.58,542.94,548.3,553.65,559.01,564.36,569.72,575.07,580.43,585.78,591.14,596.5,601.85,607.21,612.56,617.92,623.27,628.63,633.99,-646.58,-641.23,-635.87,-630.52,-625.16,-619.81,-614.45,-609.09,-603.74,-598.38,-593.03,-587.67,-582.32,-576.96,-571.6,-566.25,-560.89,-555.54,-550.18,-544.83,-539.47,-534.11,-528.76,-523.4,-518.05,-512.69,-507.34,-501.98,-496.63,-491.27,-485.91,-480.56,-475.2,-469.85,-464.49,-459.14,-453.78,-448.42,-443.07,-437.71,-432.36,-427.0,-421.65,-416.29,-410.93,-405.58,-400.22,-394.87,-389.51,-384.16,-378.8,-373.45,-368.09,-362.73,-357.38,-352.02,-346.67,-341.31,-335.96,-330.6,-325.24,-319.89,-314.53,-309.18,-303.82,-298.47,-293.11,-287.76,-282.4,-277.04,-271.69,-266.33,-260.98,-255.62,-250.27,-244.91,-239.55,-234.2,-228.84,-223.49,-218.13,-212.78,-207.42,-202.06,-196.71,-191.35,-186.0,-180.64,-175.29,-169.93,-164.58,-159.22,-153.86,-148.51,-143.15,-137.8,-132.44,-127.09,-121.73,-116.37,-111.02,-105.66,-100.31,-94.95,-89.6,-84.24,-78.88,-73.53,-68.17,-62.82,-57.46,-52.11,-46.75,-41.4,-36.04,-30.68,-25.33,-19.97,-14.62,-9.26,-3.91,1.45,6.81,12.16,17.52,22.87,28.23,33.58,38.94,44.3,49.65,55.01,60.36,65.72,71.07,76.43,81.78,87.14,92.5,97.85,103.21,108.56,113.92,119.27,124.63,129.99,135.34,140.7,146.05,151.41,156.76,162.12,167.48,172.83,178.19,183.54,188.9,194.25,199.61,204.96,210.32,215.68,221.03,226.39,231.74,237.1,242.45,247.81,253.17,258.52,263.88,269.23,274.59,279.94,285.3,290.66,296.01,301.37,306.72,312.08,317.43,322.79,328.14,333.5,338.86,344.21,349.57,354.92,360.28,365.63,370.99,376.35,381.7,387.06,392.41,397.77,403.12,408.48,413.83,419.19,424.55,429.9,435.26,440.61,445.97,451.32,456.68,462.04,467.39,472.75,478.1,483.46,488.81,494.17,499.53,504.88,510.24,515.59,520.95,526.3,531.66,537.01,542.37,547.73,553.08,558.44,563.79,569.15,574.5,579.86,585.22,590.57,595.93,601.28,606.64,611.99,617.35,622.71,628.06,633.42,-647.1,-641.75,-636.39,-631.03,-625.68,-620.32,-614.97,-609.61,-604.26,-598.9,-593.54,-588.19,-582.83,-577.48,-572.12,-566.77,-561.41,-556.05,-550.7,-545.34,-539.99,-534.63,-529.28,-523.92,-518.57,-513.21,-507.85,-502.5,-497.14,-491.79,-486.43,-481.08,-475.72,-470.36,-465.01,-459.65,-454.3,-448.94,-443.59,-438.23,-432.87,-427.52,-422.16,-416.81,-411.45,-406.1,-400.74,-395.39,-390.03,-384.67,-379.32,-373.96,-368.61,-363.25,-357.9,-352.54,-347.18,-341.83,-336.47,-331.12,-325.76,-320.41,-315.05,-309.69,-304.34,-298.98,-293.63,-288.27,-282.92,-277.56,-272.21,-266.85,-261.49,-256.14,-250.78,-245.43,-240.07,-234.72,-229.36,-224.0,-218.65,-213.29,-207.94,-202.58,-197.23,-191.87,-186.52,-181.16,-175.8,-170.45,-165.09,-159.74,-154.38,-149.03,-143.67,-138.31,-132.96,-127.6,-122.25,-116.89,-111.54,-106.18,-100.82,-95.47,-90.11,-84.76,-79.4,-74.05,-68.69,-63.34,-57.98,-52.62,-47.27,-41.91,-36.56,-31.2,-25.85,-20.49,-15.13,-9.78,-4.42,0.93,6.29,11.64,17.0,22.36,27.71,33.07,38.42,43.78,49.13,54.49,59.84,65.2,70.56,75.91,81.27,86.62,91.98,97.33,102.69,108.05,113.4,118.76,124.11,129.47,134.82,140.18,145.54,150.89,156.25,161.6,166.96,172.31,177.67,183.02,188.38,193.74,199.09,204.45,209.8,215.16,220.51,225.87,231.23,236.58,241.94,247.29,252.65,258.0,263.36,268.72,274.07,279.43,284.78,290.14,295.49,300.85,306.2,311.56,316.92,322.27,327.63,332.98,338.34,343.69,349.05,354.41,359.76,365.12,370.47,375.83,381.18,386.54,391.89,397.25,402.61,407.96,413.32,418.67,424.03,429.38,434.74,440.1,445.45,450.81,456.16,461.52,466.87,472.23,477.59,482.94,488.3,493.65,499.01,504.36,509.72,515.07,520.43,525.79,531.14,536.5,541.85,547.21,552.56,557.92,563.28,568.63,573.99,579.34,584.7,590.05,595.41,600.77,606.12,611.48,616.83,622.19,627.54,632.9,-647.56,-642.21,-636.85,-631.5,-626.14,-620.78,-615.43,-610.07,-604.72,-599.36,-594.01,-588.65,-583.29,-577.94,-572.58,-567.23,-561.87,-556.52,-551.16,-545.81,-540.45,-535.09,-529.74,-524.38,-519.03,-513.67,-508.32,-502.96,-497.6,-492.25,-486.89,-481.54,-476.18,-470.83,-465.47,-460.11,-454.76,-449.4,-444.05,-438.69,-433.34,-427.98,-422.63,-417.27,-411.91,-406.56,-401.2,-395.85,-390.49,-385.14,-379.78,-374.42,-369.07,-363.71,-358.36,-353.0,-347.65,-342.29,-336.93,-331.58,-326.22,-320.87,-315.51,-310.16,-304.8,-299.45,-294.09,-288.73,-283.38,-278.02,-272.67,-267.31,-261.96,-256.6,-251.24,-245.89,-240.53,-235.18,-229.82,-224.47,-219.11,-213.75,-208.4,-203.04,-197.69,-192.33,-186.98,-181.62,-176.27,-170.91,-165.55,-160.2,-154.84,-149.49,-144.13,-138.78,-133.42,-128.06,-122.71,-117.35,-112.0,-106.64,-101.29,-95.93,-90.57,-85.22,-79.86,-74.51,-69.15,-63.8,-58.44,-53.09,-47.73,-42.37,-37.02,-31.66,-26.31,-20.95,-15.6,-10.24,-4.88,0.47,5.83,11.18,16.54,21.89,27.25,32.6,37.96,43.32,48.67,54.03,59.38,64.74,70.09,75.45,80.81,86.16,91.52,96.87,102.23,107.58,112.94,118.3,123.65,129.01,134.36,139.72,145.07,150.43,155.78,161.14,166.5,171.85,177.21,182.56,187.92,193.27,198.63,203.99,209.34,214.7,220.05,225.41,230.76,236.12,241.48,246.83,252.19,257.54,262.9,268.25,273.61,278.96,284.32,289.68,295.03,300.39,305.74,311.1,316.45,321.81,327.17,332.52,337.88,343.23,348.59,353.94,359.3,364.66,370.01,375.37,380.72,386.08,391.43,396.79,402.14,407.5,412.86,418.21,423.57,428.92,434.28,439.63,444.99,450.35,455.7,461.06,466.41,471.77,477.12,482.48,487.84,493.19,498.55,503.9,509.26,514.61,519.97,525.32,530.68,536.04,541.39,546.75,552.1,557.46,562.81,568.17,573.53,578.88,584.24,589.59,594.95,600.3,605.66,611.01,616.37,621.73,627.08,632.44,-647.96,-642.61,-637.25,-631.9,-626.54,-621.19,-615.83,-610.48,-605.12,-599.76,-594.41,-589.05,-583.7,-578.34,-572.99,-567.63,-562.27,-556.92,-551.56,-546.21,-540.85,-535.5,-530.14,-524.78,-519.43,-514.07,-508.72,-503.36,-498.01,-492.65,-487.3,-481.94,-476.58,-471.23,-465.87,-460.52,-455.16,-449.81,-444.45,-439.09,-433.74,-428.38,-423.03,-417.67,-412.32,-406.96,-401.6,-396.25,-390.89,-385.54,-380.18,-374.83,-369.47,-364.12,-358.76,-353.4,-348.05,-342.69,-337.34,-331.98,-326.63,-321.27,-315.91,-310.56,-305.2,-299.85,-294.49,-289.14,-283.78,-278.42,-273.07,-267.71,-262.36,-257.0,-251.65,-246.29,-240.94,-235.58,-230.22,-224.87,-219.51,-214.16,-208.8,-203.45,-198.09,-192.73,-187.38,-182.02,-176.67,-171.31,-165.96,-160.6,-155.24,-149.89,-144.53,-139.18,-133.82,-128.47,-123.11,-117.76,-112.4,-107.04,-101.69,-96.33,-90.98,-85.62,-80.27,-74.91,-69.55,-64.2,-58.84,-53.49,-48.13,-42.78,-37.42,-32.07,-26.71,-21.35,-16.0,-10.64,-5.29,0.07,5.42,10.78,16.14,21.49,26.85,32.2,37.56,42.91,48.27,53.63,58.98,64.34,69.69,75.05,80.4,85.76,91.11,96.47,101.83,107.18,112.54,117.89,123.25,128.6,133.96,139.32,144.67,150.03,155.38,160.74,166.09,171.45,176.81,182.16,187.52,192.87,198.23,203.58,208.94,214.29,219.65,225.01,230.36,235.72,241.07,246.43,251.78,257.14,262.5,267.85,273.21,278.56,283.92,289.27,294.63,299.99,305.34,310.7,316.05,321.41,326.76,332.12,337.47,342.83,348.19,353.54,358.9,364.25,369.61,374.96,380.32,385.68,391.03,396.39,401.74,407.1,412.45,417.81,423.17,428.52,433.88,439.23,444.59,449.94,455.3,460.65,466.01,471.37,476.72,482.08,487.43,492.79,498.14,503.5,508.86,514.21,519.57,524.92,530.28,535.63,540.99,546.34,551.7,557.06,562.41,567.77,573.12,578.48,583.83,589.19,594.55,599.9,605.26,610.61,615.97,621.32,626.68,632.04,-648.3,-642.95,-637.59,-632.24,-626.88,-621.53,-616.17,-610.81,-605.46,-600.1,-594.75,-589.39,-584.04,-578.68,-573.33,-567.97,-562.61,-557.26,-551.9,-546.55,-541.19,-535.84,-530.48,-525.12,-519.77,-514.41,-509.06,-503.7,-498.35,-492.99,-487.63,-482.28,-476.92,-471.57,-466.21,-460.86,-455.5,-450.15,-444.79,-439.43,-434.08,-428.72,-423.37,-418.01,-412.66,-407.3,-401.94,-396.59,-391.23,-385.88,-380.52,-375.17,-369.81,-364.45,-359.1,-353.74,-348.39,-343.03,-337.68,-332.32,-326.97,-321.61,-316.25,-310.9,-305.54,-300.19,-294.83,-289.48,-284.12,-278.76,-273.41,-268.05,-262.7,-257.34,-251.99,-246.63,-241.28,-235.92,-230.56,-225.21,-219.85,-214.5,-209.14,-203.79,-198.43,-193.07,-187.72,-182.36,-177.01,-171.65,-166.3,-160.94,-155.58,-150.23,-144.87,-139.52,-134.16,-128.81,-123.45,-118.1,-112.74,-107.38,-102.03,-96.67,-91.32,-85.96,-80.61,-75.25,-69.89,-64.54,-59.18,-53.83,-48.47,-43.12,-37.76,-32.4,-27.05,-21.69,-16.34,-10.98,-5.63,-0.27,5.08,10.44,15.8,21.15,26.51,31.86,37.22,42.57,47.93,53.29,58.64,64.0,69.35,74.71,80.06,85.42,90.78,96.13,101.49,106.84,112.2,117.55,122.91,128.26,133.62,138.98,144.33,149.69,155.04,160.4,165.75,171.11,176.47,181.82,187.18,192.53,197.89,203.24,208.6,213.96,219.31,224.67,230.02,235.38,240.73,246.09,251.44,256.8,262.16,267.51,272.87,278.22,283.58,288.93,294.29,299.65,305.0,310.36,315.71,321.07,326.42,331.78,337.13,342.49,347.85,353.2,358.56,363.91,369.27,374.62,379.98,385.34,390.69,396.05,401.4,406.76,412.11,417.47,422.83,428.18,433.54,438.89,444.25,449.6,454.96,460.31,465.67,471.03,476.38,481.74,487.09,492.45,497.8,503.16,508.52,513.87,519.23,524.58,529.94,535.29,540.65,546.01,551.36,556.72,562.07,567.43,572.78,578.14,583.49,588.85,594.21,599.56,604.92,610.27,615.63,620.98,626.34,631.7,-648.58,-643.22,-637.87,-632.51,-627.16,-621.8,-616.44,-611.09,-605.73,-600.38,-595.02,-589.67,-584.31,-578.96,-573.6,-568.24,-562.89,-557.53,-552.18,-546.82,-541.47,-536.11,-530.75,-525.4,-520.04,-514.69,-509.33,-503.98,-498.62,-493.27,-487.91,-482.55,-477.2,-471.84,-466.49,-461.13,-455.78,-450.42,-445.06,-439.71,-434.35,-429.0,-423.64,-418.29,-412.93,-407.57,-402.22,-396.86,-391.51,-386.15,-380.8,-375.44,-370.09,-364.73,-359.37,-354.02,-348.66,-343.31,-337.95,-332.6,-327.24,-321.88,-316.53,-311.17,-305.82,-300.46,-295.11,-289.75,-284.39,-279.04,-273.68,-268.33,-262.97,-257.62,-252.26,-246.91,-241.55,-236.19,-230.84,-225.48,-220.13,-214.77,-209.42,-204.06,-198.7,-193.35,-187.99,-182.64,-177.28,-171.93,-166.57,-161.21,-155.86,-150.5,-145.15,-139.79,-134.44,-129.08,-123.73,-118.37,-113.01,-107.66,-102.3,-96.95,-91.59,-86.24,-80.88,-75.52,-70.17,-64.81,-59.46,-54.1,-48.75,-43.39,-38.03,-32.68,-27.32,-21.97,-16.61,-11.26,-5.9,-0.55,4.81,10.17,15.52,20.88,26.23,31.59,36.94,42.3,47.66,53.01,58.37,63.72,69.08,74.43,79.79,85.14,90.5,95.86,101.21,106.57,111.92,117.28,122.63,127.99,133.35,138.7,144.06,149.41,154.77,160.12,165.48,170.84,176.19,181.55,186.9,192.26,197.61,202.97,208.32,213.68,219.04,224.39,229.75,235.1,240.46,245.81,251.17,256.53,261.88,267.24,272.59,277.95,283.3,288.66,294.02,299.37,304.73,310.08,315.44,320.79,326.15,331.5,336.86,342.22,347.57,352.93,358.28,363.64,368.99,374.35,379.71,385.06,390.42,395.77,401.13,406.48,411.84,417.2,422.55,427.91,433.26,438.62,443.97,449.33,454.68,460.04,465.4,470.75,476.11,481.46,486.82,492.17,497.53,502.89,508.24,513.6,518.95,524.31,529.66,535.02,540.38,545.73,551.09,556.44,561.8,567.15,572.51,577.86,583.22,588.58,593.93,599.29,604.64,610.0,615.35,620.71,626.07,631.42,-648.79,-643.43,-638.07,-632.72,-627.36,-622.01,-616.65,-611.3,-605.94,-600.59,-595.23,-589.87,-584.52,-579.16,-573.81,-568.45,-563.1,-557.74,-552.38,-547.03,-541.67,-536.32,-530.96,-525.61,-520.25,-514.89,-509.54,-504.18,-498.83,-493.47,-488.12,-482.76,-477.41,-472.05,-466.69,-461.34,-455.98,-450.63,-445.27,-439.92,-434.56,-429.2,-423.85,-418.49,-413.14,-407.78,-402.43,-397.07,-391.71,-386.36,-381.0,-375.65,-370.29,-364.94,-359.58,-354.23,-348.87,-343.51,-338.16,-332.8,-327.45,-322.09,-316.74,-311.38,-306.02,-300.67,-295.31,-289.96,-284.6,-279.25,-273.89,-268.53,-263.18,-257.82,-252.47,-247.11,-241.76,-236.4,-231.05,-225.69,-220.33,-214.98,-209.62,-204.27,-198.91,-193.56,-188.2,-182.84,-177.49,-172.13,-166.78,-161.42,-156.07,-150.71,-145.36,-140.0,-134.64,-129.29,-123.93,-118.58,-113.22,-107.87,-102.51,-97.15,-91.8,-86.44,-81.09,-75.73,-70.38,-65.02,-59.66,-54.31,-48.95,-43.6,-38.24,-32.89,-27.53,-22.18,-16.82,-11.46,-6.11,-0.75,4.6,9.96,15.31,20.67,26.03,31.38,36.74,42.09,47.45,52.8,58.16,63.52,68.87,74.23,79.58,84.94,90.29,95.65,101.0,106.36,111.72,117.07,122.43,127.78,133.14,138.49,143.85,149.21,154.56,159.92,165.27,170.63,175.98,181.34,186.7,192.05,197.41,202.76,208.12,213.47,218.83,224.18,229.54,234.9,240.25,245.61,250.96,256.32,261.67,267.03,272.39,277.74,283.1,288.45,293.81,299.16,304.52,309.88,315.23,320.59,325.94,331.3,336.65,342.01,347.36,352.72,358.08,363.43,368.79,374.14,379.5,384.85,390.21,395.57,400.92,406.28,411.63,416.99,422.34,427.7,433.05,438.41,443.77,449.12,454.48,459.83,465.19,470.54,475.9,481.26,486.61,491.97,497.32,502.68,508.03,513.39,518.75,524.1,529.46,534.81,540.17,545.52,550.88,556.23,561.59,566.95,572.3,577.66,583.01,588.37,593.72,599.08,604.44,609.79,615.15,620.5,625.86,631.21,-648.92,-643.57,-638.21,-632.86,-627.5,-622.15,-616.79,-611.43,-606.08,-600.72,-595.37,-590.01,-584.66,-579.3,-573.95,-568.59,-563.23,-557.88,-552.52,-547.17,-541.81,-536.46,-531.1,-525.74,-520.39,-515.03,-509.68,-504.32,-498.97,-493.61,-488.25,-482.9,-477.54,-472.19,-466.83,-461.48,-456.12,-450.77,-445.41,-440.05,-434.7,-429.34,-423.99,-418.63,-413.28,-407.92,-402.56,-397.21,-391.85,-386.5,-381.14,-375.79,-370.43,-365.07,-359.72,-354.36,-349.01,-343.65,-338.3,-332.94,-327.59,-322.23,-316.87,-311.52,-306.16,-300.81,-295.45,-290.1,-284.74,-279.38,-274.03,-268.67,-263.32,-257.96,-252.61,-247.25,-241.89,-236.54,-231.18,-225.83,-220.47,-215.12,-209.76,-204.41,-199.05,-193.69,-188.34,-182.98,-177.63,-172.27,-166.92,-161.56,-156.2,-150.85,-145.49,-140.14,-134.78,-129.43,-124.07,-118.72,-113.36,-108.0,-102.65,-97.29,-91.94,-86.58,-81.23,-75.87,-70.51,-65.16,-59.8,-54.45,-49.09,-43.74,-38.38,-33.02,-27.67,-22.31,-16.96,-11.6,-6.25,-0.89,4.46,9.82,15.18,20.53,25.89,31.24,36.6,41.95,47.31,52.67,58.02,63.38,68.73,74.09,79.44,84.8,90.16,95.51,100.87,106.22,111.58,116.93,122.29,127.64,133.0,138.36,143.71,149.07,154.42,159.78,165.13,170.49,175.85,181.2,186.56,191.91,197.27,202.62,207.98,213.34,218.69,224.05,229.4,234.76,240.11,245.47,250.82,256.18,261.54,266.89,272.25,277.6,282.96,288.31,293.67,299.03,304.38,309.74,315.09,320.45,325.8,331.16,336.52,341.87,347.23,352.58,357.94,363.29,368.65,374.0,379.36,384.72,390.07,395.43,400.78,406.14,411.49,416.85,422.21,427.56,432.92,438.27,443.63,448.98,454.34,459.7,465.05,470.41,475.76,481.12,486.47,491.83,497.18,502.54,507.9,513.25,518.61,523.96,529.32,534.67,540.03,545.39,550.74,556.1,561.45,566.81,572.16,577.52,582.87,588.23,593.59,598.94,604.3,609.65,615.01,620.36,625.72,631.08,-648.99,-643.64,-638.28,-632.93,-627.57,-622.21,-616.86,-611.5,-606.15,-600.79,-595.44,-590.08,-584.72,-579.37,-574.01,-568.66,-563.3,-557.95,-552.59,-547.24,-541.88,-536.52,-531.17,-525.81,-520.46,-515.1,-509.75,-504.39,-499.03,-493.68,-488.32,-482.97,-477.61,-472.26,-466.9,-461.54,-456.19,-450.83,-445.48,-440.12,-434.77,-429.41,-424.06,-418.7,-413.34,-407.99,-402.63,-397.28,-391.92,-386.57,-381.21,-375.85,-370.5,-365.14,-359.79,-354.43,-349.08,-343.72,-338.36,-333.01,-327.65,-322.3,-316.94,-311.59,-306.23,-300.88,-295.52,-290.16,-284.81,-279.45,-274.1,-268.74,-263.39,-258.03,-252.67,-247.32,-241.96,-236.61,-231.25,-225.9,-220.54,-215.18,-209.83,-204.47,-199.12,-193.76,-188.41,-183.05,-177.7,-172.34,-166.98,-161.63,-156.27,-150.92,-145.56,-140.21,-134.85,-129.49,-124.14,-118.78,-113.43,-108.07,-102.72,-97.36,-92.0,-86.65,-81.29,-75.94,-70.58,-65.23,-59.87,-54.52,-49.16,-43.8,-38.45,-33.09,-27.74,-22.38,-17.03,-11.67,-6.31,-0.96,4.4,9.75,15.11,20.46,25.82,31.18,36.53,41.89,47.24,52.6,57.95,63.31,68.66,74.02,79.38,84.73,90.09,95.44,100.8,106.15,111.51,116.87,122.22,127.58,132.93,138.29,143.64,149.0,154.35,159.71,165.07,170.42,175.78,181.13,186.49,191.84,197.2,202.56,207.91,213.27,218.62,223.98,229.33,234.69,240.05,245.4,250.76,256.11,261.47,266.82,272.18,277.53,282.89,288.25,293.6,298.96,304.31,309.67,315.02,320.38,325.74,331.09,336.45,341.8,347.16,352.51,357.87,363.23,368.58,373.94,379.29,384.65,390.0,395.36,400.71,406.07,411.43,416.78,422.14,427.49,432.85,438.2,443.56,448.92,454.27,459.63,464.98,470.34,475.69,481.05,486.41,491.76,497.12,502.47,507.83,513.18,518.54,523.89,529.25,534.61,539.96,545.32,550.67,556.03,561.38,566.74,572.1,577.45,582.81,588.16,593.52,598.87,604.23,609.59,614.94,620.3,625.65,631.01,-648.99,-643.63,-638.28,-632.92,-627.57,-622.21,-616.86,-611.5,-606.14,-600.79,-595.43,-590.08,-584.72,-579.37,-574.01,-568.66,-563.3,-557.94,-552.59,-547.23,-541.88,-536.52,-531.17,-525.81,-520.45,-515.1,-509.74,-504.39,-499.03,-493.68,-488.32,-482.96,-477.61,-472.25,-466.9,-461.54,-456.19,-450.83,-445.48,-440.12,-434.76,-429.41,-424.05,-418.7,-413.34,-407.99,-402.63,-397.27,-391.92,-386.56,-381.21,-375.85,-370.5,-365.14,-359.78,-354.43,-349.07,-343.72,-338.36,-333.01,-327.65,-322.3,-316.94,-311.58,-306.23,-300.87,-295.52,-290.16,-284.81,-279.45,-274.09,-268.74,-263.38,-258.03,-252.67,-247.32,-241.96,-236.6,-231.25,-225.89,-220.54,-215.18,-209.83,-204.47,-199.12,-193.76,-188.4,-183.05,-177.69,-172.34,-166.98,-161.63,-156.27,-150.91,-145.56,-140.2,-134.85,-129.49,-124.14,-118.78,-113.43,-108.07,-102.71,-97.36,-92.0,-86.65,-81.29,-75.94,-70.58,-65.22,-59.87,-54.51,-49.16,-43.8,-38.45,-33.09,-27.73,-22.38,-17.02,-11.67,-6.31,-0.96,4.4,9.75,15.11,20.47,25.82,31.18,36.53,41.89,47.24,52.6,57.96,63.31,68.67,74.02,79.38,84.73,90.09,95.45,100.8,106.16,111.51,116.87,122.22,127.58,132.93,138.29,143.65,149.0,154.36,159.71,165.07,170.42,175.78,181.14,186.49,191.85,197.2,202.56,207.91,213.27,218.63,223.98,229.34,234.69,240.05,245.4,250.76,256.11,261.47,266.83,272.18,277.54,282.89,288.25,293.6,298.96,304.32,309.67,315.03,320.38,325.74,331.09,336.45,341.81,347.16,352.52,357.87,363.23,368.58,373.94,379.29,384.65,390.01,395.36,400.72,406.07,411.43,416.78,422.14,427.5,432.85,438.21,443.56,448.92,454.27,459.63,464.99,470.34,475.7,481.05,486.41,491.76,497.12,502.47,507.83,513.19,518.54,523.9,529.25,534.61,539.96,545.32,550.68,556.03,561.39,566.74,572.1,577.45,582.81,588.16,593.52,598.88,604.23,609.59,614.94,620.3,625.65,631.01,-648.92,-643.56,-638.21,-632.85,-627.49,-622.14,-616.78,-611.43,-606.07,-600.72,-595.36,-590.0,-584.65,-579.29,-573.94,-568.58,-563.23,-557.87,-552.52,-547.16,-541.8,-536.45,-531.09,-525.74,-520.38,-515.03,-509.67,-504.31,-498.96,-493.6,-488.25,-482.89,-477.54,-472.18,-466.82,-461.47,-456.11,-450.76,-445.4,-440.05,-434.69,-429.34,-423.98,-418.62,-413.27,-407.91,-402.56,-397.2,-391.85,-386.49,-381.13,-375.78,-370.42,-365.07,-359.71,-354.36,-349.0,-343.64,-338.29,-332.93,-327.58,-322.22,-316.87,-311.51,-306.16,-300.8,-295.44,-290.09,-284.73,-279.38,-274.02,-268.67,-263.31,-257.95,-252.6,-247.24,-241.89,-236.53,-231.18,-225.82,-220.46,-215.11,-209.75,-204.4,-199.04,-193.69,-188.33,-182.98,-177.62,-172.26,-166.91,-161.55,-156.2,-150.84,-145.49,-140.13,-134.77,-129.42,-124.06,-118.71,-113.35,-108.0,-102.64,-97.29,-91.93,-86.57,-81.22,-75.86,-70.51,-65.15,-59.8,-54.44,-49.08,-43.73,-38.37,-33.02,-27.66,-22.31,-16.95,-11.59,-6.24,-0.88,4.47,9.83,15.18,20.54,25.89,31.25,36.61,41.96,47.32,52.67,58.03,63.38,68.74,74.1,79.45,84.81,90.16,95.52,100.87,106.23,111.59,116.94,122.3,127.65,133.01,138.36,143.72,149.07,154.43,159.79,165.14,170.5,175.85,181.21,186.56,191.92,197.28,202.63,207.99,213.34,218.7,224.05,229.41,234.77,240.12,245.48,250.83,256.19,261.54,266.9,272.25,277.61,282.97,288.32,293.68,299.03,304.39,309.74,315.1,320.46,325.81,331.17,336.52,341.88,347.23,352.59,357.95,363.3,368.66,374.01,379.37,384.72,390.08,395.43,400.79,406.15,411.5,416.86,422.21,427.57,432.92,438.28,443.64,448.99,454.35,459.7,465.06,470.41,475.77,481.13,486.48,491.84,497.19,502.55,507.9,513.26,518.61,523.97,529.33,534.68,540.04,545.39,550.75,556.1,561.46,566.82,572.17,577.53,582.88,588.24,593.59,598.95,604.3,609.66,615.02,620.37,625.73,631.08,-648.77,-643.42,-638.06,-632.71,-627.35,-622.0,-616.64,-611.28,-605.93,-600.57,-595.22,-589.86,-584.51,-579.15,-573.79,-568.44,-563.08,-557.73,-552.37,-547.02,-541.66,-536.31,-530.95,-525.59,-520.24,-514.88,-509.53,-504.17,-498.82,-493.46,-488.1,-482.75,-477.39,-472.04,-466.68,-461.33,-455.97,-450.61,-445.26,-439.9,-434.55,-429.19,-423.84,-418.48,-413.13,-407.77,-402.41,-397.06,-391.7,-386.35,-380.99,-375.64,-370.28,-364.92,-359.57,-354.21,-348.86,-343.5,-338.15,-332.79,-327.43,-322.08,-316.72,-311.37,-306.01,-300.66,-295.3,-289.95,-284.59,-279.23,-273.88,-268.52,-263.17,-257.81,-252.46,-247.1,-241.74,-236.39,-231.03,-225.68,-220.32,-214.97,-209.61,-204.25,-198.9,-193.54,-188.19,-182.83,-177.48,-172.12,-166.77,-161.41,-156.05,-150.7,-145.34,-139.99,-134.63,-129.28,-123.92,-118.56,-113.21,-107.85,-102.5,-97.14,-91.79,-86.43,-81.08,-75.72,-70.36,-65.01,-59.65,-54.3,-48.94,-43.59,-38.23,-32.87,-27.52,-22.16,-16.81,-11.45,-6.1,-0.74,4.62,9.97,15.33,20.68,26.04,31.39,36.75,42.1,47.46,52.82,58.17,63.53,68.88,74.24,79.59,84.95,90.31,95.66,101.02,106.37,111.73,117.08,122.44,127.8,133.15,138.51,143.86,149.22,154.57,159.93,165.28,170.64,176.0,181.35,186.71,192.06,197.42,202.77,208.13,213.49,218.84,224.2,229.55,234.91,240.26,245.62,250.98,256.33,261.69,267.04,272.4,277.75,283.11,288.46,293.82,299.18,304.53,309.89,315.24,320.6,325.95,331.31,336.67,342.02,347.38,352.73,358.09,363.44,368.8,374.16,379.51,384.87,390.22,395.58,400.93,406.29,411.64,417.0,422.36,427.71,433.07,438.42,443.78,449.13,454.49,459.85,465.2,470.56,475.91,481.27,486.62,491.98,497.33,502.69,508.05,513.4,518.76,524.11,529.47,534.82,540.18,545.54,550.89,556.25,561.6,566.96,572.31,577.67,583.03,588.38,593.74,599.09,604.45,609.8,615.16,620.51,625.87,631.23,-648.56,-643.21,-637.85,-632.49,-627.14,-621.78,-616.43,-611.07,-605.72,-600.36,-595.01,-589.65,-584.29,-578.94,-573.58,-568.23,-562.87,-557.52,-552.16,-546.8,-541.45,-536.09,-530.74,-525.38,-520.03,-514.67,-509.31,-503.96,-498.6,-493.25,-487.89,-482.54,-477.18,-471.83,-466.47,-461.11,-455.76,-450.4,-445.05,-439.69,-434.34,-428.98,-423.62,-418.27,-412.91,-407.56,-402.2,-396.85,-391.49,-386.14,-380.78,-375.42,-370.07,-364.71,-359.36,-354.0,-348.65,-343.29,-337.93,-332.58,-327.22,-321.87,-316.51,-311.16,-305.8,-300.44,-295.09,-289.73,-284.38,-279.02,-273.67,-268.31,-262.96,-257.6,-252.24,-246.89,-241.53,-236.18,-230.82,-225.47,-220.11,-214.75,-209.4,-204.04,-198.69,-193.33,-187.98,-182.62,-177.26,-171.91,-166.55,-161.2,-155.84,-150.49,-145.13,-139.78,-134.42,-129.06,-123.71,-118.35,-113.0,-107.64,-102.29,-96.93,-91.57,-86.22,-80.86,-75.51,-70.15,-64.8,-59.44,-54.08,-48.73,-43.37,-38.02,-32.66,-27.31,-21.95,-16.6,-11.24,-5.88,-0.53,4.83,10.18,15.54,20.89,26.25,31.61,36.96,42.32,47.67,53.03,58.38,63.74,69.1,74.45,79.81,85.16,90.52,95.87,101.23,106.58,111.94,117.3,122.65,128.01,133.36,138.72,144.07,149.43,154.79,160.14,165.5,170.85,176.21,181.56,186.92,192.27,197.63,202.99,208.34,213.7,219.05,224.41,229.76,235.12,240.48,245.83,251.19,256.54,261.9,267.25,272.61,277.97,283.32,288.68,294.03,299.39,304.74,310.1,315.45,320.81,326.17,331.52,336.88,342.23,347.59,352.94,358.3,363.66,369.01,374.37,379.72,385.08,390.43,395.79,401.15,406.5,411.86,417.21,422.57,427.92,433.28,438.63,443.99,449.35,454.7,460.06,465.41,470.77,476.12,481.48,486.84,492.19,497.55,502.9,508.26,513.61,518.97,524.33,529.68,535.04,540.39,545.75,551.1,556.46,561.81,567.17,572.53,577.88,583.24,588.59,593.95,599.3,604.66,610.02,615.37,620.73,626.08,631.44,-648.28,-642.93,-637.57,-632.22,-626.86,-621.5,-616.15,-610.79,-605.44,-600.08,-594.73,-589.37,-584.01,-578.66,-573.3,-567.95,-562.59,-557.24,-551.88,-546.53,-541.17,-535.81,-530.46,-525.1,-519.75,-514.39,-509.04,-503.68,-498.32,-492.97,-487.61,-482.26,-476.9,-471.55,-466.19,-460.84,-455.48,-450.12,-444.77,-439.41,-434.06,-428.7,-423.35,-417.99,-412.63,-407.28,-401.92,-396.57,-391.21,-385.86,-380.5,-375.14,-369.79,-364.43,-359.08,-353.72,-348.37,-343.01,-337.66,-332.3,-326.94,-321.59,-316.23,-310.88,-305.52,-300.17,-294.81,-289.45,-284.1,-278.74,-273.39,-268.03,-262.68,-257.32,-251.96,-246.61,-241.25,-235.9,-230.54,-225.19,-219.83,-214.48,-209.12,-203.76,-198.41,-193.05,-187.7,-182.34,-176.99,-171.63,-166.27,-160.92,-155.56,-150.21,-144.85,-139.5,-134.14,-128.78,-123.43,-118.07,-112.72,-107.36,-102.01,-96.65,-91.3,-85.94,-80.58,-75.23,-69.87,-64.52,-59.16,-53.81,-48.45,-43.09,-37.74,-32.38,-27.03,-21.67,-16.32,-10.96,-5.6,-0.25,5.11,10.46,15.82,21.17,26.53,31.88,37.24,42.6,47.95,53.31,58.66,64.02,69.37,74.73,80.09,85.44,90.8,96.15,101.51,106.86,112.22,117.58,122.93,128.29,133.64,139.0,144.35,149.71,155.06,160.42,165.78,171.13,176.49,181.84,187.2,192.55,197.91,203.27,208.62,213.98,219.33,224.69,230.04,235.4,240.75,246.11,251.47,256.82,262.18,267.53,272.89,278.24,283.6,288.96,294.31,299.67,305.02,310.38,315.73,321.09,326.45,331.8,337.16,342.51,347.87,353.22,358.58,363.93,369.29,374.65,380.0,385.36,390.71,396.07,401.42,406.78,412.14,417.49,422.85,428.2,433.56,438.91,444.27,449.63,454.98,460.34,465.69,471.05,476.4,481.76,487.11,492.47,497.83,503.18,508.54,513.89,519.25,524.6,529.96,535.32,540.67,546.03,551.38,556.74,562.09,567.45,572.81,578.16,583.52,588.87,594.23,599.58,604.94,610.29,615.65,621.01,626.36,631.72,-647.94,-642.58,-637.23,-631.87,-626.52,-621.16,-615.8,-610.45,-605.09,-599.74,-594.38,-589.03,-583.67,-578.32,-572.96,-567.6,-562.25,-556.89,-551.54,-546.18,-540.83,-535.47,-530.11,-524.76,-519.4,-514.05,-508.69,-503.34,-497.98,-492.62,-487.27,-481.91,-476.56,-471.2,-465.85,-460.49,-455.14,-449.78,-444.42,-439.07,-433.71,-428.36,-423.0,-417.65,-412.29,-406.93,-401.58,-396.22,-390.87,-385.51,-380.16,-374.8,-369.44,-364.09,-358.73,-353.38,-348.02,-342.67,-337.31,-331.96,-326.6,-321.24,-315.89,-310.53,-305.18,-299.82,-294.47,-289.11,-283.75,-278.4,-273.04,-267.69,-262.33,-256.98,-251.62,-246.26,-240.91,-235.55,-230.2,-224.84,-219.49,-214.13,-208.78,-203.42,-198.06,-192.71,-187.35,-182.0,-176.64,-171.29,-165.93,-160.57,-155.22,-149.86,-144.51,-139.15,-133.8,-128.44,-123.08,-117.73,-112.37,-107.02,-101.66,-96.31,-90.95,-85.6,-80.24,-74.88,-69.53,-64.17,-58.82,-53.46,-48.11,-42.75,-37.39,-32.04,-26.68,-21.33,-15.97,-10.62,-5.26,0.09,5.45,10.81,16.16,21.52,26.87,32.23,37.58,42.94,48.3,53.65,59.01,64.36,69.72,75.07,80.43,85.79,91.14,96.5,101.85,107.21,112.56,117.92,123.27,128.63,133.99,139.34,144.7,150.05,155.41,160.76,166.12,171.48,176.83,182.19,187.54,192.9,198.25,203.61,208.97,214.32,219.68,225.03,230.39,235.74,241.1,246.45,251.81,257.17,262.52,267.88,273.23,278.59,283.94,289.3,294.66,300.01,305.37,310.72,316.08,321.43,326.79,332.15,337.5,342.86,348.21,353.57,358.92,364.28,369.63,374.99,380.35,385.7,391.06,396.41,401.77,407.12,412.48,417.84,423.19,428.55,433.9,439.26,444.61,449.97,455.33,460.68,466.04,471.39,476.75,482.1,487.46,492.81,498.17,503.53,508.88,514.24,519.59,524.95,530.3,535.66,541.02,546.37,551.73,557.08,562.44,567.79,573.15,578.5,583.86,589.22,594.57,599.93,605.28,610.64,615.99,621.35,626.71,632.06,-647.53,-642.18,-636.82,-631.47,-626.11,-620.75,-615.4,-610.04,-604.69,-599.33,-593.98,-588.62,-583.26,-577.91,-572.55,-567.2,-561.84,-556.49,-551.13,-545.77,-540.42,-535.06,-529.71,-524.35,-519.0,-513.64,-508.29,-502.93,-497.57,-492.22,-486.86,-481.51,-476.15,-470.8,-465.44,-460.08,-454.73,-449.37,-444.02,-438.66,-433.31,-427.95,-422.59,-417.24,-411.88,-406.53,-401.17,-395.82,-390.46,-385.11,-379.75,-374.39,-369.04,-363.68,-358.33,-352.97,-347.62,-342.26,-336.9,-331.55,-326.19,-320.84,-315.48,-310.13,-304.77,-299.41,-294.06,-288.7,-283.35,-277.99,-272.64,-267.28,-261.93,-256.57,-251.21,-245.86,-240.5,-235.15,-229.79,-224.44,-219.08,-213.72,-208.37,-203.01,-197.66,-192.3,-186.95,-181.59,-176.23,-170.88,-165.52,-160.17,-154.81,-149.46,-144.1,-138.75,-133.39,-128.03,-122.68,-117.32,-111.97,-106.61,-101.26,-95.9,-90.54,-85.19,-79.83,-74.48,-69.12,-63.77,-58.41,-53.06,-47.7,-42.34,-36.99,-31.63,-26.28,-20.92,-15.57,-10.21,-4.85,0.5,5.86,11.21,16.57,21.92,27.28,32.64,37.99,43.35,48.7,54.06,59.41,64.77,70.12,75.48,80.84,86.19,91.55,96.9,102.26,107.61,112.97,118.33,123.68,129.04,134.39,139.75,145.1,150.46,155.82,161.17,166.53,171.88,177.24,182.59,187.95,193.3,198.66,204.02,209.37,214.73,220.08,225.44,230.79,236.15,241.51,246.86,252.22,257.57,262.93,268.28,273.64,279.0,284.35,289.71,295.06,300.42,305.77,311.13,316.48,321.84,327.2,332.55,337.91,343.26,348.62,353.97,359.33,364.69,370.04,375.4,380.75,386.11,391.46,396.82,402.18,407.53,412.89,418.24,423.6,428.95,434.31,439.66,445.02,450.38,455.73,461.09,466.44,471.8,477.15,482.51,487.87,493.22,498.58,503.93,509.29,514.64,520.0,525.35,530.71,536.07,541.42,546.78,552.13,557.49,562.84,568.2,573.56,578.91,584.27,589.62,594.98,600.33,605.69,611.05,616.4,621.76,627.11,632.47,-647.07,-641.71,-636.36,-631.0,-625.64,-620.29,-614.93,-609.58,-604.22,-598.87,-593.51,-588.15,-582.8,-577.44,-572.09,-566.73,-561.38,-556.02,-550.66,-545.31,-539.95,-534.6,-529.24,-523.89,-518.53,-513.18,-507.82,-502.46,-497.11,-491.75,-486.4,-481.04,-475.69,-470.33,-464.97,-459.62,-454.26,-448.91,-443.55,-438.2,-432.84,-427.48,-422.13,-416.77,-411.42,-406.06,-400.71,-395.35,-390.0,-384.64,-379.28,-373.93,-368.57,-363.22,-357.86,-352.51,-347.15,-341.79,-336.44,-331.08,-325.73,-320.37,-315.02,-309.66,-304.3,-298.95,-293.59,-288.24,-282.88,-277.53,-272.17,-266.82,-261.46,-256.1,-250.75,-245.39,-240.04,-234.68,-229.33,-223.97,-218.61,-213.26,-207.9,-202.55,-197.19,-191.84,-186.48,-181.12,-175.77,-170.41,-165.06,-159.7,-154.35,-148.99,-143.64,-138.28,-132.92,-127.57,-122.21,-116.86,-111.5,-106.15,-100.79,-95.43,-90.08,-84.72,-79.37,-74.01,-68.66,-63.3,-57.95,-52.59,-47.23,-41.88,-36.52,-31.17,-25.81,-20.46,-15.1,-9.74,-4.39,0.97,6.32,11.68,17.03,22.39,27.75,33.1,38.46,43.81,49.17,54.52,59.88,65.23,70.59,75.95,81.3,86.66,92.01,97.37,102.72,108.08,113.44,118.79,124.15,129.5,134.86,140.21,145.57,150.93,156.28,161.64,166.99,172.35,177.7,183.06,188.41,193.77,199.13,204.48,209.84,215.19,220.55,225.9,231.26,236.62,241.97,247.33,252.68,258.04,263.39,268.75,274.11,279.46,284.82,290.17,295.53,300.88,306.24,311.59,316.95,322.31,327.66,333.02,338.37,343.73,349.08,354.44,359.8,365.15,370.51,375.86,381.22,386.57,391.93,397.29,402.64,408.0,413.35,418.71,424.06,429.42,434.77,440.13,445.49,450.84,456.2,461.55,466.91,472.26,477.62,482.98,488.33,493.69,499.04,504.4,509.75,515.11,520.46,525.82,531.18,536.53,541.89,547.24,552.6,557.95,563.31,568.67,574.02,579.38,584.73,590.09,595.44,600.8,606.16,611.51,616.87,622.22,627.58,632.93,-646.55,-641.19,-635.83,-630.48,-625.12,-619.77,-614.41,-609.06,-603.7,-598.34,-592.99,-587.63,-582.28,-576.92,-571.57,-566.21,-560.85,-555.5,-550.14,-544.79,-539.43,-534.08,-528.72,-523.37,-518.01,-512.65,-507.3,-501.94,-496.59,-491.23,-485.88,-480.52,-475.16,-469.81,-464.45,-459.1,-453.74,-448.39,-443.03,-437.68,-432.32,-426.96,-421.61,-416.25,-410.9,-405.54,-400.19,-394.83,-389.47,-384.12,-378.76,-373.41,-368.05,-362.7,-357.34,-351.98,-346.63,-341.27,-335.92,-330.56,-325.21,-319.85,-314.5,-309.14,-303.78,-298.43,-293.07,-287.72,-282.36,-277.01,-271.65,-266.29,-260.94,-255.58,-250.23,-244.87,-239.52,-234.16,-228.8,-223.45,-218.09,-212.74,-207.38,-202.03,-196.67,-191.32,-185.96,-180.6,-175.25,-169.89,-164.54,-159.18,-153.83,-148.47,-143.11,-137.76,-132.4,-127.05,-121.69,-116.34,-110.98,-105.62,-100.27,-94.91,-89.56,-84.2,-78.85,-73.49,-68.14,-62.78,-57.42,-52.07,-46.71,-41.36,-36.0,-30.65,-25.29,-19.93,-14.58,-9.22,-3.87,1.49,6.84,12.2,17.56,22.91,28.27,33.62,38.98,44.33,49.69,55.04,60.4,65.76,71.11,76.47,81.82,87.18,92.53,97.89,103.25,108.6,113.96,119.31,124.67,130.02,135.38,140.74,146.09,151.45,156.8,162.16,167.51,172.87,178.22,183.58,188.94,194.29,199.65,205.0,210.36,215.71,221.07,226.43,231.78,237.14,242.49,247.85,253.2,258.56,263.91,269.27,274.63,279.98,285.34,290.69,296.05,301.4,306.76,312.12,317.47,322.83,328.18,333.54,338.89,344.25,349.61,354.96,360.32,365.67,371.03,376.38,381.74,387.09,392.45,397.81,403.16,408.52,413.87,419.23,424.58,429.94,435.3,440.65,446.01,451.36,456.72,462.07,467.43,472.79,478.14,483.5,488.85,494.21,499.56,504.92,510.27,515.63,520.99,526.34,531.7,537.05,542.41,547.76,553.12,558.48,563.83,569.19,574.54,579.9,585.25,590.61,595.97,601.32,606.68,612.03,617.39,622.74,628.1,633.45,-645.97,-640.62,-635.26,-629.91,-624.55,-619.19,-613.84,-608.48,-603.13,-597.77,-592.42,-587.06,-581.71,-576.35,-570.99,-565.64,-560.28,-554.93,-549.57,-544.22,-538.86,-533.5,-528.15,-522.79,-517.44,-512.08,-506.73,-501.37,-496.01,-490.66,-485.3,-479.95,-474.59,-469.24,-463.88,-458.53,-453.17,-447.81,-442.46,-437.1,-431.75,-426.39,-421.04,-415.68,-410.32,-404.97,-399.61,-394.26,-388.9,-383.55,-378.19,-372.83,-367.48,-362.12,-356.77,-351.41,-346.06,-340.7,-335.35,-329.99,-324.63,-319.28,-313.92,-308.57,-303.21,-297.86,-292.5,-287.14,-281.79,-276.43,-271.08,-265.72,-260.37,-255.01,-249.65,-244.3,-238.94,-233.59,-228.23,-222.88,-217.52,-212.17,-206.81,-201.45,-196.1,-190.74,-185.39,-180.03,-174.68,-169.32,-163.96,-158.61,-153.25,-147.9,-142.54,-137.19,-131.83,-126.47,-121.12,-115.76,-110.41,-105.05,-99.7,-94.34,-88.99,-83.63,-78.27,-72.92,-67.56,-62.21,-56.85,-51.5,-46.14,-40.78,-35.43,-30.07,-24.72,-19.36,-14.01,-8.65,-3.29,2.06,7.42,12.77,18.13,23.48,28.84,34.19,39.55,44.91,50.26,55.62,60.97,66.33,71.68,77.04,82.4,87.75,93.11,98.46,103.82,109.17,114.53,119.88,125.24,130.6,135.95,141.31,146.66,152.02,157.37,162.73,168.09,173.44,178.8,184.15,189.51,194.86,200.22,205.58,210.93,216.29,221.64,227.0,232.35,237.71,243.06,248.42,253.78,259.13,264.49,269.84,275.2,280.55,285.91,291.27,296.62,301.98,307.33,312.69,318.04,323.4,328.76,334.11,339.47,344.82,350.18,355.53,360.89,366.24,371.6,376.96,382.31,387.67,393.02,398.38,403.73,409.09,414.45,419.8,425.16,430.51,435.87,441.22,446.58,451.94,457.29,462.65,468.0,473.36,478.71,484.07,489.42,494.78,500.14,505.49,510.85,516.2,521.56,526.91,532.27,537.63,542.98,548.34,553.69,559.05,564.4,569.76,575.12,580.47,585.83,591.18,596.54,601.89,607.25,612.6,617.96,623.32,628.67,634.03,-645.35,-640.0,-634.64,-629.29,-623.93,-618.58,-613.22,-607.86,-602.51,-597.15,-591.8,-586.44,-581.09,-575.73,-570.37,-565.02,-559.66,-554.31,-548.95,-543.6,-538.24,-532.88,-527.53,-522.17,-516.82,-511.46,-506.11,-500.75,-495.4,-490.04,-484.68,-479.33,-473.97,-468.62,-463.26,-457.91,-452.55,-447.19,-441.84,-436.48,-431.13,-425.77,-420.42,-415.06,-409.7,-404.35,-398.99,-393.64,-388.28,-382.93,-377.57,-372.22,-366.86,-361.5,-356.15,-350.79,-345.44,-340.08,-334.73,-329.37,-324.01,-318.66,-313.3,-307.95,-302.59,-297.24,-291.88,-286.52,-281.17,-275.81,-270.46,-265.1,-259.75,-254.39,-249.04,-243.68,-238.32,-232.97,-227.61,-222.26,-216.9,-211.55,-206.19,-200.83,-195.48,-190.12,-184.77,-179.41,-174.06,-168.7,-163.35,-157.99,-152.63,-147.28,-141.92,-136.57,-131.21,-125.86,-120.5,-115.14,-109.79,-104.43,-99.08,-93.72,-88.37,-83.01,-77.65,-72.3,-66.94,-61.59,-56.23,-50.88,-45.52,-40.17,-34.81,-29.45,-24.1,-18.74,-13.39,-8.03,-2.68,2.68,8.04,13.39,18.75,24.1,29.46,34.81,40.17,45.53,50.88,56.24,61.59,66.95,72.3,77.66,83.01,88.37,93.73,99.08,104.44,109.79,115.15,120.5,125.86,131.22,136.57,141.93,147.28,152.64,157.99,163.35,168.71,174.06,179.42,184.77,190.13,195.48,200.84,206.19,211.55,216.91,222.26,227.62,232.97,238.33,243.68,249.04,254.4,259.75,265.11,270.46,275.82,281.17,286.53,291.89,297.24,302.6,307.95,313.31,318.66,324.02,329.37,334.73,340.09,345.44,350.8,356.15,361.51,366.86,372.22,377.58,382.93,388.29,393.64,399.0,404.35,409.71,415.06,420.42,425.78,431.13,436.49,441.84,447.2,452.55,457.91,463.27,468.62,473.98,479.33,484.69,490.04,495.4,500.76,506.11,511.47,516.82,522.18,527.53,532.89,538.24,543.6,548.96,554.31,559.67,565.02,570.38,575.73,581.09,586.45,591.8,597.16,602.51,607.87,613.22,618.58,623.94,629.29,634.65,-644.69,-639.34,-633.98,-628.63,-623.27,-617.91,-612.56,-607.2,-601.85,-596.49,-591.14,-585.78,-580.42,-575.07,-569.71,-564.36,-559.0,-553.65,-548.29,-542.93,-537.58,-532.22,-526.87,-521.51,-516.16,-510.8,-505.45,-500.09,-494.73,-489.38,-484.02,-478.67,-473.31,-467.96,-462.6,-457.24,-451.89,-446.53,-441.18,-435.82,-430.47,-425.11,-419.75,-414.4,-409.04,-403.69,-398.33,-392.98,-387.62,-382.27,-376.91,-371.55,-366.2,-360.84,-355.49,-350.13,-344.78,-339.42,-334.06,-328.71,-323.35,-318.0,-312.64,-307.29,-301.93,-296.57,-291.22,-285.86,-280.51,-275.15,-269.8,-264.44,-259.09,-253.73,-248.37,-243.02,-237.66,-232.31,-226.95,-221.6,-216.24,-210.88,-205.53,-200.17,-194.82,-189.46,-184.11,-178.75,-173.39,-168.04,-162.68,-157.33,-151.97,-146.62,-141.26,-135.91,-130.55,-125.19,-119.84,-114.48,-109.13,-103.77,-98.42,-93.06,-87.7,-82.35,-76.99,-71.64,-66.28,-60.93,-55.57,-50.22,-44.86,-39.5,-34.15,-28.79,-23.44,-18.08,-12.73,-7.37,-2.01,3.34,8.7,14.05,19.41,24.76,30.12,35.48,40.83,46.19,51.54,56.9,62.25,67.61,72.96,78.32,83.68,89.03,94.39,99.74,105.1,110.45,115.81,121.17,126.52,131.88,137.23,142.59,147.94,153.3,158.66,164.01,169.37,174.72,180.08,185.43,190.79,196.14,201.5,206.86,212.21,217.57,222.92,228.28,233.63,238.99,244.35,249.7,255.06,260.41,265.77,271.12,276.48,281.84,287.19,292.55,297.9,303.26,308.61,313.97,319.32,324.68,330.04,335.39,340.75,346.1,351.46,356.81,362.17,367.53,372.88,378.24,383.59,388.95,394.3,399.66,405.02,410.37,415.73,421.08,426.44,431.79,437.15,442.5,447.86,453.22,458.57,463.93,469.28,474.64,479.99,485.35,490.71,496.06,501.42,506.77,512.13,517.48,522.84,528.19,533.55,538.91,544.26,549.62,554.97,560.33,565.68,571.04,576.4,581.75,587.11,592.46,597.82,603.17,608.53,613.89,619.24,624.6,629.95,635.31,-643.99,-638.64,-633.28,-627.93,-622.57,-617.22,-611.86,-606.5,-601.15,-595.79,-590.44,-585.08,-579.73,-574.37,-569.01,-563.66,-558.3,-552.95,-547.59,-542.24,-536.88,-531.53,-526.17,-520.81,-515.46,-510.1,-504.75,-499.39,-494.04,-488.68,-483.32,-477.97,-472.61,-467.26,-461.9,-456.55,-451.19,-445.83,-440.48,-435.12,-429.77,-424.41,-419.06,-413.7,-408.35,-402.99,-397.63,-392.28,-386.92,-381.57,-376.21,-370.86,-365.5,-360.14,-354.79,-349.43,-344.08,-338.72,-333.37,-328.01,-322.65,-317.3,-311.94,-306.59,-301.23,-295.88,-290.52,-285.17,-279.81,-274.45,-269.1,-263.74,-258.39,-253.03,-247.68,-242.32,-236.96,-231.61,-226.25,-220.9,-215.54,-210.19,-204.83,-199.47,-194.12,-188.76,-183.41,-178.05,-172.7,-167.34,-161.99,-156.63,-151.27,-145.92,-140.56,-135.21,-129.85,-124.5,-119.14,-113.78,-108.43,-103.07,-97.72,-92.36,-87.01,-81.65,-76.3,-70.94,-65.58,-60.23,-54.87,-49.52,-44.16,-38.81,-33.45,-28.09,-22.74,-17.38,-12.03,-6.67,-1.32,4.04,9.4,14.75,20.11,25.46,30.82,36.17,41.53,46.88,52.24,57.6,62.95,68.31,73.66,79.02,84.37,89.73,95.09,100.44,105.8,111.15,116.51,121.86,127.22,132.58,137.93,143.29,148.64,154.0,159.35,164.71,170.06,175.42,180.78,186.13,191.49,196.84,202.2,207.55,212.91,218.27,223.62,228.98,234.33,239.69,245.04,250.4,255.76,261.11,266.47,271.82,277.18,282.53,287.89,293.24,298.6,303.96,309.31,314.67,320.02,325.38,330.73,336.09,341.45,346.8,352.16,357.51,362.87,368.22,373.58,378.94,384.29,389.65,395.0,400.36,405.71,411.07,416.42,421.78,427.14,432.49,437.85,443.2,448.56,453.91,459.27,464.63,469.98,475.34,480.69,486.05,491.4,496.76,502.11,507.47,512.83,518.18,523.54,528.89,534.25,539.6,544.96,550.32,555.67,561.03,566.38,571.74,577.09,582.45,587.81,593.16,598.52,603.87,609.23,614.58,619.94,625.29,630.65,636.01,-643.26,-637.91,-632.55,-627.2,-621.84,-616.49,-611.13,-605.77,-600.42,-595.06,-589.71,-584.35,-579.0,-573.64,-568.29,-562.93,-557.57,-552.22,-546.86,-541.51,-536.15,-530.8,-525.44,-520.08,-514.73,-509.37,-504.02,-498.66,-493.31,-487.95,-482.59,-477.24,-471.88,-466.53,-461.17,-455.82,-450.46,-445.11,-439.75,-434.39,-429.04,-423.68,-418.33,-412.97,-407.62,-402.26,-396.9,-391.55,-386.19,-380.84,-375.48,-370.13,-364.77,-359.41,-354.06,-348.7,-343.35,-337.99,-332.64,-327.28,-321.93,-316.57,-311.21,-305.86,-300.5,-295.15,-289.79,-284.44,-279.08,-273.72,-268.37,-263.01,-257.66,-252.3,-246.95,-241.59,-236.23,-230.88,-225.52,-220.17,-214.81,-209.46,-204.1,-198.75,-193.39,-188.03,-182.68,-177.32,-171.97,-166.61,-161.26,-155.9,-150.54,-145.19,-139.83,-134.48,-129.12,-123.77,-118.41,-113.05,-107.7,-102.34,-96.99,-91.63,-86.28,-80.92,-75.57,-70.21,-64.85,-59.5,-54.14,-48.79,-43.43,-38.08,-32.72,-27.36,-22.01,-16.65,-11.3,-5.94,-0.59,4.77,10.12,15.48,20.84,26.19,31.55,36.9,42.26,47.61,52.97,58.33,63.68,69.04,74.39,79.75,85.1,90.46,95.82,101.17,106.53,111.88,117.24,122.59,127.95,133.3,138.66,144.02,149.37,154.73,160.08,165.44,170.79,176.15,181.51,186.86,192.22,197.57,202.93,208.28,213.64,219.0,224.35,229.71,235.06,240.42,245.77,251.13,256.48,261.84,267.2,272.55,277.91,283.26,288.62,293.97,299.33,304.69,310.04,315.4,320.75,326.11,331.46,336.82,342.18,347.53,352.89,358.24,363.6,368.95,374.31,379.66,385.02,390.38,395.73,401.09,406.44,411.8,417.15,422.51,427.87,433.22,438.58,443.93,449.29,454.64,460.0,465.36,470.71,476.07,481.42,486.78,492.13,497.49,502.84,508.2,513.56,518.91,524.27,529.62,534.98,540.33,545.69,551.05,556.4,561.76,567.11,572.47,577.82,583.18,588.53,593.89,599.25,604.6,609.96,615.31,620.67,626.02,631.38,636.74,-642.51,-637.15,-631.8,-626.44,-621.09,-615.73,-610.38,-605.02,-599.66,-594.31,-588.95,-583.6,-578.24,-572.89,-567.53,-562.17,-556.82,-551.46,-546.11,-540.75,-535.4,-530.04,-524.68,-519.33,-513.97,-508.62,-503.26,-497.91,-492.55,-487.2,-481.84,-476.48,-471.13,-465.77,-460.42,-455.06,-449.71,-444.35,-438.99,-433.64,-428.28,-422.93,-417.57,-412.22,-406.86,-401.5,-396.15,-390.79,-385.44,-380.08,-374.73,-369.37,-364.02,-358.66,-353.3,-347.95,-342.59,-337.24,-331.88,-326.53,-321.17,-315.81,-310.46,-305.1,-299.75,-294.39,-289.04,-283.68,-278.32,-272.97,-267.61,-262.26,-256.9,-251.55,-246.19,-240.84,-235.48,-230.12,-224.77,-219.41,-214.06,-208.7,-203.35,-197.99,-192.63,-187.28,-181.92,-176.57,-171.21,-165.86,-160.5,-155.14,-149.79,-144.43,-139.08,-133.72,-128.37,-123.01,-117.66,-112.3,-106.94,-101.59,-96.23,-90.88,-85.52,-80.17,-74.81,-69.45,-64.1,-58.74,-53.39,-48.03,-42.68,-37.32,-31.97,-26.61,-21.25,-15.9,-10.54,-5.19,0.17,5.52,10.88,16.24,21.59,26.95,32.3,37.66,43.01,48.37,53.73,59.08,64.44,69.79,75.15,80.5,85.86,91.21,96.57,101.93,107.28,112.64,117.99,123.35,128.7,134.06,139.42,144.77,150.13,155.48,160.84,166.19,171.55,176.91,182.26,187.62,192.97,198.33,203.68,209.04,214.39,219.75,225.11,230.46,235.82,241.17,246.53,251.88,257.24,262.6,267.95,273.31,278.66,284.02,289.37,294.73,300.09,305.44,310.8,316.15,321.51,326.86,332.22,337.57,342.93,348.29,353.64,359.0,364.35,369.71,375.06,380.42,385.78,391.13,396.49,401.84,407.2,412.55,417.91,423.27,428.62,433.98,439.33,444.69,450.04,455.4,460.75,466.11,471.47,476.82,482.18,487.53,492.89,498.24,503.6,508.96,514.31,519.67,525.02,530.38,535.73,541.09,546.45,551.8,557.16,562.51,567.87,573.22,578.58,583.93,589.29,594.65,600.0,605.36,610.71,616.07,621.42,626.78,632.14,637.49,-641.73,-636.38,-631.02,-625.67,-620.31,-614.96,-609.6,-604.24,-598.89,-593.53,-588.18,-582.82,-577.47,-572.11,-566.75,-561.4,-556.04,-550.69,-545.33,-539.98,-534.62,-529.27,-523.91,-518.55,-513.2,-507.84,-502.49,-497.13,-491.78,-486.42,-481.06,-475.71,-470.35,-465.0,-459.64,-454.29,-448.93,-443.58,-438.22,-432.86,-427.51,-422.15,-416.8,-411.44,-406.09,-400.73,-395.37,-390.02,-384.66,-379.31,-373.95,-368.6,-363.24,-357.88,-352.53,-347.17,-341.82,-336.46,-331.11,-325.75,-320.4,-315.04,-309.68,-304.33,-298.97,-293.62,-288.26,-282.91,-277.55,-272.19,-266.84,-261.48,-256.13,-250.77,-245.42,-240.06,-234.7,-229.35,-223.99,-218.64,-213.28,-207.93,-202.57,-197.22,-191.86,-186.5,-181.15,-175.79,-170.44,-165.08,-159.73,-154.37,-149.01,-143.66,-138.3,-132.95,-127.59,-122.24,-116.88,-111.52,-106.17,-100.81,-95.46,-90.1,-84.75,-79.39,-74.04,-68.68,-63.32,-57.97,-52.61,-47.26,-41.9,-36.55,-31.19,-25.83,-20.48,-15.12,-9.77,-4.41,0.94,6.3,11.66,17.01,22.37,27.72,33.08,38.43,43.79,49.14,54.5,59.86,65.21,70.57,75.92,81.28,86.63,91.99,97.35,102.7,108.06,113.41,118.77,124.12,129.48,134.83,140.19,145.55,150.9,156.26,161.61,166.97,172.32,177.68,183.04,188.39,193.75,199.1,204.46,209.81,215.17,220.53,225.88,231.24,236.59,241.95,247.3,252.66,258.01,263.37,268.73,274.08,279.44,284.79,290.15,295.5,300.86,306.22,311.57,316.93,322.28,327.64,332.99,338.35,343.71,349.06,354.42,359.77,365.13,370.48,375.84,381.19,386.55,391.91,397.26,402.62,407.97,413.33,418.68,424.04,429.4,434.75,440.11,445.46,450.82,456.17,461.53,466.89,472.24,477.6,482.95,488.31,493.66,499.02,504.37,509.73,515.09,520.44,525.8,531.15,536.51,541.86,547.22,552.58,557.93,563.29,568.64,574.0,579.35,584.71,590.07,595.42,600.78,606.13,611.49,616.84,622.2,627.55,632.91,638.27,-640.95,-635.59,-630.23,-624.88,-619.52,-614.17,-608.81,-603.46,-598.1,-592.74,-587.39,-582.03,-576.68,-571.32,-565.97,-560.61,-555.26,-549.9,-544.54,-539.19,-533.83,-528.48,-523.12,-517.77,-512.41,-507.05,-501.7,-496.34,-490.99,-485.63,-480.28,-474.92,-469.56,-464.21,-458.85,-453.5,-448.14,-442.79,-437.43,-432.08,-426.72,-421.36,-416.01,-410.65,-405.3,-399.94,-394.59,-389.23,-383.87,-378.52,-373.16,-367.81,-362.45,-357.1,-351.74,-346.38,-341.03,-335.67,-330.32,-324.96,-319.61,-314.25,-308.9,-303.54,-298.18,-292.83,-287.47,-282.12,-276.76,-271.41,-266.05,-260.69,-255.34,-249.98,-244.63,-239.27,-233.92,-228.56,-223.2,-217.85,-212.49,-207.14,-201.78,-196.43,-191.07,-185.72,-180.36,-175.0,-169.65,-164.29,-158.94,-153.58,-148.23,-142.87,-137.51,-132.16,-126.8,-121.45,-116.09,-110.74,-105.38,-100.03,-94.67,-89.31,-83.96,-78.6,-73.25,-67.89,-62.54,-57.18,-51.82,-46.47,-41.11,-35.76,-30.4,-25.05,-19.69,-14.33,-8.98,-3.62,1.73,7.09,12.44,17.8,23.15,28.51,33.87,39.22,44.58,49.93,55.29,60.64,66.0,71.36,76.71,82.07,87.42,92.78,98.13,103.49,108.85,114.2,119.56,124.91,130.27,135.62,140.98,146.33,151.69,157.05,162.4,167.76,173.11,178.47,183.82,189.18,194.54,199.89,205.25,210.6,215.96,221.31,226.67,232.03,237.38,242.74,248.09,253.45,258.8,264.16,269.51,274.87,280.23,285.58,290.94,296.29,301.65,307.0,312.36,317.72,323.07,328.43,333.78,339.14,344.49,349.85,355.21,360.56,365.92,371.27,376.63,381.98,387.34,392.69,398.05,403.41,408.76,414.12,419.47,424.83,430.18,435.54,440.9,446.25,451.61,456.96,462.32,467.67,473.03,478.39,483.74,489.1,494.45,499.81,505.16,510.52,515.87,521.23,526.59,531.94,537.3,542.65,548.01,553.36,558.72,564.08,569.43,574.79,580.14,585.5,590.85,596.21,601.56,606.92,612.28,617.63,622.99,628.34,633.7,639.05,-640.15,-634.79,-629.44,-624.08,-618.73,-613.37,-608.02,-602.66,-597.3,-591.95,-586.59,-581.24,-575.88,-570.53,-565.17,-559.81,-554.46,-549.1,-543.75,-538.39,-533.04,-527.68,-522.33,-516.97,-511.61,-506.26,-500.9,-495.55,-490.19,-484.84,-479.48,-474.12,-468.77,-463.41,-458.06,-452.7,-447.35,-441.99,-436.63,-431.28,-425.92,-420.57,-415.21,-409.86,-404.5,-399.15,-393.79,-388.43,-383.08,-377.72,-372.37,-367.01,-361.66,-356.3,-350.94,-345.59,-340.23,-334.88,-329.52,-324.17,-318.81,-313.46,-308.1,-302.74,-297.39,-292.03,-286.68,-281.32,-275.97,-270.61,-265.25,-259.9,-254.54,-249.19,-243.83,-238.48,-233.12,-227.76,-222.41,-217.05,-211.7,-206.34,-200.99,-195.63,-190.28,-184.92,-179.56,-174.21,-168.85,-163.5,-158.14,-152.79,-147.43,-142.07,-136.72,-131.36,-126.01,-120.65,-115.3,-109.94,-104.58,-99.23,-93.87,-88.52,-83.16,-77.81,-72.45,-67.1,-61.74,-56.38,-51.03,-45.67,-40.32,-34.96,-29.61,-24.25,-18.89,-13.54,-8.18,-2.83,2.53,7.88,13.24,18.6,23.95,29.31,34.66,40.02,45.37,50.73,56.08,61.44,66.8,72.15,77.51,82.86,88.22,93.57,98.93,104.29,109.64,115.0,120.35,125.71,131.06,136.42,141.78,147.13,152.49,157.84,163.2,168.55,173.91,179.26,184.62,189.98,195.33,200.69,206.04,211.4,216.75,222.11,227.47,232.82,238.18,243.53,248.89,254.24,259.6,264.96,270.31,275.67,281.02,286.38,291.73,297.09,302.44,307.8,313.16,318.51,323.87,329.22,334.58,339.93,345.29,350.65,356.0,361.36,366.71,372.07,377.42,382.78,388.13,393.49,398.85,404.2,409.56,414.91,420.27,425.62,430.98,436.34,441.69,447.05,452.4,457.76,463.11,468.47,473.83,479.18,484.54,489.89,495.25,500.6,505.96,511.31,516.67,522.03,527.38,532.74,538.09,543.45,548.8,554.16,559.52,564.87,570.23,575.58,580.94,586.29,591.65,597.01,602.36,607.72,613.07,618.43,623.78,629.14,634.49,639.85,-639.35,-634.0,-628.64,-623.29,-617.93,-612.57,-607.22,-601.86,-596.51,-591.15,-585.8,-580.44,-575.08,-569.73,-564.37,-559.02,-553.66,-548.31,-542.95,-537.6,-532.24,-526.88,-521.53,-516.17,-510.82,-505.46,-500.11,-494.75,-489.39,-484.04,-478.68,-473.33,-467.97,-462.62,-457.26,-451.9,-446.55,-441.19,-435.84,-430.48,-425.13,-419.77,-414.42,-409.06,-403.7,-398.35,-392.99,-387.64,-382.28,-376.93,-371.57,-366.21,-360.86,-355.5,-350.15,-344.79,-339.44,-334.08,-328.72,-323.37,-318.01,-312.66,-307.3,-301.95,-296.59,-291.24,-285.88,-280.52,-275.17,-269.81,-264.46,-259.1,-253.75,-248.39,-243.03,-237.68,-232.32,-226.97,-221.61,-216.26,-210.9,-205.54,-200.19,-194.83,-189.48,-184.12,-178.77,-173.41,-168.06,-162.7,-157.34,-151.99,-146.63,-141.28,-135.92,-130.57,-125.21,-119.85,-114.5,-109.14,-103.79,-98.43,-93.08,-87.72,-82.36,-77.01,-71.65,-66.3,-60.94,-55.59,-50.23,-44.88,-39.52,-34.16,-28.81,-23.45,-18.1,-12.74,-7.39,-2.03,3.33,8.68,14.04,19.39,24.75,30.1,35.46,40.81,46.17,51.53,56.88,62.24,67.59,72.95,78.3,83.66,89.02,94.37,99.73,105.08,110.44,115.79,121.15,126.51,131.86,137.22,142.57,147.93,153.28,158.64,163.99,169.35,174.71,180.06,185.42,190.77,196.13,201.48,206.84,212.2,217.55,222.91,228.26,233.62,238.97,244.33,249.69,255.04,260.4,265.75,271.11,276.46,281.82,287.17,292.53,297.89,303.24,308.6,313.95,319.31,324.66,330.02,335.38,340.73,346.09,351.44,356.8,362.15,367.51,372.87,378.22,383.58,388.93,394.29,399.64,405.0,410.35,415.71,421.07,426.42,431.78,437.13,442.49,447.84,453.2,458.56,463.91,469.27,474.62,479.98,485.33,490.69,496.05,501.4,506.76,512.11,517.47,522.82,528.18,533.53,538.89,544.25,549.6,554.96,560.31,565.67,571.02,576.38,581.74,587.09,592.45,597.8,603.16,608.51,613.87,619.22,624.58,629.94,635.29,640.65,-638.56,-633.2,-627.85,-622.49,-617.14,-611.78,-606.43,-601.07,-595.72,-590.36,-585.0,-579.65,-574.29,-568.94,-563.58,-558.23,-552.87,-547.51,-542.16,-536.8,-531.45,-526.09,-520.74,-515.38,-510.02,-504.67,-499.31,-493.96,-488.6,-483.25,-477.89,-472.54,-467.18,-461.82,-456.47,-451.11,-445.76,-440.4,-435.05,-429.69,-424.33,-418.98,-413.62,-408.27,-402.91,-397.56,-392.2,-386.84,-381.49,-376.13,-370.78,-365.42,-360.07,-354.71,-349.36,-344.0,-338.64,-333.29,-327.93,-322.58,-317.22,-311.87,-306.51,-301.15,-295.8,-290.44,-285.09,-279.73,-274.38,-269.02,-263.66,-258.31,-252.95,-247.6,-242.24,-236.89,-231.53,-226.18,-220.82,-215.46,-210.11,-204.75,-199.4,-194.04,-188.69,-183.33,-177.97,-172.62,-167.26,-161.91,-156.55,-151.2,-145.84,-140.49,-135.13,-129.77,-124.42,-119.06,-113.71,-108.35,-103.0,-97.64,-92.28,-86.93,-81.57,-76.22,-70.86,-65.51,-60.15,-54.79,-49.44,-44.08,-38.73,-33.37,-28.02,-22.66,-17.31,-11.95,-6.59,-1.24,4.12,9.47,14.83,20.18,25.54,30.9,36.25,41.61,46.96,52.32,57.67,63.03,68.39,73.74,79.1,84.45,89.81,95.16,100.52,105.87,111.23,116.59,121.94,127.3,132.65,138.01,143.36,148.72,154.08,159.43,164.79,170.14,175.5,180.85,186.21,191.57,196.92,202.28,207.63,212.99,218.34,223.7,229.05,234.41,239.77,245.12,250.48,255.83,261.19,266.54,271.9,277.26,282.61,287.97,293.32,298.68,304.03,309.39,314.75,320.1,325.46,330.81,336.17,341.52,346.88,352.23,357.59,362.95,368.3,373.66,379.01,384.37,389.72,395.08,400.44,405.79,411.15,416.5,421.86,427.21,432.57,437.92,443.28,448.64,453.99,459.35,464.7,470.06,475.41,480.77,486.13,491.48,496.84,502.19,507.55,512.9,518.26,523.62,528.97,534.33,539.68,545.04,550.39,555.75,561.1,566.46,571.82,577.17,582.53,587.88,593.24,598.59,603.95,609.31,614.66,620.02,625.37,630.73,636.08,641.44,-637.78,-632.42,-627.07,-621.71,-616.36,-611.0,-605.65,-600.29,-594.93,-589.58,-584.22,-578.87,-573.51,-568.16,-562.8,-557.44,-552.09,-546.73,-541.38,-536.02,-530.67,-525.31,-519.96,-514.6,-509.24,-503.89,-498.53,-493.18,-487.82,-482.47,-477.11,-471.75,-466.4,-461.04,-455.69,-450.33,-444.98,-439.62,-434.26,-428.91,-423.55,-418.2,-412.84,-407.49,-402.13,-396.78,-391.42,-386.06,-380.71,-375.35,-370.0,-364.64,-359.29,-353.93,-348.57,-343.22,-337.86,-332.51,-327.15,-321.8,-316.44,-311.09,-305.73,-300.37,-295.02,-289.66,-284.31,-278.95,-273.6,-268.24,-262.88,-257.53,-252.17,-246.82,-241.46,-236.11,-230.75,-225.39,-220.04,-214.68,-209.33,-203.97,-198.62,-193.26,-187.91,-182.55,-177.19,-171.84,-166.48,-161.13,-155.77,-150.42,-145.06,-139.7,-134.35,-128.99,-123.64,-118.28,-112.93,-107.57,-102.21,-96.86,-91.5,-86.15,-80.79,-75.44,-70.08,-64.73,-59.37,-54.01,-48.66,-43.3,-37.95,-32.59,-27.24,-21.88,-16.52,-11.17,-5.81,-0.46,4.9,10.25,15.61,20.97,26.32,31.68,37.03,42.39,47.74,53.1,58.45,63.81,69.17,74.52,79.88,85.23,90.59,95.94,101.3,106.66,112.01,117.37,122.72,128.08,133.43,138.79,144.15,149.5,154.86,160.21,165.57,170.92,176.28,181.63,186.99,192.35,197.7,203.06,208.41,213.77,219.12,224.48,229.84,235.19,240.55,245.9,251.26,256.61,261.97,267.32,272.68,278.04,283.39,288.75,294.1,299.46,304.81,310.17,315.53,320.88,326.24,331.59,336.95,342.3,347.66,353.02,358.37,363.73,369.08,374.44,379.79,385.15,390.5,395.86,401.22,406.57,411.93,417.28,422.64,427.99,433.35,438.71,444.06,449.42,454.77,460.13,465.48,470.84,476.2,481.55,486.91,492.26,497.62,502.97,508.33,513.68,519.04,524.4,529.75,535.11,540.46,545.82,551.17,556.53,561.89,567.24,572.6,577.95,583.31,588.66,594.02,599.38,604.73,610.09,615.44,620.8,626.15,631.51,636.86,642.22,-637.02,-631.66,-626.31,-620.95,-615.59,-610.24,-604.88,-599.53,-594.17,-588.82,-583.46,-578.1,-572.75,-567.39,-562.04,-556.68,-551.33,-545.97,-540.61,-535.26,-529.9,-524.55,-519.19,-513.84,-508.48,-503.13,-497.77,-492.41,-487.06,-481.7,-476.35,-470.99,-465.64,-460.28,-454.92,-449.57,-444.21,-438.86,-433.5,-428.15,-422.79,-417.43,-412.08,-406.72,-401.37,-396.01,-390.66,-385.3,-379.95,-374.59,-369.23,-363.88,-358.52,-353.17,-347.81,-342.46,-337.1,-331.74,-326.39,-321.03,-315.68,-310.32,-304.97,-299.61,-294.25,-288.9,-283.54,-278.19,-272.83,-267.48,-262.12,-256.77,-251.41,-246.05,-240.7,-235.34,-229.99,-224.63,-219.28,-213.92,-208.56,-203.21,-197.85,-192.5,-187.14,-181.79,-176.43,-171.07,-165.72,-160.36,-155.01,-149.65,-144.3,-138.94,-133.59,-128.23,-122.87,-117.52,-112.16,-106.81,-101.45,-96.1,-90.74,-85.38,-80.03,-74.67,-69.32,-63.96,-58.61,-53.25,-47.89,-42.54,-37.18,-31.83,-26.47,-21.12,-15.76,-10.41,-5.05,0.31,5.66,11.02,16.37,21.73,27.08,32.44,37.8,43.15,48.51,53.86,59.22,64.57,69.93,75.28,80.64,86.0,91.35,96.71,102.06,107.42,112.77,118.13,123.49,128.84,134.2,139.55,144.91,150.26,155.62,160.98,166.33,171.69,177.04,182.4,187.75,193.11,198.46,203.82,209.18,214.53,219.89,225.24,230.6,235.95,241.31,246.67,252.02,257.38,262.73,268.09,273.44,278.8,284.16,289.51,294.87,300.22,305.58,310.93,316.29,321.64,327.0,332.36,337.71,343.07,348.42,353.78,359.13,364.49,369.85,375.2,380.56,385.91,391.27,396.62,401.98,407.34,412.69,418.05,423.4,428.76,434.11,439.47,444.82,450.18,455.54,460.89,466.25,471.6,476.96,482.31,487.67,493.03,498.38,503.74,509.09,514.45,519.8,525.16,530.52,535.87,541.23,546.58,551.94,557.29,562.65,568.0,573.36,578.72,584.07,589.43,594.78,600.14,605.49,610.85,616.21,621.56,626.92,632.27,637.63,642.98,-636.28,-630.92,-625.57,-620.21,-614.85,-609.5,-604.14,-598.79,-593.43,-588.08,-582.72,-577.36,-572.01,-566.65,-561.3,-555.94,-550.59,-545.23,-539.87,-534.52,-529.16,-523.81,-518.45,-513.1,-507.74,-502.39,-497.03,-491.67,-486.32,-480.96,-475.61,-470.25,-464.9,-459.54,-454.18,-448.83,-443.47,-438.12,-432.76,-427.41,-422.05,-416.69,-411.34,-405.98,-400.63,-395.27,-389.92,-384.56,-379.21,-373.85,-368.49,-363.14,-357.78,-352.43,-347.07,-341.72,-336.36,-331.0,-325.65,-320.29,-314.94,-309.58,-304.23,-298.87,-293.51,-288.16,-282.8,-277.45,-272.09,-266.74,-261.38,-256.03,-250.67,-245.31,-239.96,-234.6,-229.25,-223.89,-218.54,-213.18,-207.82,-202.47,-197.11,-191.76,-186.4,-181.05,-175.69,-170.34,-164.98,-159.62,-154.27,-148.91,-143.56,-138.2,-132.85,-127.49,-122.13,-116.78,-111.42,-106.07,-100.71,-95.36,-90.0,-84.64,-79.29,-73.93,-68.58,-63.22,-57.87,-52.51,-47.16,-41.8,-36.44,-31.09,-25.73,-20.38,-15.02,-9.67,-4.31,1.05,6.4,11.76,17.11,22.47,27.82,33.18,38.54,43.89,49.25,54.6,59.96,65.31,70.67,76.02,81.38,86.74,92.09,97.45,102.8,108.16,113.51,118.87,124.23,129.58,134.94,140.29,145.65,151.0,156.36,161.72,167.07,172.43,177.78,183.14,188.49,193.85,199.2,204.56,209.92,215.27,220.63,225.98,231.34,236.69,242.05,247.41,252.76,258.12,263.47,268.83,274.18,279.54,284.9,290.25,295.61,300.96,306.32,311.67,317.03,322.38,327.74,333.1,338.45,343.81,349.16,354.52,359.87,365.23,370.59,375.94,381.3,386.65,392.01,397.36,402.72,408.08,413.43,418.79,424.14,429.5,434.85,440.21,445.56,450.92,456.28,461.63,466.99,472.34,477.7,483.05,488.41,493.77,499.12,504.48,509.83,515.19,520.54,525.9,531.25,536.61,541.97,547.32,552.68,558.03,563.39,568.74,574.1,579.46,584.81,590.17,595.52,600.88,606.23,611.59,616.95,622.3,627.66,633.01,638.37,643.72,-635.57,-630.21,-624.85,-619.5,-614.14,-608.79,-603.43,-598.08,-592.72,-587.36,-582.01,-576.65,-571.3,-565.94,-560.59,-555.23,-549.88,-544.52,-539.16,-533.81,-528.45,-523.1,-517.74,-512.39,-507.03,-501.67,-496.32,-490.96,-485.61,-480.25,-474.9,-469.54,-464.19,-458.83,-453.47,-448.12,-442.76,-437.41,-432.05,-426.7,-421.34,-415.98,-410.63,-405.27,-399.92,-394.56,-389.21,-383.85,-378.49,-373.14,-367.78,-362.43,-357.07,-351.72,-346.36,-341.01,-335.65,-330.29,-324.94,-319.58,-314.23,-308.87,-303.52,-298.16,-292.8,-287.45,-282.09,-276.74,-271.38,-266.03,-260.67,-255.31,-249.96,-244.6,-239.25,-233.89,-228.54,-223.18,-217.83,-212.47,-207.11,-201.76,-196.4,-191.05,-185.69,-180.34,-174.98,-169.62,-164.27,-158.91,-153.56,-148.2,-142.85,-137.49,-132.13,-126.78,-121.42,-116.07,-110.71,-105.36,-100.0,-94.65,-89.29,-83.93,-78.58,-73.22,-67.87,-62.51,-57.16,-51.8,-46.44,-41.09,-35.73,-30.38,-25.02,-19.67,-14.31,-8.95,-3.6,1.76,7.11,12.47,17.82,23.18,28.53,33.89,39.25,44.6,49.96,55.31,60.67,66.02,71.38,76.74,82.09,87.45,92.8,98.16,103.51,108.87,114.23,119.58,124.94,130.29,135.65,141.0,146.36,151.71,157.07,162.43,167.78,173.14,178.49,183.85,189.2,194.56,199.92,205.27,210.63,215.98,221.34,226.69,232.05,237.4,242.76,248.12,253.47,258.83,264.18,269.54,274.89,280.25,285.61,290.96,296.32,301.67,307.03,312.38,317.74,323.1,328.45,333.81,339.16,344.52,349.87,355.23,360.58,365.94,371.3,376.65,382.01,387.36,392.72,398.07,403.43,408.79,414.14,419.5,424.85,430.21,435.56,440.92,446.28,451.63,456.99,462.34,467.7,473.05,478.41,483.76,489.12,494.48,499.83,505.19,510.54,515.9,521.25,526.61,531.97,537.32,542.68,548.03,553.39,558.74,564.1,569.46,574.81,580.17,585.52,590.88,596.23,601.59,606.94,612.3,617.66,623.01,628.37,633.72,639.08,644.43,-634.89,-629.53,-624.18,-618.82,-613.47,-608.11,-602.76,-597.4,-592.04,-586.69,-581.33,-575.98,-570.62,-565.27,-559.91,-554.56,-549.2,-543.84,-538.49,-533.13,-527.78,-522.42,-517.07,-511.71,-506.35,-501.0,-495.64,-490.29,-484.93,-479.58,-474.22,-468.86,-463.51,-458.15,-452.8,-447.44,-442.09,-436.73,-431.38,-426.02,-420.66,-415.31,-409.95,-404.6,-399.24,-393.89,-388.53,-383.17,-377.82,-372.46,-367.11,-361.75,-356.4,-351.04,-345.68,-340.33,-334.97,-329.62,-324.26,-318.91,-313.55,-308.2,-302.84,-297.48,-292.13,-286.77,-281.42,-276.06,-270.71,-265.35,-259.99,-254.64,-249.28,-243.93,-238.57,-233.22,-227.86,-222.5,-217.15,-211.79,-206.44,-201.08,-195.73,-190.37,-185.02,-179.66,-174.3,-168.95,-163.59,-158.24,-152.88,-147.53,-142.17,-136.81,-131.46,-126.1,-120.75,-115.39,-110.04,-104.68,-99.33,-93.97,-88.61,-83.26,-77.9,-72.55,-67.19,-61.84,-56.48,-51.12,-45.77,-40.41,-35.06,-29.7,-24.35,-18.99,-13.63,-8.28,-2.92,2.43,7.79,13.14,18.5,23.85,29.21,34.57,39.92,45.28,50.63,55.99,61.34,66.7,72.06,77.41,82.77,88.12,93.48,98.83,104.19,109.55,114.9,120.26,125.61,130.97,136.32,141.68,147.03,152.39,157.75,163.1,168.46,173.81,179.17,184.52,189.88,195.24,200.59,205.95,211.3,216.66,222.01,227.37,232.73,238.08,243.44,248.79,254.15,259.5,264.86,270.21,275.57,280.93,286.28,291.64,296.99,302.35,307.7,313.06,318.42,323.77,329.13,334.48,339.84,345.19,350.55,355.91,361.26,366.62,371.97,377.33,382.68,388.04,393.39,398.75,404.11,409.46,414.82,420.17,425.53,430.88,436.24,441.6,446.95,452.31,457.66,463.02,468.37,473.73,479.08,484.44,489.8,495.15,500.51,505.86,511.22,516.57,521.93,527.29,532.64,538.0,543.35,548.71,554.06,559.42,564.78,570.13,575.49,580.84,586.2,591.55,596.91,602.26,607.62,612.98,618.33,623.69,629.04,634.4,639.75,645.11,-634.25,-628.9,-623.54,-618.19,-612.83,-607.48,-602.12,-596.76,-591.41,-586.05,-580.7,-575.34,-569.99,-564.63,-559.28,-553.92,-548.56,-543.21,-537.85,-532.5,-527.14,-521.79,-516.43,-511.07,-505.72,-500.36,-495.01,-489.65,-484.3,-478.94,-473.58,-468.23,-462.87,-457.52,-452.16,-446.81,-441.45,-436.1,-430.74,-425.38,-420.03,-414.67,-409.32,-403.96,-398.61,-393.25,-387.89,-382.54,-377.18,-371.83,-366.47,-361.12,-355.76,-350.4,-345.05,-339.69,-334.34,-328.98,-323.63,-318.27,-312.92,-307.56,-302.2,-296.85,-291.49,-286.14,-280.78,-275.43,-270.07,-264.71,-259.36,-254.0,-248.65,-243.29,-237.94,-232.58,-227.22,-221.87,-216.51,-211.16,-205.8,-200.45,-195.09,-189.74,-184.38,-179.02,-173.67,-168.31,-162.96,-157.6,-152.25,-146.89,-141.53,-136.18,-130.82,-125.47,-120.11,-114.76,-109.4,-104.04,-98.69,-93.33,-87.98,-82.62,-77.27,-71.91,-66.56,-61.2,-55.84,-50.49,-45.13,-39.78,-34.42,-29.07,-23.71,-18.35,-13.0,-7.64,-2.29,3.07,8.42,13.78,19.13,24.49,29.85,35.2,40.56,45.91,51.27,56.62,61.98,67.34,72.69,78.05,83.4,88.76,94.11,99.47,104.83,110.18,115.54,120.89,126.25,131.6,136.96,142.31,147.67,153.03,158.38,163.74,169.09,174.45,179.8,185.16,190.52,195.87,201.23,206.58,211.94,217.29,222.65,228.01,233.36,238.72,244.07,249.43,254.78,260.14,265.49,270.85,276.21,281.56,286.92,292.27,297.63,302.98,308.34,313.7,319.05,324.41,329.76,335.12,340.47,345.83,351.19,356.54,361.9,367.25,372.61,377.96,383.32,388.67,394.03,399.39,404.74,410.1,415.45,420.81,426.16,431.52,436.88,442.23,447.59,452.94,458.3,463.65,469.01,474.37,479.72,485.08,490.43,495.79,501.14,506.5,511.85,517.21,522.57,527.92,533.28,538.63,543.99,549.34,554.7,560.06,565.41,570.77,576.12,581.48,586.83,592.19,597.54,602.9,608.26,613.61,618.97,624.32,629.68,635.03,640.39,645.75,-633.66,-628.31,-622.95,-617.6,-612.24,-606.89,-601.53,-596.17,-590.82,-585.46,-580.11,-574.75,-569.4,-564.04,-558.68,-553.33,-547.97,-542.62,-537.26,-531.91,-526.55,-521.19,-515.84,-510.48,-505.13,-499.77,-494.42,-489.06,-483.71,-478.35,-472.99,-467.64,-462.28,-456.93,-451.57,-446.22,-440.86,-435.5,-430.15,-424.79,-419.44,-414.08,-408.73,-403.37,-398.02,-392.66,-387.3,-381.95,-376.59,-371.24,-365.88,-360.53,-355.17,-349.81,-344.46,-339.1,-333.75,-328.39,-323.04,-317.68,-312.32,-306.97,-301.61,-296.26,-290.9,-285.55,-280.19,-274.84,-269.48,-264.12,-258.77,-253.41,-248.06,-242.7,-237.35,-231.99,-226.63,-221.28,-215.92,-210.57,-205.21,-199.86,-194.5,-189.14,-183.79,-178.43,-173.08,-167.72,-162.37,-157.01,-151.66,-146.3,-140.94,-135.59,-130.23,-124.88,-119.52,-114.17,-108.81,-103.45,-98.1,-92.74,-87.39,-82.03,-76.68,-71.32,-65.96,-60.61,-55.25,-49.9,-44.54,-39.19,-33.83,-28.48,-23.12,-17.76,-12.41,-7.05,-1.7,3.66,9.01,14.37,19.73,25.08,30.44,35.79,41.15,46.5,51.86,57.22,62.57,67.93,73.28,78.64,83.99,89.35,94.7,100.06,105.42,110.77,116.13,121.48,126.84,132.19,137.55,142.91,148.26,153.62,158.97,164.33,169.68,175.04,180.39,185.75,191.11,196.46,201.82,207.17,212.53,217.88,223.24,228.6,233.95,239.31,244.66,250.02,255.37,260.73,266.09,271.44,276.8,282.15,287.51,292.86,298.22,303.57,308.93,314.29,319.64,325.0,330.35,335.71,341.06,346.42,351.78,357.13,362.49,367.84,373.2,378.55,383.91,389.27,394.62,399.98,405.33,410.69,416.04,421.4,426.75,432.11,437.47,442.82,448.18,453.53,458.89,464.24,469.6,474.96,480.31,485.67,491.02,496.38,501.73,507.09,512.45,517.8,523.16,528.51,533.87,539.22,544.58,549.93,555.29,560.65,566.0,571.36,576.71,582.07,587.42,592.78,598.14,603.49,608.85,614.2,619.56,624.91,630.27,635.63,640.98,646.34,-633.12,-627.77,-622.41,-617.06,-611.7,-606.34,-600.99,-595.63,-590.28,-584.92,-579.57,-574.21,-568.85,-563.5,-558.14,-552.79,-547.43,-542.08,-536.72,-531.37,-526.01,-520.65,-515.3,-509.94,-504.59,-499.23,-493.88,-488.52,-483.16,-477.81,-472.45,-467.1,-461.74,-456.39,-451.03,-445.68,-440.32,-434.96,-429.61,-424.25,-418.9,-413.54,-408.19,-402.83,-397.47,-392.12,-386.76,-381.41,-376.05,-370.7,-365.34,-359.98,-354.63,-349.27,-343.92,-338.56,-333.21,-327.85,-322.5,-317.14,-311.78,-306.43,-301.07,-295.72,-290.36,-285.01,-279.65,-274.29,-268.94,-263.58,-258.23,-252.87,-247.52,-242.16,-236.8,-231.45,-226.09,-220.74,-215.38,-210.03,-204.67,-199.32,-193.96,-188.6,-183.25,-177.89,-172.54,-167.18,-161.83,-156.47,-151.11,-145.76,-140.4,-135.05,-129.69,-124.34,-118.98,-113.62,-108.27,-102.91,-97.56,-92.2,-86.85,-81.49,-76.14,-70.78,-65.42,-60.07,-54.71,-49.36,-44.0,-38.65,-33.29,-27.93,-22.58,-17.22,-11.87,-6.51,-1.16,4.2,9.56,14.91,20.27,25.62,30.98,36.33,41.69,47.04,52.4,57.76,63.11,68.47,73.82,79.18,84.53,89.89,95.25,100.6,105.96,111.31,116.67,122.02,127.38,132.74,138.09,143.45,148.8,154.16,159.51,164.87,170.22,175.58,180.94,186.29,191.65,197.0,202.36,207.71,213.07,218.43,223.78,229.14,234.49,239.85,245.2,250.56,255.91,261.27,266.63,271.98,277.34,282.69,288.05,293.4,298.76,304.12,309.47,314.83,320.18,325.54,330.89,336.25,341.61,346.96,352.32,357.67,363.03,368.38,373.74,379.09,384.45,389.81,395.16,400.52,405.87,411.23,416.58,421.94,427.3,432.65,438.01,443.36,448.72,454.07,459.43,464.79,470.14,475.5,480.85,486.21,491.56,496.92,502.27,507.63,512.99,518.34,523.7,529.05,534.41,539.76,545.12,550.48,555.83,561.19,566.54,571.9,577.25,582.61,587.97,593.32,598.68,604.03,609.39,614.74,620.1,625.45,630.81,636.17,641.52,646.88,-632.64,-627.28,-621.92,-616.57,-611.21,-605.86,-600.5,-595.15,-589.79,-584.43,-579.08,-573.72,-568.37,-563.01,-557.66,-552.3,-546.95,-541.59,-536.23,-530.88,-525.52,-520.17,-514.81,-509.46,-504.1,-498.74,-493.39,-488.03,-482.68,-477.32,-471.97,-466.61,-461.26,-455.9,-450.54,-445.19,-439.83,-434.48,-429.12,-423.77,-418.41,-413.05,-407.7,-402.34,-396.99,-391.63,-386.28,-380.92,-375.56,-370.21,-364.85,-359.5,-354.14,-348.79,-343.43,-338.08,-332.72,-327.36,-322.01,-316.65,-311.3,-305.94,-300.59,-295.23,-289.87,-284.52,-279.16,-273.81,-268.45,-263.1,-257.74,-252.38,-247.03,-241.67,-236.32,-230.96,-225.61,-220.25,-214.9,-209.54,-204.18,-198.83,-193.47,-188.12,-182.76,-177.41,-172.05,-166.69,-161.34,-155.98,-150.63,-145.27,-139.92,-134.56,-129.2,-123.85,-118.49,-113.14,-107.78,-102.43,-97.07,-91.72,-86.36,-81.0,-75.65,-70.29,-64.94,-59.58,-54.23,-48.87,-43.51,-38.16,-32.8,-27.45,-22.09,-16.74,-11.38,-6.02,-0.67,4.69,10.04,15.4,20.75,26.11,31.46,36.82,42.18,47.53,52.89,58.24,63.6,68.95,74.31,79.67,85.02,90.38,95.73,101.09,106.44,111.8,117.15,122.51,127.87,133.22,138.58,143.93,149.29,154.64,160.0,165.36,170.71,176.07,181.42,186.78,192.13,197.49,202.85,208.2,213.56,218.91,224.27,229.62,234.98,240.33,245.69,251.05,256.4,261.76,267.11,272.47,277.82,283.18,288.54,293.89,299.25,304.6,309.96,315.31,320.67,326.03,331.38,336.74,342.09,347.45,352.8,358.16,363.51,368.87,374.23,379.58,384.94,390.29,395.65,401.0,406.36,411.72,417.07,422.43,427.78,433.14,438.49,443.85,449.21,454.56,459.92,465.27,470.63,475.98,481.34,486.69,492.05,497.41,502.76,508.12,513.47,518.83,524.18,529.54,534.9,540.25,545.61,550.96,556.32,561.67,567.03,572.39,577.74,583.1,588.45,593.81,599.16,604.52,609.87,615.23,620.59,625.94,631.3,636.65,642.01,647.36,-632.21,-626.85,-621.5,-616.14,-610.78,-605.43,-600.07,-594.72,-589.36,-584.01,-578.65,-573.29,-567.94,-562.58,-557.23,-551.87,-546.52,-541.16,-535.81,-530.45,-525.09,-519.74,-514.38,-509.03,-503.67,-498.32,-492.96,-487.6,-482.25,-476.89,-471.54,-466.18,-460.83,-455.47,-450.11,-444.76,-439.4,-434.05,-428.69,-423.34,-417.98,-412.63,-407.27,-401.91,-396.56,-391.2,-385.85,-380.49,-375.14,-369.78,-364.42,-359.07,-353.71,-348.36,-343.0,-337.65,-332.29,-326.93,-321.58,-316.22,-310.87,-305.51,-300.16,-294.8,-289.45,-284.09,-278.73,-273.38,-268.02,-262.67,-257.31,-251.96,-246.6,-241.24,-235.89,-230.53,-225.18,-219.82,-214.47,-209.11,-203.75,-198.4,-193.04,-187.69,-182.33,-176.98,-171.62,-166.27,-160.91,-155.55,-150.2,-144.84,-139.49,-134.13,-128.78,-123.42,-118.06,-112.71,-107.35,-102.0,-96.64,-91.29,-85.93,-80.57,-75.22,-69.86,-64.51,-59.15,-53.8,-48.44,-43.09,-37.73,-32.37,-27.02,-21.66,-16.31,-10.95,-5.6,-0.24,5.12,10.47,15.83,21.18,26.54,31.89,37.25,42.6,47.96,53.32,58.67,64.03,69.38,74.74,80.09,85.45,90.81,96.16,101.52,106.87,112.23,117.58,122.94,128.3,133.65,139.01,144.36,149.72,155.07,160.43,165.78,171.14,176.5,181.85,187.21,192.56,197.92,203.27,208.63,213.99,219.34,224.7,230.05,235.41,240.76,246.12,251.48,256.83,262.19,267.54,272.9,278.25,283.61,288.96,294.32,299.68,305.03,310.39,315.74,321.1,326.45,331.81,337.17,342.52,347.88,353.23,358.59,363.94,369.3,374.66,380.01,385.37,390.72,396.08,401.43,406.79,412.14,417.5,422.86,428.21,433.57,438.92,444.28,449.63,454.99,460.35,465.7,471.06,476.41,481.77,487.12,492.48,497.84,503.19,508.55,513.9,519.26,524.61,529.97,535.32,540.68,546.04,551.39,556.75,562.1,567.46,572.81,578.17,583.53,588.88,594.24,599.59,604.95,610.3,615.66,621.01,626.37,631.73,637.08,642.44,647.79,-631.84,-626.48,-621.13,-615.77,-610.42,-605.06,-599.7,-594.35,-588.99,-583.64,-578.28,-572.93,-567.57,-562.22,-556.86,-551.5,-546.15,-540.79,-535.44,-530.08,-524.73,-519.37,-514.01,-508.66,-503.3,-497.95,-492.59,-487.24,-481.88,-476.53,-471.17,-465.81,-460.46,-455.1,-449.75,-444.39,-439.04,-433.68,-428.32,-422.97,-417.61,-412.26,-406.9,-401.55,-396.19,-390.83,-385.48,-380.12,-374.77,-369.41,-364.06,-358.7,-353.35,-347.99,-342.63,-337.28,-331.92,-326.57,-321.21,-315.86,-310.5,-305.14,-299.79,-294.43,-289.08,-283.72,-278.37,-273.01,-267.65,-262.3,-256.94,-251.59,-246.23,-240.88,-235.52,-230.17,-224.81,-219.45,-214.1,-208.74,-203.39,-198.03,-192.68,-187.32,-181.96,-176.61,-171.25,-165.9,-160.54,-155.19,-149.83,-144.47,-139.12,-133.76,-128.41,-123.05,-117.7,-112.34,-106.99,-101.63,-96.27,-90.92,-85.56,-80.21,-74.85,-69.5,-64.14,-58.78,-53.43,-48.07,-42.72,-37.36,-32.01,-26.65,-21.29,-15.94,-10.58,-5.23,0.13,5.48,10.84,16.19,21.55,26.91,32.26,37.62,42.97,48.33,53.68,59.04,64.4,69.75,75.11,80.46,85.82,91.17,96.53,101.88,107.24,112.6,117.95,123.31,128.66,134.02,139.37,144.73,150.09,155.44,160.8,166.15,171.51,176.86,182.22,187.58,192.93,198.29,203.64,209.0,214.35,219.71,225.06,230.42,235.78,241.13,246.49,251.84,257.2,262.55,267.91,273.27,278.62,283.98,289.33,294.69,300.04,305.4,310.76,316.11,321.47,326.82,332.18,337.53,342.89,348.24,353.6,358.96,364.31,369.67,375.02,380.38,385.73,391.09,396.45,401.8,407.16,412.51,417.87,423.22,428.58,433.94,439.29,444.65,450.0,455.36,460.71,466.07,471.42,476.78,482.14,487.49,492.85,498.2,503.56,508.91,514.27,519.63,524.98,530.34,535.69,541.05,546.4,551.76,557.12,562.47,567.83,573.18,578.54,583.89,589.25,594.6,599.96,605.32,610.67,616.03,621.38,626.74,632.09,637.45,642.81,648.16,-631.54,-626.18,-620.82,-615.47,-610.11,-604.76,-599.4,-594.05,-588.69,-583.33,-577.98,-572.62,-567.27,-561.91,-556.56,-551.2,-545.84,-540.49,-535.13,-529.78,-524.42,-519.07,-513.71,-508.36,-503.0,-497.64,-492.29,-486.93,-481.58,-476.22,-470.87,-465.51,-460.15,-454.8,-449.44,-444.09,-438.73,-433.38,-428.02,-422.66,-417.31,-411.95,-406.6,-401.24,-395.89,-390.53,-385.18,-379.82,-374.46,-369.11,-363.75,-358.4,-353.04,-347.69,-342.33,-336.97,-331.62,-326.26,-320.91,-315.55,-310.2,-304.84,-299.48,-294.13,-288.77,-283.42,-278.06,-272.71,-267.35,-262.0,-256.64,-251.28,-245.93,-240.57,-235.22,-229.86,-224.51,-219.15,-213.79,-208.44,-203.08,-197.73,-192.37,-187.02,-181.66,-176.3,-170.95,-165.59,-160.24,-154.88,-149.53,-144.17,-138.82,-133.46,-128.1,-122.75,-117.39,-112.04,-106.68,-101.33,-95.97,-90.61,-85.26,-79.9,-74.55,-69.19,-63.84,-58.48,-53.13,-47.77,-42.41,-37.06,-31.7,-26.35,-20.99,-15.64,-10.28,-4.92,0.43,5.79,11.14,16.5,21.85,27.21,32.57,37.92,43.28,48.63,53.99,59.34,64.7,70.05,75.41,80.77,86.12,91.48,96.83,102.19,107.54,112.9,118.26,123.61,128.97,134.32,139.68,145.03,150.39,155.75,161.1,166.46,171.81,177.17,182.52,187.88,193.23,198.59,203.95,209.3,214.66,220.01,225.37,230.72,236.08,241.44,246.79,252.15,257.5,262.86,268.21,273.57,278.93,284.28,289.64,294.99,300.35,305.7,311.06,316.41,321.77,327.13,332.48,337.84,343.19,348.55,353.9,359.26,364.62,369.97,375.33,380.68,386.04,391.39,396.75,402.11,407.46,412.82,418.17,423.53,428.88,434.24,439.59,444.95,450.31,455.66,461.02,466.37,471.73,477.08,482.44,487.8,493.15,498.51,503.86,509.22,514.57,519.93,525.29,530.64,536.0,541.35,546.71,552.06,557.42,562.77,568.13,573.49,578.84,584.2,589.55,594.91,600.26,605.62,610.98,616.33,621.69,627.04,632.4,637.75,643.11,648.46,-631.3,-625.94,-620.59,-615.23,-609.88,-604.52,-599.16,-593.81,-588.45,-583.1,-577.74,-572.39,-567.03,-561.67,-556.32,-550.96,-545.61,-540.25,-534.9,-529.54,-524.18,-518.83,-513.47,-508.12,-502.76,-497.41,-492.05,-486.7,-481.34,-475.98,-470.63,-465.27,-459.92,-454.56,-449.21,-443.85,-438.49,-433.14,-427.78,-422.43,-417.07,-411.72,-406.36,-401.0,-395.65,-390.29,-384.94,-379.58,-374.23,-368.87,-363.52,-358.16,-352.8,-347.45,-342.09,-336.74,-331.38,-326.03,-320.67,-315.31,-309.96,-304.6,-299.25,-293.89,-288.54,-283.18,-277.82,-272.47,-267.11,-261.76,-256.4,-251.05,-245.69,-240.34,-234.98,-229.62,-224.27,-218.91,-213.56,-208.2,-202.85,-197.49,-192.13,-186.78,-181.42,-176.07,-170.71,-165.36,-160.0,-154.64,-149.29,-143.93,-138.58,-133.22,-127.87,-122.51,-117.16,-111.8,-106.44,-101.09,-95.73,-90.38,-85.02,-79.67,-74.31,-68.95,-63.6,-58.24,-52.89,-47.53,-42.18,-36.82,-31.47,-26.11,-20.75,-15.4,-10.04,-4.69,0.67,6.02,11.38,16.74,22.09,27.45,32.8,38.16,43.51,48.87,54.23,59.58,64.94,70.29,75.65,81.0,86.36,91.71,97.07,102.43,107.78,113.14,118.49,123.85,129.2,134.56,139.92,145.27,150.63,155.98,161.34,166.69,172.05,177.41,182.76,188.12,193.47,198.83,204.18,209.54,214.89,220.25,225.61,230.96,236.32,241.67,247.03,252.38,257.74,263.1,268.45,273.81,279.16,284.52,289.87,295.23,300.59,305.94,311.3,316.65,322.01,327.36,332.72,338.07,343.43,348.79,354.14,359.5,364.85,370.21,375.56,380.92,386.28,391.63,396.99,402.34,407.7,413.05,418.41,423.77,429.12,434.48,439.83,445.19,450.54,455.9,461.25,466.61,471.97,477.32,482.68,488.03,493.39,498.74,504.1,509.46,514.81,520.17,525.52,530.88,536.23,541.59,546.94,552.3,557.66,563.01,568.37,573.72,579.08,584.43,589.79,595.15,600.5,605.86,611.21,616.57,621.92,627.28,632.64,637.99,643.35,648.7,-631.13,-625.77,-620.42,-615.06,-609.71,-604.35,-598.99,-593.64,-588.28,-582.93,-577.57,-572.22,-566.86,-561.51,-556.15,-550.79,-545.44,-540.08,-534.73,-529.37,-524.02,-518.66,-513.3,-507.95,-502.59,-497.24,-491.88,-486.53,-481.17,-475.81,-470.46,-465.1,-459.75,-454.39,-449.04,-443.68,-438.33,-432.97,-427.61,-422.26,-416.9,-411.55,-406.19,-400.84,-395.48,-390.12,-384.77,-379.41,-374.06,-368.7,-363.35,-357.99,-352.63,-347.28,-341.92,-336.57,-331.21,-325.86,-320.5,-315.15,-309.79,-304.43,-299.08,-293.72,-288.37,-283.01,-277.66,-272.3,-266.94,-261.59,-256.23,-250.88,-245.52,-240.17,-234.81,-229.46,-224.1,-218.74,-213.39,-208.03,-202.68,-197.32,-191.97,-186.61,-181.25,-175.9,-170.54,-165.19,-159.83,-154.48,-149.12,-143.76,-138.41,-133.05,-127.7,-122.34,-116.99,-111.63,-106.28,-100.92,-95.56,-90.21,-84.85,-79.5,-74.14,-68.79,-63.43,-58.07,-52.72,-47.36,-42.01,-36.65,-31.3,-25.94,-20.58,-15.23,-9.87,-4.52,0.84,6.19,11.55,16.9,22.26,27.62,32.97,38.33,43.68,49.04,54.39,59.75,65.11,70.46,75.82,81.17,86.53,91.88,97.24,102.6,107.95,113.31,118.66,124.02,129.37,134.73,140.08,145.44,150.8,156.15,161.51,166.86,172.22,177.57,182.93,188.29,193.64,199.0,204.35,209.71,215.06,220.42,225.78,231.13,236.49,241.84,247.2,252.55,257.91,263.26,268.62,273.98,279.33,284.69,290.04,295.4,300.75,306.11,311.47,316.82,322.18,327.53,332.89,338.24,343.6,348.96,354.31,359.67,365.02,370.38,375.73,381.09,386.44,391.8,397.16,402.51,407.87,413.22,418.58,423.93,429.29,434.65,440.0,445.36,450.71,456.07,461.42,466.78,472.13,477.49,482.85,488.2,493.56,498.91,504.27,509.62,514.98,520.34,525.69,531.05,536.4,541.76,547.11,552.47,557.83,563.18,568.54,573.89,579.25,584.6,589.96,595.31,600.67,606.03,611.38,616.74,622.09,627.45,632.8,638.16,643.52,648.87,-631.03,-625.67,-620.32,-614.96,-609.61,-604.25,-598.9,-593.54,-588.18,-582.83,-577.47,-572.12,-566.76,-561.41,-556.05,-550.69,-545.34,-539.98,-534.63,-529.27,-523.92,-518.56,-513.2,-507.85,-502.49,-497.14,-491.78,-486.43,-481.07,-475.72,-470.36,-465.0,-459.65,-454.29,-448.94,-443.58,-438.23,-432.87,-427.51,-422.16,-416.8,-411.45,-406.09,-400.74,-395.38,-390.03,-384.67,-379.31,-373.96,-368.6,-363.25,-357.89,-352.54,-347.18,-341.82,-336.47,-331.11,-325.76,-320.4,-315.05,-309.69,-304.33,-298.98,-293.62,-288.27,-282.91,-277.56,-272.2,-266.85,-261.49,-256.13,-250.78,-245.42,-240.07,-234.71,-229.36,-224.0,-218.64,-213.29,-207.93,-202.58,-197.22,-191.87,-186.51,-181.15,-175.8,-170.44,-165.09,-159.73,-154.38,-149.02,-143.67,-138.31,-132.95,-127.6,-122.24,-116.89,-111.53,-106.18,-100.82,-95.46,-90.11,-84.75,-79.4,-74.04,-68.69,-63.33,-57.97,-52.62,-47.26,-41.91,-36.55,-31.2,-25.84,-20.49,-15.13,-9.77,-4.42,0.94,6.29,11.65,17.0,22.36,27.72,33.07,38.43,43.78,49.14,54.49,59.85,65.21,70.56,75.92,81.27,86.63,91.98,97.34,102.69,108.05,113.41,118.76,124.12,129.47,134.83,140.18,145.54,150.9,156.25,161.61,166.96,172.32,177.67,183.03,188.38,193.74,199.1,204.45,209.81,215.16,220.52,225.87,231.23,236.59,241.94,247.3,252.65,258.01,263.36,268.72,274.08,279.43,284.79,290.14,295.5,300.85,306.21,311.56,316.92,322.28,327.63,332.99,338.34,343.7,349.05,354.41,359.77,365.12,370.48,375.83,381.19,386.54,391.9,397.26,402.61,407.97,413.32,418.68,424.03,429.39,434.74,440.1,445.46,450.81,456.17,461.52,466.88,472.23,477.59,482.95,488.3,493.66,499.01,504.37,509.72,515.08,520.44,525.79,531.15,536.5,541.86,547.21,552.57,557.92,563.28,568.64,573.99,579.35,584.7,590.06,595.41,600.77,606.13,611.48,616.84,622.19,627.55,632.9,638.26,643.62,648.97,-631.0,-625.64,-620.29,-614.93,-609.58,-604.22,-598.87,-593.51,-588.16,-582.8,-577.44,-572.09,-566.73,-561.38,-556.02,-550.67,-545.31,-539.95,-534.6,-529.24,-523.89,-518.53,-513.18,-507.82,-502.46,-497.11,-491.75,-486.4,-481.04,-475.69,-470.33,-464.98,-459.62,-454.26,-448.91,-443.55,-438.2,-432.84,-427.49,-422.13,-416.77,-411.42,-406.06,-400.71,-395.35,-390.0,-384.64,-379.28,-373.93,-368.57,-363.22,-357.86,-352.51,-347.15,-341.8,-336.44,-331.08,-325.73,-320.37,-315.02,-309.66,-304.31,-298.95,-293.59,-288.24,-282.88,-277.53,-272.17,-266.82,-261.46,-256.1,-250.75,-245.39,-240.04,-234.68,-229.33,-223.97,-218.62,-213.26,-207.9,-202.55,-197.19,-191.84,-186.48,-181.13,-175.77,-170.41,-165.06,-159.7,-154.35,-148.99,-143.64,-138.28,-132.92,-127.57,-122.21,-116.86,-111.5,-106.15,-100.79,-95.44,-90.08,-84.72,-79.37,-74.01,-68.66,-63.3,-57.95,-52.59,-47.23,-41.88,-36.52,-31.17,-25.81,-20.46,-15.1,-9.75,-4.39,0.97,6.32,11.68,17.03,22.39,27.74,33.1,38.46,43.81,49.17,54.52,59.88,65.23,70.59,75.95,81.3,86.66,92.01,97.37,102.72,108.08,113.43,118.79,124.15,129.5,134.86,140.21,145.57,150.92,156.28,161.64,166.99,172.35,177.7,183.06,188.41,193.77,199.13,204.48,209.84,215.19,220.55,225.9,231.26,236.61,241.97,247.33,252.68,258.04,263.39,268.75,274.1,279.46,284.82,290.17,295.53,300.88,306.24,311.59,316.95,322.31,327.66,333.02,338.37,343.73,349.08,354.44,359.79,365.15,370.51,375.86,381.22,386.57,391.93,397.28,402.64,408.0,413.35,418.71,424.06,429.42,434.77,440.13,445.49,450.84,456.2,461.55,466.91,472.26,477.62,482.97,488.33,493.69,499.04,504.4,509.75,515.11,520.46,525.82,531.18,536.53,541.89,547.24,552.6,557.95,563.31,568.66,574.02,579.38,584.73,590.09,595.44,600.8,606.15,611.51,616.87,622.22,627.58,632.93,638.29,643.64,649.0,-631.04,-625.69,-620.33,-614.98,-609.62,-604.26,-598.91,-593.55,-588.2,-582.84,-577.49,-572.13,-566.77,-561.42,-556.06,-550.71,-545.35,-540.0,-534.64,-529.28,-523.93,-518.57,-513.22,-507.86,-502.51,-497.15,-491.8,-486.44,-481.08,-475.73,-470.37,-465.02,-459.66,-454.31,-448.95,-443.59,-438.24,-432.88,-427.53,-422.17,-416.82,-411.46,-406.1,-400.75,-395.39,-390.04,-384.68,-379.33,-373.97,-368.62,-363.26,-357.9,-352.55,-347.19,-341.84,-336.48,-331.13,-325.77,-320.41,-315.06,-309.7,-304.35,-298.99,-293.64,-288.28,-282.92,-277.57,-272.21,-266.86,-261.5,-256.15,-250.79,-245.44,-240.08,-234.72,-229.37,-224.01,-218.66,-213.3,-207.95,-202.59,-197.23,-191.88,-186.52,-181.17,-175.81,-170.46,-165.1,-159.74,-154.39,-149.03,-143.68,-138.32,-132.97,-127.61,-122.26,-116.9,-111.54,-106.19,-100.83,-95.48,-90.12,-84.77,-79.41,-74.05,-68.7,-63.34,-57.99,-52.63,-47.28,-41.92,-36.56,-31.21,-25.85,-20.5,-15.14,-9.79,-4.43,0.92,6.28,11.64,16.99,22.35,27.7,33.06,38.41,43.77,49.13,54.48,59.84,65.19,70.55,75.9,81.26,86.61,91.97,97.33,102.68,108.04,113.39,118.75,124.1,129.46,134.82,140.17,145.53,150.88,156.24,161.59,166.95,172.31,177.66,183.02,188.37,193.73,199.08,204.44,209.79,215.15,220.51,225.86,231.22,236.57,241.93,247.28,252.64,258.0,263.35,268.71,274.06,279.42,284.77,290.13,295.49,300.84,306.2,311.55,316.91,322.26,327.62,332.97,338.33,343.69,349.04,354.4,359.75,365.11,370.46,375.82,381.18,386.53,391.89,397.24,402.6,407.95,413.31,418.67,424.02,429.38,434.73,440.09,445.44,450.8,456.15,461.51,466.87,472.22,477.58,482.93,488.29,493.64,499.0,504.36,509.71,515.07,520.42,525.78,531.13,536.49,541.85,547.2,552.56,557.91,563.27,568.62,573.98,579.33,584.69,590.05,595.4,600.76,606.11,611.47,616.82,622.18,627.54,632.89,638.25,643.6,648.96,-631.15,-625.8,-620.44,-615.09,-609.73,-604.38,-599.02,-593.66,-588.31,-582.95,-577.6,-572.24,-566.89,-561.53,-556.17,-550.82,-545.46,-540.11,-534.75,-529.4,-524.04,-518.69,-513.33,-507.97,-502.62,-497.26,-491.91,-486.55,-481.2,-475.84,-470.48,-465.13,-459.77,-454.42,-449.06,-443.71,-438.35,-432.99,-427.64,-422.28,-416.93,-411.57,-406.22,-400.86,-395.51,-390.15,-384.79,-379.44,-374.08,-368.73,-363.37,-358.02,-352.66,-347.3,-341.95,-336.59,-331.24,-325.88,-320.53,-315.17,-309.82,-304.46,-299.1,-293.75,-288.39,-283.04,-277.68,-272.33,-266.97,-261.61,-256.26,-250.9,-245.55,-240.19,-234.84,-229.48,-224.12,-218.77,-213.41,-208.06,-202.7,-197.35,-191.99,-186.64,-181.28,-175.92,-170.57,-165.21,-159.86,-154.5,-149.15,-143.79,-138.43,-133.08,-127.72,-122.37,-117.01,-111.66,-106.3,-100.94,-95.59,-90.23,-84.88,-79.52,-74.17,-68.81,-63.46,-58.1,-52.74,-47.39,-42.03,-36.68,-31.32,-25.97,-20.61,-15.25,-9.9,-4.54,0.81,6.17,11.52,16.88,22.24,27.59,32.95,38.3,43.66,49.01,54.37,59.72,65.08,70.44,75.79,81.15,86.5,91.86,97.21,102.57,107.93,113.28,118.64,123.99,129.35,134.7,140.06,145.42,150.77,156.13,161.48,166.84,172.19,177.55,182.9,188.26,193.62,198.97,204.33,209.68,215.04,220.39,225.75,231.11,236.46,241.82,247.17,252.53,257.88,263.24,268.59,273.95,279.31,284.66,290.02,295.37,300.73,306.08,311.44,316.8,322.15,327.51,332.86,338.22,343.57,348.93,354.29,359.64,365.0,370.35,375.71,381.06,386.42,391.77,397.13,402.49,407.84,413.2,418.55,423.91,429.26,434.62,439.98,445.33,450.69,456.04,461.4,466.75,472.11,477.47,482.82,488.18,493.53,498.89,504.24,509.6,514.95,520.31,525.67,531.02,536.38,541.73,547.09,552.44,557.8,563.16,568.51,573.87,579.22,584.58,589.93,595.29,600.65,606.0,611.36,616.71,622.07,627.42,632.78,638.13,643.49,648.85,-631.34,-625.98,-620.62,-615.27,-609.91,-604.56,-599.2,-593.85,-588.49,-583.13,-577.78,-572.42,-567.07,-561.71,-556.36,-551.0,-545.65,-540.29,-534.93,-529.58,-524.22,-518.87,-513.51,-508.16,-502.8,-497.44,-492.09,-486.73,-481.38,-476.02,-470.67,-465.31,-459.95,-454.6,-449.24,-443.89,-438.53,-433.18,-427.82,-422.47,-417.11,-411.75,-406.4,-401.04,-395.69,-390.33,-384.98,-379.62,-374.26,-368.91,-363.55,-358.2,-352.84,-347.49,-342.13,-336.77,-331.42,-326.06,-320.71,-315.35,-310.0,-304.64,-299.29,-293.93,-288.57,-283.22,-277.86,-272.51,-267.15,-261.8,-256.44,-251.08,-245.73,-240.37,-235.02,-229.66,-224.31,-218.95,-213.59,-208.24,-202.88,-197.53,-192.17,-186.82,-181.46,-176.11,-170.75,-165.39,-160.04,-154.68,-149.33,-143.97,-138.62,-133.26,-127.9,-122.55,-117.19,-111.84,-106.48,-101.13,-95.77,-90.41,-85.06,-79.7,-74.35,-68.99,-63.64,-58.28,-52.93,-47.57,-42.21,-36.86,-31.5,-26.15,-20.79,-15.44,-10.08,-4.72,0.63,5.99,11.34,16.7,22.05,27.41,32.76,38.12,43.48,48.83,54.19,59.54,64.9,70.25,75.61,80.97,86.32,91.68,97.03,102.39,107.74,113.1,118.46,123.81,129.17,134.52,139.88,145.23,150.59,155.94,161.3,166.66,172.01,177.37,182.72,188.08,193.43,198.79,204.15,209.5,214.86,220.21,225.57,230.92,236.28,241.64,246.99,252.35,257.7,263.06,268.41,273.77,279.12,284.48,289.84,295.19,300.55,305.9,311.26,316.61,321.97,327.33,332.68,338.04,343.39,348.75,354.1,359.46,364.82,370.17,375.53,380.88,386.24,391.59,396.95,402.3,407.66,413.02,418.37,423.73,429.08,434.44,439.79,445.15,450.51,455.86,461.22,466.57,471.93,477.28,482.64,488.0,493.35,498.71,504.06,509.42,514.77,520.13,525.48,530.84,536.2,541.55,546.91,552.26,557.62,562.97,568.33,573.69,579.04,584.4,589.75,595.11,600.46,605.82,611.18,616.53,621.89,627.24,632.6,637.95,643.31,648.66,-631.58,-626.23,-620.87,-615.52,-610.16,-604.81,-599.45,-594.1,-588.74,-583.38,-578.03,-572.67,-567.32,-561.96,-556.61,-551.25,-545.89,-540.54,-535.18,-529.83,-524.47,-519.12,-513.76,-508.41,-503.05,-497.69,-492.34,-486.98,-481.63,-476.27,-470.92,-465.56,-460.2,-454.85,-449.49,-444.14,-438.78,-433.43,-428.07,-422.71,-417.36,-412.0,-406.65,-401.29,-395.94,-390.58,-385.23,-379.87,-374.51,-369.16,-363.8,-358.45,-353.09,-347.74,-342.38,-337.02,-331.67,-326.31,-320.96,-315.6,-310.25,-304.89,-299.53,-294.18,-288.82,-283.47,-278.11,-272.76,-267.4,-262.05,-256.69,-251.33,-245.98,-240.62,-235.27,-229.91,-224.56,-219.2,-213.84,-208.49,-203.13,-197.78,-192.42,-187.07,-181.71,-176.35,-171.0,-165.64,-160.29,-154.93,-149.58,-144.22,-138.87,-133.51,-128.15,-122.8,-117.44,-112.09,-106.73,-101.38,-96.02,-90.66,-85.31,-79.95,-74.6,-69.24,-63.89,-58.53,-53.17,-47.82,-42.46,-37.11,-31.75,-26.4,-21.04,-15.69,-10.33,-4.97,0.38,5.74,11.09,16.45,21.8,27.16,32.52,37.87,43.23,48.58,53.94,59.29,64.65,70.01,75.36,80.72,86.07,91.43,96.78,102.14,107.49,112.85,118.21,123.56,128.92,134.27,139.63,144.98,150.34,155.7,161.05,166.41,171.76,177.12,182.47,187.83,193.18,198.54,203.9,209.25,214.61,219.96,225.32,230.67,236.03,241.39,246.74,252.1,257.45,262.81,268.16,273.52,278.88,284.23,289.59,294.94,300.3,305.65,311.01,316.36,321.72,327.08,332.43,337.79,343.14,348.5,353.85,359.21,364.57,369.92,375.28,380.63,385.99,391.34,396.7,402.06,407.41,412.77,418.12,423.48,428.83,434.19,439.54,444.9,450.26,455.61,460.97,466.32,471.68,477.03,482.39,487.75,493.1,498.46,503.81,509.17,514.52,519.88,525.24,530.59,535.95,541.3,546.66,552.01,557.37,562.72,568.08,573.44,578.79,584.15,589.5,594.86,600.21,605.57,610.93,616.28,621.64,626.99,632.35,637.7,643.06,648.42,-631.9,-626.54,-621.19,-615.83,-610.48,-605.12,-599.77,-594.41,-589.06,-583.7,-578.34,-572.99,-567.63,-562.28,-556.92,-551.57,-546.21,-540.85,-535.5,-530.14,-524.79,-519.43,-514.08,-508.72,-503.36,-498.01,-492.65,-487.3,-481.94,-476.59,-471.23,-465.88,-460.52,-455.16,-449.81,-444.45,-439.1,-433.74,-428.39,-423.03,-417.67,-412.32,-406.96,-401.61,-396.25,-390.9,-385.54,-380.18,-374.83,-369.47,-364.12,-358.76,-353.41,-348.05,-342.7,-337.34,-331.98,-326.63,-321.27,-315.92,-310.56,-305.21,-299.85,-294.49,-289.14,-283.78,-278.43,-273.07,-267.72,-262.36,-257.01,-251.65,-246.29,-240.94,-235.58,-230.23,-224.87,-219.52,-214.16,-208.8,-203.45,-198.09,-192.74,-187.38,-182.03,-176.67,-171.31,-165.96,-160.6,-155.25,-149.89,-144.54,-139.18,-133.83,-128.47,-123.11,-117.76,-112.4,-107.05,-101.69,-96.34,-90.98,-85.62,-80.27,-74.91,-69.56,-64.2,-58.85,-53.49,-48.13,-42.78,-37.42,-32.07,-26.71,-21.36,-16.0,-10.65,-5.29,0.07,5.42,10.78,16.13,21.49,26.84,32.2,37.56,42.91,48.27,53.62,58.98,64.33,69.69,75.05,80.4,85.76,91.11,96.47,101.82,107.18,112.53,117.89,123.25,128.6,133.96,139.31,144.67,150.02,155.38,160.74,166.09,171.45,176.8,182.16,187.51,192.87,198.23,203.58,208.94,214.29,219.65,225.0,230.36,235.71,241.07,246.43,251.78,257.14,262.49,267.85,273.2,278.56,283.92,289.27,294.63,299.98,305.34,310.69,316.05,321.4,326.76,332.12,337.47,342.83,348.18,353.54,358.89,364.25,369.61,374.96,380.32,385.67,391.03,396.38,401.74,407.1,412.45,417.81,423.16,428.52,433.87,439.23,444.58,449.94,455.3,460.65,466.01,471.36,476.72,482.07,487.43,492.79,498.14,503.5,508.85,514.21,519.56,524.92,530.28,535.63,540.99,546.34,551.7,557.05,562.41,567.76,573.12,578.48,583.83,589.19,594.54,599.9,605.25,610.61,615.97,621.32,626.68,632.03,637.39,642.74,648.1,-632.28,-626.92,-621.57,-616.21,-610.86,-605.5,-600.15,-594.79,-589.43,-584.08,-578.72,-573.37,-568.01,-562.66,-557.3,-551.94,-546.59,-541.23,-535.88,-530.52,-525.17,-519.81,-514.46,-509.1,-503.74,-498.39,-493.03,-487.68,-482.32,-476.97,-471.61,-466.25,-460.9,-455.54,-450.19,-444.83,-439.48,-434.12,-428.76,-423.41,-418.05,-412.7,-407.34,-401.99,-396.63,-391.28,-385.92,-380.56,-375.21,-369.85,-364.5,-359.14,-353.79,-348.43,-343.07,-337.72,-332.36,-327.01,-321.65,-316.3,-310.94,-305.59,-300.23,-294.87,-289.52,-284.16,-278.81,-273.45,-268.1,-262.74,-257.38,-252.03,-246.67,-241.32,-235.96,-230.61,-225.25,-219.89,-214.54,-209.18,-203.83,-198.47,-193.12,-187.76,-182.41,-177.05,-171.69,-166.34,-160.98,-155.63,-150.27,-144.92,-139.56,-134.2,-128.85,-123.49,-118.14,-112.78,-107.43,-102.07,-96.71,-91.36,-86.0,-80.65,-75.29,-69.94,-64.58,-59.23,-53.87,-48.51,-43.16,-37.8,-32.45,-27.09,-21.74,-16.38,-11.02,-5.67,-0.31,5.04,10.4,15.75,21.11,26.47,31.82,37.18,42.53,47.89,53.24,58.6,63.95,69.31,74.67,80.02,85.38,90.73,96.09,101.44,106.8,112.16,117.51,122.87,128.22,133.58,138.93,144.29,149.65,155.0,160.36,165.71,171.07,176.42,181.78,187.13,192.49,197.85,203.2,208.56,213.91,219.27,224.62,229.98,235.34,240.69,246.05,251.4,256.76,262.11,267.47,272.83,278.18,283.54,288.89,294.25,299.6,304.96,310.31,315.67,321.03,326.38,331.74,337.09,342.45,347.8,353.16,358.52,363.87,369.23,374.58,379.94,385.29,390.65,396.0,401.36,406.72,412.07,417.43,422.78,428.14,433.49,438.85,444.21,449.56,454.92,460.27,465.63,470.98,476.34,481.7,487.05,492.41,497.76,503.12,508.47,513.83,519.18,524.54,529.9,535.25,540.61,545.96,551.32,556.67,562.03,567.39,572.74,578.1,583.45,588.81,594.16,599.52,604.88,610.23,615.59,620.94,626.3,631.65,637.01,642.36,647.72,-632.72,-627.36,-622.01,-616.65,-611.3,-605.94,-600.59,-595.23,-589.87,-584.52,-579.16,-573.81,-568.45,-563.1,-557.74,-552.38,-547.03,-541.67,-536.32,-530.96,-525.61,-520.25,-514.9,-509.54,-504.18,-498.83,-493.47,-488.12,-482.76,-477.41,-472.05,-466.69,-461.34,-455.98,-450.63,-445.27,-439.92,-434.56,-429.2,-423.85,-418.49,-413.14,-407.78,-402.43,-397.07,-391.72,-386.36,-381.0,-375.65,-370.29,-364.94,-359.58,-354.23,-348.87,-343.51,-338.16,-332.8,-327.45,-322.09,-316.74,-311.38,-306.02,-300.67,-295.31,-289.96,-284.6,-279.25,-273.89,-268.54,-263.18,-257.82,-252.47,-247.11,-241.76,-236.4,-231.05,-225.69,-220.33,-214.98,-209.62,-204.27,-198.91,-193.56,-188.2,-182.84,-177.49,-172.13,-166.78,-161.42,-156.07,-150.71,-145.36,-140.0,-134.64,-129.29,-123.93,-118.58,-113.22,-107.87,-102.51,-97.15,-91.8,-86.44,-81.09,-75.73,-70.38,-65.02,-59.66,-54.31,-48.95,-43.6,-38.24,-32.89,-27.53,-22.18,-16.82,-11.46,-6.11,-0.75,4.6,9.96,15.31,20.67,26.03,31.38,36.74,42.09,47.45,52.8,58.16,63.51,68.87,74.23,79.58,84.94,90.29,95.65,101.0,106.36,111.72,117.07,122.43,127.78,133.14,138.49,143.85,149.21,154.56,159.92,165.27,170.63,175.98,181.34,186.69,192.05,197.41,202.76,208.12,213.47,218.83,224.18,229.54,234.9,240.25,245.61,250.96,256.32,261.67,267.03,272.39,277.74,283.1,288.45,293.81,299.16,304.52,309.87,315.23,320.59,325.94,331.3,336.65,342.01,347.36,352.72,358.08,363.43,368.79,374.14,379.5,384.85,390.21,395.57,400.92,406.28,411.63,416.99,422.34,427.7,433.05,438.41,443.77,449.12,454.48,459.83,465.19,470.54,475.9,481.26,486.61,491.97,497.32,502.68,508.03,513.39,518.75,524.1,529.46,534.81,540.17,545.52,550.88,556.23,561.59,566.95,572.3,577.66,583.01,588.37,593.72,599.08,604.44,609.79,615.15,620.5,625.86,631.21,636.57,641.93,647.28,-633.22,-627.86,-622.5,-617.15,-611.79,-606.44,-601.08,-595.73,-590.37,-585.02,-579.66,-574.3,-568.95,-563.59,-558.24,-552.88,-547.53,-542.17,-536.81,-531.46,-526.1,-520.75,-515.39,-510.04,-504.68,-499.33,-493.97,-488.61,-483.26,-477.9,-472.55,-467.19,-461.84,-456.48,-451.12,-445.77,-440.41,-435.06,-429.7,-424.35,-418.99,-413.63,-408.28,-402.92,-397.57,-392.21,-386.86,-381.5,-376.15,-370.79,-365.43,-360.08,-354.72,-349.37,-344.01,-338.66,-333.3,-327.94,-322.59,-317.23,-311.88,-306.52,-301.17,-295.81,-290.45,-285.1,-279.74,-274.39,-269.03,-263.68,-258.32,-252.97,-247.61,-242.25,-236.9,-231.54,-226.19,-220.83,-215.48,-210.12,-204.76,-199.41,-194.05,-188.7,-183.34,-177.99,-172.63,-167.27,-161.92,-156.56,-151.21,-145.85,-140.5,-135.14,-129.79,-124.43,-119.07,-113.72,-108.36,-103.01,-97.65,-92.3,-86.94,-81.58,-76.23,-70.87,-65.52,-60.16,-54.81,-49.45,-44.09,-38.74,-33.38,-28.03,-22.67,-17.32,-11.96,-6.61,-1.25,4.11,9.46,14.82,20.17,25.53,30.88,36.24,41.6,46.95,52.31,57.66,63.02,68.37,73.73,79.09,84.44,89.8,95.15,100.51,105.86,111.22,116.57,121.93,127.29,132.64,138.0,143.35,148.71,154.06,159.42,164.78,170.13,175.49,180.84,186.2,191.55,196.91,202.26,207.62,212.98,218.33,223.69,229.04,234.4,239.75,245.11,250.47,255.82,261.18,266.53,271.89,277.24,282.6,287.96,293.31,298.67,304.02,309.38,314.73,320.09,325.44,330.8,336.16,341.51,346.87,352.22,357.58,362.93,368.29,373.65,379.0,384.36,389.71,395.07,400.42,405.78,411.14,416.49,421.85,427.2,432.56,437.91,443.27,448.62,453.98,459.34,464.69,470.05,475.4,480.76,486.11,491.47,496.83,502.18,507.54,512.89,518.25,523.6,528.96,534.32,539.67,545.03,550.38,555.74,561.09,566.45,571.8,577.16,582.52,587.87,593.23,598.58,603.94,609.29,614.65,620.01,625.36,630.72,636.07,641.43,646.78,-633.77,-628.41,-623.06,-617.7,-612.34,-606.99,-601.63,-596.28,-590.92,-585.57,-580.21,-574.85,-569.5,-564.14,-558.79,-553.43,-548.08,-542.72,-537.36,-532.01,-526.65,-521.3,-515.94,-510.59,-505.23,-499.88,-494.52,-489.16,-483.81,-478.45,-473.1,-467.74,-462.39,-457.03,-451.67,-446.32,-440.96,-435.61,-430.25,-424.9,-419.54,-414.18,-408.83,-403.47,-398.12,-392.76,-387.41,-382.05,-376.7,-371.34,-365.98,-360.63,-355.27,-349.92,-344.56,-339.21,-333.85,-328.49,-323.14,-317.78,-312.43,-307.07,-301.72,-296.36,-291.0,-285.65,-280.29,-274.94,-269.58,-264.23,-258.87,-253.52,-248.16,-242.8,-237.45,-232.09,-226.74,-221.38,-216.03,-210.67,-205.31,-199.96,-194.6,-189.25,-183.89,-178.54,-173.18,-167.82,-162.47,-157.11,-151.76,-146.4,-141.05,-135.69,-130.34,-124.98,-119.62,-114.27,-108.91,-103.56,-98.2,-92.85,-87.49,-82.13,-76.78,-71.42,-66.07,-60.71,-55.36,-50.0,-44.65,-39.29,-33.93,-28.58,-23.22,-17.87,-12.51,-7.16,-1.8,3.56,8.91,14.27,19.62,24.98,30.33,35.69,41.05,46.4,51.76,57.11,62.47,67.82,73.18,78.53,83.89,89.25,94.6,99.96,105.31,110.67,116.02,121.38,126.74,132.09,137.45,142.8,148.16,153.51,158.87,164.23,169.58,174.94,180.29,185.65,191.0,196.36,201.71,207.07,212.43,217.78,223.14,228.49,233.85,239.2,244.56,249.92,255.27,260.63,265.98,271.34,276.69,282.05,287.41,292.76,298.12,303.47,308.83,314.18,319.54,324.89,330.25,335.61,340.96,346.32,351.67,357.03,362.38,367.74,373.1,378.45,383.81,389.16,394.52,399.87,405.23,410.59,415.94,421.3,426.65,432.01,437.36,442.72,448.07,453.43,458.79,464.14,469.5,474.85,480.21,485.56,490.92,496.28,501.63,506.99,512.34,517.7,523.05,528.41,533.76,539.12,544.48,549.83,555.19,560.54,565.9,571.25,576.61,581.97,587.32,592.68,598.03,603.39,608.74,614.1,619.46,624.81,630.17,635.52,640.88,646.23,-634.37,-629.01,-623.65,-618.3,-612.94,-607.59,-602.23,-596.88,-591.52,-586.16,-580.81,-575.45,-570.1,-564.74,-559.39,-554.03,-548.68,-543.32,-537.96,-532.61,-527.25,-521.9,-516.54,-511.19,-505.83,-500.47,-495.12,-489.76,-484.41,-479.05,-473.7,-468.34,-462.98,-457.63,-452.27,-446.92,-441.56,-436.21,-430.85,-425.5,-420.14,-414.78,-409.43,-404.07,-398.72,-393.36,-388.01,-382.65,-377.29,-371.94,-366.58,-361.23,-355.87,-350.52,-345.16,-339.8,-334.45,-329.09,-323.74,-318.38,-313.03,-307.67,-302.32,-296.96,-291.6,-286.25,-280.89,-275.54,-270.18,-264.83,-259.47,-254.11,-248.76,-243.4,-238.05,-232.69,-227.34,-221.98,-216.62,-211.27,-205.91,-200.56,-195.2,-189.85,-184.49,-179.14,-173.78,-168.42,-163.07,-157.71,-152.36,-147.0,-141.65,-136.29,-130.93,-125.58,-120.22,-114.87,-109.51,-104.16,-98.8,-93.44,-88.09,-82.73,-77.38,-72.02,-66.67,-61.31,-55.96,-50.6,-45.24,-39.89,-34.53,-29.18,-23.82,-18.47,-13.11,-7.75,-2.4,2.96,8.31,13.67,19.02,24.38,29.73,35.09,40.45,45.8,51.16,56.51,61.87,67.22,72.58,77.94,83.29,88.65,94.0,99.36,104.71,110.07,115.43,120.78,126.14,131.49,136.85,142.2,147.56,152.91,158.27,163.63,168.98,174.34,179.69,185.05,190.4,195.76,201.12,206.47,211.83,217.18,222.54,227.89,233.25,238.61,243.96,249.32,254.67,260.03,265.38,270.74,276.09,281.45,286.81,292.16,297.52,302.87,308.23,313.58,318.94,324.3,329.65,335.01,340.36,345.72,351.07,356.43,361.79,367.14,372.5,377.85,383.21,388.56,393.92,399.27,404.63,409.99,415.34,420.7,426.05,431.41,436.76,442.12,447.48,452.83,458.19,463.54,468.9,474.25,479.61,484.97,490.32,495.68,501.03,506.39,511.74,517.1,522.45,527.81,533.17,538.52,543.88,549.23,554.59,559.94,565.3,570.66,576.01,581.37,586.72,592.08,597.43,602.79,608.14,613.5,618.86,624.21,629.57,634.92,640.28,645.63,-635.01,-629.65,-624.3,-618.94,-613.59,-608.23,-602.87,-597.52,-592.16,-586.81,-581.45,-576.1,-570.74,-565.39,-560.03,-554.67,-549.32,-543.96,-538.61,-533.25,-527.9,-522.54,-517.18,-511.83,-506.47,-501.12,-495.76,-490.41,-485.05,-479.7,-474.34,-468.98,-463.63,-458.27,-452.92,-447.56,-442.21,-436.85,-431.49,-426.14,-420.78,-415.43,-410.07,-404.72,-399.36,-394.0,-388.65,-383.29,-377.94,-372.58,-367.23,-361.87,-356.52,-351.16,-345.8,-340.45,-335.09,-329.74,-324.38,-319.03,-313.67,-308.31,-302.96,-297.6,-292.25,-286.89,-281.54,-276.18,-270.82,-265.47,-260.11,-254.76,-249.4,-244.05,-238.69,-233.34,-227.98,-222.62,-217.27,-211.91,-206.56,-201.2,-195.85,-190.49,-185.13,-179.78,-174.42,-169.07,-163.71,-158.36,-153.0,-147.64,-142.29,-136.93,-131.58,-126.22,-120.87,-115.51,-110.16,-104.8,-99.44,-94.09,-88.73,-83.38,-78.02,-72.67,-67.31,-61.95,-56.6,-51.24,-45.89,-40.53,-35.18,-29.82,-24.46,-19.11,-13.75,-8.4,-3.04,2.31,7.67,13.02,18.38,23.74,29.09,34.45,39.8,45.16,50.51,55.87,61.23,66.58,71.94,77.29,82.65,88.0,93.36,98.72,104.07,109.43,114.78,120.14,125.49,130.85,136.2,141.56,146.92,152.27,157.63,162.98,168.34,173.69,179.05,184.41,189.76,195.12,200.47,205.83,211.18,216.54,221.89,227.25,232.61,237.96,243.32,248.67,254.03,259.38,264.74,270.1,275.45,280.81,286.16,291.52,296.87,302.23,307.59,312.94,318.3,323.65,329.01,334.36,339.72,345.07,350.43,355.79,361.14,366.5,371.85,377.21,382.56,387.92,393.28,398.63,403.99,409.34,414.7,420.05,425.41,430.77,436.12,441.48,446.83,452.19,457.54,462.9,468.25,473.61,478.97,484.32,489.68,495.03,500.39,505.74,511.1,516.46,521.81,527.17,532.52,537.88,543.23,548.59,553.95,559.3,564.66,570.01,575.37,580.72,586.08,591.43,596.79,602.15,607.5,612.86,618.21,623.57,628.92,634.28,639.64,644.99,-635.69,-630.34,-624.98,-619.62,-614.27,-608.91,-603.56,-598.2,-592.85,-587.49,-582.13,-576.78,-571.42,-566.07,-560.71,-555.36,-550.0,-544.65,-539.29,-533.93,-528.58,-523.22,-517.87,-512.51,-507.16,-501.8,-496.44,-491.09,-485.73,-480.38,-475.02,-469.67,-464.31,-458.95,-453.6,-448.24,-442.89,-437.53,-432.18,-426.82,-421.47,-416.11,-410.75,-405.4,-400.04,-394.69,-389.33,-383.98,-378.62,-373.26,-367.91,-362.55,-357.2,-351.84,-346.49,-341.13,-335.78,-330.42,-325.06,-319.71,-314.35,-309.0,-303.64,-298.29,-292.93,-287.57,-282.22,-276.86,-271.51,-266.15,-260.8,-255.44,-250.08,-244.73,-239.37,-234.02,-228.66,-223.31,-217.95,-212.6,-207.24,-201.88,-196.53,-191.17,-185.82,-180.46,-175.11,-169.75,-164.39,-159.04,-153.68,-148.33,-142.97,-137.62,-132.26,-126.9,-121.55,-116.19,-110.84,-105.48,-100.13,-94.77,-89.42,-84.06,-78.7,-73.35,-67.99,-62.64,-57.28,-51.93,-46.57,-41.21,-35.86,-30.5,-25.15,-19.79,-14.44,-9.08,-3.72,1.63,6.99,12.34,17.7,23.05,28.41,33.76,39.12,44.48,49.83,55.19,60.54,65.9,71.25,76.61,81.97,87.32,92.68,98.03,103.39,108.74,114.1,119.46,124.81,130.17,135.52,140.88,146.23,151.59,156.94,162.3,167.66,173.01,178.37,183.72,189.08,194.43,199.79,205.15,210.5,215.86,221.21,226.57,231.92,237.28,242.64,247.99,253.35,258.7,264.06,269.41,274.77,280.12,285.48,290.84,296.19,301.55,306.9,312.26,317.61,322.97,328.33,333.68,339.04,344.39,349.75,355.1,360.46,365.81,371.17,376.53,381.88,387.24,392.59,397.95,403.3,408.66,414.02,419.37,424.73,430.08,435.44,440.79,446.15,451.51,456.86,462.22,467.57,472.93,478.28,483.64,488.99,494.35,499.71,505.06,510.42,515.77,521.13,526.48,531.84,537.2,542.55,547.91,553.26,558.62,563.97,569.33,574.69,580.04,585.4,590.75,596.11,601.46,606.82,612.17,617.53,622.89,628.24,633.6,638.95,644.31,-636.41,-631.05,-625.7,-620.34,-614.99,-609.63,-604.27,-598.92,-593.56,-588.21,-582.85,-577.5,-572.14,-566.78,-561.43,-556.07,-550.72,-545.36,-540.01,-534.65,-529.29,-523.94,-518.58,-513.23,-507.87,-502.52,-497.16,-491.81,-486.45,-481.09,-475.74,-470.38,-465.03,-459.67,-454.32,-448.96,-443.6,-438.25,-432.89,-427.54,-422.18,-416.83,-411.47,-406.11,-400.76,-395.4,-390.05,-384.69,-379.34,-373.98,-368.63,-363.27,-357.91,-352.56,-347.2,-341.85,-336.49,-331.14,-325.78,-320.42,-315.07,-309.71,-304.36,-299.0,-293.65,-288.29,-282.93,-277.58,-272.22,-266.87,-261.51,-256.16,-250.8,-245.45,-240.09,-234.73,-229.38,-224.02,-218.67,-213.31,-207.96,-202.6,-197.24,-191.89,-186.53,-181.18,-175.82,-170.47,-165.11,-159.75,-154.4,-149.04,-143.69,-138.33,-132.98,-127.62,-122.27,-116.91,-111.55,-106.2,-100.84,-95.49,-90.13,-84.78,-79.42,-74.06,-68.71,-63.35,-58.0,-52.64,-47.29,-41.93,-36.58,-31.22,-25.86,-20.51,-15.15,-9.8,-4.44,0.91,6.27,11.63,16.98,22.34,27.69,33.05,38.4,43.76,49.12,54.47,59.83,65.18,70.54,75.89,81.25,86.6,91.96,97.32,102.67,108.03,113.38,118.74,124.09,129.45,134.81,140.16,145.52,150.87,156.23,161.58,166.94,172.3,177.65,183.01,188.36,193.72,199.07,204.43,209.78,215.14,220.5,225.85,231.21,236.56,241.92,247.27,252.63,257.99,263.34,268.7,274.05,279.41,284.76,290.12,295.48,300.83,306.19,311.54,316.9,322.25,327.61,332.96,338.32,343.68,349.03,354.39,359.74,365.1,370.45,375.81,381.17,386.52,391.88,397.23,402.59,407.94,413.3,418.66,424.01,429.37,434.72,440.08,445.43,450.79,456.14,461.5,466.86,472.21,477.57,482.92,488.28,493.63,498.99,504.35,509.7,515.06,520.41,525.77,531.12,536.48,541.83,547.19,552.55,557.9,563.26,568.61,573.97,579.32,584.68,590.04,595.39,600.75,606.1,611.46,616.81,622.17,627.53,632.88,638.24,643.59,-637.15,-631.8,-626.44,-621.09,-615.73,-610.37,-605.02,-599.66,-594.31,-588.95,-583.6,-578.24,-572.88,-567.53,-562.17,-556.82,-551.46,-546.11,-540.75,-535.39,-530.04,-524.68,-519.33,-513.97,-508.62,-503.26,-497.91,-492.55,-487.19,-481.84,-476.48,-471.13,-465.77,-460.42,-455.06,-449.7,-444.35,-438.99,-433.64,-428.28,-422.93,-417.57,-412.21,-406.86,-401.5,-396.15,-390.79,-385.44,-380.08,-374.73,-369.37,-364.01,-358.66,-353.3,-347.95,-342.59,-337.24,-331.88,-326.52,-321.17,-315.81,-310.46,-305.1,-299.75,-294.39,-289.04,-283.68,-278.32,-272.97,-267.61,-262.26,-256.9,-251.55,-246.19,-240.83,-235.48,-230.12,-224.77,-219.41,-214.06,-208.7,-203.34,-197.99,-192.63,-187.28,-181.92,-176.57,-171.21,-165.86,-160.5,-155.14,-149.79,-144.43,-139.08,-133.72,-128.37,-123.01,-117.65,-112.3,-106.94,-101.59,-96.23,-90.88,-85.52,-80.16,-74.81,-69.45,-64.1,-58.74,-53.39,-48.03,-42.68,-37.32,-31.96,-26.61,-21.25,-15.9,-10.54,-5.19,0.17,5.53,10.88,16.24,21.59,26.95,32.3,37.66,43.02,48.37,53.73,59.08,64.44,69.79,75.15,80.5,85.86,91.22,96.57,101.93,107.28,112.64,117.99,123.35,128.71,134.06,139.42,144.77,150.13,155.48,160.84,166.2,171.55,176.91,182.26,187.62,192.97,198.33,203.68,209.04,214.4,219.75,225.11,230.46,235.82,241.17,246.53,251.89,257.24,262.6,267.95,273.31,278.66,284.02,289.37,294.73,300.09,305.44,310.8,316.15,321.51,326.86,332.22,337.58,342.93,348.29,353.64,359.0,364.35,369.71,375.07,380.42,385.78,391.13,396.49,401.84,407.2,412.55,417.91,423.27,428.62,433.98,439.33,444.69,450.04,455.4,460.76,466.11,471.47,476.82,482.18,487.53,492.89,498.25,503.6,508.96,514.31,519.67,525.02,530.38,535.73,541.09,546.45,551.8,557.16,562.51,567.87,573.22,578.58,583.94,589.29,594.65,600.0,605.36,610.71,616.07,621.43,626.78,632.14,637.49,642.85,-637.92,-632.56,-627.21,-621.85,-616.5,-611.14,-605.79,-600.43,-595.07,-589.72,-584.36,-579.01,-573.65,-568.3,-562.94,-557.58,-552.23,-546.87,-541.52,-536.16,-530.81,-525.45,-520.09,-514.74,-509.38,-504.03,-498.67,-493.32,-487.96,-482.61,-477.25,-471.89,-466.54,-461.18,-455.83,-450.47,-445.12,-439.76,-434.4,-429.05,-423.69,-418.34,-412.98,-407.63,-402.27,-396.91,-391.56,-386.2,-380.85,-375.49,-370.14,-364.78,-359.43,-354.07,-348.71,-343.36,-338.0,-332.65,-327.29,-321.94,-316.58,-311.22,-305.87,-300.51,-295.16,-289.8,-284.45,-279.09,-273.74,-268.38,-263.02,-257.67,-252.31,-246.96,-241.6,-236.25,-230.89,-225.53,-220.18,-214.82,-209.47,-204.11,-198.76,-193.4,-188.04,-182.69,-177.33,-171.98,-166.62,-161.27,-155.91,-150.56,-145.2,-139.84,-134.49,-129.13,-123.78,-118.42,-113.07,-107.71,-102.35,-97.0,-91.64,-86.29,-80.93,-75.58,-70.22,-64.86,-59.51,-54.15,-48.8,-43.44,-38.09,-32.73,-27.38,-22.02,-16.66,-11.31,-5.95,-0.6,4.76,10.11,15.47,20.83,26.18,31.54,36.89,42.25,47.6,52.96,58.32,63.67,69.03,74.38,79.74,85.09,90.45,95.8,101.16,106.52,111.87,117.23,122.58,127.94,133.29,138.65,144.01,149.36,154.72,160.07,165.43,170.78,176.14,181.5,186.85,192.21,197.56,202.92,208.27,213.63,218.98,224.34,229.7,235.05,240.41,245.76,251.12,256.47,261.83,267.19,272.54,277.9,283.25,288.61,293.96,299.32,304.68,310.03,315.39,320.74,326.1,331.45,336.81,342.16,347.52,352.88,358.23,363.59,368.94,374.3,379.65,385.01,390.37,395.72,401.08,406.43,411.79,417.14,422.5,427.85,433.21,438.57,443.92,449.28,454.63,459.99,465.34,470.7,476.06,481.41,486.77,492.12,497.48,502.83,508.19,513.55,518.9,524.26,529.61,534.97,540.32,545.68,551.03,556.39,561.75,567.1,572.46,577.81,583.17,588.52,593.88,599.24,604.59,609.95,615.3,620.66,626.01,631.37,636.73,642.08,-638.7,-633.35,-627.99,-622.64,-617.28,-611.92,-606.57,-601.21,-595.86,-590.5,-585.15,-579.79,-574.43,-569.08,-563.72,-558.37,-553.01,-547.66,-542.3,-536.95,-531.59,-526.23,-520.88,-515.52,-510.17,-504.81,-499.46,-494.1,-488.74,-483.39,-478.03,-472.68,-467.32,-461.97,-456.61,-451.25,-445.9,-440.54,-435.19,-429.83,-424.48,-419.12,-413.77,-408.41,-403.05,-397.7,-392.34,-386.99,-381.63,-376.28,-370.92,-365.56,-360.21,-354.85,-349.5,-344.14,-338.79,-333.43,-328.07,-322.72,-317.36,-312.01,-306.65,-301.3,-295.94,-290.59,-285.23,-279.87,-274.52,-269.16,-263.81,-258.45,-253.1,-247.74,-242.38,-237.03,-231.67,-226.32,-220.96,-215.61,-210.25,-204.89,-199.54,-194.18,-188.83,-183.47,-178.12,-172.76,-167.41,-162.05,-156.69,-151.34,-145.98,-140.63,-135.27,-129.92,-124.56,-119.2,-113.85,-108.49,-103.14,-97.78,-92.43,-87.07,-81.71,-76.36,-71.0,-65.65,-60.29,-54.94,-49.58,-44.23,-38.87,-33.51,-28.16,-22.8,-17.45,-12.09,-6.74,-1.38,3.98,9.33,14.69,20.04,25.4,30.75,36.11,41.47,46.82,52.18,57.53,62.89,68.24,73.6,78.95,84.31,89.67,95.02,100.38,105.73,111.09,116.44,121.8,127.16,132.51,137.87,143.22,148.58,153.93,159.29,164.64,170.0,175.36,180.71,186.07,191.42,196.78,202.13,207.49,212.85,218.2,223.56,228.91,234.27,239.62,244.98,250.34,255.69,261.05,266.4,271.76,277.11,282.47,287.82,293.18,298.54,303.89,309.25,314.6,319.96,325.31,330.67,336.03,341.38,346.74,352.09,357.45,362.8,368.16,373.52,378.87,384.23,389.58,394.94,400.29,405.65,411.0,416.36,421.72,427.07,432.43,437.78,443.14,448.49,453.85,459.21,464.56,469.92,475.27,480.63,485.98,491.34,496.7,502.05,507.41,512.76,518.12,523.47,528.83,534.18,539.54,544.9,550.25,555.61,560.96,566.32,571.67,577.03,582.39,587.74,593.1,598.45,603.81,609.16,614.52,619.88,625.23,630.59,635.94,641.3,-639.5,-634.14,-628.78,-623.43,-618.07,-612.72,-607.36,-602.01,-596.65,-591.29,-585.94,-580.58,-575.23,-569.87,-564.52,-559.16,-553.81,-548.45,-543.09,-537.74,-532.38,-527.03,-521.67,-516.32,-510.96,-505.6,-500.25,-494.89,-489.54,-484.18,-478.83,-473.47,-468.12,-462.76,-457.4,-452.05,-446.69,-441.34,-435.98,-430.63,-425.27,-419.91,-414.56,-409.2,-403.85,-398.49,-393.14,-387.78,-382.42,-377.07,-371.71,-366.36,-361.0,-355.65,-350.29,-344.94,-339.58,-334.22,-328.87,-323.51,-318.16,-312.8,-307.45,-302.09,-296.73,-291.38,-286.02,-280.67,-275.31,-269.96,-264.6,-259.24,-253.89,-248.53,-243.18,-237.82,-232.47,-227.11,-221.76,-216.4,-211.04,-205.69,-200.33,-194.98,-189.62,-184.27,-178.91,-173.55,-168.2,-162.84,-157.49,-152.13,-146.78,-141.42,-136.06,-130.71,-125.35,-120.0,-114.64,-109.29,-103.93,-98.58,-93.22,-87.86,-82.51,-77.15,-71.8,-66.44,-61.09,-55.73,-50.37,-45.02,-39.66,-34.31,-28.95,-23.6,-18.24,-12.88,-7.53,-2.17,3.18,8.54,13.89,19.25,24.6,29.96,35.32,40.67,46.03,51.38,56.74,62.09,67.45,72.81,78.16,83.52,88.87,94.23,99.58,104.94,110.3,115.65,121.01,126.36,131.72,137.07,142.43,147.78,153.14,158.5,163.85,169.21,174.56,179.92,185.27,190.63,195.99,201.34,206.7,212.05,217.41,222.76,228.12,233.47,238.83,244.19,249.54,254.9,260.25,265.61,270.96,276.32,281.68,287.03,292.39,297.74,303.1,308.45,313.81,319.17,324.52,329.88,335.23,340.59,345.94,351.3,356.65,362.01,367.37,372.72,378.08,383.43,388.79,394.14,399.5,404.86,410.21,415.57,420.92,426.28,431.63,436.99,442.35,447.7,453.06,458.41,463.77,469.12,474.48,479.83,485.19,490.55,495.9,501.26,506.61,511.97,517.32,522.68,528.04,533.39,538.75,544.1,549.46,554.81,560.17,565.53,570.88,576.24,581.59,586.95,592.3,597.66,603.01,608.37,613.73,619.08,624.44,629.79,635.15,640.5,-640.29,-634.94,-629.58,-624.23,-618.87,-613.51,-608.16,-602.8,-597.45,-592.09,-586.74,-581.38,-576.03,-570.67,-565.31,-559.96,-554.6,-549.25,-543.89,-538.54,-533.18,-527.82,-522.47,-517.11,-511.76,-506.4,-501.05,-495.69,-490.34,-484.98,-479.62,-474.27,-468.91,-463.56,-458.2,-452.85,-447.49,-442.13,-436.78,-431.42,-426.07,-420.71,-415.36,-410.0,-404.64,-399.29,-393.93,-388.58,-383.22,-377.87,-372.51,-367.16,-361.8,-356.44,-351.09,-345.73,-340.38,-335.02,-329.67,-324.31,-318.95,-313.6,-308.24,-302.89,-297.53,-292.18,-286.82,-281.46,-276.11,-270.75,-265.4,-260.04,-254.69,-249.33,-243.98,-238.62,-233.26,-227.91,-222.55,-217.2,-211.84,-206.49,-201.13,-195.77,-190.42,-185.06,-179.71,-174.35,-169.0,-163.64,-158.28,-152.93,-147.57,-142.22,-136.86,-131.51,-126.15,-120.8,-115.44,-110.08,-104.73,-99.37,-94.02,-88.66,-83.31,-77.95,-72.59,-67.24,-61.88,-56.53,-51.17,-45.82,-40.46,-35.1,-29.75,-24.39,-19.04,-13.68,-8.33,-2.97,2.38,7.74,13.1,18.45,23.81,29.16,34.52,39.87,45.23,50.59,55.94,61.3,66.65,72.01,77.36,82.72,88.08,93.43,98.79,104.14,109.5,114.85,120.21,125.56,130.92,136.28,141.63,146.99,152.34,157.7,163.05,168.41,173.77,179.12,184.48,189.83,195.19,200.54,205.9,211.25,216.61,221.97,227.32,232.68,238.03,243.39,248.74,254.1,259.46,264.81,270.17,275.52,280.88,286.23,291.59,296.95,302.3,307.66,313.01,318.37,323.72,329.08,334.43,339.79,345.15,350.5,355.86,361.21,366.57,371.92,377.28,382.64,387.99,393.35,398.7,404.06,409.41,414.77,420.13,425.48,430.84,436.19,441.55,446.9,452.26,457.61,462.97,468.33,473.68,479.04,484.39,489.75,495.1,500.46,505.82,511.17,516.53,521.88,527.24,532.59,537.95,543.31,548.66,554.02,559.37,564.73,570.08,575.44,580.79,586.15,591.51,596.86,602.22,607.57,612.93,618.28,623.64,629.0,634.35,639.71,-641.09,-635.73,-630.38,-625.02,-619.67,-614.31,-608.95,-603.6,-598.24,-592.89,-587.53,-582.18,-576.82,-571.46,-566.11,-560.75,-555.4,-550.04,-544.69,-539.33,-533.98,-528.62,-523.26,-517.91,-512.55,-507.2,-501.84,-496.49,-491.13,-485.77,-480.42,-475.06,-469.71,-464.35,-459.0,-453.64,-448.28,-442.93,-437.57,-432.22,-426.86,-421.51,-416.15,-410.8,-405.44,-400.08,-394.73,-389.37,-384.02,-378.66,-373.31,-367.95,-362.59,-357.24,-351.88,-346.53,-341.17,-335.82,-330.46,-325.1,-319.75,-314.39,-309.04,-303.68,-298.33,-292.97,-287.62,-282.26,-276.9,-271.55,-266.19,-260.84,-255.48,-250.13,-244.77,-239.41,-234.06,-228.7,-223.35,-217.99,-212.64,-207.28,-201.93,-196.57,-191.21,-185.86,-180.5,-175.15,-169.79,-164.44,-159.08,-153.72,-148.37,-143.01,-137.66,-132.3,-126.95,-121.59,-116.23,-110.88,-105.52,-100.17,-94.81,-89.46,-84.1,-78.75,-73.39,-68.03,-62.68,-57.32,-51.97,-46.61,-41.26,-35.9,-30.54,-25.19,-19.83,-14.48,-9.12,-3.77,1.59,6.95,12.3,17.66,23.01,28.37,33.72,39.08,44.43,49.79,55.15,60.5,65.86,71.21,76.57,81.92,87.28,92.64,97.99,103.35,108.7,114.06,119.41,124.77,130.13,135.48,140.84,146.19,151.55,156.9,162.26,167.61,172.97,178.33,183.68,189.04,194.39,199.75,205.1,210.46,215.82,221.17,226.53,231.88,237.24,242.59,247.95,253.31,258.66,264.02,269.37,274.73,280.08,285.44,290.79,296.15,301.51,306.86,312.22,317.57,322.93,328.28,333.64,339.0,344.35,349.71,355.06,360.42,365.77,371.13,376.48,381.84,387.2,392.55,397.91,403.26,408.62,413.97,419.33,424.69,430.04,435.4,440.75,446.11,451.46,456.82,462.18,467.53,472.89,478.24,483.6,488.95,494.31,499.66,505.02,510.38,515.73,521.09,526.44,531.8,537.15,542.51,547.87,553.22,558.58,563.93,569.29,574.64,580.0,585.36,590.71,596.07,601.42,606.78,612.13,617.49,622.84,628.2,633.56,638.91,-641.87,-636.52,-631.16,-625.81,-620.45,-615.1,-609.74,-604.39,-599.03,-593.67,-588.32,-582.96,-577.61,-572.25,-566.9,-561.54,-556.18,-550.83,-545.47,-540.12,-534.76,-529.41,-524.05,-518.69,-513.34,-507.98,-502.63,-497.27,-491.92,-486.56,-481.21,-475.85,-470.49,-465.14,-459.78,-454.43,-449.07,-443.72,-438.36,-433.0,-427.65,-422.29,-416.94,-411.58,-406.23,-400.87,-395.51,-390.16,-384.8,-379.45,-374.09,-368.74,-363.38,-358.03,-352.67,-347.31,-341.96,-336.6,-331.25,-325.89,-320.54,-315.18,-309.82,-304.47,-299.11,-293.76,-288.4,-283.05,-277.69,-272.34,-266.98,-261.62,-256.27,-250.91,-245.56,-240.2,-234.85,-229.49,-224.13,-218.78,-213.42,-208.07,-202.71,-197.36,-192.0,-186.64,-181.29,-175.93,-170.58,-165.22,-159.87,-154.51,-149.16,-143.8,-138.44,-133.09,-127.73,-122.38,-117.02,-111.67,-106.31,-100.95,-95.6,-90.24,-84.89,-79.53,-74.18,-68.82,-63.46,-58.11,-52.75,-47.4,-42.04,-36.69,-31.33,-25.98,-20.62,-15.26,-9.91,-4.55,0.8,6.16,11.51,16.87,22.23,27.58,32.94,38.29,43.65,49.0,54.36,59.72,65.07,70.43,75.78,81.14,86.49,91.85,97.2,102.56,107.92,113.27,118.63,123.98,129.34,134.69,140.05,145.41,150.76,156.12,161.47,166.83,172.18,177.54,182.9,188.25,193.61,198.96,204.32,209.67,215.03,220.38,225.74,231.1,236.45,241.81,247.16,252.52,257.87,263.23,268.59,273.94,279.3,284.65,290.01,295.36,300.72,306.08,311.43,316.79,322.14,327.5,332.85,338.21,343.56,348.92,354.28,359.63,364.99,370.34,375.7,381.05,386.41,391.77,397.12,402.48,407.83,413.19,418.54,423.9,429.25,434.61,439.97,445.32,450.68,456.03,461.39,466.74,472.1,477.46,482.81,488.17,493.52,498.88,504.23,509.59,514.95,520.3,525.66,531.01,536.37,541.72,547.08,552.43,557.79,563.15,568.5,573.86,579.21,584.57,589.92,595.28,600.64,605.99,611.35,616.7,622.06,627.41,632.77,638.13,-642.65,-637.29,-631.94,-626.58,-621.22,-615.87,-610.51,-605.16,-599.8,-594.45,-589.09,-583.73,-578.38,-573.02,-567.67,-562.31,-556.96,-551.6,-546.24,-540.89,-535.53,-530.18,-524.82,-519.47,-514.11,-508.76,-503.4,-498.04,-492.69,-487.33,-481.98,-476.62,-471.27,-465.91,-460.55,-455.2,-449.84,-444.49,-439.13,-433.78,-428.42,-423.07,-417.71,-412.35,-407.0,-401.64,-396.29,-390.93,-385.58,-380.22,-374.86,-369.51,-364.15,-358.8,-353.44,-348.09,-342.73,-337.37,-332.02,-326.66,-321.31,-315.95,-310.6,-305.24,-299.89,-294.53,-289.17,-283.82,-278.46,-273.11,-267.75,-262.4,-257.04,-251.68,-246.33,-240.97,-235.62,-230.26,-224.91,-219.55,-214.19,-208.84,-203.48,-198.13,-192.77,-187.42,-182.06,-176.71,-171.35,-165.99,-160.64,-155.28,-149.93,-144.57,-139.22,-133.86,-128.5,-123.15,-117.79,-112.44,-107.08,-101.73,-96.37,-91.01,-85.66,-80.3,-74.95,-69.59,-64.24,-58.88,-53.53,-48.17,-42.81,-37.46,-32.1,-26.75,-21.39,-16.04,-10.68,-5.32,0.03,5.39,10.74,16.1,21.45,26.81,32.17,37.52,42.88,48.23,53.59,58.94,64.3,69.65,75.01,80.37,85.72,91.08,96.43,101.79,107.14,112.5,117.86,123.21,128.57,133.92,139.28,144.63,149.99,155.35,160.7,166.06,171.41,176.77,182.12,187.48,192.83,198.19,203.55,208.9,214.26,219.61,224.97,230.32,235.68,241.04,246.39,251.75,257.1,262.46,267.81,273.17,278.52,283.88,289.24,294.59,299.95,305.3,310.66,316.01,321.37,326.73,332.08,337.44,342.79,348.15,353.5,358.86,364.22,369.57,374.93,380.28,385.64,390.99,396.35,401.7,407.06,412.42,417.77,423.13,428.48,433.84,439.19,444.55,449.91,455.26,460.62,465.97,471.33,476.68,482.04,487.4,492.75,498.11,503.46,508.82,514.17,519.53,524.88,530.24,535.6,540.95,546.31,551.66,557.02,562.37,567.73,573.09,578.44,583.8,589.15,594.51,599.86,605.22,610.58,615.93,621.29,626.64,632.0,637.35,-643.4,-638.04,-632.69,-627.33,-621.98,-616.62,-611.26,-605.91,-600.55,-595.2,-589.84,-584.49,-579.13,-573.77,-568.42,-563.06,-557.71,-552.35,-547.0,-541.64,-536.28,-530.93,-525.57,-520.22,-514.86,-509.51,-504.15,-498.8,-493.44,-488.08,-482.73,-477.37,-472.02,-466.66,-461.31,-455.95,-450.59,-445.24,-439.88,-434.53,-429.17,-423.82,-418.46,-413.1,-407.75,-402.39,-397.04,-391.68,-386.33,-380.97,-375.62,-370.26,-364.9,-359.55,-354.19,-348.84,-343.48,-338.13,-332.77,-327.41,-322.06,-316.7,-311.35,-305.99,-300.64,-295.28,-289.92,-284.57,-279.21,-273.86,-268.5,-263.15,-257.79,-252.44,-247.08,-241.72,-236.37,-231.01,-225.66,-220.3,-214.95,-209.59,-204.23,-198.88,-193.52,-188.17,-182.81,-177.46,-172.1,-166.74,-161.39,-156.03,-150.68,-145.32,-139.97,-134.61,-129.26,-123.9,-118.54,-113.19,-107.83,-102.48,-97.12,-91.77,-86.41,-81.05,-75.7,-70.34,-64.99,-59.63,-54.28,-48.92,-43.57,-38.21,-32.85,-27.5,-22.14,-16.79,-11.43,-6.08,-0.72,4.64,9.99,15.35,20.7,26.06,31.41,36.77,42.13,47.48,52.84,58.19,63.55,68.9,74.26,79.61,84.97,90.33,95.68,101.04,106.39,111.75,117.1,122.46,127.82,133.17,138.53,143.88,149.24,154.59,159.95,165.31,170.66,176.02,181.37,186.73,192.08,197.44,202.79,208.15,213.51,218.86,224.22,229.57,234.93,240.28,245.64,251.0,256.35,261.71,267.06,272.42,277.77,283.13,288.49,293.84,299.2,304.55,309.91,315.26,320.62,325.97,331.33,336.69,342.04,347.4,352.75,358.11,363.46,368.82,374.18,379.53,384.89,390.24,395.6,400.95,406.31,411.67,417.02,422.38,427.73,433.09,438.44,443.8,449.15,454.51,459.87,465.22,470.58,475.93,481.29,486.64,492.0,497.36,502.71,508.07,513.42,518.78,524.13,529.49,534.85,540.2,545.56,550.91,556.27,561.62,566.98,572.33,577.69,583.05,588.4,593.76,599.11,604.47,609.82,615.18,620.54,625.89,631.25,636.6,-644.12,-638.77,-633.41,-628.06,-622.7,-617.34,-611.99,-606.63,-601.28,-595.92,-590.57,-585.21,-579.85,-574.5,-569.14,-563.79,-558.43,-553.08,-547.72,-542.36,-537.01,-531.65,-526.3,-520.94,-515.59,-510.23,-504.88,-499.52,-494.16,-488.81,-483.45,-478.1,-472.74,-467.39,-462.03,-456.67,-451.32,-445.96,-440.61,-435.25,-429.9,-424.54,-419.18,-413.83,-408.47,-403.12,-397.76,-392.41,-387.05,-381.7,-376.34,-370.98,-365.63,-360.27,-354.92,-349.56,-344.21,-338.85,-333.49,-328.14,-322.78,-317.43,-312.07,-306.72,-301.36,-296.0,-290.65,-285.29,-279.94,-274.58,-269.23,-263.87,-258.52,-253.16,-247.8,-242.45,-237.09,-231.74,-226.38,-221.03,-215.67,-210.31,-204.96,-199.6,-194.25,-188.89,-183.54,-178.18,-172.82,-167.47,-162.11,-156.76,-151.4,-146.05,-140.69,-135.34,-129.98,-124.62,-119.27,-113.91,-108.56,-103.2,-97.85,-92.49,-87.13,-81.78,-76.42,-71.07,-65.71,-60.36,-55.0,-49.65,-44.29,-38.93,-33.58,-28.22,-22.87,-17.51,-12.16,-6.8,-1.44,3.91,9.27,14.62,19.98,25.33,30.69,36.05,41.4,46.76,52.11,57.47,62.82,68.18,73.53,78.89,84.25,89.6,94.96,100.31,105.67,111.02,116.38,121.74,127.09,132.45,137.8,143.16,148.51,153.87,159.23,164.58,169.94,175.29,180.65,186.0,191.36,196.71,202.07,207.43,212.78,218.14,223.49,228.85,234.2,239.56,244.92,250.27,255.63,260.98,266.34,271.69,277.05,282.41,287.76,293.12,298.47,303.83,309.18,314.54,319.89,325.25,330.61,335.96,341.32,346.67,352.03,357.38,362.74,368.1,373.45,378.81,384.16,389.52,394.87,400.23,405.59,410.94,416.3,421.65,427.01,432.36,437.72,443.07,448.43,453.79,459.14,464.5,469.85,475.21,480.56,485.92,491.28,496.63,501.99,507.34,512.7,518.05,523.41,528.77,534.12,539.48,544.83,550.19,555.54,560.9,566.25,571.61,576.97,582.32,587.68,593.03,598.39,603.74,609.1,614.46,619.81,625.17,630.52,635.88,-644.81,-639.46,-634.1,-628.75,-623.39,-618.04,-612.68,-607.32,-601.97,-596.61,-591.26,-585.9,-580.55,-575.19,-569.83,-564.48,-559.12,-553.77,-548.41,-543.06,-537.7,-532.35,-526.99,-521.63,-516.28,-510.92,-505.57,-500.21,-494.86,-489.5,-484.14,-478.79,-473.43,-468.08,-462.72,-457.37,-452.01,-446.66,-441.3,-435.94,-430.59,-425.23,-419.88,-414.52,-409.17,-403.81,-398.45,-393.1,-387.74,-382.39,-377.03,-371.68,-366.32,-360.96,-355.61,-350.25,-344.9,-339.54,-334.19,-328.83,-323.48,-318.12,-312.76,-307.41,-302.05,-296.7,-291.34,-285.99,-280.63,-275.27,-269.92,-264.56,-259.21,-253.85,-248.5,-243.14,-237.78,-232.43,-227.07,-221.72,-216.36,-211.01,-205.65,-200.3,-194.94,-189.58,-184.23,-178.87,-173.52,-168.16,-162.81,-157.45,-152.09,-146.74,-141.38,-136.03,-130.67,-125.32,-119.96,-114.6,-109.25,-103.89,-98.54,-93.18,-87.83,-82.47,-77.12,-71.76,-66.4,-61.05,-55.69,-50.34,-44.98,-39.63,-34.27,-28.91,-23.56,-18.2,-12.85,-7.49,-2.14,3.22,8.58,13.93,19.29,24.64,30.0,35.35,40.71,46.06,51.42,56.78,62.13,67.49,72.84,78.2,83.55,88.91,94.27,99.62,104.98,110.33,115.69,121.04,126.4,131.76,137.11,142.47,147.82,153.18,158.53,163.89,169.24,174.6,179.96,185.31,190.67,196.02,201.38,206.73,212.09,217.45,222.8,228.16,233.51,238.87,244.22,249.58,254.93,260.29,265.65,271.0,276.36,281.71,287.07,292.42,297.78,303.14,308.49,313.85,319.2,324.56,329.91,335.27,340.63,345.98,351.34,356.69,362.05,367.4,372.76,378.11,383.47,388.83,394.18,399.54,404.89,410.25,415.6,420.96,426.32,431.67,437.03,442.38,447.74,453.09,458.45,463.81,469.16,474.52,479.87,485.23,490.58,495.94,501.29,506.65,512.01,517.36,522.72,528.07,533.43,538.78,544.14,549.5,554.85,560.21,565.56,570.92,576.27,581.63,586.99,592.34,597.7,603.05,608.41,613.76,619.12,624.47,629.83,635.19,-645.47,-640.11,-634.76,-629.4,-624.05,-618.69,-613.33,-607.98,-602.62,-597.27,-591.91,-586.56,-581.2,-575.84,-570.49,-565.13,-559.78,-554.42,-549.07,-543.71,-538.36,-533.0,-527.64,-522.29,-516.93,-511.58,-506.22,-500.87,-495.51,-490.15,-484.8,-479.44,-474.09,-468.73,-463.38,-458.02,-452.66,-447.31,-441.95,-436.6,-431.24,-425.89,-420.53,-415.18,-409.82,-404.46,-399.11,-393.75,-388.4,-383.04,-377.69,-372.33,-366.97,-361.62,-356.26,-350.91,-345.55,-340.2,-334.84,-329.48,-324.13,-318.77,-313.42,-308.06,-302.71,-297.35,-292.0,-286.64,-281.28,-275.93,-270.57,-265.22,-259.86,-254.51,-249.15,-243.79,-238.44,-233.08,-227.73,-222.37,-217.02,-211.66,-206.31,-200.95,-195.59,-190.24,-184.88,-179.53,-174.17,-168.82,-163.46,-158.1,-152.75,-147.39,-142.04,-136.68,-131.33,-125.97,-120.61,-115.26,-109.9,-104.55,-99.19,-93.84,-88.48,-83.13,-77.77,-72.41,-67.06,-61.7,-56.35,-50.99,-45.64,-40.28,-34.92,-29.57,-24.21,-18.86,-13.5,-8.15,-2.79,2.57,7.92,13.28,18.63,23.99,29.34,34.7,40.05,45.41,50.77,56.12,61.48,66.83,72.19,77.54,82.9,88.26,93.61,98.97,104.32,109.68,115.03,120.39,125.75,131.1,136.46,141.81,147.17,152.52,157.88,163.23,168.59,173.95,179.3,184.66,190.01,195.37,200.72,206.08,211.44,216.79,222.15,227.5,232.86,238.21,243.57,248.93,254.28,259.64,264.99,270.35,275.7,281.06,286.41,291.77,297.13,302.48,307.84,313.19,318.55,323.9,329.26,334.62,339.97,345.33,350.68,356.04,361.39,366.75,372.1,377.46,382.82,388.17,393.53,398.88,404.24,409.59,414.95,420.31,425.66,431.02,436.37,441.73,447.08,452.44,457.8,463.15,468.51,473.86,479.22,484.57,489.93,495.28,500.64,506.0,511.35,516.71,522.06,527.42,532.77,538.13,543.49,548.84,554.2,559.55,564.91,570.26,575.62,580.98,586.33,591.69,597.04,602.4,607.75,613.11,618.46,623.82,629.18,634.53,-646.08,-640.72,-635.37,-630.01,-624.66,-619.3,-613.95,-608.59,-603.23,-597.88,-592.52,-587.17,-581.81,-576.46,-571.1,-565.74,-560.39,-555.03,-549.68,-544.32,-538.97,-533.61,-528.26,-522.9,-517.54,-512.19,-506.83,-501.48,-496.12,-490.77,-485.41,-480.05,-474.7,-469.34,-463.99,-458.63,-453.28,-447.92,-442.56,-437.21,-431.85,-426.5,-421.14,-415.79,-410.43,-405.08,-399.72,-394.36,-389.01,-383.65,-378.3,-372.94,-367.59,-362.23,-356.87,-351.52,-346.16,-340.81,-335.45,-330.1,-324.74,-319.38,-314.03,-308.67,-303.32,-297.96,-292.61,-287.25,-281.9,-276.54,-271.18,-265.83,-260.47,-255.12,-249.76,-244.41,-239.05,-233.69,-228.34,-222.98,-217.63,-212.27,-206.92,-201.56,-196.21,-190.85,-185.49,-180.14,-174.78,-169.43,-164.07,-158.72,-153.36,-148.0,-142.65,-137.29,-131.94,-126.58,-121.23,-115.87,-110.51,-105.16,-99.8,-94.45,-89.09,-83.74,-78.38,-73.03,-67.67,-62.31,-56.96,-51.6,-46.25,-40.89,-35.54,-30.18,-24.82,-19.47,-14.11,-8.76,-3.4,1.95,7.31,12.67,18.02,23.38,28.73,34.09,39.44,44.8,50.15,55.51,60.87,66.22,71.58,76.93,82.29,87.64,93.0,98.36,103.71,109.07,114.42,119.78,125.13,130.49,135.85,141.2,146.56,151.91,157.27,162.62,167.98,173.33,178.69,184.05,189.4,194.76,200.11,205.47,210.82,216.18,221.54,226.89,232.25,237.6,242.96,248.31,253.67,259.03,264.38,269.74,275.09,280.45,285.8,291.16,296.51,301.87,307.23,312.58,317.94,323.29,328.65,334.0,339.36,344.72,350.07,355.43,360.78,366.14,371.49,376.85,382.21,387.56,392.92,398.27,403.63,408.98,414.34,419.69,425.05,430.41,435.76,441.12,446.47,451.83,457.18,462.54,467.9,473.25,478.61,483.96,489.32,494.67,500.03,505.38,510.74,516.1,521.45,526.81,532.16,537.52,542.87,548.23,553.59,558.94,564.3,569.65,575.01,580.36,585.72,591.08,596.43,601.79,607.14,612.5,617.85,623.21,628.56,633.92,-646.64,-641.29,-635.93,-630.58,-625.22,-619.86,-614.51,-609.15,-603.8,-598.44,-593.09,-587.73,-582.38,-577.02,-571.66,-566.31,-560.95,-555.6,-550.24,-544.89,-539.53,-534.17,-528.82,-523.46,-518.11,-512.75,-507.4,-502.04,-496.68,-491.33,-485.97,-480.62,-475.26,-469.91,-464.55,-459.2,-453.84,-448.48,-443.13,-437.77,-432.42,-427.06,-421.71,-416.35,-410.99,-405.64,-400.28,-394.93,-389.57,-384.22,-378.86,-373.5,-368.15,-362.79,-357.44,-352.08,-346.73,-341.37,-336.02,-330.66,-325.3,-319.95,-314.59,-309.24,-303.88,-298.53,-293.17,-287.81,-282.46,-277.1,-271.75,-266.39,-261.04,-255.68,-250.33,-244.97,-239.61,-234.26,-228.9,-223.55,-218.19,-212.84,-207.48,-202.12,-196.77,-191.41,-186.06,-180.7,-175.35,-169.99,-164.63,-159.28,-153.92,-148.57,-143.21,-137.86,-132.5,-127.15,-121.79,-116.43,-111.08,-105.72,-100.37,-95.01,-89.66,-84.3,-78.94,-73.59,-68.23,-62.88,-57.52,-52.17,-46.81,-41.45,-36.1,-30.74,-25.39,-20.03,-14.68,-9.32,-3.97,1.39,6.75,12.1,17.46,22.81,28.17,33.52,38.88,44.24,49.59,54.95,60.3,65.66,71.01,76.37,81.73,87.08,92.44,97.79,103.15,108.5,113.86,119.21,124.57,129.93,135.28,140.64,145.99,151.35,156.7,162.06,167.42,172.77,178.13,183.48,188.84,194.19,199.55,204.91,210.26,215.62,220.97,226.33,231.68,237.04,242.39,247.75,253.11,258.46,263.82,269.17,274.53,279.88,285.24,290.6,295.95,301.31,306.66,312.02,317.37,322.73,328.08,333.44,338.8,344.15,349.51,354.86,360.22,365.57,370.93,376.29,381.64,387.0,392.35,397.71,403.06,408.42,413.78,419.13,424.49,429.84,435.2,440.55,445.91,451.26,456.62,461.98,467.33,472.69,478.04,483.4,488.75,494.11,499.47,504.82,510.18,515.53,520.89,526.24,531.6,536.96,542.31,547.67,553.02,558.38,563.73,569.09,574.44,579.8,585.16,590.51,595.87,601.22,606.58,611.93,617.29,622.65,628.0,633.36,-647.15,-641.8,-636.44,-631.09,-625.73,-620.38,-615.02,-609.66,-604.31,-598.95,-593.6,-588.24,-582.89,-577.53,-572.18,-566.82,-561.46,-556.11,-550.75,-545.4,-540.04,-534.69,-529.33,-523.97,-518.62,-513.26,-507.91,-502.55,-497.2,-491.84,-486.49,-481.13,-475.77,-470.42,-465.06,-459.71,-454.35,-449.0,-443.64,-438.28,-432.93,-427.57,-422.22,-416.86,-411.51,-406.15,-400.79,-395.44,-390.08,-384.73,-379.37,-374.02,-368.66,-363.31,-357.95,-352.59,-347.24,-341.88,-336.53,-331.17,-325.82,-320.46,-315.1,-309.75,-304.39,-299.04,-293.68,-288.33,-282.97,-277.61,-272.26,-266.9,-261.55,-256.19,-250.84,-245.48,-240.13,-234.77,-229.41,-224.06,-218.7,-213.35,-207.99,-202.64,-197.28,-191.92,-186.57,-181.21,-175.86,-170.5,-165.15,-159.79,-154.43,-149.08,-143.72,-138.37,-133.01,-127.66,-122.3,-116.95,-111.59,-106.23,-100.88,-95.52,-90.17,-84.81,-79.46,-74.1,-68.74,-63.39,-58.03,-52.68,-47.32,-41.97,-36.61,-31.25,-25.9,-20.54,-15.19,-9.83,-4.48,0.88,6.23,11.59,16.95,22.3,27.66,33.01,38.37,43.72,49.08,54.44,59.79,65.15,70.5,75.86,81.21,86.57,91.93,97.28,102.64,107.99,113.35,118.7,124.06,129.41,134.77,140.13,145.48,150.84,156.19,161.55,166.9,172.26,177.62,182.97,188.33,193.68,199.04,204.39,209.75,215.1,220.46,225.82,231.17,236.53,241.88,247.24,252.59,257.95,263.31,268.66,274.02,279.37,284.73,290.08,295.44,300.8,306.15,311.51,316.86,322.22,327.57,332.93,338.28,343.64,349.0,354.35,359.71,365.06,370.42,375.77,381.13,386.49,391.84,397.2,402.55,407.91,413.26,418.62,423.98,429.33,434.69,440.04,445.4,450.75,456.11,461.46,466.82,472.18,477.53,482.89,488.24,493.6,498.95,504.31,509.67,515.02,520.38,525.73,531.09,536.44,541.8,547.16,552.51,557.87,563.22,568.58,573.93,579.29,584.64,590.0,595.36,600.71,606.07,611.42,616.78,622.13,627.49,632.85,-647.61,-642.25,-636.9,-631.54,-626.19,-620.83,-615.48,-610.12,-604.76,-599.41,-594.05,-588.7,-583.34,-577.99,-572.63,-567.27,-561.92,-556.56,-551.21,-545.85,-540.5,-535.14,-529.79,-524.43,-519.07,-513.72,-508.36,-503.01,-497.65,-492.3,-486.94,-481.58,-476.23,-470.87,-465.52,-460.16,-454.81,-449.45,-444.1,-438.74,-433.38,-428.03,-422.67,-417.32,-411.96,-406.61,-401.25,-395.89,-390.54,-385.18,-379.83,-374.47,-369.12,-363.76,-358.4,-353.05,-347.69,-342.34,-336.98,-331.63,-326.27,-320.92,-315.56,-310.2,-304.85,-299.49,-294.14,-288.78,-283.43,-278.07,-272.71,-267.36,-262.0,-256.65,-251.29,-245.94,-240.58,-235.22,-229.87,-224.51,-219.16,-213.8,-208.45,-203.09,-197.74,-192.38,-187.02,-181.67,-176.31,-170.96,-165.6,-160.25,-154.89,-149.53,-144.18,-138.82,-133.47,-128.11,-122.76,-117.4,-112.04,-106.69,-101.33,-95.98,-90.62,-85.27,-79.91,-74.56,-69.2,-63.84,-58.49,-53.13,-47.78,-42.42,-37.07,-31.71,-26.35,-21.0,-15.64,-10.29,-4.93,0.42,5.78,11.14,16.49,21.85,27.2,32.56,37.91,43.27,48.62,53.98,59.34,64.69,70.05,75.4,80.76,86.11,91.47,96.83,102.18,107.54,112.89,118.25,123.6,128.96,134.31,139.67,145.03,150.38,155.74,161.09,166.45,171.8,177.16,182.52,187.87,193.23,198.58,203.94,209.29,214.65,220.01,225.36,230.72,236.07,241.43,246.78,252.14,257.49,262.85,268.21,273.56,278.92,284.27,289.63,294.98,300.34,305.7,311.05,316.41,321.76,327.12,332.47,337.83,343.19,348.54,353.9,359.25,364.61,369.96,375.32,380.67,386.03,391.39,396.74,402.1,407.45,412.81,418.16,423.52,428.88,434.23,439.59,444.94,450.3,455.65,461.01,466.37,471.72,477.08,482.43,487.79,493.14,498.5,503.85,509.21,514.57,519.92,525.28,530.63,535.99,541.34,546.7,552.06,557.41,562.77,568.12,573.48,578.83,584.19,589.55,594.9,600.26,605.61,610.97,616.32,621.68,627.03,632.39,-648.01,-642.65,-637.29,-631.94,-626.58,-621.23,-615.87,-610.52,-605.16,-599.8,-594.45,-589.09,-583.74,-578.38,-573.03,-567.67,-562.31,-556.96,-551.6,-546.25,-540.89,-535.54,-530.18,-524.83,-519.47,-514.11,-508.76,-503.4,-498.05,-492.69,-487.34,-481.98,-476.62,-471.27,-465.91,-460.56,-455.2,-449.85,-444.49,-439.13,-433.78,-428.42,-423.07,-417.71,-412.36,-407.0,-401.65,-396.29,-390.93,-385.58,-380.22,-374.87,-369.51,-364.16,-358.8,-353.44,-348.09,-342.73,-337.38,-332.02,-326.67,-321.31,-315.95,-310.6,-305.24,-299.89,-294.53,-289.18,-283.82,-278.47,-273.11,-267.75,-262.4,-257.04,-251.69,-246.33,-240.98,-235.62,-230.26,-224.91,-219.55,-214.2,-208.84,-203.49,-198.13,-192.78,-187.42,-182.06,-176.71,-171.35,-166.0,-160.64,-155.29,-149.93,-144.57,-139.22,-133.86,-128.51,-123.15,-117.8,-112.44,-107.08,-101.73,-96.37,-91.02,-85.66,-80.31,-74.95,-69.6,-64.24,-58.88,-53.53,-48.17,-42.82,-37.46,-32.11,-26.75,-21.39,-16.04,-10.68,-5.33,0.03,5.38,10.74,16.1,21.45,26.81,32.16,37.52,42.87,48.23,53.58,58.94,64.3,69.65,75.01,80.36,85.72,91.07,96.43,101.79,107.14,112.5,117.85,123.21,128.56,133.92,139.28,144.63,149.99,155.34,160.7,166.05,171.41,176.76,182.12,187.48,192.83,198.19,203.54,208.9,214.25,219.61,224.97,230.32,235.68,241.03,246.39,251.74,257.1,262.46,267.81,273.17,278.52,283.88,289.23,294.59,299.94,305.3,310.66,316.01,321.37,326.72,332.08,337.43,342.79,348.15,353.5,358.86,364.21,369.57,374.92,380.28,385.63,390.99,396.35,401.7,407.06,412.41,417.77,423.12,428.48,433.84,439.19,444.55,449.9,455.26,460.61,465.97,471.33,476.68,482.04,487.39,492.75,498.1,503.46,508.81,514.17,519.53,524.88,530.24,535.59,540.95,546.3,551.66,557.02,562.37,567.73,573.08,578.44,583.79,589.15,594.51,599.86,605.22,610.57,615.93,621.28,626.64,631.99,-648.34,-642.98,-637.63,-632.27,-626.92,-621.56,-616.2,-610.85,-605.49,-600.14,-594.78,-589.43,-584.07,-578.71,-573.36,-568.0,-562.65,-557.29,-551.94,-546.58,-541.22,-535.87,-530.51,-525.16,-519.8,-514.45,-509.09,-503.74,-498.38,-493.02,-487.67,-482.31,-476.96,-471.6,-466.25,-460.89,-455.53,-450.18,-444.82,-439.47,-434.11,-428.76,-423.4,-418.04,-412.69,-407.33,-401.98,-396.62,-391.27,-385.91,-380.56,-375.2,-369.84,-364.49,-359.13,-353.78,-348.42,-343.07,-337.71,-332.35,-327.0,-321.64,-316.29,-310.93,-305.58,-300.22,-294.87,-289.51,-284.15,-278.8,-273.44,-268.09,-262.73,-257.38,-252.02,-246.66,-241.31,-235.95,-230.6,-225.24,-219.89,-214.53,-209.17,-203.82,-198.46,-193.11,-187.75,-182.4,-177.04,-171.69,-166.33,-160.97,-155.62,-150.26,-144.91,-139.55,-134.2,-128.84,-123.48,-118.13,-112.77,-107.42,-102.06,-96.71,-91.35,-85.99,-80.64,-75.28,-69.93,-64.57,-59.22,-53.86,-48.51,-43.15,-37.79,-32.44,-27.08,-21.73,-16.37,-11.02,-5.66,-0.3,5.05,10.41,15.76,21.12,26.47,31.83,37.19,42.54,47.9,53.25,58.61,63.96,69.32,74.67,80.03,85.39,90.74,96.1,101.45,106.81,112.16,117.52,122.88,128.23,133.59,138.94,144.3,149.65,155.01,160.37,165.72,171.08,176.43,181.79,187.14,192.5,197.85,203.21,208.57,213.92,219.28,224.63,229.99,235.34,240.7,246.06,251.41,256.77,262.12,267.48,272.83,278.19,283.54,288.9,294.26,299.61,304.97,310.32,315.68,321.03,326.39,331.75,337.1,342.46,347.81,353.17,358.52,363.88,369.24,374.59,379.95,385.3,390.66,396.01,401.37,406.72,412.08,417.44,422.79,428.15,433.5,438.86,444.21,449.57,454.93,460.28,465.64,470.99,476.35,481.7,487.06,492.42,497.77,503.13,508.48,513.84,519.19,524.55,529.9,535.26,540.62,545.97,551.33,556.68,562.04,567.39,572.75,578.11,583.46,588.82,594.17,599.53,604.88,610.24,615.6,620.95,626.31,631.66,-648.61,-643.25,-637.89,-632.54,-627.18,-621.83,-616.47,-611.12,-605.76,-600.4,-595.05,-589.69,-584.34,-578.98,-573.63,-568.27,-562.91,-557.56,-552.2,-546.85,-541.49,-536.14,-530.78,-525.43,-520.07,-514.71,-509.36,-504.0,-498.65,-493.29,-487.94,-482.58,-477.22,-471.87,-466.51,-461.16,-455.8,-450.45,-445.09,-439.73,-434.38,-429.02,-423.67,-418.31,-412.96,-407.6,-402.25,-396.89,-391.53,-386.18,-380.82,-375.47,-370.11,-364.76,-359.4,-354.04,-348.69,-343.33,-337.98,-332.62,-327.27,-321.91,-316.55,-311.2,-305.84,-300.49,-295.13,-289.78,-284.42,-279.07,-273.71,-268.35,-263.0,-257.64,-252.29,-246.93,-241.58,-236.22,-230.86,-225.51,-220.15,-214.8,-209.44,-204.09,-198.73,-193.37,-188.02,-182.66,-177.31,-171.95,-166.6,-161.24,-155.89,-150.53,-145.17,-139.82,-134.46,-129.11,-123.75,-118.4,-113.04,-107.68,-102.33,-96.97,-91.62,-86.26,-80.91,-75.55,-70.19,-64.84,-59.48,-54.13,-48.77,-43.42,-38.06,-32.71,-27.35,-21.99,-16.64,-11.28,-5.93,-0.57,4.78,10.14,15.5,20.85,26.21,31.56,36.92,42.27,47.63,52.98,58.34,63.7,69.05,74.41,79.76,85.12,90.47,95.83,101.19,106.54,111.9,117.25,122.61,127.96,133.32,138.68,144.03,149.39,154.74,160.1,165.45,170.81,176.16,181.52,186.88,192.23,197.59,202.94,208.3,213.65,219.01,224.37,229.72,235.08,240.43,245.79,251.14,256.5,261.86,267.21,272.57,277.92,283.28,288.63,293.99,299.34,304.7,310.06,315.41,320.77,326.12,331.48,336.83,342.19,347.55,352.9,358.26,363.61,368.97,374.32,379.68,385.04,390.39,395.75,401.1,406.46,411.81,417.17,422.52,427.88,433.24,438.59,443.95,449.3,454.66,460.01,465.37,470.73,476.08,481.44,486.79,492.15,497.5,502.86,508.22,513.57,518.93,524.28,529.64,534.99,540.35,545.7,551.06,556.42,561.77,567.13,572.48,577.84,583.19,588.55,593.91,599.26,604.62,609.97,615.33,620.68,626.04,631.39,-648.8,-643.45,-638.09,-632.74,-627.38,-622.03,-616.67,-611.32,-605.96,-600.6,-595.25,-589.89,-584.54,-579.18,-573.83,-568.47,-563.11,-557.76,-552.4,-547.05,-541.69,-536.34,-530.98,-525.62,-520.27,-514.91,-509.56,-504.2,-498.85,-493.49,-488.14,-482.78,-477.42,-472.07,-466.71,-461.36,-456.0,-450.65,-445.29,-439.93,-434.58,-429.22,-423.87,-418.51,-413.16,-407.8,-402.44,-397.09,-391.73,-386.38,-381.02,-375.67,-370.31,-364.96,-359.6,-354.24,-348.89,-343.53,-338.18,-332.82,-327.47,-322.11,-316.75,-311.4,-306.04,-300.69,-295.33,-289.98,-284.62,-279.26,-273.91,-268.55,-263.2,-257.84,-252.49,-247.13,-241.78,-236.42,-231.06,-225.71,-220.35,-215.0,-209.64,-204.29,-198.93,-193.57,-188.22,-182.86,-177.51,-172.15,-166.8,-161.44,-156.09,-150.73,-145.37,-140.02,-134.66,-129.31,-123.95,-118.6,-113.24,-107.88,-102.53,-97.17,-91.82,-86.46,-81.11,-75.75,-70.39,-65.04,-59.68,-54.33,-48.97,-43.62,-38.26,-32.91,-27.55,-22.19,-16.84,-11.48,-6.13,-0.77,4.58,9.94,15.3,20.65,26.01,31.36,36.72,42.07,47.43,52.79,58.14,63.5,68.85,74.21,79.56,84.92,90.27,95.63,100.99,106.34,111.7,117.05,122.41,127.76,133.12,138.48,143.83,149.19,154.54,159.9,165.25,170.61,175.97,181.32,186.68,192.03,197.39,202.74,208.1,213.45,218.81,224.17,229.52,234.88,240.23,245.59,250.94,256.3,261.66,267.01,272.37,277.72,283.08,288.43,293.79,299.15,304.5,309.86,315.21,320.57,325.92,331.28,336.63,341.99,347.35,352.7,358.06,363.41,368.77,374.12,379.48,384.84,390.19,395.55,400.9,406.26,411.61,416.97,422.33,427.68,433.04,438.39,443.75,449.1,454.46,459.81,465.17,470.53,475.88,481.24,486.59,491.95,497.3,502.66,508.02,513.37,518.73,524.08,529.44,534.79,540.15,545.5,550.86,556.22,561.57,566.93,572.28,577.64,582.99,588.35,593.71,599.06,604.42,609.77,615.13,620.48,625.84,631.2,-648.94,-643.58,-638.22,-632.87,-627.51,-622.16,-616.8,-611.45,-606.09,-600.73,-595.38,-590.02,-584.67,-579.31,-573.96,-568.6,-563.24,-557.89,-552.53,-547.18,-541.82,-536.47,-531.11,-525.76,-520.4,-515.04,-509.69,-504.33,-498.98,-493.62,-488.27,-482.91,-477.55,-472.2,-466.84,-461.49,-456.13,-450.78,-445.42,-440.06,-434.71,-429.35,-424.0,-418.64,-413.29,-407.93,-402.58,-397.22,-391.86,-386.51,-381.15,-375.8,-370.44,-365.09,-359.73,-354.37,-349.02,-343.66,-338.31,-332.95,-327.6,-322.24,-316.88,-311.53,-306.17,-300.82,-295.46,-290.11,-284.75,-279.4,-274.04,-268.68,-263.33,-257.97,-252.62,-247.26,-241.91,-236.55,-231.19,-225.84,-220.48,-215.13,-209.77,-204.42,-199.06,-193.71,-188.35,-182.99,-177.64,-172.28,-166.93,-161.57,-156.22,-150.86,-145.5,-140.15,-134.79,-129.44,-124.08,-118.73,-113.37,-108.01,-102.66,-97.3,-91.95,-86.59,-81.24,-75.88,-70.53,-65.17,-59.81,-54.46,-49.1,-43.75,-38.39,-33.04,-27.68,-22.32,-16.97,-11.61,-6.26,-0.9,4.45,9.81,15.17,20.52,25.88,31.23,36.59,41.94,47.3,52.65,58.01,63.37,68.72,74.08,79.43,84.79,90.14,95.5,100.86,106.21,111.57,116.92,122.28,127.63,132.99,138.35,143.7,149.06,154.41,159.77,165.12,170.48,175.83,181.19,186.55,191.9,197.26,202.61,207.97,213.32,218.68,224.04,229.39,234.75,240.1,245.46,250.81,256.17,261.53,266.88,272.24,277.59,282.95,288.3,293.66,299.01,304.37,309.73,315.08,320.44,325.79,331.15,336.5,341.86,347.22,352.57,357.93,363.28,368.64,373.99,379.35,384.7,390.06,395.42,400.77,406.13,411.48,416.84,422.19,427.55,432.91,438.26,443.62,448.97,454.33,459.68,465.04,470.4,475.75,481.11,486.46,491.82,497.17,502.53,507.88,513.24,518.6,523.95,529.31,534.66,540.02,545.37,550.73,556.09,561.44,566.8,572.15,577.51,582.86,588.22,593.58,598.93,604.29,609.64,615.0,620.35,625.71,631.06,-649.0,-643.64,-638.28,-632.93,-627.57,-622.22,-616.86,-611.51,-606.15,-600.79,-595.44,-590.08,-584.73,-579.37,-574.02,-568.66,-563.31,-557.95,-552.59,-547.24,-541.88,-536.53,-531.17,-525.82,-520.46,-515.1,-509.75,-504.39,-499.04,-493.68,-488.33,-482.97,-477.61,-472.26,-466.9,-461.55,-456.19,-450.84,-445.48,-440.13,-434.77,-429.41,-424.06,-418.7,-413.35,-407.99,-402.64,-397.28,-391.92,-386.57,-381.21,-375.86,-370.5,-365.15,-359.79,-354.43,-349.08,-343.72,-338.37,-333.01,-327.66,-322.3,-316.95,-311.59,-306.23,-300.88,-295.52,-290.17,-284.81,-279.46,-274.1,-268.74,-263.39,-258.03,-252.68,-247.32,-241.97,-236.61,-231.25,-225.9,-220.54,-215.19,-209.83,-204.48,-199.12,-193.77,-188.41,-183.05,-177.7,-172.34,-166.99,-161.63,-156.28,-150.92,-145.56,-140.21,-134.85,-129.5,-124.14,-118.79,-113.43,-108.08,-102.72,-97.36,-92.01,-86.65,-81.3,-75.94,-70.59,-65.23,-59.87,-54.52,-49.16,-43.81,-38.45,-33.1,-27.74,-22.38,-17.03,-11.67,-6.32,-0.96,4.39,9.75,15.1,20.46,25.82,31.17,36.53,41.88,47.24,52.59,57.95,63.31,68.66,74.02,79.37,84.73,90.08,95.44,100.8,106.15,111.51,116.86,122.22,127.57,132.93,138.28,143.64,149.0,154.35,159.71,165.06,170.42,175.77,181.13,186.49,191.84,197.2,202.55,207.91,213.26,218.62,223.98,229.33,234.69,240.04,245.4,250.75,256.11,261.46,266.82,272.18,277.53,282.89,288.24,293.6,298.95,304.31,309.67,315.02,320.38,325.73,331.09,336.44,341.8,347.16,352.51,357.87,363.22,368.58,373.93,379.29,384.64,390.0,395.36,400.71,406.07,411.42,416.78,422.13,427.49,432.85,438.2,443.56,448.91,454.27,459.62,464.98,470.33,475.69,481.05,486.4,491.76,497.11,502.47,507.82,513.18,518.54,523.89,529.25,534.6,539.96,545.31,550.67,556.03,561.38,566.74,572.09,577.45,582.8,588.16,593.51,598.87,604.23,609.58,614.94,620.29,625.65,631.0,-648.99,-643.63,-638.27,-632.92,-627.56,-622.21,-616.85,-611.5,-606.14,-600.78,-595.43,-590.07,-584.72,-579.36,-574.01,-568.65,-563.29,-557.94,-552.58,-547.23,-541.87,-536.52,-531.16,-525.81,-520.45,-515.09,-509.74,-504.38,-499.03,-493.67,-488.32,-482.96,-477.6,-472.25,-466.89,-461.54,-456.18,-450.83,-445.47,-440.11,-434.76,-429.4,-424.05,-418.69,-413.34,-407.98,-402.63,-397.27,-391.91,-386.56,-381.2,-375.85,-370.49,-365.14,-359.78,-354.42,-349.07,-343.71,-338.36,-333.0,-327.65,-322.29,-316.94,-311.58,-306.22,-300.87,-295.51,-290.16,-284.8,-279.45,-274.09,-268.73,-263.38,-258.02,-252.67,-247.31,-241.96,-236.6,-231.24,-225.89,-220.53,-215.18,-209.82,-204.47,-199.11,-193.76,-188.4,-183.04,-177.69,-172.33,-166.98,-161.62,-156.27,-150.91,-145.55,-140.2,-134.84,-129.49,-124.13,-118.78,-113.42,-108.06,-102.71,-97.35,-92.0,-86.64,-81.29,-75.93,-70.58,-65.22,-59.86,-54.51,-49.15,-43.8,-38.44,-33.09,-27.73,-22.37,-17.02,-11.66,-6.31,-0.95,4.4,9.76,15.12,20.47,25.83,31.18,36.54,41.89,47.25,52.6,57.96,63.32,68.67,74.03,79.38,84.74,90.09,95.45,100.81,106.16,111.52,116.87,122.23,127.58,132.94,138.3,143.65,149.01,154.36,159.72,165.07,170.43,175.78,181.14,186.5,191.85,197.21,202.56,207.92,213.27,218.63,223.99,229.34,234.7,240.05,245.41,250.76,256.12,261.47,266.83,272.19,277.54,282.9,288.25,293.61,298.96,304.32,309.68,315.03,320.39,325.74,331.1,336.45,341.81,347.17,352.52,357.88,363.23,368.59,373.94,379.3,384.65,390.01,395.37,400.72,406.08,411.43,416.79,422.14,427.5,432.86,438.21,443.57,448.92,454.28,459.63,464.99,470.35,475.7,481.06,486.41,491.77,497.12,502.48,507.83,513.19,518.55,523.9,529.26,534.61,539.97,545.32,550.68,556.04,561.39,566.75,572.1,577.46,582.81,588.17,593.53,598.88,604.24,609.59,614.95,620.3,625.66,631.01,-648.9,-643.55,-638.19,-632.84,-627.48,-622.13,-616.77,-611.41,-606.06,-600.7,-595.35,-589.99,-584.64,-579.28,-573.93,-568.57,-563.21,-557.86,-552.5,-547.15,-541.79,-536.44,-531.08,-525.72,-520.37,-515.01,-509.66,-504.3,-498.95,-493.59,-488.24,-482.88,-477.52,-472.17,-466.81,-461.46,-456.1,-450.75,-445.39,-440.03,-434.68,-429.32,-423.97,-418.61,-413.26,-407.9,-402.54,-397.19,-391.83,-386.48,-381.12,-375.77,-370.41,-365.06,-359.7,-354.34,-348.99,-343.63,-338.28,-332.92,-327.57,-322.21,-316.85,-311.5,-306.14,-300.79,-295.43,-290.08,-284.72,-279.36,-274.01,-268.65,-263.3,-257.94,-252.59,-247.23,-241.88,-236.52,-231.16,-225.81,-220.45,-215.1,-209.74,-204.39,-199.03,-193.67,-188.32,-182.96,-177.61,-172.25,-166.9,-161.54,-156.18,-150.83,-145.47,-140.12,-134.76,-129.41,-124.05,-118.7,-113.34,-107.98,-102.63,-97.27,-91.92,-86.56,-81.21,-75.85,-70.49,-65.14,-59.78,-54.43,-49.07,-43.72,-38.36,-33.0,-27.65,-22.29,-16.94,-11.58,-6.23,-0.87,4.48,9.84,15.2,20.55,25.91,31.26,36.62,41.97,47.33,52.69,58.04,63.4,68.75,74.11,79.46,84.82,90.18,95.53,100.89,106.24,111.6,116.95,122.31,127.66,133.02,138.38,143.73,149.09,154.44,159.8,165.15,170.51,175.87,181.22,186.58,191.93,197.29,202.64,208.0,213.35,218.71,224.07,229.42,234.78,240.13,245.49,250.84,256.2,261.56,266.91,272.27,277.62,282.98,288.33,293.69,299.05,304.4,309.76,315.11,320.47,325.82,331.18,336.53,341.89,347.25,352.6,357.96,363.31,368.67,374.02,379.38,384.74,390.09,395.45,400.8,406.16,411.51,416.87,422.23,427.58,432.94,438.29,443.65,449.0,454.36,459.71,465.07,470.43,475.78,481.14,486.49,491.85,497.2,502.56,507.92,513.27,518.63,523.98,529.34,534.69,540.05,545.41,550.76,556.12,561.47,566.83,572.18,577.54,582.89,588.25,593.61,598.96,604.32,609.67,615.03,620.38,625.74,631.1,-648.75,-643.4,-638.04,-632.69,-627.33,-621.98,-616.62,-611.26,-605.91,-600.55,-595.2,-589.84,-584.49,-579.13,-573.77,-568.42,-563.06,-557.71,-552.35,-547.0,-541.64,-536.29,-530.93,-525.57,-520.22,-514.86,-509.51,-504.15,-498.8,-493.44,-488.08,-482.73,-477.37,-472.02,-466.66,-461.31,-455.95,-450.59,-445.24,-439.88,-434.53,-429.17,-423.82,-418.46,-413.11,-407.75,-402.39,-397.04,-391.68,-386.33,-380.97,-375.62,-370.26,-364.9,-359.55,-354.19,-348.84,-343.48,-338.13,-332.77,-327.41,-322.06,-316.7,-311.35,-305.99,-300.64,-295.28,-289.93,-284.57,-279.21,-273.86,-268.5,-263.15,-257.79,-252.44,-247.08,-241.72,-236.37,-231.01,-225.66,-220.3,-214.95,-209.59,-204.23,-198.88,-193.52,-188.17,-182.81,-177.46,-172.1,-166.75,-161.39,-156.03,-150.68,-145.32,-139.97,-134.61,-129.26,-123.9,-118.54,-113.19,-107.83,-102.48,-97.12,-91.77,-86.41,-81.06,-75.7,-70.34,-64.99,-59.63,-54.28,-48.92,-43.57,-38.21,-32.85,-27.5,-22.14,-16.79,-11.43,-6.08,-0.72,4.64,9.99,15.35,20.7,26.06,31.41,36.77,42.12,47.48,52.84,58.19,63.55,68.9,74.26,79.61,84.97,90.33,95.68,101.04,106.39,111.75,117.1,122.46,127.82,133.17,138.53,143.88,149.24,154.59,159.95,165.3,170.66,176.02,181.37,186.73,192.08,197.44,202.79,208.15,213.51,218.86,224.22,229.57,234.93,240.28,245.64,251.0,256.35,261.71,267.06,272.42,277.77,283.13,288.48,293.84,299.2,304.55,309.91,315.26,320.62,325.97,331.33,336.69,342.04,347.4,352.75,358.11,363.46,368.82,374.18,379.53,384.89,390.24,395.6,400.95,406.31,411.66,417.02,422.38,427.73,433.09,438.44,443.8,449.15,454.51,459.87,465.22,470.58,475.93,481.29,486.64,492.0,497.35,502.71,508.07,513.42,518.78,524.13,529.49,534.84,540.2,545.56,550.91,556.27,561.62,566.98,572.33,577.69,583.05,588.4,593.76,599.11,604.47,609.82,615.18,620.53,625.89,631.25,-648.53,-643.18,-637.82,-632.47,-627.11,-621.76,-616.4,-611.04,-605.69,-600.33,-594.98,-589.62,-584.27,-578.91,-573.56,-568.2,-562.84,-557.49,-552.13,-546.78,-541.42,-536.07,-530.71,-525.35,-520.0,-514.64,-509.29,-503.93,-498.58,-493.22,-487.86,-482.51,-477.15,-471.8,-466.44,-461.09,-455.73,-450.38,-445.02,-439.66,-434.31,-428.95,-423.6,-418.24,-412.89,-407.53,-402.17,-396.82,-391.46,-386.11,-380.75,-375.4,-370.04,-364.68,-359.33,-353.97,-348.62,-343.26,-337.91,-332.55,-327.2,-321.84,-316.48,-311.13,-305.77,-300.42,-295.06,-289.71,-284.35,-278.99,-273.64,-268.28,-262.93,-257.57,-252.22,-246.86,-241.51,-236.15,-230.79,-225.44,-220.08,-214.73,-209.37,-204.02,-198.66,-193.3,-187.95,-182.59,-177.24,-171.88,-166.53,-161.17,-155.81,-150.46,-145.1,-139.75,-134.39,-129.04,-123.68,-118.33,-112.97,-107.61,-102.26,-96.9,-91.55,-86.19,-80.84,-75.48,-70.12,-64.77,-59.41,-54.06,-48.7,-43.35,-37.99,-32.63,-27.28,-21.92,-16.57,-11.21,-5.86,-0.5,4.85,10.21,15.57,20.92,26.28,31.63,36.99,42.34,47.7,53.06,58.41,63.77,69.12,74.48,79.83,85.19,90.55,95.9,101.26,106.61,111.97,117.32,122.68,128.03,133.39,138.75,144.1,149.46,154.81,160.17,165.52,170.88,176.24,181.59,186.95,192.3,197.66,203.01,208.37,213.73,219.08,224.44,229.79,235.15,240.5,245.86,251.21,256.57,261.93,267.28,272.64,277.99,283.35,288.7,294.06,299.42,304.77,310.13,315.48,320.84,326.19,331.55,336.9,342.26,347.62,352.97,358.33,363.68,369.04,374.39,379.75,385.11,390.46,395.82,401.17,406.53,411.88,417.24,422.6,427.95,433.31,438.66,444.02,449.37,454.73,460.08,465.44,470.8,476.15,481.51,486.86,492.22,497.57,502.93,508.29,513.64,519.0,524.35,529.71,535.06,540.42,545.78,551.13,556.49,561.84,567.2,572.55,577.91,583.26,588.62,593.98,599.33,604.69,610.04,615.4,620.75,626.11,631.47,-648.25,-642.89,-637.54,-632.18,-626.83,-621.47,-616.11,-610.76,-605.4,-600.05,-594.69,-589.34,-583.98,-578.62,-573.27,-567.91,-562.56,-557.2,-551.85,-546.49,-541.13,-535.78,-530.42,-525.07,-519.71,-514.36,-509.0,-503.65,-498.29,-492.93,-487.58,-482.22,-476.87,-471.51,-466.16,-460.8,-455.44,-450.09,-444.73,-439.38,-434.02,-428.67,-423.31,-417.96,-412.6,-407.24,-401.89,-396.53,-391.18,-385.82,-380.47,-375.11,-369.75,-364.4,-359.04,-353.69,-348.33,-342.98,-337.62,-332.26,-326.91,-321.55,-316.2,-310.84,-305.49,-300.13,-294.78,-289.42,-284.06,-278.71,-273.35,-268.0,-262.64,-257.29,-251.93,-246.57,-241.22,-235.86,-230.51,-225.15,-219.8,-214.44,-209.08,-203.73,-198.37,-193.02,-187.66,-182.31,-176.95,-171.6,-166.24,-160.88,-155.53,-150.17,-144.82,-139.46,-134.11,-128.75,-123.39,-118.04,-112.68,-107.33,-101.97,-96.62,-91.26,-85.9,-80.55,-75.19,-69.84,-64.48,-59.13,-53.77,-48.42,-43.06,-37.7,-32.35,-26.99,-21.64,-16.28,-10.93,-5.57,-0.21,5.14,10.5,15.85,21.21,26.56,31.92,37.28,42.63,47.99,53.34,58.7,64.05,69.41,74.76,80.12,85.48,90.83,96.19,101.54,106.9,112.25,117.61,122.97,128.32,133.68,139.03,144.39,149.74,155.1,160.45,165.81,171.17,176.52,181.88,187.23,192.59,197.94,203.3,208.66,214.01,219.37,224.72,230.08,235.43,240.79,246.15,251.5,256.86,262.21,267.57,272.92,278.28,283.63,288.99,294.35,299.7,305.06,310.41,315.77,321.12,326.48,331.84,337.19,342.55,347.9,353.26,358.61,363.97,369.33,374.68,380.04,385.39,390.75,396.1,401.46,406.81,412.17,417.53,422.88,428.24,433.59,438.95,444.3,449.66,455.02,460.37,465.73,471.08,476.44,481.79,487.15,492.51,497.86,503.22,508.57,513.93,519.28,524.64,529.99,535.35,540.71,546.06,551.42,556.77,562.13,567.48,572.84,578.2,583.55,588.91,594.26,599.62,604.97,610.33,615.69,621.04,626.4,631.75,-647.9,-642.54,-637.19,-631.83,-626.47,-621.12,-615.76,-610.41,-605.05,-599.7,-594.34,-588.98,-583.63,-578.27,-572.92,-567.56,-562.21,-556.85,-551.5,-546.14,-540.78,-535.43,-530.07,-524.72,-519.36,-514.01,-508.65,-503.29,-497.94,-492.58,-487.23,-481.87,-476.52,-471.16,-465.8,-460.45,-455.09,-449.74,-444.38,-439.03,-433.67,-428.32,-422.96,-417.6,-412.25,-406.89,-401.54,-396.18,-390.83,-385.47,-380.11,-374.76,-369.4,-364.05,-358.69,-353.34,-347.98,-342.62,-337.27,-331.91,-326.56,-321.2,-315.85,-310.49,-305.14,-299.78,-294.42,-289.07,-283.71,-278.36,-273.0,-267.65,-262.29,-256.93,-251.58,-246.22,-240.87,-235.51,-230.16,-224.8,-219.44,-214.09,-208.73,-203.38,-198.02,-192.67,-187.31,-181.96,-176.6,-171.24,-165.89,-160.53,-155.18,-149.82,-144.47,-139.11,-133.75,-128.4,-123.04,-117.69,-112.33,-106.98,-101.62,-96.26,-90.91,-85.55,-80.2,-74.84,-69.49,-64.13,-58.78,-53.42,-48.06,-42.71,-37.35,-32.0,-26.64,-21.29,-15.93,-10.57,-5.22,0.14,5.49,10.85,16.2,21.56,26.91,32.27,37.63,42.98,48.34,53.69,59.05,64.4,69.76,75.12,80.47,85.83,91.18,96.54,101.89,107.25,112.61,117.96,123.32,128.67,134.03,139.38,144.74,150.09,155.45,160.81,166.16,171.52,176.87,182.23,187.58,192.94,198.3,203.65,209.01,214.36,219.72,225.07,230.43,235.79,241.14,246.5,251.85,257.21,262.56,267.92,273.27,278.63,283.99,289.34,294.7,300.05,305.41,310.76,316.12,321.48,326.83,332.19,337.54,342.9,348.25,353.61,358.97,364.32,369.68,375.03,380.39,385.74,391.1,396.45,401.81,407.17,412.52,417.88,423.23,428.59,433.94,439.3,444.66,450.01,455.37,460.72,466.08,471.43,476.79,482.15,487.5,492.86,498.21,503.57,508.92,514.28,519.63,524.99,530.35,535.7,541.06,546.41,551.77,557.12,562.48,567.84,573.19,578.55,583.9,589.26,594.61,599.97,605.33,610.68,616.04,621.39,626.75,632.1,-647.48,-642.13,-636.77,-631.42,-626.06,-620.71,-615.35,-609.99,-604.64,-599.28,-593.93,-588.57,-583.22,-577.86,-572.5,-567.15,-561.79,-556.44,-551.08,-545.73,-540.37,-535.01,-529.66,-524.3,-518.95,-513.59,-508.24,-502.88,-497.53,-492.17,-486.81,-481.46,-476.1,-470.75,-465.39,-460.04,-454.68,-449.32,-443.97,-438.61,-433.26,-427.9,-422.55,-417.19,-411.84,-406.48,-401.12,-395.77,-390.41,-385.06,-379.7,-374.35,-368.99,-363.63,-358.28,-352.92,-347.57,-342.21,-336.86,-331.5,-326.14,-320.79,-315.43,-310.08,-304.72,-299.37,-294.01,-288.66,-283.3,-277.94,-272.59,-267.23,-261.88,-256.52,-251.17,-245.81,-240.45,-235.1,-229.74,-224.39,-219.03,-213.68,-208.32,-202.96,-197.61,-192.25,-186.9,-181.54,-176.19,-170.83,-165.48,-160.12,-154.76,-149.41,-144.05,-138.7,-133.34,-127.99,-122.63,-117.27,-111.92,-106.56,-101.21,-95.85,-90.5,-85.14,-79.78,-74.43,-69.07,-63.72,-58.36,-53.01,-47.65,-42.3,-36.94,-31.58,-26.23,-20.87,-15.52,-10.16,-4.81,0.55,5.91,11.26,16.62,21.97,27.33,32.68,38.04,43.4,48.75,54.11,59.46,64.82,70.17,75.53,80.88,86.24,91.6,96.95,102.31,107.66,113.02,118.37,123.73,129.09,134.44,139.8,145.15,150.51,155.86,161.22,166.57,171.93,177.29,182.64,188.0,193.35,198.71,204.06,209.42,214.78,220.13,225.49,230.84,236.2,241.55,246.91,252.27,257.62,262.98,268.33,273.69,279.04,284.4,289.75,295.11,300.47,305.82,311.18,316.53,321.89,327.24,332.6,337.96,343.31,348.67,354.02,359.38,364.73,370.09,375.45,380.8,386.16,391.51,396.87,402.22,407.58,412.93,418.29,423.65,429.0,434.36,439.71,445.07,450.42,455.78,461.14,466.49,471.85,477.2,482.56,487.91,493.27,498.63,503.98,509.34,514.69,520.05,525.4,530.76,536.11,541.47,546.83,552.18,557.54,562.89,568.25,573.6,578.96,584.32,589.67,595.03,600.38,605.74,611.09,616.45,621.81,627.16,632.52,-647.01,-641.66,-636.3,-630.94,-625.59,-620.23,-614.88,-609.52,-604.17,-598.81,-593.46,-588.1,-582.74,-577.39,-572.03,-566.68,-561.32,-555.97,-550.61,-545.25,-539.9,-534.54,-529.19,-523.83,-518.48,-513.12,-507.76,-502.41,-497.05,-491.7,-486.34,-480.99,-475.63,-470.28,-464.92,-459.56,-454.21,-448.85,-443.5,-438.14,-432.79,-427.43,-422.07,-416.72,-411.36,-406.01,-400.65,-395.3,-389.94,-384.58,-379.23,-373.87,-368.52,-363.16,-357.81,-352.45,-347.1,-341.74,-336.38,-331.03,-325.67,-320.32,-314.96,-309.61,-304.25,-298.89,-293.54,-288.18,-282.83,-277.47,-272.12,-266.76,-261.4,-256.05,-250.69,-245.34,-239.98,-234.63,-229.27,-223.92,-218.56,-213.2,-207.85,-202.49,-197.14,-191.78,-186.43,-181.07,-175.71,-170.36,-165.0,-159.65,-154.29,-148.94,-143.58,-138.23,-132.87,-127.51,-122.16,-116.8,-111.45,-106.09,-100.74,-95.38,-90.02,-84.67,-79.31,-73.96,-68.6,-63.25,-57.89,-52.53,-47.18,-41.82,-36.47,-31.11,-25.76,-20.4,-15.05,-9.69,-4.33,1.02,6.38,11.73,17.09,22.44,27.8,33.16,38.51,43.87,49.22,54.58,59.93,65.29,70.65,76.0,81.36,86.71,92.07,97.42,102.78,108.13,113.49,118.85,124.2,129.56,134.91,140.27,145.62,150.98,156.34,161.69,167.05,172.4,177.76,183.11,188.47,193.83,199.18,204.54,209.89,215.25,220.6,225.96,231.31,236.67,242.03,247.38,252.74,258.09,263.45,268.8,274.16,279.52,284.87,290.23,295.58,300.94,306.29,311.65,317.01,322.36,327.72,333.07,338.43,343.78,349.14,354.49,359.85,365.21,370.56,375.92,381.27,386.63,391.98,397.34,402.7,408.05,413.41,418.76,424.12,429.47,434.83,440.18,445.54,450.9,456.25,461.61,466.96,472.32,477.67,483.03,488.39,493.74,499.1,504.45,509.81,515.16,520.52,525.88,531.23,536.59,541.94,547.3,552.65,558.01,563.36,568.72,574.08,579.43,584.79,590.14,595.5,600.85,606.21,611.57,616.92,622.28,627.63,632.99],"y":[-324.54,-323.75,-322.89,-321.98,-321.01,-320.0,-318.96,-317.89,-316.79,-315.68,-314.57,-313.46,-312.36,-311.28,-310.23,-309.21,-308.23,-307.31,-306.44,-305.63,-304.9,-304.23,-303.65,-303.15,-302.73,-302.41,-302.18,-302.04,-302.0,-302.05,-302.2,-302.44,-302.78,-303.2,-303.71,-304.31,-304.98,-305.72,-306.54,-307.41,-308.34,-309.32,-310.34,-311.4,-312.48,-313.58,-314.69,-315.81,-316.92,-318.01,-319.08,-320.12,-321.13,-322.08,-322.99,-323.84,-324.62,-325.34,-325.97,-326.53,-327.0,-327.38,-327.68,-327.88,-327.98,-327.99,-327.91,-327.73,-327.45,-327.09,-326.64,-326.1,-325.48,-324.78,-324.01,-323.17,-322.28,-321.33,-320.34,-319.3,-318.24,-317.15,-316.04,-314.93,-313.82,-312.71,-311.63,-310.56,-309.53,-308.54,-307.6,-306.71,-305.89,-305.13,-304.44,-303.83,-303.3,-302.86,-302.51,-302.24,-302.08,-302.0,-302.03,-302.14,-302.35,-302.66,-303.05,-303.54,-304.1,-304.75,-305.47,-306.27,-307.12,-308.04,-309.0,-310.01,-311.05,-312.13,-313.23,-314.33,-315.45,-316.56,-317.66,-318.74,-319.79,-320.8,-321.78,-322.7,-323.57,-324.38,-325.11,-325.77,-326.36,-326.86,-327.27,-327.59,-327.82,-327.96,-328.0,-327.95,-327.8,-327.55,-327.22,-326.79,-326.28,-325.69,-325.01,-324.27,-323.45,-322.58,-321.64,-320.66,-319.64,-318.58,-317.5,-316.4,-315.29,-314.18,-313.07,-311.98,-310.9,-309.86,-308.86,-307.9,-307.0,-306.15,-305.37,-304.65,-304.02,-303.46,-302.99,-302.61,-302.32,-302.12,-302.02,-302.01,-302.09,-302.28,-302.55,-302.92,-303.37,-303.91,-304.53,-305.23,-306.0,-306.84,-307.73,-308.68,-309.68,-310.71,-311.78,-312.87,-313.97,-315.09,-316.2,-317.3,-318.39,-319.45,-320.48,-321.47,-322.41,-323.3,-324.12,-324.88,-325.57,-326.18,-326.7,-327.15,-327.5,-327.76,-327.93,-328.0,-327.97,-327.85,-327.64,-327.34,-326.94,-326.46,-325.89,-325.24,-324.52,-323.72,-322.87,-321.95,-320.99,-319.98,-318.93,-317.86,-316.76,-315.65,-314.54,-313.43,-312.33,-311.25,-310.2,-309.18,-308.21,-307.28,-306.42,-305.61,-320.14,-319.32,-318.44,-317.5,-316.52,-315.49,-314.43,-313.34,-312.24,-311.13,-310.02,-308.91,-307.82,-306.75,-305.71,-304.72,-303.76,-302.86,-302.02,-301.25,-300.55,-299.92,-299.37,-298.91,-298.54,-298.26,-298.07,-297.98,-297.98,-298.08,-298.27,-298.56,-298.94,-299.4,-299.95,-300.58,-301.29,-302.07,-302.91,-303.81,-304.77,-305.77,-306.81,-307.88,-308.97,-310.08,-311.19,-312.3,-313.4,-314.49,-315.55,-316.57,-317.55,-318.49,-319.37,-320.19,-320.94,-321.62,-322.22,-322.73,-323.16,-323.51,-323.75,-323.91,-323.97,-323.94,-323.81,-323.58,-323.26,-322.86,-322.36,-321.79,-321.13,-320.4,-319.6,-318.73,-317.81,-316.84,-315.83,-314.78,-313.7,-312.6,-311.49,-310.38,-309.27,-308.17,-307.09,-306.05,-305.03,-304.07,-303.15,-302.29,-301.49,-300.77,-300.11,-299.54,-299.05,-298.65,-298.34,-298.13,-298.0,-297.97,-298.04,-298.2,-298.46,-298.81,-299.24,-299.76,-300.37,-301.05,-301.81,-302.63,-303.52,-304.45,-305.44,-306.47,-307.53,-308.61,-309.72,-310.83,-311.94,-313.05,-314.14,-315.21,-316.24,-317.24,-318.19,-319.09,-319.93,-320.7,-321.4,-322.03,-322.57,-323.03,-323.4,-323.68,-323.87,-323.96,-323.96,-323.86,-323.66,-323.38,-323.0,-322.53,-321.98,-321.35,-320.64,-319.86,-319.02,-318.12,-317.16,-316.16,-315.12,-314.05,-312.96,-311.85,-310.74,-309.63,-308.52,-307.44,-306.38,-305.36,-304.38,-303.44,-302.56,-301.74,-300.99,-300.32,-299.72,-299.2,-298.77,-298.43,-298.19,-298.03,-297.97,-298.01,-298.14,-298.36,-298.68,-299.09,-299.59,-300.17,-300.82,-301.56,-302.36,-303.22,-304.14,-305.12,-306.13,-307.18,-308.26,-309.36,-310.47,-311.58,-312.69,-313.79,-314.86,-315.91,-316.92,-317.89,-318.81,-319.66,-320.46,-321.19,-321.84,-322.41,-322.89,-323.29,-323.6,-323.82,-323.94,-323.97,-323.9,-323.74,-323.48,-323.13,-322.69,-322.17,-321.56,-320.88,-320.12,-319.3,-318.41,-317.48,-316.49,-315.46,-314.4,-313.31,-312.21,-311.1,-309.99,-308.88,-307.79,-306.72,-305.69,-304.69,-303.74,-302.84,-302.0,-301.23,-315.74,-314.89,-313.98,-313.01,-312.01,-310.97,-309.89,-308.8,-307.69,-306.58,-305.47,-304.37,-303.28,-302.23,-301.21,-300.23,-299.3,-298.43,-297.62,-296.88,-296.21,-295.62,-295.12,-294.7,-294.37,-294.13,-293.99,-293.94,-293.99,-294.13,-294.37,-294.7,-295.12,-295.62,-296.21,-296.88,-297.62,-298.43,-299.3,-300.23,-301.21,-302.23,-303.28,-304.36,-305.46,-306.57,-307.68,-308.79,-309.89,-310.96,-312.0,-313.01,-313.97,-314.88,-315.73,-316.52,-317.24,-317.88,-318.44,-318.92,-319.31,-319.61,-319.81,-319.92,-319.94,-319.86,-319.68,-319.42,-319.06,-318.61,-318.07,-317.46,-316.76,-316.0,-315.17,-314.28,-313.33,-312.34,-311.31,-310.24,-309.15,-308.05,-306.94,-305.83,-304.72,-303.63,-302.57,-301.54,-300.54,-299.6,-298.71,-297.88,-297.11,-296.42,-295.81,-295.27,-294.83,-294.47,-294.2,-294.03,-293.95,-293.96,-294.08,-294.28,-294.58,-294.97,-295.45,-296.01,-296.65,-297.37,-298.16,-299.01,-299.92,-300.88,-301.89,-302.93,-304.01,-305.1,-306.21,-307.32,-308.43,-309.53,-310.61,-311.67,-312.69,-313.66,-314.59,-315.46,-316.27,-317.01,-317.68,-318.27,-318.77,-319.19,-319.52,-319.75,-319.9,-319.94,-319.89,-319.75,-319.51,-319.18,-318.76,-318.26,-317.67,-317.0,-316.26,-315.45,-314.57,-313.64,-312.67,-311.65,-310.59,-309.51,-308.41,-307.3,-306.19,-305.08,-303.98,-302.91,-301.87,-300.86,-299.9,-298.99,-298.14,-297.35,-296.64,-296.0,-295.44,-294.96,-294.57,-294.28,-294.07,-293.96,-293.95,-294.03,-294.2,-294.47,-294.83,-295.28,-295.82,-296.44,-297.13,-297.9,-298.73,-299.62,-300.57,-301.56,-302.59,-303.66,-304.75,-305.85,-306.96,-308.07,-309.18,-310.27,-311.33,-312.36,-313.35,-314.3,-315.19,-316.02,-316.78,-317.47,-318.09,-318.62,-319.06,-319.42,-319.69,-319.86,-319.94,-319.92,-319.81,-319.6,-319.3,-318.91,-318.43,-317.87,-317.22,-316.5,-315.72,-314.86,-313.95,-312.99,-311.98,-310.94,-309.86,-308.77,-307.66,-306.55,-305.44,-304.34,-303.26,-302.2,-301.18,-300.21,-299.28,-298.41,-297.6,-296.86,-311.32,-310.44,-309.5,-308.52,-307.49,-306.44,-305.35,-304.25,-303.14,-302.02,-300.92,-299.83,-298.76,-297.72,-296.72,-295.76,-294.86,-294.01,-293.24,-292.53,-291.9,-291.35,-290.88,-290.5,-290.22,-290.03,-289.93,-289.92,-290.02,-290.2,-290.48,-290.85,-291.31,-291.86,-292.49,-293.19,-293.96,-294.8,-295.7,-296.65,-297.65,-298.69,-299.76,-300.85,-301.95,-303.07,-304.18,-305.28,-306.37,-307.43,-308.45,-309.44,-310.38,-311.26,-312.08,-312.84,-313.52,-314.12,-314.65,-315.08,-315.43,-315.68,-315.85,-315.91,-315.88,-315.76,-315.54,-315.23,-314.83,-314.34,-313.77,-313.11,-312.39,-311.59,-310.73,-309.81,-308.84,-307.83,-306.78,-305.71,-304.61,-303.5,-302.39,-301.28,-300.18,-299.1,-298.05,-297.04,-296.07,-295.14,-294.28,-293.48,-292.75,-292.09,-291.52,-291.02,-290.62,-290.3,-290.08,-289.95,-289.91,-289.98,-290.13,-290.38,-290.72,-291.16,-291.67,-292.27,-292.95,-293.7,-294.52,-295.4,-296.34,-297.32,-298.35,-299.41,-300.49,-301.59,-302.7,-303.82,-304.92,-306.02,-307.09,-308.12,-309.12,-310.08,-310.98,-311.82,-312.6,-313.31,-313.94,-314.49,-314.95,-315.33,-315.61,-315.8,-315.9,-315.9,-315.81,-315.62,-315.34,-314.97,-314.51,-313.96,-313.33,-312.63,-311.85,-311.01,-310.11,-309.16,-308.16,-307.12,-306.06,-304.97,-303.86,-302.75,-301.63,-300.53,-299.45,-298.39,-297.36,-296.38,-295.44,-294.55,-293.73,-292.98,-292.3,-291.69,-291.17,-290.74,-290.39,-290.14,-289.98,-289.92,-289.95,-290.07,-290.29,-290.6,-291.01,-291.5,-292.07,-292.72,-293.45,-294.25,-295.11,-296.03,-297.0,-298.01,-299.06,-300.14,-301.23,-302.34,-303.46,-304.57,-305.66,-306.74,-307.79,-308.8,-309.77,-310.69,-311.56,-312.36,-313.09,-313.74,-314.32,-314.81,-315.22,-315.53,-315.75,-315.88,-315.91,-315.85,-315.69,-315.44,-315.1,-314.66,-314.15,-313.54,-312.87,-312.11,-311.29,-310.41,-309.48,-308.49,-307.46,-306.41,-305.32,-304.22,-303.11,-301.99,-300.89,-299.8,-298.73,-297.69,-296.69,-295.74,-294.83,-293.99,-293.22,-292.51,-306.88,-305.97,-305.02,-304.01,-302.97,-301.9,-300.81,-299.7,-298.59,-297.47,-296.37,-295.29,-294.23,-293.21,-292.23,-291.3,-290.43,-289.61,-288.87,-288.19,-287.6,-287.09,-286.66,-286.33,-286.09,-285.94,-285.89,-285.93,-286.06,-286.29,-286.62,-287.03,-287.53,-288.12,-288.78,-289.51,-290.32,-291.19,-292.11,-293.09,-294.11,-295.16,-296.24,-297.34,-298.45,-299.56,-300.67,-301.76,-302.84,-303.88,-304.89,-305.86,-306.77,-307.63,-308.42,-309.14,-309.79,-310.35,-310.83,-311.23,-311.53,-311.74,-311.86,-311.88,-311.81,-311.64,-311.38,-311.02,-310.58,-310.05,-309.44,-308.75,-307.99,-307.16,-306.27,-305.33,-304.34,-303.31,-302.25,-301.16,-300.06,-298.95,-297.83,-296.73,-295.64,-294.57,-293.54,-292.55,-291.6,-290.7,-289.87,-289.1,-288.4,-287.78,-287.25,-286.79,-286.43,-286.16,-285.98,-285.89,-285.9,-286.01,-286.21,-286.5,-286.89,-287.36,-287.92,-288.55,-289.27,-290.05,-290.9,-291.81,-292.77,-293.77,-294.81,-295.88,-296.98,-298.09,-299.2,-300.31,-301.41,-302.49,-303.55,-304.57,-305.55,-306.48,-307.36,-308.17,-308.91,-309.58,-310.18,-310.69,-311.11,-311.44,-311.69,-311.83,-311.88,-311.84,-311.7,-311.47,-311.15,-310.73,-310.23,-309.65,-308.98,-308.24,-307.44,-306.57,-305.64,-304.67,-303.65,-302.6,-301.52,-300.42,-299.31,-298.19,-297.09,-295.99,-294.92,-293.87,-292.86,-291.9,-290.99,-290.13,-289.34,-288.62,-287.98,-287.41,-286.93,-286.54,-286.23,-286.02,-285.91,-285.89,-285.96,-286.13,-286.4,-286.75,-287.2,-287.73,-288.34,-289.03,-289.79,-290.62,-291.51,-292.45,-293.44,-294.47,-295.53,-296.62,-297.73,-298.84,-299.95,-301.06,-302.15,-303.21,-304.24,-305.24,-306.18,-307.08,-307.91,-308.68,-309.38,-309.99,-310.53,-310.98,-311.35,-311.62,-311.8,-311.88,-311.87,-311.76,-311.56,-311.26,-310.88,-310.4,-309.84,-309.21,-308.49,-307.71,-306.86,-305.95,-304.99,-303.98,-302.94,-301.87,-300.78,-299.67,-298.56,-297.44,-296.34,-295.26,-294.21,-293.19,-292.21,-291.28,-290.4,-289.59,-288.85,-288.18,-302.43,-301.5,-300.52,-299.5,-298.44,-297.36,-296.26,-295.15,-294.03,-292.93,-291.83,-290.76,-289.72,-288.72,-287.76,-286.85,-286.01,-285.22,-284.51,-283.88,-283.32,-282.85,-282.47,-282.18,-281.98,-281.87,-281.86,-281.95,-282.13,-282.41,-282.77,-283.23,-283.77,-284.39,-285.09,-285.86,-286.69,-287.59,-288.54,-289.53,-290.57,-291.63,-292.72,-293.83,-294.94,-296.05,-297.16,-298.24,-299.31,-300.33,-301.32,-302.27,-303.15,-303.98,-304.74,-305.42,-306.03,-306.56,-307.0,-307.35,-307.61,-307.78,-307.85,-307.83,-307.71,-307.5,-307.19,-306.8,-306.31,-305.74,-305.1,-304.37,-303.58,-302.72,-301.81,-300.84,-299.83,-298.79,-297.71,-296.62,-295.51,-294.39,-293.28,-292.19,-291.11,-290.05,-289.04,-288.06,-287.14,-286.27,-285.47,-284.73,-284.07,-283.49,-282.99,-282.58,-282.26,-282.03,-281.9,-281.86,-281.91,-282.06,-282.31,-282.64,-283.07,-283.58,-284.18,-284.85,-285.6,-286.41,-287.29,-288.22,-289.21,-290.23,-291.29,-292.37,-293.47,-294.58,-295.69,-296.8,-297.89,-298.96,-300.01,-301.01,-301.97,-302.87,-303.72,-304.5,-305.21,-305.84,-306.4,-306.87,-307.25,-307.54,-307.74,-307.84,-307.85,-307.76,-307.58,-307.3,-306.93,-306.48,-305.94,-305.31,-304.62,-303.84,-303.01,-302.11,-301.16,-300.17,-299.13,-298.06,-296.97,-295.87,-294.76,-293.64,-292.54,-291.45,-290.39,-289.36,-288.38,-287.43,-286.55,-285.72,-284.96,-284.28,-283.67,-283.15,-282.7,-282.35,-282.09,-281.93,-281.86,-281.88,-282.0,-282.22,-282.52,-282.92,-283.41,-283.98,-284.63,-285.35,-286.14,-287.0,-287.92,-288.88,-289.89,-290.94,-292.01,-293.11,-294.22,-295.33,-296.44,-297.54,-298.62,-299.67,-300.69,-301.66,-302.58,-303.45,-304.25,-304.99,-305.65,-306.23,-306.73,-307.14,-307.46,-307.68,-307.82,-307.86,-307.8,-307.65,-307.4,-307.06,-306.64,-306.12,-305.53,-304.85,-304.1,-303.29,-302.41,-301.47,-300.49,-299.47,-298.41,-297.33,-296.23,-295.12,-294.0,-292.9,-291.8,-290.73,-289.69,-288.69,-287.73,-286.83,-285.98,-285.2,-284.49,-283.86,-297.97,-297.02,-296.02,-294.98,-293.91,-292.81,-291.71,-290.59,-289.48,-288.38,-287.3,-286.24,-285.22,-284.23,-283.3,-282.42,-281.6,-280.85,-280.17,-279.58,-279.06,-278.63,-278.29,-278.04,-277.89,-277.83,-277.86,-278.0,-278.22,-278.54,-278.95,-279.44,-280.02,-280.68,-281.41,-282.21,-283.08,-284.0,-284.97,-285.99,-287.04,-288.11,-289.21,-290.32,-291.44,-292.55,-293.64,-294.72,-295.77,-296.78,-297.74,-298.66,-299.52,-300.32,-301.04,-301.69,-302.26,-302.75,-303.15,-303.46,-303.68,-303.8,-303.83,-303.76,-303.59,-303.34,-302.99,-302.55,-302.03,-301.42,-300.74,-299.98,-299.16,-298.27,-297.33,-296.34,-295.32,-294.26,-293.17,-292.07,-290.96,-289.84,-288.74,-287.65,-286.58,-285.54,-284.55,-283.59,-282.7,-281.86,-281.09,-280.39,-279.76,-279.22,-278.76,-278.39,-278.11,-277.93,-277.84,-277.84,-277.94,-278.14,-278.43,-278.8,-279.27,-279.82,-280.46,-281.17,-281.95,-282.79,-283.69,-284.65,-285.65,-286.69,-287.76,-288.86,-289.96,-291.08,-292.19,-293.29,-294.37,-295.43,-296.45,-297.44,-298.37,-299.25,-300.06,-300.81,-301.49,-302.09,-302.6,-303.03,-303.37,-303.62,-303.77,-303.83,-303.79,-303.66,-303.43,-303.11,-302.7,-302.21,-301.63,-300.97,-300.23,-299.43,-298.56,-297.64,-296.67,-295.65,-294.6,-293.52,-292.43,-291.32,-290.2,-289.09,-288.0,-286.92,-285.88,-284.86,-283.9,-282.98,-282.12,-281.33,-280.6,-279.95,-279.38,-278.9,-278.5,-278.19,-277.98,-277.86,-277.83,-277.9,-278.06,-278.32,-278.67,-279.11,-279.64,-280.24,-280.93,-281.69,-282.51,-283.4,-284.34,-285.32,-286.35,-287.41,-288.5,-289.6,-290.71,-291.83,-292.93,-294.02,-295.09,-296.13,-297.12,-298.07,-298.97,-299.81,-300.58,-301.28,-301.9,-302.44,-302.9,-303.27,-303.55,-303.73,-303.82,-303.81,-303.71,-303.51,-303.22,-302.84,-302.38,-301.82,-301.19,-300.48,-299.7,-298.85,-297.95,-296.99,-295.99,-294.95,-293.88,-292.78,-291.68,-290.56,-289.45,-288.35,-287.27,-286.21,-285.19,-284.21,-283.27,-282.4,-281.58,-280.83,-280.16,-279.56,-293.5,-292.52,-291.5,-290.45,-289.37,-288.27,-287.16,-286.04,-284.93,-283.84,-282.77,-281.72,-280.72,-279.76,-278.85,-278.0,-277.21,-276.49,-275.85,-275.29,-274.82,-274.43,-274.13,-273.93,-273.82,-273.8,-273.89,-274.06,-274.33,-274.69,-275.14,-275.68,-276.29,-276.99,-277.75,-278.58,-279.48,-280.42,-281.42,-282.45,-283.51,-284.6,-285.71,-286.82,-287.93,-289.03,-290.12,-291.19,-292.22,-293.21,-294.15,-295.04,-295.87,-296.64,-297.33,-297.94,-298.47,-298.92,-299.28,-299.54,-299.72,-299.79,-299.78,-299.66,-299.46,-299.16,-298.76,-298.29,-297.72,-297.08,-296.36,-295.57,-294.72,-293.81,-292.84,-291.84,-290.79,-289.72,-288.62,-287.52,-286.4,-285.29,-284.19,-283.11,-282.06,-281.04,-280.06,-279.14,-278.27,-277.46,-276.72,-276.05,-275.47,-274.96,-274.55,-274.22,-273.98,-273.84,-273.8,-273.85,-273.99,-274.23,-274.56,-274.98,-275.49,-276.08,-276.75,-277.5,-278.31,-279.18,-280.11,-281.09,-282.11,-283.16,-284.25,-285.35,-286.46,-287.57,-288.68,-289.77,-290.84,-291.89,-292.89,-293.85,-294.76,-295.61,-296.4,-297.11,-297.75,-298.31,-298.79,-299.17,-299.47,-299.67,-299.78,-299.79,-299.71,-299.53,-299.26,-298.9,-298.45,-297.91,-297.3,-296.6,-295.83,-295.0,-294.11,-293.16,-292.17,-291.14,-290.07,-288.98,-287.88,-286.76,-285.65,-284.55,-283.46,-282.4,-281.37,-280.38,-279.43,-278.54,-277.71,-276.95,-276.26,-275.65,-275.12,-274.67,-274.31,-274.05,-273.88,-273.8,-273.82,-273.94,-274.14,-274.45,-274.84,-275.32,-275.88,-276.53,-277.25,-278.04,-278.89,-279.8,-280.77,-281.77,-282.82,-283.89,-284.99,-286.1,-287.21,-288.32,-289.42,-290.5,-291.55,-292.57,-293.55,-294.47,-295.34,-296.15,-296.89,-297.55,-298.14,-298.64,-299.06,-299.38,-299.62,-299.75,-299.8,-299.75,-299.6,-299.36,-299.03,-298.61,-298.1,-297.51,-296.84,-296.09,-295.28,-294.4,-293.47,-292.5,-291.47,-290.42,-289.34,-288.24,-287.13,-286.01,-284.9,-283.81,-282.74,-281.7,-280.69,-279.73,-278.82,-277.97,-277.19,-276.48,-275.84,-275.28,-289.02,-288.02,-286.98,-285.91,-284.82,-283.72,-282.6,-281.49,-280.39,-279.3,-278.24,-277.22,-276.23,-275.29,-274.41,-273.59,-272.84,-272.15,-271.55,-271.03,-270.6,-270.25,-270.0,-269.84,-269.77,-269.8,-269.93,-270.15,-270.46,-270.86,-271.35,-271.93,-272.58,-273.31,-274.11,-274.97,-275.89,-276.85,-277.87,-278.92,-279.99,-281.09,-282.2,-283.31,-284.42,-285.52,-286.6,-287.65,-288.66,-289.63,-290.55,-291.41,-292.21,-292.94,-293.6,-294.17,-294.67,-295.07,-295.39,-295.61,-295.74,-295.77,-295.71,-295.55,-295.3,-294.95,-294.52,-294.0,-293.4,-292.72,-291.97,-291.15,-290.27,-289.33,-288.35,-287.32,-286.26,-285.18,-284.08,-282.96,-281.85,-280.74,-279.65,-278.58,-277.55,-276.55,-275.59,-274.69,-273.85,-273.07,-272.37,-271.74,-271.19,-270.73,-270.35,-270.07,-269.88,-269.78,-269.78,-269.88,-270.07,-270.35,-270.72,-271.18,-271.73,-272.36,-273.06,-273.84,-274.68,-275.58,-276.54,-277.53,-278.57,-279.64,-280.73,-281.84,-282.95,-284.06,-285.17,-286.25,-287.31,-288.34,-289.32,-290.26,-291.14,-291.96,-292.71,-293.39,-294.0,-294.52,-294.95,-295.29,-295.55,-295.7,-295.77,-295.74,-295.61,-295.39,-295.08,-294.67,-294.18,-293.6,-292.95,-292.22,-291.42,-290.56,-289.64,-288.67,-287.66,-286.61,-285.53,-284.44,-283.33,-282.21,-281.1,-280.01,-278.93,-277.88,-276.87,-275.9,-274.98,-274.12,-273.32,-272.59,-271.93,-271.36,-270.87,-270.46,-270.15,-269.93,-269.8,-269.77,-269.84,-269.99,-270.25,-270.59,-271.02,-271.54,-272.15,-272.83,-273.58,-274.4,-275.28,-276.22,-277.21,-278.23,-279.29,-280.38,-281.48,-282.59,-283.7,-284.81,-285.9,-286.97,-288.01,-289.01,-289.96,-290.86,-291.7,-292.48,-293.18,-293.81,-294.36,-294.82,-295.19,-295.47,-295.66,-295.76,-295.76,-295.66,-295.47,-295.19,-294.81,-294.35,-293.8,-293.17,-292.47,-291.69,-290.85,-289.95,-288.99,-287.99,-286.95,-285.88,-284.79,-283.69,-282.57,-281.46,-280.36,-279.27,-278.22,-277.19,-276.21,-275.27,-274.39,-273.57,-272.82,-272.14,-271.54,-271.02,-284.52,-283.51,-282.45,-281.37,-280.28,-279.16,-278.05,-276.94,-275.85,-274.77,-273.73,-272.72,-271.76,-270.84,-269.99,-269.2,-268.48,-267.83,-267.27,-266.79,-266.39,-266.09,-265.88,-265.77,-265.74,-265.82,-265.99,-266.25,-266.61,-267.05,-267.58,-268.2,-268.88,-269.65,-270.47,-271.36,-272.31,-273.3,-274.33,-275.39,-276.48,-277.58,-278.69,-279.81,-280.91,-282.0,-283.07,-284.1,-285.09,-286.04,-286.93,-287.77,-288.54,-289.23,-289.85,-290.39,-290.84,-291.2,-291.47,-291.65,-291.73,-291.72,-291.61,-291.41,-291.12,-290.73,-290.26,-289.7,-289.06,-288.35,-287.56,-286.71,-285.81,-284.85,-283.84,-282.8,-281.73,-280.63,-279.53,-278.41,-277.3,-276.2,-275.12,-274.06,-273.04,-272.06,-271.13,-270.26,-269.45,-268.7,-268.03,-267.44,-266.93,-266.51,-266.18,-265.94,-265.79,-265.74,-265.79,-265.92,-266.16,-266.48,-266.9,-267.4,-267.99,-268.65,-269.39,-270.2,-271.07,-272.0,-272.97,-273.99,-275.04,-276.12,-277.22,-278.33,-279.45,-280.55,-281.65,-282.72,-283.77,-284.78,-285.74,-286.65,-287.5,-288.29,-289.01,-289.66,-290.22,-290.7,-291.09,-291.4,-291.6,-291.72,-291.74,-291.66,-291.49,-291.22,-290.87,-290.42,-289.89,-289.28,-288.59,-287.83,-287.0,-286.11,-285.16,-284.17,-283.14,-282.08,-280.99,-279.89,-278.77,-277.66,-276.56,-275.47,-274.4,-273.37,-272.38,-271.43,-270.54,-269.7,-268.94,-268.24,-267.62,-267.09,-266.64,-266.28,-266.01,-265.83,-265.75,-265.76,-265.87,-266.07,-266.37,-266.76,-267.23,-267.79,-268.43,-269.14,-269.93,-270.78,-271.69,-272.65,-273.65,-274.7,-275.77,-276.86,-277.97,-279.09,-280.2,-281.3,-282.38,-283.43,-284.45,-285.43,-286.36,-287.23,-288.05,-288.79,-289.46,-290.05,-290.56,-290.98,-291.31,-291.55,-291.69,-291.74,-291.7,-291.55,-291.32,-290.99,-290.58,-290.07,-289.49,-288.82,-288.08,-287.27,-286.4,-285.47,-284.5,-283.48,-282.43,-281.34,-280.24,-279.13,-278.02,-276.91,-275.82,-274.74,-273.7,-272.69,-271.73,-270.82,-269.97,-269.18,-268.46,-267.82,-267.25,-266.77,-280.02,-278.99,-277.92,-276.83,-275.73,-274.61,-273.5,-272.4,-271.31,-270.25,-269.22,-268.23,-267.29,-266.4,-265.58,-264.82,-264.14,-263.53,-263.0,-262.56,-262.21,-261.95,-261.79,-261.72,-261.74,-261.86,-262.07,-262.38,-262.78,-263.26,-263.83,-264.48,-265.21,-266.0,-266.86,-267.77,-268.74,-269.75,-270.79,-271.87,-272.97,-274.07,-275.19,-276.3,-277.4,-278.48,-279.53,-280.54,-281.52,-282.44,-283.31,-284.11,-284.84,-285.5,-286.08,-286.58,-286.99,-287.31,-287.54,-287.67,-287.71,-287.65,-287.5,-287.26,-286.92,-286.49,-285.98,-285.38,-284.71,-283.96,-283.14,-282.26,-281.33,-280.35,-279.33,-278.27,-277.19,-276.08,-274.97,-273.86,-272.75,-271.66,-270.59,-269.55,-268.55,-267.59,-266.69,-265.84,-265.06,-264.35,-263.72,-263.16,-262.69,-262.31,-262.03,-261.83,-261.73,-261.72,-261.81,-261.99,-262.27,-262.64,-263.1,-263.64,-264.26,-264.96,-265.73,-266.57,-267.47,-268.42,-269.42,-270.45,-271.52,-272.61,-273.71,-274.83,-275.94,-277.04,-278.13,-279.19,-280.22,-281.21,-282.15,-283.03,-283.86,-284.61,-285.3,-285.9,-286.43,-286.87,-287.22,-287.48,-287.64,-287.71,-287.68,-287.56,-287.35,-287.04,-286.64,-286.15,-285.58,-284.93,-284.21,-283.41,-282.56,-281.64,-280.67,-279.66,-278.62,-277.54,-276.44,-275.33,-274.22,-273.11,-272.01,-270.93,-269.88,-268.87,-267.9,-266.97,-266.11,-265.31,-264.57,-263.91,-263.33,-262.84,-262.43,-262.11,-261.88,-261.75,-261.71,-261.77,-261.92,-262.17,-262.51,-262.94,-263.45,-264.05,-264.73,-265.48,-266.29,-267.17,-268.11,-269.09,-270.11,-271.17,-272.25,-273.35,-274.47,-275.58,-276.69,-277.78,-278.85,-279.89,-280.89,-281.85,-282.75,-283.6,-284.38,-285.08,-285.72,-286.27,-286.74,-287.11,-287.4,-287.6,-287.7,-287.7,-287.61,-287.43,-287.15,-286.78,-286.32,-285.78,-285.15,-284.45,-283.68,-282.84,-281.94,-280.99,-279.99,-278.96,-277.89,-276.8,-275.69,-274.58,-273.47,-272.37,-271.28,-270.22,-269.19,-268.21,-267.27,-266.38,-265.56,-264.8,-264.12,-263.51,-262.99,-262.55,-275.51,-274.46,-273.38,-272.28,-271.17,-270.06,-268.95,-267.85,-266.78,-265.73,-264.72,-263.75,-262.84,-261.98,-261.19,-260.46,-259.81,-259.24,-258.75,-258.36,-258.05,-257.83,-257.71,-257.69,-257.76,-257.92,-258.18,-258.53,-258.97,-259.49,-260.1,-260.78,-261.54,-262.37,-263.25,-264.19,-265.18,-266.21,-267.27,-268.35,-269.46,-270.57,-271.68,-272.79,-273.88,-274.95,-275.98,-276.98,-277.93,-278.83,-279.66,-280.43,-281.13,-281.76,-282.3,-282.76,-283.12,-283.4,-283.59,-283.67,-283.67,-283.57,-283.37,-283.08,-282.7,-282.23,-281.68,-281.05,-280.34,-279.55,-278.71,-277.8,-276.85,-275.84,-274.8,-273.73,-272.64,-271.53,-270.42,-269.31,-268.21,-267.12,-266.07,-265.04,-264.06,-263.13,-262.25,-261.44,-260.69,-260.01,-259.42,-258.9,-258.48,-258.14,-257.89,-257.74,-257.68,-257.72,-257.86,-258.08,-258.4,-258.81,-259.31,-259.89,-260.55,-261.29,-262.09,-262.96,-263.88,-264.85,-265.87,-266.92,-268.0,-269.1,-270.21,-271.32,-272.43,-273.53,-274.6,-275.65,-276.66,-277.63,-278.54,-279.4,-280.19,-280.92,-281.56,-282.13,-282.62,-283.02,-283.32,-283.54,-283.66,-283.68,-283.61,-283.44,-283.18,-282.83,-282.39,-281.87,-281.26,-280.57,-279.81,-278.99,-278.1,-277.16,-276.17,-275.15,-274.08,-273.0,-271.89,-270.78,-269.67,-268.56,-267.47,-266.41,-265.37,-264.38,-263.43,-262.53,-261.69,-260.92,-260.22,-259.6,-259.06,-258.6,-258.24,-257.96,-257.78,-257.69,-257.7,-257.8,-258.0,-258.29,-258.67,-259.14,-259.7,-260.33,-261.04,-261.82,-262.67,-263.58,-264.53,-265.54,-266.58,-267.65,-268.74,-269.85,-270.96,-272.07,-273.17,-274.26,-275.31,-276.34,-277.32,-278.25,-279.13,-279.94,-280.69,-281.36,-281.96,-282.47,-282.9,-283.23,-283.48,-283.63,-283.68,-283.64,-283.51,-283.28,-282.96,-282.55,-282.05,-281.47,-280.8,-280.07,-279.26,-278.4,-277.47,-276.5,-275.48,-274.43,-273.35,-272.25,-271.14,-270.03,-268.92,-267.82,-266.75,-265.7,-264.69,-263.73,-262.81,-261.96,-261.17,-260.44,-259.79,-259.23,-258.74,-258.35,-270.99,-269.93,-268.84,-267.73,-266.62,-265.51,-264.4,-263.32,-262.25,-261.22,-260.23,-259.29,-258.4,-257.57,-256.81,-256.12,-255.5,-254.97,-254.53,-254.17,-253.91,-253.74,-253.66,-253.68,-253.79,-254.0,-254.3,-254.69,-255.17,-255.74,-256.38,-257.1,-257.89,-258.75,-259.66,-260.62,-261.63,-262.67,-263.75,-264.84,-265.95,-267.06,-268.18,-269.27,-270.35,-271.41,-272.43,-273.4,-274.33,-275.2,-276.01,-276.74,-277.41,-277.99,-278.5,-278.91,-279.24,-279.47,-279.61,-279.65,-279.6,-279.46,-279.22,-278.88,-278.46,-277.95,-277.36,-276.69,-275.95,-275.14,-274.26,-273.33,-272.35,-271.33,-270.28,-269.19,-268.09,-266.98,-265.87,-264.76,-263.67,-262.6,-261.55,-260.55,-259.59,-258.68,-257.83,-257.05,-256.33,-255.69,-255.14,-254.66,-254.28,-253.98,-253.78,-253.67,-253.66,-253.74,-253.92,-254.19,-254.56,-255.01,-255.55,-256.17,-256.86,-257.63,-258.46,-259.36,-260.3,-261.3,-262.33,-263.4,-264.49,-265.59,-266.7,-267.82,-268.92,-270.01,-271.07,-272.1,-273.09,-274.03,-274.92,-275.75,-276.51,-277.2,-277.81,-278.34,-278.79,-279.14,-279.41,-279.58,-279.65,-279.63,-279.51,-279.31,-279.0,-278.61,-278.13,-277.56,-276.92,-276.2,-275.41,-274.55,-273.64,-272.67,-271.67,-270.62,-269.55,-268.45,-267.34,-266.23,-265.12,-264.02,-262.94,-261.89,-260.87,-259.89,-258.97,-258.1,-257.29,-256.56,-255.89,-255.31,-254.81,-254.39,-254.07,-253.84,-253.7,-253.65,-253.71,-253.85,-254.1,-254.43,-254.85,-255.36,-255.96,-256.63,-257.37,-258.19,-259.06,-259.99,-260.97,-261.99,-263.05,-264.13,-265.23,-266.34,-267.46,-268.56,-269.66,-270.73,-271.77,-272.77,-273.73,-274.64,-275.49,-276.27,-276.99,-277.62,-278.18,-278.65,-279.04,-279.33,-279.53,-279.64,-279.65,-279.56,-279.38,-279.11,-278.75,-278.29,-277.75,-277.14,-276.44,-275.67,-274.84,-273.94,-272.99,-272.0,-270.96,-269.9,-268.81,-267.7,-266.59,-265.48,-264.37,-263.29,-262.23,-261.2,-260.21,-259.26,-258.38,-257.55,-256.79,-256.1,-255.49,-254.96,-254.52,-254.16,-266.47,-265.39,-264.29,-263.18,-262.07,-260.96,-259.86,-258.78,-257.74,-256.72,-255.75,-254.83,-253.97,-253.17,-252.44,-251.79,-251.22,-250.72,-250.32,-250.01,-249.79,-249.66,-249.63,-249.69,-249.85,-250.1,-250.45,-250.88,-251.4,-252.0,-252.68,-253.44,-254.26,-255.14,-256.08,-257.06,-258.09,-259.15,-260.23,-261.33,-262.45,-263.56,-264.67,-265.76,-266.82,-267.86,-268.86,-269.81,-270.72,-271.56,-272.33,-273.04,-273.67,-274.21,-274.67,-275.05,-275.33,-275.52,-275.61,-275.61,-275.52,-275.33,-275.04,-274.67,-274.21,-273.66,-273.03,-272.32,-271.55,-270.7,-269.8,-268.85,-267.85,-266.81,-265.74,-264.65,-263.54,-262.43,-261.32,-260.22,-259.13,-258.07,-257.05,-256.06,-255.13,-254.25,-253.43,-252.67,-251.99,-251.39,-250.87,-250.44,-250.1,-249.85,-249.69,-249.63,-249.66,-249.79,-250.01,-250.33,-250.73,-251.22,-251.8,-252.45,-253.18,-253.98,-254.85,-255.77,-256.74,-257.75,-258.8,-259.88,-260.97,-262.08,-263.2,-264.31,-265.4,-266.48,-267.53,-268.54,-269.51,-270.43,-271.29,-272.09,-272.82,-273.47,-274.04,-274.53,-274.94,-275.25,-275.47,-275.59,-275.62,-275.56,-275.4,-275.15,-274.8,-274.36,-273.84,-273.24,-272.56,-271.8,-270.98,-270.1,-269.16,-268.18,-267.15,-266.09,-265.01,-263.9,-262.79,-261.68,-260.57,-259.48,-258.41,-257.38,-256.38,-255.42,-254.52,-253.68,-252.91,-252.21,-251.58,-251.03,-250.57,-250.2,-249.92,-249.73,-249.64,-249.64,-249.74,-249.93,-250.21,-250.59,-251.05,-251.6,-252.23,-252.94,-253.72,-254.56,-255.46,-256.42,-257.42,-258.46,-259.53,-260.62,-261.72,-262.84,-263.95,-265.05,-266.13,-267.19,-268.22,-269.2,-270.14,-271.02,-271.84,-272.59,-273.27,-273.87,-274.38,-274.82,-275.16,-275.41,-275.56,-275.62,-275.59,-275.46,-275.24,-274.92,-274.52,-274.02,-273.44,-272.79,-272.06,-271.26,-270.39,-269.47,-268.5,-267.49,-266.44,-265.36,-264.26,-263.15,-262.04,-260.93,-259.83,-258.76,-257.71,-256.7,-255.73,-254.81,-253.95,-253.15,-252.43,-251.77,-251.2,-250.71,-250.31,-250.0,-261.93,-260.85,-259.74,-258.63,-257.52,-256.41,-255.32,-254.26,-253.23,-252.23,-251.29,-250.39,-249.56,-248.79,-248.1,-247.48,-246.94,-246.49,-246.13,-245.86,-245.69,-245.6,-245.62,-245.73,-245.93,-246.22,-246.61,-247.09,-247.64,-248.28,-249.0,-249.79,-250.64,-251.54,-252.51,-253.51,-254.55,-255.63,-256.72,-257.83,-258.94,-260.05,-261.15,-262.23,-263.29,-264.31,-265.29,-266.22,-267.09,-267.9,-268.64,-269.31,-269.9,-270.41,-270.83,-271.16,-271.4,-271.55,-271.6,-271.55,-271.41,-271.18,-270.85,-270.43,-269.93,-269.34,-268.68,-267.94,-267.13,-266.26,-265.33,-264.35,-263.34,-262.28,-261.2,-260.1,-258.99,-257.88,-256.77,-255.67,-254.6,-253.56,-252.55,-251.59,-250.68,-249.82,-249.03,-248.32,-247.67,-247.11,-246.63,-246.24,-245.94,-245.73,-245.62,-245.6,-245.68,-245.85,-246.12,-246.48,-246.92,-247.45,-248.07,-248.76,-249.52,-250.35,-251.24,-252.19,-253.18,-254.21,-255.27,-256.36,-257.47,-258.58,-259.69,-260.8,-261.89,-262.95,-263.98,-264.97,-265.92,-266.81,-267.65,-268.41,-269.1,-269.72,-270.26,-270.71,-271.07,-271.34,-271.51,-271.59,-271.58,-271.47,-271.26,-270.97,-270.58,-270.1,-269.54,-268.9,-268.18,-267.4,-266.55,-265.64,-264.68,-263.67,-262.63,-261.55,-260.46,-259.35,-258.24,-257.13,-256.03,-254.95,-253.89,-252.87,-251.89,-250.97,-250.09,-249.28,-248.54,-247.87,-247.28,-246.78,-246.36,-246.03,-245.79,-245.65,-245.6,-245.64,-245.79,-246.02,-246.35,-246.77,-247.27,-247.86,-248.53,-249.27,-250.08,-250.95,-251.88,-252.85,-253.87,-254.93,-256.01,-257.11,-258.22,-259.33,-260.44,-261.53,-262.61,-263.65,-264.66,-265.62,-266.53,-267.38,-268.17,-268.89,-269.53,-270.09,-270.57,-270.96,-271.26,-271.46,-271.58,-271.59,-271.51,-271.34,-271.07,-270.71,-270.27,-269.73,-269.12,-268.42,-267.66,-266.83,-265.94,-264.99,-264.0,-262.97,-261.9,-260.82,-259.71,-258.6,-257.49,-256.38,-255.29,-254.23,-253.2,-252.21,-251.26,-250.37,-249.54,-248.77,-248.08,-247.47,-246.93,-246.48,-246.12,-245.86,-257.4,-256.3,-255.19,-254.08,-252.97,-251.87,-250.79,-249.74,-248.72,-247.75,-246.83,-245.96,-245.16,-244.43,-243.77,-243.19,-242.69,-242.28,-241.97,-241.74,-241.61,-241.57,-241.63,-241.78,-242.03,-242.37,-242.79,-243.31,-243.91,-244.58,-245.33,-246.15,-247.03,-247.96,-248.94,-249.97,-251.03,-252.11,-253.21,-254.32,-255.43,-256.54,-257.63,-258.7,-259.74,-260.75,-261.7,-262.61,-263.45,-264.23,-264.94,-265.57,-266.12,-266.59,-266.97,-267.26,-267.45,-267.55,-267.56,-267.47,-267.28,-267.01,-266.64,-266.18,-265.63,-265.01,-264.31,-263.54,-262.7,-261.8,-260.85,-259.85,-258.82,-257.75,-256.66,-255.55,-254.44,-253.33,-252.22,-251.14,-250.08,-249.05,-248.06,-247.12,-246.24,-245.41,-244.66,-243.97,-243.37,-242.84,-242.41,-242.06,-241.8,-241.64,-241.57,-241.6,-241.72,-241.94,-242.25,-242.65,-243.13,-243.7,-244.36,-245.08,-245.88,-246.74,-247.65,-248.62,-249.63,-250.68,-251.75,-252.85,-253.96,-255.07,-256.18,-257.28,-258.36,-259.41,-260.43,-261.4,-262.32,-263.18,-263.99,-264.72,-265.38,-265.95,-266.45,-266.86,-267.18,-267.4,-267.53,-267.57,-267.51,-267.35,-267.11,-266.77,-266.34,-265.82,-265.22,-264.54,-263.79,-262.98,-262.1,-261.16,-260.18,-259.15,-258.1,-257.01,-255.91,-254.8,-253.69,-252.58,-251.49,-250.42,-249.38,-248.38,-247.42,-246.52,-245.67,-244.9,-244.19,-243.56,-243.01,-242.54,-242.16,-241.87,-241.68,-241.58,-241.58,-241.67,-241.86,-242.14,-242.51,-242.97,-243.51,-244.14,-244.84,-245.61,-246.45,-247.35,-248.3,-249.3,-250.34,-251.4,-252.49,-253.6,-254.71,-255.83,-256.93,-258.01,-259.07,-260.1,-261.09,-262.03,-262.91,-263.73,-264.49,-265.17,-265.78,-266.3,-266.74,-267.08,-267.34,-267.5,-267.57,-267.54,-267.41,-267.2,-266.89,-266.48,-266.0,-265.42,-264.77,-264.04,-263.25,-262.39,-261.47,-260.5,-259.49,-258.44,-257.37,-256.27,-255.16,-254.05,-252.94,-251.84,-250.76,-249.71,-248.7,-247.73,-246.81,-245.94,-245.14,-244.41,-243.75,-243.17,-242.68,-242.27,-241.96,-241.73,-252.85,-251.75,-250.64,-249.53,-248.42,-247.33,-246.26,-245.23,-244.23,-243.28,-242.39,-241.55,-240.78,-240.08,-239.46,-238.92,-238.46,-238.09,-237.82,-237.64,-237.55,-237.56,-237.66,-237.86,-238.15,-238.53,-239.0,-239.55,-240.19,-240.9,-241.68,-242.53,-243.43,-244.39,-245.39,-246.43,-247.5,-248.6,-249.7,-250.82,-251.93,-253.03,-254.11,-255.17,-256.19,-257.17,-258.11,-258.98,-259.8,-260.54,-261.22,-261.81,-262.33,-262.75,-263.09,-263.33,-263.48,-263.54,-263.5,-263.36,-263.14,-262.81,-262.4,-261.9,-261.32,-260.66,-259.93,-259.12,-258.25,-257.33,-256.36,-255.34,-254.29,-253.21,-252.11,-251.0,-249.89,-248.78,-247.68,-246.61,-245.56,-244.55,-243.59,-242.67,-241.81,-241.02,-240.3,-239.65,-239.08,-238.6,-238.2,-237.9,-237.68,-237.57,-237.54,-237.61,-237.78,-238.04,-238.39,-238.84,-239.36,-239.97,-240.66,-241.42,-242.24,-243.13,-244.07,-245.06,-246.09,-247.15,-248.24,-249.34,-250.46,-251.57,-252.67,-253.76,-254.83,-255.86,-256.86,-257.81,-258.7,-259.54,-260.31,-261.01,-261.63,-262.17,-262.62,-262.99,-263.26,-263.45,-263.53,-263.52,-263.42,-263.22,-262.93,-262.55,-262.07,-261.52,-260.88,-260.17,-259.39,-258.54,-257.64,-256.68,-255.67,-254.63,-253.56,-252.47,-251.36,-250.25,-249.14,-248.04,-246.95,-245.9,-244.87,-243.89,-242.96,-242.09,-241.27,-240.53,-239.85,-239.26,-238.75,-238.32,-237.99,-237.74,-237.59,-237.54,-237.58,-237.72,-237.95,-238.27,-238.68,-239.18,-239.77,-240.43,-241.16,-241.97,-242.84,-243.76,-244.74,-245.75,-246.81,-247.88,-248.98,-250.09,-251.21,-252.32,-253.41,-254.49,-255.53,-256.54,-257.51,-258.42,-259.28,-260.07,-260.79,-261.44,-262.0,-262.49,-262.88,-263.19,-263.4,-263.51,-263.54,-263.46,-263.29,-263.03,-262.68,-262.24,-261.71,-261.1,-260.41,-259.65,-258.82,-257.94,-256.99,-256.0,-254.97,-253.91,-252.82,-251.72,-250.61,-249.5,-248.39,-247.3,-246.24,-245.2,-244.21,-243.26,-242.36,-241.53,-240.76,-240.06,-239.44,-238.9,-238.45,-238.09,-237.81,-237.63,-248.31,-247.2,-246.09,-244.98,-243.88,-242.8,-241.74,-240.73,-239.75,-238.83,-237.96,-237.15,-236.41,-235.75,-235.16,-234.66,-234.25,-233.92,-233.69,-233.55,-233.51,-233.56,-233.71,-233.95,-234.29,-234.71,-235.22,-235.81,-236.48,-237.23,-238.04,-238.92,-239.85,-240.83,-241.85,-242.9,-243.99,-245.09,-246.2,-247.31,-248.42,-249.51,-250.58,-251.63,-252.63,-253.59,-254.5,-255.34,-256.13,-256.84,-257.48,-258.04,-258.51,-258.89,-259.19,-259.39,-259.49,-259.5,-259.42,-259.24,-258.97,-258.6,-258.15,-257.61,-256.99,-256.29,-255.53,-254.69,-253.8,-252.85,-251.85,-250.82,-249.75,-248.67,-247.56,-246.45,-245.34,-244.23,-243.14,-242.08,-241.05,-240.06,-239.12,-238.23,-237.4,-236.64,-235.96,-235.34,-234.82,-234.37,-234.02,-233.76,-233.59,-233.51,-233.54,-233.65,-233.86,-234.17,-234.56,-235.04,-235.61,-236.26,-236.98,-237.77,-238.63,-239.54,-240.5,-241.51,-242.56,-243.63,-244.73,-245.84,-246.95,-248.06,-249.16,-250.24,-251.29,-252.31,-253.28,-254.21,-255.08,-255.88,-256.62,-257.28,-257.86,-258.36,-258.78,-259.1,-259.33,-259.47,-259.51,-259.46,-259.31,-259.07,-258.73,-258.31,-257.8,-257.2,-256.53,-255.78,-254.97,-254.09,-253.16,-252.18,-251.16,-250.1,-249.02,-247.92,-246.81,-245.7,-244.59,-243.49,-242.42,-241.38,-240.38,-239.42,-238.51,-237.67,-236.88,-236.17,-235.53,-234.98,-234.51,-234.12,-233.83,-233.63,-233.53,-233.52,-233.6,-233.79,-234.06,-234.42,-234.88,-235.42,-236.04,-236.74,-237.51,-238.34,-239.24,-240.19,-241.18,-242.22,-243.28,-244.37,-245.48,-246.59,-247.7,-248.8,-249.89,-250.95,-251.98,-252.97,-253.91,-254.8,-255.63,-256.39,-257.07,-257.68,-258.21,-258.65,-259.01,-259.27,-259.43,-259.51,-259.48,-259.37,-259.15,-258.85,-258.45,-257.97,-257.4,-256.76,-256.03,-255.24,-254.38,-253.47,-252.5,-251.5,-250.45,-249.37,-248.28,-247.17,-246.06,-244.95,-243.85,-242.77,-241.72,-240.7,-239.73,-238.8,-237.93,-237.13,-236.39,-235.73,-235.15,-234.65,-234.24,-233.92,-233.69,-233.55,-243.76,-242.65,-241.53,-240.43,-239.34,-238.27,-237.23,-236.23,-235.28,-234.38,-233.54,-232.77,-232.06,-231.44,-230.89,-230.43,-230.06,-229.77,-229.59,-229.49,-229.49,-229.59,-229.78,-230.07,-230.45,-230.91,-231.46,-232.09,-232.8,-233.57,-234.42,-235.32,-236.27,-237.27,-238.31,-239.38,-240.47,-241.58,-242.69,-243.8,-244.91,-245.99,-247.05,-248.07,-249.06,-249.99,-250.87,-251.69,-252.44,-253.12,-253.72,-254.24,-254.67,-255.01,-255.26,-255.42,-255.48,-255.45,-255.32,-255.09,-254.78,-254.37,-253.88,-253.3,-252.64,-251.91,-251.11,-250.25,-249.33,-248.36,-247.34,-246.29,-245.22,-244.12,-243.01,-241.9,-240.79,-239.69,-238.61,-237.56,-236.55,-235.58,-234.67,-233.81,-233.01,-232.28,-231.63,-231.06,-230.57,-230.17,-229.86,-229.64,-229.51,-229.48,-229.55,-229.71,-229.97,-230.31,-230.75,-231.27,-231.88,-232.56,-233.31,-234.14,-235.02,-235.96,-236.94,-237.97,-239.03,-240.12,-241.22,-242.33,-243.44,-244.55,-245.64,-246.71,-247.75,-248.74,-249.7,-250.59,-251.43,-252.21,-252.91,-253.54,-254.08,-254.54,-254.91,-255.19,-255.38,-255.47,-255.47,-255.37,-255.18,-254.89,-254.51,-254.05,-253.5,-252.87,-252.16,-251.38,-250.54,-249.63,-248.68,-247.68,-246.64,-245.57,-244.48,-243.37,-242.26,-241.14,-240.04,-238.96,-237.9,-236.88,-235.89,-234.96,-234.08,-233.26,-232.51,-231.83,-231.23,-230.72,-230.29,-229.95,-229.7,-229.54,-229.48,-229.52,-229.65,-229.87,-230.19,-230.6,-231.09,-231.67,-232.33,-233.06,-233.86,-234.73,-235.65,-236.62,-237.63,-238.68,-239.76,-240.86,-241.97,-243.08,-244.19,-245.29,-246.37,-247.41,-248.42,-249.39,-250.31,-251.17,-251.96,-252.69,-253.34,-253.91,-254.4,-254.8,-255.11,-255.33,-255.45,-255.48,-255.41,-255.25,-254.99,-254.65,-254.21,-253.68,-253.08,-252.4,-251.64,-250.82,-249.93,-248.99,-248.01,-246.98,-245.92,-244.83,-243.73,-242.62,-241.5,-240.4,-239.31,-238.24,-237.2,-236.21,-235.26,-234.36,-233.52,-232.75,-232.04,-231.42,-230.88,-230.42,-230.05,-229.77,-229.58,-229.49,-239.21,-238.1,-236.98,-235.88,-234.8,-233.75,-232.73,-231.75,-230.82,-229.95,-229.14,-228.4,-227.73,-227.14,-226.63,-226.21,-225.88,-225.65,-225.5,-225.45,-225.5,-225.64,-225.88,-226.21,-226.62,-227.13,-227.72,-228.38,-229.12,-229.93,-230.8,-231.73,-232.71,-233.73,-234.78,-235.86,-236.96,-238.07,-239.19,-240.3,-241.39,-242.46,-243.51,-244.51,-245.48,-246.39,-247.24,-248.03,-248.74,-249.39,-249.95,-250.43,-250.81,-251.11,-251.32,-251.43,-251.45,-251.37,-251.2,-250.93,-250.57,-250.12,-249.59,-248.97,-248.28,-247.52,-246.69,-245.79,-244.85,-243.86,-242.83,-241.76,-240.67,-239.57,-238.46,-237.34,-236.24,-235.15,-234.09,-233.06,-232.06,-231.12,-230.23,-229.39,-228.63,-227.94,-227.32,-226.79,-226.34,-225.98,-225.71,-225.54,-225.46,-225.47,-225.59,-225.79,-226.09,-226.48,-226.96,-227.52,-228.16,-228.88,-229.66,-230.52,-231.43,-232.39,-233.39,-234.44,-235.51,-236.6,-237.71,-238.83,-239.94,-241.04,-242.12,-243.17,-244.19,-245.17,-246.1,-246.97,-247.78,-248.52,-249.19,-249.77,-250.28,-250.7,-251.03,-251.26,-251.41,-251.45,-251.41,-251.26,-251.02,-250.7,-250.28,-249.77,-249.18,-248.51,-247.77,-246.96,-246.09,-245.16,-244.18,-243.16,-242.11,-241.03,-239.93,-238.82,-237.7,-236.6,-235.5,-234.43,-233.39,-232.38,-231.42,-230.51,-229.66,-228.87,-228.15,-227.51,-226.95,-226.48,-226.09,-225.79,-225.58,-225.47,-225.46,-225.54,-225.71,-225.98,-226.34,-226.79,-227.33,-227.94,-228.64,-229.4,-230.23,-231.12,-232.07,-233.06,-234.1,-235.16,-236.25,-237.35,-238.46,-239.58,-240.68,-241.77,-242.83,-243.86,-244.86,-245.8,-246.69,-247.52,-248.29,-248.98,-249.59,-250.13,-250.57,-250.93,-251.2,-251.37,-251.45,-251.43,-251.32,-251.11,-250.81,-250.42,-249.94,-249.38,-248.74,-248.02,-247.23,-246.38,-245.47,-244.51,-243.5,-242.45,-241.38,-240.29,-239.18,-238.07,-236.95,-235.85,-234.77,-233.72,-232.7,-231.72,-230.8,-229.93,-229.12,-228.38,-227.71,-227.12,-226.62,-226.2,-225.88,-225.64,-225.5,-225.45,-234.66,-233.54,-232.44,-231.34,-230.27,-229.24,-228.23,-227.28,-226.38,-225.53,-224.75,-224.04,-223.41,-222.86,-222.4,-222.02,-221.73,-221.54,-221.44,-221.43,-221.53,-221.71,-221.99,-222.36,-222.82,-223.37,-223.99,-224.69,-225.47,-226.31,-227.21,-228.16,-229.15,-230.19,-231.26,-232.35,-233.46,-234.57,-235.68,-236.78,-237.87,-238.93,-239.96,-240.94,-241.88,-242.77,-243.59,-244.34,-245.03,-245.63,-246.15,-246.59,-246.94,-247.19,-247.36,-247.42,-247.39,-247.27,-247.05,-246.74,-246.34,-245.85,-245.28,-244.63,-243.9,-243.11,-242.25,-241.33,-240.36,-239.35,-238.3,-237.22,-236.13,-235.02,-233.9,-232.79,-231.7,-230.62,-229.57,-228.55,-227.58,-226.66,-225.8,-225.0,-224.27,-223.61,-223.03,-222.54,-222.13,-221.81,-221.59,-221.46,-221.43,-221.49,-221.64,-221.89,-222.23,-222.66,-223.18,-223.78,-224.46,-225.21,-226.03,-226.91,-227.84,-228.83,-229.85,-230.91,-231.99,-233.1,-234.21,-235.32,-236.43,-237.52,-238.59,-239.63,-240.63,-241.58,-242.49,-243.33,-244.11,-244.81,-245.44,-245.99,-246.46,-246.84,-247.12,-247.31,-247.41,-247.41,-247.32,-247.13,-246.85,-246.48,-246.02,-245.47,-244.85,-244.15,-243.37,-242.53,-241.63,-240.68,-239.68,-238.64,-237.58,-236.48,-235.38,-234.27,-233.15,-232.05,-230.97,-229.91,-228.88,-227.89,-226.96,-226.07,-225.25,-224.5,-223.81,-223.21,-222.69,-222.25,-221.91,-221.65,-221.49,-221.43,-221.46,-221.58,-221.8,-222.11,-222.51,-223.0,-223.58,-224.23,-224.96,-225.75,-226.62,-227.53,-228.5,-229.51,-230.56,-231.64,-232.74,-233.85,-234.96,-236.07,-237.17,-238.24,-239.29,-240.31,-241.28,-242.2,-243.06,-243.86,-244.59,-245.25,-245.82,-246.32,-246.72,-247.04,-247.26,-247.39,-247.42,-247.36,-247.2,-246.95,-246.61,-246.18,-245.66,-245.06,-244.38,-243.63,-242.81,-241.93,-240.99,-240.01,-238.98,-237.92,-236.84,-235.74,-234.63,-233.51,-232.41,-231.32,-230.25,-229.21,-228.21,-227.25,-226.35,-225.51,-224.73,-224.03,-223.4,-222.85,-222.38,-222.01,-221.72,-221.53,-221.44,-221.44,-230.1,-228.99,-227.89,-226.81,-225.75,-224.73,-223.75,-222.82,-221.94,-221.13,-220.38,-219.71,-219.11,-218.6,-218.18,-217.84,-217.6,-217.45,-217.4,-217.44,-217.57,-217.8,-218.13,-218.54,-219.04,-219.62,-220.28,-221.02,-221.83,-222.69,-223.62,-224.59,-225.61,-226.66,-227.74,-228.84,-229.95,-231.06,-232.17,-233.27,-234.34,-235.39,-236.4,-237.36,-238.28,-239.13,-239.92,-240.65,-241.29,-241.86,-242.34,-242.74,-243.04,-243.25,-243.37,-243.39,-243.32,-243.15,-242.89,-242.54,-242.09,-241.56,-240.95,-240.27,-239.51,-238.68,-237.79,-236.85,-235.86,-234.83,-233.77,-232.68,-231.58,-230.47,-229.35,-228.25,-227.16,-226.09,-225.06,-224.06,-223.11,-222.22,-221.38,-220.62,-219.92,-219.3,-218.76,-218.31,-217.94,-217.67,-217.49,-217.4,-217.41,-217.52,-217.72,-218.01,-218.4,-218.87,-219.42,-220.06,-220.77,-221.56,-222.41,-223.31,-224.27,-225.27,-226.32,-227.39,-228.48,-229.59,-230.7,-231.81,-232.91,-234.0,-235.05,-236.07,-237.05,-237.99,-238.86,-239.67,-240.42,-241.09,-241.68,-242.19,-242.62,-242.95,-243.19,-243.34,-243.4,-243.35,-243.22,-242.98,-242.66,-242.25,-241.75,-241.16,-240.5,-239.76,-238.95,-238.09,-237.16,-236.19,-235.17,-234.12,-233.04,-231.94,-230.83,-229.71,-228.6,-227.51,-226.43,-225.39,-224.38,-223.42,-222.5,-221.65,-220.86,-220.14,-219.49,-218.93,-218.44,-218.05,-217.75,-217.54,-217.42,-217.4,-217.47,-217.64,-217.91,-218.26,-218.7,-219.23,-219.85,-220.53,-221.3,-222.12,-223.01,-223.95,-224.94,-225.98,-227.04,-228.12,-229.23,-230.34,-231.45,-232.56,-233.65,-234.71,-235.75,-236.74,-237.69,-238.58,-239.42,-240.19,-240.88,-241.5,-242.04,-242.49,-242.85,-243.13,-243.3,-243.39,-243.38,-243.27,-243.07,-242.78,-242.39,-241.92,-241.36,-240.72,-240.01,-239.22,-238.37,-237.47,-236.51,-235.5,-234.46,-233.39,-232.3,-231.19,-230.07,-228.96,-227.86,-226.78,-225.72,-224.7,-223.72,-222.79,-221.92,-221.11,-220.36,-219.69,-219.1,-218.59,-218.17,-217.83,-217.59,-217.45,-217.4,-217.44,-225.55,-224.44,-223.35,-222.28,-221.24,-220.24,-219.28,-218.37,-217.52,-216.74,-216.03,-215.39,-214.83,-214.36,-213.98,-213.69,-213.49,-213.38,-213.37,-213.46,-213.64,-213.91,-214.28,-214.73,-215.27,-215.89,-216.59,-217.36,-218.2,-219.09,-220.04,-221.04,-222.07,-223.14,-224.23,-225.33,-226.44,-227.56,-228.66,-229.75,-230.81,-231.84,-232.83,-233.77,-234.66,-235.48,-236.24,-236.93,-237.54,-238.07,-238.51,-238.86,-239.12,-239.29,-239.36,-239.34,-239.22,-239.01,-238.71,-238.31,-237.83,-237.26,-236.61,-235.89,-235.1,-234.24,-233.33,-232.36,-231.35,-230.31,-229.23,-228.14,-227.03,-225.91,-224.8,-223.7,-222.62,-221.57,-220.56,-219.58,-218.66,-217.79,-216.99,-216.25,-215.59,-215.01,-214.51,-214.09,-213.77,-213.54,-213.41,-213.37,-213.42,-213.57,-213.82,-214.15,-214.58,-215.09,-215.68,-216.36,-217.1,-217.92,-218.8,-219.73,-220.71,-221.73,-222.79,-223.87,-224.97,-226.08,-227.2,-228.3,-229.4,-230.47,-231.51,-232.51,-233.47,-234.38,-235.22,-236.0,-236.72,-237.35,-237.91,-238.38,-238.76,-239.05,-239.25,-239.35,-239.36,-239.27,-239.09,-238.81,-238.45,-237.99,-237.45,-236.83,-236.13,-235.36,-234.53,-233.63,-232.68,-231.68,-230.65,-229.58,-228.49,-227.39,-226.27,-225.16,-224.06,-222.97,-221.91,-220.88,-219.89,-218.95,-218.07,-217.24,-216.48,-215.79,-215.19,-214.66,-214.22,-213.87,-213.61,-213.44,-213.37,-213.39,-213.51,-213.73,-214.03,-214.43,-214.91,-215.48,-216.13,-216.85,-217.65,-218.51,-219.42,-220.39,-221.4,-222.44,-223.52,-224.61,-225.72,-226.84,-227.95,-229.04,-230.12,-231.17,-232.19,-233.16,-234.09,-234.95,-235.76,-236.49,-237.15,-237.74,-238.23,-238.64,-238.96,-239.19,-239.33,-239.37,-239.31,-239.16,-238.91,-238.58,-238.15,-237.64,-237.04,-236.37,-235.62,-234.8,-233.93,-232.99,-232.01,-230.99,-229.93,-228.85,-227.75,-226.64,-225.52,-224.41,-223.32,-222.25,-221.21,-220.21,-219.25,-218.35,-217.5,-216.72,-216.01,-215.37,-214.82,-214.35,-213.97,-213.68,-213.48,-213.38,-213.38,-213.46,-221.0,-219.9,-218.82,-217.76,-216.73,-215.75,-214.82,-213.94,-213.12,-212.37,-211.69,-211.09,-210.57,-210.14,-209.8,-209.55,-209.4,-209.34,-209.37,-209.5,-209.73,-210.05,-210.45,-210.95,-211.53,-212.18,-212.92,-213.72,-214.58,-215.5,-216.48,-217.49,-218.54,-219.62,-220.72,-221.83,-222.94,-224.05,-225.15,-226.22,-227.27,-228.28,-229.25,-230.16,-231.02,-231.82,-232.55,-233.2,-233.77,-234.26,-234.66,-234.97,-235.19,-235.31,-235.34,-235.27,-235.11,-234.85,-234.5,-234.06,-233.54,-232.94,-232.25,-231.5,-230.67,-229.79,-228.85,-227.86,-226.84,-225.78,-224.69,-223.59,-222.47,-221.36,-220.26,-219.16,-218.1,-217.06,-216.06,-215.11,-214.21,-213.38,-212.6,-211.9,-211.28,-210.73,-210.27,-209.9,-209.62,-209.44,-209.35,-209.35,-209.45,-209.65,-209.93,-210.31,-210.78,-211.33,-211.96,-212.67,-213.45,-214.3,-215.2,-216.15,-217.16,-218.2,-219.27,-220.36,-221.46,-222.58,-223.69,-224.79,-225.87,-226.93,-227.96,-228.94,-229.87,-230.75,-231.57,-232.32,-233.0,-233.59,-234.11,-234.54,-234.88,-235.13,-235.28,-235.34,-235.3,-235.17,-234.94,-234.62,-234.22,-233.72,-233.14,-232.48,-231.75,-230.95,-230.08,-229.16,-228.19,-227.17,-226.12,-225.04,-223.95,-222.84,-221.72,-220.61,-219.52,-218.44,-217.39,-216.38,-215.42,-214.5,-213.64,-212.85,-212.12,-211.47,-210.9,-210.41,-210.01,-209.7,-209.49,-209.37,-209.34,-209.41,-209.57,-209.83,-210.18,-210.62,-211.14,-211.75,-212.43,-213.19,-214.01,-214.9,-215.84,-216.83,-217.85,-218.92,-220.0,-221.1,-222.22,-223.33,-224.44,-225.53,-226.59,-227.63,-228.63,-229.58,-230.47,-231.31,-232.08,-232.78,-233.41,-233.95,-234.41,-234.78,-235.06,-235.24,-235.33,-235.32,-235.22,-235.03,-234.74,-234.36,-233.89,-233.34,-232.7,-231.99,-231.21,-230.37,-229.46,-228.51,-227.51,-226.47,-225.4,-224.3,-223.2,-222.08,-220.97,-219.87,-218.79,-217.73,-216.71,-215.72,-214.79,-213.91,-213.1,-212.35,-211.67,-211.08,-210.56,-210.13,-209.79,-209.55,-209.4,-209.34,-209.38,-209.51,-216.45,-215.36,-214.29,-213.24,-212.24,-211.28,-210.37,-209.51,-208.73,-208.01,-207.37,-206.81,-206.33,-205.94,-205.65,-205.44,-205.33,-205.31,-205.4,-205.57,-205.84,-206.2,-206.65,-207.18,-207.8,-208.49,-209.26,-210.09,-210.98,-211.93,-212.92,-213.95,-215.01,-216.1,-217.21,-218.32,-219.43,-220.54,-221.63,-222.69,-223.72,-224.71,-225.66,-226.55,-227.38,-228.14,-228.83,-229.45,-229.98,-230.43,-230.79,-231.05,-231.23,-231.3,-231.29,-231.18,-230.97,-230.67,-230.28,-229.8,-229.24,-228.6,-227.88,-227.09,-226.24,-225.32,-224.36,-223.36,-222.31,-221.24,-220.14,-219.04,-217.92,-216.81,-215.71,-214.63,-213.58,-212.56,-211.58,-210.65,-209.78,-208.97,-208.23,-207.57,-206.98,-206.48,-206.06,-205.73,-205.5,-205.36,-205.31,-205.36,-205.5,-205.74,-206.07,-206.49,-207.0,-207.59,-208.26,-209.0,-209.81,-210.68,-211.61,-212.59,-213.61,-214.67,-215.75,-216.85,-217.96,-219.07,-220.18,-221.27,-222.35,-223.39,-224.4,-225.36,-226.27,-227.12,-227.9,-228.62,-229.26,-229.82,-230.29,-230.68,-230.98,-231.18,-231.29,-231.3,-231.22,-231.05,-230.78,-230.41,-229.96,-229.43,-228.81,-228.12,-227.35,-226.52,-225.63,-224.68,-223.69,-222.65,-221.59,-220.5,-219.4,-218.28,-217.17,-216.07,-214.98,-213.92,-212.88,-211.89,-210.95,-210.06,-209.23,-208.47,-207.78,-207.16,-206.63,-206.18,-205.83,-205.56,-205.39,-205.31,-205.33,-205.45,-205.65,-205.95,-206.35,-206.83,-207.39,-208.03,-208.75,-209.54,-210.39,-211.31,-212.27,-213.28,-214.32,-215.39,-216.49,-217.6,-218.71,-219.82,-220.92,-222.0,-223.06,-224.07,-225.05,-225.98,-226.85,-227.65,-228.39,-229.06,-229.65,-230.15,-230.56,-230.89,-231.12,-231.26,-231.31,-231.26,-231.11,-230.87,-230.54,-230.12,-229.61,-229.02,-228.35,-227.61,-226.8,-225.92,-224.99,-224.01,-222.99,-221.94,-220.86,-219.76,-218.64,-217.53,-216.42,-215.33,-214.26,-213.21,-212.21,-211.25,-210.34,-209.49,-208.71,-207.99,-207.35,-206.79,-206.32,-205.93,-205.64,-205.44,-205.33,-205.32,-205.4,-205.58,-211.91,-210.82,-209.76,-208.74,-207.75,-206.81,-205.93,-205.11,-204.35,-203.67,-203.07,-202.54,-202.11,-201.76,-201.51,-201.35,-201.28,-201.31,-201.44,-201.66,-201.97,-202.37,-202.86,-203.43,-204.09,-204.81,-205.61,-206.47,-207.39,-208.36,-209.37,-210.42,-211.5,-212.59,-213.7,-214.82,-215.92,-217.02,-218.1,-219.15,-220.16,-221.13,-222.05,-222.92,-223.72,-224.45,-225.1,-225.68,-226.17,-226.58,-226.89,-227.12,-227.25,-227.28,-227.22,-227.06,-226.81,-226.47,-226.04,-225.52,-224.92,-224.24,-223.49,-222.67,-221.79,-220.85,-219.87,-218.84,-217.78,-216.7,-215.6,-214.48,-213.37,-212.26,-211.17,-210.1,-209.06,-208.06,-207.11,-206.21,-205.37,-204.59,-203.88,-203.25,-202.7,-202.24,-201.87,-201.58,-201.39,-201.29,-201.29,-201.39,-201.57,-201.86,-202.23,-202.69,-203.24,-203.87,-204.57,-205.34,-206.19,-207.09,-208.04,-209.04,-210.08,-211.14,-212.23,-213.34,-214.45,-215.57,-216.67,-217.75,-218.81,-219.84,-220.82,-221.76,-222.64,-223.47,-224.22,-224.9,-225.5,-226.02,-226.46,-226.8,-227.06,-227.21,-227.28,-227.25,-227.12,-226.9,-226.59,-226.19,-225.69,-225.12,-224.47,-223.74,-222.94,-222.08,-221.16,-220.19,-219.18,-218.13,-217.05,-215.95,-214.84,-213.73,-212.62,-211.52,-210.45,-209.4,-208.38,-207.41,-206.49,-205.63,-204.83,-204.1,-203.45,-202.87,-202.38,-201.98,-201.66,-201.44,-201.31,-201.28,-201.35,-201.5,-201.76,-202.1,-202.53,-203.05,-203.65,-204.33,-205.09,-205.91,-206.79,-207.72,-208.71,-209.74,-210.79,-211.88,-212.98,-214.09,-215.21,-216.31,-217.4,-218.47,-219.51,-220.51,-221.46,-222.36,-223.21,-223.98,-224.69,-225.32,-225.86,-226.33,-226.7,-226.98,-227.17,-227.27,-227.27,-227.17,-226.98,-226.7,-226.33,-225.86,-225.32,-224.69,-223.98,-223.21,-222.36,-221.46,-220.51,-219.51,-218.47,-217.4,-216.31,-215.21,-214.09,-212.98,-211.88,-210.79,-209.73,-208.71,-207.72,-206.79,-205.91,-205.09,-204.33,-203.65,-203.05,-202.53,-202.1,-201.75,-201.5,-201.34,-201.28,-201.31,-201.44,-201.66,-207.37,-206.29,-205.25,-204.24,-203.27,-202.36,-201.51,-200.71,-199.99,-199.35,-198.78,-198.3,-197.91,-197.6,-197.39,-197.28,-197.26,-197.33,-197.5,-197.76,-198.12,-198.56,-199.09,-199.7,-200.39,-201.15,-201.98,-202.87,-203.81,-204.8,-205.83,-206.89,-207.98,-209.08,-210.2,-211.31,-212.41,-213.5,-214.57,-215.6,-216.6,-217.54,-218.44,-219.27,-220.04,-220.74,-221.36,-221.89,-222.35,-222.71,-222.98,-223.16,-223.24,-223.23,-223.13,-222.93,-222.63,-222.25,-221.77,-221.22,-220.58,-219.86,-219.08,-218.23,-217.32,-216.36,-215.36,-214.32,-213.25,-212.15,-211.04,-209.93,-208.82,-207.72,-206.64,-205.58,-204.56,-203.58,-202.65,-201.78,-200.96,-200.22,-199.55,-198.96,-198.45,-198.02,-197.69,-197.45,-197.3,-197.25,-197.3,-197.43,-197.67,-197.99,-198.41,-198.91,-199.49,-200.16,-200.9,-201.7,-202.57,-203.5,-204.47,-205.49,-206.55,-207.63,-208.72,-209.84,-210.95,-212.06,-213.15,-214.23,-215.27,-216.28,-217.24,-218.16,-219.01,-219.8,-220.52,-221.16,-221.73,-222.21,-222.6,-222.9,-223.11,-223.23,-223.25,-223.17,-223.0,-222.74,-222.38,-221.94,-221.41,-220.79,-220.1,-219.34,-218.51,-217.62,-216.68,-215.69,-214.66,-213.6,-212.51,-211.4,-210.29,-209.18,-208.07,-206.99,-205.92,-204.89,-203.89,-202.95,-202.05,-201.22,-200.45,-199.76,-199.14,-198.6,-198.15,-197.79,-197.52,-197.34,-197.26,-197.27,-197.38,-197.58,-197.88,-198.26,-198.74,-199.3,-199.93,-200.65,-201.43,-202.28,-203.19,-204.15,-205.16,-206.2,-207.27,-208.37,-209.47,-210.59,-211.7,-212.8,-213.88,-214.94,-215.96,-216.94,-217.87,-218.74,-219.55,-220.29,-220.96,-221.55,-222.06,-222.48,-222.82,-223.06,-223.2,-223.25,-223.21,-223.07,-222.83,-222.51,-222.09,-221.59,-221.0,-220.34,-219.6,-218.79,-217.92,-216.99,-216.02,-215.0,-213.94,-212.86,-211.76,-210.65,-209.54,-208.43,-207.34,-206.26,-205.22,-204.21,-203.25,-202.34,-201.48,-200.69,-199.97,-199.33,-198.77,-198.29,-197.9,-197.6,-197.39,-197.27,-197.26,-197.33,-197.51,-197.77,-202.83,-201.77,-200.74,-199.75,-198.81,-197.92,-197.1,-196.34,-195.65,-195.04,-194.52,-194.08,-193.72,-193.46,-193.3,-193.23,-193.25,-193.37,-193.58,-193.89,-194.29,-194.77,-195.34,-195.99,-196.71,-197.5,-198.36,-199.28,-200.24,-201.25,-202.3,-203.37,-204.47,-205.58,-206.69,-207.8,-208.9,-209.98,-211.03,-212.05,-213.02,-213.94,-214.81,-215.61,-216.35,-217.01,-217.59,-218.09,-218.5,-218.82,-219.05,-219.18,-219.22,-219.17,-219.02,-218.77,-218.43,-218.01,-217.49,-216.9,-216.22,-215.48,-214.66,-213.78,-212.85,-211.87,-210.84,-209.79,-208.7,-207.6,-206.49,-205.38,-204.27,-203.18,-202.11,-201.07,-200.07,-199.11,-198.2,-197.36,-196.58,-195.87,-195.23,-194.68,-194.21,-193.83,-193.54,-193.34,-193.24,-193.23,-193.32,-193.5,-193.78,-194.15,-194.6,-195.15,-195.77,-196.47,-197.24,-198.08,-198.97,-199.92,-200.92,-201.95,-203.02,-204.11,-205.22,-206.33,-207.44,-208.55,-209.63,-210.69,-211.72,-212.71,-213.65,-214.54,-215.36,-216.12,-216.8,-217.41,-217.94,-218.38,-218.73,-218.99,-219.15,-219.22,-219.2,-219.07,-218.86,-218.55,-218.15,-217.67,-217.1,-216.45,-215.73,-214.93,-214.07,-213.16,-212.19,-211.18,-210.13,-209.06,-207.96,-206.85,-205.74,-204.63,-203.53,-202.45,-201.4,-200.39,-199.41,-198.49,-197.62,-196.82,-196.09,-195.43,-194.85,-194.35,-193.94,-193.62,-193.39,-193.26,-193.22,-193.28,-193.43,-193.68,-194.02,-194.45,-194.96,-195.56,-196.23,-196.98,-197.8,-198.68,-199.61,-200.59,-201.62,-202.67,-203.76,-204.86,-205.97,-207.08,-208.19,-209.28,-210.35,-211.39,-212.39,-213.35,-214.25,-215.1,-215.88,-216.59,-217.22,-217.78,-218.24,-218.62,-218.91,-219.11,-219.21,-219.21,-219.12,-218.94,-218.66,-218.29,-217.84,-217.29,-216.67,-215.97,-215.2,-214.36,-213.46,-212.51,-211.51,-210.48,-209.41,-208.32,-207.21,-206.1,-204.99,-203.89,-202.8,-201.74,-200.71,-199.72,-198.78,-197.9,-197.07,-196.32,-195.63,-195.03,-194.5,-194.06,-193.72,-193.46,-193.29,-193.23,-193.25,-193.37,-193.59,-193.9,-198.3,-197.25,-196.24,-195.27,-194.36,-193.5,-192.7,-191.98,-191.33,-190.76,-190.27,-189.87,-189.56,-189.34,-189.22,-189.2,-189.27,-189.43,-189.69,-190.04,-190.47,-191.0,-191.6,-192.29,-193.05,-193.87,-194.76,-195.7,-196.68,-197.71,-198.77,-199.86,-200.96,-202.07,-203.19,-204.29,-205.38,-206.45,-207.48,-208.48,-209.43,-210.33,-211.17,-211.94,-212.64,-213.26,-213.81,-214.26,-214.63,-214.91,-215.1,-215.18,-215.18,-215.08,-214.88,-214.59,-214.21,-213.75,-213.19,-212.56,-211.85,-211.07,-210.23,-209.32,-208.36,-207.36,-206.32,-205.25,-204.16,-203.05,-201.94,-200.83,-199.73,-198.64,-197.59,-196.56,-195.58,-194.65,-193.77,-192.95,-192.2,-191.53,-190.93,-190.42,-189.99,-189.65,-189.4,-189.25,-189.19,-189.23,-189.37,-189.59,-189.91,-190.32,-190.82,-191.4,-192.06,-192.79,-193.6,-194.46,-195.38,-196.36,-197.37,-198.42,-199.5,-200.6,-201.71,-202.82,-203.93,-205.03,-206.11,-207.15,-208.16,-209.13,-210.04,-210.9,-211.7,-212.42,-213.07,-213.64,-214.13,-214.52,-214.83,-215.05,-215.17,-215.19,-215.12,-214.96,-214.7,-214.35,-213.91,-213.38,-212.77,-212.09,-211.33,-210.51,-209.62,-208.68,-207.69,-206.66,-205.6,-204.52,-203.41,-202.3,-201.19,-200.08,-198.99,-197.93,-196.89,-195.89,-194.94,-194.05,-193.21,-192.44,-191.74,-191.12,-190.57,-190.12,-189.75,-189.47,-189.29,-189.2,-189.21,-189.31,-189.51,-189.8,-190.18,-190.65,-191.2,-191.84,-192.55,-193.33,-194.17,-195.08,-196.04,-197.04,-198.08,-199.15,-200.24,-201.35,-202.46,-203.58,-204.68,-205.76,-206.82,-207.84,-208.82,-209.75,-210.63,-211.45,-212.19,-212.87,-213.46,-213.98,-214.4,-214.74,-214.99,-215.14,-215.19,-215.15,-215.02,-214.79,-214.47,-214.06,-213.56,-212.98,-212.32,-211.59,-210.78,-209.91,-208.99,-208.02,-207.0,-205.95,-204.87,-203.77,-202.66,-201.55,-200.44,-199.34,-198.27,-197.22,-196.21,-195.25,-194.33,-193.47,-192.68,-191.96,-191.31,-190.74,-190.26,-189.86,-189.55,-189.34,-189.22,-189.2,-189.27,-189.43,-189.69,-190.05,-193.77,-192.74,-191.75,-190.81,-189.92,-189.09,-188.32,-187.63,-187.02,-186.49,-186.04,-185.68,-185.42,-185.25,-185.17,-185.19,-185.3,-185.51,-185.81,-186.2,-186.68,-187.24,-187.89,-188.61,-189.4,-190.25,-191.16,-192.13,-193.13,-194.18,-195.25,-196.35,-197.45,-198.57,-199.68,-200.78,-201.86,-202.91,-203.93,-204.91,-205.83,-206.7,-207.51,-208.25,-208.91,-209.5,-210.0,-210.42,-210.75,-210.98,-211.12,-211.17,-211.11,-210.97,-210.73,-210.4,-209.98,-209.47,-208.88,-208.21,-207.46,-206.65,-205.78,-204.85,-203.87,-202.85,-201.79,-200.71,-199.61,-198.5,-197.39,-196.28,-195.19,-194.11,-193.07,-192.07,-191.11,-190.2,-189.35,-188.56,-187.85,-187.21,-186.65,-186.18,-185.79,-185.49,-185.29,-185.18,-185.17,-185.25,-185.43,-185.7,-186.07,-186.52,-187.05,-187.67,-188.37,-189.13,-189.97,-190.86,-191.81,-192.8,-193.83,-194.9,-195.99,-197.09,-198.21,-199.32,-200.42,-201.51,-202.57,-203.6,-204.59,-205.54,-206.43,-207.26,-208.02,-208.71,-209.32,-209.85,-210.3,-210.65,-210.91,-211.09,-211.16,-211.14,-211.03,-210.82,-210.52,-210.12,-209.64,-209.08,-208.43,-207.71,-206.92,-206.07,-205.16,-204.19,-203.18,-202.14,-201.07,-199.97,-198.86,-197.75,-196.64,-195.54,-194.46,-193.41,-192.39,-191.41,-190.49,-189.62,-188.81,-188.07,-187.41,-186.82,-186.32,-185.91,-185.58,-185.35,-185.21,-185.17,-185.22,-185.36,-185.6,-185.94,-186.36,-186.87,-187.46,-188.13,-188.88,-189.69,-190.56,-191.49,-192.47,-193.5,-194.55,-195.63,-196.73,-197.84,-198.96,-200.07,-201.16,-202.23,-203.27,-204.28,-205.24,-206.14,-206.99,-207.78,-208.49,-209.13,-209.69,-210.16,-210.55,-210.84,-211.04,-211.15,-211.16,-211.07,-210.9,-210.62,-210.26,-209.81,-209.27,-208.65,-207.95,-207.19,-206.35,-205.46,-204.51,-203.52,-202.48,-201.42,-200.33,-199.22,-198.11,-197.0,-195.89,-194.81,-193.74,-192.71,-191.72,-190.78,-189.89,-189.06,-188.3,-187.61,-187.0,-186.47,-186.03,-185.68,-185.41,-185.24,-185.17,-185.19,-185.31,-185.52,-185.82,-186.21,-189.25,-188.24,-187.27,-186.35,-185.49,-184.69,-183.96,-183.31,-182.73,-182.24,-181.83,-181.52,-181.3,-181.17,-181.14,-181.2,-181.36,-181.61,-181.95,-182.39,-182.91,-183.51,-184.19,-184.94,-185.76,-186.64,-187.58,-188.56,-189.59,-190.65,-191.73,-192.84,-193.95,-195.06,-196.17,-197.26,-198.33,-199.37,-200.37,-201.32,-202.22,-203.06,-203.84,-204.54,-205.17,-205.72,-206.18,-206.56,-206.84,-207.03,-207.12,-207.12,-207.03,-206.84,-206.56,-206.18,-205.72,-205.17,-204.54,-203.84,-203.06,-202.22,-201.32,-200.37,-199.37,-198.33,-197.26,-196.17,-195.06,-193.95,-192.84,-191.73,-190.65,-189.59,-188.57,-187.58,-186.64,-185.76,-184.94,-184.19,-183.51,-182.91,-182.39,-181.95,-181.61,-181.36,-181.2,-181.14,-181.17,-181.3,-181.52,-181.83,-182.24,-182.73,-183.31,-183.96,-184.69,-185.49,-186.35,-187.27,-188.24,-189.25,-190.3,-191.38,-192.48,-193.59,-194.7,-195.81,-196.91,-197.98,-199.03,-200.05,-201.02,-201.93,-202.8,-203.59,-204.32,-204.98,-205.55,-206.04,-206.44,-206.76,-206.98,-207.1,-207.14,-207.07,-206.91,-206.66,-206.31,-205.88,-205.36,-204.76,-204.07,-203.32,-202.5,-201.62,-200.68,-199.69,-198.67,-197.61,-196.52,-195.42,-194.31,-193.2,-192.09,-191.0,-189.93,-188.89,-187.89,-186.94,-186.04,-185.2,-184.43,-183.72,-183.09,-182.55,-182.09,-181.71,-181.43,-181.24,-181.15,-181.15,-181.25,-181.44,-181.72,-182.1,-182.56,-183.11,-183.74,-184.45,-185.22,-186.06,-186.97,-187.92,-188.92,-189.96,-191.03,-192.12,-193.23,-194.34,-195.45,-196.55,-197.64,-198.7,-199.72,-200.71,-201.64,-202.52,-203.34,-204.09,-204.77,-205.37,-205.89,-206.32,-206.67,-206.92,-207.07,-207.14,-207.1,-206.97,-206.75,-206.44,-206.03,-205.54,-204.96,-204.3,-203.57,-202.77,-201.91,-200.99,-200.02,-199.01,-197.96,-196.88,-195.78,-194.67,-193.56,-192.45,-191.35,-190.27,-189.23,-188.21,-187.25,-186.33,-185.47,-184.67,-183.94,-183.29,-182.72,-182.23,-181.82,-181.51,-181.29,-181.17,-181.14,-181.2,-181.36,-181.62,-181.97,-182.4,-184.74,-183.75,-182.8,-181.91,-181.08,-180.31,-179.61,-179.0,-178.46,-178.01,-177.65,-177.37,-177.2,-177.11,-177.13,-177.23,-177.44,-177.73,-178.12,-178.59,-179.15,-179.79,-180.51,-181.29,-182.14,-183.05,-184.01,-185.01,-186.06,-187.13,-188.22,-189.33,-190.44,-191.55,-192.65,-193.74,-194.79,-195.81,-196.79,-197.72,-198.59,-199.41,-200.15,-200.82,-201.41,-201.92,-202.34,-202.67,-202.91,-203.06,-203.11,-203.06,-202.92,-202.69,-202.36,-201.95,-201.44,-200.86,-200.19,-199.45,-198.65,-197.77,-196.85,-195.87,-194.85,-193.8,-192.72,-191.62,-190.51,-189.4,-188.29,-187.19,-186.12,-185.08,-184.07,-183.1,-182.19,-181.34,-180.55,-179.83,-179.19,-178.62,-178.14,-177.75,-177.45,-177.24,-177.13,-177.11,-177.19,-177.36,-177.63,-177.98,-178.43,-178.96,-179.57,-180.27,-181.03,-181.86,-182.75,-183.69,-184.68,-185.71,-186.78,-187.87,-188.97,-190.08,-191.19,-192.3,-193.39,-194.45,-195.49,-196.48,-197.43,-198.32,-199.15,-199.92,-200.61,-201.23,-201.76,-202.21,-202.57,-202.84,-203.02,-203.1,-203.09,-202.98,-202.78,-202.48,-202.09,-201.62,-201.06,-200.42,-199.7,-198.91,-198.06,-197.15,-196.19,-195.19,-194.15,-193.07,-191.98,-190.87,-189.76,-188.65,-187.55,-186.47,-185.41,-184.39,-183.41,-182.48,-181.61,-180.8,-180.06,-179.39,-178.8,-178.29,-177.87,-177.54,-177.3,-177.16,-177.11,-177.15,-177.3,-177.53,-177.86,-178.28,-178.78,-179.37,-180.03,-180.77,-181.58,-182.45,-183.38,-184.36,-185.38,-186.43,-187.51,-188.61,-189.72,-190.83,-191.94,-193.04,-194.11,-195.15,-196.16,-197.12,-198.03,-198.89,-199.68,-200.39,-201.04,-201.6,-202.08,-202.47,-202.77,-202.97,-203.09,-203.1,-203.02,-202.85,-202.58,-202.23,-201.78,-201.25,-200.63,-199.94,-199.18,-198.35,-197.46,-196.51,-195.52,-194.49,-193.42,-192.34,-191.23,-190.12,-189.01,-187.9,-186.81,-185.75,-184.72,-183.72,-182.78,-181.89,-181.05,-180.29,-179.6,-178.98,-178.45,-178.0,-177.64,-177.37,-177.19,-177.11,-177.13,-177.24,-177.44,-177.74,-178.13,-178.61,-180.24,-179.27,-178.35,-177.48,-176.68,-175.94,-175.28,-174.7,-174.21,-173.8,-173.48,-173.25,-173.12,-173.08,-173.14,-173.29,-173.54,-173.87,-174.3,-174.82,-175.41,-176.09,-176.84,-177.65,-178.53,-179.47,-180.45,-181.47,-182.53,-183.61,-184.71,-185.82,-186.94,-188.04,-189.14,-190.21,-191.25,-192.25,-193.21,-194.11,-194.96,-195.74,-196.45,-197.08,-197.63,-198.1,-198.48,-198.77,-198.96,-199.06,-199.07,-198.98,-198.8,-198.52,-198.15,-197.69,-197.15,-196.53,-195.82,-195.05,-194.21,-193.32,-192.37,-191.37,-190.33,-189.27,-188.18,-187.07,-185.96,-184.85,-183.74,-182.66,-181.6,-180.57,-179.58,-178.64,-177.76,-176.93,-176.17,-175.49,-174.88,-174.36,-173.92,-173.57,-173.31,-173.15,-173.08,-173.11,-173.23,-173.45,-173.75,-174.15,-174.64,-175.21,-175.86,-176.59,-177.38,-178.24,-179.16,-180.12,-181.13,-182.18,-183.26,-184.35,-185.46,-186.58,-187.69,-188.78,-189.86,-190.91,-191.93,-192.9,-193.82,-194.69,-195.49,-196.22,-196.88,-197.46,-197.96,-198.37,-198.68,-198.91,-199.04,-199.08,-199.02,-198.87,-198.62,-198.28,-197.85,-197.33,-196.74,-196.06,-195.31,-194.49,-193.61,-192.68,-191.7,-190.67,-189.62,-188.53,-187.43,-186.32,-185.21,-184.1,-183.01,-181.94,-180.9,-179.9,-178.94,-178.04,-177.19,-176.41,-175.7,-175.07,-174.52,-174.05,-173.67,-173.39,-173.19,-173.09,-173.09,-173.18,-173.37,-173.64,-174.01,-174.47,-175.02,-175.64,-176.34,-177.12,-177.96,-178.85,-179.81,-180.8,-181.84,-182.91,-184.0,-185.1,-186.22,-187.33,-188.43,-189.52,-190.58,-191.6,-192.59,-193.53,-194.41,-195.24,-195.99,-196.68,-197.28,-197.81,-198.24,-198.59,-198.85,-199.01,-199.08,-199.05,-198.93,-198.71,-198.4,-198.0,-197.51,-196.94,-196.29,-195.56,-194.77,-193.91,-192.99,-192.02,-191.01,-189.96,-188.89,-187.79,-186.68,-185.57,-184.46,-183.36,-182.28,-181.23,-180.22,-179.24,-178.32,-177.46,-176.66,-175.93,-175.27,-174.69,-174.2,-173.79,-173.47,-173.25,-173.12,-173.08,-173.14,-173.29,-173.54,-173.88,-174.31,-174.83,-175.75,-174.8,-173.9,-173.07,-172.3,-171.6,-170.97,-170.43,-169.97,-169.61,-169.33,-169.15,-169.06,-169.07,-169.17,-169.36,-169.65,-170.04,-170.5,-171.06,-171.69,-172.4,-173.18,-174.03,-174.94,-175.89,-176.89,-177.94,-179.01,-180.1,-181.21,-182.32,-183.43,-184.53,-185.61,-186.67,-187.69,-188.68,-189.61,-190.49,-191.3,-192.05,-192.72,-193.32,-193.83,-194.26,-194.6,-194.84,-194.99,-195.05,-195.01,-194.88,-194.65,-194.33,-193.92,-193.42,-192.84,-192.18,-191.44,-190.64,-189.77,-188.85,-187.87,-186.86,-185.81,-184.73,-183.63,-182.52,-181.41,-180.3,-179.2,-178.13,-177.08,-176.07,-175.1,-174.19,-173.33,-172.54,-171.81,-171.17,-170.6,-170.11,-169.72,-169.41,-169.2,-169.08,-169.05,-169.12,-169.29,-169.55,-169.9,-170.34,-170.87,-171.48,-172.16,-172.92,-173.75,-174.64,-175.58,-176.57,-177.59,-178.66,-179.74,-180.85,-181.96,-183.07,-184.18,-185.27,-186.33,-187.37,-188.36,-189.31,-190.21,-191.04,-191.82,-192.51,-193.14,-193.68,-194.13,-194.5,-194.77,-194.96,-195.04,-195.03,-194.93,-194.73,-194.44,-194.06,-193.59,-193.03,-192.4,-191.69,-190.91,-190.06,-189.15,-188.19,-187.19,-186.15,-185.08,-183.99,-182.88,-181.77,-180.66,-179.55,-178.47,-177.41,-176.39,-175.41,-174.48,-173.6,-172.79,-172.04,-171.37,-170.77,-170.26,-169.84,-169.5,-169.26,-169.11,-169.05,-169.09,-169.23,-169.46,-169.78,-170.19,-170.69,-171.27,-171.93,-172.67,-173.47,-174.34,-175.27,-176.24,-177.26,-178.31,-179.39,-180.49,-181.6,-182.71,-183.82,-184.91,-185.99,-187.04,-188.04,-189.01,-189.92,-190.78,-191.57,-192.3,-192.94,-193.51,-193.99,-194.39,-194.69,-194.91,-195.02,-195.05,-194.97,-194.81,-194.55,-194.19,-193.75,-193.22,-192.61,-191.93,-191.17,-190.34,-189.45,-188.51,-187.52,-186.49,-185.43,-184.34,-183.24,-182.13,-181.01,-179.91,-178.82,-177.75,-176.72,-175.72,-174.78,-173.88,-173.04,-172.28,-171.58,-170.96,-170.42,-169.96,-169.6,-169.32,-169.14,-169.06,-169.07,-169.17,-169.37,-169.66,-170.05,-170.52,-171.07,-171.27,-170.34,-169.47,-168.67,-167.93,-167.26,-166.68,-166.18,-165.76,-165.44,-165.2,-165.07,-165.02,-165.07,-165.22,-165.46,-165.79,-166.22,-166.73,-167.32,-167.99,-168.73,-169.55,-170.42,-171.35,-172.33,-173.35,-174.41,-175.49,-176.59,-177.7,-178.81,-179.92,-181.01,-182.09,-183.13,-184.13,-185.09,-186.0,-186.85,-187.63,-188.35,-188.99,-189.54,-190.02,-190.4,-190.7,-190.9,-191.0,-191.01,-190.93,-190.75,-190.48,-190.12,-189.66,-189.13,-188.51,-187.81,-187.04,-186.21,-185.31,-184.37,-183.37,-182.34,-181.27,-180.18,-179.08,-177.97,-176.85,-175.75,-174.66,-173.6,-172.57,-171.58,-170.64,-169.75,-168.92,-168.16,-167.47,-166.86,-166.33,-165.89,-165.53,-165.27,-165.1,-165.03,-165.05,-165.16,-165.37,-165.68,-166.07,-166.55,-167.12,-167.76,-168.48,-169.27,-170.13,-171.04,-172.01,-173.02,-174.06,-175.14,-176.23,-177.34,-178.45,-179.56,-180.66,-181.74,-182.79,-183.81,-184.79,-185.71,-186.58,-187.39,-188.12,-188.79,-189.37,-189.87,-190.29,-190.61,-190.84,-190.98,-191.02,-190.97,-190.82,-190.58,-190.24,-189.82,-189.31,-188.72,-188.05,-187.3,-186.49,-185.61,-184.68,-183.7,-182.68,-181.62,-180.54,-179.44,-178.33,-177.21,-176.11,-175.01,-173.94,-172.9,-171.9,-170.94,-170.03,-169.18,-168.4,-167.69,-167.05,-166.49,-166.02,-165.64,-165.34,-165.14,-165.04,-165.03,-165.11,-165.29,-165.57,-165.93,-166.39,-166.92,-167.54,-168.24,-169.01,-169.85,-170.74,-171.69,-172.68,-173.72,-174.78,-175.87,-176.98,-178.09,-179.2,-180.31,-181.39,-182.46,-183.49,-184.48,-185.42,-186.31,-187.13,-187.89,-188.58,-189.19,-189.72,-190.16,-190.52,-190.78,-190.94,-191.02,-191.0,-190.88,-190.67,-190.36,-189.97,-189.48,-188.92,-188.27,-187.55,-186.76,-185.9,-184.99,-184.02,-183.01,-181.97,-180.89,-179.8,-178.69,-177.58,-176.46,-175.37,-174.29,-173.23,-172.22,-171.24,-170.32,-169.45,-168.65,-167.91,-167.25,-166.66,-166.16,-165.75,-165.43,-165.2,-165.06,-165.02,-165.08,-165.23,-165.47,-165.8,-166.23,-166.74,-167.33,-166.8,-165.9,-165.06,-164.28,-163.58,-162.95,-162.4,-161.94,-161.57,-161.29,-161.1,-161.0,-161.01,-161.1,-161.29,-161.58,-161.95,-162.42,-162.97,-163.59,-164.3,-165.08,-165.92,-166.82,-167.78,-168.78,-169.81,-170.88,-171.98,-173.08,-174.2,-175.31,-176.41,-177.49,-178.55,-179.58,-180.56,-181.5,-182.38,-183.2,-183.95,-184.63,-185.23,-185.75,-186.18,-186.52,-186.77,-186.93,-186.99,-186.96,-186.83,-186.61,-186.29,-185.89,-185.39,-184.82,-184.16,-183.43,-182.63,-181.77,-180.85,-179.88,-178.86,-177.81,-176.74,-175.64,-174.53,-173.41,-172.3,-171.21,-170.13,-169.08,-168.07,-167.1,-166.18,-165.32,-164.53,-163.8,-163.15,-162.57,-162.08,-161.68,-161.37,-161.15,-161.02,-160.99,-161.06,-161.22,-161.47,-161.82,-162.26,-162.78,-163.38,-164.06,-164.82,-165.64,-166.52,-167.46,-168.45,-169.47,-170.53,-171.62,-172.72,-173.83,-174.95,-176.05,-177.14,-178.21,-179.25,-180.25,-181.2,-182.1,-182.94,-183.71,-184.42,-185.04,-185.59,-186.05,-186.42,-186.7,-186.89,-186.98,-186.98,-186.88,-186.69,-186.4,-186.03,-185.56,-185.01,-184.38,-183.67,-182.9,-182.05,-181.15,-180.2,-179.2,-178.16,-177.09,-176.0,-174.89,-173.78,-172.66,-171.56,-170.48,-169.42,-168.39,-167.41,-166.48,-165.6,-164.78,-164.03,-163.35,-162.75,-162.23,-161.8,-161.46,-161.21,-161.05,-160.99,-161.03,-161.16,-161.38,-161.7,-162.11,-162.6,-163.18,-163.83,-164.57,-165.37,-166.23,-167.15,-168.12,-169.14,-170.19,-171.27,-172.36,-173.47,-174.59,-175.7,-176.79,-177.87,-178.92,-179.93,-180.9,-181.81,-182.67,-183.47,-184.2,-184.85,-185.42,-185.91,-186.31,-186.62,-186.84,-186.96,-186.99,-186.92,-186.76,-186.51,-186.16,-185.72,-185.2,-184.59,-183.91,-183.16,-182.33,-181.45,-180.51,-179.52,-178.5,-177.44,-176.35,-175.25,-174.14,-173.02,-171.92,-170.83,-169.76,-168.72,-167.73,-166.77,-165.87,-165.04,-164.26,-163.56,-162.93,-162.39,-161.93,-161.56,-161.28,-161.09,-161.0,-161.01,-161.11,-161.3,-161.59,-161.96,-162.43,-162.98,-163.61,-162.34,-161.47,-160.66,-159.91,-159.24,-158.65,-158.15,-157.73,-157.4,-157.16,-157.01,-156.96,-157.01,-157.15,-157.39,-157.71,-158.13,-158.64,-159.22,-159.89,-160.63,-161.44,-162.31,-163.24,-164.21,-165.23,-166.29,-167.37,-168.47,-169.58,-170.69,-171.8,-172.89,-173.97,-175.01,-176.02,-176.98,-177.89,-178.74,-179.53,-180.25,-180.89,-181.45,-181.93,-182.32,-182.62,-182.83,-182.94,-182.96,-182.88,-182.71,-182.44,-182.08,-181.64,-181.1,-180.49,-179.8,-179.03,-178.2,-177.31,-176.37,-175.38,-174.34,-173.28,-172.19,-171.09,-169.98,-168.86,-167.76,-166.67,-165.61,-164.57,-163.58,-162.64,-161.74,-160.91,-160.15,-159.45,-158.84,-158.3,-157.85,-157.49,-157.22,-157.05,-156.97,-156.98,-157.1,-157.3,-157.6,-157.99,-158.46,-159.02,-159.66,-160.38,-161.17,-162.02,-162.93,-163.89,-164.9,-165.94,-167.01,-168.11,-169.22,-170.33,-171.44,-172.54,-173.62,-174.67,-175.69,-176.67,-177.6,-178.47,-179.28,-180.02,-180.69,-181.28,-181.79,-182.21,-182.54,-182.77,-182.92,-182.96,-182.92,-182.77,-182.54,-182.21,-181.79,-181.29,-180.7,-180.03,-179.29,-178.48,-177.61,-176.68,-175.7,-174.68,-173.63,-172.55,-171.45,-170.34,-169.22,-168.12,-167.02,-165.95,-164.9,-163.9,-162.94,-162.03,-161.17,-160.39,-159.67,-159.03,-158.47,-157.99,-157.6,-157.3,-157.1,-156.99,-156.97,-157.05,-157.22,-157.49,-157.85,-158.3,-158.83,-159.45,-160.14,-160.91,-161.74,-162.63,-163.57,-164.57,-165.6,-166.66,-167.75,-168.85,-169.97,-171.08,-172.18,-173.27,-174.34,-175.37,-176.36,-177.31,-178.2,-179.03,-179.79,-180.48,-181.1,-181.63,-182.08,-182.44,-182.71,-182.88,-182.96,-182.94,-182.83,-182.62,-182.33,-181.94,-181.46,-180.9,-180.25,-179.54,-178.75,-177.9,-176.99,-176.02,-175.02,-173.97,-172.9,-171.81,-170.7,-169.58,-168.47,-167.37,-166.29,-165.24,-164.22,-163.24,-162.32,-161.44,-160.63,-159.89,-159.23,-158.64,-158.13,-157.72,-157.39,-157.15,-157.01,-156.96,-157.01,-157.16,-157.39,-157.72,-158.14,-158.65,-159.24,-159.91,-157.89,-157.05,-156.27,-155.56,-154.93,-154.38,-153.91,-153.53,-153.24,-153.05,-152.95,-152.95,-153.04,-153.22,-153.5,-153.87,-154.33,-154.87,-155.5,-156.2,-156.97,-157.81,-158.71,-159.66,-160.66,-161.69,-162.76,-163.85,-164.96,-166.07,-167.18,-168.29,-169.37,-170.43,-171.46,-172.45,-173.39,-174.27,-175.09,-175.85,-176.53,-177.14,-177.66,-178.1,-178.45,-178.7,-178.87,-178.93,-178.91,-178.78,-178.57,-178.26,-177.86,-177.37,-176.8,-176.14,-175.42,-174.62,-173.76,-172.85,-171.88,-170.87,-169.82,-168.74,-167.65,-166.54,-165.42,-164.31,-163.22,-162.14,-161.09,-160.07,-159.1,-158.18,-157.32,-156.51,-155.78,-155.12,-154.55,-154.05,-153.64,-153.33,-153.1,-152.97,-152.94,-153.0,-153.15,-153.4,-153.74,-154.17,-154.69,-155.29,-155.96,-156.71,-157.53,-158.41,-159.35,-160.33,-161.35,-162.41,-163.5,-164.6,-165.71,-166.82,-167.93,-169.02,-170.09,-171.13,-172.13,-173.09,-173.99,-174.83,-175.61,-176.32,-176.95,-177.5,-177.97,-178.34,-178.63,-178.82,-178.92,-178.92,-178.83,-178.65,-178.37,-177.99,-177.53,-176.99,-176.36,-175.66,-174.89,-174.05,-173.15,-172.2,-171.2,-170.16,-169.09,-168.0,-166.9,-165.78,-164.67,-163.57,-162.48,-161.42,-160.4,-159.41,-158.47,-157.59,-156.77,-156.01,-155.33,-154.72,-154.2,-153.77,-153.42,-153.16,-153.0,-152.94,-152.97,-153.09,-153.31,-153.62,-154.02,-154.51,-155.08,-155.74,-156.46,-157.26,-158.12,-159.04,-160.01,-161.02,-162.07,-163.14,-164.24,-165.35,-166.46,-167.57,-168.67,-169.75,-170.8,-171.81,-172.78,-173.7,-174.57,-175.37,-176.1,-176.75,-177.33,-177.83,-178.23,-178.55,-178.77,-178.9,-178.93,-178.87,-178.72,-178.47,-178.12,-177.69,-177.18,-176.58,-175.9,-175.15,-174.33,-173.45,-172.51,-171.53,-170.5,-169.44,-168.36,-167.26,-166.15,-165.03,-163.93,-162.83,-161.76,-160.73,-159.73,-158.77,-157.87,-157.03,-156.25,-155.54,-154.91,-154.36,-153.9,-153.52,-153.24,-153.05,-152.95,-152.95,-153.04,-153.23,-153.51,-153.88,-154.34,-154.89,-155.52,-156.22,-153.46,-152.64,-151.9,-151.22,-150.63,-150.12,-149.69,-149.36,-149.11,-148.96,-148.91,-148.95,-149.08,-149.31,-149.63,-150.05,-150.55,-151.13,-151.79,-152.53,-153.33,-154.2,-155.12,-156.1,-157.11,-158.16,-159.24,-160.34,-161.45,-162.57,-163.67,-164.77,-165.85,-166.89,-167.9,-168.87,-169.78,-170.64,-171.43,-172.15,-172.8,-173.37,-173.85,-174.24,-174.55,-174.76,-174.88,-174.9,-174.83,-174.66,-174.4,-174.05,-173.61,-173.08,-172.47,-171.78,-171.02,-170.2,-169.31,-168.37,-167.38,-166.35,-165.29,-164.2,-163.1,-161.98,-160.87,-159.77,-158.68,-157.61,-156.58,-155.58,-154.63,-153.74,-152.9,-152.13,-151.43,-150.81,-150.27,-149.82,-149.45,-149.18,-149.0,-148.91,-148.92,-149.03,-149.23,-149.52,-149.9,-150.37,-150.93,-151.57,-152.28,-153.06,-153.91,-154.82,-155.77,-156.78,-157.82,-158.89,-159.98,-161.09,-162.2,-163.32,-164.42,-165.5,-166.56,-167.58,-168.56,-169.49,-170.37,-171.18,-171.92,-172.6,-173.19,-173.7,-174.13,-174.46,-174.7,-174.85,-174.91,-174.86,-174.73,-174.5,-174.17,-173.76,-173.26,-172.68,-172.01,-171.28,-170.47,-169.6,-168.68,-167.7,-166.69,-165.63,-164.56,-163.46,-162.35,-161.23,-160.12,-159.03,-157.95,-156.91,-155.9,-154.93,-154.02,-153.17,-152.37,-151.65,-151.01,-150.44,-149.96,-149.56,-149.26,-149.05,-148.93,-148.91,-148.98,-149.15,-149.41,-149.77,-150.21,-150.74,-151.35,-152.04,-152.8,-153.63,-154.52,-155.46,-156.45,-157.48,-158.54,-159.63,-160.73,-161.84,-162.96,-164.06,-165.15,-166.22,-167.25,-168.24,-169.19,-170.09,-170.92,-171.69,-172.39,-173.01,-173.55,-174.0,-174.36,-174.64,-174.81,-174.9,-174.89,-174.78,-174.58,-174.29,-173.9,-173.43,-172.87,-172.24,-171.52,-170.74,-169.89,-168.98,-168.02,-167.02,-165.98,-164.91,-163.81,-162.71,-161.59,-160.48,-159.38,-158.3,-157.24,-156.22,-155.24,-154.31,-153.44,-152.62,-151.88,-151.21,-150.61,-150.1,-149.68,-149.35,-149.11,-148.96,-148.91,-148.95,-149.09,-149.32,-149.64,-150.06,-150.56,-151.14,-151.81,-152.55,-149.04,-148.26,-147.54,-146.91,-146.35,-145.88,-145.49,-145.2,-145.0,-144.9,-144.89,-144.97,-145.15,-145.42,-145.79,-146.24,-146.78,-147.4,-148.1,-148.87,-149.7,-150.6,-151.54,-152.54,-153.57,-154.64,-155.73,-156.83,-157.95,-159.06,-160.16,-161.25,-162.31,-163.34,-164.33,-165.27,-166.16,-166.99,-167.75,-168.44,-169.05,-169.58,-170.02,-170.37,-170.63,-170.8,-170.87,-170.85,-170.73,-170.52,-170.22,-169.82,-169.34,-168.77,-168.13,-167.41,-166.61,-165.76,-164.84,-163.88,-162.87,-161.82,-160.75,-159.65,-158.55,-157.43,-156.32,-155.22,-154.14,-153.09,-152.07,-151.1,-150.18,-149.31,-148.5,-147.77,-147.1,-146.52,-146.02,-145.61,-145.29,-145.06,-144.92,-144.88,-144.93,-145.08,-145.32,-145.66,-146.08,-146.6,-147.19,-147.86,-148.61,-149.42,-150.3,-151.23,-152.21,-153.23,-154.29,-155.37,-156.47,-157.59,-158.7,-159.81,-160.9,-161.97,-163.01,-164.02,-164.97,-165.88,-166.73,-167.51,-168.22,-168.86,-169.41,-169.88,-170.27,-170.56,-170.76,-170.86,-170.87,-170.78,-170.6,-170.33,-169.96,-169.51,-168.97,-168.35,-167.65,-166.88,-166.04,-165.15,-164.2,-163.2,-162.17,-161.1,-160.01,-158.91,-157.79,-156.68,-155.58,-154.49,-153.43,-152.4,-151.41,-150.47,-149.58,-148.76,-148.0,-147.31,-146.7,-146.17,-145.73,-145.38,-145.12,-144.95,-144.88,-144.9,-145.02,-145.24,-145.54,-145.94,-146.42,-146.99,-147.64,-148.36,-149.15,-150.01,-150.92,-151.89,-152.9,-153.95,-155.02,-156.12,-157.22,-158.34,-159.45,-160.55,-161.63,-162.68,-163.69,-164.67,-165.59,-166.46,-167.26,-168.0,-168.66,-169.24,-169.74,-170.15,-170.47,-170.7,-170.84,-170.88,-170.82,-170.67,-170.43,-170.09,-169.66,-169.15,-168.56,-167.88,-167.14,-166.32,-165.44,-164.51,-163.53,-162.51,-161.45,-160.37,-159.27,-158.15,-157.04,-155.93,-154.84,-153.77,-152.73,-151.73,-150.77,-149.86,-149.02,-148.24,-147.52,-146.89,-146.34,-145.87,-145.48,-145.19,-145.0,-144.89,-144.89,-144.97,-145.16,-145.43,-145.8,-146.25,-146.8,-147.42,-148.12,-148.89,-144.63,-143.88,-143.2,-142.61,-142.09,-141.66,-141.32,-141.07,-140.91,-140.85,-140.88,-141.01,-141.24,-141.55,-141.96,-142.46,-143.03,-143.69,-144.42,-145.22,-146.09,-147.01,-147.98,-148.99,-150.04,-151.12,-152.22,-153.33,-154.44,-155.55,-156.65,-157.72,-158.77,-159.78,-160.75,-161.67,-162.53,-163.33,-164.05,-164.7,-165.28,-165.77,-166.17,-166.48,-166.69,-166.82,-166.85,-166.78,-166.62,-166.36,-166.02,-165.58,-165.06,-164.45,-163.77,-163.01,-162.19,-161.31,-160.37,-159.38,-158.35,-157.29,-156.21,-155.11,-153.99,-152.88,-151.77,-150.68,-149.62,-148.58,-147.58,-146.63,-145.73,-144.89,-144.12,-143.42,-142.79,-142.25,-141.79,-141.42,-141.14,-140.95,-140.86,-140.86,-140.96,-141.16,-141.44,-141.82,-142.29,-142.84,-143.47,-144.18,-144.96,-145.8,-146.7,-147.66,-148.66,-149.7,-150.77,-151.86,-152.97,-154.08,-155.19,-156.29,-157.38,-158.44,-159.46,-160.44,-161.38,-162.26,-163.07,-163.82,-164.5,-165.1,-165.62,-166.05,-166.39,-166.63,-166.79,-166.85,-166.81,-166.68,-166.46,-166.14,-165.73,-165.23,-164.66,-164.0,-163.27,-162.46,-161.6,-160.68,-159.71,-158.69,-157.64,-156.56,-155.46,-154.35,-153.24,-152.13,-151.04,-149.96,-148.91,-147.9,-146.93,-146.02,-145.16,-144.36,-143.64,-142.99,-142.41,-141.93,-141.53,-141.22,-141.0,-140.88,-140.85,-140.92,-141.08,-141.34,-141.69,-142.13,-142.65,-143.26,-143.94,-144.7,-145.52,-146.4,-147.34,-148.33,-149.36,-150.42,-151.5,-152.61,-153.72,-154.83,-155.94,-157.03,-158.1,-159.13,-160.13,-161.08,-161.98,-162.82,-163.59,-164.29,-164.91,-165.46,-165.92,-166.29,-166.56,-166.75,-166.84,-166.83,-166.73,-166.54,-166.25,-165.87,-165.4,-164.85,-164.22,-163.51,-162.73,-161.89,-160.98,-160.03,-159.02,-157.98,-156.91,-155.82,-154.72,-153.6,-152.49,-151.39,-150.31,-149.25,-148.22,-147.24,-146.31,-145.43,-144.61,-143.86,-143.19,-142.59,-142.08,-141.65,-141.31,-141.06,-140.91,-140.85,-140.89,-141.02,-141.25,-141.56,-141.97,-142.47,-143.05,-143.71,-144.44,-145.25,-140.24,-139.53,-138.88,-138.32,-137.85,-137.46,-137.16,-136.95,-136.84,-136.83,-136.9,-137.08,-137.35,-137.71,-138.15,-138.69,-139.3,-140.0,-140.76,-141.59,-142.48,-143.43,-144.42,-145.45,-146.52,-147.61,-148.71,-149.82,-150.94,-152.04,-153.13,-154.19,-155.22,-156.22,-157.16,-158.05,-158.88,-159.65,-160.34,-160.95,-161.49,-161.94,-162.29,-162.56,-162.74,-162.81,-162.8,-162.69,-162.48,-162.18,-161.79,-161.31,-160.75,-160.11,-159.39,-158.61,-157.75,-156.84,-155.88,-154.87,-153.83,-152.76,-151.66,-150.55,-149.44,-148.33,-147.23,-146.15,-145.1,-144.08,-143.1,-142.17,-141.3,-140.49,-139.75,-139.08,-138.5,-137.99,-137.57,-137.24,-137.01,-136.87,-136.82,-136.87,-137.01,-137.25,-137.58,-138.0,-138.51,-139.1,-139.76,-140.51,-141.32,-142.19,-143.12,-144.1,-145.12,-146.17,-147.25,-148.35,-149.46,-150.58,-151.68,-152.78,-153.85,-154.89,-155.9,-156.86,-157.77,-158.62,-159.41,-160.12,-160.76,-161.32,-161.8,-162.19,-162.49,-162.69,-162.8,-162.81,-162.73,-162.56,-162.29,-161.93,-161.48,-160.94,-160.33,-159.63,-158.87,-158.04,-157.14,-156.2,-155.2,-154.17,-153.11,-152.02,-150.91,-149.8,-148.69,-147.59,-146.5,-145.43,-144.4,-143.41,-142.47,-141.58,-140.75,-139.98,-139.29,-138.68,-138.15,-137.7,-137.34,-137.08,-136.9,-136.82,-136.84,-136.96,-137.16,-137.46,-137.85,-138.33,-138.9,-139.54,-140.26,-141.05,-141.9,-142.81,-143.77,-144.78,-145.82,-146.9,-147.99,-149.1,-150.21,-151.33,-152.42,-153.51,-154.56,-155.58,-156.55,-157.48,-158.35,-159.16,-159.9,-160.57,-161.15,-161.66,-162.07,-162.4,-162.63,-162.77,-162.82,-162.77,-162.63,-162.39,-162.06,-161.63,-161.13,-160.54,-159.87,-159.12,-158.31,-157.44,-156.51,-155.53,-154.51,-153.46,-152.37,-151.27,-150.16,-149.05,-147.94,-146.85,-145.78,-144.73,-143.73,-142.77,-141.86,-141.01,-140.22,-139.51,-138.87,-138.31,-137.83,-137.45,-137.15,-136.95,-136.84,-136.83,-136.91,-137.09,-137.36,-137.72,-138.17,-138.7,-139.32,-140.02,-140.78,-141.62,-135.87,-135.19,-134.58,-134.06,-133.62,-133.28,-133.02,-132.86,-132.79,-132.82,-132.95,-133.16,-133.48,-133.88,-134.37,-134.94,-135.59,-136.32,-137.12,-137.98,-138.89,-139.86,-140.87,-141.92,-143.0,-144.09,-145.2,-146.32,-147.43,-148.53,-149.6,-150.65,-151.67,-152.64,-153.56,-154.42,-155.22,-155.95,-156.61,-157.19,-157.68,-158.09,-158.4,-158.63,-158.76,-158.79,-158.73,-158.57,-158.32,-157.98,-157.55,-157.03,-156.43,-155.75,-155.0,-154.18,-153.3,-152.37,-151.38,-150.36,-149.3,-148.22,-147.11,-146.0,-144.89,-143.78,-142.69,-141.62,-140.58,-139.58,-138.63,-137.73,-136.88,-136.11,-135.4,-134.77,-134.22,-133.75,-133.38,-133.09,-132.9,-132.8,-132.8,-132.9,-133.08,-133.36,-133.74,-134.2,-134.74,-135.37,-136.07,-136.85,-137.69,-138.59,-139.54,-140.54,-141.58,-142.65,-143.74,-144.84,-145.96,-147.07,-148.17,-149.26,-150.32,-151.34,-152.33,-153.27,-154.15,-154.97,-155.72,-156.41,-157.01,-157.53,-157.97,-158.31,-158.56,-158.72,-158.79,-158.76,-158.63,-158.41,-158.1,-157.7,-157.21,-156.64,-155.98,-155.25,-154.46,-153.6,-152.68,-151.71,-150.7,-149.65,-148.57,-147.47,-146.36,-145.25,-144.14,-143.04,-141.97,-140.92,-139.9,-138.93,-138.01,-137.15,-136.35,-135.62,-134.96,-134.39,-133.9,-133.49,-133.18,-132.95,-132.83,-132.79,-132.86,-133.01,-133.26,-133.61,-134.04,-134.56,-135.16,-135.84,-136.59,-137.41,-138.29,-139.23,-140.21,-141.24,-142.3,-143.38,-144.48,-145.6,-146.71,-147.82,-148.91,-149.98,-151.01,-152.01,-152.97,-153.87,-154.71,-155.49,-156.19,-156.82,-157.37,-157.83,-158.21,-158.49,-158.68,-158.78,-158.78,-158.69,-158.5,-158.21,-157.84,-157.38,-156.83,-156.2,-155.5,-154.72,-153.88,-152.98,-152.03,-151.03,-149.99,-148.92,-147.83,-146.72,-145.61,-144.5,-143.4,-142.31,-141.25,-140.23,-139.24,-138.3,-137.42,-136.6,-135.85,-135.17,-134.57,-134.05,-133.61,-133.27,-133.02,-132.86,-132.79,-132.82,-132.95,-133.17,-133.49,-133.89,-134.38,-134.96,-135.61,-136.34,-137.14,-138.0,-131.51,-130.86,-130.3,-129.81,-129.42,-129.12,-128.9,-128.79,-128.77,-128.84,-129.01,-129.27,-129.62,-130.07,-130.6,-131.21,-131.9,-132.66,-133.48,-134.37,-135.31,-136.3,-137.33,-138.4,-139.48,-140.59,-141.7,-142.81,-143.92,-145.01,-146.07,-147.11,-148.1,-149.05,-149.94,-150.78,-151.55,-152.24,-152.86,-153.4,-153.85,-154.22,-154.49,-154.67,-154.76,-154.74,-154.64,-154.44,-154.14,-153.76,-153.29,-152.73,-152.09,-151.38,-150.6,-149.75,-148.84,-147.88,-146.88,-145.84,-144.76,-143.67,-142.56,-141.45,-140.34,-139.24,-138.16,-137.1,-136.08,-135.1,-134.17,-133.29,-132.48,-131.74,-131.06,-130.47,-129.96,-129.54,-129.2,-128.96,-128.82,-128.76,-128.81,-128.94,-129.18,-129.5,-129.91,-130.42,-131.0,-131.66,-132.4,-133.21,-134.08,-135.0,-135.98,-137.0,-138.05,-139.13,-140.23,-141.34,-142.45,-143.56,-144.66,-145.73,-146.77,-147.78,-148.75,-149.66,-150.51,-151.3,-152.03,-152.67,-153.24,-153.72,-154.11,-154.41,-154.62,-154.74,-154.76,-154.68,-154.51,-154.25,-153.9,-153.45,-152.92,-152.31,-151.62,-150.86,-150.03,-149.14,-148.2,-147.21,-146.18,-145.11,-144.03,-142.92,-141.81,-140.7,-139.59,-138.5,-137.44,-136.41,-135.41,-134.46,-133.57,-132.74,-131.97,-131.27,-130.65,-130.12,-129.67,-129.3,-129.03,-128.85,-128.77,-128.78,-128.89,-129.09,-129.38,-129.77,-130.24,-130.8,-131.44,-132.15,-132.94,-133.79,-134.7,-135.66,-136.66,-137.7,-138.78,-139.87,-140.98,-142.09,-143.2,-144.3,-145.38,-146.44,-147.46,-148.44,-149.37,-150.24,-151.06,-151.8,-152.47,-153.06,-153.57,-153.99,-154.32,-154.57,-154.71,-154.76,-154.72,-154.58,-154.35,-154.02,-153.6,-153.1,-152.52,-151.85,-151.11,-150.31,-149.44,-148.51,-147.53,-146.52,-145.46,-144.38,-143.28,-142.17,-141.06,-139.95,-138.86,-137.78,-136.74,-135.73,-134.77,-133.85,-133.0,-132.21,-131.49,-130.85,-130.28,-129.8,-129.41,-129.11,-128.9,-128.79,-128.77,-128.84,-129.01,-129.28,-129.64,-130.08,-130.61,-131.22,-131.92,-132.68,-133.51,-134.4,-127.17,-126.56,-126.03,-125.59,-125.24,-124.98,-124.81,-124.74,-124.76,-124.88,-125.09,-125.4,-125.79,-126.28,-126.84,-127.49,-128.22,-129.01,-129.87,-130.78,-131.75,-132.75,-133.8,-134.88,-135.97,-137.08,-138.19,-139.3,-140.4,-141.48,-142.53,-143.55,-144.52,-145.45,-146.31,-147.12,-147.85,-148.52,-149.1,-149.6,-150.01,-150.33,-150.56,-150.69,-150.73,-150.68,-150.53,-150.28,-149.95,-149.52,-149.01,-148.41,-147.74,-146.99,-146.18,-145.3,-144.37,-143.39,-142.36,-141.31,-140.22,-139.12,-138.01,-136.9,-135.79,-134.7,-133.63,-132.59,-131.58,-130.63,-129.72,-128.87,-128.09,-127.38,-126.75,-126.19,-125.72,-125.34,-125.05,-124.85,-124.75,-124.74,-124.83,-125.01,-125.29,-125.66,-126.11,-126.65,-127.27,-127.97,-128.74,-129.58,-130.48,-131.43,-132.42,-133.46,-134.52,-135.61,-136.72,-137.83,-138.94,-140.05,-141.13,-142.2,-143.22,-144.21,-145.15,-146.04,-146.87,-147.62,-148.31,-148.92,-149.44,-149.88,-150.24,-150.49,-150.66,-150.73,-150.71,-150.59,-150.37,-150.07,-149.67,-149.18,-148.61,-147.97,-147.24,-146.45,-145.59,-144.68,-143.71,-142.7,-141.65,-140.58,-139.48,-138.37,-137.26,-136.15,-135.05,-133.97,-132.92,-131.9,-130.93,-130.01,-129.14,-128.34,-127.6,-126.94,-126.36,-125.87,-125.45,-125.13,-124.91,-124.77,-124.73,-124.79,-124.94,-125.19,-125.53,-125.95,-126.47,-127.06,-127.74,-128.49,-129.3,-130.18,-131.11,-132.1,-133.12,-134.18,-135.26,-136.36,-137.47,-138.58,-139.69,-140.78,-141.85,-142.9,-143.9,-144.85,-145.76,-146.6,-147.39,-148.1,-148.73,-149.28,-149.75,-150.13,-150.42,-150.62,-150.72,-150.72,-150.64,-150.45,-150.18,-149.81,-149.35,-148.81,-148.18,-147.48,-146.71,-145.88,-144.98,-144.03,-143.03,-142.0,-140.93,-139.84,-138.73,-137.62,-136.51,-135.4,-134.32,-133.26,-132.23,-131.24,-130.3,-129.42,-128.59,-127.83,-127.15,-126.54,-126.02,-125.58,-125.23,-124.97,-124.81,-124.74,-124.76,-124.88,-125.1,-125.41,-125.81,-126.29,-126.86,-127.51,-128.24,-129.03,-129.89,-130.81,-122.84,-122.27,-121.78,-121.38,-121.07,-120.86,-120.73,-120.71,-120.78,-120.94,-121.2,-121.54,-121.98,-122.51,-123.11,-123.79,-124.55,-125.37,-126.26,-127.2,-128.19,-129.21,-130.27,-131.36,-132.46,-133.57,-134.69,-135.79,-136.88,-137.95,-138.99,-139.98,-140.94,-141.83,-142.67,-143.44,-144.15,-144.77,-145.31,-145.77,-146.14,-146.42,-146.61,-146.7,-146.69,-146.59,-146.4,-146.11,-145.73,-145.26,-144.71,-144.08,-143.37,-142.59,-141.74,-140.84,-139.88,-138.88,-137.84,-136.77,-135.68,-134.57,-133.46,-132.35,-131.25,-130.16,-129.1,-128.08,-127.1,-126.16,-125.29,-124.47,-123.72,-123.04,-122.45,-121.93,-121.5,-121.16,-120.92,-120.76,-120.71,-120.74,-120.88,-121.1,-121.42,-121.83,-122.33,-122.91,-123.56,-124.3,-125.1,-125.97,-126.89,-127.86,-128.88,-129.93,-131.01,-132.1,-133.21,-134.33,-135.44,-136.53,-137.61,-138.66,-139.67,-140.63,-141.55,-142.41,-143.2,-143.93,-144.58,-145.15,-145.63,-146.03,-146.34,-146.56,-146.68,-146.7,-146.63,-146.47,-146.21,-145.86,-145.42,-144.9,-144.29,-143.61,-142.85,-142.02,-141.14,-140.2,-139.21,-138.18,-137.12,-136.04,-134.93,-133.82,-132.71,-131.6,-130.51,-129.44,-128.41,-127.41,-126.46,-125.56,-124.73,-123.96,-123.25,-122.63,-122.09,-121.63,-121.26,-120.99,-120.8,-120.71,-120.72,-120.82,-121.02,-121.31,-121.69,-122.16,-122.71,-123.34,-124.05,-124.83,-125.68,-126.58,-127.54,-128.54,-129.58,-130.65,-131.75,-132.85,-133.97,-135.08,-136.18,-137.26,-138.32,-139.34,-140.32,-141.26,-142.14,-142.95,-143.7,-144.37,-144.97,-145.48,-145.91,-146.25,-146.5,-146.65,-146.7,-146.67,-146.53,-146.3,-145.98,-145.57,-145.08,-144.5,-143.84,-143.1,-142.3,-141.43,-140.51,-139.54,-138.52,-137.47,-136.39,-135.29,-134.18,-133.07,-131.96,-130.86,-129.79,-128.74,-127.73,-126.76,-125.85,-124.99,-124.2,-123.47,-122.82,-122.26,-121.77,-121.37,-121.07,-120.85,-120.73,-120.71,-120.78,-120.94,-121.2,-121.55,-121.99,-122.52,-123.13,-123.81,-124.57,-125.4,-126.28,-127.22,-118.53,-118.0,-117.56,-117.2,-116.93,-116.76,-116.68,-116.7,-116.81,-117.02,-117.32,-117.71,-118.19,-118.75,-119.39,-120.11,-120.9,-121.75,-122.67,-123.63,-124.64,-125.68,-126.75,-127.85,-128.96,-130.07,-131.18,-132.28,-133.36,-134.41,-135.43,-136.41,-137.34,-138.21,-139.02,-139.76,-140.42,-141.01,-141.51,-141.93,-142.26,-142.49,-142.63,-142.68,-142.63,-142.48,-142.24,-141.91,-141.49,-140.98,-140.39,-139.72,-138.98,-138.17,-137.3,-136.37,-135.39,-134.37,-133.31,-132.23,-131.13,-130.02,-128.91,-127.8,-126.7,-125.63,-124.59,-123.58,-122.62,-121.72,-120.87,-120.08,-119.36,-118.72,-118.17,-117.69,-117.3,-117.01,-116.8,-116.7,-116.68,-116.76,-116.94,-117.21,-117.57,-118.02,-118.56,-119.18,-119.87,-120.64,-121.47,-122.36,-123.31,-124.3,-125.34,-126.4,-127.49,-128.6,-129.71,-130.82,-131.93,-133.01,-134.08,-135.11,-136.1,-137.04,-137.93,-138.76,-139.52,-140.21,-140.83,-141.36,-141.8,-142.16,-142.42,-142.6,-142.67,-142.65,-142.54,-142.33,-142.03,-141.64,-141.16,-140.59,-139.95,-139.23,-138.44,-137.59,-136.67,-135.71,-134.7,-133.66,-132.58,-131.49,-130.38,-129.27,-128.16,-127.06,-125.98,-124.92,-123.91,-122.93,-122.0,-121.13,-120.33,-119.59,-118.92,-118.34,-117.83,-117.42,-117.09,-116.86,-116.72,-116.68,-116.73,-116.87,-117.11,-117.45,-117.87,-118.38,-118.97,-119.64,-120.38,-121.19,-122.07,-123.0,-123.98,-125.0,-126.05,-127.14,-128.24,-129.35,-130.46,-131.57,-132.66,-133.73,-134.78,-135.78,-136.74,-137.65,-138.5,-139.28,-140.0,-140.64,-141.19,-141.67,-142.05,-142.35,-142.55,-142.66,-142.67,-142.59,-142.41,-142.14,-141.77,-141.32,-140.79,-140.17,-139.47,-138.7,-137.87,-136.98,-136.03,-135.03,-134.0,-132.94,-131.85,-130.74,-129.63,-128.52,-127.41,-126.33,-125.26,-124.23,-123.24,-122.3,-121.41,-120.58,-119.82,-119.13,-118.52,-117.99,-117.54,-117.19,-116.93,-116.76,-116.68,-116.7,-116.82,-117.03,-117.33,-117.72,-118.2,-118.77,-119.41,-120.13,-120.92,-121.78,-122.69,-123.66,-114.24,-113.75,-113.35,-113.03,-112.81,-112.68,-112.65,-112.71,-112.87,-113.12,-113.46,-113.9,-114.41,-115.02,-115.69,-116.45,-117.27,-118.15,-119.08,-120.07,-121.09,-122.15,-123.24,-124.34,-125.45,-126.56,-127.67,-128.76,-129.83,-130.87,-131.87,-132.82,-133.72,-134.57,-135.34,-136.05,-136.68,-137.23,-137.69,-138.06,-138.35,-138.54,-138.64,-138.64,-138.54,-138.35,-138.07,-137.7,-137.23,-136.69,-136.06,-135.35,-134.58,-133.74,-132.84,-131.88,-130.88,-129.85,-128.78,-127.69,-126.58,-125.47,-124.36,-123.25,-122.17,-121.11,-120.08,-119.1,-118.16,-117.28,-116.46,-115.71,-115.02,-114.42,-113.9,-113.47,-113.12,-112.87,-112.71,-112.65,-112.68,-112.81,-113.03,-113.34,-113.75,-114.24,-114.81,-115.47,-116.19,-116.99,-117.86,-118.77,-119.74,-120.76,-121.81,-122.88,-123.98,-125.09,-126.2,-127.31,-128.41,-129.49,-130.54,-131.55,-132.52,-133.44,-134.3,-135.1,-135.83,-136.48,-137.06,-137.55,-137.95,-138.27,-138.49,-138.61,-138.65,-138.58,-138.42,-138.17,-137.83,-137.39,-136.87,-136.27,-135.59,-134.84,-134.02,-133.14,-132.2,-131.21,-130.19,-129.13,-128.04,-126.94,-125.83,-124.72,-123.61,-122.52,-121.45,-120.41,-119.41,-118.46,-117.56,-116.72,-115.94,-115.24,-114.61,-114.06,-113.6,-113.23,-112.94,-112.75,-112.66,-112.66,-112.76,-112.95,-113.23,-113.6,-114.07,-114.62,-115.25,-115.95,-116.73,-117.57,-118.47,-119.42,-120.42,-121.46,-122.53,-123.62,-124.73,-125.84,-126.95,-128.06,-129.14,-130.2,-131.23,-132.21,-133.15,-134.03,-134.85,-135.6,-136.28,-136.88,-137.4,-137.83,-138.17,-138.43,-138.58,-138.65,-138.61,-138.49,-138.26,-137.95,-137.54,-137.05,-136.48,-135.82,-135.09,-134.29,-133.43,-132.51,-131.54,-130.52,-129.47,-128.4,-127.3,-126.19,-125.08,-123.97,-122.87,-121.79,-120.74,-119.73,-118.76,-117.84,-116.98,-116.19,-115.46,-114.8,-114.23,-113.74,-113.34,-113.02,-112.8,-112.68,-112.65,-112.71,-112.87,-113.13,-113.47,-113.91,-114.43,-115.03,-115.71,-116.47,-117.29,-118.17,-119.11,-120.1,-109.97,-109.52,-109.16,-108.89,-108.71,-108.63,-108.64,-108.74,-108.95,-109.24,-109.63,-110.1,-110.66,-111.3,-112.01,-112.8,-113.64,-114.55,-115.51,-116.52,-117.56,-118.63,-119.72,-120.83,-121.95,-123.06,-124.16,-125.24,-126.29,-127.32,-128.29,-129.22,-130.1,-130.91,-131.66,-132.33,-132.92,-133.43,-133.85,-134.18,-134.42,-134.57,-134.62,-134.57,-134.44,-134.2,-133.88,-133.46,-132.96,-132.37,-131.71,-130.97,-130.16,-129.29,-128.37,-127.39,-126.37,-125.32,-124.24,-123.14,-122.03,-120.92,-119.81,-118.71,-117.64,-116.59,-115.59,-114.62,-113.71,-112.86,-112.07,-111.35,-110.7,-110.14,-109.66,-109.27,-108.96,-108.76,-108.64,-108.62,-108.7,-108.87,-109.14,-109.49,-109.94,-110.47,-111.08,-111.77,-112.53,-113.36,-114.25,-115.2,-116.19,-117.22,-118.28,-119.37,-120.47,-121.58,-122.7,-123.8,-124.89,-125.96,-126.99,-127.98,-128.93,-129.82,-130.66,-131.42,-132.12,-132.73,-133.27,-133.72,-134.08,-134.35,-134.53,-134.61,-134.6,-134.49,-134.29,-133.99,-133.61,-133.13,-132.57,-131.93,-131.22,-130.43,-129.58,-128.67,-127.71,-126.71,-125.66,-124.59,-123.5,-122.39,-121.28,-120.17,-119.07,-117.98,-116.93,-115.91,-114.93,-114.0,-113.13,-112.32,-111.57,-110.9,-110.31,-109.8,-109.38,-109.05,-108.81,-108.67,-108.62,-108.66,-108.8,-109.04,-109.37,-109.78,-110.29,-110.87,-111.54,-112.28,-113.09,-113.96,-114.88,-115.86,-116.88,-117.93,-119.01,-120.11,-121.22,-122.34,-123.45,-124.54,-125.61,-126.66,-127.66,-128.63,-129.54,-130.39,-131.18,-131.9,-132.54,-133.11,-133.58,-133.98,-134.28,-134.48,-134.6,-134.61,-134.54,-134.36,-134.1,-133.74,-133.29,-132.76,-132.15,-131.46,-130.69,-129.86,-128.97,-128.03,-127.04,-126.01,-124.94,-123.85,-122.75,-121.64,-120.53,-119.42,-118.33,-117.27,-116.24,-115.24,-114.3,-113.4,-112.57,-111.81,-111.11,-110.5,-109.96,-109.51,-109.15,-108.88,-108.71,-108.62,-108.64,-108.75,-108.95,-109.25,-109.64,-110.11,-110.67,-111.31,-112.03,-112.82,-113.67,-114.58,-115.54,-116.54,-105.72,-105.31,-104.99,-104.76,-104.63,-104.59,-104.65,-104.8,-105.04,-105.38,-105.81,-106.32,-106.92,-107.59,-108.34,-109.16,-110.04,-110.97,-111.95,-112.97,-114.03,-115.11,-116.22,-117.33,-118.44,-119.55,-120.64,-121.71,-122.75,-123.75,-124.71,-125.61,-126.46,-127.24,-127.95,-128.59,-129.14,-129.61,-129.99,-130.28,-130.47,-130.57,-130.58,-130.49,-130.31,-130.03,-129.66,-129.21,-128.66,-128.04,-127.34,-126.57,-125.73,-124.83,-123.88,-122.89,-121.85,-120.79,-119.7,-118.59,-117.48,-116.36,-115.26,-114.18,-113.11,-112.09,-111.1,-110.16,-109.27,-108.45,-107.69,-107.01,-106.4,-105.87,-105.43,-105.08,-104.83,-104.66,-104.59,-104.62,-104.74,-104.95,-105.26,-105.66,-106.15,-106.72,-107.37,-108.09,-108.89,-109.74,-110.66,-111.63,-112.64,-113.68,-114.76,-115.86,-116.97,-118.08,-119.19,-120.29,-121.37,-122.42,-123.43,-124.4,-125.33,-126.19,-127.0,-127.73,-128.39,-128.97,-129.46,-129.87,-130.19,-130.42,-130.55,-130.59,-130.53,-130.38,-130.13,-129.79,-129.36,-128.85,-128.25,-127.58,-126.83,-126.01,-125.13,-124.2,-123.22,-122.19,-121.13,-120.05,-118.95,-117.84,-116.72,-115.62,-114.53,-113.46,-112.42,-111.41,-110.46,-109.55,-108.71,-107.93,-107.22,-106.59,-106.03,-105.57,-105.19,-104.9,-104.7,-104.6,-104.6,-104.69,-104.87,-105.15,-105.52,-105.98,-106.52,-107.15,-107.85,-108.62,-109.46,-110.36,-111.31,-112.31,-113.34,-114.41,-115.5,-116.61,-117.72,-118.83,-119.93,-121.02,-122.08,-123.11,-124.09,-125.03,-125.92,-126.74,-127.5,-128.18,-128.79,-129.31,-129.75,-130.1,-130.36,-130.52,-130.59,-130.56,-130.44,-130.22,-129.91,-129.51,-129.03,-128.45,-127.8,-127.08,-126.28,-125.42,-124.51,-123.54,-122.53,-121.48,-120.4,-119.31,-118.2,-117.09,-115.98,-114.88,-113.8,-112.75,-111.73,-110.76,-109.84,-108.98,-108.17,-107.44,-106.78,-106.2,-105.71,-105.3,-104.98,-104.76,-104.63,-104.59,-104.65,-104.8,-105.05,-105.39,-105.82,-106.34,-106.94,-107.61,-108.36,-109.18,-110.06,-110.99,-111.98,-113.0,-101.49,-101.12,-100.84,-100.66,-100.57,-100.58,-100.68,-100.87,-101.16,-101.54,-102.01,-102.56,-103.2,-103.91,-104.69,-105.53,-106.44,-107.4,-108.4,-109.44,-110.51,-111.6,-112.71,-113.82,-114.93,-116.03,-117.12,-118.17,-119.2,-120.18,-121.11,-121.99,-122.81,-123.56,-124.23,-124.83,-125.34,-125.77,-126.11,-126.35,-126.5,-126.56,-126.52,-126.39,-126.16,-125.84,-125.43,-124.93,-124.35,-123.69,-122.96,-122.15,-121.29,-120.37,-119.39,-118.38,-117.33,-116.25,-115.15,-114.04,-112.92,-111.82,-110.72,-109.64,-108.6,-107.59,-106.62,-105.71,-104.85,-104.05,-103.33,-102.68,-102.11,-101.63,-101.23,-100.92,-100.71,-100.59,-100.56,-100.63,-100.8,-101.06,-101.41,-101.85,-102.38,-102.98,-103.67,-104.43,-105.25,-106.14,-107.08,-108.07,-109.1,-110.16,-111.24,-112.35,-113.46,-114.57,-115.68,-116.77,-117.84,-118.87,-119.87,-120.82,-121.71,-122.55,-123.32,-124.02,-124.64,-125.18,-125.64,-126.01,-126.28,-126.46,-126.55,-126.55,-126.44,-126.25,-125.95,-125.57,-125.1,-124.55,-123.91,-123.2,-122.42,-121.58,-120.67,-119.71,-118.71,-117.67,-116.6,-115.51,-114.4,-113.29,-112.17,-111.07,-109.99,-108.93,-107.91,-106.93,-106.0,-105.12,-104.3,-103.56,-102.88,-102.29,-101.78,-101.35,-101.01,-100.77,-100.62,-100.56,-100.6,-100.74,-100.97,-101.29,-101.7,-102.2,-102.78,-103.44,-104.17,-104.98,-105.85,-106.77,-107.74,-108.76,-109.81,-110.89,-111.99,-113.1,-114.21,-115.32,-116.42,-117.49,-118.54,-119.55,-120.51,-121.43,-122.29,-123.08,-123.8,-124.45,-125.02,-125.5,-125.9,-126.2,-126.42,-126.53,-126.56,-126.49,-126.32,-126.06,-125.71,-125.27,-124.74,-124.13,-123.44,-122.68,-121.86,-120.97,-120.03,-119.04,-118.01,-116.95,-115.86,-114.76,-113.65,-112.53,-111.43,-110.34,-109.27,-108.24,-107.24,-106.29,-105.4,-104.56,-103.79,-103.09,-102.47,-101.93,-101.48,-101.11,-100.84,-100.66,-100.57,-100.58,-100.68,-100.88,-101.17,-101.55,-102.03,-102.58,-103.22,-103.93,-104.71,-105.56,-106.46,-107.42,-108.43,-109.47,-97.28,-96.95,-96.72,-96.58,-96.53,-96.58,-96.73,-96.97,-97.3,-97.72,-98.23,-98.82,-99.49,-100.24,-101.05,-101.92,-102.85,-103.83,-104.85,-105.91,-106.99,-108.09,-109.2,-110.32,-111.42,-112.52,-113.59,-114.63,-115.64,-116.6,-117.5,-118.35,-119.14,-119.85,-120.49,-121.05,-121.52,-121.91,-122.2,-122.41,-122.51,-122.53,-122.44,-122.26,-121.99,-121.63,-121.18,-120.64,-120.02,-119.33,-118.56,-117.73,-116.83,-115.88,-114.89,-113.86,-112.79,-111.7,-110.6,-109.49,-108.37,-107.27,-106.18,-105.12,-104.09,-103.1,-102.16,-101.27,-100.44,-99.68,-98.99,-98.37,-97.84,-97.4,-97.05,-96.78,-96.61,-96.54,-96.56,-96.67,-96.88,-97.18,-97.58,-98.06,-98.62,-99.27,-99.99,-100.78,-101.63,-102.55,-103.51,-104.52,-105.56,-106.64,-107.73,-108.84,-109.96,-111.07,-112.17,-113.24,-114.3,-115.32,-116.29,-117.22,-118.09,-118.89,-119.63,-120.29,-120.88,-121.38,-121.79,-122.12,-122.35,-122.49,-122.53,-122.48,-122.33,-122.09,-121.76,-121.33,-120.82,-120.23,-119.56,-118.82,-118.0,-117.13,-116.2,-115.22,-114.2,-113.14,-112.06,-110.96,-109.85,-108.73,-107.63,-106.53,-105.46,-104.42,-103.41,-102.46,-101.55,-100.7,-99.92,-99.2,-98.56,-98.01,-97.54,-97.15,-96.86,-96.66,-96.55,-96.54,-96.62,-96.8,-97.08,-97.44,-97.89,-98.43,-99.05,-99.75,-100.52,-101.35,-102.24,-103.19,-104.19,-105.22,-106.29,-107.38,-108.48,-109.59,-110.71,-111.81,-112.9,-113.96,-114.99,-115.98,-116.92,-117.81,-118.64,-119.4,-120.09,-120.7,-121.23,-121.67,-122.02,-122.29,-122.45,-122.53,-122.51,-122.39,-122.18,-121.88,-121.48,-121.0,-120.43,-119.79,-119.07,-118.27,-117.42,-116.51,-115.54,-114.53,-113.49,-112.41,-111.32,-110.21,-109.09,-107.98,-106.88,-105.81,-104.75,-103.74,-102.76,-101.84,-100.97,-100.16,-99.43,-98.76,-98.18,-97.68,-97.27,-96.94,-96.71,-96.57,-96.53,-96.59,-96.73,-96.98,-97.31,-97.74,-98.25,-98.84,-99.51,-100.26,-101.07,-101.95,-102.88,-103.86,-104.88,-105.94,-93.08,-92.8,-92.61,-92.52,-92.52,-92.61,-92.8,-93.09,-93.46,-93.92,-94.47,-95.1,-95.81,-96.58,-97.42,-98.33,-99.28,-100.28,-101.32,-102.39,-103.48,-104.58,-105.7,-106.81,-107.91,-109.0,-110.06,-111.08,-112.07,-113.0,-113.88,-114.7,-115.46,-116.13,-116.74,-117.25,-117.69,-118.03,-118.28,-118.44,-118.5,-118.47,-118.34,-118.12,-117.8,-117.4,-116.91,-116.33,-115.68,-114.95,-114.15,-113.28,-112.36,-111.39,-110.38,-109.33,-108.25,-107.16,-106.05,-104.93,-103.82,-102.73,-101.65,-100.6,-99.59,-98.62,-97.7,-96.84,-96.04,-95.31,-94.66,-94.09,-93.6,-93.19,-92.88,-92.66,-92.54,-92.51,-92.57,-92.73,-92.98,-93.33,-93.76,-94.28,-94.89,-95.57,-96.32,-97.14,-98.03,-98.97,-99.95,-100.98,-102.04,-103.12,-104.22,-105.34,-106.45,-107.56,-108.65,-109.71,-110.75,-111.75,-112.7,-113.6,-114.44,-115.22,-115.92,-116.55,-117.1,-117.56,-117.93,-118.21,-118.4,-118.49,-118.49,-118.39,-118.2,-117.92,-117.54,-117.08,-116.53,-115.9,-115.19,-114.41,-113.57,-112.67,-111.71,-110.71,-109.68,-108.61,-107.51,-106.41,-105.29,-104.18,-103.08,-102.0,-100.94,-99.91,-98.93,-97.99,-97.11,-96.29,-95.54,-94.86,-94.26,-93.75,-93.31,-92.97,-92.72,-92.57,-92.5,-92.54,-92.67,-92.89,-93.21,-93.61,-94.11,-94.68,-95.34,-96.07,-96.87,-97.74,-98.66,-99.63,-100.64,-101.69,-102.77,-103.87,-104.98,-106.09,-107.2,-108.3,-109.37,-110.42,-111.43,-112.4,-113.32,-114.18,-114.98,-115.7,-116.36,-116.93,-117.42,-117.82,-118.13,-118.35,-118.47,-118.5,-118.44,-118.27,-118.02,-117.67,-117.24,-116.71,-116.11,-115.43,-114.67,-113.85,-112.97,-112.03,-111.04,-110.02,-108.96,-107.87,-106.77,-105.66,-104.54,-103.44,-102.35,-101.28,-100.24,-99.24,-98.29,-97.39,-96.55,-95.78,-95.08,-94.45,-93.9,-93.44,-93.07,-92.79,-92.61,-92.51,-92.52,-92.62,-92.81,-93.09,-93.47,-93.94,-94.49,-95.12,-95.83,-96.6,-97.45,-98.35,-99.31,-100.31,-101.35,-102.42,-88.91,-88.67,-88.52,-88.47,-88.52,-88.66,-88.9,-89.22,-89.64,-90.14,-90.73,-91.39,-92.13,-92.94,-93.81,-94.74,-95.72,-96.73,-97.79,-98.87,-99.97,-101.08,-102.19,-103.3,-104.4,-105.47,-106.51,-107.52,-108.48,-109.39,-110.25,-111.04,-111.76,-112.4,-112.96,-113.44,-113.83,-114.13,-114.34,-114.45,-114.47,-114.39,-114.22,-113.95,-113.6,-113.15,-112.62,-112.0,-111.31,-110.55,-109.72,-108.83,-107.89,-106.89,-105.86,-104.8,-103.71,-102.61,-101.49,-100.38,-99.28,-98.19,-97.12,-96.09,-95.1,-94.15,-93.26,-92.43,-91.66,-90.97,-90.35,-89.82,-89.37,-89.01,-88.74,-88.56,-88.48,-88.5,-88.6,-88.81,-89.11,-89.49,-89.97,-90.53,-91.17,-91.89,-92.67,-93.52,-94.43,-95.39,-96.4,-97.44,-98.52,-99.61,-100.72,-101.83,-102.94,-104.04,-105.12,-106.18,-107.2,-108.18,-109.1,-109.98,-110.79,-111.53,-112.2,-112.79,-113.29,-113.71,-114.04,-114.28,-114.43,-114.47,-114.43,-114.29,-114.05,-113.72,-113.3,-112.8,-112.21,-111.55,-110.81,-110.0,-109.12,-108.2,-107.22,-106.2,-105.15,-104.07,-102.97,-101.86,-100.74,-99.63,-98.54,-97.47,-96.42,-95.42,-94.45,-93.54,-92.69,-91.9,-91.19,-90.54,-89.98,-89.5,-89.11,-88.81,-88.61,-88.5,-88.48,-88.56,-88.73,-89.0,-89.36,-89.81,-90.34,-90.95,-91.65,-92.41,-93.24,-94.13,-95.08,-96.07,-97.1,-98.17,-99.25,-100.36,-101.47,-102.58,-103.69,-104.78,-105.84,-106.87,-107.86,-108.81,-109.7,-110.53,-111.3,-111.99,-112.61,-113.14,-113.59,-113.95,-114.22,-114.39,-114.47,-114.45,-114.34,-114.14,-113.84,-113.45,-112.97,-112.41,-111.77,-111.05,-110.27,-109.41,-108.5,-107.54,-106.54,-105.49,-104.42,-103.32,-102.22,-101.1,-99.99,-98.89,-97.81,-96.76,-95.74,-94.76,-93.83,-92.96,-92.15,-91.41,-90.74,-90.15,-89.65,-89.23,-88.9,-88.66,-88.52,-88.47,-88.52,-88.67,-88.9,-89.23,-89.65,-90.16,-90.75,-91.41,-92.16,-92.96,-93.84,-94.77,-95.74,-96.76,-97.82,-98.9,-84.76,-84.56,-84.46,-84.46,-84.55,-84.73,-85.01,-85.38,-85.84,-86.38,-87.0,-87.7,-88.48,-89.32,-90.21,-91.16,-92.16,-93.2,-94.26,-95.35,-96.46,-97.57,-98.69,-99.79,-100.87,-101.94,-102.96,-103.95,-104.89,-105.77,-106.6,-107.35,-108.04,-108.64,-109.17,-109.61,-109.96,-110.21,-110.38,-110.44,-110.42,-110.29,-110.08,-109.77,-109.37,-108.88,-108.31,-107.66,-106.93,-106.14,-105.28,-104.36,-103.4,-102.38,-101.34,-100.26,-99.16,-98.06,-96.94,-95.83,-94.73,-93.66,-92.61,-91.59,-90.62,-89.7,-88.83,-88.03,-87.3,-86.64,-86.06,-85.57,-85.16,-84.84,-84.61,-84.48,-84.45,-84.51,-84.66,-84.91,-85.25,-85.68,-86.19,-86.79,-87.47,-88.22,-89.04,-89.92,-90.85,-91.83,-92.86,-93.92,-95.0,-96.1,-97.21,-98.33,-99.43,-100.52,-101.59,-102.63,-103.63,-104.59,-105.49,-106.34,-107.12,-107.83,-108.46,-109.01,-109.47,-109.85,-110.14,-110.33,-110.43,-110.44,-110.34,-110.16,-109.88,-109.51,-109.05,-108.51,-107.88,-107.18,-106.4,-105.57,-104.67,-103.71,-102.72,-101.68,-100.61,-99.52,-98.42,-97.3,-96.19,-95.09,-94.0,-92.94,-91.92,-90.93,-89.99,-89.11,-88.28,-87.53,-86.84,-86.24,-85.72,-85.28,-84.93,-84.68,-84.52,-84.45,-84.48,-84.6,-84.82,-85.13,-85.53,-86.02,-86.59,-87.24,-87.97,-88.76,-89.62,-90.54,-91.51,-92.52,-93.57,-94.65,-95.74,-96.85,-97.96,-99.07,-100.17,-101.25,-102.3,-103.31,-104.29,-105.21,-106.07,-106.87,-107.6,-108.26,-108.84,-109.33,-109.74,-110.06,-110.28,-110.41,-110.45,-110.38,-110.23,-109.98,-109.64,-109.21,-108.69,-108.09,-107.41,-106.66,-105.84,-104.96,-104.03,-103.05,-102.02,-100.96,-99.88,-98.78,-97.66,-96.55,-95.44,-94.35,-93.28,-92.24,-91.24,-90.29,-89.39,-88.54,-87.76,-87.06,-86.43,-85.88,-85.41,-85.04,-84.75,-84.56,-84.46,-84.46,-84.55,-84.74,-85.02,-85.39,-85.85,-86.39,-87.02,-87.72,-88.5,-89.34,-90.24,-91.19,-92.19,-93.23,-94.29,-95.38,-80.62,-80.47,-80.42,-80.46,-80.59,-80.82,-81.14,-81.55,-82.05,-82.63,-83.29,-84.03,-84.83,-85.7,-86.63,-87.6,-88.62,-89.67,-90.75,-91.84,-92.95,-94.07,-95.18,-96.27,-97.35,-98.39,-99.4,-100.37,-101.28,-102.14,-102.93,-103.66,-104.3,-104.87,-105.36,-105.75,-106.06,-106.27,-106.39,-106.41,-106.34,-106.18,-105.92,-105.56,-105.12,-104.59,-103.99,-103.3,-102.54,-101.71,-100.83,-99.89,-98.9,-97.87,-96.81,-95.72,-94.62,-93.5,-92.39,-91.29,-90.2,-89.13,-88.09,-87.1,-86.15,-85.25,-84.42,-83.65,-82.95,-82.33,-81.79,-81.33,-80.97,-80.69,-80.51,-80.43,-80.43,-80.54,-80.74,-81.03,-81.41,-81.88,-82.44,-83.07,-83.78,-84.57,-85.41,-86.32,-87.28,-88.28,-89.32,-90.39,-91.49,-92.59,-93.71,-94.82,-95.92,-97.0,-98.06,-99.08,-100.06,-100.99,-101.87,-102.68,-103.43,-104.1,-104.7,-105.21,-105.63,-105.97,-106.21,-106.36,-106.42,-106.38,-106.24,-106.01,-105.69,-105.27,-104.78,-104.19,-103.53,-102.79,-101.99,-101.12,-100.2,-99.22,-98.21,-97.15,-96.07,-94.97,-93.86,-92.75,-91.64,-90.55,-89.47,-88.43,-87.42,-86.45,-85.54,-84.68,-83.89,-83.17,-82.52,-81.95,-81.47,-81.08,-80.77,-80.56,-80.44,-80.42,-80.49,-80.66,-80.92,-81.28,-81.72,-82.25,-82.86,-83.55,-84.31,-85.13,-86.02,-86.96,-87.95,-88.98,-90.04,-91.13,-92.23,-93.35,-94.46,-95.56,-96.65,-97.72,-98.75,-99.75,-100.7,-101.59,-102.43,-103.2,-103.89,-104.51,-105.05,-105.51,-105.87,-106.14,-106.32,-106.41,-106.4,-106.29,-106.09,-105.8,-105.42,-104.95,-104.39,-103.75,-103.04,-102.26,-101.41,-100.5,-99.54,-98.54,-97.5,-96.43,-95.33,-94.23,-93.11,-92.0,-90.9,-89.82,-88.76,-87.74,-86.76,-85.83,-84.95,-84.14,-83.39,-82.72,-82.13,-81.62,-81.19,-80.86,-80.62,-80.47,-80.42,-80.46,-80.6,-80.83,-81.15,-81.57,-82.07,-82.65,-83.31,-84.05,-84.86,-85.73,-86.65,-87.63,-88.64,-89.7,-90.78,-91.87,-76.51,-76.41,-76.4,-76.48,-76.66,-76.93,-77.3,-77.75,-78.29,-78.91,-79.6,-80.37,-81.21,-82.1,-83.05,-84.04,-85.08,-86.14,-87.23,-88.34,-89.45,-90.56,-91.67,-92.75,-93.82,-94.85,-95.83,-96.78,-97.67,-98.49,-99.25,-99.94,-100.55,-101.08,-101.53,-101.88,-102.14,-102.31,-102.38,-102.36,-102.25,-102.04,-101.73,-101.34,-100.86,-100.29,-99.64,-98.92,-98.13,-97.28,-96.36,-95.4,-94.39,-93.34,-92.27,-91.17,-90.06,-88.95,-87.84,-86.74,-85.66,-84.61,-83.59,-82.62,-81.69,-80.82,-80.02,-79.28,-78.62,-78.04,-77.54,-77.12,-76.8,-76.57,-76.43,-76.39,-76.44,-76.59,-76.83,-77.17,-77.59,-78.1,-78.7,-79.37,-80.11,-80.93,-81.8,-82.74,-83.72,-84.74,-85.79,-86.88,-87.98,-89.09,-90.2,-91.31,-92.4,-93.47,-94.52,-95.52,-96.48,-97.38,-98.23,-99.02,-99.73,-100.36,-100.92,-101.39,-101.77,-102.07,-102.27,-102.37,-102.38,-102.3,-102.11,-101.84,-101.48,-101.02,-100.48,-99.86,-99.16,-98.39,-97.56,-96.66,-95.72,-94.72,-93.69,-92.62,-91.53,-90.43,-89.31,-88.2,-87.1,-86.01,-84.95,-83.92,-82.93,-81.99,-81.1,-80.27,-79.51,-78.83,-78.22,-77.69,-77.25,-76.89,-76.63,-76.46,-76.39,-76.41,-76.53,-76.74,-77.05,-77.45,-77.93,-78.5,-79.14,-79.87,-80.66,-81.51,-82.43,-83.39,-84.4,-85.45,-86.52,-87.62,-88.73,-89.84,-90.95,-92.05,-93.13,-94.18,-95.2,-96.17,-97.1,-97.96,-98.77,-99.5,-100.17,-100.75,-101.25,-101.66,-101.98,-102.21,-102.35,-102.39,-102.33,-102.18,-101.94,-101.6,-101.18,-100.67,-100.07,-99.4,-98.65,-97.84,-96.96,-96.03,-95.05,-94.03,-92.97,-91.89,-90.78,-89.67,-88.56,-87.45,-86.36,-85.29,-84.25,-83.24,-82.29,-81.38,-80.53,-79.75,-79.04,-78.4,-77.85,-77.38,-77.0,-76.71,-76.51,-76.4,-76.4,-76.48,-76.67,-76.94,-77.31,-77.76,-78.3,-78.92,-79.62,-80.39,-81.23,-82.13,-83.07,-84.07,-85.11,-86.17,-87.26,-88.37,-72.42,-72.36,-72.39,-72.52,-72.75,-73.06,-73.47,-73.96,-74.54,-75.2,-75.93,-76.73,-77.59,-78.51,-79.48,-80.5,-81.55,-82.62,-83.72,-84.83,-85.94,-87.05,-88.15,-89.23,-90.28,-91.29,-92.26,-93.17,-94.03,-94.83,-95.56,-96.21,-96.78,-97.27,-97.67,-97.99,-98.2,-98.33,-98.36,-98.29,-98.13,-97.88,-97.53,-97.09,-96.57,-95.97,-95.28,-94.53,-93.71,-92.82,-91.89,-90.9,-89.87,-88.81,-87.73,-86.62,-85.51,-84.4,-83.29,-82.2,-81.13,-80.1,-79.1,-78.15,-77.25,-76.41,-75.63,-74.93,-74.31,-73.76,-73.3,-72.93,-72.65,-72.46,-72.37,-72.37,-72.47,-72.66,-72.95,-73.33,-73.79,-74.34,-74.97,-75.68,-76.46,-77.3,-78.21,-79.16,-80.16,-81.2,-82.27,-83.36,-84.47,-85.58,-86.69,-87.8,-88.88,-89.94,-90.96,-91.95,-92.88,-93.76,-94.58,-95.33,-96.01,-96.61,-97.12,-97.55,-97.89,-98.14,-98.3,-98.36,-98.32,-98.19,-97.97,-97.65,-97.24,-96.75,-96.17,-95.51,-94.78,-93.98,-93.12,-92.2,-91.22,-90.21,-89.16,-88.08,-86.98,-85.87,-84.76,-83.65,-82.55,-81.48,-80.43,-79.42,-78.45,-77.53,-76.67,-75.88,-75.15,-74.5,-73.93,-73.44,-73.04,-72.73,-72.51,-72.39,-72.36,-72.43,-72.59,-72.85,-73.2,-73.63,-74.16,-74.76,-75.44,-76.2,-77.02,-77.91,-78.85,-79.83,-80.86,-81.92,-83.01,-84.11,-85.22,-86.34,-87.44,-88.53,-89.6,-90.64,-91.63,-92.58,-93.48,-94.32,-95.09,-95.8,-96.42,-96.97,-97.42,-97.79,-98.07,-98.26,-98.35,-98.35,-98.25,-98.05,-97.76,-97.39,-96.92,-96.37,-95.74,-95.03,-94.25,-93.4,-92.5,-91.54,-90.54,-89.5,-88.43,-87.34,-86.23,-85.12,-84.01,-82.91,-81.82,-80.77,-79.74,-78.76,-77.83,-76.95,-76.13,-75.38,-74.7,-74.1,-73.59,-73.16,-72.82,-72.57,-72.42,-72.36,-72.4,-72.53,-72.75,-73.07,-73.48,-73.98,-74.56,-75.21,-75.95,-76.75,-77.61,-78.54,-79.51,-80.52,-81.57,-82.65,-83.75,-84.86,-68.35,-68.34,-68.41,-68.59,-68.86,-69.21,-69.66,-70.19,-70.81,-71.5,-72.27,-73.1,-73.99,-74.93,-75.93,-76.96,-78.02,-79.11,-80.21,-81.33,-82.44,-83.54,-84.63,-85.7,-86.73,-87.72,-88.67,-89.56,-90.39,-91.15,-91.85,-92.46,-93.0,-93.44,-93.8,-94.07,-94.25,-94.33,-94.31,-94.2,-93.99,-93.7,-93.31,-92.83,-92.27,-91.63,-90.91,-90.12,-89.27,-88.36,-87.4,-86.39,-85.35,-84.28,-83.18,-82.07,-80.96,-79.85,-78.75,-77.67,-76.61,-75.59,-74.62,-73.69,-72.82,-72.01,-71.27,-70.6,-70.01,-69.51,-69.09,-68.76,-68.52,-68.38,-68.33,-68.38,-68.52,-68.76,-69.09,-69.51,-70.01,-70.6,-71.27,-72.01,-72.82,-73.69,-74.62,-75.6,-76.62,-77.67,-78.75,-79.85,-80.96,-82.08,-83.19,-84.28,-85.35,-86.4,-87.4,-88.36,-89.27,-90.13,-90.91,-91.63,-92.27,-92.83,-93.31,-93.7,-93.99,-94.2,-94.31,-94.33,-94.25,-94.07,-93.8,-93.44,-92.99,-92.46,-91.84,-91.15,-90.39,-89.55,-88.66,-87.72,-86.72,-85.69,-84.63,-83.54,-82.43,-81.32,-80.21,-79.1,-78.02,-76.95,-75.92,-74.93,-73.98,-73.09,-72.26,-71.5,-70.81,-70.19,-69.66,-69.21,-68.85,-68.59,-68.41,-68.34,-68.35,-68.47,-68.67,-68.97,-69.36,-69.84,-70.4,-71.04,-71.76,-72.55,-73.4,-74.31,-75.28,-76.28,-77.33,-78.4,-79.5,-80.6,-81.72,-82.83,-83.93,-85.01,-86.06,-87.08,-88.06,-88.98,-89.86,-90.66,-91.41,-92.07,-92.66,-93.16,-93.58,-93.91,-94.14,-94.28,-94.33,-94.28,-94.14,-93.9,-93.57,-93.15,-92.64,-92.05,-91.38,-90.64,-89.83,-88.96,-88.03,-87.05,-86.03,-84.97,-83.89,-82.79,-81.68,-80.57,-79.46,-78.37,-77.29,-76.25,-75.25,-74.29,-73.38,-72.53,-71.74,-71.02,-70.38,-69.82,-69.35,-68.96,-68.66,-68.46,-68.35,-68.34,-68.42,-68.59,-68.86,-69.23,-69.67,-70.21,-70.83,-71.52,-72.29,-73.12,-74.01,-74.96,-75.95,-76.99,-78.05,-79.14,-80.24,-81.36,-64.3,-64.33,-64.46,-64.67,-64.98,-65.38,-65.87,-66.45,-67.1,-67.82,-68.62,-69.48,-70.4,-71.37,-72.38,-73.42,-74.5,-75.6,-76.71,-77.82,-78.93,-80.03,-81.11,-82.16,-83.17,-84.14,-85.06,-85.93,-86.73,-87.46,-88.12,-88.69,-89.19,-89.6,-89.91,-90.14,-90.27,-90.3,-90.24,-90.09,-89.84,-89.49,-89.06,-88.55,-87.95,-87.27,-86.52,-85.7,-84.82,-83.89,-82.9,-81.88,-80.82,-79.73,-78.63,-77.52,-76.41,-75.3,-74.21,-73.14,-72.1,-71.1,-70.15,-69.24,-68.4,-67.62,-66.91,-66.28,-65.73,-65.27,-64.89,-64.61,-64.41,-64.32,-64.31,-64.41,-64.59,-64.87,-65.25,-65.71,-66.25,-66.88,-67.58,-68.35,-69.19,-70.09,-71.05,-72.04,-73.08,-74.15,-75.24,-76.35,-77.46,-78.57,-79.67,-80.76,-81.82,-82.85,-83.83,-84.77,-85.65,-86.48,-87.23,-87.91,-88.52,-89.04,-89.47,-89.82,-90.07,-90.23,-90.3,-90.27,-90.15,-89.93,-89.62,-89.21,-88.72,-88.15,-87.5,-86.77,-85.97,-85.11,-84.19,-83.23,-82.21,-81.17,-80.09,-78.99,-77.88,-76.77,-75.66,-74.56,-73.48,-72.43,-71.42,-70.45,-69.53,-68.67,-67.87,-67.14,-66.48,-65.9,-65.41,-65.0,-64.69,-64.47,-64.34,-64.3,-64.36,-64.52,-64.77,-65.11,-65.55,-66.06,-66.67,-67.34,-68.1,-68.92,-69.8,-70.73,-71.72,-72.74,-73.8,-74.88,-75.99,-77.1,-78.21,-79.32,-80.41,-81.48,-82.52,-83.52,-84.47,-85.37,-86.22,-86.99,-87.7,-88.33,-88.88,-89.34,-89.72,-90.0,-90.19,-90.29,-90.29,-90.2,-90.01,-89.73,-89.35,-88.89,-88.35,-87.72,-87.01,-86.24,-85.4,-84.5,-83.54,-82.55,-81.51,-80.44,-79.35,-78.24,-77.13,-76.02,-74.92,-73.83,-72.77,-71.74,-70.76,-69.82,-68.94,-68.12,-67.36,-66.68,-66.08,-65.56,-65.13,-64.78,-64.53,-64.37,-64.3,-64.33,-64.46,-64.68,-64.99,-65.4,-65.89,-66.46,-67.12,-67.84,-68.64,-69.5,-70.42,-71.39,-72.4,-73.45,-74.53,-75.63,-76.74,-77.85,-60.28,-60.35,-60.52,-60.78,-61.13,-61.57,-62.1,-62.71,-63.4,-64.16,-64.99,-65.88,-66.82,-67.81,-68.84,-69.9,-70.99,-72.09,-73.2,-74.31,-75.42,-76.51,-77.57,-78.61,-79.6,-80.55,-81.45,-82.28,-83.05,-83.75,-84.37,-84.91,-85.36,-85.73,-86.0,-86.18,-86.27,-86.26,-86.15,-85.95,-85.66,-85.27,-84.8,-84.25,-83.61,-82.9,-82.11,-81.27,-80.36,-79.4,-78.4,-77.35,-76.28,-75.19,-74.08,-72.97,-71.86,-70.76,-69.67,-68.62,-67.6,-66.62,-65.69,-64.81,-64.0,-63.25,-62.58,-61.99,-61.48,-61.05,-60.72,-60.47,-60.33,-60.27,-60.32,-60.45,-60.68,-61.01,-61.42,-61.92,-62.51,-63.17,-63.91,-64.71,-65.58,-66.51,-67.48,-68.5,-69.55,-70.63,-71.73,-72.84,-73.95,-75.06,-76.16,-77.23,-78.28,-79.29,-80.25,-81.16,-82.02,-82.81,-83.53,-84.18,-84.74,-85.22,-85.62,-85.92,-86.13,-86.25,-86.27,-86.2,-86.03,-85.76,-85.41,-84.97,-84.44,-83.82,-83.14,-82.38,-81.55,-80.66,-79.72,-78.73,-77.7,-76.63,-75.55,-74.44,-73.33,-72.22,-71.11,-70.02,-68.96,-67.92,-66.93,-65.98,-65.09,-64.25,-63.48,-62.79,-62.17,-61.63,-61.18,-60.82,-60.54,-60.36,-60.28,-60.29,-60.4,-60.6,-60.89,-61.28,-61.75,-62.31,-62.95,-63.66,-64.44,-65.29,-66.2,-67.16,-68.16,-69.21,-70.28,-71.37,-72.48,-73.59,-74.7,-75.8,-76.89,-77.94,-78.96,-79.94,-80.87,-81.75,-82.56,-83.31,-83.98,-84.57,-85.08,-85.5,-85.83,-86.07,-86.22,-86.27,-86.23,-86.09,-85.86,-85.53,-85.12,-84.62,-84.03,-83.37,-82.63,-81.82,-80.95,-80.03,-79.05,-78.03,-76.98,-75.9,-74.8,-73.69,-72.58,-71.47,-70.37,-69.3,-68.26,-67.25,-66.28,-65.37,-64.52,-63.73,-63.01,-62.36,-61.8,-61.32,-60.92,-60.62,-60.41,-60.3,-60.28,-60.35,-60.52,-60.79,-61.14,-61.59,-62.12,-62.73,-63.42,-64.18,-65.01,-65.9,-66.84,-67.83,-68.87,-69.93,-71.02,-72.12,-73.23,-74.34,-56.27,-56.39,-56.6,-56.91,-57.3,-57.78,-58.35,-59.0,-59.72,-60.51,-61.37,-62.28,-63.25,-64.26,-65.3,-66.38,-67.47,-68.58,-69.7,-70.81,-71.91,-72.98,-74.04,-75.05,-76.03,-76.95,-77.82,-78.62,-79.36,-80.02,-80.6,-81.1,-81.52,-81.84,-82.07,-82.2,-82.24,-82.19,-82.04,-81.8,-81.46,-81.03,-80.52,-79.93,-79.25,-78.51,-77.69,-76.82,-75.89,-74.9,-73.88,-72.83,-71.74,-70.64,-69.53,-68.42,-67.31,-66.22,-65.15,-64.1,-63.1,-62.14,-61.24,-60.39,-59.61,-58.9,-58.26,-57.71,-57.24,-56.85,-56.56,-56.36,-56.26,-56.25,-56.34,-56.52,-56.8,-57.16,-57.62,-58.16,-58.78,-59.48,-60.25,-61.08,-61.98,-62.93,-63.93,-64.96,-66.03,-67.12,-68.22,-69.34,-70.45,-71.55,-72.64,-73.7,-74.73,-75.72,-76.66,-77.54,-78.37,-79.13,-79.82,-80.42,-80.95,-81.39,-81.74,-82.0,-82.17,-82.24,-82.22,-82.1,-81.89,-81.58,-81.18,-80.7,-80.13,-79.48,-78.76,-77.97,-77.11,-76.19,-75.23,-74.22,-73.17,-72.1,-71.0,-69.89,-68.78,-67.67,-66.57,-65.49,-64.44,-63.42,-62.45,-61.53,-60.66,-59.85,-59.12,-58.46,-57.88,-57.38,-56.97,-56.65,-56.42,-56.28,-56.24,-56.3,-56.45,-56.7,-57.03,-57.46,-57.97,-58.57,-59.24,-59.99,-60.81,-61.68,-62.62,-63.6,-64.62,-65.68,-66.76,-67.86,-68.97,-70.09,-71.19,-72.29,-73.36,-74.4,-75.4,-76.36,-77.26,-78.11,-78.89,-79.6,-80.24,-80.79,-81.26,-81.64,-81.93,-82.13,-82.23,-82.24,-82.15,-81.96,-81.69,-81.32,-80.86,-80.32,-79.7,-79.0,-78.23,-77.39,-76.5,-75.55,-74.55,-73.51,-72.45,-71.36,-70.25,-69.14,-68.03,-66.92,-65.84,-64.78,-63.75,-62.76,-61.82,-60.93,-60.11,-59.35,-58.66,-58.06,-57.53,-57.09,-56.74,-56.48,-56.32,-56.25,-56.27,-56.39,-56.61,-56.91,-57.31,-57.8,-58.37,-59.02,-59.74,-60.54,-61.39,-62.31,-63.28,-64.29,-65.33,-66.41,-67.5,-68.61,-69.73,-70.84,-52.29,-52.45,-52.7,-53.05,-53.49,-54.01,-54.62,-55.3,-56.06,-56.88,-57.76,-58.7,-59.69,-60.72,-61.78,-62.86,-63.97,-65.08,-66.19,-67.3,-68.39,-69.45,-70.49,-71.49,-72.44,-73.34,-74.18,-74.95,-75.65,-76.28,-76.82,-77.28,-77.65,-77.93,-78.11,-78.21,-78.2,-78.1,-77.91,-77.62,-77.24,-76.78,-76.22,-75.59,-74.88,-74.1,-73.26,-72.36,-71.4,-70.4,-69.36,-68.29,-67.2,-66.09,-64.98,-63.87,-62.76,-61.68,-60.62,-59.6,-58.62,-57.68,-56.8,-55.99,-55.24,-54.56,-53.96,-53.45,-53.02,-52.68,-52.43,-52.28,-52.22,-52.25,-52.38,-52.61,-52.93,-53.34,-53.83,-54.41,-55.07,-55.8,-56.61,-57.47,-58.39,-59.36,-60.38,-61.43,-62.51,-63.61,-64.72,-65.83,-66.94,-68.04,-69.11,-70.16,-71.17,-72.14,-73.05,-73.91,-74.71,-75.43,-76.08,-76.65,-77.14,-77.54,-77.85,-78.06,-78.19,-78.21,-78.14,-77.98,-77.72,-77.37,-76.94,-76.41,-75.81,-75.12,-74.36,-73.54,-72.66,-71.72,-70.73,-69.7,-68.64,-67.55,-66.45,-65.34,-64.23,-63.12,-62.03,-60.96,-59.93,-58.93,-57.98,-57.08,-56.24,-55.47,-54.77,-54.15,-53.6,-53.15,-52.78,-52.5,-52.31,-52.23,-52.23,-52.33,-52.53,-52.82,-53.19,-53.66,-54.22,-54.85,-55.56,-56.34,-57.18,-58.09,-59.04,-60.05,-61.09,-62.16,-63.25,-64.36,-65.47,-66.58,-67.68,-68.77,-69.82,-70.85,-71.83,-72.76,-73.64,-74.46,-75.21,-75.88,-76.48,-76.99,-77.42,-77.76,-78.01,-78.16,-78.22,-78.18,-78.04,-77.82,-77.5,-77.09,-76.59,-76.01,-75.35,-74.62,-73.82,-72.95,-72.03,-71.05,-70.04,-68.99,-67.91,-66.81,-65.7,-64.59,-63.48,-62.38,-61.31,-60.26,-59.25,-58.28,-57.37,-56.51,-55.71,-54.99,-54.34,-53.77,-53.28,-52.89,-52.58,-52.36,-52.24,-52.22,-52.29,-52.45,-52.71,-53.06,-53.5,-54.03,-54.63,-55.32,-56.08,-56.9,-57.79,-58.73,-59.72,-60.74,-61.81,-62.89,-64.0,-65.11,-66.22,-67.33,-48.32,-48.53,-48.83,-49.22,-49.7,-50.26,-50.9,-51.62,-52.41,-53.26,-54.17,-55.13,-56.14,-57.18,-58.26,-59.35,-60.46,-61.57,-62.68,-63.78,-64.86,-65.92,-66.94,-67.91,-68.84,-69.71,-70.52,-71.26,-71.93,-72.51,-73.02,-73.44,-73.76,-74.0,-74.14,-74.19,-74.14,-73.99,-73.76,-73.43,-73.01,-72.5,-71.91,-71.24,-70.5,-69.69,-68.81,-67.88,-66.91,-65.89,-64.83,-63.75,-62.65,-61.54,-60.43,-59.32,-58.22,-57.15,-56.11,-55.1,-54.14,-53.23,-52.38,-51.6,-50.88,-50.24,-49.68,-49.2,-48.82,-48.52,-48.32,-48.21,-48.19,-48.27,-48.45,-48.72,-49.08,-49.53,-50.07,-50.68,-51.38,-52.14,-52.98,-53.87,-54.81,-55.81,-56.84,-57.91,-58.99,-60.1,-61.21,-62.32,-63.43,-64.52,-65.58,-66.61,-67.6,-68.55,-69.44,-70.27,-71.03,-71.72,-72.33,-72.86,-73.31,-73.67,-73.93,-74.11,-74.18,-74.16,-74.05,-73.84,-73.54,-73.15,-72.67,-72.11,-71.46,-70.75,-69.96,-69.1,-68.19,-67.23,-66.22,-65.18,-64.1,-63.01,-61.9,-60.79,-59.68,-58.58,-57.5,-56.44,-55.42,-54.45,-53.52,-52.65,-51.84,-51.1,-50.44,-49.85,-49.35,-48.93,-48.61,-48.37,-48.23,-48.19,-48.24,-48.38,-48.62,-48.95,-49.38,-49.88,-50.47,-51.14,-51.89,-52.7,-53.57,-54.5,-55.48,-56.5,-57.56,-58.64,-59.74,-60.85,-61.96,-63.07,-64.17,-65.24,-66.28,-67.28,-68.24,-69.15,-70.0,-70.79,-71.5,-72.14,-72.7,-73.18,-73.56,-73.86,-74.06,-74.17,-74.18,-74.1,-73.92,-73.65,-73.29,-72.84,-72.3,-71.68,-70.99,-70.22,-69.39,-68.49,-67.55,-66.55,-65.52,-64.45,-63.37,-62.26,-61.15,-60.04,-58.93,-57.84,-56.78,-55.75,-54.76,-53.82,-52.93,-52.1,-51.34,-50.65,-50.03,-49.5,-49.06,-48.7,-48.44,-48.27,-48.19,-48.21,-48.33,-48.53,-48.84,-49.23,-49.71,-50.27,-50.92,-51.64,-52.43,-53.28,-54.2,-55.16,-56.17,-57.21,-58.29,-59.38,-60.49,-61.6,-62.71,-63.81,-44.38,-44.63,-44.97,-45.4,-45.92,-46.52,-47.2,-47.95,-48.77,-49.65,-50.59,-51.57,-52.6,-53.66,-54.74,-55.84,-56.95,-58.07,-59.17,-60.26,-61.33,-62.37,-63.37,-64.33,-65.23,-66.07,-66.85,-67.55,-68.18,-68.73,-69.2,-69.57,-69.86,-70.05,-70.15,-70.15,-70.05,-69.86,-69.58,-69.21,-68.75,-68.2,-67.57,-66.87,-66.1,-65.25,-64.35,-63.4,-62.4,-61.37,-60.3,-59.21,-58.1,-56.99,-55.87,-54.77,-53.69,-52.63,-51.6,-50.62,-49.68,-48.8,-47.98,-47.22,-46.54,-45.94,-45.42,-44.98,-44.64,-44.38,-44.22,-44.16,-44.19,-44.32,-44.54,-44.85,-45.25,-45.74,-46.32,-46.97,-47.7,-48.5,-49.36,-50.28,-51.25,-52.26,-53.31,-54.39,-55.48,-56.59,-57.71,-58.82,-59.91,-60.99,-62.04,-63.05,-64.02,-64.94,-65.8,-66.6,-67.33,-67.99,-68.56,-69.06,-69.46,-69.78,-70.0,-70.12,-70.16,-70.09,-69.94,-69.68,-69.34,-68.91,-68.39,-67.79,-67.11,-66.35,-65.53,-64.65,-63.72,-62.73,-61.71,-60.65,-59.56,-58.46,-57.35,-56.23,-55.13,-54.04,-52.97,-51.93,-50.93,-49.98,-49.08,-48.23,-47.46,-46.75,-46.12,-45.58,-45.11,-44.74,-44.46,-44.27,-44.17,-44.17,-44.27,-44.46,-44.74,-45.11,-45.57,-46.12,-46.75,-47.46,-48.23,-49.07,-49.97,-50.93,-51.93,-52.97,-54.03,-55.13,-56.23,-57.34,-58.46,-59.56,-60.64,-61.7,-62.73,-63.71,-64.65,-65.53,-66.35,-67.11,-67.78,-68.39,-68.91,-69.34,-69.68,-69.94,-70.09,-70.16,-70.12,-70.0,-69.78,-69.46,-69.06,-68.57,-67.99,-67.34,-66.61,-65.81,-64.94,-64.03,-63.06,-62.04,-60.99,-59.92,-58.82,-57.71,-56.6,-55.49,-54.39,-53.31,-52.26,-51.25,-50.28,-49.36,-48.5,-47.7,-46.97,-46.32,-45.74,-45.25,-44.85,-44.54,-44.32,-44.19,-44.16,-44.22,-44.38,-44.64,-44.98,-45.42,-45.94,-46.54,-47.22,-47.97,-48.79,-49.68,-50.61,-51.6,-52.63,-53.68,-54.77,-55.87,-56.98,-58.1,-59.2,-60.29,-40.46,-40.75,-41.13,-41.61,-42.16,-42.8,-43.52,-44.3,-45.15,-46.06,-47.02,-48.02,-49.06,-50.13,-51.23,-52.33,-53.45,-54.56,-55.66,-56.74,-57.8,-58.82,-59.8,-60.73,-61.6,-62.42,-63.16,-63.83,-64.42,-64.93,-65.36,-65.69,-65.93,-66.08,-66.13,-66.09,-65.95,-65.71,-65.39,-64.98,-64.47,-63.89,-63.22,-62.49,-61.68,-60.81,-59.88,-58.91,-57.89,-56.84,-55.76,-54.66,-53.55,-52.43,-51.33,-50.23,-49.16,-48.11,-47.1,-46.14,-45.23,-44.37,-43.58,-42.86,-42.22,-41.65,-41.17,-40.78,-40.48,-40.27,-40.15,-40.13,-40.21,-40.38,-40.64,-41.0,-41.44,-41.97,-42.59,-43.28,-44.04,-44.87,-45.76,-46.7,-47.69,-48.72,-49.78,-50.87,-51.97,-53.09,-54.2,-55.3,-56.39,-57.46,-58.49,-59.49,-60.43,-61.33,-62.16,-62.93,-63.62,-64.24,-64.78,-65.23,-65.59,-65.86,-66.04,-66.12,-66.11,-66.0,-65.8,-65.51,-65.12,-64.65,-64.09,-63.45,-62.73,-61.95,-61.1,-60.19,-59.23,-58.22,-57.18,-56.11,-55.02,-53.91,-52.8,-51.68,-50.58,-49.5,-48.45,-47.43,-46.45,-45.52,-44.64,-43.83,-43.09,-42.42,-41.83,-41.32,-40.9,-40.57,-40.33,-40.18,-40.13,-40.17,-40.31,-40.55,-40.87,-41.29,-41.79,-42.38,-43.04,-43.78,-44.59,-45.46,-46.39,-47.36,-48.38,-49.44,-50.52,-51.62,-52.73,-53.84,-54.95,-56.04,-57.12,-58.16,-59.17,-60.13,-61.04,-61.9,-62.69,-63.41,-64.05,-64.61,-65.09,-65.48,-65.78,-65.99,-66.11,-66.13,-66.05,-65.88,-65.61,-65.25,-64.81,-64.28,-63.66,-62.97,-62.21,-61.38,-60.49,-59.55,-58.56,-57.52,-56.46,-55.37,-54.27,-53.16,-52.04,-50.94,-49.85,-48.79,-47.75,-46.76,-45.81,-44.92,-44.09,-43.32,-42.63,-42.01,-41.47,-41.02,-40.66,-40.39,-40.22,-40.14,-40.15,-40.26,-40.46,-40.76,-41.15,-41.62,-42.18,-42.82,-43.54,-44.32,-45.17,-46.08,-47.04,-48.05,-49.09,-50.16,-51.26,-52.37,-53.48,-54.59,-55.69,-56.77,-36.55,-36.89,-37.32,-37.83,-38.43,-39.1,-39.85,-40.66,-41.54,-42.47,-43.45,-44.48,-45.53,-46.62,-47.72,-48.83,-49.94,-51.05,-52.14,-53.21,-54.25,-55.26,-56.21,-57.12,-57.97,-58.75,-59.46,-60.09,-60.65,-61.11,-61.5,-61.79,-61.98,-62.08,-62.09,-62.0,-61.82,-61.54,-61.18,-60.72,-60.18,-59.56,-58.86,-58.09,-57.25,-56.35,-55.4,-54.41,-53.37,-52.3,-51.21,-50.11,-49.0,-47.88,-46.78,-45.69,-44.63,-43.6,-42.62,-41.68,-40.79,-39.96,-39.21,-38.52,-37.91,-37.39,-36.95,-36.6,-36.34,-36.17,-36.1,-36.13,-36.25,-36.46,-36.77,-37.17,-37.65,-38.22,-38.87,-39.6,-40.39,-41.25,-42.16,-43.13,-44.14,-45.19,-46.26,-47.36,-48.47,-49.58,-50.69,-51.79,-52.87,-53.92,-54.94,-55.91,-56.83,-57.7,-58.5,-59.23,-59.89,-60.47,-60.97,-61.38,-61.7,-61.93,-62.06,-62.1,-62.04,-61.89,-61.64,-61.31,-60.88,-60.36,-59.77,-59.09,-58.34,-57.53,-56.65,-55.72,-54.73,-53.71,-52.65,-51.57,-50.47,-49.36,-48.24,-47.14,-46.04,-44.97,-43.93,-42.93,-41.98,-41.07,-40.23,-39.44,-38.74,-38.1,-37.55,-37.08,-36.7,-36.41,-36.22,-36.12,-36.11,-36.2,-36.38,-36.66,-37.03,-37.49,-38.03,-38.65,-39.35,-40.13,-40.96,-41.86,-42.81,-43.81,-44.84,-45.91,-47.0,-48.11,-49.22,-50.33,-51.44,-52.52,-53.58,-54.61,-55.6,-56.54,-57.42,-58.25,-59.0,-59.69,-60.3,-60.82,-61.26,-61.61,-61.87,-62.03,-62.1,-62.07,-61.95,-61.73,-61.43,-61.03,-60.54,-59.97,-59.32,-58.59,-57.8,-56.94,-56.02,-55.06,-54.05,-53.0,-51.92,-50.83,-49.72,-48.6,-47.49,-46.4,-45.32,-44.27,-43.25,-42.28,-41.36,-40.49,-39.69,-38.96,-38.3,-37.72,-37.22,-36.81,-36.5,-36.27,-36.14,-36.1,-36.16,-36.31,-36.56,-36.9,-37.33,-37.84,-38.44,-39.12,-39.87,-40.69,-41.56,-42.5,-43.48,-44.51,-45.56,-46.65,-47.75,-48.86,-49.97,-51.08,-52.17,-53.24,-32.67,-33.05,-33.52,-34.07,-34.7,-35.41,-36.19,-37.04,-37.94,-38.9,-39.9,-40.94,-42.01,-43.1,-44.21,-45.32,-46.44,-47.54,-48.62,-49.68,-50.7,-51.68,-52.62,-53.5,-54.31,-55.06,-55.74,-56.33,-56.85,-57.28,-57.61,-57.86,-58.01,-58.07,-58.03,-57.9,-57.67,-57.35,-56.94,-56.45,-55.87,-55.21,-54.47,-53.67,-52.81,-51.88,-50.91,-49.89,-48.84,-47.77,-46.67,-45.56,-44.44,-43.33,-42.24,-41.16,-40.12,-39.11,-38.14,-37.22,-36.37,-35.57,-34.85,-34.2,-33.63,-33.14,-32.74,-32.44,-32.22,-32.1,-32.07,-32.14,-32.31,-32.57,-32.92,-33.36,-33.88,-34.49,-35.18,-35.93,-36.76,-37.64,-38.58,-39.57,-40.6,-41.66,-42.75,-43.85,-44.96,-46.08,-47.18,-48.27,-49.34,-50.37,-51.37,-52.32,-53.22,-54.05,-54.83,-55.53,-56.15,-56.69,-57.15,-57.51,-57.79,-57.97,-58.06,-58.06,-57.95,-57.76,-57.47,-57.09,-56.62,-56.06,-55.43,-54.72,-53.94,-53.09,-52.19,-51.23,-50.23,-49.19,-48.12,-47.02,-45.92,-44.8,-43.69,-42.59,-41.51,-40.45,-39.43,-38.45,-37.51,-36.64,-35.82,-35.07,-34.4,-33.8,-33.29,-32.86,-32.53,-32.28,-32.13,-32.07,-32.11,-32.25,-32.47,-32.79,-33.21,-33.7,-34.28,-34.94,-35.68,-36.48,-37.35,-38.27,-39.25,-40.26,-41.31,-42.39,-43.49,-44.6,-45.72,-46.82,-47.92,-49.0,-50.04,-51.05,-52.02,-52.93,-53.79,-54.58,-55.31,-55.96,-56.52,-57.01,-57.41,-57.71,-57.93,-58.04,-58.07,-58.0,-57.83,-57.57,-57.22,-56.78,-56.25,-55.64,-54.96,-54.2,-53.37,-52.49,-51.55,-50.56,-49.53,-48.47,-47.38,-46.28,-45.17,-44.05,-42.95,-41.86,-40.79,-39.76,-38.76,-37.81,-36.91,-36.08,-35.31,-34.61,-33.99,-33.45,-32.99,-32.62,-32.35,-32.17,-32.08,-32.09,-32.19,-32.39,-32.68,-33.06,-33.53,-34.09,-34.72,-35.43,-36.22,-37.06,-37.97,-38.93,-39.93,-40.97,-42.04,-43.13,-44.24,-45.35,-46.47,-47.57,-48.65,-49.71,-28.81,-29.23,-29.74,-30.33,-31.0,-31.74,-32.55,-33.43,-34.36,-35.34,-36.36,-37.41,-38.49,-39.59,-40.71,-41.82,-42.93,-44.02,-45.09,-46.14,-47.14,-48.1,-49.01,-49.86,-50.64,-51.36,-52.0,-52.56,-53.03,-53.42,-53.71,-53.92,-54.02,-54.04,-53.95,-53.78,-53.51,-53.14,-52.69,-52.16,-51.54,-50.84,-50.08,-49.24,-48.35,-47.4,-46.41,-45.38,-44.31,-43.22,-42.12,-41.0,-39.89,-38.79,-37.7,-36.64,-35.61,-34.62,-33.67,-32.78,-31.95,-31.19,-30.5,-29.89,-29.36,-28.91,-28.56,-28.29,-28.12,-28.05,-28.07,-28.18,-28.39,-28.69,-29.08,-29.57,-30.13,-30.77,-31.49,-32.28,-33.14,-34.05,-35.01,-36.02,-37.07,-38.14,-39.24,-40.34,-41.46,-42.57,-43.67,-44.75,-45.8,-46.82,-47.79,-48.72,-49.59,-50.4,-51.14,-51.8,-52.39,-52.89,-53.3,-53.63,-53.86,-54.0,-54.04,-53.99,-53.84,-53.6,-53.27,-52.85,-52.34,-51.75,-51.08,-50.33,-49.52,-48.65,-47.72,-46.74,-45.71,-44.66,-43.58,-42.48,-41.37,-40.25,-39.14,-38.05,-36.98,-35.94,-34.93,-33.97,-33.07,-32.22,-31.43,-30.72,-30.08,-29.52,-29.05,-28.66,-28.37,-28.17,-28.06,-28.05,-28.13,-28.31,-28.58,-28.95,-29.4,-29.94,-30.56,-31.25,-32.02,-32.85,-33.75,-34.7,-35.69,-36.72,-37.79,-38.88,-39.98,-41.1,-42.21,-43.31,-44.4,-45.46,-46.49,-47.48,-48.43,-49.31,-50.14,-50.9,-51.59,-52.2,-52.73,-53.18,-53.53,-53.8,-53.96,-54.04,-54.02,-53.9,-53.69,-53.39,-53.0,-52.51,-51.95,-51.3,-50.58,-49.79,-48.94,-48.02,-47.06,-46.05,-45.01,-43.93,-42.84,-41.73,-40.61,-39.5,-38.4,-37.32,-36.27,-35.25,-34.28,-33.35,-32.48,-31.68,-30.94,-30.28,-29.69,-29.19,-28.78,-28.45,-28.22,-28.09,-28.04,-28.1,-28.24,-28.49,-28.82,-29.24,-29.75,-30.35,-31.02,-31.76,-32.58,-33.45,-34.38,-35.36,-36.39,-37.44,-38.52,-39.62,-40.74,-41.85,-42.96,-44.05,-45.12,-46.16,-24.97,-25.43,-25.98,-26.61,-27.31,-28.09,-28.93,-29.83,-30.78,-31.78,-32.82,-33.89,-34.98,-36.09,-37.2,-38.31,-39.41,-40.5,-41.56,-42.58,-43.57,-44.51,-45.39,-46.21,-46.96,-47.64,-48.24,-48.76,-49.2,-49.54,-49.79,-49.95,-50.01,-49.98,-49.85,-49.63,-49.32,-48.91,-48.42,-47.85,-47.19,-46.46,-45.66,-44.8,-43.88,-42.91,-41.9,-40.85,-39.77,-38.68,-37.57,-36.45,-35.34,-34.25,-33.17,-32.12,-31.11,-30.14,-29.22,-28.36,-27.56,-26.83,-26.18,-25.6,-25.11,-24.71,-24.39,-24.17,-24.05,-24.02,-24.08,-24.24,-24.49,-24.84,-25.27,-25.79,-26.39,-27.07,-27.83,-28.65,-29.53,-30.47,-31.45,-32.48,-33.54,-34.62,-35.73,-36.84,-37.95,-39.06,-40.15,-41.22,-42.26,-43.25,-44.21,-45.11,-45.95,-46.72,-47.43,-48.06,-48.6,-49.06,-49.44,-49.72,-49.91,-50.0,-50.0,-49.91,-49.71,-49.43,-49.05,-48.59,-48.04,-47.41,-46.71,-45.93,-45.09,-44.19,-43.23,-42.23,-41.19,-40.12,-39.03,-37.93,-36.81,-35.7,-34.6,-33.52,-32.46,-31.43,-30.45,-29.51,-28.63,-27.81,-27.06,-26.38,-25.78,-25.26,-24.83,-24.49,-24.23,-24.08,-24.02,-24.05,-24.18,-24.4,-24.72,-25.12,-25.61,-26.19,-26.85,-27.58,-28.38,-29.24,-30.16,-31.13,-32.14,-33.19,-34.27,-35.37,-36.48,-37.59,-38.7,-39.8,-40.87,-41.92,-42.94,-43.9,-44.82,-45.68,-46.48,-47.21,-47.86,-48.43,-48.92,-49.33,-49.64,-49.86,-49.98,-50.01,-49.95,-49.79,-49.53,-49.19,-48.75,-48.23,-47.63,-46.94,-46.19,-45.37,-44.48,-43.55,-42.56,-41.53,-40.47,-39.39,-38.29,-37.17,-36.06,-34.96,-33.86,-32.8,-31.76,-30.76,-29.81,-28.91,-28.07,-27.29,-26.59,-25.96,-25.42,-24.96,-24.59,-24.31,-24.12,-24.03,-24.03,-24.13,-24.32,-24.6,-24.98,-25.44,-25.99,-26.62,-27.33,-28.11,-28.95,-29.86,-30.81,-31.81,-32.85,-33.92,-35.01,-36.12,-37.23,-38.34,-39.44,-40.53,-41.59,-42.61,-21.15,-21.65,-22.23,-22.9,-23.64,-24.45,-25.32,-26.24,-27.22,-28.24,-29.29,-30.37,-31.47,-32.58,-33.69,-34.8,-35.9,-36.97,-38.02,-39.02,-39.99,-40.9,-41.75,-42.54,-43.26,-43.9,-44.47,-44.95,-45.34,-45.64,-45.85,-45.96,-45.98,-45.9,-45.73,-45.47,-45.11,-44.66,-44.13,-43.52,-42.83,-42.07,-41.24,-40.35,-39.4,-38.41,-37.38,-36.32,-35.23,-34.13,-33.01,-31.9,-30.8,-29.71,-28.64,-27.61,-26.62,-25.67,-24.78,-23.94,-23.18,-22.48,-21.87,-21.33,-20.88,-20.52,-20.25,-20.07,-19.99,-20.01,-20.11,-20.32,-20.61,-21.0,-21.48,-22.04,-22.68,-23.39,-24.18,-25.03,-25.94,-26.9,-27.9,-28.95,-30.02,-31.11,-32.22,-33.33,-34.44,-35.55,-36.63,-37.68,-38.7,-39.68,-40.61,-41.48,-42.29,-43.04,-43.7,-44.29,-44.8,-45.22,-45.55,-45.79,-45.94,-45.99,-45.94,-45.8,-45.56,-45.24,-44.82,-44.31,-43.73,-43.06,-42.32,-41.51,-40.64,-39.71,-38.74,-37.72,-36.67,-35.59,-34.49,-33.37,-32.26,-31.15,-30.06,-28.98,-27.94,-26.93,-25.97,-25.06,-24.21,-23.42,-22.7,-22.06,-21.5,-21.02,-20.63,-20.33,-20.12,-20.01,-19.99,-20.07,-20.24,-20.51,-20.87,-21.31,-21.85,-22.46,-23.15,-23.92,-24.75,-25.64,-26.58,-27.57,-28.6,-29.67,-30.76,-31.86,-32.97,-34.09,-35.19,-36.28,-37.34,-38.37,-39.37,-40.31,-41.21,-42.04,-42.8,-43.5,-44.11,-44.65,-45.1,-45.46,-45.72,-45.9,-45.98,-45.96,-45.85,-45.65,-45.35,-44.96,-44.49,-43.93,-43.29,-42.57,-41.78,-40.93,-40.02,-39.06,-38.05,-37.01,-35.94,-34.84,-33.74,-32.62,-31.51,-30.41,-29.33,-28.28,-27.26,-26.28,-25.35,-24.48,-23.67,-22.93,-22.26,-21.67,-21.16,-20.74,-20.41,-20.18,-20.03,-19.99,-20.03,-20.18,-20.41,-20.74,-21.16,-21.66,-22.25,-22.92,-23.66,-24.47,-25.34,-26.27,-27.25,-28.27,-29.32,-30.4,-31.5,-32.61,-33.73,-34.83,-35.93,-37.0,-38.04,-39.05,-17.34,-17.89,-18.51,-19.21,-19.98,-20.82,-21.72,-22.67,-23.66,-24.7,-25.77,-26.86,-27.96,-29.08,-30.19,-31.29,-32.38,-33.44,-34.47,-35.45,-36.39,-37.28,-38.1,-38.86,-39.54,-40.15,-40.68,-41.11,-41.46,-41.72,-41.89,-41.95,-41.93,-41.81,-41.59,-41.28,-40.88,-40.4,-39.83,-39.18,-38.45,-37.66,-36.8,-35.88,-34.91,-33.9,-32.86,-31.78,-30.68,-29.57,-28.46,-27.35,-26.25,-25.17,-24.12,-23.11,-22.14,-21.21,-20.35,-19.55,-18.81,-18.16,-17.58,-17.08,-16.67,-16.35,-16.13,-15.99,-15.96,-16.02,-16.17,-16.42,-16.76,-17.19,-17.7,-18.3,-18.97,-19.72,-20.54,-21.42,-22.35,-23.34,-24.36,-25.42,-26.5,-27.6,-28.72,-29.83,-30.94,-32.03,-33.1,-34.14,-35.14,-36.09,-37.0,-37.84,-38.62,-39.33,-39.96,-40.52,-40.98,-41.36,-41.65,-41.84,-41.94,-41.95,-41.86,-41.67,-41.39,-41.02,-40.56,-40.02,-39.4,-38.69,-37.92,-37.08,-36.18,-35.23,-34.24,-33.2,-32.13,-31.04,-29.94,-28.82,-27.71,-26.61,-25.52,-24.46,-23.43,-22.45,-21.51,-20.62,-19.8,-19.04,-18.36,-17.75,-17.23,-16.79,-16.45,-16.19,-16.03,-15.96,-15.99,-16.11,-16.33,-16.64,-17.04,-17.52,-18.1,-18.75,-19.47,-20.27,-21.13,-22.05,-23.01,-24.02,-25.07,-26.15,-27.24,-28.35,-29.47,-30.58,-31.68,-32.75,-33.8,-34.82,-35.79,-36.71,-37.58,-38.38,-39.11,-39.77,-40.35,-40.84,-41.25,-41.57,-41.79,-41.92,-41.96,-41.9,-41.74,-41.49,-41.15,-40.72,-40.21,-39.61,-38.93,-38.18,-37.36,-36.48,-35.55,-34.56,-33.54,-32.48,-31.4,-30.3,-29.18,-28.07,-26.96,-25.87,-24.8,-23.76,-22.76,-21.81,-20.9,-20.06,-19.28,-18.57,-17.94,-17.39,-16.93,-16.55,-16.26,-16.07,-15.97,-15.97,-16.06,-16.25,-16.53,-16.9,-17.36,-17.9,-18.53,-19.23,-20.0,-20.84,-21.74,-22.69,-23.69,-24.73,-25.8,-26.89,-27.99,-29.11,-30.22,-31.32,-32.41,-33.47,-34.49,-35.48,-13.56,-14.14,-14.8,-15.54,-16.34,-17.21,-18.13,-19.1,-20.12,-21.17,-22.25,-23.35,-24.46,-25.57,-26.68,-27.78,-28.85,-29.9,-30.91,-31.87,-32.79,-33.65,-34.44,-35.16,-35.81,-36.38,-36.86,-37.26,-37.57,-37.78,-37.9,-37.93,-37.85,-37.69,-37.43,-37.08,-36.64,-36.11,-35.5,-34.82,-34.06,-33.23,-32.34,-31.4,-30.41,-29.39,-28.32,-27.24,-26.13,-25.02,-23.91,-22.8,-21.71,-20.65,-19.61,-18.62,-17.67,-16.77,-15.93,-15.16,-14.47,-13.84,-13.3,-12.85,-12.48,-12.21,-12.02,-11.94,-11.94,-12.05,-12.25,-12.54,-12.92,-13.39,-13.94,-14.58,-15.29,-16.07,-16.92,-17.82,-18.78,-19.78,-20.83,-21.9,-22.99,-24.1,-25.21,-26.32,-27.42,-28.51,-29.56,-30.58,-31.57,-32.5,-33.37,-34.19,-34.94,-35.61,-36.2,-36.72,-37.14,-37.48,-37.72,-37.87,-37.93,-37.89,-37.75,-37.52,-37.2,-36.79,-36.29,-35.71,-35.05,-34.31,-33.51,-32.64,-31.71,-30.74,-29.72,-28.67,-27.59,-26.49,-25.38,-24.27,-23.16,-22.07,-20.99,-19.94,-18.94,-17.97,-17.06,-16.2,-15.41,-14.68,-14.04,-13.47,-12.99,-12.59,-12.28,-12.07,-11.95,-11.93,-12.0,-12.17,-12.43,-12.78,-13.23,-13.75,-14.36,-15.05,-15.81,-16.64,-17.52,-18.47,-19.45,-20.48,-21.55,-22.63,-23.74,-24.85,-25.96,-27.07,-28.16,-29.22,-30.26,-31.25,-32.2,-33.1,-33.93,-34.7,-35.4,-36.02,-36.56,-37.01,-37.38,-37.65,-37.83,-37.92,-37.91,-37.81,-37.61,-37.32,-36.93,-36.46,-35.91,-35.27,-34.56,-33.77,-32.93,-32.02,-31.06,-30.06,-29.02,-27.95,-26.85,-25.74,-24.63,-23.52,-22.42,-21.34,-20.28,-19.26,-18.28,-17.35,-16.47,-15.66,-14.91,-14.24,-13.64,-13.13,-12.71,-12.37,-12.13,-11.98,-11.93,-11.97,-12.11,-12.34,-12.66,-13.07,-13.57,-14.16,-14.82,-15.56,-16.36,-17.23,-18.15,-19.13,-20.15,-21.2,-22.28,-23.38,-24.49,-25.6,-26.71,-27.81,-28.88,-29.93,-30.93,-31.9,-9.79,-10.41,-11.11,-11.88,-12.71,-13.6,-14.55,-15.55,-16.58,-17.65,-18.73,-19.84,-20.95,-22.06,-23.17,-24.26,-25.32,-26.35,-27.34,-28.28,-29.17,-30.0,-30.76,-31.45,-32.06,-32.59,-33.03,-33.39,-33.65,-33.82,-33.9,-33.87,-33.76,-33.55,-33.25,-32.85,-32.37,-31.81,-31.16,-30.44,-29.65,-28.79,-27.88,-26.92,-25.91,-24.86,-23.79,-22.69,-21.58,-20.47,-19.36,-18.26,-17.18,-16.13,-15.11,-14.14,-13.21,-12.34,-11.54,-10.8,-10.13,-9.55,-9.05,-8.64,-8.31,-8.08,-7.94,-7.9,-7.95,-8.1,-8.34,-8.68,-9.1,-9.61,-10.2,-10.87,-11.62,-12.43,-13.31,-14.24,-15.22,-16.24,-17.3,-18.38,-19.48,-20.59,-21.7,-22.81,-23.91,-24.98,-26.02,-27.02,-27.98,-28.89,-29.74,-30.52,-31.23,-31.87,-32.43,-32.9,-33.28,-33.58,-33.78,-33.88,-33.89,-33.81,-33.63,-33.35,-32.99,-32.54,-32.0,-31.38,-30.68,-29.91,-29.08,-28.18,-27.23,-26.24,-25.2,-24.14,-23.05,-21.94,-20.83,-19.72,-18.62,-17.53,-16.47,-15.44,-14.45,-13.5,-12.62,-11.79,-11.03,-10.34,-9.73,-9.2,-8.76,-8.41,-8.14,-7.98,-7.9,-7.92,-8.04,-8.25,-8.56,-8.95,-9.44,-10.0,-10.65,-11.37,-12.16,-13.02,-13.93,-14.9,-15.91,-16.95,-18.03,-19.12,-20.23,-21.34,-22.45,-23.55,-24.63,-25.68,-26.7,-27.68,-28.6,-29.47,-30.27,-31.01,-31.67,-32.26,-32.76,-33.17,-33.49,-33.72,-33.86,-33.9,-33.84,-33.7,-33.45,-33.12,-32.69,-32.18,-31.59,-30.91,-30.17,-29.35,-28.48,-27.55,-26.57,-25.54,-24.49,-23.4,-22.3,-21.19,-20.08,-18.97,-17.88,-16.81,-15.77,-14.76,-13.8,-12.9,-12.05,-11.27,-10.56,-9.92,-9.36,-8.89,-8.51,-8.22,-8.02,-7.92,-7.91,-7.99,-8.17,-8.45,-8.81,-9.27,-9.81,-10.43,-11.13,-11.9,-12.73,-13.63,-14.58,-15.57,-16.61,-17.67,-18.76,-19.87,-20.98,-22.09,-23.2,-24.28,-25.35,-26.38,-27.36,-28.31,-6.05,-6.7,-7.43,-8.23,-9.09,-10.01,-10.99,-12.0,-13.05,-14.13,-15.22,-16.33,-17.45,-18.56,-19.65,-20.73,-21.78,-22.79,-23.76,-24.68,-25.54,-26.34,-27.06,-27.72,-28.29,-28.78,-29.18,-29.49,-29.71,-29.84,-29.87,-29.8,-29.64,-29.39,-29.04,-28.61,-28.09,-27.48,-26.8,-26.05,-25.22,-24.34,-23.4,-22.42,-21.39,-20.33,-19.25,-18.14,-17.03,-15.92,-14.81,-13.72,-12.65,-11.62,-10.62,-9.67,-8.77,-7.93,-7.15,-6.45,-5.82,-5.28,-4.81,-4.44,-4.16,-3.97,-3.88,-3.88,-3.98,-4.17,-4.46,-4.84,-5.3,-5.85,-6.48,-7.19,-7.97,-8.81,-9.71,-10.67,-11.67,-12.7,-13.77,-14.87,-15.97,-17.09,-18.2,-19.3,-20.38,-21.44,-22.47,-23.45,-24.39,-25.27,-26.08,-26.84,-27.51,-28.11,-28.63,-29.06,-29.4,-29.65,-29.81,-29.87,-29.84,-29.71,-29.48,-29.16,-28.76,-28.26,-27.69,-27.03,-26.3,-25.5,-24.63,-23.71,-22.74,-21.73,-20.68,-19.6,-18.5,-17.39,-16.28,-15.17,-14.07,-13.0,-11.95,-10.94,-9.97,-9.05,-8.19,-7.39,-6.67,-6.02,-5.44,-4.95,-4.55,-4.24,-4.02,-3.9,-3.87,-3.94,-4.1,-4.36,-4.7,-5.14,-5.66,-6.27,-6.95,-7.71,-8.53,-9.41,-10.35,-11.34,-12.36,-13.42,-14.51,-15.61,-16.72,-17.84,-18.94,-20.03,-21.1,-22.14,-23.14,-24.09,-24.99,-25.83,-26.6,-27.3,-27.93,-28.47,-28.93,-29.3,-29.58,-29.77,-29.86,-29.86,-29.76,-29.56,-29.28,-28.9,-28.43,-27.88,-27.25,-26.54,-25.76,-24.92,-24.02,-23.06,-22.06,-21.02,-19.95,-18.86,-17.75,-16.64,-15.53,-14.43,-13.34,-12.28,-11.26,-10.28,-9.34,-8.46,-7.65,-6.9,-6.22,-5.62,-5.1,-4.67,-4.33,-4.09,-3.93,-3.87,-3.91,-4.04,-4.26,-4.58,-4.99,-5.48,-6.06,-6.72,-7.45,-8.25,-9.12,-10.04,-11.01,-12.03,-13.08,-14.16,-15.25,-16.36,-17.48,-18.59,-19.68,-20.76,-21.81,-22.82,-23.79,-24.7,-2.32,-3.01,-3.77,-4.6,-5.49,-6.44,-7.43,-8.46,-9.52,-10.61,-11.72,-12.83,-13.94,-15.05,-16.13,-17.2,-18.23,-19.22,-20.17,-21.06,-21.89,-22.66,-23.35,-23.97,-24.5,-24.95,-25.31,-25.58,-25.76,-25.84,-25.82,-25.71,-25.51,-25.21,-24.82,-24.34,-23.78,-23.14,-22.43,-21.64,-20.79,-19.88,-18.92,-17.91,-16.87,-15.79,-14.7,-13.59,-12.48,-11.37,-10.27,-9.19,-8.13,-7.11,-6.14,-5.21,-4.33,-3.52,-2.78,-2.11,-1.53,-1.02,-0.6,-0.27,-0.03,0.11,0.16,0.11,-0.03,-0.27,-0.6,-1.01,-1.52,-2.11,-2.77,-3.52,-4.33,-5.2,-6.12,-7.1,-8.12,-9.18,-10.26,-11.36,-12.47,-13.58,-14.69,-15.78,-16.86,-17.9,-18.91,-19.87,-20.78,-21.63,-22.42,-23.14,-23.78,-24.34,-24.82,-25.21,-25.5,-25.71,-25.82,-25.84,-25.76,-25.58,-25.32,-24.96,-24.51,-23.97,-23.36,-22.67,-21.9,-21.07,-20.18,-19.23,-18.24,-17.21,-16.15,-15.06,-13.95,-12.84,-11.73,-10.62,-9.54,-8.47,-7.44,-6.45,-5.5,-4.61,-3.78,-3.02,-2.32,-1.71,-1.17,-0.73,-0.37,-0.1,0.07,0.15,0.14,0.03,-0.18,-0.48,-0.87,-1.35,-1.91,-2.55,-3.27,-4.06,-4.91,-5.82,-6.78,-7.79,-8.83,-9.9,-11.0,-12.11,-13.22,-14.33,-15.43,-16.51,-17.56,-18.58,-19.56,-20.49,-21.36,-22.17,-22.91,-23.58,-24.17,-24.67,-25.09,-25.42,-25.65,-25.79,-25.84,-25.79,-25.65,-25.41,-25.08,-24.66,-24.16,-23.57,-22.9,-22.16,-21.35,-20.47,-19.55,-18.57,-17.55,-16.49,-15.41,-14.31,-13.2,-12.09,-10.98,-9.89,-8.81,-7.77,-6.76,-5.8,-4.89,-4.04,-3.26,-2.54,-1.9,-1.34,-0.86,-0.47,-0.18,0.03,0.14,0.15,0.07,-0.1,-0.37,-0.73,-1.18,-1.72,-2.33,-3.03,-3.79,-4.62,-5.52,-6.46,-7.46,-8.49,-9.55,-10.64,-11.75,-12.86,-13.97,-15.08,-16.16,-17.23,-18.26,-19.25,-20.19,-21.08,1.4,0.67,-0.12,-0.98,-1.9,-2.87,-3.88,-4.93,-6.0,-7.1,-8.21,-9.32,-10.43,-11.53,-12.61,-13.66,-14.67,-15.65,-16.57,-17.43,-18.23,-18.96,-19.62,-20.2,-20.7,-21.1,-21.42,-21.65,-21.78,-21.81,-21.75,-21.6,-21.35,-21.01,-20.58,-20.06,-19.46,-18.79,-18.04,-17.22,-16.34,-15.4,-14.42,-13.4,-12.34,-11.25,-10.15,-9.04,-7.93,-6.82,-5.73,-4.66,-3.62,-2.62,-1.66,-0.76,0.08,0.86,1.57,2.2,2.75,3.22,3.6,3.88,4.07,4.17,4.18,4.08,3.9,3.62,3.25,2.79,2.24,1.62,0.91,0.14,-0.7,-1.6,-2.55,-3.55,-4.58,-5.65,-6.74,-7.85,-8.96,-10.07,-11.18,-12.26,-13.32,-14.35,-15.34,-16.27,-17.16,-17.98,-18.74,-19.42,-20.02,-20.54,-20.98,-21.33,-21.58,-21.74,-21.81,-21.78,-21.66,-21.44,-21.13,-20.73,-20.24,-19.67,-19.01,-18.29,-17.49,-16.63,-15.71,-14.74,-13.73,-12.68,-11.61,-10.51,-9.4,-8.29,-7.18,-6.08,-5.0,-3.95,-2.94,-1.97,-1.05,-0.18,0.62,1.35,2.01,2.58,3.08,3.48,3.8,4.02,4.15,4.19,4.13,3.97,3.72,3.38,2.95,2.43,1.83,1.15,0.4,-0.42,-1.3,-2.24,-3.22,-4.24,-5.3,-6.39,-7.49,-8.6,-9.71,-10.82,-11.91,-12.98,-14.02,-15.02,-15.98,-16.88,-17.72,-18.5,-19.2,-19.84,-20.38,-20.85,-21.23,-21.51,-21.7,-21.8,-21.8,-21.71,-21.52,-21.24,-20.87,-20.41,-19.86,-19.23,-18.53,-17.76,-16.92,-16.02,-15.06,-14.06,-13.03,-11.96,-10.87,-9.76,-8.65,-7.54,-6.43,-5.35,-4.29,-3.26,-2.28,-1.34,-0.46,0.37,1.12,1.8,2.4,2.93,3.36,3.71,3.96,4.12,4.19,4.16,4.03,3.81,3.5,3.1,2.61,2.03,1.38,0.65,-0.15,-1.01,-1.93,-2.9,-3.91,-4.96,-6.03,-7.13,-8.24,-9.35,-10.46,-11.56,-12.64,-13.69,-14.7,-15.67,-16.59,-17.45,5.09,4.33,3.51,2.62,1.68,0.69,-0.34,-1.4,-2.49,-3.59,-4.7,-5.82,-6.92,-8.01,-9.08,-10.11,-11.11,-12.06,-12.95,-13.79,-14.56,-15.26,-15.88,-16.42,-16.87,-17.24,-17.51,-17.69,-17.78,-17.77,-17.66,-17.46,-17.17,-16.79,-16.32,-15.76,-15.13,-14.41,-13.63,-12.78,-11.88,-10.92,-9.91,-8.87,-7.8,-6.71,-5.6,-4.49,-3.38,-2.28,-1.19,-0.14,0.88,1.87,2.8,3.67,4.49,5.23,5.91,6.5,7.01,7.44,7.77,8.01,8.16,8.22,8.17,8.04,7.81,7.48,7.07,6.57,5.99,5.32,4.59,3.78,2.91,1.99,1.02,-0.0,-1.05,-2.13,-3.23,-4.34,-5.46,-6.57,-7.66,-8.74,-9.78,-10.79,-11.75,-12.67,-13.52,-14.32,-15.04,-15.68,-16.25,-16.73,-17.13,-17.43,-17.64,-17.76,-17.78,-17.71,-17.54,-17.28,-16.92,-16.48,-15.95,-15.34,-14.65,-13.89,-13.06,-12.18,-11.23,-10.24,-9.21,-8.15,-7.07,-5.96,-4.85,-3.74,-2.63,-1.54,-0.48,0.56,1.55,2.5,3.4,4.23,5.0,5.7,6.32,6.85,7.31,7.67,7.94,8.12,8.21,8.2,8.09,7.89,7.6,7.21,6.74,6.19,5.55,4.83,4.05,3.2,2.3,1.34,0.33,-0.71,-1.78,-2.87,-3.98,-5.1,-6.21,-7.31,-8.39,-9.45,-10.47,-11.45,-12.38,-13.25,-14.07,-14.81,-15.48,-16.08,-16.59,-17.01,-17.34,-17.58,-17.73,-17.78,-17.74,-17.6,-17.37,-17.05,-16.63,-16.13,-15.55,-14.88,-14.15,-13.34,-12.47,-11.55,-10.57,-9.55,-8.5,-7.42,-6.32,-5.21,-4.1,-2.99,-1.89,-0.82,0.23,1.23,2.2,3.11,3.97,4.76,5.48,6.12,6.69,7.17,7.56,7.87,8.08,8.19,8.21,8.14,7.97,7.7,7.35,6.9,6.37,5.76,5.07,4.31,3.48,2.6,1.65,0.66,-0.37,-1.43,-2.52,-3.62,-4.73,-5.85,-6.95,-8.04,-9.11,-10.14,-11.13,-12.08,-12.98,-13.81,8.77,7.98,7.13,6.21,5.25,4.24,3.19,2.12,1.02,-0.09,-1.2,-2.31,-3.41,-4.49,-5.54,-6.56,-7.53,-8.46,-9.32,-10.13,-10.87,-11.53,-12.11,-12.61,-13.02,-13.35,-13.58,-13.71,-13.76,-13.7,-13.55,-13.31,-12.97,-12.55,-12.04,-11.44,-10.77,-10.02,-9.21,-8.33,-7.4,-6.42,-5.4,-4.34,-3.26,-2.16,-1.05,0.06,1.17,2.26,3.34,4.38,5.38,6.34,7.24,8.09,8.88,9.59,10.22,10.78,11.25,11.63,11.92,12.12,12.23,12.24,12.15,11.97,11.7,11.33,10.87,10.34,9.71,9.02,8.25,7.41,6.51,5.57,4.57,3.54,2.47,1.38,0.28,-0.84,-1.95,-3.05,-4.14,-5.2,-6.23,-7.22,-8.16,-9.05,-9.88,-10.63,-11.32,-11.93,-12.46,-12.9,-13.25,-13.51,-13.68,-13.75,-13.73,-13.61,-13.4,-13.09,-12.7,-12.21,-11.65,-11.0,-10.27,-9.48,-8.63,-7.71,-6.75,-5.74,-4.69,-3.61,-2.52,-1.41,-0.3,0.81,1.91,2.99,4.04,5.06,6.03,6.96,7.82,8.63,9.36,10.03,10.61,11.11,11.52,11.84,12.07,12.2,12.24,12.19,12.04,11.79,11.46,11.03,10.52,9.92,9.25,8.5,7.69,6.81,5.88,4.9,3.88,2.82,1.74,0.63,-0.48,-1.59,-2.7,-3.79,-4.86,-5.9,-6.9,-7.86,-8.77,-9.61,-10.4,-11.11,-11.74,-12.3,-12.77,-13.15,-13.44,-13.64,-13.74,-13.75,-13.66,-13.48,-13.2,-12.83,-12.38,-11.84,-11.22,-10.52,-9.75,-8.91,-8.01,-7.06,-6.07,-5.03,-3.97,-2.88,-1.77,-0.66,0.45,1.56,2.64,3.71,4.73,5.72,6.66,7.55,8.38,9.13,9.82,10.43,10.95,11.39,11.75,12.01,12.17,12.24,12.22,12.1,11.88,11.58,11.18,10.69,10.13,9.48,8.75,7.96,7.1,6.19,5.22,4.21,3.16,2.09,0.99,-0.12,-1.23,-2.34,-3.44,-4.52,-5.57,-6.58,-7.56,-8.48,-9.35,-10.15,12.44,11.62,10.73,9.79,8.81,7.78,6.72,5.63,4.53,3.42,2.31,1.2,0.11,-0.96,-1.99,-2.99,-3.94,-4.84,-5.68,-6.46,-7.16,-7.78,-8.33,-8.79,-9.16,-9.44,-9.62,-9.72,-9.71,-9.61,-9.42,-9.13,-8.76,-8.29,-7.74,-7.11,-6.4,-5.62,-4.78,-3.87,-2.92,-1.92,-0.88,0.19,1.28,2.39,3.5,4.61,5.72,6.8,7.86,8.88,9.87,10.8,11.68,12.5,13.25,13.92,14.52,15.04,15.47,15.81,16.06,16.21,16.27,16.24,16.11,15.88,15.56,15.16,14.66,14.08,13.42,12.69,11.89,11.03,10.1,9.13,8.12,7.07,5.99,4.89,3.78,2.67,1.56,0.46,-0.61,-1.66,-2.67,-3.64,-4.56,-5.42,-6.21,-6.94,-7.59,-8.16,-8.65,-9.05,-9.36,-9.57,-9.7,-9.72,-9.66,-9.49,-9.24,-8.89,-8.45,-7.93,-7.32,-6.64,-5.88,-5.06,-4.17,-3.23,-2.25,-1.22,-0.16,0.93,2.03,3.14,4.25,5.36,6.45,7.52,8.55,9.55,10.5,11.4,12.24,13.01,13.71,14.34,14.88,15.34,15.71,15.99,16.17,16.26,16.26,16.16,15.96,15.68,15.3,14.83,14.28,13.65,12.94,12.16,11.31,10.41,9.45,8.45,7.41,6.34,5.25,4.14,3.03,1.92,0.82,-0.27,-1.33,-2.35,-3.33,-4.27,-5.14,-5.96,-6.71,-7.39,-7.98,-8.5,-8.93,-9.27,-9.51,-9.67,-9.73,-9.69,-9.56,-9.33,-9.01,-8.6,-8.11,-7.53,-6.87,-6.13,-5.33,-4.47,-3.54,-2.57,-1.56,-0.51,0.57,1.67,2.78,3.89,5.0,6.1,7.18,8.22,9.23,10.2,11.12,11.97,12.77,13.49,14.14,14.71,15.2,15.6,15.91,16.12,16.24,16.27,16.2,16.04,15.78,15.43,14.99,14.47,13.86,13.17,12.42,11.59,10.71,9.77,8.78,7.75,6.69,5.6,4.5,3.39,2.28,1.17,0.08,-0.99,-2.02,-3.02,-3.97,-4.87,-5.7,-6.48,16.09,15.24,14.33,13.36,12.36,11.31,10.24,9.15,8.04,6.93,5.81,4.71,3.63,2.58,1.56,0.58,-0.34,-1.22,-2.03,-2.77,-3.43,-4.02,-4.53,-4.94,-5.27,-5.51,-5.65,-5.7,-5.65,-5.51,-5.27,-4.94,-4.52,-4.01,-3.42,-2.76,-2.01,-1.2,-0.33,0.6,1.58,2.6,3.65,4.73,5.83,6.94,8.06,9.16,10.26,11.33,12.37,13.38,14.34,15.25,16.1,16.89,17.6,18.25,18.81,19.28,19.67,19.97,20.17,20.28,20.3,20.22,20.04,19.77,19.41,18.96,18.43,17.81,17.12,16.35,15.52,14.63,13.68,12.69,11.66,10.59,9.5,8.4,7.29,6.17,5.07,3.98,2.92,1.89,0.9,-0.05,-0.94,-1.77,-2.53,-3.23,-3.84,-4.37,-4.82,-5.18,-5.44,-5.62,-5.69,-5.68,-5.56,-5.36,-5.06,-4.67,-4.19,-3.62,-2.98,-2.26,-1.47,-0.62,0.29,1.25,2.26,3.3,4.38,5.47,6.58,7.69,8.81,9.9,10.99,12.04,13.06,14.03,14.96,15.83,16.64,17.38,18.05,18.63,19.14,19.55,19.88,20.12,20.26,20.3,20.25,20.11,19.87,19.54,19.12,18.61,18.02,17.35,16.61,15.8,14.92,13.99,13.02,11.99,10.94,9.86,8.76,7.65,6.53,5.43,4.33,3.26,2.22,1.21,0.25,-0.66,-1.51,-2.29,-3.01,-3.65,-4.21,-4.68,-5.07,-5.37,-5.57,-5.68,-5.69,-5.61,-5.43,-5.16,-4.8,-4.35,-3.82,-3.2,-2.5,-1.74,-0.9,-0.01,0.94,1.93,2.96,4.03,5.12,6.22,7.33,8.45,9.55,10.64,11.7,12.73,13.72,14.67,15.56,16.39,17.15,17.84,18.45,18.98,19.43,19.78,20.05,20.22,20.3,20.28,20.16,19.96,19.66,19.26,18.78,18.22,17.58,16.86,16.07,15.21,14.3,13.34,12.33,11.29,10.21,9.12,8.01,6.89,5.78,4.68,3.6,2.55,1.53,0.56,-0.37,-1.24,-2.05,-2.79,19.72,18.84,17.91,16.93,15.9,14.84,13.76,12.66,11.54,10.43,9.32,8.23,7.16,6.12,5.12,4.17,3.27,2.42,1.65,0.94,0.31,-0.24,-0.71,-1.08,-1.37,-1.56,-1.66,-1.66,-1.56,-1.38,-1.1,-0.72,-0.26,0.28,0.91,1.61,2.39,3.23,4.13,5.08,6.08,7.12,8.18,9.27,10.38,11.49,12.61,13.71,14.79,15.85,16.88,17.87,18.8,19.69,20.51,21.26,21.94,22.55,23.07,23.5,23.85,24.1,24.26,24.33,24.3,24.17,23.95,23.64,23.24,22.75,22.18,21.52,20.79,20.0,19.14,18.22,17.25,16.24,15.19,14.11,13.01,11.91,10.79,9.68,8.58,7.51,6.46,5.44,4.47,3.55,2.69,1.89,1.16,0.5,-0.07,-0.56,-0.97,-1.28,-1.51,-1.63,-1.67,-1.61,-1.45,-1.2,-0.85,-0.42,0.1,0.7,1.38,2.13,2.95,3.83,4.77,5.75,6.78,7.83,8.92,10.02,11.13,12.25,13.35,14.44,15.51,16.55,17.55,18.51,19.41,20.25,21.03,21.73,22.36,22.91,23.37,23.75,24.03,24.22,24.32,24.32,24.22,24.04,23.75,23.38,22.92,22.37,21.74,21.04,20.26,19.42,18.52,17.57,16.57,15.53,14.46,13.37,12.27,11.15,10.04,8.94,7.85,6.79,5.77,4.78,3.85,2.96,2.14,1.39,0.71,0.11,-0.41,-0.85,-1.19,-1.44,-1.6,-1.67,-1.64,-1.51,-1.29,-0.98,-0.57,-0.08,0.49,1.15,1.88,2.68,3.54,4.46,5.43,6.44,7.49,8.57,9.66,10.77,11.89,13.0,14.09,15.17,16.22,17.23,18.2,19.12,19.98,20.78,21.51,22.17,22.74,23.23,23.64,23.95,24.17,24.3,24.33,24.27,24.11,23.86,23.51,23.08,22.56,21.96,21.28,20.52,19.7,18.82,17.88,16.9,15.87,14.81,13.73,12.63,11.51,10.4,9.29,8.2,7.13,6.1,5.1,4.14,3.24,2.4,1.63,0.92,23.35,22.44,21.48,20.48,19.44,18.36,17.27,16.16,15.05,13.94,12.84,11.75,10.7,9.68,8.7,7.77,6.89,6.08,5.33,4.66,4.07,3.56,3.14,2.8,2.56,2.41,2.36,2.4,2.54,2.77,3.1,3.51,4.01,4.6,5.26,6.0,6.8,7.67,8.6,9.57,10.59,11.64,12.72,13.82,14.93,16.05,17.15,18.25,19.32,20.37,21.38,22.34,23.25,24.11,24.9,25.62,26.27,26.83,27.31,27.71,28.01,28.22,28.34,28.36,28.28,28.11,27.85,27.49,27.05,26.52,25.91,25.22,24.46,23.63,22.74,21.8,20.81,19.78,18.71,17.63,16.52,15.41,14.3,13.19,12.1,11.04,10.0,9.01,8.06,7.17,6.33,5.57,4.87,4.25,3.72,3.26,2.9,2.63,2.45,2.37,2.38,2.49,2.69,2.98,3.37,3.84,4.4,5.04,5.75,6.54,7.38,8.29,9.25,10.26,11.3,12.37,13.46,14.57,15.69,16.8,17.9,18.98,20.03,21.06,22.03,22.96,23.84,24.65,25.4,26.07,26.66,27.17,27.59,27.92,28.16,28.31,28.36,28.32,28.18,27.94,27.62,27.2,26.7,26.11,25.45,24.71,23.9,23.03,22.11,21.13,20.11,19.06,17.98,16.88,15.77,14.66,13.55,12.45,11.38,10.34,9.33,8.36,7.45,6.6,5.81,5.09,4.44,3.88,3.4,3.01,2.71,2.5,2.38,2.36,2.44,2.61,2.88,3.23,3.68,4.21,4.82,5.51,6.27,7.1,7.99,8.94,9.93,10.96,12.02,13.11,14.21,15.32,16.44,17.54,18.63,19.7,20.73,21.72,22.67,23.56,24.4,25.16,25.86,26.47,27.01,27.46,27.82,28.09,28.27,28.35,28.34,28.23,28.03,27.73,27.35,26.87,26.31,25.67,24.96,24.17,23.32,22.41,21.45,20.45,19.41,18.33,17.24,16.13,15.02,13.91,12.81,11.73,10.67,9.65,8.67,7.74,6.87,6.06,5.31,4.64,26.96,26.02,25.04,24.02,22.96,21.88,20.78,19.67,18.55,17.45,16.35,15.28,14.24,13.24,12.28,11.38,10.53,9.75,9.04,8.4,7.85,7.38,7.0,6.71,6.51,6.4,6.4,6.48,6.67,6.94,7.31,7.76,8.31,8.93,9.63,10.4,11.23,12.13,13.08,14.08,15.11,16.18,17.27,18.37,19.49,20.6,21.7,22.79,23.85,24.88,25.87,26.81,27.69,28.52,29.28,29.96,30.57,31.1,31.54,31.89,32.15,32.31,32.39,32.36,32.24,32.03,31.72,31.32,30.84,30.27,29.62,28.9,28.1,27.25,26.33,25.37,24.36,23.31,22.23,21.14,20.03,18.92,17.81,16.71,15.63,14.58,13.56,12.59,11.66,10.8,9.99,9.26,8.6,8.02,7.52,7.11,6.79,6.56,6.43,6.39,6.45,6.6,6.84,7.18,7.61,8.12,8.72,9.39,10.14,10.96,11.83,12.77,13.75,14.77,15.83,16.91,18.01,19.12,20.24,21.34,22.44,23.51,24.55,25.55,26.51,27.41,28.26,29.04,29.75,30.38,30.94,31.41,31.79,32.07,32.27,32.37,32.38,32.29,32.11,31.83,31.46,31.01,30.46,29.84,29.14,28.37,27.53,26.63,25.68,24.69,23.65,22.59,21.5,20.39,19.28,18.16,17.06,15.98,14.91,13.89,12.9,11.96,11.07,10.25,9.49,8.8,8.2,7.67,7.23,6.88,6.63,6.46,6.39,6.42,6.54,6.75,7.06,7.46,7.95,8.51,9.16,9.89,10.68,11.54,12.46,13.42,14.44,15.48,16.56,17.65,18.76,19.88,20.99,22.09,23.16,24.21,25.23,26.2,27.12,27.99,28.79,29.53,30.19,30.77,31.26,31.67,31.99,32.22,32.35,32.39,32.33,32.18,31.93,31.59,31.16,30.65,30.05,29.38,28.63,27.81,26.93,26.0,25.02,23.99,22.93,21.85,20.75,19.64,18.52,17.42,16.32,15.25,14.22,13.21,12.26,11.35,10.51,9.73,9.02,8.39,30.55,29.6,28.6,27.56,26.49,25.39,24.29,23.17,22.06,20.96,19.88,18.82,17.8,16.81,15.88,15.0,14.18,13.43,12.76,12.16,11.64,11.22,10.88,10.63,10.48,10.42,10.45,10.59,10.81,11.13,11.54,12.04,12.62,13.28,14.01,14.81,15.68,16.6,17.57,18.59,19.64,20.72,21.81,22.92,24.04,25.15,26.24,27.32,28.37,29.38,30.34,31.26,32.12,32.91,33.64,34.29,34.86,35.34,35.74,36.05,36.27,36.39,36.41,36.35,36.18,35.92,35.57,35.14,34.61,34.0,33.32,32.56,31.74,30.85,29.91,28.92,27.9,26.84,25.75,24.65,23.53,22.42,21.32,20.23,19.16,18.12,17.13,16.18,15.28,14.44,13.67,12.97,12.34,11.8,11.35,10.98,10.7,10.52,10.43,10.43,10.53,10.73,11.02,11.4,11.87,12.42,13.05,13.76,14.54,15.39,16.29,17.25,18.25,19.29,20.36,21.46,22.56,23.68,24.79,25.89,26.97,28.03,29.05,30.04,30.97,31.85,32.66,33.41,34.09,34.68,35.2,35.62,35.96,36.21,36.36,36.42,36.38,36.25,36.02,35.7,35.29,34.79,34.21,33.55,32.82,32.01,31.15,30.22,29.25,28.23,27.18,26.1,25.01,23.9,22.78,21.67,20.58,19.5,18.45,17.44,16.48,15.56,14.71,13.91,13.19,12.54,11.97,11.48,11.09,10.78,10.56,10.44,10.42,10.49,10.66,10.91,11.27,11.71,12.23,12.84,13.53,14.28,15.11,15.99,16.94,17.92,18.95,20.01,21.1,22.2,23.32,24.43,25.53,26.62,27.69,28.73,29.72,30.67,31.57,32.4,33.18,33.88,34.5,35.04,35.49,35.86,36.14,36.32,36.41,36.4,36.3,36.1,35.81,35.43,34.96,34.41,33.77,33.06,32.28,31.43,30.53,29.57,28.57,27.53,26.46,25.36,24.26,23.14,22.03,20.93,19.85,18.79,17.77,16.79,15.85,14.98,14.16,13.41,12.74,12.14,34.14,33.16,32.14,31.08,30.0,28.9,27.79,26.68,25.57,24.48,23.4,22.36,21.36,20.4,19.49,18.64,17.85,17.14,16.5,15.94,15.46,15.07,14.78,14.57,14.47,14.45,14.53,14.71,14.98,15.34,15.79,16.33,16.95,17.64,18.41,19.24,20.13,21.08,22.07,23.11,24.17,25.26,26.36,27.48,28.59,29.69,30.78,31.84,32.87,33.87,34.81,35.7,36.53,37.29,37.98,38.6,39.13,39.57,39.93,40.19,40.36,40.44,40.42,40.31,40.1,39.8,39.41,38.93,38.36,37.72,37.0,36.21,35.36,34.45,33.48,32.47,31.43,30.36,29.26,28.15,27.04,25.93,24.83,23.75,22.7,21.68,20.7,19.78,18.91,18.1,17.36,16.69,16.11,15.61,15.19,14.86,14.63,14.49,14.45,14.5,14.64,14.88,15.22,15.64,16.15,16.74,17.41,18.15,18.96,19.84,20.77,21.75,22.77,23.82,24.9,26.0,27.12,28.23,29.34,30.43,31.5,32.54,33.55,34.51,35.42,36.27,37.05,37.77,38.4,38.96,39.44,39.82,40.12,40.32,40.43,40.44,40.36,40.18,39.91,39.54,39.09,38.56,37.94,37.24,36.47,35.64,34.75,33.8,32.81,31.77,30.71,29.62,28.51,27.4,26.29,25.18,24.1,23.03,22.0,21.01,20.07,19.18,18.35,17.59,16.9,16.29,15.76,15.31,14.96,14.7,14.53,14.45,14.47,14.59,14.79,15.1,15.49,15.97,16.54,17.18,17.9,18.69,19.55,20.46,21.42,22.43,23.48,24.55,25.65,26.75,27.87,28.98,30.08,31.16,32.21,33.23,34.2,35.13,36.0,36.8,37.54,38.21,38.79,39.29,39.71,40.03,40.26,40.4,40.45,40.39,40.25,40.01,39.67,39.25,38.74,38.15,37.48,36.73,35.92,35.04,34.11,33.13,32.11,31.06,29.97,28.87,27.76,26.65,25.54,24.45,23.38,22.33,21.33,20.37,19.46,18.61,17.83,17.12,16.48,15.92,37.71,36.71,35.68,34.61,33.52,32.41,31.3,30.19,29.08,28.0,26.94,25.91,24.93,23.99,23.11,22.29,21.53,20.85,20.25,19.73,19.3,18.95,18.7,18.54,18.48,18.51,18.63,18.85,19.17,19.57,20.06,20.64,21.29,22.02,22.82,23.68,24.6,25.57,26.58,27.63,28.71,29.81,30.92,32.03,33.14,34.24,35.31,36.36,37.37,38.34,39.26,40.13,40.92,41.65,42.31,42.88,43.38,43.78,44.09,44.31,44.44,44.47,44.41,44.25,44.0,43.66,43.22,42.7,42.1,41.42,40.67,39.85,38.96,38.03,37.04,36.02,34.96,33.87,32.77,31.66,30.55,29.44,28.35,27.28,26.24,25.24,24.29,23.39,22.55,21.77,21.07,20.44,19.89,19.43,19.05,18.77,18.58,18.49,18.49,18.58,18.77,19.06,19.43,19.89,20.44,21.07,21.78,22.55,23.39,24.3,25.25,26.25,27.29,28.36,29.45,30.55,31.67,32.78,33.88,34.97,36.03,37.05,38.04,38.97,39.85,40.67,41.43,42.11,42.71,43.23,43.66,44.0,44.25,44.41,44.47,44.44,44.31,44.09,43.78,43.37,42.88,42.3,41.65,40.92,40.12,39.26,38.34,37.37,36.35,35.3,34.23,33.13,32.02,30.91,29.8,28.7,27.62,26.57,25.56,24.59,23.67,22.81,22.01,21.29,20.63,20.06,19.57,19.17,18.85,18.63,18.51,18.48,18.54,18.7,18.95,19.3,19.73,20.26,20.86,21.54,22.29,23.12,24.0,24.94,25.92,26.95,28.01,29.09,30.19,31.31,32.42,33.53,34.62,35.68,36.72,37.72,38.67,39.57,40.41,41.19,41.89,42.52,43.07,43.53,43.9,44.18,44.37,44.46,44.46,44.37,44.17,43.89,43.51,43.05,42.5,41.87,41.16,40.39,39.54,38.64,37.69,36.69,35.65,34.58,33.49,32.38,31.27,30.16,29.05,27.97,26.91,25.89,24.9,23.97,23.08,22.27,21.51,20.84,20.24,19.72,41.28,40.26,39.21,38.13,37.03,35.92,34.8,33.69,32.6,31.53,30.48,29.47,28.51,27.6,26.74,25.95,25.23,24.59,24.02,23.54,23.15,22.85,22.64,22.53,22.51,22.58,22.75,23.02,23.38,23.82,24.35,24.96,25.65,26.42,27.25,28.14,29.08,30.07,31.1,32.16,33.25,34.35,35.47,36.58,37.69,38.77,39.84,40.87,41.87,42.81,43.71,44.54,45.31,46.0,46.62,47.15,47.61,47.97,48.24,48.41,48.5,48.48,48.38,48.17,47.88,47.49,47.02,46.46,45.82,45.1,44.32,43.47,42.56,41.6,40.59,39.55,38.48,37.38,36.28,35.16,34.05,32.95,31.87,30.82,29.8,28.82,27.89,27.01,26.2,25.46,24.79,24.2,23.69,23.27,22.94,22.7,22.55,22.5,22.55,22.69,22.92,23.25,23.67,24.17,24.76,25.42,26.16,26.97,27.84,28.77,29.74,30.76,31.82,32.9,34.0,35.11,36.22,37.33,38.42,39.5,40.54,41.55,42.51,43.42,44.28,45.06,45.78,46.43,46.99,47.47,47.86,48.16,48.37,48.48,48.5,48.42,48.25,47.98,47.63,47.18,46.65,46.03,45.34,44.58,43.75,42.86,41.92,40.92,39.89,38.83,37.74,36.64,35.52,34.41,33.31,32.22,31.15,30.12,29.13,28.18,27.29,26.46,25.69,25.0,24.38,23.85,23.4,23.04,22.77,22.59,22.51,22.52,22.63,22.84,23.13,23.52,24.0,24.56,25.2,25.91,26.7,27.55,28.46,29.42,30.43,31.47,32.54,33.64,34.75,35.86,36.97,38.07,39.15,40.21,41.23,42.2,43.13,44.01,44.82,45.56,46.23,46.82,47.32,47.74,48.07,48.31,48.45,48.5,48.46,48.32,48.08,47.75,47.33,46.83,46.24,45.58,44.83,44.03,43.15,42.23,41.25,40.23,39.18,38.1,37.0,35.89,34.77,33.66,32.57,31.5,30.45,29.45,28.48,27.57,26.72,25.93,25.21,24.57,24.01,23.53,44.83,43.8,42.73,41.64,40.53,39.42,38.31,37.21,36.12,35.06,34.03,33.04,32.1,31.22,30.39,29.63,28.95,28.34,27.82,27.38,27.03,26.77,26.6,26.53,26.56,26.68,26.9,27.2,27.6,28.09,28.66,29.31,30.03,30.83,31.69,32.6,33.57,34.58,35.63,36.7,37.8,38.91,40.02,41.13,42.23,43.31,44.36,45.37,46.35,47.27,48.13,48.94,49.67,50.33,50.91,51.41,51.82,52.13,52.36,52.49,52.53,52.47,52.32,52.07,51.74,51.31,50.79,50.2,49.52,48.77,47.95,47.08,46.14,45.16,44.14,43.08,42.0,40.89,39.78,38.67,37.56,36.47,35.4,34.36,33.36,32.4,31.5,30.65,29.87,29.16,28.53,27.98,27.51,27.13,26.84,26.65,26.55,26.54,26.63,26.82,27.09,27.46,27.92,28.46,29.09,29.79,30.56,31.4,32.3,33.25,34.25,35.28,36.35,37.44,38.55,39.66,40.77,41.87,42.96,44.02,45.05,46.04,46.97,47.86,48.68,49.44,50.12,50.73,51.25,51.69,52.04,52.3,52.46,52.53,52.5,52.38,52.16,51.86,51.46,50.97,50.4,49.75,49.02,48.23,47.37,46.45,45.48,44.47,43.42,42.35,41.25,40.14,39.03,37.92,36.82,35.74,34.69,33.68,32.71,31.78,30.92,30.12,29.39,28.73,28.15,27.65,27.24,26.93,26.7,26.57,26.53,26.59,26.75,26.99,27.33,27.76,28.28,28.88,29.55,30.3,31.12,32.0,32.94,33.92,34.94,36.0,37.08,38.19,39.3,40.41,41.52,42.61,43.68,44.72,45.72,46.68,47.58,48.42,49.2,49.91,50.54,51.09,51.56,51.94,52.23,52.42,52.52,52.52,52.43,52.25,51.97,51.6,51.14,50.59,49.97,49.26,48.49,47.65,46.75,45.8,44.8,43.77,42.7,41.61,40.5,39.39,38.28,37.18,36.09,35.03,34.0,33.02,32.08,31.19,30.37,29.61,28.93,28.33,27.8,27.37,48.38,47.33,46.25,45.15,44.04,42.93,41.82,40.72,39.65,38.6,37.59,36.62,35.71,34.85,34.06,33.33,32.68,32.11,31.63,31.23,30.92,30.71,30.59,30.56,30.63,30.8,31.06,31.41,31.85,32.38,32.98,33.67,34.43,35.25,36.14,37.08,38.07,39.1,40.16,41.24,42.35,43.46,44.57,45.68,46.77,47.83,48.87,49.86,50.81,51.71,52.55,53.32,54.02,54.64,55.18,55.64,56.01,56.28,56.46,56.55,56.55,56.44,56.25,55.96,55.57,55.1,54.55,53.92,53.21,52.42,51.58,50.67,49.71,48.71,47.67,46.6,45.51,44.4,43.29,42.18,41.07,39.99,38.94,37.91,36.93,36.0,35.12,34.31,33.56,32.88,32.29,31.78,31.35,31.01,30.77,30.62,30.56,30.6,30.74,30.96,31.29,31.7,32.2,32.78,33.44,34.17,34.98,35.84,36.77,37.74,38.76,39.81,40.89,41.99,43.1,44.21,45.32,46.42,47.49,48.54,49.55,50.51,51.43,52.28,53.08,53.8,54.45,55.02,55.5,55.9,56.2,56.42,56.53,56.56,56.49,56.32,56.06,55.71,55.27,54.74,54.13,53.44,52.68,51.86,50.97,50.03,49.04,48.01,46.95,45.86,44.76,43.65,42.54,41.43,40.34,39.27,38.24,37.24,36.3,35.4,34.56,33.79,33.09,32.47,31.93,31.48,31.11,30.84,30.66,30.57,30.58,30.68,30.88,31.17,31.55,32.02,32.58,33.22,33.93,34.71,35.56,36.46,37.42,38.42,39.47,40.54,41.63,42.74,43.85,44.96,46.06,47.14,48.2,49.22,50.2,51.14,52.01,52.83,53.57,54.25,54.84,55.35,55.78,56.11,56.36,56.51,56.56,56.52,56.38,56.15,55.83,55.42,54.92,54.34,53.67,52.94,52.13,51.27,50.34,49.37,48.35,47.3,46.22,45.12,44.01,42.9,41.79,40.69,39.62,38.57,37.56,36.6,35.68,34.83,34.04,33.31,32.67,32.1,31.62,31.22,51.92,50.85,49.76,48.66,47.55,46.43,45.33,44.24,43.18,42.15,41.16,40.21,39.33,38.5,37.74,37.05,36.43,35.9,35.46,35.1,34.84,34.67,34.59,34.61,34.73,34.94,35.24,35.63,36.11,36.68,37.32,38.05,38.84,39.69,40.6,41.57,42.57,43.62,44.69,45.79,46.9,48.01,49.12,50.22,51.3,52.35,53.37,54.35,55.27,56.14,56.95,57.69,58.35,58.93,59.44,59.85,60.18,60.41,60.55,60.59,60.54,60.39,60.15,59.82,59.39,58.88,58.29,57.62,56.88,56.06,55.19,54.26,53.28,52.26,51.2,50.12,49.02,47.91,46.79,45.69,44.59,43.52,42.48,41.47,40.51,39.61,38.76,37.97,37.26,36.62,36.07,35.59,35.21,34.91,34.71,34.61,34.6,34.68,34.86,35.13,35.5,35.95,36.49,37.11,37.8,38.57,39.41,40.3,41.25,42.24,43.28,44.34,45.43,46.54,47.65,48.76,49.87,50.95,52.02,53.05,54.04,54.98,55.87,56.69,57.45,58.14,58.75,59.28,59.73,60.08,60.34,60.51,60.59,60.57,60.45,60.24,59.93,59.54,59.06,58.49,57.85,57.12,56.33,55.48,54.56,53.6,52.59,51.55,50.47,49.38,48.27,47.15,46.04,44.94,43.86,42.81,41.8,40.82,39.9,39.03,38.22,37.48,36.82,36.24,35.74,35.32,35.0,34.77,34.63,34.59,34.64,34.79,35.03,35.37,35.79,36.3,36.9,37.57,38.32,39.13,40.0,40.94,41.92,42.94,43.99,45.08,46.18,47.29,48.4,49.51,50.6,51.67,52.72,53.72,54.68,55.58,56.43,57.22,57.93,58.56,59.12,59.59,59.98,60.27,60.47,60.57,60.58,60.5,60.32,60.04,59.68,59.22,58.68,58.06,57.37,56.6,55.76,54.87,53.92,52.92,51.89,50.82,49.73,48.63,47.51,46.4,45.3,44.21,43.15,42.12,41.13,40.19,39.3,38.48,37.72,37.03,36.42,35.89,35.45,35.1,55.45,54.37,53.27,52.16,51.05,49.94,48.84,47.77,46.72,45.71,44.74,43.82,42.96,42.16,41.43,40.78,40.2,39.71,39.31,39.0,38.78,38.65,38.62,38.69,38.84,39.1,39.44,39.88,40.4,41.0,41.68,42.44,43.26,44.14,45.08,46.06,47.09,48.15,49.24,50.34,51.45,52.56,53.67,54.76,55.83,56.87,57.86,58.82,59.72,60.56,61.33,62.04,62.66,63.21,63.67,64.04,64.33,64.51,64.61,64.61,64.51,64.32,64.03,63.66,63.19,62.64,62.01,61.31,60.53,59.69,58.79,57.83,56.83,55.79,54.72,53.63,52.52,51.41,50.3,49.2,48.11,47.05,46.03,45.05,44.11,43.23,42.41,41.66,40.98,40.38,39.86,39.43,39.09,38.84,38.68,38.62,38.65,38.78,39.01,39.32,39.73,40.22,40.8,41.45,42.18,42.99,43.85,44.77,45.74,46.75,47.8,48.88,49.98,51.09,52.2,53.31,54.41,55.48,56.53,57.54,58.51,59.43,60.29,61.09,61.82,62.47,63.04,63.53,63.93,64.24,64.46,64.59,64.62,64.55,64.39,64.14,63.79,63.35,62.83,62.23,61.54,60.79,59.97,59.08,58.15,57.16,56.13,55.07,53.99,52.88,51.77,50.66,49.55,48.46,47.39,46.36,45.36,44.41,43.51,42.67,41.89,41.19,40.57,40.02,39.56,39.19,38.91,38.72,38.63,38.63,38.73,38.92,39.21,39.59,40.05,40.6,41.23,41.94,42.72,43.56,44.46,45.42,46.42,47.46,48.53,49.62,50.73,51.84,52.95,54.05,55.14,56.2,57.22,58.2,59.14,60.02,60.84,61.59,62.27,62.87,63.38,63.81,64.15,64.4,64.56,64.62,64.58,64.45,64.23,63.91,63.5,63.01,62.43,61.77,61.04,60.24,59.38,58.46,57.48,56.47,55.42,54.34,53.24,52.13,51.02,49.91,48.81,47.74,46.69,45.68,44.71,43.79,42.93,42.14,41.41,40.76,40.19,39.7,39.3,38.99,58.97,57.89,56.78,55.67,54.56,53.45,52.36,51.3,50.27,49.27,48.33,47.43,46.6,45.84,45.14,44.53,43.99,43.54,43.18,42.91,42.73,42.65,42.67,42.78,42.98,43.28,43.67,44.14,44.7,45.34,46.06,46.84,47.69,48.6,49.57,50.57,51.61,52.69,53.78,54.89,56.0,57.11,58.21,59.29,60.35,61.37,62.35,63.28,64.15,64.96,65.7,66.37,66.96,67.47,67.89,68.22,68.45,68.6,68.65,68.6,68.46,68.22,67.9,67.48,66.97,66.39,65.72,64.98,64.17,63.3,62.37,61.39,60.38,59.32,58.24,57.14,56.03,54.92,53.81,52.71,51.64,50.6,49.59,48.63,47.72,46.86,46.08,45.36,44.72,44.15,43.68,43.29,42.99,42.78,42.67,42.65,42.73,42.9,43.17,43.53,43.98,44.51,45.13,45.82,46.58,47.41,48.3,49.25,50.24,51.27,52.34,53.42,54.53,55.64,56.75,57.86,58.95,60.01,61.04,62.03,62.98,63.87,64.7,65.47,66.16,66.78,67.31,67.76,68.12,68.39,68.56,68.64,68.63,68.52,68.31,68.01,67.62,67.15,66.59,65.94,65.23,64.44,63.59,62.68,61.72,60.71,59.67,58.59,57.5,56.39,55.28,54.17,53.07,51.99,50.93,49.91,48.93,48.01,47.13,46.33,45.58,44.92,44.33,43.82,43.4,43.07,42.84,42.7,42.65,42.7,42.84,43.07,43.4,43.82,44.33,44.92,45.58,46.33,47.14,48.01,48.94,49.91,50.93,51.99,53.07,54.17,55.28,56.39,57.5,58.6,59.67,60.71,61.72,62.68,63.59,64.44,65.23,65.95,66.59,67.15,67.62,68.01,68.31,68.52,68.63,68.64,68.56,68.39,68.12,67.76,67.31,66.78,66.16,65.47,64.7,63.87,62.98,62.03,61.04,60.01,58.94,57.86,56.75,55.64,54.53,53.42,52.33,51.27,50.24,49.25,48.3,47.41,46.58,45.82,45.12,44.51,43.98,43.53,43.17,42.9,62.49,61.4,60.29,59.17,58.06,56.97,55.89,54.84,53.82,52.85,51.93,51.06,50.26,49.53,48.87,48.29,47.8,47.39,47.07,46.84,46.71,46.68,46.74,46.89,47.14,47.48,47.91,48.42,49.02,49.7,50.45,51.27,52.14,53.08,54.06,55.09,56.14,57.23,58.33,59.44,60.55,61.66,62.75,63.82,64.86,65.86,66.82,67.72,68.57,69.35,70.05,70.69,71.24,71.7,72.08,72.37,72.56,72.66,72.67,72.58,72.39,72.11,71.74,71.28,70.74,70.11,69.41,68.64,67.8,66.9,65.95,64.95,63.91,62.85,61.75,60.65,59.54,58.42,57.32,56.24,55.17,54.15,53.16,52.22,51.34,50.51,49.76,49.08,48.47,47.95,47.51,47.16,46.91,46.75,46.68,46.71,46.83,47.05,47.36,47.76,48.25,48.82,49.47,50.2,50.99,51.85,52.77,53.74,54.75,55.8,56.87,57.97,59.08,60.19,61.3,62.4,63.48,64.53,65.54,66.51,67.44,68.3,69.1,69.83,70.49,71.07,71.56,71.97,72.29,72.51,72.64,72.68,72.62,72.46,72.21,71.87,71.44,70.92,70.32,69.64,68.89,68.08,67.2,66.26,65.28,64.25,63.19,62.11,61.01,59.9,58.78,57.68,56.58,55.52,54.48,53.48,52.52,51.62,50.77,50.0,49.29,48.66,48.11,47.64,47.27,46.98,46.79,46.69,46.69,46.78,46.97,47.25,47.62,48.08,48.62,49.25,49.95,50.73,51.57,52.47,53.42,54.42,55.45,56.52,57.61,58.72,59.83,60.94,62.05,63.13,64.19,65.22,66.2,67.14,68.03,68.85,69.6,70.29,70.89,71.41,71.85,72.19,72.45,72.61,72.67,72.65,72.52,72.3,71.99,71.59,71.1,70.53,69.87,69.15,68.35,67.49,66.57,65.6,64.59,63.54,62.46,61.37,60.26,59.14,58.03,56.94,55.86,54.81,53.8,52.83,51.9,51.04,50.24,49.51,48.85,48.28,47.78,47.38,47.06,46.84,66.01,64.91,63.79,62.68,61.58,60.49,59.42,58.38,57.39,56.44,55.54,54.71,53.94,53.24,52.62,52.08,51.62,51.26,50.98,50.8,50.71,50.72,50.83,51.02,51.32,51.7,52.17,52.72,53.36,54.07,54.85,55.7,56.61,57.56,58.57,59.61,60.68,61.77,62.88,63.99,65.1,66.21,67.29,68.34,69.37,70.35,71.28,72.16,72.97,73.72,74.39,74.98,75.5,75.92,76.26,76.5,76.65,76.7,76.66,76.53,76.3,75.98,75.56,75.06,74.48,73.82,73.08,72.28,71.41,70.49,69.51,68.49,67.44,66.36,65.26,64.15,63.04,61.93,60.84,59.76,58.72,57.71,56.74,55.83,54.97,54.18,53.46,52.81,52.24,51.76,51.37,51.06,50.85,50.73,50.71,50.78,50.95,51.21,51.56,52.01,52.53,53.14,53.83,54.59,55.42,56.31,57.25,58.24,59.27,60.33,61.42,62.52,63.63,64.74,65.85,66.94,68.01,69.04,70.03,70.98,71.88,72.71,73.48,74.18,74.8,75.34,75.79,76.16,76.43,76.61,76.7,76.69,76.58,76.38,76.09,75.71,75.24,74.68,74.04,73.33,72.55,71.7,70.79,69.83,68.83,67.79,66.72,65.62,64.52,63.4,62.29,61.19,60.11,59.05,58.03,57.05,56.12,55.24,54.43,53.68,53.01,52.42,51.91,51.48,51.15,50.91,50.76,50.71,50.75,50.88,51.12,51.44,51.85,52.35,52.94,53.6,54.34,55.14,56.01,56.94,57.91,58.93,59.98,61.06,62.16,63.27,64.38,65.49,66.59,67.66,68.71,69.72,70.68,71.59,72.45,73.24,73.96,74.61,75.17,75.66,76.05,76.35,76.56,76.68,76.7,76.63,76.46,76.2,75.84,75.4,74.87,74.26,73.57,72.81,71.98,71.09,70.15,69.16,68.13,67.07,65.98,64.88,63.76,62.65,61.55,60.46,59.39,58.36,57.36,56.41,55.52,54.69,53.92,53.22,52.6,52.06,51.61,51.25,50.98,50.8,69.52,68.41,67.3,66.19,65.09,64.01,62.96,61.94,60.97,60.04,59.17,58.37,57.63,56.97,56.38,55.88,55.47,55.14,54.91,54.78,54.73,54.79,54.94,55.18,55.51,55.94,56.45,57.04,57.71,58.46,59.27,60.15,61.08,62.06,63.08,64.14,65.22,66.32,67.43,68.55,69.65,70.75,71.82,72.86,73.86,74.82,75.73,76.58,77.36,78.07,78.71,79.26,79.74,80.12,80.41,80.61,80.72,80.73,80.64,80.46,80.19,79.82,79.37,78.83,78.21,77.51,76.74,75.91,75.01,74.06,73.07,72.03,70.97,69.88,68.77,67.66,66.55,65.44,64.36,63.29,62.27,61.28,60.33,59.45,58.62,57.86,57.17,56.56,56.03,55.59,55.24,54.98,54.81,54.74,54.76,54.88,55.09,55.39,55.79,56.27,56.84,57.49,58.21,59.0,59.86,60.77,61.74,62.75,63.79,64.87,65.96,67.07,68.18,69.29,70.39,71.47,72.52,73.54,74.52,75.44,76.31,77.11,77.85,78.51,79.09,79.59,80.0,80.33,80.56,80.69,80.73,80.68,80.53,80.29,79.95,79.52,79.01,78.42,77.74,77.0,76.18,75.31,74.38,73.39,72.37,71.32,70.23,69.13,68.02,66.91,65.8,64.71,63.64,62.6,61.59,60.63,59.73,58.88,58.1,57.39,56.75,56.2,55.73,55.34,55.05,54.85,54.75,54.74,54.83,55.01,55.29,55.65,56.11,56.65,57.27,57.97,58.74,59.57,60.47,61.42,62.41,63.45,64.52,65.6,66.71,67.82,68.94,70.04,71.13,72.19,73.22,74.2,75.15,76.03,76.86,77.62,78.3,78.91,79.44,79.88,80.23,80.49,80.66,80.73,80.71,80.59,80.37,80.07,79.67,79.19,78.62,77.97,77.25,76.46,75.6,74.68,73.72,72.71,71.66,70.59,69.49,68.38,67.27,66.16,65.06,63.98,62.93,61.91,60.94,60.02,59.15,58.34,57.61,56.95,56.37,55.87,55.46,55.14,54.91,54.77,73.03,71.92,70.8,69.7,68.61,67.54,66.5,65.5,64.55,63.65,62.81,62.04,61.34,60.71,60.16,59.7,59.33,59.05,58.87,58.77,58.78,58.87,59.07,59.35,59.73,60.2,60.75,61.38,62.08,62.86,63.71,64.61,65.56,66.56,67.6,68.67,69.76,70.87,71.98,73.1,74.2,75.28,76.34,77.36,78.35,79.28,80.16,80.98,81.73,82.41,83.01,83.53,83.96,84.3,84.55,84.7,84.76,84.73,84.6,84.37,84.06,83.65,83.15,82.58,81.92,81.19,80.39,79.52,78.6,77.63,76.61,75.56,74.49,73.39,72.28,71.16,70.06,68.96,67.88,66.84,65.82,64.86,63.94,63.08,62.28,61.56,60.9,60.33,59.84,59.44,59.13,58.92,58.79,58.76,58.83,58.99,59.25,59.6,60.03,60.56,61.16,61.85,62.6,63.42,64.31,65.25,66.23,67.26,68.32,69.41,70.51,71.62,72.74,73.84,74.93,76.0,77.04,78.03,78.99,79.88,80.72,81.5,82.2,82.82,83.37,83.83,84.2,84.48,84.66,84.75,84.75,84.65,84.46,84.17,83.79,83.32,82.77,82.14,81.43,80.65,79.81,78.9,77.95,76.95,75.91,74.84,73.75,72.64,71.53,70.41,69.31,68.23,67.17,66.15,65.16,64.23,63.35,62.53,61.78,61.11,60.51,59.99,59.56,59.22,58.98,58.82,58.76,58.8,58.93,59.16,59.48,59.88,60.38,60.96,61.62,62.35,63.15,64.02,64.94,65.91,66.93,67.98,69.05,70.15,71.26,72.38,73.48,74.58,75.66,76.7,77.72,78.68,79.6,80.46,81.25,81.98,82.63,83.2,83.69,84.09,84.4,84.61,84.73,84.76,84.69,84.53,84.27,83.92,83.48,82.96,82.35,81.67,80.91,80.09,79.2,78.26,77.28,76.25,75.19,74.1,73.0,71.89,70.77,69.67,68.58,67.51,66.48,65.48,64.53,63.63,62.79,62.02,61.32,60.69,60.15,59.69,59.32,59.05,58.86,58.77,76.54,75.42,74.31,73.21,72.13,71.08,70.06,69.08,68.15,67.28,66.47,65.73,65.06,64.47,63.97,63.55,63.22,62.98,62.84,62.79,62.84,62.98,63.22,63.55,63.97,64.47,65.06,65.73,66.47,67.28,68.15,69.08,70.06,71.08,72.13,73.21,74.31,75.42,76.54,77.64,78.74,79.81,80.85,81.86,82.82,83.73,84.58,85.37,86.09,86.73,87.29,87.77,88.16,88.45,88.66,88.77,88.79,88.71,88.53,88.26,87.9,87.45,86.92,86.3,85.61,84.85,84.02,83.12,82.18,81.19,80.15,79.09,78.0,76.9,75.78,74.67,73.57,72.48,71.41,70.38,69.39,68.45,67.56,66.72,65.96,65.27,64.65,64.12,63.67,63.32,63.05,62.87,62.8,62.81,62.93,63.13,63.43,63.82,64.3,64.86,65.5,66.22,67.01,67.86,68.77,69.74,70.74,71.79,72.86,73.95,75.06,76.18,77.29,78.39,79.47,80.52,81.54,82.52,83.44,84.32,85.12,85.86,86.53,87.12,87.62,88.04,88.37,88.6,88.74,88.79,88.74,88.6,88.36,88.03,87.61,87.1,86.51,85.84,85.1,84.29,83.42,82.49,81.51,80.49,79.44,78.36,77.26,76.14,75.03,73.92,72.83,71.76,70.71,69.71,68.75,67.84,66.99,66.2,65.48,64.84,64.28,63.81,63.42,63.12,62.92,62.81,62.8,62.88,63.05,63.32,63.68,64.13,64.67,65.29,65.98,66.75,67.58,68.47,69.42,70.41,71.44,72.51,73.6,74.7,75.81,76.93,78.03,79.12,80.18,81.21,82.2,83.15,84.04,84.87,85.63,86.32,86.94,87.47,87.91,88.27,88.54,88.71,88.79,88.77,88.66,88.45,88.15,87.76,87.28,86.71,86.07,85.35,84.56,83.71,82.8,81.83,80.83,79.78,78.71,77.61,76.51,75.39,74.28,73.18,72.1,71.05,70.03,69.05,68.13,67.26,66.45,65.71,65.04,64.46,63.95,63.54,63.21,62.98,62.84,62.79,80.04,78.93,77.82,76.73,75.66,74.62,73.62,72.67,71.76,70.92,70.14,69.43,68.8,68.25,67.79,67.41,67.12,66.93,66.83,66.83,66.92,67.11,67.39,67.76,68.22,68.77,69.39,70.1,70.87,71.71,72.61,73.56,74.56,75.6,76.67,77.76,78.86,79.98,81.09,82.19,83.28,84.34,85.36,86.35,87.29,88.17,88.99,89.75,90.43,91.03,91.55,91.99,92.34,92.59,92.75,92.82,92.79,92.66,92.45,92.13,91.73,91.24,90.67,90.02,89.29,88.49,87.63,86.71,85.75,84.73,83.69,82.61,81.51,80.4,79.29,78.18,77.08,76.0,74.95,73.94,72.97,72.05,71.19,70.39,69.65,69.0,68.42,67.93,67.52,67.21,66.98,66.85,66.82,66.88,67.04,67.29,67.63,68.06,68.58,69.18,69.86,70.61,71.43,72.31,73.25,74.23,75.26,76.32,77.4,78.5,79.61,80.73,81.83,82.93,83.99,85.03,86.03,86.99,87.89,88.73,89.51,90.22,90.85,91.39,91.86,92.23,92.52,92.71,92.81,92.81,92.72,92.53,92.25,91.87,91.41,90.86,90.24,89.53,88.76,87.92,87.02,86.06,85.07,84.03,82.96,81.87,80.76,79.65,78.54,77.44,76.35,75.29,74.26,73.28,72.34,71.46,70.64,69.88,69.2,68.6,68.08,67.64,67.3,67.05,66.89,66.82,66.85,66.98,67.2,67.51,67.91,68.4,68.98,69.63,70.36,71.16,72.02,72.94,73.91,74.92,75.97,77.05,78.14,79.25,80.37,81.48,82.57,83.65,84.7,85.71,86.68,87.6,88.47,89.27,89.99,90.65,91.23,91.72,92.12,92.44,92.66,92.79,92.82,92.76,92.6,92.35,92.0,91.57,91.05,90.45,89.77,89.02,88.2,87.32,86.38,85.39,84.37,83.31,82.23,81.12,80.01,78.9,77.79,76.7,75.63,74.59,73.59,72.64,71.74,70.9,70.12,69.42,68.79,68.24,67.78,67.4,67.12,66.93,66.83,66.83,83.55,82.44,81.33,80.25,79.2,78.17,77.19,76.26,75.39,74.57,73.83,73.16,72.56,72.05,71.63,71.29,71.05,70.9,70.85,70.89,71.03,71.26,71.58,72.0,72.5,73.08,73.74,74.48,75.29,76.16,77.08,78.06,79.07,80.12,81.2,82.3,83.41,84.53,85.64,86.73,87.81,88.85,89.86,90.82,91.74,92.59,93.38,94.11,94.75,95.32,95.8,96.19,96.5,96.71,96.82,96.85,96.77,96.6,96.34,95.99,95.54,95.01,94.4,93.71,92.95,92.12,91.24,90.29,89.3,88.27,87.21,86.12,85.02,83.91,82.79,81.69,80.6,79.54,78.5,77.51,76.56,75.66,74.83,74.06,73.37,72.75,72.21,71.76,71.39,71.12,70.94,70.86,70.87,70.97,71.17,71.47,71.85,72.33,72.88,73.52,74.23,75.02,75.87,76.77,77.73,78.74,79.78,80.85,81.95,83.05,84.17,85.28,86.38,87.46,88.52,89.54,90.52,91.45,92.32,93.14,93.88,94.55,95.14,95.65,96.08,96.41,96.65,96.8,96.85,96.81,96.67,96.43,96.11,95.7,95.19,94.61,93.94,93.21,92.4,91.53,90.6,89.63,88.61,87.56,86.48,85.38,84.27,83.16,82.05,80.95,79.88,78.83,77.82,76.86,75.95,75.09,74.3,73.58,72.94,72.37,71.89,71.5,71.2,70.99,70.87,70.85,70.93,71.1,71.36,71.72,72.16,72.69,73.31,73.99,74.76,75.59,76.47,77.42,78.41,79.44,80.5,81.59,82.69,83.81,84.92,86.02,87.11,88.18,89.21,90.2,91.15,92.05,92.88,93.65,94.34,94.96,95.5,95.95,96.31,96.58,96.76,96.84,96.83,96.72,96.52,96.23,95.84,95.37,94.81,94.17,93.45,92.67,91.82,90.91,89.95,88.95,87.9,86.83,85.74,84.63,83.52,82.41,81.3,80.22,79.17,78.15,77.17,76.24,75.36,74.55,73.81,73.14,72.55,72.04,71.62,71.29,71.05,70.9,70.85,70.89,87.05,85.94,84.85,83.78,82.74,81.74,80.78,79.87,79.03,78.24,77.53,76.9,76.34,75.87,75.49,75.2,75.0,74.89,74.89,74.97,75.15,75.43,75.8,76.25,76.79,77.41,78.11,78.88,79.72,80.61,81.56,82.56,83.59,84.66,85.75,86.85,87.97,89.08,90.18,91.27,92.33,93.36,94.35,95.29,96.18,97.0,97.76,98.45,99.06,99.58,100.02,100.38,100.64,100.8,100.87,100.85,100.73,100.52,100.21,99.82,99.33,98.76,98.12,97.39,96.6,95.74,94.83,93.86,92.85,91.81,90.73,89.64,88.53,87.41,86.3,85.2,84.12,83.07,82.06,81.08,80.16,79.29,78.49,77.75,77.09,76.51,76.01,75.6,75.28,75.05,74.92,74.88,74.93,75.08,75.33,75.67,76.09,76.61,77.2,77.88,78.62,79.44,80.32,81.25,82.23,83.25,84.31,85.39,86.49,87.61,88.72,89.83,90.92,91.99,93.03,94.03,94.99,95.89,96.74,97.52,98.23,98.87,99.42,99.89,100.27,100.56,100.76,100.86,100.87,100.78,100.6,100.32,99.95,99.5,98.96,98.33,97.64,96.86,96.03,95.13,94.18,93.18,92.15,91.08,89.99,88.89,87.77,86.66,85.56,84.47,83.41,82.38,81.39,80.45,79.57,78.74,77.98,77.3,76.69,76.17,75.73,75.37,75.12,74.95,74.88,74.91,75.03,75.24,75.55,75.95,76.43,77.0,77.65,78.37,79.17,80.02,80.94,81.91,82.92,83.96,85.04,86.14,87.24,88.36,89.47,90.57,91.64,92.7,93.71,94.68,95.61,96.47,97.28,98.01,98.67,99.25,99.75,100.16,100.48,100.71,100.84,100.88,100.82,100.67,100.42,100.08,99.66,99.14,98.55,97.87,97.12,96.31,95.43,94.49,93.51,92.49,91.43,90.35,89.25,88.14,87.02,85.91,84.82,83.75,82.71,81.71,80.75,79.85,79.0,78.22,77.51,76.88,76.33,75.86,75.48,75.19,74.99,74.89,74.89,74.98,90.56,89.46,88.37,87.32,86.29,85.31,84.37,83.5,82.68,81.93,81.25,80.65,80.14,79.71,79.37,79.12,78.97,78.91,78.94,79.07,79.3,79.62,80.03,80.52,81.1,81.76,82.49,83.29,84.16,85.08,86.05,87.07,88.12,89.2,90.3,91.4,92.52,93.63,94.72,95.8,96.85,97.86,98.83,99.74,100.6,101.4,102.12,102.77,103.34,103.83,104.23,104.54,104.76,104.88,104.9,104.84,104.67,104.42,104.07,103.63,103.1,102.5,101.81,101.06,100.23,99.35,98.41,97.42,96.39,95.33,94.25,93.14,92.03,90.92,89.81,88.72,87.66,86.62,85.62,84.67,83.77,82.94,82.16,81.46,80.84,80.3,79.84,79.47,79.19,79.01,78.92,78.92,79.02,79.22,79.51,79.88,80.35,80.9,81.54,82.25,83.03,83.87,84.78,85.73,86.73,87.77,88.84,89.94,91.04,92.16,93.27,94.37,95.45,96.51,97.53,98.52,99.45,100.33,101.15,101.89,102.57,103.17,103.68,104.11,104.45,104.7,104.85,104.91,104.87,104.74,104.51,104.19,103.78,103.28,102.7,102.04,101.31,100.51,99.64,98.72,97.75,96.73,95.68,94.6,93.5,92.39,91.28,90.17,89.07,88.0,86.95,85.94,84.97,84.06,83.2,82.41,81.68,81.03,80.46,79.98,79.58,79.27,79.06,78.93,78.91,78.98,79.14,79.4,79.75,80.19,80.72,81.32,82.01,82.77,83.59,84.48,85.42,86.41,87.43,88.49,89.58,90.68,91.8,92.91,94.01,95.11,96.17,97.21,98.2,99.15,100.05,100.89,101.66,102.36,102.98,103.52,103.98,104.35,104.63,104.81,104.9,104.89,104.79,104.59,104.3,103.92,103.45,102.9,102.27,101.56,100.77,99.93,99.02,98.07,97.06,96.02,94.95,93.86,92.75,91.64,90.53,89.43,88.34,87.29,86.26,85.28,84.35,83.47,82.66,81.91,81.23,80.64,80.12,79.7,79.36,79.11,78.96,78.91,78.95,79.08,94.07,92.97,91.9,90.86,89.85,88.89,87.98,87.13,86.35,85.63,84.99,84.43,83.95,83.57,83.27,83.06,82.96,82.94,83.02,83.2,83.47,83.83,84.28,84.81,85.43,86.12,86.89,87.72,88.61,89.56,90.55,91.59,92.65,93.74,94.84,95.96,97.07,98.17,99.26,100.33,101.36,102.35,103.29,104.18,105.01,105.78,106.47,107.08,107.61,108.06,108.42,108.68,108.85,108.93,108.91,108.8,108.59,108.29,107.9,107.42,106.86,106.21,105.5,104.71,103.85,102.94,101.98,100.97,99.93,98.85,97.76,96.65,95.54,94.43,93.33,92.25,91.19,90.17,89.2,88.27,87.4,86.59,85.85,85.19,84.6,84.1,83.68,83.35,83.12,82.98,82.94,82.99,83.13,83.37,83.7,84.12,84.63,85.22,85.89,86.63,87.45,88.32,89.25,90.23,91.25,92.3,93.38,94.49,95.6,96.71,97.82,98.91,99.98,101.03,102.03,102.99,103.9,104.75,105.54,106.25,106.89,107.45,107.92,108.31,108.61,108.81,108.92,108.93,108.85,108.67,108.4,108.04,107.59,107.05,106.43,105.74,104.97,104.14,103.24,102.3,101.3,100.27,99.2,98.12,97.01,95.9,94.79,93.68,92.59,91.53,90.5,89.51,88.57,87.68,86.85,86.09,85.4,84.78,84.25,83.81,83.45,83.19,83.02,82.94,82.96,83.07,83.28,83.58,83.98,84.46,85.02,85.67,86.39,87.18,88.03,88.94,89.91,90.91,91.96,93.03,94.13,95.24,96.35,97.46,98.56,99.64,100.69,101.71,102.69,103.61,104.48,105.29,106.03,106.69,107.28,107.78,108.19,108.52,108.75,108.89,108.94,108.88,108.74,108.5,108.16,107.74,107.23,106.64,105.97,105.23,104.41,103.54,102.61,101.63,100.61,99.55,98.47,97.37,96.26,95.15,94.04,92.94,91.87,90.83,89.83,88.87,87.96,87.11,86.32,85.61,84.97,84.41,83.94,83.56,83.26,83.06,82.95,82.94,83.03,83.2,97.58,96.5,95.44,94.41,93.42,92.49,91.6,90.78,90.03,89.35,88.74,88.22,87.79,87.44,87.19,87.03,86.97,87.0,87.12,87.34,87.65,88.06,88.55,89.12,89.78,90.5,91.3,92.16,93.08,94.05,95.06,96.11,97.19,98.29,99.4,100.51,101.62,102.72,103.79,104.84,105.86,106.83,107.75,108.61,109.41,110.14,110.79,111.37,111.86,112.27,112.58,112.8,112.93,112.96,112.9,112.74,112.49,112.15,111.71,111.2,110.59,109.91,109.16,108.34,107.46,106.52,105.54,104.51,103.45,102.37,101.27,100.16,99.04,97.94,96.84,95.78,94.74,93.74,92.78,91.88,91.04,90.27,89.56,88.93,88.38,87.92,87.55,87.26,87.07,86.98,86.98,87.07,87.26,87.54,87.92,88.38,88.93,89.56,90.26,91.04,91.88,92.78,93.73,94.73,95.77,96.84,97.93,99.04,100.15,101.26,102.36,103.45,104.51,105.53,106.52,107.45,108.34,109.16,109.91,110.59,111.19,111.71,112.14,112.49,112.74,112.9,112.96,112.93,112.8,112.58,112.27,111.86,111.37,110.8,110.14,109.41,108.61,107.75,106.83,105.86,104.85,103.8,102.72,101.63,100.52,99.4,98.29,97.2,96.12,95.07,94.06,93.09,92.17,91.31,90.51,89.78,89.13,88.55,88.06,87.66,87.34,87.12,87.0,86.97,87.03,87.19,87.44,87.79,88.22,88.74,89.34,90.02,90.78,91.6,92.48,93.42,94.4,95.43,96.49,97.57,98.68,99.79,100.9,102.01,103.1,104.17,105.2,106.2,107.16,108.06,108.9,109.67,110.38,111.01,111.55,112.01,112.39,112.67,112.86,112.95,112.95,112.86,112.66,112.38,112.01,111.54,110.99,110.36,109.66,108.88,108.04,107.14,106.18,105.18,104.14,103.08,101.98,100.88,99.76,98.65,97.55,96.47,95.41,94.38,93.4,92.46,91.58,90.76,90.01,89.33,88.73,88.21,87.78,87.44,87.18,87.03,86.97,87.0,87.13,87.35,101.1,100.02,98.98,97.97,97.01,96.09,95.24,94.45,93.73,93.08,92.52,92.04,91.64,91.34,91.13,91.02,91.0,91.07,91.24,91.51,91.86,92.31,92.84,93.45,94.14,94.9,95.73,96.62,97.56,98.55,99.58,100.64,101.73,102.84,103.95,105.06,106.17,107.26,108.32,109.35,110.35,111.29,112.19,113.02,113.79,114.48,115.1,115.64,116.09,116.45,116.73,116.9,116.99,116.97,116.87,116.66,116.37,115.98,115.51,114.95,114.31,113.6,112.81,111.96,111.05,110.09,109.09,108.05,106.98,105.88,104.77,103.66,102.55,101.45,100.37,99.31,98.29,97.31,96.38,95.51,94.7,93.95,93.28,92.69,92.18,91.76,91.43,91.19,91.04,90.99,91.04,91.18,91.41,91.74,92.15,92.66,93.24,93.91,94.65,95.45,96.32,97.25,98.23,99.24,100.3,101.38,102.48,103.59,104.7,105.81,106.9,107.98,109.02,110.03,110.99,111.9,112.76,113.55,114.27,114.91,115.48,115.95,116.35,116.65,116.86,116.97,116.99,116.91,116.74,116.48,116.12,115.67,115.14,114.53,113.84,113.07,112.25,111.36,110.41,109.42,108.39,107.33,106.24,105.13,104.02,102.91,101.8,100.72,99.65,98.62,97.63,96.68,95.79,94.95,94.19,93.49,92.87,92.34,91.89,91.53,91.26,91.08,91.0,91.01,91.12,91.32,91.62,92.01,92.48,93.04,93.68,94.4,95.18,96.03,96.94,97.9,98.91,99.95,101.02,102.12,103.23,104.34,105.45,106.55,107.63,108.69,109.71,110.69,111.62,112.49,113.3,114.04,114.71,115.3,115.81,116.23,116.56,116.8,116.94,116.99,116.95,116.81,116.57,116.24,115.83,115.32,114.74,114.07,113.33,112.52,111.65,110.72,109.75,108.73,107.67,106.59,105.49,104.38,103.27,102.16,101.07,99.99,98.95,97.94,96.98,96.07,95.22,94.43,93.71,93.07,92.5,92.02,91.63,91.33,91.13,91.01,91.0,91.08,91.25,91.51,104.62,103.56,102.53,101.54,100.6,99.71,98.89,98.13,97.44,96.84,96.31,95.87,95.52,95.26,95.09,95.02,95.05,95.17,95.38,95.69,96.09,96.57,97.14,97.79,98.52,99.31,100.17,101.08,102.05,103.06,104.11,105.18,106.28,107.39,108.5,109.61,110.71,111.79,112.84,113.85,114.83,115.75,116.62,117.42,118.15,118.81,119.39,119.89,120.3,120.62,120.85,120.98,121.02,120.96,120.81,120.57,120.23,119.8,119.29,118.69,118.01,117.27,116.45,115.57,114.64,113.66,112.63,111.58,110.49,109.39,108.28,107.17,106.06,104.97,103.9,102.86,101.85,100.9,99.99,99.15,98.37,97.66,97.02,96.47,96.0,95.62,95.33,95.14,95.04,95.03,95.12,95.3,95.58,95.95,96.41,96.95,97.57,98.27,99.05,99.88,100.78,101.73,102.73,103.76,104.83,105.92,107.03,108.14,109.25,110.35,111.44,112.5,113.53,114.52,115.46,116.34,117.17,117.92,118.61,119.22,119.74,120.18,120.53,120.79,120.95,121.02,120.99,120.87,120.66,120.35,119.95,119.46,118.89,118.24,117.52,116.72,115.86,114.95,113.98,112.97,111.92,110.85,109.75,108.64,107.53,106.42,105.32,104.24,103.19,102.17,101.2,100.28,99.41,98.61,97.88,97.22,96.64,96.14,95.74,95.42,95.19,95.06,95.02,95.08,95.23,95.48,95.82,96.25,96.76,97.36,98.04,98.79,99.6,100.48,101.42,102.4,103.42,104.48,105.57,106.67,107.78,108.89,110.0,111.09,112.16,113.2,114.2,115.16,116.06,116.91,117.69,118.39,119.03,119.58,120.05,120.42,120.71,120.91,121.01,121.01,120.92,120.74,120.46,120.09,119.63,119.09,118.46,117.76,116.99,116.15,115.25,114.3,113.3,112.27,111.2,110.11,109.0,107.89,106.78,105.67,104.59,103.53,102.5,101.51,100.57,99.69,98.87,98.11,97.43,96.82,96.3,95.86,95.51,95.25,95.09,95.02,95.05,95.17,95.39,95.7,108.14,107.1,106.09,105.12,104.2,103.34,102.55,101.83,101.18,100.61,100.12,99.72,99.41,99.2,99.08,99.05,99.12,99.29,99.55,99.9,100.33,100.86,101.47,102.15,102.91,103.73,104.62,105.56,106.55,107.58,108.64,109.72,110.83,111.94,113.05,114.16,115.25,116.31,117.35,118.35,119.3,120.19,121.03,121.8,122.5,123.13,123.67,124.12,124.49,124.77,124.95,125.04,125.03,124.93,124.74,124.45,124.07,123.6,123.04,122.41,121.7,120.92,120.07,119.17,118.21,117.21,116.17,115.1,114.01,112.9,111.78,110.67,109.57,108.49,107.43,106.41,105.43,104.49,103.62,102.8,102.05,101.38,100.78,100.27,99.84,99.5,99.26,99.11,99.05,99.09,99.22,99.45,99.77,100.18,100.68,101.26,101.92,102.66,103.46,104.33,105.25,106.22,107.24,108.29,109.37,110.47,111.58,112.69,113.8,114.9,115.97,117.02,118.03,118.99,119.91,120.77,121.56,122.28,122.93,123.5,123.99,124.38,124.69,124.9,125.02,125.05,124.98,124.81,124.55,124.2,123.76,123.23,122.62,121.94,121.18,120.35,119.47,118.53,117.54,116.51,115.45,114.36,113.26,112.15,111.03,109.93,108.84,107.77,106.74,105.74,104.79,103.89,103.06,102.29,101.59,100.97,100.43,99.97,99.6,99.33,99.15,99.06,99.07,99.17,99.37,99.66,100.04,100.51,101.06,101.7,102.41,103.19,104.04,104.95,105.9,106.91,107.95,109.02,110.11,111.22,112.33,113.44,114.54,115.63,116.68,117.71,118.69,119.62,120.5,121.31,122.06,122.73,123.33,123.84,124.26,124.6,124.84,124.99,125.05,125.01,124.87,124.65,124.32,123.91,123.41,122.83,122.17,121.43,120.63,119.76,118.84,117.86,116.85,115.8,114.72,113.62,112.51,111.39,110.28,109.19,108.11,107.07,106.06,105.09,104.18,103.32,102.53,101.81,101.16,100.59,100.11,99.71,99.41,99.19,99.08,99.05,99.13,99.29,99.55,99.91,111.68,110.64,109.65,108.71,107.82,106.99,106.23,105.54,104.93,104.4,103.95,103.59,103.33,103.16,103.08,103.1,103.22,103.43,103.73,104.12,104.6,105.16,105.81,106.53,107.32,108.17,109.09,110.05,111.06,112.1,113.17,114.27,115.38,116.49,117.6,118.7,119.78,120.83,121.85,122.83,123.75,124.62,125.43,126.17,126.83,127.42,127.92,128.34,128.66,128.9,129.04,129.08,129.03,128.88,128.64,128.31,127.89,127.38,126.78,126.11,125.37,124.56,123.68,122.75,121.77,120.75,119.7,118.62,117.51,116.4,115.29,114.18,113.09,112.02,110.98,109.97,109.01,108.1,107.25,106.47,105.76,105.12,104.56,104.09,103.7,103.41,103.2,103.1,103.09,103.17,103.35,103.62,103.98,104.44,104.97,105.59,106.29,107.06,107.89,108.78,109.73,110.73,111.76,112.82,113.91,115.02,116.13,117.24,118.35,119.43,120.5,121.53,122.52,123.46,124.35,125.18,125.94,126.63,127.24,127.77,128.21,128.57,128.83,129.0,129.08,129.05,128.94,128.73,128.43,128.03,127.55,126.99,126.34,125.62,124.83,123.97,123.06,122.1,121.09,120.04,118.97,117.87,116.76,115.65,114.54,113.44,112.36,111.31,110.29,109.32,108.39,107.52,106.72,105.98,105.32,104.73,104.23,103.82,103.49,103.26,103.12,103.08,103.13,103.28,103.52,103.86,104.28,104.79,105.38,106.05,106.8,107.61,108.49,109.42,110.4,111.42,112.48,113.56,114.66,115.77,116.88,117.99,119.08,120.16,121.2,122.2,123.16,124.07,124.92,125.7,126.41,127.05,127.61,128.08,128.46,128.76,128.96,129.06,129.07,128.99,128.81,128.53,128.17,127.72,127.18,126.56,125.86,125.09,124.26,123.36,122.41,121.42,120.39,119.32,118.23,117.13,116.01,114.9,113.8,112.71,111.65,110.62,109.63,108.69,107.8,106.97,106.21,105.52,104.91,104.38,103.94,103.59,103.32,103.16,103.08,103.1,103.22,103.43,103.74,104.13,115.22,114.2,113.23,112.31,111.45,110.65,109.92,109.27,108.7,108.2,107.8,107.49,107.27,107.14,107.11,107.17,107.33,107.59,107.93,108.36,108.88,109.49,110.17,110.92,111.74,112.62,113.56,114.55,115.57,116.63,117.72,118.82,119.93,121.04,122.15,123.24,124.31,125.35,126.35,127.3,128.2,129.04,129.82,130.52,131.15,131.7,132.16,132.53,132.81,133.0,133.1,133.1,133.0,132.81,132.52,132.15,131.69,131.14,130.51,129.8,129.03,128.18,127.28,126.33,125.33,124.29,123.22,122.13,121.02,119.91,118.8,117.7,116.61,115.55,114.53,113.54,112.61,111.72,110.91,110.15,109.47,108.87,108.35,107.92,107.58,107.33,107.17,107.11,107.14,107.27,107.49,107.81,108.21,108.71,109.28,109.94,110.67,111.47,112.33,113.25,114.22,115.24,116.28,117.36,118.46,119.57,120.68,121.79,122.89,123.97,125.01,126.03,127.0,127.91,128.78,129.57,130.3,130.95,131.53,132.02,132.42,132.73,132.95,133.08,133.11,133.04,132.88,132.63,132.28,131.85,131.32,130.72,130.04,129.28,128.46,127.58,126.64,125.66,124.63,123.57,122.48,121.38,120.27,119.16,118.05,116.96,115.89,114.85,113.86,112.9,112.0,111.16,110.39,109.69,109.06,108.51,108.05,107.68,107.4,107.21,107.12,107.12,107.22,107.41,107.7,108.07,108.54,109.09,109.72,110.42,111.2,112.04,112.95,113.9,114.9,115.94,117.01,118.1,119.21,120.32,121.43,122.54,123.62,124.68,125.7,126.69,127.62,128.5,129.32,130.07,130.75,131.35,131.87,132.3,132.64,132.89,133.05,133.11,133.07,132.94,132.72,132.4,132.0,131.5,130.93,130.27,129.54,128.74,127.87,126.95,125.98,124.97,123.92,122.84,121.74,120.63,119.52,118.41,117.31,116.24,115.19,114.18,113.21,112.29,111.43,110.63,109.91,109.25,108.68,108.19,107.79,107.48,107.26,107.14,107.11,107.18,107.34,107.59,107.94,108.38,118.76,117.77,116.82,115.93,115.1,114.33,113.64,113.02,112.48,112.03,111.67,111.4,111.22,111.14,111.16,111.27,111.47,111.76,112.15,112.63,113.19,113.83,114.54,115.33,116.18,117.09,118.05,119.05,120.1,121.17,122.26,123.37,124.48,125.59,126.69,127.78,128.83,129.85,130.83,131.76,132.63,133.44,134.19,134.85,135.44,135.95,136.37,136.7,136.94,137.09,137.14,137.09,136.95,136.72,136.39,135.97,135.47,134.88,134.21,133.47,132.67,131.79,130.87,129.89,128.87,127.82,126.74,125.64,124.53,123.41,122.31,121.21,120.14,119.09,118.09,117.12,116.21,115.36,114.57,113.85,113.21,112.65,112.17,111.78,111.48,111.27,111.16,111.14,111.22,111.39,111.66,112.02,112.46,113.0,113.61,114.3,115.06,115.9,116.79,117.73,118.72,119.75,120.82,121.9,123.01,124.12,125.23,126.34,127.43,128.49,129.52,130.52,131.46,132.36,133.19,133.95,134.65,135.26,135.8,136.25,136.61,136.88,137.05,137.13,137.12,137.01,136.8,136.5,136.12,135.64,135.08,134.44,133.72,132.94,132.08,131.17,130.21,129.21,128.16,127.09,126.0,124.89,123.78,122.66,121.56,120.48,119.43,118.41,117.43,116.5,115.63,114.82,114.08,113.41,112.82,112.31,111.9,111.57,111.33,111.19,111.14,111.18,111.33,111.56,111.89,112.31,112.81,113.4,114.07,114.81,115.62,116.49,117.42,118.4,119.42,120.47,121.55,122.65,123.76,124.87,125.98,127.08,128.15,129.19,130.2,131.16,132.07,132.92,133.71,134.43,135.07,135.63,136.11,136.5,136.8,137.0,137.12,137.13,137.05,136.88,136.61,136.25,135.8,135.27,134.65,133.96,133.2,132.37,131.48,130.53,129.54,128.51,127.44,126.35,125.25,124.14,123.02,121.92,120.83,119.77,118.74,117.74,116.8,115.91,115.08,114.31,113.62,113.0,112.47,112.02,111.66,111.4,111.22,111.14,111.16,111.27,111.48,111.77,112.16,112.64,122.32,121.35,120.42,119.56,118.76,118.02,117.36,116.79,116.29,115.88,115.56,115.34,115.2,115.17,115.22,115.38,115.63,115.96,116.39,116.91,117.51,118.18,118.93,119.75,120.63,121.56,122.54,123.57,124.62,125.71,126.81,127.92,129.03,130.14,131.23,132.3,133.34,134.35,135.3,136.21,137.05,137.83,138.54,139.17,139.72,140.19,140.57,140.86,141.05,141.15,141.16,141.07,140.88,140.6,140.23,139.77,139.23,138.61,137.9,137.13,136.29,135.39,134.44,133.45,132.41,131.34,130.25,129.15,128.03,126.92,125.82,124.73,123.67,122.64,121.66,120.72,119.83,119.01,118.25,117.57,116.96,116.44,116.0,115.65,115.4,115.24,115.17,115.2,115.32,115.53,115.84,116.24,116.73,117.3,117.95,118.68,119.48,120.34,121.25,122.22,123.23,124.28,125.35,126.45,127.56,128.67,129.78,130.88,131.96,133.01,134.03,135.0,135.92,136.78,137.58,138.32,138.97,139.55,140.05,140.46,140.77,141.0,141.13,141.16,141.11,140.95,140.7,140.36,139.93,139.42,138.82,138.14,137.39,136.57,135.69,134.76,133.77,132.75,131.69,130.61,129.51,128.39,127.28,126.17,125.08,124.01,122.97,121.97,121.02,120.11,119.27,118.49,117.78,117.15,116.6,116.14,115.76,115.47,115.28,115.18,115.18,115.27,115.45,115.73,116.1,116.56,117.11,117.73,118.44,119.21,120.05,120.95,121.9,122.9,123.94,125.0,126.09,127.2,128.31,129.43,130.53,131.61,132.67,133.7,134.69,135.63,136.51,137.33,138.09,138.77,139.37,139.9,140.33,140.68,140.94,141.1,141.16,141.13,141.01,140.79,140.48,140.08,139.59,139.02,138.37,137.64,136.84,135.98,135.07,134.1,133.09,132.04,130.96,129.86,128.76,127.64,126.53,125.43,124.36,123.31,122.29,121.32,120.4,119.54,118.74,118.0,117.35,116.77,116.28,115.87,115.55,115.33,115.2,115.17,115.23,115.38,115.63,115.97,116.41,116.92,125.89,124.94,124.04,123.2,122.43,121.73,121.11,120.57,120.11,119.75,119.47,119.29,119.2,119.21,119.31,119.51,119.8,120.18,120.65,121.21,121.84,122.55,123.34,124.18,125.09,126.05,127.05,128.09,129.16,130.25,131.36,132.47,133.59,134.69,135.77,136.83,137.85,138.83,139.76,140.64,141.45,142.2,142.87,143.47,143.98,144.41,144.74,144.99,145.14,145.19,145.15,145.02,144.79,144.47,144.06,143.56,142.97,142.31,141.58,140.77,139.91,138.98,138.01,136.99,135.94,134.86,133.76,132.65,131.54,130.43,129.33,128.26,127.21,126.2,125.24,124.32,123.47,122.67,121.95,121.3,120.74,120.25,119.86,119.55,119.34,119.22,119.2,119.27,119.44,119.7,120.05,120.49,121.02,121.63,122.32,123.08,123.9,124.79,125.73,126.72,127.75,128.81,129.9,131.0,132.11,133.23,134.33,135.42,136.49,137.52,138.52,139.47,140.36,141.2,141.97,142.66,143.29,143.83,144.28,144.65,144.92,145.1,145.19,145.18,145.07,144.87,144.58,144.2,143.73,143.17,142.54,141.82,141.04,140.19,139.29,138.33,137.33,136.28,135.21,134.12,133.01,131.9,130.79,129.69,128.6,127.55,126.53,125.55,124.61,123.74,122.92,122.18,121.51,120.91,120.4,119.98,119.64,119.4,119.25,119.19,119.24,119.37,119.6,119.93,120.34,120.84,121.42,122.08,122.82,123.63,124.49,125.42,126.39,127.41,128.46,129.54,130.64,131.75,132.87,133.97,135.07,136.14,137.19,138.2,139.16,140.08,140.93,141.72,142.45,143.09,143.66,144.14,144.54,144.84,145.05,145.17,145.19,145.12,144.95,144.69,144.33,143.89,143.36,142.75,142.06,141.3,140.48,139.59,138.65,137.66,136.63,135.56,134.48,133.37,132.26,131.15,130.04,128.95,127.89,126.85,125.86,124.91,124.02,123.18,122.41,121.72,121.1,120.56,120.1,119.74,119.47,119.29,119.2,119.21,119.32,119.52,119.81,120.2,120.67,121.22,129.46,128.54,127.67,126.86,126.12,125.46,124.88,124.37,123.96,123.64,123.4,123.27,123.22,123.28,123.42,123.67,124.0,124.42,124.93,125.53,126.2,126.94,127.76,128.63,129.56,130.54,131.56,132.62,133.7,134.8,135.91,137.03,138.13,139.23,140.3,141.34,142.34,143.3,144.21,145.06,145.84,146.56,147.19,147.75,148.22,148.61,148.9,149.1,149.21,149.22,149.13,148.95,148.68,148.31,147.86,147.32,146.7,146.01,145.24,144.4,143.51,142.56,141.56,140.53,139.46,138.38,137.27,136.16,135.04,133.94,132.85,131.79,130.76,129.77,128.83,127.94,127.11,126.35,125.67,125.06,124.53,124.08,123.73,123.47,123.3,123.23,123.25,123.37,123.58,123.88,124.28,124.76,125.32,125.97,126.69,127.48,128.34,129.25,130.22,131.23,132.27,133.35,134.44,135.55,136.67,137.78,138.87,139.95,141.01,142.02,143.0,143.92,144.79,145.6,146.33,146.99,147.58,148.08,148.49,148.81,149.04,149.18,149.22,149.17,149.02,148.78,148.44,148.02,147.51,146.91,146.24,145.49,144.68,143.8,142.87,141.89,140.87,139.81,138.73,137.63,136.52,135.4,134.3,133.2,132.13,131.09,130.09,129.13,128.22,127.38,126.59,125.88,125.24,124.69,124.22,123.84,123.54,123.34,123.24,123.23,123.32,123.5,123.77,124.14,124.59,125.13,125.75,126.45,127.22,128.06,128.95,129.9,130.9,131.93,133.0,134.09,135.19,136.3,137.42,138.52,139.61,140.67,141.7,142.69,143.63,144.52,145.34,146.1,146.79,147.4,147.93,148.37,148.72,148.98,149.15,149.22,149.2,149.08,148.87,148.56,148.16,147.68,147.11,146.47,145.74,144.95,144.09,143.18,142.21,141.2,140.16,139.08,137.99,136.88,135.77,134.66,133.56,132.48,131.43,130.41,129.44,128.51,127.64,126.84,126.1,125.44,124.86,124.36,123.95,123.63,123.4,123.26,123.22,123.28,123.43,123.67,124.01,124.44,124.95,125.54,133.05,132.15,131.31,130.53,129.83,129.2,128.66,128.2,127.82,127.54,127.36,127.26,127.26,127.36,127.55,127.84,128.22,128.68,129.23,129.86,130.57,131.34,132.19,133.09,134.05,135.05,136.08,137.15,138.25,139.35,140.47,141.58,142.68,143.76,144.82,145.85,146.83,147.77,148.65,149.46,150.22,150.89,151.49,152.01,152.44,152.78,153.03,153.19,153.25,153.22,153.09,152.86,152.55,152.14,151.65,151.07,150.41,149.68,148.88,148.02,147.1,146.13,145.11,144.06,142.98,141.89,140.78,139.66,138.55,137.46,136.38,135.33,134.32,133.35,132.43,131.57,130.78,130.05,129.4,128.83,128.34,127.94,127.62,127.41,127.28,127.25,127.32,127.48,127.74,128.08,128.52,129.04,129.65,130.33,131.09,131.91,132.79,133.73,134.72,135.74,136.8,137.89,138.99,140.1,141.22,142.32,143.41,144.48,145.52,146.52,147.47,148.37,149.21,149.98,150.68,151.31,151.85,152.31,152.68,152.96,153.15,153.24,153.24,153.14,152.95,152.66,152.28,151.82,151.27,150.63,149.93,149.15,148.3,147.4,146.45,145.44,144.41,143.34,142.24,141.14,140.02,138.91,137.81,136.73,135.67,134.64,133.66,132.73,131.85,131.03,130.28,129.6,129.0,128.49,128.06,127.72,127.47,127.31,127.25,127.29,127.42,127.64,127.96,128.37,128.86,129.44,130.1,130.83,131.63,132.5,133.42,134.39,135.41,136.46,137.53,138.63,139.74,140.86,141.97,143.06,144.14,145.19,146.2,147.16,148.08,148.94,149.74,150.46,151.11,151.69,152.17,152.57,152.88,153.1,153.22,153.25,153.18,153.02,152.76,152.41,151.98,151.45,150.85,150.16,149.41,148.58,147.7,146.76,145.77,144.75,143.69,142.6,141.5,140.38,139.27,138.17,137.08,136.01,134.97,133.97,133.02,132.12,131.29,130.51,129.81,129.19,128.64,128.19,127.82,127.54,127.35,127.26,127.27,127.37,127.56,127.85,128.23,128.69,129.25,129.88,136.65,135.77,134.96,134.22,133.55,132.97,132.46,132.04,131.71,131.47,131.33,131.28,131.33,131.47,131.71,132.03,132.45,132.96,133.55,134.21,134.95,135.76,136.63,137.56,138.54,139.56,140.61,141.69,142.79,143.9,145.02,146.13,147.22,148.29,149.34,150.34,151.31,152.22,153.07,153.86,154.57,155.21,155.78,156.25,156.64,156.94,157.15,157.26,157.28,157.2,157.02,156.75,156.4,155.95,155.41,154.8,154.11,153.34,152.51,151.62,150.67,149.68,148.65,147.59,146.5,145.39,144.28,143.17,142.06,140.98,139.91,138.88,137.89,136.94,136.05,135.22,134.46,133.76,133.15,132.61,132.17,131.81,131.54,131.37,131.29,131.3,131.41,131.62,131.92,132.31,132.78,133.35,133.99,134.71,135.49,136.34,137.26,138.22,139.22,140.27,141.34,142.43,143.54,144.66,145.77,146.87,147.95,149.0,150.02,151.0,151.93,152.8,153.61,154.35,155.02,155.6,156.11,156.53,156.86,157.09,157.23,157.28,157.23,157.09,156.85,156.52,156.1,155.6,155.01,154.34,153.6,152.79,151.91,150.99,150.01,148.99,147.93,146.85,145.75,144.64,143.53,142.42,141.33,140.25,139.21,138.2,137.24,136.33,135.48,134.7,133.98,133.34,132.78,132.3,131.91,131.62,131.41,131.3,131.29,131.37,131.54,131.81,132.17,132.62,133.15,133.77,134.46,135.23,136.06,136.95,137.9,138.89,139.93,140.99,142.08,143.18,144.3,145.41,146.51,147.6,148.66,149.69,150.69,151.63,152.52,153.35,154.12,154.81,155.42,155.95,156.4,156.76,157.02,157.2,157.28,157.26,157.15,156.94,156.64,156.25,155.77,155.21,154.56,153.85,153.06,152.2,151.29,150.33,149.32,148.28,147.21,146.11,145.0,143.89,142.78,141.68,140.6,139.55,138.53,137.55,136.62,135.75,134.94,134.2,133.54,132.95,132.45,132.03,131.7,131.47,131.33,131.28,131.33,131.47,131.71,132.04,132.46,132.97,133.56,134.23,140.26,139.41,138.64,137.93,137.3,136.75,136.28,135.9,135.62,135.42,135.32,135.32,135.41,135.6,135.88,136.25,136.71,137.25,137.88,138.58,139.35,140.19,141.09,142.04,143.04,144.08,145.15,146.24,147.34,148.46,149.57,150.67,151.76,152.82,153.84,154.83,155.77,156.65,157.48,158.23,158.91,159.52,160.04,160.48,160.82,161.08,161.24,161.31,161.28,161.15,160.94,160.63,160.22,159.74,159.16,158.51,157.78,156.99,156.13,155.21,154.24,153.23,152.18,151.11,150.01,148.9,147.79,146.68,145.58,144.5,143.45,142.44,141.47,140.54,139.68,138.88,138.15,137.49,136.91,136.42,136.01,135.7,135.47,135.34,135.31,135.37,135.53,135.78,136.12,136.55,137.07,137.67,138.34,139.1,139.91,140.79,141.73,142.71,143.74,144.8,145.88,146.98,148.1,149.21,150.31,151.41,152.48,153.51,154.52,155.47,156.37,157.22,157.99,158.7,159.33,159.88,160.34,160.72,161.01,161.2,161.3,161.3,161.21,161.02,160.74,160.36,159.9,159.36,158.73,158.03,157.25,156.41,155.51,154.56,153.56,152.53,151.46,150.37,149.26,148.15,147.04,145.93,144.85,143.79,142.76,141.78,140.84,139.95,139.13,138.38,137.7,137.09,136.57,136.14,135.79,135.54,135.38,135.31,135.34,135.47,135.69,136.0,136.4,136.89,137.46,138.12,138.84,139.64,140.5,141.42,142.39,143.4,144.45,145.53,146.62,147.73,148.85,149.96,151.05,152.13,153.18,154.2,155.17,156.09,156.95,157.75,158.48,159.13,159.71,160.2,160.61,160.92,161.15,161.28,161.31,161.25,161.09,160.84,160.5,160.06,159.54,158.94,158.26,157.51,156.69,155.81,154.88,153.89,152.87,151.81,150.72,149.62,148.51,147.4,146.29,145.2,144.13,143.09,142.09,141.14,140.23,139.39,138.62,137.91,137.28,136.73,136.27,135.89,135.61,135.42,135.32,135.32,135.42,135.6,135.89,136.26,136.72,137.27,137.9,138.6,143.88,143.07,142.32,141.65,141.06,140.54,140.12,139.78,139.54,139.39,139.34,139.38,139.52,139.75,140.07,140.48,140.98,141.57,142.23,142.96,143.77,144.64,145.56,146.54,147.55,148.61,149.69,150.78,151.89,153.01,154.12,155.21,156.29,157.33,158.34,159.31,160.22,161.08,161.87,162.59,163.24,163.8,164.29,164.68,164.98,165.2,165.31,165.33,165.26,165.09,164.83,164.48,164.03,163.51,162.9,162.21,161.45,160.62,159.73,158.79,157.8,156.77,155.71,154.62,153.52,152.41,151.29,150.19,149.1,148.03,147.0,146.0,145.05,144.16,143.33,142.56,141.86,141.24,140.7,140.25,139.88,139.61,139.43,139.35,139.36,139.46,139.66,139.95,140.34,140.81,141.37,142.0,142.72,143.5,144.35,145.26,146.22,147.22,148.26,149.33,150.43,151.53,152.65,153.76,154.86,155.94,157.0,158.02,159.0,159.93,160.81,161.62,162.36,163.04,163.63,164.14,164.56,164.9,165.14,165.29,165.34,165.3,165.16,164.93,164.6,164.19,163.69,163.1,162.44,161.7,160.9,160.03,159.1,158.13,157.11,156.06,154.98,153.88,152.77,151.65,150.54,149.45,148.37,147.33,146.32,145.36,144.44,143.59,142.8,142.08,141.43,140.87,140.39,139.99,139.69,139.48,139.36,139.34,139.42,139.59,139.85,140.2,140.65,141.18,141.79,142.48,143.24,144.07,144.96,145.9,146.89,147.92,148.98,150.07,151.17,152.29,153.4,154.5,155.59,156.66,157.69,158.69,159.63,160.53,161.36,162.13,162.83,163.44,163.98,164.43,164.8,165.07,165.25,165.33,165.32,165.21,165.01,164.72,164.33,163.86,163.3,162.66,161.95,161.16,160.31,159.41,158.45,157.44,156.4,155.33,154.23,153.13,152.01,150.9,149.8,148.72,147.66,146.64,145.66,144.73,143.86,143.05,142.3,141.63,141.04,140.53,140.11,139.78,139.54,139.39,139.34,139.38,139.52,139.75,140.08,140.49,141.0,141.58,142.25,142.99,147.52,146.74,146.03,145.39,144.83,144.36,143.98,143.69,143.49,143.38,143.37,143.46,143.64,143.92,144.28,144.74,145.28,145.9,146.59,147.36,148.2,149.09,150.04,151.04,152.07,153.14,154.23,155.33,156.45,157.56,158.66,159.75,160.81,161.84,162.83,163.77,164.66,165.49,166.25,166.93,167.54,168.07,168.51,168.86,169.12,169.29,169.36,169.34,169.22,169.01,168.7,168.31,167.83,167.26,166.61,165.89,165.09,164.24,163.32,162.36,161.35,160.3,159.23,158.13,157.02,155.91,154.8,153.7,152.62,151.57,150.55,149.58,148.66,147.79,146.98,146.25,145.59,145.0,144.51,144.09,143.77,143.54,143.41,143.37,143.42,143.57,143.82,144.15,144.58,145.09,145.69,146.36,147.11,147.92,148.8,149.73,150.71,151.73,152.79,153.87,154.97,156.09,157.2,158.31,159.4,160.47,161.51,162.51,163.47,164.38,165.22,166.01,166.72,167.35,167.91,168.38,168.76,169.05,169.25,169.35,169.36,169.27,169.09,168.81,168.45,167.99,167.45,166.83,166.13,165.36,164.52,163.63,162.68,161.68,160.65,159.58,158.49,157.38,156.27,155.16,154.06,152.97,151.91,150.88,149.89,148.95,148.06,147.24,146.48,145.79,145.18,144.66,144.22,143.87,143.61,143.44,143.37,143.39,143.51,143.73,144.03,144.43,144.92,145.48,146.13,146.86,147.65,148.51,149.42,150.39,151.4,152.44,153.52,154.62,155.73,156.84,157.95,159.05,160.13,161.18,162.19,163.17,164.09,164.96,165.76,166.49,167.16,167.74,168.23,168.64,168.97,169.19,169.33,169.37,169.31,169.16,168.91,168.58,168.15,167.64,167.04,166.36,165.62,164.8,163.92,162.99,162.01,160.99,159.93,158.85,157.74,156.63,155.52,154.41,153.32,152.25,151.21,150.21,149.25,148.34,147.5,146.72,146.01,145.37,144.82,144.35,143.97,143.68,143.48,143.38,143.38,143.46,143.65,143.92,144.29,144.75,145.29,145.91,146.61,147.39,151.17,150.42,149.75,149.15,148.63,148.2,147.86,147.61,147.46,147.4,147.43,147.56,147.79,148.11,148.51,149.01,149.59,150.24,150.98,151.78,152.64,153.56,154.54,155.55,156.6,157.68,158.78,159.89,161.0,162.11,163.21,164.28,165.33,166.34,167.31,168.22,169.08,169.88,170.61,171.26,171.83,172.32,172.72,173.03,173.24,173.37,173.39,173.33,173.16,172.91,172.56,172.12,171.6,170.99,170.31,169.55,168.73,167.84,166.9,165.92,164.89,163.83,162.74,161.64,160.53,159.42,158.31,157.22,156.15,155.12,154.12,153.17,152.27,151.43,150.66,149.96,149.33,148.79,148.33,147.96,147.68,147.5,147.41,147.41,147.51,147.7,147.99,148.37,148.84,149.39,150.02,150.73,151.51,152.36,153.26,154.22,155.22,156.26,157.33,158.42,159.53,160.64,161.75,162.85,163.94,164.99,166.02,167.0,167.93,168.81,169.63,170.38,171.05,171.65,172.17,172.6,172.94,173.18,173.34,173.4,173.36,173.23,173.0,172.68,172.27,171.78,171.2,170.54,169.8,169.0,168.14,167.21,166.24,165.23,164.18,163.1,162.0,160.89,159.78,158.67,157.57,156.5,155.45,154.44,153.47,152.55,151.7,150.9,150.18,149.53,148.96,148.47,148.07,147.76,147.55,147.42,147.4,147.47,147.63,147.89,148.24,148.68,149.2,149.81,150.49,151.25,152.07,152.96,153.9,154.89,155.92,156.98,158.06,159.17,160.28,161.39,162.5,163.59,164.65,165.69,166.69,167.64,168.53,169.37,170.14,170.84,171.47,172.01,172.47,172.84,173.11,173.3,173.39,173.38,173.28,173.08,172.79,172.41,171.95,171.39,170.76,170.05,169.27,168.42,167.52,166.56,165.56,164.52,163.45,162.36,161.25,160.14,159.03,157.92,156.84,155.78,154.76,153.78,152.85,151.97,151.15,150.4,149.73,149.13,148.62,148.19,147.85,147.61,147.45,147.4,147.43,147.57,147.8,148.12,148.53,149.02,149.6,150.26,151.0,151.8,154.84,154.12,153.48,152.92,152.45,152.06,151.76,151.56,151.45,151.43,151.51,151.69,151.95,152.31,152.76,153.3,153.91,154.61,155.37,156.21,157.1,158.04,159.04,160.07,161.13,162.22,163.33,164.44,165.55,166.66,167.74,168.81,169.84,170.83,171.77,172.67,173.5,174.26,174.95,175.57,176.1,176.54,176.9,177.17,177.34,177.42,177.4,177.29,177.08,176.78,176.39,175.91,175.35,174.71,173.99,173.2,172.35,171.44,170.48,169.47,168.42,167.35,166.26,165.15,164.03,162.92,161.82,160.74,159.69,158.67,157.69,156.77,155.9,155.09,154.35,153.68,153.09,152.59,152.17,151.85,151.61,151.47,151.42,151.47,151.62,151.86,152.19,152.61,153.12,153.71,154.37,155.12,155.93,156.8,157.73,158.71,159.73,160.78,161.87,162.97,164.08,165.19,166.3,167.39,168.46,169.51,170.51,171.47,172.38,173.23,174.02,174.73,175.37,175.93,176.41,176.8,177.09,177.3,177.4,177.42,177.34,177.16,176.89,176.53,176.08,175.54,174.93,174.23,173.46,172.63,171.74,170.79,169.8,168.77,167.7,166.61,165.51,164.4,163.28,162.18,161.09,160.03,159.0,158.01,157.06,156.17,155.34,154.58,153.89,153.28,152.74,152.3,151.94,151.68,151.51,151.43,151.45,151.56,151.77,152.07,152.46,152.94,153.51,154.15,154.87,155.66,156.51,157.42,158.39,159.39,160.44,161.51,162.61,163.72,164.83,165.94,167.04,168.12,169.17,170.19,171.17,172.09,172.96,173.77,174.51,175.18,175.76,176.26,176.68,177.01,177.24,177.38,177.42,177.37,177.23,176.99,176.66,176.23,175.73,175.13,174.46,173.72,172.91,172.03,171.1,170.13,169.11,168.05,166.97,165.87,164.76,163.64,162.54,161.44,160.37,159.33,158.32,157.36,156.45,155.6,154.82,154.1,153.47,152.91,152.43,152.05,151.75,151.55,151.44,151.43,151.51,151.69,151.96,152.33,152.78,153.31,153.93,154.63,155.4,156.23,158.52,157.84,157.24,156.72,156.28,155.93,155.68,155.52,155.45,155.48,155.61,155.83,156.14,156.54,157.03,157.61,158.26,158.99,159.79,160.65,161.56,162.53,163.55,164.59,165.67,166.77,167.88,168.99,170.1,171.2,172.28,173.32,174.34,175.31,176.23,177.09,177.89,178.62,179.28,179.85,180.35,180.75,181.07,181.29,181.42,181.45,181.39,181.23,180.98,180.64,180.21,179.69,179.09,178.41,177.66,176.84,175.96,175.02,174.04,173.01,171.95,170.87,169.76,168.65,167.54,166.43,165.34,164.27,163.23,162.23,161.28,160.38,159.54,158.76,158.05,157.42,156.88,156.41,156.04,155.75,155.56,155.47,155.46,155.56,155.75,156.03,156.4,156.87,157.41,158.04,158.74,159.52,160.36,161.26,162.21,163.21,164.25,165.32,166.41,167.52,168.63,169.74,170.84,171.93,172.99,174.01,175.0,175.94,176.82,177.64,178.39,179.07,179.68,180.2,180.63,180.98,181.23,181.39,181.45,181.42,181.29,181.07,180.76,180.36,179.87,179.29,178.64,177.91,177.11,176.25,175.33,174.36,173.35,172.3,171.22,170.12,169.01,167.9,166.79,165.69,164.62,163.57,162.55,161.58,160.67,159.8,159.0,158.27,157.62,157.04,156.55,156.15,155.83,155.61,155.49,155.45,155.52,155.68,155.93,156.27,156.71,157.23,157.83,158.51,159.26,160.08,160.96,161.9,162.88,163.91,164.97,166.05,167.16,168.27,169.38,170.49,171.58,172.65,173.69,174.68,175.64,176.54,177.38,178.16,178.86,179.49,180.04,180.5,180.87,181.16,181.35,181.44,181.44,181.35,181.16,180.87,180.5,180.03,179.49,178.86,178.15,177.38,176.53,175.63,174.68,173.68,172.64,171.57,170.48,169.37,168.26,167.15,166.05,164.96,163.9,162.88,161.89,160.96,160.08,159.26,158.5,157.82,157.22,156.7,156.27,155.93,155.68,155.52,155.45,155.49,155.61,155.84,156.15,156.56,157.05,157.62,158.28,159.01,159.81,160.67,162.22,161.58,161.01,160.53,160.14,159.83,159.62,159.51,159.49,159.56,159.73,159.99,160.35,160.79,161.32,161.93,162.62,163.38,164.21,165.1,166.04,167.03,168.06,169.13,170.21,171.32,172.43,173.54,174.65,175.74,176.8,177.84,178.83,179.78,180.67,181.51,182.27,182.97,183.59,184.13,184.58,184.94,185.21,185.39,185.48,185.46,185.36,185.16,184.86,184.48,184.0,183.44,182.81,182.09,181.31,180.46,179.55,178.59,177.59,176.54,175.47,174.38,173.27,172.16,171.05,169.95,168.86,167.81,166.79,165.81,164.88,164.0,163.19,162.45,161.78,161.18,160.68,160.25,159.92,159.68,159.53,159.48,159.53,159.66,159.9,160.22,160.64,161.14,161.73,162.39,163.13,163.94,164.81,165.73,166.71,167.73,168.78,169.86,170.96,172.07,173.18,174.29,175.39,176.46,177.5,178.51,179.48,180.39,181.24,182.03,182.75,183.4,183.96,184.44,184.83,185.13,185.34,185.46,185.48,185.4,185.23,184.97,184.61,184.17,183.63,183.02,182.33,181.57,180.74,179.85,178.91,177.92,176.89,175.82,174.74,173.63,172.52,171.41,170.3,169.21,168.15,167.12,166.12,165.17,164.28,163.45,162.68,161.99,161.37,160.83,160.38,160.02,159.75,159.57,159.49,159.5,159.61,159.81,160.11,160.49,160.97,161.53,162.17,162.88,163.67,164.52,165.43,166.39,167.39,168.43,169.51,170.6,171.71,172.82,173.93,175.03,176.11,177.17,178.19,179.17,180.1,180.97,181.78,182.53,183.2,183.79,184.29,184.72,185.05,185.29,185.43,185.48,185.44,185.3,185.06,184.74,184.32,183.82,183.23,182.56,181.82,181.02,180.15,179.22,178.24,177.22,176.17,175.09,173.99,172.88,171.77,170.66,169.56,168.49,167.45,166.44,165.48,164.56,163.71,162.92,162.2,161.56,161.0,160.52,160.13,159.83,159.62,159.5,159.49,159.56,159.74,160.0,160.36,160.81,161.34,161.95,162.64,163.4,164.23,165.13,165.94,165.33,164.8,164.36,164.01,163.75,163.58,163.51,163.54,163.66,163.87,164.18,164.57,165.06,165.63,166.28,167.0,167.79,168.65,169.57,170.53,171.54,172.59,173.66,174.76,175.87,176.98,178.09,179.19,180.27,181.32,182.34,183.31,184.23,185.1,185.9,186.64,187.3,187.88,188.38,188.79,189.11,189.34,189.47,189.51,189.45,189.3,189.06,188.72,188.29,187.78,187.18,186.51,185.76,184.95,184.07,183.13,182.15,181.13,180.07,178.99,177.89,176.78,175.66,174.56,173.46,172.39,171.35,170.35,169.39,168.49,167.64,166.86,166.15,165.52,164.96,164.5,164.11,163.82,163.63,163.53,163.52,163.61,163.79,164.07,164.44,164.89,165.43,166.06,166.76,167.53,168.37,169.26,170.21,171.21,172.25,173.31,174.4,175.51,176.62,177.73,178.84,179.92,180.98,182.01,183.0,183.94,184.83,185.65,186.41,187.09,187.7,188.23,188.67,189.02,189.27,189.44,189.51,189.48,189.36,189.15,188.84,188.44,187.96,187.39,186.74,186.01,185.22,184.36,183.44,182.48,181.47,180.42,179.34,178.25,177.14,176.02,174.91,173.82,172.74,171.69,170.67,169.7,168.78,167.91,167.11,166.37,165.71,165.13,164.64,164.23,163.91,163.68,163.55,163.51,163.57,163.72,163.97,164.31,164.74,165.25,165.85,166.52,167.27,168.09,168.97,169.9,170.88,171.91,172.96,174.05,175.15,176.26,177.37,178.48,179.57,180.64,181.68,182.68,183.64,184.54,185.39,186.17,186.88,187.51,188.06,188.53,188.91,189.2,189.4,189.5,189.5,189.41,189.23,188.95,188.58,188.12,187.58,186.95,186.25,185.48,184.64,183.75,182.79,181.8,180.76,179.69,178.6,177.5,176.39,175.27,174.17,173.08,172.02,171.0,170.01,169.07,168.18,167.36,166.6,165.92,165.31,164.79,164.35,164.0,163.75,163.58,163.51,163.54,163.66,163.88,164.19,164.59,165.07,165.64,166.3,167.02,167.82,168.67,169.59,169.67,169.1,168.61,168.21,167.91,167.69,167.57,167.54,167.61,167.77,168.03,168.38,168.82,169.35,169.95,170.64,171.39,172.22,173.1,174.04,175.03,176.06,177.12,178.21,179.31,180.42,181.53,182.64,183.73,184.8,185.83,186.83,187.78,188.68,189.51,190.29,190.99,191.61,192.15,192.61,192.98,193.26,193.44,193.53,193.52,193.42,193.23,192.94,192.56,192.09,191.54,190.9,190.19,189.41,188.57,187.66,186.71,185.71,184.67,183.6,182.5,181.4,180.28,179.17,178.07,176.99,175.93,174.91,173.92,172.99,172.11,171.3,170.55,169.87,169.28,168.76,168.33,168.0,167.75,167.6,167.54,167.58,167.71,167.94,168.26,168.67,169.17,169.75,170.41,171.14,171.94,172.81,173.73,174.71,175.72,176.77,177.85,178.95,180.06,181.17,182.28,183.38,184.45,185.5,186.51,187.48,188.39,189.25,190.04,190.77,191.42,191.99,192.47,192.87,193.18,193.39,193.51,193.54,193.47,193.3,193.04,192.69,192.25,191.73,191.12,190.43,189.67,188.85,187.96,187.02,186.03,185.01,183.95,182.86,181.76,180.64,179.53,178.43,177.33,176.27,175.23,174.24,173.29,172.39,171.55,170.78,170.08,169.46,168.92,168.46,168.1,167.82,167.64,167.55,167.56,167.66,167.85,168.15,168.53,169.0,169.55,170.18,170.89,171.68,172.52,173.43,174.38,175.39,176.43,177.5,178.59,179.7,180.81,181.92,183.02,184.11,185.16,186.19,187.17,188.1,188.98,189.79,190.54,191.22,191.81,192.32,192.75,193.09,193.33,193.48,193.54,193.5,193.37,193.14,192.82,192.4,191.91,191.32,190.66,189.93,189.12,188.26,187.33,186.36,185.34,184.29,183.21,182.11,181.0,179.89,178.78,177.69,176.61,175.57,174.56,173.59,172.67,171.82,171.02,170.3,169.65,169.09,168.6,168.2,167.9,167.69,167.57,167.54,167.61,167.78,168.04,168.39,168.83,169.36,169.97,170.66,171.42,172.24,173.13,174.07,173.42,172.89,172.44,172.09,171.82,171.65,171.57,171.59,171.71,171.91,172.21,172.61,173.09,173.65,174.29,175.01,175.8,176.66,177.57,178.53,179.54,180.58,181.66,182.75,183.86,184.97,186.08,187.18,188.26,189.32,190.33,191.31,192.24,193.11,193.92,194.65,195.32,195.91,196.41,196.82,197.15,197.38,197.52,197.57,197.52,197.37,197.13,196.8,196.38,195.87,195.28,194.61,193.87,193.05,192.18,191.25,190.27,189.25,188.19,187.11,186.01,184.9,183.79,182.68,181.59,180.51,179.47,178.47,177.51,176.6,175.75,174.96,174.25,173.61,173.05,172.58,172.19,171.9,171.69,171.59,171.57,171.66,171.84,172.11,172.47,172.92,173.46,174.08,174.77,175.54,176.37,177.27,178.21,179.21,180.24,181.31,182.39,183.5,184.61,185.72,186.83,187.92,188.98,190.01,191.0,191.94,192.83,193.66,194.42,195.11,195.72,196.25,196.7,197.05,197.32,197.49,197.56,197.54,197.43,197.22,196.92,196.52,196.04,195.48,194.83,194.11,193.32,192.47,191.56,190.59,189.58,188.54,187.47,186.37,185.26,184.15,183.04,181.94,180.86,179.81,178.79,177.81,176.89,176.02,175.21,174.47,173.81,173.22,172.72,172.31,171.98,171.75,171.61,171.57,171.62,171.77,172.01,172.34,172.76,173.27,173.87,174.54,175.28,176.09,176.97,177.9,178.88,179.9,180.96,182.04,183.14,184.25,185.36,186.47,187.57,188.64,189.68,190.68,191.64,192.55,193.4,194.18,194.9,195.53,196.09,196.56,196.95,197.24,197.44,197.55,197.56,197.48,197.3,197.03,196.66,196.21,195.67,195.05,194.36,193.59,192.75,191.86,190.91,189.92,188.88,187.82,186.73,185.62,184.51,183.4,182.29,181.21,180.14,179.11,178.12,177.18,176.29,175.47,174.7,174.02,173.4,172.88,172.43,172.08,171.82,171.65,171.57,171.59,171.71,171.92,172.22,172.62,173.1,173.67,174.31,175.03,175.82,176.68,177.59,178.56,177.19,176.7,176.29,175.98,175.76,175.63,175.6,175.66,175.82,176.07,176.42,176.85,177.37,177.97,178.65,179.4,180.22,181.11,182.04,183.03,184.05,185.11,186.2,187.3,188.41,189.52,190.63,191.72,192.79,193.83,194.83,195.78,196.68,197.52,198.3,199.01,199.63,200.18,200.64,201.02,201.3,201.49,201.59,201.59,201.49,201.3,201.02,200.64,200.18,199.63,199.0,198.3,197.52,196.68,195.78,194.82,193.82,192.79,191.72,190.63,189.52,188.41,187.29,186.19,185.11,184.05,183.02,182.04,181.1,180.22,179.4,178.65,177.97,177.37,176.85,176.41,176.07,175.82,175.66,175.6,175.63,175.76,175.98,176.29,176.7,177.19,177.77,178.42,179.15,179.95,180.81,181.73,182.7,183.72,184.77,185.84,186.94,188.05,189.16,190.27,191.37,192.45,193.5,194.51,195.48,196.4,197.26,198.06,198.78,199.44,200.01,200.5,200.91,201.22,201.44,201.56,201.6,201.53,201.37,201.12,200.77,200.34,199.82,199.21,198.53,197.78,196.96,196.08,195.14,194.15,193.13,192.07,190.98,189.88,188.77,187.65,186.55,185.46,184.39,183.35,182.35,181.4,180.5,179.66,178.88,178.18,177.55,177.01,176.55,176.17,175.89,175.7,175.61,175.61,175.71,175.9,176.18,176.56,177.02,177.57,178.2,178.91,179.68,180.53,181.43,182.38,183.38,184.42,185.49,186.58,187.69,188.8,189.91,191.02,192.1,193.16,194.18,195.17,196.1,196.99,197.8,198.56,199.23,199.84,200.35,200.79,201.13,201.38,201.53,201.6,201.56,201.43,201.21,200.89,200.49,200.0,199.42,198.76,198.03,197.23,196.37,195.45,194.48,193.46,192.41,191.34,190.24,189.13,188.02,186.91,185.81,184.73,183.68,182.67,181.7,180.79,179.92,179.13,178.4,177.75,177.17,176.69,176.28,175.97,175.75,175.63,175.6,175.66,175.83,176.08,176.43,176.86,177.38,177.99,178.67,179.43,180.25,181.13,182.07,183.06,180.98,180.52,180.16,179.89,179.71,179.63,179.65,179.75,179.96,180.25,180.64,181.11,181.67,182.31,183.02,183.81,184.66,185.57,186.53,187.53,188.58,189.65,190.74,191.85,192.96,194.08,195.18,196.26,197.31,198.33,199.31,200.24,201.11,201.93,202.67,203.34,203.93,204.44,204.86,205.19,205.43,205.58,205.63,205.58,205.44,205.21,204.88,204.46,203.96,203.37,202.71,201.97,201.16,200.29,199.36,198.39,197.37,196.32,195.24,194.14,193.03,191.91,190.8,189.71,188.63,187.59,186.58,185.62,184.71,183.86,183.07,182.35,181.7,181.14,180.66,180.27,179.97,179.76,179.65,179.63,179.71,179.88,180.15,180.5,180.95,181.48,182.09,182.79,183.55,184.38,185.27,186.21,187.2,188.24,189.3,190.39,191.49,192.6,193.72,194.82,195.91,196.97,198.01,199.0,199.95,200.84,201.67,202.44,203.13,203.75,204.28,204.73,205.09,205.36,205.54,205.62,205.61,205.5,205.29,205.0,204.61,204.13,203.57,202.93,202.22,201.43,200.58,199.67,198.71,197.7,196.66,195.59,194.49,193.39,192.27,191.16,190.06,188.98,187.93,186.91,185.93,185.0,184.13,183.31,182.57,181.9,181.31,180.81,180.39,180.06,179.82,179.67,179.63,179.67,179.81,180.05,180.38,180.79,181.3,181.89,182.55,183.29,184.1,184.97,185.9,186.88,187.9,188.95,190.03,191.13,192.24,193.36,194.46,195.56,196.63,197.68,198.68,199.64,200.55,201.41,202.2,202.91,203.56,204.12,204.6,204.99,205.29,205.49,205.6,205.62,205.54,205.37,205.1,204.74,204.3,203.76,203.15,202.46,201.69,200.86,199.97,199.03,198.03,197.0,195.94,194.85,193.75,192.63,191.52,190.42,189.33,188.26,187.23,186.24,185.29,184.4,183.57,182.81,182.11,181.5,180.96,180.51,180.15,179.89,179.71,179.63,179.65,179.76,179.96,180.26,180.65,181.13,181.69,182.33,183.05,183.83,184.68,185.59,186.56,187.56,184.78,184.37,184.05,183.83,183.69,183.66,183.71,183.87,184.11,184.45,184.88,185.39,185.99,186.67,187.41,188.23,189.11,190.04,191.03,192.05,193.11,194.19,195.29,196.4,197.52,198.62,199.72,200.79,201.83,202.83,203.78,204.69,205.53,206.31,207.02,207.66,208.21,208.68,209.06,209.34,209.54,209.64,209.65,209.56,209.37,209.09,208.72,208.27,207.72,207.1,206.4,205.63,204.79,203.89,202.94,201.94,200.91,199.84,198.75,197.64,196.53,195.42,194.32,193.23,192.17,191.14,190.15,189.21,188.33,187.5,186.75,186.06,185.46,184.93,184.5,184.15,183.89,183.73,183.66,183.68,183.81,184.02,184.33,184.73,185.22,185.79,186.44,187.16,187.96,188.82,189.73,190.7,191.71,192.76,193.84,194.93,196.04,197.16,198.27,199.36,200.44,201.49,202.51,203.48,204.4,205.27,206.07,206.8,207.46,208.04,208.53,208.94,209.26,209.49,209.62,209.65,209.6,209.44,209.19,208.85,208.42,207.91,207.31,206.63,205.88,205.07,204.19,203.25,202.27,201.25,200.19,199.1,198.0,196.89,195.78,194.67,193.58,192.51,191.47,190.47,189.51,188.61,187.76,186.99,186.28,185.65,185.09,184.63,184.25,183.96,183.77,183.67,183.66,183.76,183.94,184.22,184.59,185.05,185.59,186.22,186.92,187.69,188.53,189.43,190.38,191.38,192.42,193.48,194.58,195.68,196.79,197.91,199.01,200.09,201.15,202.18,203.17,204.11,204.99,205.82,206.57,207.25,207.86,208.38,208.82,209.17,209.42,209.59,209.65,209.62,209.5,209.28,208.97,208.57,208.09,207.51,206.86,206.13,205.34,204.48,203.56,202.59,201.58,200.53,199.46,198.36,197.25,196.14,195.03,193.93,192.85,191.8,190.79,189.82,188.9,188.03,187.23,186.5,185.84,185.26,184.77,184.36,184.05,183.82,183.69,183.66,183.72,183.87,184.12,184.46,184.89,185.41,186.01,186.69,187.44,188.25,189.13,190.07,191.05,192.08,188.61,188.24,187.96,187.78,187.69,187.7,187.8,188.0,188.29,188.67,189.14,189.69,190.33,191.04,191.82,192.67,193.57,194.53,195.53,196.57,197.64,198.73,199.84,200.96,202.07,203.17,204.25,205.31,206.33,207.31,208.24,209.12,209.94,210.68,211.36,211.95,212.47,212.89,213.23,213.48,213.63,213.68,213.64,213.51,213.28,212.96,212.55,212.05,211.47,210.81,210.07,209.27,208.4,207.48,206.5,205.49,204.44,203.36,202.26,201.15,200.04,198.93,197.83,196.76,195.71,194.7,193.73,192.82,191.96,191.17,190.45,189.8,189.23,188.75,188.35,188.04,187.83,187.71,187.69,187.76,187.92,188.18,188.54,188.98,189.5,190.11,190.8,191.56,192.38,193.27,194.21,195.2,196.23,197.29,198.38,199.48,200.59,201.71,202.81,203.9,204.97,206.0,207.0,207.95,208.84,209.68,210.45,211.15,211.77,212.31,212.77,213.13,213.41,213.59,213.68,213.67,213.56,213.36,213.07,212.69,212.22,211.67,211.03,210.32,209.54,208.69,207.78,206.83,205.82,204.78,203.71,202.62,201.51,200.4,199.29,198.18,197.1,196.05,195.02,194.04,193.11,192.23,191.42,190.67,190.0,189.4,188.89,188.47,188.13,187.89,187.74,187.68,187.72,187.86,188.09,188.41,188.82,189.32,189.91,190.57,191.3,192.11,192.98,193.9,194.88,195.89,196.94,198.02,199.12,200.23,201.35,202.46,203.55,204.63,205.67,206.68,207.65,208.56,209.42,210.21,210.93,211.58,212.14,212.63,213.02,213.33,213.54,213.66,213.68,213.61,213.44,213.18,212.83,212.38,211.86,211.25,210.56,209.8,208.97,208.08,207.14,206.15,205.12,204.06,202.97,201.87,200.76,199.65,198.54,197.45,196.38,195.35,194.36,193.41,192.51,191.68,190.91,190.21,189.59,189.05,188.6,188.23,187.96,187.78,187.69,187.7,187.81,188.01,188.3,188.68,189.15,189.71,190.35,191.06,191.84,192.69,193.6,194.55,195.56,196.6,192.45,192.13,191.89,191.76,191.71,191.76,191.91,192.15,192.49,192.91,193.42,194.01,194.68,195.43,196.24,197.11,198.04,199.02,200.04,201.1,202.18,203.28,204.39,205.51,206.61,207.71,208.78,209.82,210.83,211.79,212.69,213.54,214.33,215.04,215.68,216.24,216.71,217.09,217.39,217.59,217.69,217.71,217.62,217.44,217.17,216.81,216.35,215.82,215.2,214.5,213.73,212.9,212.0,211.06,210.06,209.03,207.96,206.87,205.77,204.65,203.54,202.44,201.35,200.29,199.26,198.27,197.33,196.44,195.61,194.85,194.16,193.55,193.02,192.58,192.22,191.96,191.79,191.72,191.74,191.85,192.06,192.37,192.76,193.24,193.81,194.46,195.18,195.97,196.82,197.74,198.7,199.71,200.75,201.83,202.92,204.03,205.15,206.26,207.36,208.44,209.49,210.51,211.48,212.41,213.27,214.08,214.82,215.48,216.06,216.56,216.98,217.3,217.53,217.67,217.71,217.66,217.51,217.27,216.93,216.51,216.0,215.41,214.73,213.99,213.17,212.3,211.37,210.39,209.37,208.31,207.23,206.13,205.02,203.9,202.79,201.7,200.63,199.59,198.58,197.63,196.72,195.87,195.09,194.38,193.74,193.18,192.71,192.33,192.03,191.83,191.73,191.72,191.81,191.99,192.26,192.62,193.08,193.62,194.24,194.93,195.7,196.54,197.43,198.38,199.38,200.41,201.48,202.57,203.67,204.79,205.9,207.0,208.09,209.15,210.18,211.17,212.11,213.0,213.83,214.59,215.27,215.88,216.41,216.85,217.21,217.47,217.64,217.71,217.69,217.57,217.36,217.05,216.66,216.17,215.61,214.96,214.24,213.45,212.59,211.68,210.71,209.7,208.66,207.58,206.49,205.38,204.26,203.15,202.05,200.97,199.92,198.91,197.93,197.01,196.14,195.33,194.6,193.94,193.35,192.85,192.44,192.12,191.89,191.75,191.71,191.77,191.92,192.16,192.5,192.92,193.43,194.03,194.7,195.45,196.26,197.14,198.07,199.05,200.07,201.13,196.32,196.03,195.85,195.75,195.75,195.85,196.04,196.33,196.7,197.17,197.71,198.34,199.05,199.83,200.67,201.57,202.53,203.53,204.57,205.63,206.73,207.83,208.95,210.06,211.16,212.24,213.3,214.33,215.31,216.25,217.13,217.95,218.7,219.38,219.98,220.5,220.93,221.27,221.52,221.68,221.74,221.71,221.58,221.35,221.04,220.63,220.14,219.56,218.91,218.18,217.38,216.51,215.59,214.62,213.61,212.56,211.48,210.38,209.27,208.16,207.05,205.95,204.88,203.83,202.82,201.85,200.93,200.07,199.27,198.54,197.89,197.32,196.83,196.43,196.12,195.9,195.77,195.74,195.81,195.97,196.22,196.57,197.01,197.53,198.13,198.81,199.57,200.39,201.27,202.21,203.2,204.23,205.29,206.37,207.47,208.58,209.7,210.8,211.9,212.96,214.0,215.0,215.95,216.85,217.69,218.46,219.17,219.79,220.34,220.8,221.17,221.45,221.64,221.73,221.73,221.63,221.44,221.15,220.77,220.31,219.76,219.13,218.42,217.64,216.8,215.9,214.94,213.94,212.9,211.83,210.74,209.63,208.52,207.41,206.31,205.22,204.16,203.14,202.16,201.22,200.34,199.52,198.77,198.09,197.5,196.98,196.55,196.21,195.96,195.8,195.74,195.78,195.91,196.13,196.45,196.86,197.35,197.93,198.58,199.32,200.12,200.98,201.9,202.87,203.89,204.94,206.02,207.11,208.22,209.34,210.45,211.54,212.62,213.67,214.68,215.65,216.56,217.42,218.22,218.95,219.6,220.17,220.66,221.06,221.37,221.59,221.71,221.74,221.67,221.51,221.25,220.91,220.47,219.95,219.34,218.66,217.9,217.08,216.2,215.26,214.27,213.24,212.18,211.1,209.99,208.88,207.77,206.66,205.57,204.5,203.47,202.47,201.52,200.62,199.78,199.01,198.31,197.68,197.14,196.68,196.31,196.03,195.84,195.75,195.76,195.85,196.05,196.34,196.71,197.18,197.73,198.36,199.07,199.85,200.69,201.6,202.55,203.56,204.59,205.66,200.2,199.96,199.82,199.77,199.82,199.96,200.19,200.52,200.94,201.44,202.03,202.7,203.44,204.25,205.12,206.04,207.02,208.04,209.09,210.17,211.27,212.38,213.5,214.61,215.7,216.77,217.82,218.83,219.79,220.7,221.55,222.34,223.06,223.7,224.26,224.74,225.13,225.43,225.64,225.75,225.76,225.69,225.51,225.25,224.89,224.44,223.91,223.29,222.6,221.84,221.01,220.12,219.17,218.18,217.15,216.08,215.0,213.89,212.78,211.67,210.56,209.47,208.41,207.38,206.38,205.44,204.55,203.71,202.95,202.26,201.64,201.11,200.66,200.3,200.03,199.86,199.78,199.79,199.9,200.11,200.4,200.79,201.27,201.83,202.47,203.19,203.98,204.83,205.74,206.7,207.71,208.75,209.82,210.92,212.02,213.14,214.25,215.35,216.43,217.48,218.5,219.48,220.41,221.28,222.09,222.83,223.5,224.09,224.59,225.01,225.34,225.58,225.72,225.77,225.72,225.58,225.34,225.01,224.6,224.09,223.5,222.83,222.09,221.28,220.41,219.48,218.51,217.49,216.43,215.35,214.25,213.14,212.03,210.92,209.82,208.75,207.71,206.7,205.74,204.83,203.98,203.19,202.47,201.83,201.27,200.79,200.4,200.11,199.9,199.79,199.78,199.85,200.03,200.3,200.66,201.11,201.64,202.26,202.95,203.71,204.54,205.44,206.38,207.37,208.41,209.47,210.56,211.66,212.78,213.89,214.99,216.08,217.15,218.18,219.17,220.11,221.0,221.84,222.6,223.29,223.91,224.44,224.89,225.25,225.51,225.69,225.76,225.75,225.64,225.43,225.13,224.74,224.26,223.7,223.06,222.34,221.55,220.7,219.79,218.83,217.82,216.78,215.7,214.61,213.5,212.39,211.28,210.18,209.1,208.04,207.02,206.05,205.12,204.25,203.44,202.7,202.03,201.44,200.94,200.52,200.19,199.96,199.82,199.77,199.82,199.96,200.2,200.53,200.95,201.46,202.05,202.72,203.46,204.27,205.14,206.07,207.05,208.07,209.12,210.2,204.11,203.91,203.81,203.81,203.9,204.09,204.36,204.73,205.19,205.74,206.36,207.06,207.84,208.68,209.57,210.53,211.52,212.56,213.63,214.72,215.82,216.94,218.05,219.15,220.24,221.3,222.33,223.31,224.25,225.14,225.96,226.71,227.4,228.0,228.53,228.96,229.31,229.57,229.73,229.8,229.77,229.65,229.43,229.12,228.72,228.23,227.66,227.01,226.28,225.48,224.62,223.71,222.74,221.73,220.68,219.6,218.51,217.4,216.28,215.17,214.08,213.0,211.95,210.93,209.96,209.04,208.18,207.38,206.64,205.99,205.41,204.91,204.51,204.19,203.96,203.83,203.8,203.86,204.01,204.26,204.6,205.04,205.55,206.15,206.83,207.58,208.4,209.28,210.21,211.2,212.22,213.28,214.36,215.46,216.58,217.69,218.8,219.89,220.96,222.0,223.0,223.95,224.86,225.7,226.48,227.18,227.82,228.37,228.83,229.21,229.49,229.69,229.79,229.79,229.7,229.51,229.23,228.86,228.4,227.85,227.23,226.52,225.75,224.91,224.01,223.06,222.06,221.02,219.95,218.86,217.76,216.64,215.53,214.43,213.34,212.28,211.26,210.27,209.33,208.45,207.63,206.87,206.19,205.59,205.06,204.63,204.28,204.03,203.87,203.8,203.83,203.95,204.17,204.48,204.89,205.38,205.95,206.6,207.33,208.13,208.99,209.9,210.87,211.88,212.93,214.01,215.11,216.21,217.33,218.44,219.54,220.61,221.66,222.68,223.65,224.57,225.43,226.23,226.96,227.62,228.2,228.69,229.1,229.41,229.63,229.76,229.8,229.74,229.58,229.33,228.99,228.56,228.04,227.44,226.76,226.01,225.19,224.31,223.37,222.39,221.36,220.3,219.22,218.12,217.01,215.89,214.79,213.69,212.63,211.59,210.59,209.63,208.73,207.89,207.11,206.4,205.77,205.22,204.76,204.38,204.1,203.91,203.81,203.81,203.9,204.09,204.37,204.75,205.21,205.75,206.38,207.08,207.86,208.7,209.6,210.55,211.55,212.59,213.66,214.75,208.03,207.88,207.83,207.87,208.0,208.23,208.56,208.97,209.47,210.05,210.71,211.45,212.25,213.12,214.04,215.02,216.04,217.09,218.17,219.27,220.38,221.49,222.6,223.69,224.77,225.81,226.82,227.79,228.7,229.56,230.35,231.07,231.72,232.29,232.77,233.17,233.47,233.68,233.8,233.82,233.75,233.58,233.32,232.97,232.53,232.0,231.39,230.7,229.94,229.12,228.23,227.29,226.3,225.27,224.21,223.12,222.01,220.9,219.79,218.68,217.59,216.53,215.49,214.5,213.55,212.66,211.82,211.05,210.35,209.73,209.19,208.74,208.37,208.1,207.92,207.83,207.84,207.95,208.15,208.44,208.82,209.3,209.85,210.49,211.2,211.98,212.83,213.74,214.7,215.7,216.74,217.81,218.91,220.02,221.13,222.24,223.34,224.42,225.48,226.5,227.48,228.41,229.29,230.1,230.85,231.52,232.11,232.62,233.05,233.38,233.63,233.77,233.83,233.79,233.65,233.42,233.09,232.68,232.18,231.6,230.93,230.2,229.39,228.52,227.6,226.62,225.6,224.55,223.47,222.37,221.26,220.15,219.04,217.95,216.87,215.83,214.82,213.85,212.94,212.08,211.29,210.57,209.93,209.36,208.88,208.48,208.18,207.97,207.85,207.83,207.91,208.07,208.34,208.69,209.13,209.66,210.27,210.96,211.72,212.55,213.44,214.38,215.37,216.4,217.46,218.55,219.65,220.77,221.88,222.99,224.07,225.14,226.17,227.17,228.12,229.01,229.85,230.61,231.31,231.93,232.47,232.92,233.28,233.56,233.74,233.82,233.81,233.7,233.5,233.21,232.82,232.35,231.79,231.16,230.44,229.66,228.81,227.9,226.94,225.94,224.9,223.83,222.73,221.62,220.51,219.4,218.3,217.22,216.16,215.14,214.16,213.23,212.35,211.54,210.8,210.13,209.53,209.02,208.6,208.27,208.03,207.88,207.83,207.87,208.01,208.24,208.57,208.98,209.48,210.07,210.73,211.47,212.28,213.14,214.07,215.05,216.06,217.12,218.2,219.3,211.98,211.87,211.86,211.95,212.13,212.4,212.77,213.22,213.76,214.38,215.08,215.85,216.68,217.58,218.53,219.52,220.56,221.62,222.71,223.82,224.93,226.04,227.14,228.23,229.29,230.32,231.31,232.25,233.14,233.97,234.73,235.42,236.03,236.55,237.0,237.35,237.61,237.78,237.85,237.83,237.71,237.5,237.2,236.8,236.32,235.75,235.1,234.38,233.59,232.73,231.82,230.86,229.85,228.8,227.73,226.63,225.52,224.41,223.3,222.2,221.12,220.07,219.05,218.08,217.15,216.28,215.48,214.74,214.08,213.5,213.0,212.59,212.26,212.03,211.9,211.86,211.91,212.06,212.3,212.64,213.06,213.58,214.17,214.84,215.59,216.4,217.28,218.21,219.19,220.22,221.27,222.35,223.46,224.57,225.68,226.79,227.88,228.95,229.99,231.0,231.95,232.86,233.71,234.49,235.2,235.84,236.39,236.86,237.25,237.54,237.74,237.84,237.85,237.76,237.58,237.31,236.94,236.48,235.94,235.32,234.62,233.85,233.02,232.12,231.17,230.18,229.14,228.08,226.99,225.88,224.77,223.66,222.55,221.47,220.4,219.38,218.39,217.45,216.56,215.73,214.97,214.29,213.68,213.15,212.71,212.36,212.1,211.93,211.86,211.88,212.0,212.21,212.52,212.92,213.4,213.97,214.62,215.34,216.13,216.99,217.9,218.87,219.88,220.93,222.0,223.1,224.21,225.32,226.43,227.53,228.61,229.66,230.68,231.65,232.57,233.44,234.24,234.98,235.64,236.22,236.72,237.13,237.45,237.68,237.82,237.86,237.8,237.65,237.4,237.07,236.64,236.13,235.53,234.86,234.11,233.3,232.42,231.49,230.51,229.48,228.43,227.34,226.24,225.13,224.02,222.91,221.82,220.75,219.71,218.7,217.75,216.84,215.99,215.21,214.5,213.87,213.31,212.84,212.46,212.17,211.97,211.87,211.86,211.95,212.14,212.41,212.78,213.23,213.78,214.4,215.1,215.87,216.71,217.6,218.55,219.55,220.58,221.65,222.74,223.85,215.95,215.89,215.92,216.05,216.27,216.59,217.0,217.49,218.07,218.73,219.46,220.26,221.12,222.05,223.02,224.03,225.08,226.16,227.26,228.37,229.48,230.59,231.69,232.76,233.81,234.82,235.79,236.71,237.57,238.36,239.09,239.74,240.31,240.8,241.2,241.51,241.73,241.85,241.88,241.82,241.65,241.4,241.05,240.61,240.09,239.49,238.8,238.05,237.22,236.34,235.4,234.41,233.39,232.33,231.24,230.14,229.03,227.91,226.81,225.72,224.65,223.61,222.62,221.66,220.77,219.93,219.15,218.45,217.83,217.28,216.82,216.45,216.17,215.99,215.89,215.9,216.0,216.19,216.48,216.86,217.32,217.87,218.51,219.21,219.99,220.84,221.74,222.7,223.7,224.74,225.81,226.9,228.01,229.12,230.23,231.33,232.42,233.47,234.5,235.48,236.42,237.3,238.11,238.86,239.54,240.14,240.65,241.08,241.42,241.67,241.83,241.88,241.85,241.72,241.49,241.17,240.76,240.27,239.69,239.03,238.3,237.5,236.63,235.71,234.74,233.72,232.67,231.6,230.5,229.39,228.27,227.16,226.07,224.99,223.95,222.93,221.97,221.05,220.19,219.4,218.67,218.02,217.45,216.96,216.56,216.25,216.04,215.91,215.89,215.96,216.12,216.38,216.72,217.16,217.69,218.29,218.98,219.73,220.56,221.44,222.38,223.37,224.4,225.46,226.54,227.65,228.76,229.87,230.98,232.07,233.13,234.17,235.17,236.12,237.02,237.85,238.63,239.33,239.95,240.5,240.95,241.32,241.6,241.79,241.88,241.87,241.77,241.57,241.29,240.91,240.44,239.89,239.25,238.55,237.77,236.92,236.02,235.06,234.06,233.02,231.95,230.86,229.75,228.64,227.52,226.42,225.34,224.28,223.26,222.28,221.34,220.46,219.65,218.9,218.22,217.62,217.11,216.68,216.34,216.1,215.94,215.89,215.92,216.06,216.28,216.6,217.01,217.51,218.09,218.75,219.48,220.28,221.15,222.07,223.04,224.06,225.11,226.19,227.29,228.4,219.93,219.92,220.0,220.17,220.44,220.8,221.25,221.78,222.4,223.09,223.86,224.69,225.58,226.53,227.52,228.55,229.61,230.7,231.81,232.92,234.03,235.14,236.22,237.29,238.32,239.31,240.26,241.15,241.98,242.74,243.44,244.05,244.58,245.03,245.39,245.66,245.83,245.91,245.89,245.78,245.57,245.27,244.88,244.41,243.85,243.2,242.48,241.7,240.84,239.93,238.97,237.96,236.92,235.85,234.75,233.65,232.53,231.42,230.32,229.24,228.19,227.17,226.19,225.26,224.39,223.58,222.84,222.18,221.59,221.08,220.67,220.34,220.1,219.96,219.91,219.96,220.11,220.34,220.67,221.09,221.6,222.19,222.86,223.6,224.41,225.28,226.21,227.19,228.21,229.27,230.35,231.45,232.56,233.67,234.78,235.87,236.95,237.99,238.99,239.96,240.87,241.72,242.5,243.22,243.86,244.42,244.9,245.28,245.58,245.78,245.89,245.91,245.83,245.65,245.38,245.02,244.57,244.04,243.42,242.73,241.96,241.13,240.24,239.29,238.3,237.26,236.2,235.11,234.01,232.89,231.78,230.68,229.59,228.52,227.49,226.5,225.56,224.67,223.84,223.07,222.38,221.77,221.24,220.79,220.43,220.17,220.0,219.92,219.94,220.05,220.26,220.56,220.95,221.43,221.99,222.63,223.35,224.14,224.99,225.91,226.87,227.88,228.92,229.99,231.09,232.2,233.31,234.42,235.52,236.6,237.65,238.67,239.65,240.58,241.45,242.26,242.99,243.66,244.25,244.75,245.17,245.49,245.73,245.87,245.91,245.86,245.72,245.48,245.15,244.73,244.22,243.63,242.96,242.22,241.4,240.53,239.6,238.62,237.6,236.55,235.47,234.37,233.25,232.14,231.03,229.94,228.87,227.82,226.82,225.86,224.95,224.1,223.31,222.6,221.96,221.4,220.93,220.54,220.24,220.04,219.93,219.92,220.0,220.18,220.45,220.81,221.26,221.8,222.42,223.11,223.88,224.71,225.6,226.55,227.55,228.58,229.64,230.73,231.84,232.95,223.94,223.97,224.1,224.32,224.63,225.03,225.52,226.09,226.74,227.47,228.27,229.13,230.05,231.02,232.03,233.08,234.15,235.25,236.36,237.47,238.58,239.68,240.76,241.81,242.82,243.79,244.71,245.58,246.38,247.11,247.76,248.34,248.83,249.24,249.56,249.78,249.91,249.94,249.88,249.72,249.47,249.13,248.7,248.18,247.58,246.9,246.15,245.33,244.45,243.52,242.53,241.51,240.45,239.36,238.26,237.15,236.04,234.93,233.84,232.77,231.73,230.73,229.78,228.87,228.03,227.25,226.55,225.92,225.37,224.9,224.53,224.24,224.05,223.96,223.95,224.05,224.24,224.52,224.89,225.35,225.9,226.52,227.23,228.0,228.84,229.74,230.7,231.69,232.73,233.8,234.89,236.0,237.11,238.22,239.33,240.41,241.47,242.5,243.48,244.42,245.3,246.12,246.88,247.56,248.16,248.68,249.12,249.46,249.72,249.88,249.94,249.91,249.78,249.56,249.25,248.85,248.36,247.78,247.13,246.4,245.61,244.74,243.83,242.86,241.84,240.8,239.72,238.62,237.51,236.4,235.29,234.19,233.11,232.06,231.05,230.08,229.16,228.3,227.5,226.77,226.11,225.54,225.05,224.64,224.33,224.1,223.98,223.94,224.01,224.16,224.42,224.76,225.19,225.71,226.31,226.99,227.74,228.56,229.45,230.38,231.37,232.39,233.45,234.54,235.64,236.75,237.86,238.97,240.06,241.13,242.17,243.17,244.12,245.02,245.86,246.64,247.35,247.97,248.52,248.99,249.36,249.64,249.83,249.93,249.93,249.84,249.65,249.36,248.99,248.53,247.98,247.35,246.65,245.87,245.03,244.13,243.18,242.18,241.14,240.07,238.98,237.87,236.76,235.65,234.54,233.46,232.4,231.38,230.39,229.45,228.57,227.75,227.0,226.32,225.72,225.2,224.76,224.42,224.17,224.01,223.94,223.98,224.1,224.32,224.64,225.04,225.53,226.11,226.76,227.49,228.29,229.15,230.07,231.04,232.06,233.1,234.18,235.28,236.39,237.5,227.97,228.05,228.22,228.48,228.83,229.28,229.81,230.42,231.11,231.87,232.69,233.58,234.53,235.51,236.54,237.61,238.69,239.8,240.91,242.02,243.13,244.22,245.28,246.32,247.31,248.26,249.15,249.99,250.76,251.45,252.07,252.61,253.06,253.43,253.7,253.88,253.96,253.95,253.85,253.65,253.35,252.97,252.5,251.94,251.3,250.59,249.8,248.95,248.05,247.09,246.08,245.04,243.97,242.88,241.77,240.66,239.54,238.44,237.36,236.31,235.28,234.31,233.37,232.5,231.69,230.94,230.27,229.68,229.17,228.75,228.41,228.17,228.02,227.97,228.01,228.15,228.38,228.71,229.12,229.63,230.21,230.87,231.61,232.42,233.29,234.21,235.19,236.21,237.26,238.34,239.44,240.55,241.66,242.77,243.87,244.94,245.99,246.99,247.96,248.87,249.72,250.52,251.24,251.88,252.45,252.93,253.32,253.62,253.83,253.95,253.97,253.89,253.72,253.46,253.1,252.66,252.13,251.52,250.83,250.06,249.24,248.35,247.4,246.41,245.38,244.32,243.23,242.13,241.02,239.9,238.8,237.71,236.65,235.61,234.62,233.67,232.78,231.94,231.18,230.48,229.86,229.32,228.87,228.51,228.24,228.06,227.98,227.99,228.1,228.3,228.59,228.98,229.45,230.01,230.65,231.37,232.15,233.0,233.91,234.87,235.87,236.91,237.99,239.08,240.19,241.3,242.41,243.51,244.6,245.65,246.67,247.65,248.58,249.45,250.27,251.01,251.68,252.27,252.78,253.2,253.53,253.77,253.92,253.97,253.93,253.79,253.55,253.23,252.81,252.31,251.72,251.06,250.32,249.51,248.64,247.72,246.74,245.72,244.67,243.59,242.49,241.38,240.26,239.16,238.06,236.99,235.94,234.94,233.97,233.06,232.21,231.42,230.7,230.05,229.49,229.01,228.62,228.32,228.11,227.99,227.98,228.05,228.22,228.49,228.85,229.29,229.82,230.44,231.13,231.89,232.72,233.61,234.55,235.54,236.57,237.64,238.72,239.83,240.94,242.05,232.03,232.15,232.36,232.66,233.06,233.54,234.11,234.76,235.48,236.28,237.13,238.05,239.01,240.02,241.07,242.14,243.24,244.35,245.46,246.57,247.67,248.75,249.8,250.82,251.79,252.72,253.58,254.39,255.12,255.78,256.37,256.86,257.28,257.6,257.83,257.96,258.0,257.94,257.79,257.55,257.21,256.79,256.27,255.68,255.0,254.26,253.44,252.56,251.63,250.65,249.63,248.57,247.49,246.39,245.27,244.16,243.05,241.96,240.89,239.85,238.85,237.89,236.98,236.14,235.36,234.65,234.01,233.46,232.99,232.61,232.32,232.12,232.02,232.01,232.1,232.28,232.56,232.92,233.38,233.92,234.54,235.24,236.01,236.85,237.75,238.7,239.69,240.73,241.79,242.88,243.99,245.1,246.21,247.32,248.4,249.46,250.49,251.48,252.42,253.31,254.13,254.89,255.58,256.19,256.71,257.15,257.5,257.76,257.93,258.0,257.97,257.85,257.64,257.33,256.93,256.45,255.88,255.23,254.51,253.71,252.85,251.94,250.97,249.96,248.92,247.84,246.74,245.64,244.52,243.41,242.31,241.23,240.18,239.17,238.19,237.27,236.41,235.6,234.87,234.21,233.63,233.13,232.72,232.4,232.17,232.04,232.0,232.06,232.21,232.46,232.79,233.22,233.73,234.33,235.01,235.75,236.57,237.45,238.38,239.36,240.39,241.44,242.53,243.63,244.74,245.85,246.96,248.05,249.12,250.16,251.17,252.12,253.03,253.87,254.65,255.36,256.0,256.55,257.02,257.4,257.69,257.88,257.98,257.99,257.9,257.72,257.44,257.07,256.61,256.07,255.45,254.75,253.98,253.14,252.24,251.29,250.29,249.26,248.19,247.1,246.0,244.88,243.77,242.67,241.58,240.52,239.49,238.51,237.57,236.68,235.86,235.1,234.41,233.81,233.28,232.84,232.49,232.24,232.07,232.0,232.03,232.15,232.37,232.67,233.07,233.56,234.13,234.78,235.5,236.3,237.16,238.07,239.04,240.05,241.1,242.17,243.27,244.38,245.49,246.6],"heat":[0.364,0.335,0.314,0.302,0.301,0.311,0.333,0.366,0.409,0.462,0.521,0.586,0.654,0.721,0.786,0.846,0.899,0.942,0.974,0.993,0.999,0.992,0.972,0.94,0.897,0.845,0.787,0.724,0.659,0.595,0.533,0.478,0.429,0.389,0.359,0.339,0.329,0.33,0.34,0.359,0.384,0.413,0.446,0.479,0.51,0.539,0.562,0.58,0.59,0.591,0.585,0.571,0.549,0.52,0.487,0.449,0.41,0.37,0.331,0.296,0.266,0.241,0.224,0.215,0.215,0.222,0.238,0.261,0.291,0.325,0.364,0.404,0.445,0.485,0.522,0.555,0.582,0.602,0.615,0.62,0.617,0.606,0.588,0.563,0.532,0.496,0.457,0.416,0.375,0.336,0.298,0.265,0.237,0.215,0.2,0.192,0.192,0.201,0.217,0.24,0.271,0.308,0.35,0.397,0.447,0.499,0.552,0.605,0.657,0.707,0.754,0.798,0.836,0.87,0.898,0.92,0.935,0.945,0.948,0.945,0.936,0.922,0.902,0.877,0.848,0.814,0.777,0.737,0.695,0.652,0.607,0.561,0.516,0.472,0.429,0.388,0.349,0.314,0.282,0.255,0.231,0.213,0.2,0.192,0.19,0.193,0.202,0.216,0.234,0.258,0.285,0.316,0.35,0.386,0.424,0.462,0.5,0.536,0.571,0.603,0.631,0.655,0.674,0.688,0.697,0.699,0.695,0.685,0.669,0.648,0.622,0.591,0.557,0.52,0.48,0.44,0.4,0.361,0.324,0.29,0.259,0.234,0.213,0.199,0.191,0.19,0.195,0.208,0.226,0.251,0.282,0.317,0.357,0.4,0.446,0.493,0.541,0.588,0.633,0.676,0.716,0.751,0.782,0.807,0.827,0.84,0.847,0.848,0.842,0.831,0.814,0.792,0.766,0.737,0.704,0.669,0.633,0.597,0.562,0.528,0.496,0.468,0.443,0.422,0.407,0.397,0.393,0.394,0.401,0.414,0.432,0.455,0.482,0.513,0.546,0.581,0.617,0.653,0.687,0.718,0.36,0.334,0.317,0.309,0.312,0.326,0.352,0.388,0.434,0.489,0.55,0.616,0.683,0.749,0.812,0.869,0.918,0.956,0.983,0.996,0.997,0.984,0.958,0.92,0.873,0.817,0.755,0.69,0.624,0.559,0.499,0.444,0.398,0.361,0.334,0.318,0.313,0.318,0.332,0.353,0.381,0.413,0.447,0.481,0.514,0.542,0.565,0.581,0.589,0.589,0.581,0.565,0.541,0.512,0.478,0.44,0.401,0.363,0.327,0.294,0.267,0.247,0.234,0.23,0.233,0.245,0.265,0.292,0.325,0.362,0.402,0.444,0.485,0.524,0.559,0.589,0.613,0.629,0.638,0.638,0.63,0.614,0.591,0.561,0.526,0.487,0.445,0.402,0.36,0.319,0.281,0.249,0.222,0.201,0.188,0.183,0.186,0.196,0.215,0.241,0.273,0.312,0.355,0.402,0.452,0.503,0.556,0.607,0.657,0.705,0.749,0.789,0.825,0.855,0.88,0.899,0.912,0.919,0.921,0.917,0.907,0.892,0.872,0.848,0.82,0.789,0.754,0.717,0.678,0.637,0.595,0.553,0.511,0.47,0.43,0.392,0.356,0.323,0.293,0.267,0.245,0.228,0.215,0.208,0.206,0.209,0.217,0.231,0.249,0.272,0.299,0.33,0.364,0.4,0.438,0.477,0.516,0.553,0.59,0.623,0.654,0.68,0.701,0.717,0.728,0.733,0.731,0.723,0.709,0.69,0.665,0.635,0.601,0.564,0.524,0.483,0.442,0.401,0.361,0.324,0.29,0.261,0.237,0.218,0.206,0.2,0.201,0.208,0.222,0.242,0.269,0.3,0.336,0.376,0.419,0.463,0.509,0.554,0.599,0.642,0.681,0.718,0.75,0.777,0.799,0.815,0.825,0.829,0.827,0.82,0.807,0.79,0.768,0.742,0.713,0.682,0.649,0.615,0.582,0.55,0.519,0.491,0.466,0.445,0.428,0.416,0.409,0.407,0.411,0.42,0.435,0.454,0.477,0.504,0.535,0.567,0.6,0.634,0.667,0.698,0.358,0.335,0.321,0.317,0.324,0.342,0.371,0.41,0.459,0.516,0.578,0.644,0.711,0.775,0.836,0.889,0.934,0.967,0.988,0.996,0.991,0.972,0.941,0.898,0.846,0.787,0.722,0.655,0.588,0.524,0.465,0.412,0.369,0.335,0.312,0.3,0.299,0.308,0.326,0.351,0.381,0.416,0.452,0.487,0.519,0.547,0.569,0.584,0.59,0.589,0.579,0.561,0.537,0.506,0.472,0.435,0.397,0.36,0.326,0.297,0.274,0.257,0.249,0.249,0.257,0.273,0.297,0.328,0.363,0.403,0.444,0.486,0.527,0.565,0.598,0.625,0.645,0.657,0.661,0.657,0.644,0.623,0.596,0.562,0.523,0.48,0.436,0.391,0.348,0.307,0.27,0.238,0.212,0.194,0.183,0.18,0.185,0.198,0.219,0.247,0.281,0.32,0.363,0.41,0.459,0.509,0.559,0.609,0.656,0.7,0.741,0.777,0.809,0.836,0.857,0.873,0.884,0.889,0.888,0.883,0.873,0.858,0.839,0.817,0.791,0.761,0.73,0.696,0.66,0.623,0.586,0.548,0.51,0.472,0.436,0.401,0.368,0.338,0.31,0.286,0.266,0.249,0.237,0.23,0.228,0.231,0.239,0.252,0.27,0.292,0.319,0.349,0.382,0.418,0.456,0.495,0.535,0.573,0.611,0.646,0.678,0.706,0.729,0.748,0.761,0.767,0.768,0.763,0.751,0.733,0.709,0.681,0.648,0.611,0.571,0.53,0.487,0.444,0.403,0.363,0.327,0.294,0.266,0.243,0.227,0.216,0.212,0.215,0.224,0.24,0.262,0.289,0.321,0.357,0.396,0.438,0.481,0.525,0.568,0.609,0.649,0.685,0.718,0.746,0.77,0.788,0.801,0.808,0.81,0.806,0.797,0.783,0.765,0.743,0.718,0.69,0.661,0.63,0.599,0.569,0.54,0.512,0.488,0.466,0.449,0.435,0.426,0.422,0.423,0.429,0.44,0.455,0.475,0.499,0.526,0.555,0.586,0.618,0.649,0.679,0.356,0.337,0.327,0.326,0.337,0.358,0.391,0.434,0.485,0.543,0.606,0.672,0.737,0.8,0.857,0.907,0.947,0.975,0.991,0.993,0.982,0.958,0.921,0.874,0.818,0.755,0.688,0.62,0.553,0.489,0.431,0.381,0.341,0.311,0.292,0.284,0.287,0.3,0.322,0.351,0.384,0.421,0.458,0.494,0.527,0.554,0.575,0.589,0.594,0.591,0.579,0.56,0.534,0.504,0.469,0.433,0.396,0.361,0.33,0.304,0.284,0.272,0.268,0.272,0.285,0.305,0.333,0.367,0.405,0.446,0.489,0.531,0.57,0.606,0.637,0.661,0.678,0.686,0.685,0.676,0.659,0.633,0.601,0.564,0.521,0.476,0.43,0.384,0.34,0.299,0.263,0.233,0.209,0.192,0.184,0.183,0.191,0.206,0.229,0.258,0.293,0.332,0.375,0.421,0.468,0.516,0.564,0.609,0.653,0.693,0.729,0.762,0.789,0.812,0.83,0.843,0.85,0.853,0.851,0.845,0.835,0.821,0.803,0.782,0.759,0.733,0.705,0.675,0.644,0.611,0.578,0.545,0.511,0.478,0.446,0.415,0.386,0.358,0.333,0.311,0.292,0.277,0.266,0.259,0.257,0.259,0.267,0.279,0.295,0.317,0.342,0.372,0.404,0.44,0.477,0.516,0.555,0.595,0.633,0.669,0.702,0.732,0.757,0.778,0.793,0.802,0.805,0.802,0.792,0.776,0.755,0.727,0.695,0.659,0.62,0.578,0.535,0.491,0.448,0.406,0.367,0.331,0.3,0.273,0.253,0.238,0.23,0.228,0.232,0.244,0.261,0.283,0.311,0.343,0.379,0.418,0.458,0.499,0.54,0.581,0.619,0.655,0.688,0.717,0.741,0.761,0.776,0.786,0.79,0.789,0.784,0.773,0.759,0.741,0.719,0.695,0.669,0.641,0.613,0.585,0.558,0.532,0.508,0.487,0.469,0.455,0.444,0.438,0.437,0.44,0.447,0.46,0.476,0.496,0.519,0.545,0.574,0.603,0.633,0.661,0.357,0.34,0.333,0.337,0.351,0.376,0.412,0.457,0.51,0.57,0.633,0.698,0.762,0.823,0.877,0.922,0.958,0.981,0.991,0.988,0.971,0.941,0.899,0.848,0.788,0.722,0.654,0.584,0.517,0.455,0.399,0.352,0.315,0.289,0.274,0.271,0.279,0.296,0.321,0.353,0.39,0.428,0.467,0.504,0.536,0.563,0.584,0.596,0.599,0.594,0.581,0.561,0.535,0.503,0.469,0.433,0.398,0.366,0.337,0.314,0.298,0.29,0.291,0.299,0.316,0.341,0.372,0.408,0.449,0.491,0.534,0.576,0.615,0.649,0.677,0.698,0.71,0.714,0.709,0.695,0.673,0.644,0.608,0.567,0.522,0.475,0.427,0.381,0.337,0.297,0.262,0.233,0.211,0.197,0.191,0.193,0.203,0.22,0.244,0.274,0.309,0.348,0.39,0.434,0.479,0.524,0.568,0.609,0.648,0.684,0.716,0.743,0.766,0.785,0.799,0.808,0.813,0.814,0.811,0.804,0.794,0.781,0.765,0.747,0.726,0.704,0.68,0.655,0.629,0.602,0.574,0.545,0.517,0.489,0.461,0.434,0.408,0.384,0.362,0.342,0.325,0.311,0.3,0.294,0.291,0.293,0.299,0.31,0.325,0.345,0.369,0.397,0.429,0.463,0.5,0.538,0.577,0.616,0.655,0.692,0.726,0.757,0.785,0.807,0.824,0.836,0.841,0.84,0.832,0.819,0.799,0.773,0.743,0.708,0.669,0.627,0.584,0.539,0.495,0.451,0.41,0.372,0.337,0.308,0.283,0.265,0.252,0.246,0.246,0.253,0.266,0.284,0.308,0.336,0.368,0.403,0.44,0.478,0.517,0.555,0.592,0.627,0.66,0.688,0.713,0.734,0.75,0.762,0.768,0.77,0.768,0.761,0.749,0.735,0.717,0.696,0.674,0.649,0.624,0.599,0.574,0.55,0.527,0.507,0.489,0.474,0.463,0.455,0.452,0.452,0.457,0.466,0.479,0.496,0.516,0.539,0.564,0.59,0.618,0.645,0.358,0.345,0.342,0.349,0.366,0.394,0.433,0.48,0.535,0.595,0.659,0.723,0.785,0.843,0.894,0.935,0.965,0.983,0.988,0.979,0.956,0.921,0.875,0.819,0.756,0.688,0.618,0.549,0.482,0.422,0.368,0.324,0.291,0.269,0.259,0.261,0.273,0.294,0.324,0.359,0.398,0.439,0.479,0.516,0.548,0.575,0.594,0.605,0.607,0.6,0.586,0.564,0.537,0.506,0.472,0.437,0.404,0.373,0.348,0.328,0.316,0.312,0.317,0.33,0.351,0.379,0.413,0.452,0.495,0.538,0.582,0.623,0.66,0.692,0.717,0.734,0.742,0.742,0.733,0.714,0.688,0.655,0.616,0.572,0.525,0.476,0.428,0.381,0.337,0.298,0.265,0.238,0.219,0.208,0.204,0.208,0.22,0.239,0.264,0.294,0.329,0.367,0.408,0.449,0.491,0.532,0.572,0.609,0.642,0.673,0.699,0.722,0.74,0.754,0.764,0.77,0.772,0.771,0.767,0.76,0.75,0.738,0.725,0.71,0.693,0.675,0.656,0.636,0.616,0.594,0.572,0.549,0.526,0.503,0.481,0.458,0.436,0.415,0.396,0.378,0.363,0.349,0.339,0.333,0.329,0.33,0.335,0.345,0.358,0.376,0.398,0.425,0.454,0.487,0.523,0.56,0.599,0.638,0.676,0.713,0.749,0.781,0.81,0.834,0.853,0.867,0.874,0.875,0.87,0.859,0.841,0.818,0.789,0.755,0.717,0.676,0.633,0.588,0.543,0.498,0.455,0.415,0.378,0.345,0.318,0.296,0.279,0.269,0.265,0.268,0.276,0.29,0.31,0.334,0.362,0.393,0.427,0.462,0.498,0.534,0.569,0.603,0.634,0.662,0.687,0.708,0.725,0.738,0.746,0.75,0.75,0.745,0.737,0.726,0.711,0.694,0.675,0.654,0.632,0.609,0.587,0.565,0.544,0.525,0.508,0.493,0.482,0.473,0.468,0.466,0.469,0.475,0.484,0.498,0.514,0.534,0.556,0.58,0.605,0.63,0.361,0.351,0.351,0.361,0.382,0.413,0.454,0.503,0.56,0.62,0.684,0.747,0.807,0.861,0.908,0.945,0.971,0.983,0.982,0.968,0.94,0.9,0.849,0.79,0.724,0.654,0.583,0.514,0.448,0.389,0.339,0.299,0.27,0.253,0.247,0.253,0.27,0.296,0.329,0.367,0.409,0.451,0.493,0.53,0.563,0.588,0.606,0.615,0.616,0.608,0.592,0.57,0.542,0.51,0.477,0.443,0.412,0.384,0.361,0.346,0.337,0.338,0.346,0.363,0.388,0.419,0.456,0.498,0.541,0.586,0.629,0.669,0.704,0.734,0.755,0.769,0.773,0.769,0.755,0.733,0.703,0.666,0.624,0.577,0.529,0.479,0.431,0.384,0.342,0.305,0.273,0.249,0.233,0.224,0.223,0.229,0.243,0.263,0.289,0.319,0.353,0.39,0.428,0.466,0.504,0.541,0.575,0.607,0.635,0.66,0.681,0.698,0.711,0.72,0.726,0.728,0.728,0.725,0.72,0.713,0.705,0.695,0.684,0.673,0.66,0.647,0.634,0.62,0.605,0.589,0.573,0.557,0.54,0.522,0.504,0.486,0.469,0.451,0.434,0.419,0.405,0.392,0.383,0.375,0.371,0.371,0.374,0.382,0.393,0.409,0.429,0.453,0.48,0.511,0.545,0.581,0.619,0.657,0.695,0.733,0.768,0.802,0.832,0.857,0.878,0.894,0.904,0.908,0.905,0.896,0.88,0.859,0.832,0.8,0.764,0.723,0.681,0.636,0.591,0.545,0.501,0.459,0.421,0.386,0.355,0.33,0.31,0.296,0.289,0.287,0.291,0.302,0.317,0.337,0.361,0.388,0.419,0.451,0.484,0.517,0.55,0.581,0.611,0.638,0.662,0.683,0.7,0.714,0.723,0.729,0.73,0.728,0.723,0.714,0.703,0.689,0.673,0.655,0.636,0.617,0.597,0.578,0.559,0.542,0.526,0.512,0.5,0.491,0.484,0.481,0.481,0.485,0.492,0.502,0.516,0.532,0.551,0.572,0.594,0.617,0.365,0.358,0.361,0.375,0.398,0.432,0.476,0.527,0.584,0.645,0.707,0.769,0.826,0.878,0.921,0.953,0.973,0.98,0.974,0.954,0.921,0.876,0.821,0.759,0.69,0.619,0.548,0.479,0.415,0.359,0.312,0.276,0.251,0.239,0.238,0.249,0.27,0.3,0.337,0.379,0.423,0.467,0.509,0.547,0.579,0.603,0.62,0.628,0.627,0.617,0.6,0.576,0.548,0.517,0.484,0.452,0.422,0.397,0.378,0.365,0.361,0.365,0.378,0.398,0.427,0.461,0.501,0.544,0.589,0.633,0.676,0.715,0.748,0.774,0.793,0.802,0.803,0.794,0.777,0.75,0.717,0.677,0.632,0.584,0.534,0.484,0.436,0.391,0.35,0.315,0.286,0.265,0.251,0.245,0.246,0.255,0.27,0.292,0.318,0.348,0.38,0.415,0.45,0.485,0.518,0.55,0.579,0.605,0.627,0.646,0.66,0.672,0.679,0.684,0.686,0.685,0.682,0.678,0.672,0.666,0.659,0.651,0.644,0.636,0.629,0.621,0.613,0.605,0.597,0.588,0.578,0.568,0.557,0.545,0.532,0.519,0.505,0.491,0.477,0.463,0.45,0.439,0.429,0.421,0.416,0.414,0.415,0.42,0.429,0.442,0.46,0.481,0.506,0.534,0.566,0.6,0.636,0.673,0.711,0.748,0.784,0.818,0.849,0.876,0.899,0.917,0.929,0.935,0.935,0.928,0.916,0.897,0.872,0.842,0.807,0.768,0.726,0.682,0.637,0.592,0.547,0.504,0.464,0.427,0.394,0.366,0.344,0.327,0.316,0.31,0.311,0.317,0.329,0.345,0.365,0.389,0.416,0.444,0.474,0.505,0.535,0.564,0.592,0.617,0.64,0.66,0.677,0.691,0.701,0.707,0.71,0.71,0.706,0.7,0.691,0.68,0.667,0.653,0.637,0.621,0.604,0.588,0.572,0.556,0.541,0.528,0.517,0.508,0.501,0.497,0.495,0.497,0.501,0.509,0.519,0.532,0.548,0.566,0.586,0.606,0.37,0.366,0.372,0.389,0.415,0.452,0.497,0.549,0.607,0.668,0.729,0.789,0.844,0.892,0.93,0.958,0.973,0.975,0.963,0.938,0.9,0.851,0.793,0.727,0.657,0.585,0.513,0.446,0.384,0.33,0.287,0.255,0.235,0.227,0.232,0.248,0.274,0.308,0.348,0.393,0.439,0.484,0.527,0.565,0.596,0.62,0.635,0.641,0.639,0.628,0.609,0.585,0.556,0.525,0.493,0.462,0.435,0.412,0.396,0.387,0.386,0.394,0.411,0.435,0.467,0.504,0.546,0.59,0.636,0.68,0.722,0.759,0.79,0.813,0.828,0.834,0.831,0.818,0.796,0.767,0.73,0.687,0.641,0.591,0.541,0.491,0.444,0.4,0.362,0.329,0.304,0.285,0.274,0.271,0.275,0.286,0.303,0.325,0.351,0.38,0.411,0.442,0.474,0.505,0.533,0.559,0.582,0.602,0.618,0.63,0.638,0.644,0.646,0.646,0.643,0.64,0.635,0.629,0.623,0.618,0.613,0.608,0.604,0.601,0.598,0.596,0.595,0.593,0.591,0.589,0.586,0.582,0.577,0.571,0.563,0.554,0.544,0.534,0.522,0.51,0.498,0.487,0.477,0.468,0.462,0.458,0.457,0.459,0.465,0.475,0.489,0.507,0.529,0.555,0.584,0.616,0.65,0.686,0.723,0.76,0.796,0.83,0.862,0.89,0.915,0.934,0.949,0.957,0.96,0.956,0.945,0.929,0.907,0.879,0.846,0.809,0.769,0.726,0.681,0.636,0.591,0.548,0.507,0.468,0.434,0.404,0.379,0.359,0.345,0.337,0.334,0.337,0.345,0.358,0.374,0.395,0.418,0.443,0.47,0.497,0.524,0.551,0.576,0.6,0.621,0.64,0.656,0.669,0.679,0.686,0.689,0.69,0.689,0.684,0.678,0.669,0.659,0.648,0.635,0.622,0.609,0.595,0.581,0.568,0.555,0.544,0.534,0.525,0.518,0.513,0.51,0.51,0.512,0.517,0.525,0.535,0.547,0.562,0.579,0.597,0.376,0.375,0.384,0.404,0.433,0.471,0.518,0.571,0.629,0.69,0.75,0.807,0.859,0.903,0.938,0.961,0.971,0.967,0.95,0.92,0.877,0.824,0.762,0.694,0.623,0.55,0.479,0.413,0.354,0.304,0.264,0.237,0.222,0.219,0.229,0.25,0.28,0.318,0.362,0.409,0.457,0.504,0.547,0.585,0.616,0.638,0.652,0.656,0.652,0.639,0.62,0.595,0.565,0.534,0.503,0.474,0.449,0.429,0.416,0.41,0.413,0.425,0.445,0.473,0.507,0.547,0.59,0.636,0.682,0.726,0.766,0.801,0.829,0.849,0.861,0.863,0.855,0.839,0.814,0.781,0.741,0.697,0.649,0.599,0.548,0.5,0.454,0.412,0.376,0.347,0.324,0.309,0.302,0.301,0.308,0.321,0.339,0.361,0.387,0.415,0.443,0.472,0.5,0.525,0.549,0.569,0.585,0.598,0.607,0.613,0.615,0.614,0.611,0.606,0.6,0.594,0.587,0.58,0.575,0.57,0.567,0.566,0.566,0.567,0.57,0.574,0.579,0.584,0.589,0.593,0.597,0.599,0.6,0.6,0.597,0.593,0.587,0.579,0.57,0.559,0.548,0.537,0.526,0.516,0.508,0.501,0.498,0.497,0.5,0.506,0.517,0.531,0.55,0.573,0.599,0.628,0.66,0.695,0.73,0.766,0.802,0.836,0.869,0.898,0.924,0.946,0.962,0.973,0.978,0.977,0.969,0.956,0.936,0.911,0.88,0.846,0.807,0.766,0.722,0.678,0.633,0.59,0.548,0.509,0.473,0.442,0.415,0.393,0.377,0.366,0.36,0.36,0.365,0.374,0.388,0.404,0.424,0.446,0.47,0.494,0.518,0.542,0.565,0.586,0.605,0.622,0.637,0.649,0.658,0.665,0.669,0.671,0.67,0.667,0.663,0.656,0.649,0.64,0.631,0.62,0.61,0.599,0.588,0.577,0.567,0.557,0.549,0.541,0.534,0.529,0.525,0.524,0.524,0.527,0.532,0.539,0.549,0.561,0.575,0.59,0.383,0.385,0.397,0.419,0.45,0.491,0.539,0.593,0.651,0.71,0.769,0.824,0.873,0.913,0.943,0.961,0.966,0.957,0.935,0.9,0.853,0.796,0.732,0.662,0.589,0.516,0.447,0.382,0.326,0.279,0.244,0.222,0.212,0.214,0.229,0.255,0.29,0.332,0.379,0.428,0.478,0.526,0.569,0.607,0.637,0.658,0.67,0.672,0.666,0.652,0.631,0.605,0.576,0.545,0.515,0.487,0.464,0.447,0.437,0.435,0.441,0.456,0.48,0.51,0.547,0.589,0.634,0.68,0.726,0.769,0.807,0.84,0.865,0.882,0.89,0.889,0.877,0.857,0.829,0.793,0.751,0.705,0.656,0.606,0.556,0.509,0.465,0.427,0.394,0.368,0.349,0.337,0.333,0.336,0.345,0.359,0.378,0.401,0.426,0.452,0.478,0.503,0.526,0.547,0.564,0.578,0.588,0.594,0.596,0.595,0.591,0.584,0.576,0.566,0.557,0.547,0.539,0.532,0.527,0.524,0.523,0.525,0.529,0.536,0.544,0.554,0.566,0.577,0.589,0.6,0.611,0.619,0.626,0.631,0.634,0.633,0.631,0.625,0.618,0.609,0.598,0.587,0.575,0.564,0.553,0.544,0.537,0.533,0.532,0.535,0.542,0.552,0.567,0.586,0.609,0.636,0.666,0.698,0.732,0.767,0.802,0.836,0.869,0.9,0.927,0.95,0.969,0.982,0.99,0.991,0.987,0.976,0.959,0.936,0.909,0.876,0.84,0.8,0.759,0.715,0.672,0.629,0.587,0.548,0.511,0.479,0.451,0.427,0.409,0.396,0.388,0.385,0.387,0.394,0.404,0.418,0.435,0.454,0.474,0.495,0.516,0.537,0.557,0.576,0.593,0.608,0.621,0.631,0.64,0.646,0.649,0.651,0.651,0.649,0.646,0.642,0.636,0.63,0.623,0.616,0.608,0.6,0.592,0.584,0.577,0.569,0.562,0.555,0.55,0.545,0.541,0.538,0.538,0.538,0.541,0.546,0.553,0.561,0.572,0.585,0.391,0.395,0.41,0.434,0.468,0.51,0.559,0.614,0.671,0.73,0.786,0.839,0.884,0.92,0.946,0.959,0.959,0.945,0.918,0.878,0.828,0.767,0.7,0.629,0.555,0.483,0.415,0.353,0.3,0.258,0.227,0.209,0.205,0.213,0.233,0.263,0.302,0.348,0.398,0.45,0.501,0.55,0.593,0.63,0.658,0.678,0.688,0.689,0.681,0.665,0.643,0.616,0.587,0.556,0.527,0.501,0.48,0.465,0.458,0.46,0.469,0.488,0.514,0.548,0.587,0.63,0.676,0.723,0.768,0.809,0.846,0.876,0.898,0.912,0.916,0.911,0.896,0.872,0.841,0.803,0.759,0.712,0.663,0.613,0.565,0.519,0.478,0.443,0.413,0.391,0.376,0.368,0.367,0.373,0.384,0.401,0.421,0.443,0.467,0.491,0.514,0.535,0.554,0.569,0.58,0.587,0.59,0.589,0.584,0.576,0.566,0.553,0.54,0.526,0.513,0.502,0.492,0.484,0.48,0.479,0.481,0.487,0.495,0.507,0.521,0.538,0.555,0.574,0.592,0.61,0.627,0.642,0.655,0.664,0.671,0.675,0.675,0.673,0.667,0.659,0.648,0.636,0.623,0.609,0.596,0.584,0.574,0.566,0.561,0.56,0.563,0.569,0.58,0.596,0.615,0.639,0.665,0.695,0.727,0.761,0.795,0.83,0.863,0.894,0.923,0.947,0.968,0.984,0.994,0.998,0.997,0.989,0.975,0.956,0.931,0.901,0.867,0.83,0.79,0.748,0.706,0.664,0.623,0.584,0.547,0.514,0.485,0.461,0.441,0.427,0.417,0.412,0.412,0.416,0.424,0.435,0.449,0.465,0.482,0.501,0.519,0.537,0.554,0.57,0.585,0.597,0.608,0.617,0.623,0.628,0.631,0.632,0.632,0.631,0.628,0.625,0.622,0.618,0.613,0.608,0.604,0.599,0.594,0.589,0.584,0.579,0.574,0.569,0.564,0.56,0.556,0.553,0.551,0.551,0.552,0.554,0.558,0.564,0.572,0.582,0.399,0.406,0.423,0.45,0.485,0.529,0.579,0.633,0.691,0.748,0.802,0.852,0.893,0.926,0.947,0.955,0.95,0.931,0.899,0.855,0.801,0.738,0.669,0.596,0.523,0.451,0.385,0.326,0.276,0.238,0.213,0.2,0.201,0.214,0.239,0.274,0.317,0.367,0.42,0.474,0.526,0.575,0.618,0.654,0.681,0.699,0.707,0.706,0.696,0.679,0.655,0.628,0.598,0.568,0.54,0.515,0.496,0.484,0.48,0.484,0.497,0.519,0.548,0.584,0.625,0.669,0.716,0.762,0.806,0.846,0.881,0.908,0.927,0.937,0.938,0.929,0.911,0.884,0.85,0.809,0.765,0.717,0.668,0.619,0.573,0.53,0.492,0.46,0.434,0.416,0.405,0.401,0.404,0.413,0.427,0.444,0.465,0.487,0.51,0.531,0.551,0.568,0.581,0.591,0.595,0.596,0.592,0.584,0.572,0.557,0.541,0.523,0.504,0.487,0.471,0.457,0.446,0.439,0.436,0.436,0.442,0.451,0.465,0.482,0.502,0.524,0.548,0.573,0.598,0.623,0.646,0.666,0.684,0.699,0.71,0.717,0.72,0.719,0.715,0.707,0.696,0.683,0.668,0.653,0.637,0.621,0.608,0.596,0.587,0.581,0.579,0.582,0.588,0.6,0.616,0.636,0.66,0.687,0.717,0.749,0.783,0.816,0.85,0.882,0.911,0.938,0.96,0.978,0.991,0.998,1.0,0.995,0.984,0.968,0.946,0.919,0.888,0.853,0.815,0.775,0.735,0.694,0.654,0.616,0.58,0.547,0.518,0.493,0.473,0.457,0.446,0.44,0.438,0.44,0.446,0.455,0.466,0.48,0.494,0.51,0.525,0.541,0.555,0.568,0.58,0.59,0.598,0.605,0.609,0.613,0.614,0.614,0.614,0.612,0.611,0.608,0.606,0.603,0.601,0.599,0.597,0.595,0.593,0.59,0.588,0.586,0.583,0.58,0.577,0.574,0.571,0.568,0.566,0.564,0.563,0.564,0.565,0.569,0.574,0.58,0.408,0.418,0.437,0.465,0.502,0.547,0.598,0.652,0.709,0.764,0.816,0.863,0.901,0.929,0.945,0.949,0.939,0.915,0.879,0.831,0.774,0.708,0.637,0.564,0.491,0.421,0.357,0.301,0.255,0.222,0.201,0.194,0.2,0.218,0.248,0.288,0.335,0.388,0.443,0.499,0.552,0.601,0.644,0.679,0.704,0.72,0.726,0.723,0.711,0.692,0.667,0.639,0.609,0.579,0.552,0.529,0.512,0.503,0.501,0.509,0.524,0.549,0.58,0.618,0.661,0.706,0.753,0.799,0.841,0.88,0.912,0.936,0.952,0.958,0.955,0.943,0.921,0.891,0.855,0.813,0.767,0.72,0.671,0.624,0.58,0.54,0.506,0.478,0.457,0.443,0.436,0.437,0.443,0.455,0.471,0.49,0.511,0.532,0.553,0.572,0.588,0.601,0.609,0.612,0.611,0.604,0.593,0.578,0.559,0.538,0.516,0.492,0.47,0.448,0.43,0.414,0.403,0.396,0.394,0.397,0.406,0.419,0.437,0.46,0.485,0.514,0.544,0.576,0.607,0.637,0.666,0.692,0.715,0.734,0.749,0.759,0.764,0.765,0.761,0.753,0.742,0.728,0.711,0.693,0.674,0.655,0.637,0.621,0.607,0.597,0.591,0.589,0.591,0.599,0.61,0.627,0.648,0.673,0.701,0.731,0.763,0.797,0.83,0.862,0.893,0.921,0.945,0.965,0.981,0.991,0.995,0.993,0.986,0.973,0.954,0.93,0.902,0.869,0.834,0.797,0.758,0.719,0.681,0.643,0.608,0.576,0.547,0.522,0.502,0.486,0.474,0.467,0.464,0.465,0.469,0.476,0.486,0.497,0.509,0.523,0.536,0.548,0.56,0.57,0.579,0.587,0.592,0.596,0.599,0.6,0.599,0.598,0.597,0.595,0.593,0.591,0.589,0.588,0.587,0.587,0.587,0.588,0.589,0.59,0.59,0.591,0.591,0.59,0.589,0.587,0.585,0.583,0.58,0.578,0.576,0.574,0.574,0.575,0.577,0.581,0.417,0.429,0.451,0.481,0.519,0.565,0.616,0.67,0.725,0.779,0.829,0.872,0.906,0.93,0.942,0.941,0.926,0.898,0.858,0.806,0.745,0.678,0.606,0.532,0.46,0.391,0.33,0.278,0.237,0.208,0.192,0.19,0.202,0.226,0.261,0.305,0.356,0.412,0.469,0.526,0.58,0.629,0.671,0.704,0.728,0.741,0.745,0.739,0.725,0.705,0.679,0.649,0.619,0.59,0.564,0.543,0.528,0.521,0.522,0.532,0.55,0.577,0.611,0.65,0.694,0.74,0.786,0.831,0.873,0.909,0.938,0.959,0.971,0.974,0.968,0.952,0.927,0.895,0.857,0.814,0.768,0.72,0.673,0.628,0.587,0.551,0.52,0.497,0.48,0.471,0.469,0.473,0.483,0.498,0.516,0.536,0.558,0.578,0.597,0.613,0.626,0.634,0.636,0.633,0.625,0.612,0.594,0.572,0.547,0.52,0.491,0.463,0.436,0.412,0.391,0.374,0.362,0.356,0.355,0.361,0.373,0.391,0.414,0.441,0.472,0.507,0.543,0.58,0.618,0.654,0.688,0.719,0.746,0.769,0.787,0.799,0.806,0.808,0.805,0.797,0.784,0.768,0.749,0.728,0.706,0.683,0.661,0.641,0.623,0.608,0.597,0.591,0.589,0.592,0.6,0.613,0.631,0.652,0.678,0.707,0.738,0.771,0.804,0.837,0.868,0.897,0.923,0.946,0.963,0.976,0.983,0.985,0.98,0.97,0.955,0.934,0.909,0.879,0.847,0.812,0.776,0.739,0.702,0.666,0.632,0.601,0.573,0.549,0.528,0.512,0.501,0.493,0.489,0.489,0.493,0.498,0.507,0.516,0.527,0.538,0.549,0.559,0.568,0.576,0.582,0.587,0.59,0.591,0.591,0.589,0.587,0.584,0.581,0.578,0.575,0.573,0.572,0.571,0.572,0.573,0.576,0.579,0.582,0.586,0.59,0.593,0.596,0.598,0.599,0.599,0.599,0.597,0.595,0.592,0.589,0.586,0.584,0.583,0.583,0.584,0.427,0.441,0.464,0.496,0.536,0.582,0.633,0.687,0.741,0.792,0.839,0.879,0.91,0.93,0.937,0.931,0.912,0.879,0.835,0.78,0.717,0.648,0.575,0.501,0.43,0.364,0.306,0.257,0.22,0.197,0.187,0.19,0.207,0.236,0.276,0.324,0.379,0.437,0.497,0.555,0.609,0.657,0.698,0.729,0.751,0.762,0.763,0.755,0.739,0.717,0.689,0.659,0.629,0.6,0.575,0.555,0.542,0.537,0.541,0.553,0.574,0.603,0.639,0.68,0.724,0.77,0.816,0.86,0.899,0.933,0.959,0.977,0.986,0.985,0.975,0.956,0.929,0.894,0.854,0.811,0.765,0.718,0.673,0.631,0.593,0.56,0.534,0.516,0.504,0.5,0.502,0.51,0.524,0.541,0.562,0.583,0.604,0.624,0.641,0.654,0.663,0.666,0.663,0.654,0.639,0.619,0.595,0.566,0.534,0.501,0.468,0.435,0.404,0.377,0.354,0.336,0.324,0.319,0.321,0.329,0.344,0.366,0.394,0.426,0.463,0.503,0.545,0.588,0.63,0.671,0.71,0.745,0.776,0.802,0.823,0.838,0.846,0.849,0.845,0.836,0.823,0.805,0.783,0.759,0.733,0.707,0.681,0.656,0.634,0.614,0.599,0.587,0.581,0.58,0.584,0.593,0.608,0.627,0.65,0.677,0.707,0.739,0.772,0.805,0.837,0.867,0.895,0.919,0.939,0.955,0.965,0.969,0.968,0.961,0.949,0.931,0.909,0.883,0.853,0.821,0.787,0.752,0.717,0.684,0.651,0.621,0.595,0.571,0.552,0.536,0.525,0.517,0.513,0.513,0.516,0.521,0.529,0.537,0.546,0.556,0.565,0.573,0.58,0.585,0.589,0.591,0.591,0.589,0.586,0.582,0.577,0.572,0.567,0.563,0.559,0.556,0.554,0.554,0.556,0.558,0.563,0.568,0.574,0.58,0.587,0.593,0.599,0.604,0.607,0.61,0.611,0.61,0.609,0.606,0.603,0.599,0.595,0.592,0.589,0.588,0.437,0.453,0.478,0.511,0.552,0.599,0.65,0.702,0.755,0.804,0.849,0.885,0.912,0.927,0.93,0.92,0.896,0.86,0.812,0.754,0.688,0.618,0.544,0.472,0.402,0.338,0.283,0.239,0.207,0.188,0.184,0.193,0.215,0.249,0.294,0.346,0.404,0.464,0.525,0.584,0.638,0.686,0.725,0.754,0.773,0.782,0.781,0.77,0.752,0.728,0.699,0.668,0.637,0.609,0.585,0.566,0.555,0.552,0.558,0.573,0.596,0.627,0.664,0.706,0.751,0.797,0.842,0.884,0.921,0.952,0.975,0.99,0.995,0.991,0.977,0.955,0.925,0.889,0.848,0.804,0.759,0.713,0.671,0.631,0.597,0.569,0.548,0.534,0.527,0.528,0.535,0.548,0.565,0.585,0.607,0.63,0.651,0.669,0.684,0.694,0.699,0.697,0.688,0.673,0.652,0.626,0.595,0.56,0.522,0.484,0.445,0.409,0.375,0.345,0.32,0.302,0.291,0.287,0.29,0.301,0.32,0.346,0.378,0.415,0.457,0.502,0.549,0.597,0.644,0.69,0.733,0.772,0.806,0.835,0.857,0.873,0.882,0.885,0.881,0.871,0.856,0.836,0.812,0.785,0.755,0.725,0.695,0.666,0.639,0.615,0.595,0.579,0.568,0.563,0.563,0.569,0.58,0.596,0.617,0.642,0.671,0.702,0.734,0.767,0.8,0.832,0.861,0.887,0.909,0.927,0.94,0.948,0.949,0.946,0.936,0.922,0.903,0.88,0.853,0.823,0.792,0.76,0.727,0.695,0.665,0.637,0.611,0.589,0.571,0.556,0.546,0.539,0.536,0.536,0.539,0.544,0.551,0.559,0.567,0.575,0.583,0.59,0.595,0.598,0.599,0.598,0.595,0.591,0.585,0.578,0.571,0.563,0.556,0.549,0.543,0.539,0.537,0.537,0.539,0.542,0.548,0.555,0.563,0.572,0.582,0.591,0.6,0.607,0.614,0.619,0.622,0.623,0.622,0.62,0.617,0.612,0.607,0.602,0.598,0.594,0.447,0.465,0.492,0.526,0.568,0.615,0.665,0.717,0.768,0.815,0.856,0.889,0.912,0.923,0.921,0.907,0.879,0.839,0.788,0.727,0.66,0.588,0.515,0.443,0.375,0.315,0.264,0.224,0.196,0.183,0.184,0.198,0.226,0.265,0.314,0.37,0.43,0.493,0.555,0.615,0.668,0.715,0.752,0.779,0.796,0.801,0.797,0.784,0.764,0.737,0.707,0.675,0.644,0.616,0.593,0.576,0.567,0.566,0.574,0.591,0.616,0.648,0.686,0.729,0.774,0.819,0.863,0.903,0.938,0.966,0.986,0.997,0.999,0.991,0.974,0.949,0.917,0.88,0.838,0.794,0.749,0.706,0.666,0.63,0.6,0.577,0.56,0.552,0.55,0.556,0.568,0.585,0.605,0.628,0.652,0.675,0.696,0.713,0.726,0.733,0.733,0.726,0.712,0.692,0.665,0.632,0.595,0.554,0.511,0.467,0.425,0.384,0.348,0.316,0.29,0.272,0.261,0.258,0.264,0.278,0.3,0.33,0.366,0.408,0.454,0.504,0.555,0.608,0.659,0.709,0.755,0.797,0.834,0.864,0.888,0.905,0.915,0.917,0.913,0.901,0.884,0.862,0.835,0.804,0.772,0.738,0.703,0.67,0.639,0.61,0.586,0.565,0.551,0.541,0.537,0.54,0.548,0.561,0.58,0.603,0.63,0.66,0.693,0.726,0.759,0.792,0.822,0.85,0.874,0.895,0.91,0.92,0.925,0.924,0.918,0.907,0.891,0.87,0.846,0.82,0.791,0.761,0.731,0.701,0.673,0.647,0.623,0.603,0.586,0.573,0.563,0.557,0.555,0.556,0.56,0.565,0.572,0.58,0.588,0.596,0.603,0.608,0.611,0.613,0.612,0.609,0.603,0.596,0.587,0.577,0.567,0.556,0.546,0.537,0.53,0.524,0.521,0.52,0.521,0.525,0.532,0.54,0.551,0.562,0.574,0.586,0.598,0.609,0.618,0.625,0.631,0.634,0.635,0.634,0.631,0.626,0.62,0.614,0.607,0.601,0.458,0.477,0.505,0.541,0.583,0.63,0.68,0.73,0.779,0.824,0.862,0.891,0.91,0.917,0.911,0.893,0.861,0.817,0.763,0.7,0.632,0.559,0.487,0.416,0.351,0.293,0.246,0.211,0.189,0.181,0.187,0.207,0.239,0.283,0.336,0.395,0.459,0.523,0.586,0.645,0.698,0.743,0.778,0.803,0.816,0.819,0.812,0.797,0.773,0.745,0.713,0.681,0.65,0.622,0.599,0.584,0.576,0.577,0.587,0.606,0.632,0.666,0.705,0.748,0.793,0.838,0.88,0.918,0.95,0.975,0.992,0.999,0.997,0.986,0.966,0.939,0.905,0.866,0.823,0.78,0.737,0.696,0.659,0.627,0.601,0.583,0.572,0.568,0.572,0.583,0.6,0.621,0.645,0.67,0.696,0.719,0.74,0.756,0.766,0.769,0.766,0.754,0.735,0.709,0.676,0.637,0.594,0.548,0.5,0.452,0.406,0.362,0.323,0.29,0.264,0.245,0.236,0.235,0.243,0.259,0.285,0.318,0.358,0.404,0.454,0.508,0.563,0.619,0.674,0.727,0.776,0.82,0.859,0.891,0.916,0.933,0.942,0.944,0.939,0.926,0.907,0.882,0.852,0.818,0.782,0.744,0.706,0.669,0.633,0.601,0.572,0.548,0.529,0.515,0.508,0.507,0.512,0.523,0.54,0.561,0.587,0.616,0.647,0.681,0.714,0.748,0.78,0.809,0.835,0.858,0.875,0.888,0.896,0.898,0.895,0.886,0.873,0.856,0.834,0.81,0.784,0.757,0.729,0.701,0.675,0.651,0.629,0.611,0.596,0.584,0.576,0.572,0.571,0.574,0.578,0.585,0.593,0.601,0.609,0.617,0.623,0.628,0.63,0.63,0.627,0.622,0.614,0.605,0.593,0.58,0.566,0.553,0.54,0.528,0.518,0.51,0.505,0.503,0.504,0.508,0.515,0.525,0.537,0.55,0.564,0.579,0.594,0.608,0.62,0.631,0.639,0.644,0.647,0.647,0.644,0.64,0.634,0.626,0.618,0.61,0.468,0.489,0.518,0.554,0.597,0.644,0.693,0.742,0.789,0.831,0.866,0.892,0.907,0.91,0.9,0.877,0.842,0.795,0.738,0.674,0.604,0.531,0.459,0.391,0.328,0.274,0.231,0.2,0.183,0.181,0.192,0.218,0.255,0.304,0.36,0.423,0.488,0.554,0.618,0.676,0.728,0.771,0.804,0.825,0.836,0.836,0.826,0.807,0.782,0.751,0.718,0.685,0.653,0.625,0.604,0.589,0.583,0.586,0.597,0.618,0.646,0.681,0.721,0.764,0.808,0.851,0.892,0.927,0.957,0.979,0.992,0.996,0.99,0.976,0.953,0.923,0.887,0.847,0.805,0.762,0.721,0.683,0.649,0.621,0.6,0.587,0.581,0.584,0.593,0.609,0.63,0.655,0.682,0.71,0.737,0.761,0.781,0.796,0.803,0.804,0.796,0.78,0.756,0.724,0.686,0.642,0.594,0.543,0.49,0.439,0.389,0.343,0.302,0.268,0.242,0.224,0.215,0.216,0.226,0.246,0.274,0.31,0.354,0.403,0.457,0.514,0.573,0.632,0.69,0.745,0.796,0.842,0.881,0.914,0.939,0.956,0.965,0.966,0.959,0.944,0.923,0.895,0.863,0.826,0.787,0.746,0.704,0.663,0.623,0.587,0.554,0.526,0.503,0.487,0.476,0.472,0.474,0.483,0.497,0.517,0.541,0.569,0.6,0.633,0.667,0.701,0.734,0.765,0.793,0.818,0.838,0.853,0.863,0.868,0.867,0.861,0.851,0.836,0.817,0.796,0.772,0.747,0.722,0.696,0.672,0.65,0.631,0.614,0.601,0.591,0.585,0.583,0.584,0.588,0.594,0.602,0.611,0.621,0.63,0.638,0.644,0.649,0.651,0.649,0.645,0.638,0.628,0.616,0.601,0.586,0.569,0.552,0.536,0.521,0.508,0.498,0.491,0.487,0.487,0.491,0.498,0.508,0.521,0.536,0.553,0.571,0.588,0.605,0.62,0.634,0.645,0.653,0.657,0.659,0.658,0.654,0.647,0.639,0.63,0.62,0.479,0.501,0.531,0.568,0.611,0.657,0.705,0.753,0.798,0.837,0.869,0.891,0.903,0.902,0.888,0.861,0.822,0.772,0.713,0.647,0.577,0.504,0.434,0.367,0.307,0.257,0.218,0.192,0.181,0.184,0.201,0.231,0.274,0.326,0.386,0.451,0.519,0.586,0.649,0.707,0.757,0.798,0.828,0.847,0.854,0.851,0.837,0.816,0.787,0.755,0.72,0.686,0.654,0.627,0.606,0.593,0.588,0.592,0.605,0.627,0.657,0.692,0.732,0.775,0.819,0.86,0.899,0.932,0.958,0.977,0.986,0.987,0.978,0.96,0.935,0.903,0.865,0.825,0.783,0.741,0.702,0.667,0.637,0.613,0.597,0.589,0.589,0.597,0.612,0.633,0.659,0.688,0.718,0.748,0.776,0.801,0.82,0.833,0.838,0.835,0.824,0.803,0.775,0.738,0.695,0.646,0.593,0.538,0.482,0.427,0.374,0.326,0.285,0.25,0.223,0.206,0.199,0.202,0.214,0.236,0.268,0.307,0.353,0.406,0.463,0.522,0.584,0.645,0.705,0.761,0.813,0.86,0.9,0.933,0.958,0.974,0.982,0.982,0.973,0.957,0.933,0.903,0.868,0.829,0.786,0.742,0.697,0.652,0.609,0.569,0.533,0.502,0.476,0.455,0.442,0.435,0.434,0.441,0.453,0.471,0.494,0.521,0.552,0.585,0.619,0.654,0.687,0.72,0.749,0.775,0.797,0.815,0.827,0.834,0.836,0.833,0.825,0.812,0.796,0.777,0.756,0.733,0.709,0.686,0.664,0.644,0.627,0.612,0.601,0.594,0.59,0.589,0.592,0.598,0.607,0.616,0.627,0.638,0.649,0.658,0.665,0.67,0.672,0.67,0.665,0.656,0.645,0.63,0.613,0.594,0.574,0.554,0.535,0.517,0.501,0.488,0.478,0.473,0.471,0.474,0.48,0.491,0.505,0.521,0.54,0.56,0.58,0.6,0.618,0.635,0.649,0.659,0.667,0.67,0.67,0.667,0.661,0.652,0.642,0.631,0.489,0.512,0.543,0.581,0.623,0.669,0.717,0.763,0.805,0.842,0.871,0.889,0.897,0.892,0.874,0.844,0.802,0.749,0.688,0.621,0.55,0.479,0.409,0.345,0.288,0.242,0.208,0.187,0.181,0.189,0.211,0.247,0.294,0.35,0.414,0.481,0.55,0.617,0.681,0.738,0.786,0.824,0.851,0.866,0.87,0.863,0.847,0.822,0.791,0.757,0.72,0.685,0.653,0.626,0.606,0.593,0.59,0.596,0.611,0.634,0.664,0.7,0.74,0.783,0.825,0.865,0.901,0.932,0.955,0.97,0.976,0.973,0.96,0.94,0.912,0.878,0.84,0.799,0.757,0.717,0.68,0.648,0.622,0.603,0.592,0.59,0.596,0.609,0.629,0.655,0.685,0.718,0.751,0.783,0.813,0.837,0.856,0.867,0.87,0.864,0.849,0.824,0.791,0.75,0.702,0.649,0.592,0.533,0.474,0.416,0.362,0.313,0.27,0.236,0.21,0.194,0.188,0.192,0.207,0.232,0.266,0.308,0.357,0.411,0.47,0.532,0.595,0.658,0.718,0.776,0.828,0.875,0.915,0.947,0.972,0.987,0.994,0.992,0.981,0.963,0.937,0.905,0.868,0.826,0.781,0.733,0.685,0.638,0.592,0.549,0.51,0.475,0.446,0.423,0.407,0.397,0.394,0.398,0.409,0.425,0.447,0.473,0.504,0.536,0.571,0.606,0.64,0.674,0.705,0.732,0.756,0.775,0.79,0.799,0.803,0.802,0.796,0.786,0.772,0.755,0.735,0.714,0.693,0.672,0.652,0.634,0.618,0.605,0.596,0.591,0.589,0.591,0.597,0.605,0.615,0.627,0.64,0.654,0.666,0.677,0.685,0.691,0.693,0.691,0.686,0.676,0.663,0.647,0.627,0.606,0.583,0.56,0.537,0.515,0.496,0.48,0.467,0.459,0.456,0.457,0.463,0.473,0.487,0.505,0.525,0.547,0.57,0.593,0.615,0.634,0.651,0.665,0.675,0.68,0.682,0.68,0.675,0.666,0.655,0.642,0.499,0.523,0.555,0.593,0.636,0.681,0.727,0.771,0.811,0.845,0.871,0.886,0.89,0.881,0.86,0.826,0.781,0.726,0.664,0.596,0.525,0.454,0.386,0.325,0.272,0.229,0.2,0.184,0.183,0.197,0.225,0.265,0.316,0.376,0.442,0.512,0.582,0.649,0.712,0.767,0.813,0.849,0.872,0.884,0.884,0.874,0.854,0.826,0.792,0.756,0.718,0.682,0.65,0.623,0.603,0.592,0.59,0.597,0.613,0.637,0.668,0.705,0.745,0.786,0.827,0.866,0.899,0.927,0.947,0.958,0.961,0.954,0.938,0.915,0.884,0.849,0.81,0.769,0.728,0.69,0.656,0.627,0.605,0.591,0.586,0.589,0.6,0.619,0.644,0.675,0.709,0.745,0.781,0.815,0.846,0.871,0.888,0.898,0.898,0.889,0.871,0.842,0.805,0.76,0.709,0.652,0.591,0.529,0.468,0.408,0.353,0.303,0.26,0.226,0.201,0.186,0.182,0.188,0.205,0.232,0.268,0.312,0.363,0.419,0.48,0.543,0.607,0.67,0.731,0.788,0.84,0.887,0.926,0.957,0.98,0.994,0.999,0.996,0.984,0.963,0.936,0.902,0.862,0.818,0.77,0.721,0.67,0.62,0.572,0.526,0.484,0.447,0.416,0.39,0.372,0.36,0.355,0.357,0.366,0.381,0.402,0.427,0.457,0.489,0.524,0.559,0.595,0.629,0.661,0.69,0.715,0.736,0.752,0.763,0.769,0.77,0.766,0.758,0.745,0.73,0.712,0.693,0.673,0.654,0.635,0.619,0.605,0.594,0.587,0.584,0.584,0.589,0.596,0.607,0.62,0.635,0.65,0.666,0.681,0.693,0.704,0.711,0.714,0.713,0.707,0.697,0.683,0.665,0.644,0.62,0.594,0.568,0.541,0.517,0.494,0.474,0.459,0.448,0.442,0.441,0.446,0.455,0.47,0.488,0.51,0.534,0.559,0.584,0.609,0.632,0.652,0.668,0.681,0.689,0.693,0.693,0.688,0.68,0.668,0.655,0.509,0.534,0.566,0.605,0.647,0.691,0.736,0.778,0.816,0.847,0.87,0.881,0.882,0.869,0.845,0.808,0.76,0.704,0.64,0.571,0.5,0.431,0.365,0.306,0.257,0.219,0.194,0.184,0.188,0.207,0.24,0.285,0.34,0.403,0.472,0.543,0.614,0.681,0.743,0.796,0.839,0.872,0.892,0.9,0.896,0.882,0.858,0.827,0.791,0.752,0.713,0.676,0.643,0.617,0.598,0.588,0.587,0.595,0.612,0.637,0.669,0.706,0.746,0.786,0.826,0.862,0.893,0.918,0.934,0.942,0.941,0.931,0.912,0.886,0.853,0.816,0.776,0.736,0.696,0.66,0.629,0.604,0.586,0.577,0.577,0.585,0.602,0.626,0.657,0.692,0.73,0.77,0.808,0.844,0.875,0.9,0.917,0.925,0.923,0.911,0.889,0.858,0.817,0.769,0.713,0.654,0.59,0.526,0.463,0.402,0.346,0.296,0.253,0.22,0.196,0.183,0.18,0.189,0.207,0.236,0.274,0.319,0.372,0.429,0.49,0.554,0.618,0.681,0.741,0.798,0.849,0.894,0.932,0.962,0.983,0.996,0.999,0.994,0.98,0.958,0.929,0.893,0.851,0.805,0.756,0.705,0.652,0.6,0.55,0.502,0.459,0.419,0.386,0.358,0.338,0.324,0.317,0.318,0.325,0.339,0.359,0.384,0.413,0.445,0.479,0.515,0.551,0.586,0.619,0.649,0.675,0.698,0.715,0.728,0.735,0.738,0.735,0.728,0.717,0.703,0.687,0.669,0.65,0.632,0.615,0.6,0.588,0.579,0.573,0.572,0.575,0.581,0.592,0.605,0.621,0.638,0.657,0.675,0.692,0.708,0.72,0.729,0.734,0.734,0.729,0.719,0.705,0.685,0.662,0.636,0.608,0.579,0.549,0.521,0.494,0.471,0.452,0.438,0.429,0.426,0.429,0.438,0.452,0.47,0.493,0.518,0.546,0.574,0.601,0.627,0.65,0.67,0.686,0.697,0.703,0.704,0.701,0.693,0.682,0.668,0.518,0.545,0.577,0.615,0.657,0.701,0.744,0.785,0.82,0.848,0.867,0.876,0.872,0.857,0.829,0.789,0.739,0.681,0.616,0.547,0.477,0.409,0.346,0.29,0.245,0.211,0.191,0.186,0.195,0.219,0.257,0.306,0.365,0.431,0.502,0.574,0.645,0.712,0.772,0.823,0.864,0.893,0.909,0.913,0.905,0.887,0.86,0.826,0.787,0.746,0.706,0.668,0.635,0.609,0.59,0.581,0.581,0.591,0.609,0.635,0.667,0.704,0.743,0.783,0.82,0.854,0.883,0.904,0.917,0.922,0.917,0.903,0.882,0.853,0.819,0.78,0.74,0.7,0.662,0.628,0.6,0.578,0.565,0.561,0.566,0.58,0.602,0.632,0.667,0.707,0.749,0.791,0.832,0.869,0.901,0.925,0.941,0.948,0.944,0.93,0.905,0.87,0.826,0.775,0.717,0.655,0.59,0.524,0.459,0.398,0.342,0.292,0.251,0.218,0.196,0.184,0.184,0.194,0.214,0.244,0.283,0.33,0.383,0.441,0.502,0.565,0.628,0.691,0.75,0.805,0.855,0.898,0.934,0.962,0.981,0.992,0.993,0.986,0.971,0.947,0.916,0.879,0.836,0.789,0.739,0.686,0.632,0.579,0.527,0.478,0.433,0.392,0.357,0.328,0.306,0.291,0.283,0.282,0.288,0.301,0.32,0.344,0.372,0.404,0.439,0.475,0.511,0.546,0.58,0.611,0.638,0.662,0.681,0.694,0.703,0.706,0.705,0.699,0.689,0.676,0.661,0.644,0.626,0.609,0.593,0.579,0.568,0.56,0.556,0.557,0.561,0.57,0.583,0.599,0.617,0.638,0.659,0.681,0.701,0.719,0.735,0.746,0.753,0.755,0.751,0.742,0.727,0.707,0.683,0.655,0.624,0.592,0.559,0.527,0.497,0.471,0.448,0.43,0.419,0.413,0.414,0.421,0.434,0.453,0.476,0.502,0.531,0.561,0.592,0.621,0.647,0.67,0.689,0.703,0.712,0.715,0.713,0.706,0.695,0.681,0.528,0.555,0.588,0.626,0.667,0.71,0.751,0.79,0.823,0.848,0.864,0.869,0.863,0.844,0.813,0.771,0.718,0.658,0.593,0.524,0.455,0.389,0.328,0.276,0.234,0.205,0.19,0.19,0.205,0.234,0.276,0.329,0.391,0.46,0.533,0.606,0.677,0.743,0.801,0.849,0.887,0.912,0.924,0.924,0.912,0.89,0.859,0.822,0.781,0.738,0.696,0.657,0.624,0.598,0.58,0.572,0.573,0.584,0.603,0.63,0.663,0.699,0.738,0.776,0.812,0.843,0.869,0.887,0.897,0.898,0.89,0.873,0.848,0.817,0.781,0.742,0.701,0.662,0.626,0.594,0.569,0.551,0.543,0.544,0.554,0.573,0.6,0.635,0.675,0.718,0.764,0.809,0.852,0.89,0.922,0.947,0.962,0.966,0.961,0.944,0.917,0.879,0.833,0.779,0.719,0.655,0.589,0.522,0.457,0.396,0.34,0.292,0.252,0.221,0.2,0.191,0.192,0.203,0.225,0.256,0.296,0.343,0.396,0.454,0.514,0.576,0.638,0.698,0.756,0.809,0.856,0.897,0.931,0.956,0.973,0.982,0.982,0.973,0.956,0.931,0.9,0.861,0.818,0.77,0.719,0.665,0.611,0.557,0.505,0.455,0.409,0.367,0.331,0.301,0.278,0.261,0.252,0.25,0.256,0.267,0.285,0.309,0.337,0.368,0.403,0.438,0.475,0.511,0.545,0.577,0.605,0.629,0.649,0.663,0.673,0.677,0.677,0.671,0.662,0.65,0.635,0.618,0.601,0.584,0.569,0.555,0.545,0.538,0.536,0.537,0.544,0.555,0.57,0.588,0.61,0.633,0.658,0.683,0.706,0.728,0.746,0.761,0.77,0.774,0.772,0.764,0.749,0.73,0.705,0.675,0.642,0.608,0.572,0.537,0.503,0.472,0.446,0.425,0.41,0.401,0.4,0.405,0.417,0.434,0.458,0.485,0.516,0.548,0.581,0.612,0.642,0.669,0.691,0.708,0.719,0.725,0.725,0.719,0.709,0.694,0.537,0.564,0.597,0.635,0.676,0.717,0.757,0.794,0.824,0.847,0.86,0.862,0.852,0.83,0.796,0.752,0.698,0.636,0.57,0.502,0.434,0.37,0.312,0.263,0.226,0.202,0.192,0.196,0.216,0.25,0.296,0.353,0.419,0.49,0.564,0.637,0.708,0.772,0.828,0.874,0.908,0.929,0.937,0.932,0.916,0.89,0.856,0.815,0.771,0.727,0.683,0.644,0.611,0.585,0.568,0.561,0.563,0.575,0.595,0.623,0.655,0.692,0.729,0.766,0.8,0.829,0.852,0.867,0.873,0.871,0.859,0.839,0.812,0.779,0.741,0.701,0.661,0.622,0.587,0.558,0.537,0.523,0.519,0.525,0.54,0.564,0.596,0.635,0.68,0.727,0.776,0.824,0.868,0.907,0.94,0.964,0.978,0.981,0.973,0.954,0.925,0.885,0.837,0.781,0.72,0.655,0.588,0.521,0.457,0.396,0.342,0.295,0.256,0.227,0.209,0.201,0.204,0.217,0.24,0.272,0.312,0.359,0.411,0.468,0.527,0.587,0.646,0.704,0.759,0.809,0.854,0.892,0.923,0.946,0.961,0.967,0.965,0.955,0.937,0.911,0.879,0.84,0.796,0.748,0.697,0.644,0.59,0.536,0.483,0.433,0.387,0.345,0.308,0.277,0.253,0.236,0.227,0.224,0.228,0.239,0.256,0.279,0.307,0.338,0.372,0.408,0.444,0.48,0.515,0.547,0.576,0.601,0.621,0.636,0.646,0.651,0.651,0.646,0.637,0.624,0.61,0.593,0.576,0.559,0.544,0.531,0.521,0.514,0.513,0.515,0.523,0.536,0.553,0.574,0.598,0.625,0.653,0.681,0.708,0.733,0.755,0.773,0.785,0.792,0.792,0.785,0.772,0.753,0.727,0.697,0.663,0.625,0.587,0.548,0.511,0.477,0.447,0.422,0.403,0.391,0.387,0.389,0.4,0.417,0.439,0.467,0.499,0.533,0.568,0.603,0.636,0.665,0.69,0.711,0.725,0.733,0.735,0.732,0.722,0.708,0.546,0.573,0.607,0.644,0.684,0.724,0.763,0.797,0.825,0.845,0.855,0.853,0.841,0.816,0.779,0.733,0.677,0.615,0.549,0.481,0.414,0.353,0.298,0.253,0.22,0.2,0.195,0.205,0.229,0.267,0.318,0.378,0.446,0.52,0.594,0.668,0.738,0.8,0.854,0.896,0.926,0.943,0.947,0.938,0.918,0.887,0.849,0.806,0.76,0.713,0.669,0.629,0.595,0.57,0.554,0.548,0.551,0.564,0.585,0.613,0.646,0.682,0.718,0.754,0.786,0.813,0.832,0.844,0.847,0.841,0.826,0.803,0.773,0.738,0.699,0.659,0.619,0.581,0.548,0.522,0.503,0.494,0.494,0.505,0.525,0.554,0.591,0.634,0.682,0.733,0.785,0.835,0.88,0.92,0.953,0.976,0.989,0.991,0.982,0.961,0.929,0.888,0.838,0.781,0.719,0.654,0.587,0.521,0.457,0.398,0.346,0.301,0.264,0.238,0.221,0.215,0.22,0.234,0.258,0.29,0.33,0.376,0.427,0.482,0.539,0.596,0.653,0.708,0.759,0.806,0.847,0.882,0.91,0.931,0.943,0.948,0.944,0.933,0.914,0.888,0.855,0.816,0.773,0.725,0.675,0.622,0.569,0.515,0.463,0.414,0.368,0.326,0.289,0.259,0.234,0.217,0.206,0.203,0.207,0.217,0.234,0.256,0.283,0.314,0.348,0.383,0.42,0.456,0.491,0.523,0.552,0.577,0.598,0.613,0.624,0.629,0.628,0.623,0.614,0.602,0.586,0.569,0.552,0.535,0.519,0.505,0.495,0.489,0.488,0.491,0.5,0.514,0.533,0.556,0.583,0.612,0.643,0.675,0.706,0.735,0.761,0.782,0.798,0.807,0.81,0.806,0.794,0.775,0.75,0.719,0.684,0.645,0.604,0.562,0.522,0.484,0.45,0.421,0.398,0.383,0.375,0.375,0.384,0.399,0.421,0.449,0.482,0.517,0.554,0.592,0.627,0.66,0.689,0.712,0.73,0.741,0.745,0.743,0.735,0.721,0.554,0.582,0.615,0.652,0.691,0.73,0.767,0.799,0.825,0.842,0.849,0.845,0.829,0.801,0.763,0.714,0.657,0.594,0.528,0.461,0.396,0.337,0.285,0.244,0.215,0.2,0.2,0.215,0.244,0.286,0.34,0.404,0.475,0.549,0.625,0.698,0.767,0.827,0.878,0.916,0.942,0.955,0.954,0.941,0.916,0.882,0.84,0.794,0.745,0.697,0.651,0.611,0.578,0.553,0.538,0.533,0.537,0.551,0.573,0.601,0.634,0.67,0.706,0.74,0.77,0.794,0.811,0.819,0.819,0.81,0.792,0.766,0.734,0.696,0.656,0.615,0.576,0.54,0.509,0.485,0.47,0.464,0.469,0.484,0.508,0.542,0.584,0.631,0.683,0.737,0.791,0.842,0.889,0.929,0.962,0.984,0.996,0.997,0.986,0.964,0.931,0.888,0.837,0.78,0.717,0.652,0.586,0.521,0.46,0.403,0.352,0.31,0.276,0.252,0.237,0.233,0.239,0.255,0.279,0.311,0.35,0.395,0.444,0.497,0.551,0.605,0.658,0.709,0.756,0.799,0.837,0.868,0.893,0.911,0.921,0.924,0.919,0.907,0.887,0.861,0.829,0.791,0.748,0.702,0.653,0.601,0.549,0.497,0.447,0.398,0.353,0.312,0.275,0.245,0.221,0.203,0.192,0.189,0.192,0.202,0.218,0.24,0.266,0.297,0.33,0.366,0.402,0.438,0.473,0.505,0.534,0.56,0.58,0.596,0.606,0.611,0.61,0.605,0.595,0.582,0.566,0.548,0.53,0.512,0.495,0.481,0.47,0.463,0.462,0.465,0.475,0.489,0.51,0.535,0.564,0.596,0.631,0.666,0.7,0.733,0.763,0.788,0.808,0.821,0.827,0.825,0.815,0.798,0.774,0.743,0.706,0.666,0.623,0.578,0.535,0.493,0.455,0.422,0.396,0.376,0.365,0.363,0.368,0.382,0.403,0.431,0.464,0.501,0.54,0.579,0.618,0.654,0.685,0.712,0.733,0.747,0.754,0.754,0.747,0.735,0.562,0.59,0.623,0.66,0.698,0.735,0.77,0.8,0.824,0.838,0.842,0.835,0.816,0.786,0.746,0.695,0.637,0.574,0.508,0.443,0.38,0.323,0.275,0.237,0.213,0.202,0.207,0.226,0.26,0.306,0.364,0.431,0.503,0.579,0.655,0.727,0.794,0.852,0.9,0.935,0.956,0.964,0.959,0.941,0.912,0.874,0.829,0.78,0.729,0.679,0.632,0.592,0.559,0.534,0.52,0.516,0.522,0.537,0.56,0.589,0.622,0.657,0.691,0.724,0.752,0.773,0.787,0.793,0.789,0.777,0.756,0.727,0.693,0.654,0.613,0.572,0.533,0.498,0.469,0.448,0.436,0.435,0.443,0.463,0.492,0.53,0.575,0.626,0.681,0.738,0.793,0.846,0.894,0.934,0.966,0.988,0.999,0.998,0.986,0.962,0.928,0.885,0.834,0.776,0.714,0.65,0.586,0.523,0.463,0.409,0.361,0.322,0.291,0.269,0.257,0.255,0.262,0.278,0.303,0.334,0.372,0.415,0.462,0.511,0.561,0.612,0.661,0.707,0.75,0.789,0.823,0.85,0.872,0.887,0.895,0.896,0.89,0.877,0.858,0.832,0.801,0.764,0.723,0.679,0.631,0.582,0.532,0.482,0.433,0.386,0.342,0.302,0.267,0.237,0.213,0.196,0.185,0.181,0.184,0.194,0.209,0.23,0.256,0.286,0.32,0.355,0.391,0.427,0.461,0.494,0.523,0.548,0.568,0.584,0.594,0.598,0.597,0.591,0.581,0.567,0.549,0.53,0.51,0.491,0.473,0.457,0.445,0.437,0.435,0.438,0.448,0.463,0.484,0.511,0.542,0.577,0.614,0.653,0.691,0.728,0.762,0.791,0.815,0.832,0.841,0.842,0.835,0.82,0.797,0.766,0.73,0.688,0.643,0.596,0.55,0.504,0.463,0.426,0.395,0.372,0.357,0.351,0.354,0.366,0.386,0.413,0.446,0.483,0.524,0.565,0.606,0.645,0.681,0.711,0.735,0.752,0.762,0.764,0.759,0.748,0.569,0.598,0.63,0.666,0.704,0.74,0.773,0.801,0.822,0.833,0.835,0.825,0.804,0.772,0.729,0.677,0.618,0.555,0.49,0.425,0.365,0.311,0.266,0.232,0.212,0.206,0.215,0.239,0.277,0.328,0.389,0.458,0.532,0.609,0.684,0.756,0.82,0.876,0.92,0.951,0.968,0.971,0.961,0.939,0.905,0.863,0.815,0.763,0.71,0.658,0.611,0.57,0.538,0.514,0.501,0.498,0.506,0.522,0.545,0.574,0.608,0.642,0.676,0.707,0.732,0.752,0.763,0.765,0.759,0.743,0.719,0.688,0.652,0.612,0.57,0.529,0.49,0.457,0.43,0.412,0.404,0.405,0.418,0.441,0.474,0.516,0.565,0.62,0.677,0.736,0.793,0.847,0.895,0.936,0.967,0.988,0.997,0.995,0.982,0.957,0.923,0.879,0.828,0.771,0.71,0.648,0.585,0.525,0.468,0.417,0.373,0.336,0.308,0.289,0.28,0.279,0.288,0.304,0.329,0.359,0.395,0.436,0.48,0.525,0.571,0.617,0.661,0.703,0.741,0.775,0.805,0.829,0.847,0.859,0.865,0.865,0.858,0.845,0.826,0.801,0.772,0.737,0.699,0.656,0.612,0.565,0.518,0.47,0.424,0.379,0.337,0.299,0.264,0.236,0.212,0.195,0.185,0.181,0.183,0.192,0.208,0.228,0.254,0.283,0.316,0.351,0.386,0.422,0.456,0.489,0.518,0.543,0.563,0.578,0.587,0.591,0.59,0.583,0.571,0.556,0.537,0.516,0.494,0.473,0.453,0.436,0.422,0.413,0.409,0.412,0.42,0.436,0.457,0.485,0.518,0.555,0.595,0.636,0.678,0.719,0.757,0.79,0.818,0.84,0.853,0.858,0.854,0.841,0.819,0.79,0.753,0.711,0.665,0.616,0.566,0.518,0.472,0.431,0.397,0.37,0.351,0.342,0.342,0.351,0.369,0.395,0.427,0.465,0.507,0.551,0.594,0.636,0.674,0.708,0.735,0.756,0.768,0.773,0.77,0.76,0.576,0.605,0.637,0.673,0.709,0.744,0.775,0.801,0.819,0.828,0.827,0.815,0.791,0.757,0.712,0.659,0.6,0.537,0.472,0.409,0.351,0.3,0.258,0.229,0.213,0.212,0.225,0.254,0.296,0.35,0.414,0.485,0.56,0.637,0.712,0.782,0.845,0.897,0.937,0.964,0.977,0.976,0.961,0.934,0.896,0.85,0.799,0.744,0.689,0.636,0.588,0.548,0.516,0.493,0.481,0.48,0.488,0.505,0.53,0.56,0.593,0.627,0.66,0.689,0.713,0.73,0.738,0.738,0.728,0.71,0.683,0.65,0.611,0.57,0.528,0.486,0.449,0.417,0.392,0.377,0.372,0.377,0.393,0.42,0.457,0.503,0.555,0.612,0.672,0.732,0.79,0.845,0.893,0.933,0.963,0.983,0.992,0.989,0.974,0.949,0.914,0.87,0.82,0.764,0.705,0.645,0.585,0.528,0.475,0.427,0.386,0.353,0.328,0.312,0.305,0.306,0.316,0.333,0.356,0.386,0.419,0.457,0.497,0.538,0.579,0.62,0.659,0.696,0.729,0.759,0.784,0.804,0.819,0.828,0.833,0.831,0.824,0.811,0.793,0.77,0.743,0.711,0.675,0.636,0.595,0.551,0.507,0.463,0.419,0.377,0.337,0.301,0.268,0.24,0.218,0.201,0.191,0.187,0.19,0.198,0.213,0.233,0.258,0.287,0.319,0.353,0.389,0.424,0.458,0.49,0.519,0.544,0.564,0.578,0.587,0.59,0.588,0.58,0.567,0.55,0.529,0.506,0.483,0.459,0.436,0.417,0.401,0.39,0.384,0.385,0.393,0.408,0.429,0.457,0.491,0.53,0.572,0.617,0.662,0.707,0.749,0.787,0.819,0.845,0.862,0.871,0.87,0.86,0.841,0.813,0.777,0.735,0.687,0.637,0.585,0.533,0.484,0.439,0.401,0.369,0.347,0.334,0.33,0.337,0.353,0.377,0.409,0.447,0.49,0.535,0.581,0.625,0.667,0.704,0.734,0.758,0.774,0.781,0.78,0.772,0.583,0.611,0.643,0.678,0.713,0.746,0.776,0.8,0.816,0.823,0.819,0.804,0.778,0.742,0.696,0.642,0.582,0.519,0.456,0.394,0.338,0.29,0.253,0.227,0.216,0.219,0.237,0.269,0.315,0.372,0.439,0.512,0.588,0.665,0.74,0.808,0.868,0.917,0.953,0.975,0.983,0.977,0.958,0.926,0.884,0.835,0.78,0.723,0.666,0.612,0.564,0.524,0.492,0.471,0.461,0.461,0.471,0.489,0.514,0.545,0.578,0.612,0.644,0.671,0.693,0.708,0.713,0.71,0.698,0.677,0.648,0.612,0.572,0.53,0.487,0.446,0.409,0.379,0.356,0.344,0.341,0.35,0.37,0.4,0.441,0.489,0.544,0.603,0.665,0.726,0.785,0.84,0.887,0.927,0.956,0.975,0.982,0.978,0.963,0.937,0.902,0.859,0.809,0.755,0.699,0.641,0.585,0.531,0.482,0.438,0.402,0.372,0.351,0.338,0.333,0.336,0.346,0.363,0.385,0.413,0.444,0.478,0.514,0.55,0.586,0.622,0.655,0.686,0.714,0.739,0.759,0.776,0.788,0.795,0.797,0.795,0.788,0.776,0.76,0.739,0.714,0.685,0.653,0.618,0.58,0.541,0.501,0.46,0.419,0.38,0.343,0.308,0.278,0.251,0.23,0.214,0.204,0.2,0.203,0.211,0.225,0.245,0.269,0.297,0.329,0.363,0.398,0.432,0.466,0.498,0.526,0.551,0.57,0.584,0.593,0.595,0.591,0.582,0.568,0.549,0.526,0.501,0.475,0.449,0.424,0.401,0.383,0.369,0.361,0.36,0.366,0.38,0.401,0.429,0.463,0.503,0.547,0.594,0.643,0.691,0.737,0.78,0.817,0.847,0.869,0.882,0.885,0.878,0.861,0.835,0.801,0.759,0.711,0.659,0.604,0.55,0.498,0.449,0.407,0.371,0.345,0.327,0.321,0.324,0.337,0.36,0.391,0.429,0.472,0.519,0.566,0.613,0.658,0.698,0.732,0.759,0.778,0.788,0.79,0.783,0.589,0.617,0.649,0.683,0.717,0.749,0.777,0.798,0.812,0.816,0.81,0.793,0.765,0.727,0.68,0.625,0.565,0.503,0.44,0.381,0.328,0.283,0.248,0.227,0.22,0.227,0.249,0.286,0.335,0.395,0.464,0.539,0.616,0.693,0.766,0.832,0.889,0.934,0.966,0.984,0.988,0.976,0.952,0.916,0.87,0.817,0.759,0.7,0.642,0.587,0.539,0.499,0.469,0.449,0.44,0.441,0.453,0.473,0.499,0.53,0.564,0.597,0.628,0.654,0.674,0.686,0.69,0.684,0.668,0.645,0.613,0.576,0.535,0.491,0.448,0.407,0.372,0.343,0.323,0.312,0.313,0.325,0.348,0.381,0.424,0.475,0.533,0.594,0.656,0.719,0.778,0.832,0.879,0.917,0.945,0.963,0.969,0.964,0.948,0.922,0.887,0.845,0.797,0.745,0.692,0.637,0.585,0.535,0.49,0.451,0.419,0.393,0.376,0.366,0.363,0.367,0.378,0.394,0.415,0.44,0.468,0.498,0.529,0.561,0.591,0.621,0.648,0.674,0.696,0.716,0.732,0.745,0.754,0.759,0.76,0.758,0.751,0.741,0.727,0.709,0.687,0.662,0.634,0.603,0.57,0.535,0.498,0.461,0.425,0.389,0.354,0.322,0.294,0.269,0.248,0.233,0.224,0.22,0.222,0.23,0.243,0.262,0.286,0.314,0.345,0.378,0.412,0.447,0.48,0.511,0.539,0.563,0.583,0.596,0.604,0.606,0.601,0.59,0.574,0.554,0.529,0.502,0.473,0.443,0.415,0.39,0.368,0.351,0.341,0.337,0.341,0.353,0.372,0.4,0.434,0.475,0.521,0.57,0.621,0.673,0.723,0.769,0.811,0.846,0.872,0.89,0.897,0.894,0.88,0.857,0.823,0.782,0.734,0.681,0.625,0.569,0.513,0.461,0.414,0.375,0.344,0.323,0.312,0.312,0.323,0.344,0.374,0.411,0.454,0.502,0.551,0.601,0.648,0.691,0.728,0.758,0.781,0.794,0.798,0.794,0.595,0.623,0.654,0.687,0.72,0.75,0.776,0.796,0.808,0.81,0.801,0.782,0.752,0.713,0.664,0.609,0.549,0.487,0.426,0.369,0.318,0.276,0.246,0.228,0.225,0.237,0.263,0.303,0.356,0.419,0.49,0.565,0.643,0.719,0.79,0.854,0.908,0.95,0.977,0.991,0.989,0.973,0.944,0.904,0.854,0.797,0.737,0.676,0.616,0.561,0.513,0.474,0.444,0.426,0.419,0.422,0.435,0.457,0.484,0.516,0.55,0.583,0.613,0.638,0.656,0.666,0.667,0.658,0.641,0.615,0.581,0.542,0.499,0.455,0.412,0.372,0.337,0.31,0.292,0.284,0.287,0.302,0.328,0.364,0.409,0.463,0.521,0.584,0.647,0.71,0.768,0.822,0.868,0.905,0.932,0.948,0.953,0.947,0.93,0.904,0.87,0.829,0.783,0.734,0.684,0.633,0.585,0.54,0.5,0.465,0.437,0.416,0.402,0.395,0.394,0.4,0.411,0.427,0.446,0.468,0.493,0.518,0.544,0.57,0.595,0.618,0.64,0.659,0.676,0.691,0.703,0.712,0.718,0.722,0.722,0.72,0.714,0.706,0.694,0.68,0.662,0.641,0.618,0.592,0.563,0.533,0.501,0.468,0.435,0.403,0.371,0.342,0.315,0.292,0.273,0.258,0.249,0.245,0.247,0.254,0.267,0.285,0.308,0.335,0.365,0.398,0.432,0.466,0.499,0.53,0.558,0.581,0.6,0.613,0.621,0.621,0.616,0.604,0.586,0.564,0.537,0.507,0.475,0.443,0.411,0.382,0.357,0.337,0.323,0.316,0.317,0.327,0.345,0.371,0.405,0.446,0.492,0.544,0.597,0.652,0.705,0.756,0.802,0.842,0.873,0.895,0.907,0.908,0.897,0.877,0.846,0.806,0.758,0.705,0.647,0.588,0.53,0.475,0.424,0.381,0.346,0.32,0.306,0.302,0.31,0.329,0.357,0.393,0.436,0.485,0.535,0.587,0.636,0.683,0.723,0.757,0.782,0.799,0.806,0.804,0.6,0.628,0.659,0.691,0.723,0.752,0.776,0.794,0.803,0.803,0.792,0.771,0.74,0.698,0.649,0.593,0.534,0.473,0.413,0.358,0.31,0.271,0.244,0.231,0.232,0.247,0.278,0.321,0.377,0.442,0.515,0.591,0.669,0.744,0.813,0.875,0.925,0.963,0.986,0.995,0.988,0.968,0.934,0.889,0.836,0.776,0.713,0.65,0.59,0.534,0.487,0.448,0.42,0.404,0.398,0.404,0.418,0.441,0.47,0.503,0.537,0.57,0.599,0.623,0.639,0.647,0.646,0.635,0.615,0.587,0.551,0.511,0.467,0.422,0.379,0.339,0.306,0.28,0.264,0.258,0.264,0.281,0.31,0.348,0.396,0.451,0.511,0.574,0.637,0.699,0.757,0.81,0.854,0.89,0.915,0.929,0.933,0.926,0.909,0.884,0.851,0.811,0.768,0.722,0.675,0.629,0.585,0.545,0.51,0.481,0.457,0.44,0.43,0.426,0.427,0.434,0.445,0.459,0.477,0.496,0.516,0.537,0.558,0.577,0.596,0.613,0.629,0.642,0.654,0.663,0.671,0.677,0.681,0.683,0.684,0.682,0.678,0.672,0.663,0.653,0.639,0.623,0.605,0.584,0.561,0.535,0.508,0.48,0.451,0.422,0.394,0.367,0.342,0.32,0.302,0.288,0.279,0.275,0.276,0.283,0.295,0.313,0.335,0.361,0.39,0.422,0.456,0.489,0.522,0.552,0.58,0.604,0.622,0.635,0.642,0.642,0.635,0.622,0.603,0.579,0.55,0.517,0.483,0.447,0.412,0.379,0.35,0.326,0.309,0.298,0.296,0.303,0.318,0.343,0.376,0.416,0.463,0.516,0.571,0.629,0.686,0.74,0.791,0.835,0.871,0.898,0.914,0.919,0.913,0.895,0.867,0.828,0.781,0.728,0.67,0.609,0.548,0.49,0.436,0.388,0.349,0.319,0.301,0.294,0.298,0.314,0.34,0.376,0.419,0.467,0.519,0.572,0.624,0.673,0.717,0.754,0.783,0.802,0.812,0.813,0.605,0.633,0.663,0.694,0.725,0.752,0.775,0.79,0.798,0.796,0.783,0.76,0.727,0.684,0.634,0.578,0.519,0.459,0.401,0.348,0.303,0.267,0.244,0.235,0.239,0.259,0.293,0.34,0.398,0.466,0.539,0.617,0.694,0.768,0.835,0.894,0.94,0.974,0.993,0.997,0.985,0.96,0.922,0.873,0.816,0.753,0.688,0.623,0.562,0.507,0.46,0.423,0.396,0.382,0.378,0.386,0.403,0.427,0.458,0.491,0.525,0.558,0.587,0.609,0.624,0.63,0.627,0.614,0.592,0.561,0.524,0.482,0.437,0.392,0.349,0.31,0.278,0.254,0.239,0.236,0.244,0.264,0.294,0.335,0.384,0.44,0.501,0.564,0.627,0.688,0.745,0.796,0.839,0.872,0.895,0.908,0.911,0.903,0.886,0.861,0.829,0.792,0.751,0.708,0.665,0.624,0.586,0.551,0.521,0.497,0.478,0.466,0.459,0.458,0.461,0.468,0.479,0.492,0.507,0.523,0.539,0.555,0.57,0.583,0.596,0.606,0.615,0.623,0.629,0.634,0.638,0.641,0.643,0.645,0.645,0.644,0.642,0.639,0.635,0.628,0.62,0.609,0.596,0.58,0.562,0.542,0.52,0.496,0.472,0.446,0.421,0.397,0.374,0.354,0.336,0.323,0.313,0.309,0.31,0.316,0.327,0.344,0.365,0.39,0.419,0.45,0.482,0.516,0.548,0.578,0.606,0.629,0.648,0.661,0.667,0.667,0.66,0.646,0.625,0.599,0.568,0.533,0.495,0.456,0.418,0.381,0.348,0.32,0.298,0.284,0.278,0.281,0.294,0.316,0.347,0.387,0.434,0.487,0.544,0.604,0.663,0.722,0.776,0.825,0.866,0.897,0.919,0.928,0.926,0.912,0.886,0.85,0.804,0.751,0.693,0.631,0.568,0.506,0.449,0.397,0.354,0.32,0.298,0.287,0.288,0.301,0.325,0.359,0.401,0.449,0.502,0.557,0.611,0.663,0.71,0.75,0.782,0.805,0.818,0.821,0.61,0.637,0.667,0.697,0.726,0.752,0.773,0.787,0.792,0.788,0.774,0.749,0.714,0.671,0.62,0.564,0.505,0.446,0.39,0.34,0.297,0.265,0.245,0.239,0.248,0.271,0.309,0.359,0.42,0.489,0.564,0.641,0.718,0.79,0.855,0.91,0.954,0.983,0.997,0.996,0.98,0.95,0.907,0.854,0.794,0.729,0.662,0.596,0.534,0.479,0.433,0.397,0.373,0.36,0.359,0.369,0.388,0.415,0.446,0.481,0.516,0.548,0.576,0.598,0.612,0.616,0.611,0.596,0.572,0.539,0.501,0.457,0.412,0.366,0.323,0.285,0.254,0.231,0.219,0.218,0.228,0.249,0.282,0.324,0.374,0.431,0.492,0.554,0.617,0.677,0.732,0.781,0.821,0.852,0.874,0.885,0.886,0.878,0.861,0.836,0.805,0.77,0.733,0.694,0.656,0.619,0.586,0.557,0.533,0.514,0.5,0.492,0.489,0.49,0.495,0.503,0.514,0.525,0.538,0.55,0.561,0.571,0.58,0.588,0.593,0.598,0.6,0.602,0.603,0.604,0.604,0.605,0.605,0.606,0.607,0.608,0.609,0.609,0.608,0.606,0.603,0.598,0.591,0.581,0.569,0.554,0.537,0.518,0.497,0.475,0.453,0.431,0.41,0.39,0.374,0.36,0.351,0.346,0.346,0.351,0.361,0.377,0.397,0.421,0.449,0.479,0.511,0.544,0.576,0.607,0.634,0.658,0.676,0.689,0.696,0.695,0.687,0.673,0.651,0.623,0.59,0.553,0.512,0.47,0.428,0.388,0.351,0.318,0.292,0.273,0.263,0.262,0.272,0.291,0.32,0.358,0.404,0.457,0.516,0.577,0.639,0.701,0.759,0.812,0.858,0.895,0.921,0.935,0.937,0.927,0.904,0.871,0.827,0.774,0.716,0.653,0.588,0.524,0.463,0.408,0.361,0.323,0.296,0.281,0.279,0.289,0.31,0.342,0.383,0.432,0.485,0.541,0.598,0.652,0.702,0.745,0.78,0.806,0.822,0.828,0.614,0.641,0.67,0.699,0.727,0.752,0.771,0.783,0.787,0.781,0.765,0.738,0.702,0.658,0.607,0.551,0.492,0.435,0.38,0.332,0.292,0.264,0.248,0.245,0.258,0.285,0.325,0.378,0.441,0.512,0.587,0.665,0.74,0.811,0.874,0.926,0.965,0.99,0.999,0.994,0.973,0.938,0.891,0.835,0.771,0.703,0.635,0.568,0.506,0.452,0.407,0.373,0.351,0.34,0.342,0.354,0.375,0.404,0.437,0.473,0.508,0.541,0.569,0.589,0.602,0.604,0.597,0.58,0.554,0.521,0.481,0.436,0.39,0.345,0.302,0.265,0.234,0.213,0.203,0.203,0.215,0.238,0.272,0.315,0.366,0.423,0.484,0.546,0.607,0.665,0.718,0.764,0.802,0.831,0.85,0.86,0.859,0.85,0.833,0.809,0.78,0.748,0.714,0.679,0.645,0.614,0.587,0.563,0.545,0.531,0.523,0.519,0.519,0.523,0.53,0.538,0.548,0.558,0.567,0.575,0.582,0.586,0.589,0.59,0.589,0.587,0.584,0.58,0.576,0.573,0.57,0.568,0.567,0.568,0.57,0.573,0.577,0.581,0.585,0.588,0.59,0.591,0.589,0.585,0.579,0.57,0.558,0.543,0.526,0.508,0.488,0.468,0.449,0.43,0.414,0.401,0.391,0.385,0.384,0.388,0.397,0.411,0.43,0.453,0.48,0.509,0.541,0.573,0.605,0.636,0.664,0.687,0.706,0.72,0.726,0.726,0.718,0.703,0.68,0.652,0.617,0.577,0.534,0.489,0.443,0.399,0.357,0.32,0.29,0.266,0.252,0.247,0.252,0.268,0.294,0.33,0.375,0.428,0.487,0.549,0.614,0.678,0.74,0.798,0.848,0.889,0.92,0.939,0.946,0.94,0.921,0.89,0.848,0.797,0.739,0.675,0.609,0.542,0.479,0.42,0.369,0.327,0.296,0.277,0.271,0.278,0.296,0.327,0.366,0.414,0.468,0.525,0.583,0.64,0.692,0.739,0.778,0.807,0.826,0.834,0.618,0.644,0.672,0.701,0.728,0.751,0.769,0.779,0.781,0.773,0.755,0.727,0.69,0.645,0.594,0.538,0.48,0.424,0.372,0.326,0.289,0.263,0.251,0.252,0.268,0.298,0.342,0.397,0.462,0.534,0.61,0.687,0.762,0.83,0.89,0.939,0.974,0.995,1.0,0.989,0.963,0.924,0.873,0.813,0.747,0.677,0.607,0.54,0.478,0.425,0.381,0.349,0.329,0.322,0.326,0.341,0.364,0.395,0.43,0.467,0.503,0.536,0.563,0.583,0.594,0.596,0.587,0.569,0.541,0.506,0.464,0.419,0.373,0.327,0.285,0.248,0.219,0.2,0.191,0.193,0.206,0.231,0.266,0.31,0.361,0.418,0.478,0.538,0.598,0.653,0.704,0.747,0.783,0.809,0.826,0.833,0.831,0.821,0.804,0.781,0.754,0.725,0.694,0.663,0.635,0.609,0.587,0.57,0.557,0.549,0.546,0.546,0.55,0.556,0.564,0.573,0.581,0.589,0.595,0.599,0.601,0.6,0.596,0.591,0.583,0.575,0.566,0.557,0.548,0.541,0.535,0.531,0.53,0.531,0.535,0.54,0.547,0.556,0.564,0.573,0.581,0.588,0.592,0.594,0.593,0.589,0.582,0.572,0.559,0.543,0.526,0.508,0.49,0.472,0.456,0.442,0.431,0.425,0.422,0.425,0.432,0.445,0.462,0.484,0.51,0.539,0.57,0.602,0.634,0.665,0.693,0.717,0.737,0.751,0.758,0.758,0.75,0.735,0.712,0.683,0.647,0.605,0.56,0.512,0.463,0.415,0.369,0.327,0.292,0.264,0.244,0.235,0.236,0.248,0.271,0.304,0.347,0.399,0.457,0.521,0.587,0.654,0.719,0.78,0.835,0.881,0.917,0.941,0.953,0.951,0.936,0.908,0.869,0.819,0.761,0.697,0.63,0.562,0.495,0.434,0.379,0.333,0.298,0.275,0.265,0.268,0.284,0.312,0.35,0.397,0.451,0.509,0.569,0.627,0.682,0.732,0.774,0.806,0.829,0.84,0.621,0.647,0.675,0.703,0.728,0.75,0.766,0.775,0.775,0.765,0.746,0.717,0.679,0.633,0.581,0.526,0.469,0.414,0.364,0.32,0.286,0.264,0.255,0.26,0.279,0.312,0.359,0.416,0.483,0.556,0.633,0.709,0.782,0.848,0.905,0.95,0.982,0.998,0.998,0.983,0.953,0.909,0.854,0.791,0.722,0.65,0.579,0.512,0.451,0.398,0.356,0.327,0.309,0.305,0.312,0.329,0.356,0.389,0.425,0.464,0.501,0.534,0.561,0.58,0.59,0.59,0.58,0.56,0.531,0.494,0.452,0.406,0.36,0.314,0.272,0.237,0.209,0.191,0.183,0.187,0.202,0.227,0.263,0.308,0.359,0.415,0.473,0.532,0.589,0.642,0.69,0.73,0.762,0.785,0.799,0.805,0.801,0.791,0.774,0.752,0.727,0.7,0.673,0.647,0.624,0.604,0.588,0.577,0.57,0.567,0.569,0.573,0.58,0.589,0.598,0.607,0.614,0.62,0.622,0.622,0.618,0.611,0.602,0.59,0.576,0.561,0.546,0.532,0.519,0.508,0.5,0.495,0.494,0.496,0.501,0.51,0.521,0.534,0.548,0.562,0.576,0.589,0.599,0.607,0.612,0.613,0.61,0.604,0.594,0.581,0.566,0.55,0.532,0.515,0.498,0.484,0.472,0.464,0.46,0.461,0.467,0.478,0.494,0.514,0.539,0.567,0.598,0.63,0.662,0.693,0.721,0.747,0.767,0.782,0.79,0.791,0.784,0.769,0.746,0.716,0.679,0.636,0.589,0.538,0.486,0.434,0.384,0.338,0.298,0.265,0.241,0.226,0.223,0.23,0.25,0.28,0.321,0.371,0.429,0.492,0.56,0.629,0.697,0.761,0.82,0.871,0.912,0.941,0.957,0.96,0.949,0.925,0.888,0.84,0.783,0.72,0.652,0.582,0.513,0.448,0.39,0.34,0.301,0.274,0.26,0.259,0.272,0.298,0.334,0.38,0.434,0.493,0.553,0.614,0.672,0.724,0.769,0.805,0.83,0.845,0.624,0.65,0.677,0.704,0.728,0.749,0.763,0.77,0.769,0.758,0.737,0.707,0.667,0.621,0.569,0.514,0.459,0.405,0.357,0.316,0.285,0.266,0.26,0.268,0.29,0.327,0.376,0.435,0.504,0.578,0.654,0.729,0.801,0.865,0.919,0.96,0.987,0.999,0.995,0.975,0.94,0.892,0.834,0.768,0.696,0.623,0.551,0.484,0.423,0.373,0.333,0.306,0.291,0.29,0.3,0.32,0.349,0.384,0.423,0.463,0.501,0.534,0.561,0.58,0.589,0.588,0.577,0.555,0.525,0.487,0.444,0.398,0.351,0.306,0.265,0.23,0.203,0.186,0.18,0.185,0.201,0.228,0.264,0.308,0.359,0.414,0.47,0.527,0.581,0.631,0.675,0.712,0.741,0.761,0.773,0.776,0.771,0.759,0.743,0.722,0.699,0.675,0.652,0.631,0.613,0.599,0.589,0.583,0.582,0.585,0.592,0.6,0.611,0.622,0.632,0.64,0.646,0.649,0.648,0.643,0.634,0.621,0.606,0.587,0.567,0.547,0.526,0.507,0.49,0.477,0.467,0.461,0.46,0.463,0.471,0.482,0.497,0.515,0.534,0.555,0.574,0.593,0.61,0.623,0.633,0.639,0.641,0.638,0.631,0.621,0.608,0.592,0.575,0.557,0.54,0.524,0.511,0.501,0.496,0.495,0.499,0.508,0.522,0.542,0.565,0.593,0.623,0.654,0.687,0.718,0.748,0.774,0.796,0.812,0.821,0.823,0.817,0.803,0.781,0.75,0.713,0.669,0.62,0.568,0.513,0.458,0.404,0.353,0.308,0.27,0.241,0.222,0.213,0.216,0.231,0.258,0.296,0.344,0.4,0.464,0.532,0.603,0.673,0.741,0.803,0.858,0.904,0.938,0.959,0.966,0.96,0.939,0.906,0.86,0.805,0.742,0.673,0.602,0.531,0.464,0.402,0.348,0.305,0.274,0.256,0.252,0.262,0.285,0.319,0.364,0.417,0.476,0.538,0.6,0.66,0.715,0.763,0.802,0.831,0.848,0.627,0.652,0.678,0.704,0.728,0.747,0.76,0.766,0.763,0.75,0.728,0.696,0.657,0.61,0.558,0.504,0.449,0.397,0.351,0.312,0.284,0.268,0.265,0.277,0.302,0.341,0.393,0.454,0.524,0.598,0.674,0.749,0.818,0.88,0.931,0.968,0.991,0.998,0.989,0.965,0.926,0.875,0.813,0.744,0.67,0.596,0.524,0.456,0.397,0.348,0.311,0.286,0.275,0.276,0.29,0.313,0.345,0.383,0.424,0.465,0.504,0.538,0.565,0.583,0.591,0.589,0.577,0.554,0.522,0.484,0.44,0.394,0.347,0.302,0.261,0.227,0.202,0.186,0.182,0.188,0.205,0.232,0.268,0.312,0.362,0.415,0.47,0.524,0.575,0.621,0.662,0.695,0.72,0.737,0.745,0.746,0.74,0.728,0.711,0.692,0.671,0.65,0.631,0.615,0.602,0.594,0.59,0.59,0.595,0.604,0.615,0.627,0.641,0.653,0.664,0.672,0.676,0.676,0.672,0.662,0.648,0.63,0.608,0.583,0.557,0.531,0.505,0.482,0.462,0.445,0.434,0.427,0.427,0.432,0.442,0.458,0.477,0.5,0.525,0.551,0.577,0.601,0.623,0.642,0.657,0.668,0.673,0.674,0.67,0.661,0.649,0.634,0.617,0.598,0.58,0.563,0.548,0.536,0.528,0.525,0.527,0.535,0.547,0.565,0.588,0.614,0.644,0.675,0.708,0.74,0.771,0.798,0.821,0.839,0.85,0.854,0.849,0.836,0.815,0.786,0.748,0.704,0.654,0.6,0.542,0.484,0.427,0.372,0.323,0.28,0.245,0.221,0.207,0.205,0.216,0.238,0.273,0.318,0.373,0.436,0.504,0.576,0.648,0.719,0.785,0.844,0.894,0.933,0.959,0.971,0.969,0.952,0.922,0.879,0.826,0.763,0.695,0.623,0.55,0.48,0.415,0.358,0.311,0.276,0.254,0.246,0.253,0.272,0.305,0.348,0.401,0.46,0.522,0.586,0.648,0.706,0.757,0.799,0.831,0.851,0.63,0.654,0.68,0.705,0.727,0.745,0.757,0.761,0.757,0.743,0.719,0.687,0.646,0.599,0.548,0.494,0.44,0.39,0.346,0.31,0.284,0.271,0.271,0.286,0.314,0.356,0.41,0.473,0.543,0.618,0.694,0.767,0.834,0.893,0.941,0.975,0.993,0.996,0.983,0.954,0.911,0.856,0.791,0.719,0.644,0.569,0.496,0.43,0.372,0.325,0.29,0.269,0.261,0.265,0.282,0.309,0.344,0.384,0.427,0.47,0.51,0.544,0.571,0.589,0.597,0.594,0.58,0.556,0.524,0.484,0.44,0.393,0.347,0.302,0.262,0.23,0.205,0.191,0.187,0.195,0.212,0.24,0.276,0.319,0.368,0.419,0.471,0.522,0.57,0.613,0.649,0.678,0.699,0.712,0.718,0.716,0.708,0.695,0.679,0.661,0.642,0.625,0.61,0.598,0.591,0.589,0.591,0.597,0.608,0.621,0.637,0.654,0.67,0.684,0.695,0.703,0.705,0.702,0.694,0.68,0.66,0.636,0.608,0.578,0.546,0.514,0.484,0.457,0.433,0.415,0.402,0.396,0.397,0.404,0.417,0.437,0.461,0.488,0.519,0.551,0.582,0.612,0.64,0.664,0.684,0.698,0.707,0.711,0.709,0.702,0.69,0.675,0.657,0.637,0.618,0.599,0.582,0.568,0.557,0.552,0.552,0.557,0.568,0.584,0.605,0.631,0.66,0.692,0.725,0.758,0.79,0.819,0.844,0.863,0.876,0.882,0.88,0.869,0.849,0.82,0.784,0.739,0.689,0.633,0.574,0.513,0.453,0.394,0.34,0.293,0.253,0.223,0.204,0.197,0.203,0.221,0.252,0.295,0.347,0.409,0.477,0.549,0.623,0.696,0.765,0.828,0.882,0.926,0.957,0.973,0.976,0.963,0.937,0.897,0.846,0.784,0.716,0.644,0.57,0.497,0.429,0.369,0.318,0.279,0.253,0.242,0.244,0.261,0.292,0.333,0.385,0.443,0.507,0.572,0.636,0.696,0.75,0.795,0.83,0.853,0.632,0.656,0.681,0.705,0.726,0.743,0.754,0.756,0.75,0.735,0.711,0.677,0.636,0.589,0.538,0.485,0.432,0.384,0.342,0.308,0.285,0.275,0.278,0.295,0.327,0.371,0.426,0.491,0.562,0.637,0.712,0.784,0.849,0.905,0.949,0.979,0.994,0.992,0.975,0.942,0.895,0.836,0.769,0.695,0.618,0.542,0.47,0.404,0.348,0.303,0.271,0.253,0.248,0.257,0.277,0.307,0.345,0.388,0.433,0.477,0.518,0.553,0.58,0.598,0.605,0.601,0.586,0.562,0.529,0.489,0.444,0.397,0.351,0.307,0.268,0.236,0.213,0.2,0.197,0.205,0.224,0.252,0.287,0.33,0.376,0.425,0.475,0.522,0.566,0.605,0.637,0.662,0.679,0.688,0.691,0.686,0.677,0.663,0.647,0.63,0.614,0.6,0.589,0.582,0.58,0.584,0.592,0.604,0.62,0.639,0.659,0.679,0.698,0.714,0.725,0.732,0.733,0.727,0.714,0.696,0.671,0.641,0.608,0.571,0.534,0.497,0.463,0.432,0.406,0.386,0.372,0.367,0.369,0.378,0.395,0.419,0.447,0.48,0.516,0.554,0.591,0.627,0.66,0.688,0.712,0.73,0.742,0.748,0.747,0.741,0.729,0.713,0.695,0.674,0.652,0.631,0.611,0.594,0.582,0.573,0.571,0.574,0.583,0.597,0.617,0.642,0.671,0.703,0.737,0.771,0.804,0.835,0.861,0.883,0.899,0.907,0.907,0.898,0.881,0.854,0.818,0.775,0.724,0.668,0.607,0.544,0.481,0.419,0.361,0.309,0.265,0.229,0.205,0.193,0.194,0.207,0.234,0.273,0.323,0.382,0.45,0.522,0.597,0.672,0.744,0.811,0.869,0.917,0.952,0.974,0.981,0.973,0.95,0.913,0.864,0.805,0.737,0.664,0.589,0.515,0.444,0.381,0.326,0.283,0.254,0.238,0.238,0.251,0.279,0.319,0.369,0.428,0.491,0.557,0.623,0.685,0.742,0.79,0.828,0.854,0.634,0.657,0.682,0.705,0.725,0.741,0.75,0.752,0.744,0.728,0.702,0.668,0.627,0.579,0.528,0.476,0.425,0.378,0.338,0.307,0.287,0.279,0.285,0.305,0.339,0.385,0.443,0.509,0.58,0.655,0.729,0.799,0.863,0.916,0.956,0.983,0.993,0.987,0.965,0.928,0.878,0.816,0.746,0.67,0.592,0.516,0.444,0.38,0.325,0.283,0.254,0.239,0.238,0.251,0.274,0.308,0.349,0.394,0.442,0.488,0.53,0.565,0.593,0.61,0.616,0.612,0.596,0.571,0.537,0.496,0.451,0.405,0.358,0.315,0.277,0.247,0.225,0.213,0.211,0.22,0.239,0.267,0.302,0.343,0.388,0.434,0.481,0.524,0.564,0.598,0.626,0.646,0.659,0.665,0.664,0.657,0.645,0.631,0.615,0.6,0.586,0.575,0.568,0.566,0.57,0.579,0.593,0.611,0.633,0.656,0.681,0.704,0.725,0.742,0.754,0.76,0.758,0.749,0.733,0.71,0.68,0.645,0.605,0.564,0.521,0.48,0.442,0.407,0.379,0.358,0.344,0.34,0.344,0.356,0.376,0.404,0.438,0.476,0.517,0.56,0.603,0.643,0.681,0.714,0.741,0.762,0.777,0.784,0.784,0.778,0.766,0.749,0.729,0.706,0.682,0.658,0.636,0.616,0.6,0.59,0.584,0.585,0.592,0.605,0.624,0.648,0.676,0.708,0.743,0.778,0.812,0.845,0.874,0.899,0.917,0.928,0.931,0.925,0.91,0.885,0.851,0.809,0.759,0.703,0.641,0.577,0.511,0.447,0.385,0.329,0.279,0.239,0.209,0.192,0.187,0.196,0.218,0.253,0.3,0.358,0.424,0.496,0.571,0.648,0.722,0.792,0.854,0.906,0.946,0.973,0.984,0.981,0.962,0.928,0.882,0.824,0.757,0.684,0.609,0.533,0.46,0.393,0.335,0.289,0.255,0.236,0.232,0.242,0.267,0.305,0.354,0.412,0.476,0.543,0.61,0.674,0.733,0.784,0.825,0.854,0.635,0.659,0.682,0.705,0.724,0.739,0.747,0.747,0.738,0.721,0.694,0.659,0.618,0.57,0.52,0.468,0.418,0.373,0.335,0.306,0.289,0.284,0.293,0.315,0.352,0.4,0.459,0.526,0.598,0.672,0.745,0.814,0.875,0.925,0.962,0.985,0.991,0.981,0.955,0.914,0.86,0.795,0.723,0.645,0.567,0.49,0.419,0.356,0.304,0.265,0.239,0.228,0.231,0.247,0.274,0.311,0.355,0.403,0.453,0.501,0.544,0.58,0.607,0.625,0.63,0.625,0.609,0.583,0.548,0.507,0.462,0.415,0.37,0.327,0.29,0.261,0.24,0.23,0.229,0.239,0.258,0.285,0.32,0.359,0.402,0.446,0.488,0.528,0.564,0.593,0.616,0.632,0.64,0.642,0.637,0.628,0.615,0.599,0.584,0.57,0.558,0.55,0.548,0.551,0.56,0.574,0.594,0.618,0.645,0.673,0.701,0.728,0.751,0.769,0.781,0.785,0.782,0.77,0.75,0.722,0.687,0.646,0.602,0.555,0.508,0.463,0.421,0.384,0.354,0.332,0.319,0.315,0.321,0.337,0.361,0.393,0.431,0.475,0.521,0.569,0.617,0.662,0.704,0.741,0.771,0.795,0.811,0.819,0.819,0.813,0.8,0.781,0.759,0.734,0.707,0.68,0.655,0.632,0.613,0.6,0.592,0.59,0.595,0.606,0.624,0.647,0.675,0.707,0.742,0.779,0.815,0.85,0.882,0.909,0.93,0.944,0.951,0.948,0.936,0.914,0.882,0.842,0.793,0.737,0.676,0.611,0.543,0.476,0.411,0.351,0.297,0.252,0.217,0.194,0.184,0.188,0.206,0.236,0.28,0.335,0.399,0.47,0.546,0.623,0.7,0.772,0.838,0.894,0.938,0.969,0.986,0.986,0.972,0.942,0.898,0.842,0.777,0.704,0.628,0.551,0.476,0.406,0.345,0.295,0.258,0.235,0.227,0.234,0.257,0.292,0.34,0.397,0.461,0.528,0.597,0.663,0.724,0.778,0.822,0.854,0.637,0.66,0.683,0.705,0.723,0.736,0.743,0.742,0.733,0.714,0.687,0.651,0.609,0.562,0.511,0.461,0.412,0.369,0.333,0.306,0.291,0.289,0.3,0.326,0.364,0.414,0.475,0.542,0.615,0.689,0.761,0.827,0.886,0.933,0.967,0.985,0.988,0.974,0.944,0.899,0.842,0.774,0.7,0.621,0.542,0.466,0.396,0.335,0.285,0.248,0.226,0.219,0.225,0.245,0.276,0.317,0.364,0.415,0.467,0.516,0.56,0.597,0.625,0.641,0.647,0.641,0.624,0.597,0.562,0.521,0.476,0.429,0.384,0.343,0.307,0.279,0.259,0.25,0.25,0.26,0.28,0.307,0.34,0.378,0.418,0.459,0.498,0.534,0.565,0.59,0.608,0.619,0.623,0.62,0.612,0.6,0.585,0.569,0.553,0.54,0.531,0.527,0.528,0.536,0.55,0.57,0.595,0.624,0.656,0.689,0.721,0.751,0.776,0.795,0.806,0.809,0.804,0.788,0.764,0.732,0.692,0.647,0.597,0.546,0.495,0.445,0.4,0.361,0.33,0.307,0.295,0.293,0.302,0.32,0.349,0.385,0.428,0.476,0.528,0.581,0.633,0.683,0.728,0.768,0.801,0.826,0.843,0.851,0.852,0.844,0.83,0.809,0.784,0.756,0.726,0.696,0.668,0.642,0.62,0.603,0.593,0.588,0.591,0.601,0.617,0.64,0.668,0.7,0.736,0.773,0.812,0.849,0.883,0.913,0.938,0.956,0.965,0.966,0.958,0.939,0.91,0.872,0.825,0.771,0.71,0.644,0.576,0.506,0.439,0.375,0.317,0.267,0.227,0.199,0.184,0.183,0.195,0.222,0.262,0.313,0.375,0.445,0.52,0.599,0.677,0.752,0.82,0.88,0.929,0.965,0.985,0.991,0.98,0.954,0.913,0.86,0.796,0.724,0.647,0.569,0.492,0.42,0.356,0.302,0.261,0.235,0.223,0.228,0.247,0.28,0.326,0.382,0.446,0.514,0.583,0.651,0.715,0.771,0.818,0.853,0.638,0.661,0.683,0.704,0.722,0.734,0.74,0.738,0.727,0.707,0.679,0.643,0.601,0.553,0.504,0.454,0.407,0.365,0.331,0.307,0.294,0.294,0.308,0.336,0.376,0.428,0.49,0.558,0.631,0.704,0.775,0.84,0.895,0.94,0.97,0.985,0.983,0.966,0.932,0.884,0.823,0.753,0.677,0.597,0.518,0.442,0.373,0.314,0.267,0.234,0.215,0.211,0.222,0.246,0.281,0.325,0.375,0.429,0.483,0.534,0.579,0.616,0.644,0.661,0.666,0.659,0.641,0.614,0.578,0.536,0.491,0.446,0.401,0.36,0.326,0.299,0.281,0.272,0.274,0.285,0.304,0.331,0.363,0.399,0.437,0.475,0.51,0.542,0.568,0.588,0.601,0.607,0.606,0.599,0.588,0.573,0.556,0.539,0.524,0.512,0.505,0.504,0.509,0.521,0.54,0.566,0.596,0.631,0.667,0.704,0.74,0.772,0.799,0.818,0.83,0.832,0.823,0.805,0.777,0.741,0.696,0.646,0.592,0.536,0.481,0.428,0.38,0.34,0.307,0.285,0.274,0.274,0.285,0.307,0.339,0.38,0.428,0.481,0.537,0.594,0.651,0.704,0.753,0.795,0.83,0.856,0.873,0.882,0.881,0.872,0.855,0.832,0.805,0.773,0.74,0.707,0.675,0.646,0.621,0.601,0.587,0.581,0.581,0.589,0.604,0.626,0.654,0.686,0.723,0.762,0.802,0.841,0.878,0.912,0.94,0.962,0.975,0.98,0.975,0.96,0.935,0.9,0.856,0.803,0.743,0.677,0.608,0.538,0.468,0.401,0.339,0.285,0.241,0.207,0.187,0.18,0.188,0.21,0.246,0.294,0.353,0.421,0.496,0.574,0.654,0.731,0.802,0.866,0.919,0.958,0.984,0.993,0.987,0.964,0.927,0.876,0.814,0.743,0.666,0.587,0.508,0.434,0.367,0.31,0.266,0.236,0.221,0.222,0.238,0.269,0.313,0.368,0.431,0.499,0.57,0.64,0.705,0.764,0.813,0.851,0.64,0.661,0.683,0.703,0.72,0.731,0.736,0.733,0.721,0.701,0.672,0.635,0.593,0.546,0.497,0.448,0.402,0.362,0.33,0.308,0.297,0.3,0.316,0.346,0.388,0.442,0.505,0.573,0.646,0.718,0.788,0.851,0.904,0.945,0.972,0.983,0.978,0.956,0.919,0.868,0.805,0.733,0.654,0.574,0.494,0.419,0.352,0.295,0.251,0.221,0.206,0.206,0.221,0.249,0.288,0.335,0.389,0.445,0.501,0.553,0.6,0.637,0.665,0.682,0.686,0.679,0.66,0.632,0.596,0.554,0.509,0.464,0.42,0.381,0.347,0.322,0.305,0.298,0.3,0.312,0.331,0.357,0.389,0.423,0.458,0.493,0.524,0.551,0.573,0.587,0.595,0.596,0.591,0.58,0.564,0.547,0.528,0.51,0.495,0.485,0.48,0.482,0.491,0.507,0.531,0.562,0.597,0.637,0.678,0.719,0.758,0.792,0.821,0.841,0.851,0.852,0.841,0.82,0.788,0.747,0.699,0.644,0.586,0.526,0.467,0.411,0.362,0.32,0.287,0.265,0.255,0.257,0.272,0.297,0.333,0.378,0.43,0.488,0.548,0.61,0.67,0.726,0.777,0.821,0.857,0.884,0.901,0.908,0.906,0.895,0.876,0.851,0.82,0.785,0.748,0.711,0.676,0.643,0.615,0.592,0.576,0.567,0.565,0.571,0.585,0.606,0.634,0.667,0.704,0.744,0.786,0.828,0.868,0.905,0.936,0.962,0.98,0.989,0.988,0.977,0.956,0.924,0.883,0.832,0.774,0.709,0.64,0.569,0.497,0.428,0.363,0.305,0.256,0.218,0.193,0.181,0.183,0.2,0.232,0.276,0.333,0.399,0.472,0.551,0.631,0.709,0.784,0.85,0.907,0.951,0.98,0.994,0.992,0.973,0.939,0.891,0.831,0.761,0.684,0.605,0.525,0.449,0.379,0.319,0.271,0.238,0.219,0.217,0.23,0.259,0.301,0.354,0.417,0.485,0.557,0.628,0.695,0.756,0.808,0.849,0.641,0.662,0.683,0.703,0.718,0.729,0.733,0.728,0.716,0.695,0.665,0.628,0.585,0.539,0.49,0.442,0.398,0.359,0.329,0.309,0.301,0.306,0.324,0.356,0.4,0.455,0.519,0.588,0.66,0.732,0.8,0.861,0.911,0.95,0.973,0.981,0.972,0.947,0.906,0.852,0.786,0.712,0.632,0.551,0.472,0.398,0.333,0.278,0.237,0.21,0.199,0.203,0.222,0.254,0.297,0.348,0.404,0.463,0.521,0.575,0.622,0.66,0.688,0.704,0.708,0.7,0.68,0.652,0.615,0.573,0.529,0.484,0.441,0.402,0.37,0.346,0.331,0.325,0.328,0.34,0.36,0.386,0.416,0.448,0.481,0.512,0.539,0.562,0.578,0.588,0.591,0.587,0.576,0.561,0.542,0.522,0.501,0.483,0.468,0.458,0.456,0.46,0.473,0.494,0.523,0.558,0.599,0.643,0.688,0.733,0.775,0.812,0.841,0.861,0.871,0.87,0.857,0.833,0.798,0.753,0.7,0.641,0.579,0.515,0.453,0.395,0.344,0.301,0.268,0.247,0.239,0.244,0.261,0.29,0.33,0.379,0.435,0.497,0.561,0.626,0.689,0.748,0.801,0.847,0.883,0.91,0.926,0.932,0.928,0.914,0.892,0.863,0.829,0.791,0.751,0.71,0.671,0.635,0.603,0.577,0.558,0.547,0.543,0.548,0.561,0.581,0.608,0.641,0.68,0.721,0.765,0.809,0.852,0.892,0.927,0.956,0.979,0.992,0.996,0.989,0.972,0.945,0.907,0.859,0.803,0.74,0.672,0.6,0.527,0.456,0.388,0.327,0.274,0.231,0.201,0.184,0.181,0.193,0.22,0.261,0.314,0.378,0.45,0.528,0.608,0.688,0.764,0.834,0.894,0.942,0.975,0.994,0.995,0.981,0.95,0.905,0.847,0.778,0.702,0.622,0.542,0.464,0.392,0.329,0.278,0.24,0.218,0.213,0.223,0.249,0.289,0.341,0.403,0.472,0.544,0.616,0.685,0.748,0.803,0.846,0.641,0.662,0.683,0.702,0.717,0.726,0.729,0.724,0.711,0.689,0.658,0.621,0.578,0.532,0.484,0.437,0.394,0.357,0.329,0.311,0.305,0.312,0.333,0.366,0.412,0.468,0.532,0.602,0.674,0.745,0.811,0.87,0.918,0.953,0.973,0.978,0.965,0.936,0.893,0.835,0.767,0.692,0.611,0.53,0.451,0.378,0.314,0.262,0.224,0.201,0.194,0.202,0.225,0.261,0.308,0.362,0.421,0.483,0.542,0.597,0.645,0.684,0.712,0.727,0.73,0.721,0.702,0.672,0.635,0.593,0.549,0.505,0.463,0.425,0.395,0.372,0.358,0.354,0.358,0.371,0.391,0.416,0.445,0.475,0.505,0.533,0.556,0.574,0.586,0.59,0.588,0.579,0.564,0.544,0.522,0.499,0.476,0.457,0.442,0.434,0.433,0.44,0.457,0.482,0.515,0.555,0.6,0.649,0.698,0.746,0.791,0.829,0.86,0.88,0.889,0.887,0.871,0.844,0.805,0.757,0.7,0.637,0.571,0.504,0.44,0.38,0.327,0.284,0.252,0.232,0.225,0.232,0.253,0.285,0.329,0.382,0.443,0.508,0.576,0.644,0.709,0.77,0.824,0.87,0.907,0.932,0.947,0.951,0.945,0.928,0.903,0.871,0.833,0.791,0.747,0.703,0.66,0.621,0.586,0.558,0.536,0.522,0.517,0.52,0.532,0.551,0.578,0.611,0.65,0.693,0.738,0.784,0.83,0.873,0.912,0.946,0.972,0.99,0.999,0.997,0.985,0.961,0.927,0.883,0.83,0.769,0.702,0.63,0.557,0.484,0.414,0.35,0.293,0.246,0.211,0.189,0.181,0.189,0.211,0.248,0.297,0.359,0.429,0.506,0.586,0.667,0.745,0.817,0.88,0.932,0.97,0.992,0.998,0.987,0.96,0.917,0.862,0.795,0.72,0.64,0.558,0.478,0.404,0.339,0.284,0.244,0.218,0.209,0.217,0.24,0.278,0.329,0.39,0.458,0.531,0.604,0.675,0.74,0.797,0.843,0.642,0.663,0.683,0.701,0.715,0.724,0.726,0.72,0.706,0.683,0.652,0.615,0.572,0.526,0.478,0.433,0.391,0.355,0.329,0.313,0.309,0.318,0.341,0.376,0.423,0.481,0.545,0.615,0.687,0.756,0.821,0.878,0.923,0.956,0.973,0.974,0.958,0.926,0.879,0.819,0.749,0.672,0.59,0.509,0.431,0.359,0.298,0.248,0.214,0.194,0.191,0.203,0.23,0.27,0.32,0.378,0.44,0.504,0.565,0.621,0.67,0.709,0.736,0.751,0.753,0.744,0.723,0.693,0.656,0.614,0.57,0.526,0.485,0.449,0.42,0.398,0.386,0.383,0.389,0.402,0.422,0.447,0.474,0.503,0.53,0.554,0.574,0.588,0.594,0.594,0.586,0.572,0.552,0.529,0.503,0.477,0.453,0.432,0.418,0.41,0.411,0.422,0.441,0.47,0.508,0.552,0.601,0.654,0.707,0.759,0.806,0.846,0.877,0.897,0.906,0.901,0.884,0.853,0.811,0.759,0.699,0.633,0.563,0.494,0.427,0.365,0.312,0.268,0.237,0.218,0.214,0.224,0.247,0.284,0.331,0.388,0.452,0.521,0.591,0.662,0.729,0.791,0.846,0.892,0.928,0.952,0.965,0.967,0.957,0.938,0.909,0.873,0.831,0.786,0.738,0.691,0.645,0.602,0.564,0.533,0.509,0.493,0.486,0.488,0.498,0.517,0.544,0.577,0.617,0.66,0.707,0.755,0.804,0.85,0.892,0.93,0.961,0.983,0.997,1.0,0.992,0.973,0.944,0.903,0.854,0.795,0.73,0.659,0.586,0.513,0.441,0.374,0.314,0.263,0.223,0.196,0.184,0.187,0.204,0.237,0.283,0.341,0.409,0.485,0.565,0.646,0.726,0.8,0.866,0.921,0.963,0.989,0.999,0.992,0.968,0.929,0.876,0.81,0.736,0.656,0.574,0.493,0.417,0.349,0.292,0.248,0.219,0.207,0.211,0.232,0.268,0.317,0.377,0.445,0.518,0.592,0.665,0.732,0.791,0.84,0.643,0.663,0.683,0.7,0.714,0.722,0.723,0.716,0.701,0.677,0.646,0.609,0.566,0.52,0.473,0.428,0.388,0.354,0.329,0.315,0.313,0.324,0.349,0.386,0.434,0.492,0.558,0.628,0.699,0.767,0.83,0.885,0.928,0.957,0.971,0.969,0.95,0.915,0.865,0.803,0.731,0.652,0.57,0.489,0.412,0.342,0.282,0.236,0.205,0.189,0.19,0.206,0.237,0.28,0.334,0.395,0.46,0.526,0.589,0.646,0.695,0.734,0.761,0.775,0.777,0.766,0.744,0.714,0.676,0.634,0.59,0.547,0.507,0.472,0.444,0.425,0.415,0.413,0.42,0.434,0.454,0.478,0.505,0.532,0.556,0.577,0.593,0.602,0.604,0.598,0.586,0.567,0.542,0.515,0.485,0.457,0.43,0.409,0.394,0.388,0.391,0.404,0.427,0.46,0.501,0.549,0.603,0.659,0.716,0.77,0.819,0.861,0.893,0.913,0.92,0.914,0.894,0.861,0.816,0.76,0.697,0.627,0.555,0.483,0.414,0.352,0.298,0.254,0.224,0.207,0.205,0.218,0.244,0.284,0.335,0.395,0.463,0.534,0.608,0.68,0.749,0.812,0.866,0.912,0.946,0.969,0.979,0.978,0.965,0.942,0.91,0.87,0.825,0.776,0.725,0.674,0.624,0.579,0.539,0.505,0.479,0.461,0.452,0.453,0.462,0.48,0.507,0.54,0.58,0.624,0.673,0.723,0.773,0.822,0.868,0.909,0.944,0.972,0.99,0.998,0.995,0.981,0.956,0.92,0.874,0.819,0.756,0.687,0.614,0.54,0.467,0.398,0.335,0.281,0.237,0.206,0.189,0.186,0.199,0.228,0.27,0.325,0.391,0.465,0.544,0.626,0.706,0.782,0.851,0.909,0.955,0.985,0.999,0.996,0.975,0.939,0.888,0.825,0.752,0.673,0.59,0.508,0.43,0.359,0.299,0.253,0.221,0.205,0.207,0.225,0.258,0.306,0.365,0.432,0.505,0.58,0.654,0.723,0.785,0.836,0.643,0.663,0.683,0.699,0.712,0.719,0.72,0.712,0.696,0.672,0.641,0.603,0.56,0.514,0.468,0.424,0.385,0.353,0.329,0.317,0.317,0.33,0.356,0.395,0.445,0.504,0.57,0.639,0.71,0.777,0.839,0.891,0.932,0.958,0.969,0.964,0.942,0.904,0.852,0.787,0.713,0.634,0.551,0.47,0.394,0.326,0.269,0.225,0.197,0.185,0.19,0.21,0.245,0.292,0.35,0.413,0.481,0.548,0.613,0.671,0.721,0.759,0.785,0.799,0.799,0.788,0.765,0.734,0.695,0.653,0.609,0.567,0.528,0.495,0.469,0.451,0.443,0.443,0.451,0.466,0.486,0.51,0.536,0.561,0.583,0.601,0.612,0.617,0.614,0.604,0.586,0.562,0.534,0.502,0.469,0.438,0.41,0.388,0.373,0.367,0.372,0.387,0.413,0.45,0.495,0.547,0.604,0.664,0.724,0.781,0.832,0.875,0.907,0.927,0.933,0.925,0.903,0.867,0.819,0.76,0.694,0.621,0.547,0.473,0.402,0.339,0.285,0.242,0.213,0.198,0.199,0.214,0.244,0.287,0.341,0.404,0.475,0.549,0.624,0.698,0.767,0.83,0.885,0.929,0.961,0.981,0.989,0.985,0.969,0.942,0.906,0.863,0.814,0.761,0.707,0.653,0.601,0.553,0.51,0.474,0.446,0.427,0.417,0.416,0.424,0.442,0.468,0.501,0.541,0.586,0.635,0.687,0.74,0.791,0.84,0.885,0.924,0.955,0.978,0.991,0.994,0.985,0.965,0.933,0.891,0.839,0.779,0.712,0.641,0.567,0.494,0.423,0.357,0.3,0.252,0.217,0.195,0.188,0.197,0.22,0.259,0.31,0.374,0.446,0.524,0.606,0.687,0.765,0.836,0.897,0.946,0.98,0.997,0.998,0.982,0.948,0.9,0.839,0.767,0.688,0.605,0.522,0.443,0.37,0.308,0.258,0.223,0.205,0.203,0.218,0.25,0.295,0.353,0.42,0.493,0.569,0.644,0.715,0.778,0.831,0.644,0.664,0.682,0.699,0.711,0.717,0.717,0.708,0.692,0.667,0.635,0.597,0.555,0.509,0.464,0.421,0.383,0.352,0.33,0.319,0.321,0.336,0.364,0.404,0.455,0.515,0.581,0.65,0.72,0.787,0.847,0.897,0.935,0.959,0.967,0.958,0.933,0.893,0.838,0.772,0.696,0.616,0.533,0.453,0.377,0.311,0.256,0.216,0.191,0.183,0.191,0.216,0.254,0.305,0.366,0.433,0.503,0.572,0.637,0.696,0.746,0.784,0.81,0.822,0.821,0.808,0.785,0.752,0.713,0.671,0.628,0.586,0.548,0.516,0.492,0.477,0.47,0.472,0.481,0.497,0.518,0.542,0.567,0.59,0.61,0.624,0.632,0.633,0.626,0.61,0.588,0.559,0.526,0.49,0.454,0.42,0.391,0.368,0.353,0.348,0.355,0.372,0.401,0.441,0.489,0.545,0.606,0.669,0.732,0.791,0.844,0.888,0.92,0.939,0.945,0.935,0.91,0.872,0.821,0.759,0.69,0.615,0.538,0.463,0.391,0.327,0.273,0.232,0.204,0.191,0.194,0.212,0.245,0.291,0.349,0.415,0.488,0.564,0.641,0.715,0.785,0.848,0.901,0.943,0.973,0.991,0.996,0.988,0.968,0.938,0.898,0.851,0.799,0.743,0.685,0.628,0.574,0.524,0.479,0.441,0.412,0.391,0.38,0.378,0.386,0.402,0.428,0.461,0.501,0.547,0.597,0.649,0.704,0.757,0.809,0.857,0.9,0.935,0.963,0.981,0.988,0.985,0.969,0.943,0.905,0.857,0.8,0.736,0.666,0.593,0.519,0.447,0.38,0.32,0.269,0.229,0.203,0.192,0.196,0.215,0.25,0.298,0.358,0.428,0.505,0.587,0.669,0.748,0.821,0.885,0.936,0.974,0.995,0.999,0.986,0.957,0.911,0.852,0.782,0.703,0.62,0.537,0.456,0.381,0.316,0.264,0.226,0.204,0.2,0.213,0.242,0.286,0.342,0.408,0.481,0.558,0.634,0.706,0.771,0.827,0.645,0.664,0.682,0.698,0.709,0.715,0.714,0.705,0.688,0.663,0.63,0.592,0.549,0.505,0.46,0.418,0.381,0.351,0.331,0.322,0.325,0.342,0.371,0.413,0.465,0.525,0.592,0.661,0.73,0.795,0.853,0.902,0.938,0.959,0.964,0.953,0.925,0.882,0.825,0.756,0.68,0.599,0.516,0.436,0.362,0.298,0.246,0.208,0.187,0.182,0.194,0.223,0.265,0.319,0.383,0.453,0.524,0.595,0.662,0.721,0.771,0.808,0.833,0.844,0.842,0.828,0.803,0.769,0.73,0.687,0.644,0.603,0.566,0.536,0.514,0.5,0.496,0.499,0.511,0.528,0.549,0.573,0.597,0.619,0.636,0.648,0.653,0.649,0.637,0.618,0.59,0.557,0.52,0.48,0.441,0.405,0.373,0.349,0.335,0.331,0.338,0.358,0.39,0.432,0.484,0.544,0.608,0.674,0.739,0.8,0.854,0.899,0.932,0.95,0.954,0.943,0.916,0.875,0.822,0.758,0.686,0.609,0.53,0.453,0.381,0.317,0.263,0.223,0.197,0.186,0.192,0.213,0.248,0.297,0.358,0.426,0.501,0.579,0.657,0.732,0.801,0.863,0.915,0.955,0.982,0.997,0.998,0.987,0.963,0.929,0.886,0.836,0.78,0.721,0.661,0.602,0.545,0.493,0.447,0.408,0.377,0.356,0.343,0.341,0.348,0.364,0.388,0.421,0.461,0.507,0.557,0.611,0.666,0.722,0.776,0.827,0.873,0.912,0.944,0.966,0.979,0.98,0.97,0.948,0.915,0.872,0.818,0.757,0.689,0.617,0.544,0.471,0.402,0.34,0.286,0.243,0.213,0.197,0.197,0.212,0.242,0.287,0.344,0.412,0.488,0.568,0.651,0.731,0.805,0.872,0.926,0.967,0.992,1.0,0.99,0.964,0.921,0.864,0.795,0.718,0.635,0.551,0.468,0.392,0.325,0.27,0.229,0.205,0.198,0.208,0.234,0.276,0.332,0.397,0.47,0.547,0.624,0.697,0.764,0.822,0.645,0.664,0.682,0.697,0.708,0.713,0.711,0.701,0.684,0.658,0.626,0.587,0.545,0.5,0.456,0.415,0.379,0.35,0.332,0.324,0.33,0.348,0.378,0.421,0.474,0.535,0.602,0.671,0.739,0.803,0.86,0.906,0.939,0.958,0.961,0.947,0.916,0.871,0.812,0.742,0.664,0.582,0.5,0.42,0.348,0.286,0.236,0.201,0.183,0.182,0.198,0.23,0.276,0.334,0.401,0.473,0.547,0.619,0.686,0.746,0.795,0.832,0.855,0.865,0.861,0.846,0.819,0.784,0.744,0.701,0.658,0.618,0.582,0.554,0.534,0.522,0.52,0.525,0.538,0.557,0.58,0.604,0.627,0.647,0.663,0.672,0.673,0.666,0.649,0.625,0.594,0.556,0.515,0.471,0.429,0.39,0.357,0.333,0.318,0.315,0.324,0.346,0.38,0.425,0.48,0.542,0.609,0.678,0.746,0.809,0.864,0.909,0.942,0.96,0.963,0.949,0.921,0.878,0.822,0.755,0.681,0.602,0.522,0.444,0.371,0.307,0.254,0.215,0.191,0.183,0.191,0.215,0.253,0.305,0.368,0.439,0.515,0.594,0.672,0.747,0.816,0.876,0.926,0.964,0.988,0.999,0.997,0.982,0.955,0.917,0.871,0.817,0.758,0.697,0.635,0.574,0.515,0.462,0.415,0.375,0.344,0.321,0.308,0.305,0.311,0.327,0.351,0.383,0.423,0.468,0.519,0.573,0.629,0.685,0.741,0.794,0.843,0.886,0.922,0.949,0.966,0.972,0.967,0.95,0.922,0.883,0.833,0.775,0.71,0.64,0.567,0.495,0.425,0.36,0.304,0.257,0.224,0.204,0.199,0.21,0.237,0.278,0.332,0.397,0.471,0.551,0.633,0.714,0.79,0.859,0.916,0.96,0.988,0.999,0.993,0.97,0.929,0.875,0.808,0.731,0.649,0.564,0.481,0.403,0.334,0.276,0.233,0.206,0.196,0.203,0.228,0.268,0.322,0.386,0.459,0.536,0.614,0.689,0.757,0.817,0.645,0.664,0.682,0.696,0.707,0.711,0.709,0.698,0.68,0.654,0.621,0.583,0.54,0.496,0.453,0.412,0.377,0.35,0.333,0.327,0.334,0.353,0.385,0.429,0.483,0.544,0.611,0.68,0.747,0.81,0.865,0.91,0.941,0.957,0.957,0.941,0.908,0.86,0.799,0.728,0.649,0.567,0.485,0.406,0.335,0.275,0.228,0.196,0.181,0.184,0.203,0.239,0.288,0.349,0.419,0.493,0.569,0.642,0.71,0.77,0.818,0.854,0.876,0.884,0.879,0.861,0.833,0.797,0.756,0.712,0.669,0.63,0.596,0.569,0.551,0.542,0.541,0.55,0.565,0.585,0.608,0.633,0.655,0.675,0.688,0.695,0.693,0.682,0.662,0.633,0.597,0.556,0.51,0.464,0.419,0.377,0.343,0.317,0.302,0.3,0.31,0.334,0.371,0.419,0.476,0.541,0.611,0.683,0.752,0.817,0.873,0.918,0.951,0.968,0.97,0.955,0.924,0.879,0.82,0.752,0.675,0.595,0.513,0.435,0.362,0.299,0.247,0.209,0.187,0.181,0.192,0.218,0.26,0.314,0.379,0.451,0.529,0.609,0.687,0.762,0.829,0.888,0.935,0.97,0.991,0.999,0.993,0.974,0.943,0.902,0.852,0.796,0.735,0.671,0.607,0.545,0.486,0.432,0.384,0.344,0.312,0.289,0.276,0.272,0.278,0.293,0.316,0.348,0.386,0.431,0.481,0.535,0.592,0.649,0.706,0.761,0.812,0.858,0.898,0.929,0.95,0.961,0.961,0.949,0.926,0.891,0.846,0.791,0.729,0.661,0.589,0.517,0.446,0.38,0.322,0.273,0.235,0.212,0.203,0.21,0.232,0.27,0.321,0.384,0.456,0.535,0.616,0.698,0.775,0.846,0.905,0.952,0.984,0.998,0.995,0.975,0.937,0.885,0.819,0.744,0.662,0.577,0.493,0.414,0.342,0.283,0.237,0.207,0.194,0.199,0.222,0.26,0.312,0.376,0.449,0.526,0.604,0.68,0.751,0.812,0.646,0.664,0.681,0.696,0.706,0.709,0.706,0.695,0.677,0.65,0.617,0.578,0.536,0.492,0.449,0.41,0.376,0.35,0.334,0.329,0.338,0.358,0.392,0.436,0.491,0.553,0.62,0.688,0.755,0.817,0.87,0.913,0.942,0.956,0.953,0.934,0.899,0.849,0.787,0.714,0.635,0.552,0.47,0.393,0.323,0.265,0.22,0.192,0.18,0.186,0.209,0.248,0.301,0.365,0.437,0.513,0.59,0.665,0.733,0.792,0.84,0.875,0.895,0.902,0.894,0.875,0.845,0.807,0.765,0.721,0.678,0.639,0.606,0.581,0.565,0.558,0.561,0.571,0.589,0.611,0.635,0.66,0.683,0.701,0.713,0.717,0.712,0.698,0.674,0.641,0.601,0.556,0.507,0.457,0.409,0.366,0.33,0.303,0.289,0.287,0.298,0.324,0.362,0.413,0.473,0.541,0.613,0.687,0.758,0.824,0.881,0.927,0.959,0.975,0.975,0.959,0.926,0.879,0.818,0.748,0.67,0.588,0.506,0.426,0.354,0.291,0.24,0.204,0.184,0.181,0.194,0.223,0.267,0.323,0.39,0.465,0.543,0.623,0.701,0.775,0.841,0.897,0.941,0.973,0.991,0.995,0.985,0.963,0.929,0.884,0.832,0.773,0.71,0.645,0.579,0.516,0.457,0.403,0.355,0.315,0.283,0.26,0.247,0.243,0.248,0.262,0.285,0.316,0.354,0.398,0.447,0.5,0.556,0.614,0.672,0.728,0.781,0.829,0.872,0.906,0.932,0.947,0.952,0.945,0.926,0.896,0.855,0.804,0.745,0.68,0.61,0.538,0.467,0.4,0.34,0.288,0.248,0.221,0.208,0.211,0.23,0.264,0.311,0.372,0.442,0.519,0.601,0.682,0.761,0.833,0.895,0.944,0.978,0.996,0.996,0.979,0.944,0.894,0.83,0.756,0.675,0.59,0.505,0.424,0.351,0.289,0.241,0.209,0.194,0.196,0.216,0.253,0.304,0.367,0.439,0.516,0.595,0.672,0.744,0.807,0.646,0.664,0.681,0.695,0.705,0.708,0.704,0.693,0.673,0.647,0.613,0.574,0.532,0.489,0.446,0.407,0.374,0.35,0.335,0.332,0.341,0.363,0.398,0.444,0.499,0.561,0.628,0.696,0.762,0.823,0.875,0.916,0.943,0.954,0.95,0.928,0.891,0.839,0.775,0.702,0.621,0.539,0.457,0.381,0.313,0.256,0.214,0.188,0.18,0.189,0.216,0.258,0.314,0.38,0.454,0.533,0.611,0.686,0.755,0.814,0.861,0.894,0.913,0.917,0.907,0.885,0.853,0.814,0.771,0.726,0.683,0.645,0.613,0.59,0.576,0.572,0.578,0.591,0.61,0.634,0.66,0.686,0.708,0.726,0.736,0.738,0.731,0.713,0.686,0.65,0.606,0.556,0.504,0.451,0.401,0.355,0.318,0.291,0.276,0.275,0.288,0.315,0.355,0.408,0.471,0.541,0.615,0.691,0.763,0.83,0.888,0.934,0.965,0.981,0.98,0.962,0.927,0.878,0.816,0.743,0.664,0.581,0.498,0.419,0.346,0.284,0.235,0.201,0.183,0.182,0.197,0.229,0.275,0.334,0.402,0.478,0.557,0.637,0.715,0.787,0.85,0.904,0.946,0.974,0.988,0.989,0.975,0.949,0.912,0.865,0.809,0.749,0.684,0.618,0.552,0.489,0.43,0.376,0.329,0.289,0.258,0.236,0.223,0.219,0.224,0.237,0.259,0.289,0.325,0.368,0.416,0.468,0.523,0.58,0.638,0.695,0.749,0.8,0.844,0.882,0.911,0.931,0.94,0.938,0.924,0.899,0.862,0.815,0.759,0.697,0.629,0.558,0.487,0.42,0.358,0.304,0.261,0.23,0.214,0.213,0.228,0.259,0.303,0.361,0.429,0.505,0.586,0.667,0.747,0.82,0.884,0.936,0.973,0.994,0.997,0.982,0.95,0.902,0.84,0.768,0.687,0.602,0.516,0.435,0.36,0.296,0.246,0.211,0.193,0.193,0.211,0.246,0.296,0.358,0.429,0.506,0.586,0.664,0.737,0.802,0.647,0.665,0.681,0.695,0.704,0.706,0.702,0.69,0.67,0.643,0.61,0.571,0.529,0.486,0.444,0.405,0.373,0.35,0.336,0.334,0.345,0.368,0.404,0.45,0.506,0.569,0.636,0.703,0.768,0.828,0.879,0.918,0.943,0.953,0.946,0.923,0.883,0.83,0.764,0.689,0.609,0.526,0.445,0.369,0.303,0.249,0.209,0.186,0.181,0.193,0.223,0.268,0.326,0.396,0.472,0.552,0.631,0.707,0.775,0.834,0.879,0.911,0.928,0.93,0.918,0.894,0.859,0.818,0.773,0.728,0.684,0.647,0.616,0.595,0.584,0.583,0.591,0.607,0.629,0.656,0.683,0.709,0.732,0.749,0.759,0.759,0.749,0.728,0.697,0.658,0.61,0.557,0.502,0.446,0.393,0.346,0.307,0.28,0.265,0.264,0.278,0.307,0.349,0.404,0.469,0.541,0.617,0.694,0.768,0.836,0.894,0.94,0.971,0.986,0.984,0.964,0.928,0.877,0.813,0.739,0.658,0.574,0.491,0.411,0.34,0.279,0.231,0.199,0.183,0.184,0.202,0.236,0.284,0.345,0.415,0.491,0.57,0.65,0.726,0.797,0.858,0.909,0.948,0.973,0.983,0.98,0.963,0.934,0.893,0.843,0.786,0.724,0.658,0.592,0.526,0.463,0.405,0.352,0.306,0.268,0.238,0.216,0.204,0.2,0.205,0.218,0.238,0.267,0.302,0.343,0.389,0.44,0.494,0.55,0.607,0.663,0.718,0.77,0.817,0.857,0.89,0.913,0.926,0.929,0.92,0.899,0.866,0.824,0.771,0.711,0.646,0.576,0.506,0.438,0.375,0.32,0.274,0.241,0.221,0.217,0.228,0.255,0.297,0.351,0.417,0.492,0.571,0.653,0.733,0.807,0.873,0.927,0.967,0.991,0.997,0.985,0.955,0.91,0.85,0.778,0.698,0.613,0.527,0.445,0.369,0.303,0.25,0.213,0.193,0.191,0.207,0.24,0.288,0.349,0.42,0.497,0.577,0.656,0.73,0.797,0.647,0.665,0.681,0.694,0.703,0.705,0.7,0.688,0.668,0.64,0.606,0.567,0.525,0.482,0.441,0.403,0.372,0.349,0.337,0.336,0.348,0.373,0.409,0.456,0.513,0.576,0.643,0.71,0.774,0.833,0.882,0.92,0.943,0.951,0.942,0.917,0.876,0.821,0.754,0.678,0.597,0.514,0.434,0.359,0.294,0.242,0.205,0.184,0.182,0.197,0.23,0.278,0.339,0.411,0.489,0.57,0.65,0.726,0.795,0.852,0.896,0.926,0.941,0.94,0.926,0.899,0.862,0.819,0.772,0.726,0.682,0.645,0.616,0.597,0.589,0.591,0.602,0.621,0.646,0.674,0.704,0.731,0.754,0.771,0.779,0.778,0.765,0.742,0.708,0.665,0.615,0.559,0.5,0.442,0.387,0.338,0.298,0.27,0.255,0.255,0.27,0.3,0.344,0.401,0.467,0.541,0.619,0.698,0.773,0.842,0.9,0.946,0.976,0.99,0.986,0.965,0.927,0.874,0.809,0.734,0.652,0.567,0.484,0.405,0.334,0.274,0.228,0.197,0.184,0.187,0.208,0.244,0.294,0.356,0.427,0.504,0.583,0.662,0.737,0.806,0.865,0.913,0.948,0.969,0.976,0.969,0.949,0.916,0.873,0.821,0.763,0.699,0.633,0.567,0.502,0.44,0.383,0.332,0.288,0.251,0.222,0.202,0.19,0.187,0.192,0.204,0.224,0.251,0.284,0.323,0.367,0.416,0.468,0.522,0.578,0.634,0.689,0.741,0.789,0.832,0.867,0.894,0.911,0.917,0.913,0.896,0.868,0.83,0.781,0.724,0.661,0.593,0.524,0.456,0.392,0.335,0.287,0.251,0.229,0.221,0.229,0.252,0.291,0.343,0.407,0.48,0.558,0.639,0.72,0.795,0.863,0.919,0.961,0.987,0.996,0.987,0.96,0.916,0.858,0.788,0.709,0.624,0.538,0.454,0.377,0.309,0.255,0.216,0.193,0.189,0.203,0.234,0.281,0.341,0.411,0.489,0.569,0.649,0.724,0.792,0.648,0.665,0.681,0.694,0.702,0.704,0.699,0.686,0.665,0.637,0.603,0.564,0.522,0.48,0.439,0.402,0.371,0.349,0.338,0.338,0.351,0.377,0.414,0.462,0.519,0.582,0.649,0.716,0.78,0.837,0.886,0.922,0.943,0.949,0.939,0.911,0.869,0.812,0.744,0.668,0.586,0.504,0.424,0.35,0.287,0.236,0.201,0.183,0.183,0.202,0.237,0.288,0.351,0.425,0.505,0.587,0.668,0.745,0.812,0.869,0.912,0.94,0.952,0.949,0.932,0.902,0.863,0.817,0.768,0.72,0.677,0.64,0.612,0.596,0.59,0.595,0.61,0.632,0.66,0.691,0.722,0.751,0.774,0.791,0.798,0.795,0.781,0.755,0.719,0.673,0.619,0.56,0.499,0.438,0.381,0.33,0.29,0.261,0.246,0.246,0.262,0.294,0.339,0.398,0.466,0.542,0.622,0.701,0.778,0.847,0.905,0.95,0.98,0.993,0.988,0.965,0.926,0.872,0.805,0.728,0.646,0.561,0.477,0.398,0.328,0.27,0.226,0.197,0.185,0.191,0.214,0.252,0.304,0.367,0.439,0.516,0.595,0.673,0.747,0.813,0.87,0.914,0.946,0.964,0.967,0.957,0.933,0.898,0.853,0.799,0.739,0.675,0.609,0.544,0.48,0.42,0.365,0.316,0.274,0.239,0.213,0.194,0.184,0.181,0.185,0.197,0.216,0.241,0.272,0.309,0.351,0.397,0.446,0.498,0.552,0.607,0.661,0.713,0.762,0.806,0.844,0.874,0.894,0.905,0.904,0.892,0.868,0.834,0.789,0.735,0.674,0.609,0.541,0.473,0.409,0.35,0.301,0.262,0.237,0.226,0.231,0.251,0.286,0.336,0.397,0.468,0.546,0.627,0.707,0.784,0.852,0.91,0.955,0.983,0.995,0.988,0.964,0.922,0.866,0.797,0.719,0.634,0.548,0.464,0.385,0.316,0.26,0.218,0.194,0.188,0.2,0.229,0.275,0.334,0.403,0.48,0.561,0.641,0.718,0.787,0.648,0.666,0.682,0.694,0.702,0.703,0.697,0.684,0.663,0.635,0.6,0.561,0.519,0.477,0.436,0.4,0.37,0.349,0.339,0.34,0.354,0.38,0.419,0.467,0.525,0.588,0.655,0.722,0.785,0.842,0.888,0.923,0.943,0.947,0.935,0.906,0.862,0.804,0.735,0.658,0.576,0.494,0.414,0.342,0.28,0.231,0.198,0.183,0.185,0.206,0.244,0.297,0.363,0.439,0.52,0.604,0.685,0.761,0.829,0.884,0.925,0.951,0.961,0.955,0.935,0.902,0.86,0.812,0.761,0.712,0.667,0.631,0.605,0.59,0.588,0.596,0.614,0.64,0.671,0.705,0.738,0.768,0.793,0.809,0.816,0.811,0.795,0.767,0.728,0.68,0.623,0.562,0.498,0.435,0.376,0.324,0.282,0.253,0.238,0.239,0.256,0.289,0.336,0.396,0.466,0.543,0.624,0.705,0.782,0.851,0.91,0.955,0.984,0.995,0.989,0.965,0.924,0.869,0.8,0.723,0.64,0.554,0.471,0.393,0.324,0.267,0.224,0.197,0.188,0.196,0.22,0.261,0.314,0.379,0.451,0.528,0.607,0.683,0.755,0.819,0.873,0.914,0.943,0.957,0.957,0.943,0.917,0.879,0.832,0.777,0.716,0.652,0.587,0.523,0.461,0.403,0.351,0.304,0.265,0.233,0.209,0.192,0.183,0.181,0.186,0.197,0.215,0.238,0.267,0.301,0.34,0.383,0.429,0.479,0.53,0.583,0.636,0.688,0.737,0.781,0.821,0.853,0.876,0.89,0.894,0.886,0.866,0.836,0.794,0.744,0.686,0.622,0.556,0.489,0.424,0.365,0.314,0.273,0.245,0.231,0.233,0.25,0.283,0.33,0.389,0.458,0.535,0.615,0.695,0.772,0.842,0.902,0.949,0.979,0.993,0.989,0.967,0.928,0.873,0.805,0.728,0.644,0.557,0.472,0.393,0.322,0.264,0.221,0.195,0.187,0.197,0.225,0.269,0.327,0.396,0.473,0.553,0.634,0.712,0.782,0.649,0.666,0.682,0.694,0.701,0.702,0.696,0.682,0.661,0.632,0.598,0.559,0.517,0.475,0.434,0.398,0.369,0.349,0.34,0.342,0.357,0.384,0.423,0.472,0.53,0.594,0.66,0.727,0.789,0.845,0.891,0.924,0.943,0.946,0.932,0.902,0.856,0.797,0.727,0.649,0.567,0.485,0.406,0.334,0.274,0.227,0.196,0.183,0.188,0.211,0.251,0.307,0.374,0.451,0.534,0.618,0.701,0.777,0.843,0.897,0.937,0.961,0.968,0.959,0.936,0.9,0.855,0.804,0.751,0.699,0.654,0.618,0.594,0.582,0.582,0.594,0.616,0.646,0.68,0.716,0.752,0.783,0.809,0.825,0.831,0.826,0.808,0.778,0.737,0.686,0.627,0.563,0.497,0.432,0.371,0.318,0.276,0.246,0.231,0.233,0.251,0.284,0.333,0.394,0.466,0.545,0.627,0.708,0.786,0.855,0.914,0.958,0.987,0.997,0.99,0.964,0.922,0.865,0.796,0.717,0.634,0.548,0.465,0.387,0.319,0.264,0.223,0.198,0.191,0.201,0.228,0.269,0.324,0.39,0.462,0.539,0.617,0.693,0.762,0.824,0.875,0.913,0.938,0.949,0.946,0.929,0.9,0.86,0.811,0.755,0.694,0.631,0.567,0.504,0.445,0.39,0.341,0.298,0.262,0.233,0.211,0.197,0.189,0.188,0.193,0.204,0.221,0.242,0.268,0.299,0.335,0.374,0.417,0.464,0.512,0.563,0.613,0.664,0.712,0.758,0.798,0.832,0.858,0.875,0.882,0.878,0.862,0.836,0.798,0.751,0.696,0.635,0.57,0.503,0.439,0.379,0.326,0.284,0.254,0.237,0.236,0.251,0.28,0.325,0.382,0.449,0.524,0.604,0.684,0.762,0.833,0.894,0.942,0.975,0.991,0.989,0.969,0.932,0.879,0.813,0.736,0.653,0.566,0.481,0.4,0.329,0.269,0.224,0.196,0.186,0.194,0.221,0.263,0.32,0.389,0.465,0.546,0.628,0.706,0.778,0.65,0.667,0.682,0.694,0.701,0.702,0.695,0.681,0.659,0.63,0.595,0.556,0.514,0.472,0.432,0.397,0.368,0.349,0.34,0.343,0.359,0.387,0.427,0.477,0.535,0.599,0.665,0.731,0.794,0.849,0.893,0.926,0.943,0.944,0.929,0.897,0.85,0.79,0.719,0.641,0.559,0.477,0.398,0.328,0.268,0.223,0.194,0.183,0.19,0.215,0.258,0.315,0.385,0.463,0.547,0.632,0.714,0.79,0.856,0.909,0.947,0.968,0.973,0.962,0.935,0.897,0.848,0.794,0.737,0.684,0.638,0.602,0.579,0.57,0.574,0.59,0.616,0.649,0.687,0.726,0.763,0.797,0.823,0.839,0.845,0.839,0.82,0.788,0.745,0.691,0.63,0.564,0.496,0.429,0.367,0.313,0.27,0.24,0.226,0.228,0.246,0.281,0.331,0.394,0.467,0.546,0.629,0.712,0.79,0.859,0.918,0.961,0.989,0.998,0.99,0.963,0.92,0.861,0.791,0.712,0.628,0.542,0.459,0.383,0.316,0.262,0.222,0.2,0.194,0.206,0.235,0.278,0.334,0.4,0.474,0.55,0.627,0.701,0.769,0.828,0.876,0.911,0.932,0.94,0.933,0.914,0.882,0.84,0.79,0.734,0.673,0.611,0.549,0.489,0.432,0.38,0.335,0.295,0.263,0.238,0.219,0.207,0.202,0.202,0.207,0.217,0.233,0.252,0.276,0.304,0.335,0.371,0.41,0.453,0.498,0.545,0.594,0.643,0.69,0.735,0.776,0.812,0.84,0.86,0.87,0.869,0.857,0.834,0.801,0.757,0.704,0.645,0.582,0.517,0.453,0.392,0.339,0.295,0.262,0.244,0.24,0.251,0.278,0.32,0.375,0.441,0.515,0.594,0.674,0.752,0.824,0.886,0.936,0.971,0.989,0.989,0.971,0.936,0.885,0.82,0.744,0.661,0.575,0.489,0.407,0.334,0.273,0.227,0.197,0.185,0.192,0.217,0.258,0.314,0.382,0.459,0.54,0.622,0.701,0.773,0.65,0.667,0.683,0.694,0.701,0.701,0.694,0.68,0.657,0.628,0.593,0.554,0.512,0.47,0.43,0.395,0.367,0.349,0.341,0.344,0.361,0.39,0.43,0.481,0.539,0.603,0.67,0.736,0.797,0.852,0.896,0.927,0.943,0.943,0.926,0.893,0.845,0.784,0.713,0.634,0.551,0.469,0.392,0.322,0.264,0.22,0.192,0.183,0.192,0.22,0.264,0.323,0.394,0.474,0.559,0.644,0.727,0.802,0.867,0.919,0.955,0.975,0.977,0.963,0.933,0.891,0.839,0.781,0.722,0.666,0.618,0.582,0.561,0.555,0.563,0.584,0.614,0.651,0.692,0.733,0.773,0.808,0.835,0.852,0.857,0.85,0.83,0.796,0.751,0.696,0.633,0.565,0.495,0.426,0.363,0.308,0.265,0.235,0.221,0.223,0.243,0.278,0.329,0.393,0.467,0.548,0.632,0.715,0.793,0.863,0.921,0.964,0.991,0.999,0.989,0.961,0.917,0.857,0.786,0.706,0.622,0.536,0.454,0.378,0.313,0.26,0.222,0.202,0.198,0.212,0.242,0.287,0.344,0.411,0.484,0.56,0.636,0.708,0.774,0.83,0.875,0.907,0.926,0.93,0.921,0.899,0.865,0.822,0.77,0.714,0.654,0.593,0.533,0.476,0.423,0.375,0.333,0.298,0.269,0.248,0.233,0.223,0.22,0.221,0.227,0.237,0.251,0.268,0.289,0.313,0.342,0.373,0.408,0.446,0.488,0.532,0.577,0.624,0.67,0.715,0.756,0.792,0.822,0.844,0.857,0.86,0.851,0.832,0.801,0.761,0.711,0.655,0.593,0.529,0.465,0.405,0.35,0.305,0.271,0.25,0.244,0.253,0.277,0.317,0.37,0.434,0.506,0.584,0.664,0.742,0.815,0.879,0.93,0.967,0.987,0.989,0.973,0.94,0.89,0.826,0.751,0.669,0.582,0.496,0.414,0.34,0.278,0.23,0.198,0.185,0.19,0.214,0.254,0.309,0.376,0.452,0.534,0.616,0.696,0.769,0.651,0.668,0.683,0.695,0.701,0.701,0.694,0.679,0.656,0.627,0.591,0.552,0.51,0.468,0.429,0.394,0.366,0.348,0.341,0.345,0.362,0.392,0.433,0.484,0.543,0.607,0.674,0.74,0.801,0.854,0.898,0.928,0.943,0.942,0.924,0.89,0.841,0.779,0.707,0.627,0.545,0.463,0.386,0.317,0.26,0.217,0.191,0.184,0.194,0.224,0.27,0.33,0.403,0.484,0.569,0.655,0.738,0.812,0.877,0.927,0.962,0.979,0.979,0.962,0.93,0.885,0.829,0.768,0.705,0.646,0.596,0.56,0.541,0.538,0.551,0.576,0.61,0.651,0.695,0.739,0.781,0.817,0.845,0.863,0.868,0.86,0.838,0.804,0.757,0.7,0.635,0.565,0.494,0.424,0.36,0.304,0.26,0.23,0.216,0.219,0.24,0.277,0.329,0.394,0.469,0.55,0.635,0.718,0.797,0.866,0.924,0.966,0.992,1.0,0.989,0.959,0.914,0.853,0.781,0.701,0.616,0.531,0.449,0.374,0.31,0.259,0.223,0.204,0.202,0.218,0.249,0.296,0.354,0.421,0.494,0.57,0.644,0.715,0.778,0.832,0.874,0.903,0.919,0.92,0.908,0.884,0.848,0.803,0.752,0.696,0.637,0.578,0.52,0.466,0.416,0.372,0.335,0.304,0.28,0.262,0.251,0.244,0.243,0.246,0.252,0.262,0.274,0.289,0.307,0.328,0.352,0.38,0.41,0.444,0.482,0.522,0.564,0.608,0.652,0.696,0.737,0.773,0.805,0.829,0.844,0.85,0.844,0.828,0.801,0.764,0.717,0.663,0.603,0.54,0.477,0.416,0.362,0.315,0.279,0.256,0.248,0.255,0.277,0.314,0.365,0.427,0.499,0.576,0.656,0.734,0.807,0.872,0.924,0.963,0.984,0.988,0.974,0.943,0.894,0.832,0.758,0.676,0.589,0.503,0.42,0.345,0.282,0.232,0.2,0.185,0.189,0.211,0.25,0.304,0.371,0.447,0.528,0.611,0.691,0.765,0.652,0.669,0.684,0.695,0.701,0.701,0.693,0.678,0.655,0.625,0.59,0.55,0.508,0.466,0.427,0.393,0.365,0.348,0.341,0.346,0.364,0.394,0.435,0.487,0.546,0.611,0.677,0.743,0.804,0.857,0.899,0.929,0.943,0.941,0.922,0.887,0.837,0.774,0.701,0.622,0.539,0.458,0.381,0.312,0.256,0.215,0.19,0.184,0.196,0.227,0.275,0.337,0.41,0.492,0.578,0.664,0.747,0.821,0.885,0.934,0.967,0.983,0.981,0.961,0.926,0.878,0.819,0.754,0.687,0.625,0.572,0.535,0.518,0.52,0.537,0.567,0.605,0.65,0.697,0.744,0.788,0.825,0.854,0.872,0.877,0.868,0.845,0.809,0.761,0.703,0.636,0.565,0.492,0.422,0.356,0.3,0.256,0.226,0.213,0.216,0.238,0.275,0.328,0.394,0.47,0.553,0.638,0.722,0.8,0.87,0.927,0.968,0.993,1.0,0.988,0.957,0.91,0.849,0.776,0.696,0.611,0.526,0.444,0.37,0.307,0.257,0.223,0.206,0.206,0.223,0.257,0.304,0.363,0.43,0.503,0.578,0.652,0.721,0.782,0.833,0.873,0.899,0.911,0.91,0.895,0.869,0.832,0.786,0.734,0.679,0.621,0.564,0.509,0.459,0.413,0.374,0.341,0.314,0.295,0.281,0.273,0.27,0.271,0.275,0.282,0.291,0.302,0.315,0.33,0.348,0.368,0.391,0.417,0.446,0.479,0.515,0.554,0.595,0.637,0.679,0.719,0.756,0.788,0.814,0.831,0.839,0.837,0.824,0.8,0.765,0.721,0.669,0.611,0.55,0.488,0.427,0.372,0.324,0.287,0.263,0.252,0.257,0.277,0.312,0.361,0.422,0.492,0.568,0.648,0.726,0.799,0.865,0.919,0.959,0.982,0.988,0.975,0.945,0.898,0.837,0.764,0.682,0.596,0.509,0.426,0.35,0.286,0.235,0.201,0.185,0.187,0.208,0.246,0.3,0.366,0.441,0.523,0.606,0.687,0.762,0.653,0.67,0.685,0.696,0.702,0.701,0.693,0.677,0.654,0.624,0.588,0.548,0.506,0.464,0.425,0.391,0.364,0.347,0.341,0.346,0.365,0.395,0.438,0.489,0.549,0.614,0.681,0.746,0.806,0.859,0.901,0.93,0.943,0.94,0.92,0.884,0.834,0.77,0.697,0.617,0.534,0.453,0.376,0.309,0.253,0.213,0.189,0.184,0.198,0.23,0.279,0.342,0.417,0.499,0.586,0.672,0.754,0.828,0.891,0.939,0.971,0.985,0.981,0.959,0.922,0.871,0.809,0.741,0.67,0.603,0.546,0.509,0.494,0.501,0.524,0.558,0.601,0.649,0.699,0.748,0.793,0.832,0.861,0.879,0.884,0.874,0.851,0.814,0.765,0.705,0.637,0.564,0.491,0.419,0.353,0.297,0.253,0.223,0.21,0.214,0.236,0.275,0.329,0.395,0.472,0.555,0.641,0.725,0.803,0.873,0.929,0.97,0.994,1.0,0.986,0.955,0.907,0.845,0.772,0.691,0.606,0.521,0.44,0.367,0.305,0.257,0.224,0.208,0.21,0.229,0.263,0.312,0.371,0.439,0.512,0.586,0.658,0.726,0.785,0.834,0.871,0.894,0.904,0.9,0.883,0.855,0.816,0.77,0.718,0.664,0.608,0.553,0.501,0.454,0.412,0.377,0.349,0.328,0.312,0.303,0.299,0.298,0.302,0.307,0.315,0.324,0.334,0.345,0.357,0.371,0.387,0.405,0.426,0.451,0.479,0.511,0.546,0.584,0.624,0.664,0.703,0.74,0.772,0.799,0.818,0.829,0.829,0.819,0.798,0.766,0.725,0.675,0.619,0.559,0.497,0.437,0.381,0.333,0.295,0.269,0.256,0.259,0.277,0.311,0.358,0.417,0.486,0.562,0.64,0.718,0.792,0.859,0.914,0.955,0.979,0.987,0.976,0.947,0.901,0.841,0.769,0.688,0.602,0.515,0.431,0.355,0.289,0.238,0.202,0.185,0.186,0.206,0.243,0.296,0.361,0.437,0.518,0.601,0.683,0.758,0.654,0.671,0.686,0.697,0.702,0.701,0.693,0.677,0.653,0.623,0.587,0.547,0.505,0.463,0.424,0.39,0.363,0.346,0.34,0.347,0.365,0.397,0.439,0.491,0.551,0.616,0.683,0.748,0.809,0.861,0.903,0.93,0.943,0.939,0.919,0.882,0.831,0.767,0.693,0.613,0.531,0.449,0.373,0.306,0.251,0.211,0.189,0.185,0.2,0.233,0.282,0.346,0.422,0.505,0.592,0.678,0.76,0.834,0.896,0.943,0.974,0.986,0.981,0.958,0.918,0.865,0.8,0.729,0.654,0.582,0.52,0.48,0.47,0.483,0.512,0.551,0.597,0.648,0.7,0.751,0.798,0.837,0.867,0.885,0.889,0.879,0.855,0.817,0.767,0.706,0.637,0.563,0.489,0.417,0.35,0.294,0.25,0.22,0.207,0.212,0.235,0.275,0.329,0.397,0.475,0.558,0.644,0.728,0.807,0.876,0.932,0.972,0.995,0.999,0.985,0.953,0.904,0.841,0.767,0.686,0.601,0.516,0.436,0.364,0.303,0.256,0.225,0.211,0.214,0.234,0.27,0.319,0.379,0.447,0.52,0.593,0.664,0.73,0.787,0.834,0.868,0.889,0.896,0.89,0.871,0.841,0.802,0.755,0.704,0.65,0.596,0.544,0.495,0.452,0.414,0.384,0.36,0.343,0.332,0.327,0.327,0.33,0.335,0.342,0.35,0.359,0.368,0.377,0.386,0.397,0.408,0.422,0.439,0.459,0.483,0.51,0.541,0.576,0.613,0.651,0.689,0.725,0.758,0.786,0.806,0.819,0.821,0.814,0.795,0.766,0.727,0.679,0.625,0.566,0.506,0.446,0.39,0.341,0.302,0.275,0.261,0.262,0.278,0.31,0.355,0.413,0.481,0.556,0.634,0.712,0.786,0.853,0.909,0.951,0.977,0.986,0.976,0.949,0.904,0.845,0.773,0.693,0.607,0.52,0.436,0.359,0.293,0.24,0.203,0.185,0.185,0.204,0.24,0.292,0.357,0.432,0.514,0.597,0.679,0.756,0.655,0.672,0.687,0.698,0.703,0.702,0.693,0.677,0.653,0.622,0.586,0.546,0.503,0.461,0.422,0.388,0.362,0.345,0.34,0.346,0.366,0.397,0.44,0.493,0.553,0.618,0.685,0.751,0.811,0.863,0.904,0.931,0.944,0.939,0.918,0.881,0.829,0.765,0.691,0.61,0.527,0.446,0.37,0.303,0.249,0.21,0.188,0.185,0.201,0.235,0.285,0.35,0.426,0.509,0.596,0.683,0.765,0.838,0.899,0.946,0.976,0.987,0.98,0.956,0.915,0.86,0.794,0.72,0.642,0.566,0.497,0.451,0.448,0.469,0.503,0.546,0.595,0.648,0.702,0.754,0.801,0.841,0.871,0.889,0.893,0.883,0.858,0.819,0.768,0.706,0.636,0.562,0.487,0.414,0.348,0.291,0.247,0.218,0.206,0.211,0.235,0.275,0.331,0.399,0.477,0.561,0.648,0.732,0.81,0.878,0.934,0.973,0.995,0.999,0.984,0.95,0.9,0.837,0.762,0.681,0.596,0.511,0.432,0.36,0.301,0.255,0.225,0.213,0.218,0.239,0.276,0.326,0.387,0.455,0.527,0.6,0.67,0.734,0.789,0.834,0.866,0.884,0.889,0.881,0.86,0.829,0.789,0.742,0.691,0.638,0.586,0.536,0.491,0.451,0.418,0.392,0.373,0.36,0.354,0.353,0.356,0.362,0.37,0.378,0.387,0.396,0.403,0.41,0.417,0.424,0.432,0.442,0.454,0.469,0.488,0.511,0.539,0.57,0.604,0.64,0.676,0.712,0.745,0.773,0.795,0.809,0.814,0.808,0.792,0.765,0.729,0.683,0.63,0.573,0.513,0.454,0.398,0.349,0.309,0.28,0.265,0.264,0.279,0.309,0.353,0.41,0.476,0.55,0.628,0.706,0.781,0.848,0.904,0.947,0.975,0.985,0.976,0.95,0.907,0.848,0.777,0.697,0.612,0.525,0.44,0.363,0.296,0.242,0.205,0.185,0.184,0.202,0.238,0.289,0.354,0.429,0.51,0.594,0.676,0.753,0.656,0.673,0.688,0.699,0.704,0.703,0.694,0.677,0.653,0.622,0.585,0.545,0.502,0.46,0.421,0.387,0.361,0.344,0.339,0.346,0.366,0.398,0.441,0.494,0.555,0.62,0.687,0.752,0.813,0.865,0.905,0.932,0.944,0.939,0.918,0.88,0.828,0.763,0.689,0.608,0.525,0.444,0.368,0.301,0.247,0.209,0.188,0.185,0.201,0.236,0.287,0.352,0.428,0.512,0.599,0.686,0.767,0.84,0.901,0.947,0.976,0.987,0.98,0.954,0.912,0.856,0.789,0.715,0.636,0.557,0.481,0.421,0.435,0.462,0.499,0.544,0.595,0.649,0.704,0.756,0.804,0.844,0.874,0.892,0.896,0.885,0.859,0.819,0.767,0.705,0.634,0.56,0.484,0.411,0.345,0.288,0.244,0.216,0.204,0.211,0.235,0.276,0.332,0.401,0.48,0.565,0.651,0.735,0.813,0.881,0.936,0.975,0.996,0.998,0.982,0.948,0.897,0.833,0.758,0.676,0.591,0.507,0.428,0.357,0.299,0.254,0.226,0.215,0.221,0.244,0.282,0.332,0.394,0.462,0.534,0.606,0.675,0.737,0.791,0.833,0.863,0.88,0.883,0.873,0.85,0.818,0.777,0.73,0.68,0.628,0.578,0.53,0.488,0.452,0.423,0.401,0.386,0.378,0.376,0.379,0.386,0.394,0.405,0.415,0.424,0.432,0.439,0.444,0.448,0.452,0.456,0.462,0.47,0.481,0.495,0.514,0.538,0.565,0.597,0.63,0.665,0.7,0.733,0.761,0.784,0.8,0.806,0.803,0.789,0.764,0.729,0.686,0.635,0.578,0.52,0.461,0.405,0.356,0.315,0.285,0.269,0.267,0.28,0.309,0.352,0.407,0.473,0.546,0.623,0.701,0.776,0.843,0.9,0.944,0.973,0.983,0.976,0.951,0.909,0.851,0.781,0.701,0.616,0.529,0.444,0.366,0.298,0.244,0.206,0.185,0.184,0.201,0.236,0.286,0.351,0.425,0.507,0.591,0.673,0.751,0.657,0.675,0.689,0.7,0.705,0.703,0.694,0.677,0.653,0.622,0.585,0.544,0.501,0.459,0.419,0.386,0.359,0.343,0.338,0.345,0.365,0.397,0.441,0.495,0.555,0.621,0.688,0.754,0.814,0.866,0.907,0.934,0.945,0.94,0.918,0.88,0.828,0.762,0.688,0.607,0.524,0.442,0.366,0.3,0.246,0.208,0.187,0.185,0.202,0.236,0.288,0.353,0.43,0.513,0.601,0.687,0.769,0.841,0.902,0.948,0.976,0.987,0.979,0.953,0.911,0.855,0.788,0.714,0.635,0.558,0.486,0.436,0.439,0.465,0.501,0.546,0.597,0.651,0.706,0.759,0.807,0.846,0.876,0.893,0.896,0.885,0.859,0.819,0.766,0.703,0.632,0.557,0.481,0.408,0.342,0.286,0.242,0.214,0.203,0.21,0.235,0.277,0.334,0.404,0.483,0.568,0.655,0.739,0.816,0.884,0.938,0.976,0.996,0.998,0.981,0.945,0.894,0.829,0.754,0.671,0.587,0.503,0.424,0.355,0.297,0.254,0.226,0.217,0.224,0.248,0.287,0.338,0.4,0.468,0.54,0.611,0.679,0.74,0.792,0.833,0.861,0.876,0.877,0.865,0.842,0.808,0.767,0.72,0.67,0.619,0.571,0.526,0.486,0.454,0.428,0.41,0.4,0.396,0.398,0.405,0.414,0.426,0.438,0.45,0.46,0.468,0.474,0.477,0.479,0.48,0.481,0.482,0.486,0.493,0.504,0.519,0.538,0.563,0.591,0.623,0.656,0.69,0.722,0.751,0.775,0.791,0.799,0.797,0.785,0.762,0.73,0.688,0.638,0.583,0.525,0.467,0.411,0.362,0.32,0.29,0.273,0.27,0.282,0.309,0.35,0.405,0.47,0.542,0.619,0.697,0.771,0.839,0.897,0.942,0.971,0.982,0.976,0.952,0.91,0.853,0.784,0.704,0.619,0.532,0.447,0.369,0.301,0.246,0.207,0.185,0.183,0.199,0.234,0.284,0.348,0.423,0.504,0.588,0.671,0.749,0.659,0.676,0.691,0.701,0.706,0.705,0.695,0.678,0.653,0.622,0.584,0.543,0.5,0.458,0.418,0.384,0.358,0.342,0.337,0.344,0.364,0.397,0.441,0.495,0.556,0.622,0.689,0.755,0.815,0.867,0.908,0.935,0.946,0.941,0.919,0.881,0.828,0.762,0.687,0.606,0.523,0.442,0.366,0.299,0.246,0.208,0.187,0.185,0.201,0.236,0.288,0.353,0.43,0.513,0.601,0.687,0.768,0.841,0.901,0.947,0.975,0.986,0.978,0.952,0.911,0.855,0.79,0.717,0.641,0.568,0.504,0.463,0.457,0.476,0.509,0.552,0.601,0.654,0.709,0.761,0.808,0.848,0.877,0.893,0.896,0.884,0.857,0.817,0.763,0.7,0.629,0.554,0.478,0.405,0.339,0.283,0.24,0.213,0.203,0.211,0.236,0.279,0.337,0.407,0.487,0.572,0.658,0.742,0.82,0.887,0.94,0.977,0.997,0.997,0.979,0.943,0.891,0.825,0.75,0.667,0.582,0.499,0.421,0.352,0.295,0.253,0.227,0.218,0.226,0.251,0.291,0.343,0.405,0.474,0.545,0.616,0.683,0.743,0.794,0.833,0.859,0.872,0.872,0.859,0.834,0.799,0.758,0.711,0.662,0.612,0.565,0.523,0.486,0.456,0.434,0.42,0.413,0.413,0.419,0.429,0.441,0.456,0.47,0.482,0.493,0.501,0.506,0.508,0.508,0.506,0.504,0.502,0.502,0.505,0.512,0.524,0.54,0.562,0.587,0.617,0.649,0.681,0.713,0.742,0.766,0.783,0.793,0.792,0.782,0.761,0.729,0.689,0.641,0.587,0.53,0.472,0.417,0.367,0.325,0.294,0.276,0.272,0.283,0.309,0.35,0.403,0.467,0.539,0.616,0.693,0.768,0.836,0.894,0.939,0.969,0.981,0.976,0.952,0.911,0.855,0.786,0.707,0.622,0.535,0.45,0.371,0.302,0.247,0.207,0.186,0.183,0.198,0.232,0.282,0.346,0.42,0.502,0.586,0.669,0.747,0.66,0.677,0.692,0.703,0.708,0.706,0.696,0.679,0.654,0.622,0.584,0.543,0.499,0.457,0.417,0.383,0.357,0.34,0.335,0.343,0.363,0.396,0.44,0.494,0.556,0.622,0.689,0.755,0.816,0.868,0.909,0.936,0.947,0.942,0.92,0.882,0.829,0.763,0.688,0.607,0.523,0.442,0.366,0.299,0.246,0.207,0.187,0.184,0.201,0.236,0.287,0.352,0.428,0.512,0.599,0.685,0.766,0.839,0.899,0.944,0.973,0.984,0.976,0.952,0.911,0.857,0.793,0.723,0.651,0.583,0.526,0.49,0.48,0.492,0.52,0.56,0.607,0.659,0.712,0.763,0.809,0.848,0.876,0.892,0.894,0.881,0.854,0.813,0.76,0.696,0.625,0.55,0.474,0.402,0.336,0.281,0.239,0.212,0.203,0.212,0.238,0.281,0.34,0.41,0.49,0.575,0.662,0.746,0.823,0.889,0.942,0.979,0.997,0.997,0.978,0.941,0.888,0.822,0.746,0.663,0.578,0.495,0.417,0.349,0.293,0.252,0.227,0.219,0.229,0.254,0.295,0.348,0.41,0.479,0.55,0.62,0.686,0.746,0.795,0.833,0.858,0.87,0.868,0.853,0.827,0.792,0.75,0.703,0.655,0.606,0.561,0.52,0.486,0.459,0.44,0.429,0.425,0.428,0.437,0.45,0.466,0.482,0.498,0.512,0.523,0.531,0.535,0.536,0.534,0.53,0.525,0.521,0.517,0.517,0.521,0.529,0.542,0.561,0.585,0.612,0.643,0.674,0.705,0.734,0.759,0.777,0.787,0.788,0.778,0.759,0.729,0.69,0.643,0.59,0.533,0.476,0.421,0.371,0.329,0.298,0.279,0.274,0.285,0.31,0.349,0.402,0.465,0.537,0.613,0.69,0.765,0.833,0.891,0.937,0.967,0.98,0.975,0.952,0.912,0.856,0.787,0.709,0.624,0.537,0.452,0.373,0.304,0.248,0.208,0.186,0.182,0.198,0.231,0.281,0.344,0.419,0.5,0.584,0.668,0.746,0.661,0.679,0.694,0.705,0.709,0.707,0.698,0.68,0.655,0.622,0.584,0.542,0.499,0.456,0.416,0.381,0.355,0.339,0.334,0.341,0.362,0.394,0.439,0.493,0.555,0.621,0.689,0.756,0.816,0.869,0.91,0.937,0.949,0.943,0.921,0.883,0.83,0.765,0.689,0.608,0.525,0.443,0.367,0.3,0.246,0.207,0.186,0.184,0.2,0.234,0.285,0.35,0.426,0.509,0.596,0.682,0.763,0.835,0.895,0.941,0.97,0.981,0.974,0.951,0.912,0.86,0.799,0.732,0.664,0.601,0.549,0.515,0.502,0.51,0.534,0.57,0.614,0.663,0.714,0.764,0.809,0.846,0.874,0.889,0.89,0.877,0.85,0.808,0.755,0.691,0.62,0.546,0.47,0.399,0.334,0.279,0.238,0.212,0.203,0.213,0.24,0.284,0.343,0.414,0.494,0.579,0.666,0.75,0.826,0.892,0.944,0.98,0.998,0.996,0.976,0.939,0.885,0.819,0.742,0.659,0.574,0.491,0.414,0.346,0.291,0.25,0.226,0.22,0.23,0.257,0.298,0.351,0.414,0.483,0.554,0.624,0.69,0.748,0.797,0.834,0.857,0.868,0.865,0.849,0.822,0.787,0.744,0.697,0.649,0.601,0.557,0.518,0.485,0.461,0.444,0.436,0.435,0.441,0.453,0.468,0.486,0.504,0.522,0.537,0.549,0.557,0.561,0.56,0.557,0.551,0.544,0.537,0.531,0.528,0.529,0.534,0.545,0.561,0.583,0.609,0.638,0.669,0.699,0.728,0.752,0.771,0.782,0.784,0.775,0.757,0.728,0.69,0.644,0.592,0.536,0.48,0.425,0.375,0.333,0.301,0.282,0.276,0.286,0.311,0.349,0.401,0.464,0.535,0.611,0.688,0.762,0.831,0.889,0.935,0.966,0.979,0.975,0.952,0.913,0.857,0.789,0.71,0.625,0.538,0.453,0.374,0.305,0.249,0.208,0.186,0.182,0.197,0.23,0.28,0.343,0.417,0.499,0.583,0.667,0.745,0.663,0.681,0.696,0.706,0.711,0.709,0.699,0.681,0.656,0.623,0.585,0.542,0.498,0.455,0.415,0.38,0.353,0.337,0.332,0.339,0.36,0.393,0.437,0.492,0.554,0.621,0.689,0.755,0.817,0.869,0.911,0.938,0.95,0.945,0.923,0.885,0.832,0.767,0.692,0.61,0.527,0.444,0.368,0.301,0.247,0.208,0.186,0.183,0.199,0.233,0.283,0.347,0.422,0.505,0.591,0.677,0.757,0.83,0.89,0.936,0.965,0.977,0.972,0.95,0.913,0.863,0.805,0.741,0.678,0.619,0.571,0.538,0.524,0.529,0.548,0.58,0.622,0.668,0.717,0.764,0.808,0.844,0.87,0.884,0.885,0.872,0.844,0.803,0.749,0.686,0.615,0.541,0.466,0.395,0.331,0.277,0.237,0.212,0.204,0.215,0.243,0.287,0.346,0.418,0.498,0.584,0.67,0.753,0.829,0.895,0.946,0.981,0.998,0.996,0.975,0.937,0.883,0.815,0.738,0.655,0.57,0.488,0.411,0.343,0.289,0.249,0.226,0.22,0.231,0.259,0.3,0.354,0.418,0.486,0.557,0.627,0.693,0.751,0.798,0.834,0.857,0.866,0.862,0.846,0.819,0.782,0.74,0.693,0.645,0.598,0.554,0.516,0.485,0.462,0.448,0.442,0.443,0.451,0.465,0.483,0.502,0.522,0.541,0.557,0.569,0.577,0.581,0.58,0.575,0.568,0.559,0.55,0.542,0.537,0.535,0.539,0.548,0.562,0.582,0.606,0.634,0.664,0.694,0.723,0.747,0.766,0.778,0.78,0.773,0.755,0.727,0.69,0.645,0.593,0.538,0.482,0.427,0.378,0.336,0.304,0.284,0.278,0.287,0.311,0.35,0.401,0.464,0.534,0.61,0.686,0.761,0.829,0.888,0.934,0.965,0.979,0.975,0.952,0.913,0.858,0.789,0.711,0.626,0.539,0.454,0.375,0.306,0.249,0.209,0.186,0.182,0.197,0.23,0.279,0.342,0.417,0.498,0.583,0.666,0.745,0.664,0.682,0.698,0.708,0.713,0.711,0.701,0.683,0.657,0.624,0.585,0.543,0.498,0.454,0.414,0.379,0.352,0.335,0.33,0.337,0.357,0.39,0.435,0.49,0.552,0.619,0.688,0.755,0.816,0.87,0.912,0.939,0.952,0.947,0.926,0.888,0.835,0.77,0.695,0.613,0.529,0.447,0.37,0.303,0.248,0.208,0.186,0.182,0.197,0.23,0.28,0.343,0.418,0.5,0.585,0.67,0.751,0.823,0.883,0.929,0.96,0.973,0.969,0.948,0.913,0.866,0.811,0.751,0.691,0.636,0.591,0.559,0.544,0.546,0.562,0.591,0.628,0.672,0.718,0.764,0.805,0.84,0.865,0.878,0.879,0.865,0.837,0.795,0.742,0.679,0.609,0.536,0.462,0.392,0.329,0.276,0.236,0.213,0.206,0.217,0.245,0.291,0.35,0.422,0.503,0.588,0.674,0.757,0.833,0.897,0.948,0.982,0.998,0.996,0.974,0.935,0.88,0.812,0.735,0.652,0.567,0.484,0.407,0.341,0.286,0.247,0.225,0.22,0.232,0.26,0.302,0.357,0.42,0.489,0.561,0.63,0.696,0.753,0.8,0.836,0.858,0.866,0.861,0.844,0.816,0.78,0.736,0.69,0.641,0.595,0.552,0.515,0.485,0.463,0.45,0.445,0.448,0.458,0.473,0.492,0.513,0.534,0.554,0.571,0.583,0.592,0.595,0.594,0.589,0.58,0.57,0.56,0.55,0.544,0.541,0.542,0.55,0.563,0.581,0.605,0.632,0.661,0.691,0.719,0.744,0.763,0.774,0.777,0.77,0.753,0.726,0.69,0.645,0.594,0.539,0.483,0.429,0.38,0.337,0.305,0.286,0.28,0.289,0.312,0.35,0.402,0.464,0.534,0.609,0.686,0.76,0.828,0.887,0.933,0.964,0.978,0.974,0.952,0.913,0.858,0.789,0.711,0.627,0.54,0.454,0.375,0.306,0.249,0.209,0.186,0.182,0.196,0.229,0.279,0.342,0.416,0.498,0.582,0.666,0.745,0.666,0.684,0.7,0.711,0.716,0.713,0.703,0.685,0.659,0.625,0.586,0.543,0.498,0.454,0.413,0.377,0.35,0.333,0.327,0.334,0.355,0.388,0.432,0.487,0.55,0.617,0.686,0.754,0.816,0.87,0.912,0.941,0.953,0.949,0.928,0.891,0.839,0.774,0.699,0.617,0.533,0.451,0.373,0.305,0.25,0.209,0.186,0.182,0.195,0.227,0.276,0.338,0.412,0.493,0.578,0.662,0.742,0.814,0.875,0.922,0.953,0.967,0.964,0.946,0.913,0.869,0.816,0.759,0.703,0.651,0.608,0.577,0.561,0.561,0.574,0.599,0.634,0.675,0.718,0.762,0.801,0.834,0.858,0.871,0.87,0.856,0.828,0.787,0.734,0.672,0.603,0.53,0.458,0.389,0.326,0.275,0.236,0.214,0.208,0.22,0.249,0.295,0.355,0.427,0.507,0.592,0.678,0.761,0.836,0.9,0.95,0.983,0.999,0.995,0.973,0.933,0.878,0.81,0.732,0.649,0.563,0.481,0.404,0.338,0.284,0.245,0.223,0.219,0.232,0.26,0.303,0.358,0.422,0.492,0.563,0.633,0.698,0.755,0.802,0.837,0.859,0.867,0.862,0.844,0.816,0.778,0.735,0.688,0.639,0.593,0.55,0.513,0.484,0.463,0.45,0.446,0.45,0.461,0.477,0.497,0.519,0.541,0.561,0.578,0.592,0.6,0.603,0.602,0.597,0.588,0.577,0.566,0.556,0.548,0.544,0.545,0.551,0.564,0.581,0.604,0.631,0.659,0.689,0.717,0.741,0.76,0.772,0.775,0.768,0.752,0.725,0.689,0.645,0.594,0.54,0.484,0.43,0.381,0.339,0.307,0.287,0.281,0.29,0.313,0.351,0.402,0.464,0.534,0.609,0.686,0.76,0.828,0.887,0.933,0.964,0.978,0.973,0.951,0.912,0.857,0.789,0.711,0.626,0.539,0.454,0.375,0.306,0.249,0.209,0.186,0.182,0.196,0.229,0.279,0.342,0.417,0.498,0.583,0.667,0.746,0.668,0.686,0.702,0.713,0.718,0.716,0.705,0.687,0.661,0.627,0.587,0.544,0.499,0.454,0.412,0.376,0.348,0.331,0.325,0.331,0.352,0.384,0.429,0.484,0.547,0.615,0.684,0.752,0.815,0.869,0.913,0.942,0.955,0.952,0.932,0.895,0.843,0.778,0.703,0.622,0.538,0.455,0.377,0.309,0.252,0.211,0.187,0.181,0.194,0.224,0.271,0.333,0.405,0.485,0.569,0.653,0.733,0.804,0.865,0.912,0.944,0.959,0.958,0.942,0.911,0.87,0.82,0.766,0.713,0.663,0.622,0.592,0.576,0.573,0.584,0.606,0.638,0.675,0.717,0.758,0.795,0.827,0.85,0.861,0.861,0.846,0.819,0.778,0.726,0.664,0.596,0.525,0.453,0.385,0.325,0.274,0.237,0.215,0.21,0.223,0.253,0.299,0.36,0.432,0.512,0.597,0.683,0.765,0.839,0.903,0.952,0.985,0.999,0.995,0.972,0.931,0.876,0.807,0.729,0.645,0.56,0.477,0.401,0.335,0.281,0.243,0.222,0.218,0.231,0.26,0.304,0.359,0.424,0.493,0.565,0.635,0.7,0.758,0.805,0.84,0.861,0.869,0.863,0.845,0.816,0.779,0.735,0.687,0.639,0.592,0.549,0.512,0.482,0.461,0.448,0.445,0.449,0.46,0.477,0.497,0.519,0.541,0.562,0.579,0.593,0.602,0.605,0.604,0.599,0.59,0.58,0.568,0.558,0.55,0.546,0.547,0.553,0.564,0.582,0.604,0.63,0.659,0.688,0.716,0.74,0.759,0.77,0.773,0.767,0.75,0.724,0.688,0.644,0.593,0.539,0.484,0.43,0.381,0.339,0.307,0.288,0.282,0.291,0.314,0.352,0.403,0.465,0.535,0.61,0.686,0.76,0.828,0.887,0.933,0.963,0.977,0.973,0.951,0.911,0.856,0.788,0.71,0.625,0.538,0.453,0.374,0.305,0.249,0.208,0.185,0.182,0.197,0.23,0.279,0.343,0.417,0.499,0.584,0.667,0.746,0.669,0.688,0.704,0.715,0.72,0.718,0.708,0.689,0.663,0.629,0.589,0.545,0.499,0.454,0.411,0.375,0.347,0.328,0.322,0.328,0.348,0.381,0.426,0.481,0.544,0.612,0.682,0.75,0.814,0.869,0.913,0.943,0.957,0.955,0.935,0.899,0.848,0.783,0.709,0.627,0.543,0.46,0.382,0.313,0.255,0.213,0.188,0.18,0.192,0.221,0.267,0.326,0.398,0.477,0.559,0.642,0.721,0.793,0.854,0.901,0.934,0.95,0.951,0.936,0.908,0.869,0.822,0.771,0.72,0.673,0.633,0.604,0.587,0.582,0.591,0.61,0.639,0.674,0.713,0.751,0.787,0.817,0.839,0.85,0.849,0.835,0.808,0.768,0.716,0.656,0.589,0.519,0.449,0.383,0.323,0.274,0.238,0.217,0.213,0.227,0.257,0.304,0.365,0.437,0.517,0.602,0.687,0.768,0.842,0.905,0.954,0.986,0.999,0.994,0.971,0.93,0.874,0.804,0.726,0.642,0.557,0.474,0.398,0.332,0.279,0.241,0.22,0.216,0.23,0.26,0.304,0.36,0.424,0.495,0.567,0.637,0.703,0.76,0.807,0.842,0.864,0.871,0.866,0.847,0.818,0.78,0.736,0.688,0.639,0.591,0.548,0.51,0.48,0.458,0.445,0.441,0.444,0.455,0.471,0.491,0.513,0.535,0.556,0.574,0.588,0.597,0.601,0.6,0.596,0.587,0.577,0.567,0.557,0.549,0.546,0.547,0.553,0.565,0.583,0.605,0.631,0.659,0.688,0.716,0.74,0.758,0.77,0.773,0.766,0.749,0.722,0.686,0.642,0.592,0.538,0.483,0.429,0.38,0.339,0.307,0.288,0.283,0.292,0.316,0.354,0.405,0.467,0.537,0.612,0.688,0.762,0.829,0.888,0.933,0.963,0.977,0.972,0.95,0.91,0.855,0.786,0.708,0.624,0.537,0.452,0.373,0.304,0.248,0.208,0.185,0.182,0.197,0.23,0.28,0.344,0.418,0.5,0.585,0.669,0.748,0.671,0.69,0.706,0.718,0.723,0.721,0.711,0.692,0.665,0.631,0.591,0.546,0.5,0.454,0.411,0.374,0.345,0.326,0.319,0.325,0.344,0.377,0.421,0.477,0.54,0.608,0.679,0.748,0.812,0.868,0.913,0.944,0.959,0.958,0.939,0.904,0.853,0.789,0.715,0.634,0.55,0.466,0.387,0.317,0.259,0.216,0.189,0.18,0.19,0.217,0.261,0.32,0.389,0.467,0.548,0.63,0.709,0.78,0.841,0.889,0.922,0.94,0.942,0.929,0.903,0.866,0.822,0.773,0.725,0.679,0.641,0.611,0.594,0.588,0.594,0.612,0.638,0.67,0.706,0.743,0.777,0.806,0.827,0.837,0.836,0.822,0.795,0.756,0.706,0.647,0.582,0.513,0.445,0.38,0.322,0.275,0.24,0.22,0.217,0.231,0.262,0.309,0.37,0.442,0.522,0.607,0.691,0.772,0.845,0.907,0.955,0.986,1.0,0.994,0.97,0.928,0.872,0.802,0.724,0.64,0.554,0.471,0.395,0.329,0.276,0.238,0.218,0.214,0.228,0.258,0.303,0.359,0.424,0.495,0.568,0.639,0.705,0.763,0.81,0.845,0.867,0.875,0.869,0.851,0.822,0.783,0.739,0.69,0.64,0.592,0.547,0.508,0.477,0.454,0.44,0.434,0.437,0.446,0.462,0.481,0.502,0.524,0.544,0.562,0.576,0.586,0.59,0.591,0.587,0.58,0.571,0.561,0.553,0.546,0.544,0.546,0.553,0.566,0.584,0.607,0.633,0.661,0.69,0.717,0.741,0.759,0.77,0.773,0.765,0.748,0.721,0.685,0.64,0.59,0.536,0.481,0.428,0.379,0.338,0.307,0.288,0.283,0.293,0.317,0.356,0.407,0.469,0.539,0.614,0.69,0.764,0.831,0.889,0.934,0.964,0.977,0.972,0.949,0.909,0.853,0.785,0.706,0.621,0.535,0.45,0.371,0.302,0.247,0.207,0.185,0.182,0.197,0.231,0.281,0.345,0.42,0.502,0.587,0.671,0.749,0.673,0.692,0.709,0.721,0.726,0.724,0.714,0.695,0.668,0.633,0.593,0.548,0.501,0.454,0.411,0.373,0.343,0.323,0.316,0.321,0.34,0.372,0.417,0.472,0.535,0.604,0.675,0.745,0.81,0.867,0.913,0.945,0.961,0.961,0.943,0.909,0.859,0.796,0.722,0.641,0.557,0.473,0.394,0.323,0.264,0.219,0.19,0.18,0.188,0.214,0.256,0.312,0.38,0.456,0.536,0.617,0.695,0.766,0.826,0.875,0.909,0.927,0.931,0.92,0.896,0.861,0.819,0.773,0.726,0.682,0.644,0.615,0.597,0.59,0.595,0.609,0.633,0.663,0.697,0.732,0.765,0.792,0.812,0.823,0.822,0.808,0.782,0.744,0.696,0.638,0.575,0.508,0.441,0.378,0.322,0.276,0.242,0.224,0.222,0.237,0.268,0.315,0.376,0.448,0.528,0.611,0.695,0.776,0.848,0.91,0.957,0.987,1.0,0.993,0.969,0.927,0.87,0.8,0.721,0.637,0.551,0.469,0.392,0.326,0.273,0.236,0.215,0.212,0.226,0.256,0.301,0.358,0.424,0.495,0.568,0.64,0.706,0.765,0.813,0.849,0.871,0.88,0.874,0.856,0.827,0.788,0.743,0.693,0.643,0.593,0.547,0.507,0.474,0.449,0.433,0.425,0.426,0.434,0.448,0.466,0.486,0.507,0.527,0.544,0.559,0.569,0.574,0.575,0.573,0.567,0.56,0.552,0.545,0.541,0.54,0.544,0.552,0.567,0.586,0.609,0.636,0.665,0.693,0.72,0.744,0.761,0.772,0.773,0.765,0.747,0.719,0.682,0.638,0.587,0.533,0.478,0.425,0.377,0.336,0.306,0.288,0.283,0.293,0.318,0.358,0.409,0.472,0.542,0.617,0.693,0.766,0.833,0.891,0.935,0.964,0.977,0.971,0.948,0.907,0.851,0.782,0.703,0.619,0.532,0.447,0.369,0.3,0.245,0.206,0.184,0.182,0.198,0.232,0.283,0.347,0.422,0.504,0.589,0.673,0.752,0.674,0.694,0.711,0.723,0.729,0.727,0.717,0.698,0.671,0.636,0.595,0.55,0.502,0.455,0.41,0.372,0.341,0.321,0.313,0.317,0.336,0.368,0.412,0.467,0.53,0.599,0.671,0.741,0.807,0.865,0.912,0.945,0.963,0.964,0.948,0.914,0.866,0.803,0.73,0.649,0.565,0.481,0.401,0.329,0.269,0.223,0.193,0.181,0.187,0.21,0.25,0.305,0.371,0.445,0.524,0.603,0.68,0.75,0.811,0.859,0.893,0.913,0.918,0.908,0.886,0.853,0.813,0.769,0.724,0.681,0.644,0.615,0.596,0.588,0.591,0.604,0.626,0.654,0.686,0.719,0.75,0.777,0.796,0.806,0.806,0.793,0.768,0.731,0.684,0.629,0.567,0.502,0.438,0.377,0.322,0.278,0.246,0.228,0.227,0.243,0.274,0.322,0.382,0.454,0.533,0.616,0.7,0.779,0.851,0.911,0.958,0.988,1.0,0.993,0.968,0.925,0.868,0.798,0.719,0.634,0.549,0.466,0.39,0.323,0.27,0.233,0.212,0.209,0.223,0.254,0.299,0.356,0.423,0.494,0.568,0.641,0.708,0.767,0.816,0.853,0.876,0.885,0.88,0.862,0.833,0.794,0.748,0.698,0.646,0.595,0.548,0.505,0.47,0.443,0.424,0.415,0.413,0.419,0.43,0.446,0.465,0.485,0.504,0.521,0.535,0.546,0.552,0.555,0.554,0.551,0.546,0.54,0.536,0.534,0.535,0.541,0.552,0.568,0.588,0.613,0.64,0.669,0.698,0.725,0.747,0.764,0.774,0.774,0.765,0.746,0.718,0.68,0.635,0.584,0.529,0.474,0.421,0.374,0.334,0.304,0.287,0.283,0.294,0.32,0.36,0.412,0.475,0.546,0.621,0.696,0.77,0.836,0.893,0.937,0.965,0.977,0.971,0.946,0.905,0.848,0.779,0.7,0.615,0.529,0.444,0.366,0.298,0.243,0.205,0.184,0.182,0.199,0.234,0.285,0.35,0.425,0.507,0.592,0.676,0.754,0.676,0.697,0.714,0.726,0.732,0.731,0.721,0.702,0.674,0.639,0.598,0.552,0.504,0.456,0.411,0.371,0.34,0.318,0.309,0.313,0.331,0.362,0.406,0.461,0.524,0.594,0.666,0.737,0.804,0.863,0.911,0.946,0.965,0.967,0.952,0.92,0.873,0.811,0.739,0.659,0.574,0.49,0.41,0.337,0.275,0.228,0.196,0.182,0.185,0.207,0.245,0.297,0.361,0.433,0.51,0.588,0.664,0.733,0.793,0.842,0.877,0.897,0.903,0.895,0.874,0.843,0.805,0.762,0.719,0.677,0.64,0.611,0.592,0.583,0.584,0.595,0.615,0.641,0.671,0.703,0.733,0.759,0.778,0.788,0.788,0.776,0.753,0.718,0.673,0.62,0.56,0.498,0.435,0.376,0.323,0.281,0.25,0.234,0.233,0.249,0.281,0.329,0.389,0.46,0.539,0.621,0.704,0.782,0.853,0.913,0.959,0.988,0.999,0.992,0.966,0.924,0.866,0.796,0.717,0.632,0.546,0.463,0.387,0.321,0.268,0.23,0.209,0.206,0.221,0.251,0.297,0.354,0.421,0.493,0.568,0.641,0.709,0.77,0.82,0.857,0.881,0.891,0.887,0.869,0.84,0.801,0.755,0.704,0.651,0.599,0.549,0.504,0.467,0.437,0.415,0.402,0.398,0.401,0.41,0.423,0.44,0.458,0.477,0.493,0.508,0.519,0.526,0.531,0.532,0.531,0.528,0.526,0.524,0.525,0.53,0.538,0.551,0.569,0.591,0.617,0.645,0.675,0.704,0.73,0.752,0.768,0.777,0.776,0.766,0.746,0.716,0.677,0.631,0.579,0.525,0.47,0.417,0.37,0.331,0.302,0.285,0.283,0.295,0.322,0.362,0.416,0.479,0.55,0.625,0.701,0.774,0.84,0.896,0.939,0.967,0.977,0.97,0.945,0.903,0.845,0.775,0.696,0.611,0.525,0.44,0.363,0.295,0.241,0.204,0.184,0.182,0.2,0.236,0.287,0.353,0.428,0.51,0.595,0.679,0.757,0.678,0.699,0.717,0.729,0.736,0.734,0.724,0.706,0.678,0.643,0.601,0.554,0.505,0.457,0.411,0.37,0.338,0.316,0.306,0.309,0.326,0.357,0.4,0.455,0.518,0.588,0.66,0.732,0.8,0.86,0.91,0.946,0.967,0.97,0.957,0.926,0.88,0.82,0.748,0.668,0.584,0.5,0.419,0.345,0.282,0.233,0.2,0.183,0.185,0.204,0.239,0.289,0.351,0.421,0.496,0.573,0.647,0.715,0.775,0.823,0.858,0.879,0.886,0.879,0.86,0.831,0.794,0.752,0.71,0.669,0.633,0.604,0.584,0.573,0.573,0.583,0.601,0.625,0.654,0.684,0.713,0.739,0.758,0.769,0.77,0.759,0.737,0.704,0.662,0.61,0.553,0.493,0.433,0.376,0.326,0.284,0.255,0.24,0.241,0.257,0.289,0.336,0.396,0.467,0.545,0.626,0.708,0.785,0.855,0.914,0.959,0.988,0.998,0.991,0.965,0.922,0.864,0.794,0.714,0.63,0.544,0.461,0.385,0.318,0.265,0.227,0.206,0.203,0.217,0.248,0.294,0.351,0.419,0.491,0.567,0.641,0.71,0.772,0.823,0.862,0.887,0.898,0.895,0.878,0.849,0.81,0.763,0.712,0.657,0.603,0.551,0.504,0.464,0.43,0.406,0.389,0.381,0.381,0.387,0.398,0.412,0.429,0.446,0.462,0.476,0.488,0.497,0.503,0.506,0.508,0.509,0.51,0.512,0.516,0.524,0.535,0.551,0.571,0.596,0.623,0.652,0.682,0.711,0.737,0.758,0.773,0.78,0.778,0.767,0.745,0.714,0.674,0.627,0.574,0.519,0.464,0.412,0.365,0.327,0.299,0.284,0.282,0.296,0.324,0.365,0.419,0.483,0.555,0.63,0.706,0.778,0.844,0.899,0.941,0.968,0.977,0.969,0.943,0.9,0.842,0.771,0.692,0.606,0.52,0.436,0.359,0.292,0.239,0.202,0.183,0.183,0.201,0.238,0.29,0.356,0.432,0.514,0.599,0.683,0.76,0.679,0.701,0.719,0.733,0.739,0.738,0.728,0.71,0.682,0.646,0.604,0.557,0.508,0.458,0.411,0.37,0.337,0.313,0.302,0.305,0.321,0.351,0.394,0.448,0.511,0.581,0.654,0.727,0.796,0.857,0.908,0.946,0.968,0.974,0.962,0.933,0.888,0.829,0.758,0.679,0.595,0.511,0.429,0.355,0.291,0.24,0.204,0.186,0.185,0.202,0.234,0.282,0.341,0.409,0.482,0.557,0.629,0.697,0.756,0.804,0.839,0.86,0.868,0.862,0.844,0.816,0.78,0.74,0.698,0.658,0.622,0.592,0.572,0.56,0.559,0.567,0.583,0.606,0.634,0.663,0.692,0.717,0.737,0.748,0.75,0.741,0.721,0.691,0.65,0.602,0.547,0.49,0.432,0.377,0.329,0.289,0.262,0.248,0.249,0.265,0.298,0.344,0.404,0.473,0.55,0.631,0.712,0.788,0.857,0.915,0.959,0.987,0.997,0.989,0.963,0.92,0.862,0.792,0.712,0.628,0.542,0.459,0.382,0.316,0.262,0.224,0.203,0.2,0.214,0.245,0.29,0.348,0.416,0.489,0.565,0.64,0.711,0.774,0.826,0.867,0.893,0.905,0.903,0.887,0.859,0.82,0.773,0.721,0.665,0.609,0.555,0.505,0.461,0.425,0.396,0.376,0.364,0.36,0.363,0.37,0.382,0.397,0.412,0.428,0.442,0.455,0.465,0.473,0.479,0.484,0.488,0.492,0.498,0.507,0.518,0.533,0.552,0.575,0.601,0.63,0.661,0.691,0.72,0.745,0.766,0.779,0.785,0.781,0.767,0.744,0.711,0.67,0.622,0.569,0.513,0.458,0.406,0.36,0.322,0.296,0.282,0.282,0.296,0.326,0.369,0.424,0.489,0.56,0.636,0.712,0.784,0.848,0.903,0.944,0.969,0.978,0.968,0.941,0.897,0.838,0.767,0.686,0.601,0.515,0.431,0.355,0.289,0.236,0.201,0.183,0.183,0.203,0.24,0.293,0.36,0.436,0.519,0.604,0.687,0.764,0.681,0.703,0.722,0.736,0.743,0.742,0.733,0.714,0.686,0.651,0.608,0.561,0.51,0.46,0.412,0.37,0.335,0.311,0.299,0.3,0.315,0.344,0.387,0.441,0.504,0.574,0.647,0.721,0.79,0.853,0.906,0.945,0.969,0.977,0.967,0.939,0.896,0.838,0.769,0.69,0.607,0.522,0.441,0.365,0.3,0.247,0.21,0.189,0.186,0.2,0.23,0.275,0.331,0.397,0.467,0.54,0.611,0.678,0.736,0.783,0.818,0.84,0.848,0.842,0.825,0.798,0.764,0.724,0.683,0.643,0.607,0.578,0.556,0.544,0.541,0.548,0.563,0.585,0.611,0.64,0.668,0.694,0.714,0.726,0.73,0.723,0.705,0.677,0.639,0.593,0.542,0.487,0.432,0.38,0.333,0.296,0.269,0.256,0.258,0.275,0.307,0.353,0.412,0.48,0.556,0.636,0.715,0.791,0.858,0.916,0.959,0.986,0.996,0.987,0.961,0.918,0.86,0.79,0.711,0.626,0.54,0.457,0.38,0.314,0.26,0.221,0.2,0.196,0.21,0.241,0.286,0.344,0.412,0.486,0.563,0.639,0.711,0.775,0.829,0.871,0.899,0.913,0.912,0.897,0.87,0.831,0.784,0.731,0.674,0.616,0.56,0.507,0.46,0.419,0.387,0.363,0.347,0.339,0.338,0.342,0.351,0.363,0.377,0.392,0.406,0.42,0.431,0.442,0.451,0.459,0.467,0.475,0.485,0.498,0.513,0.532,0.554,0.58,0.608,0.639,0.67,0.701,0.73,0.755,0.774,0.786,0.789,0.784,0.768,0.743,0.708,0.665,0.616,0.562,0.506,0.451,0.399,0.354,0.317,0.292,0.279,0.281,0.297,0.328,0.372,0.429,0.494,0.567,0.642,0.718,0.79,0.854,0.907,0.947,0.971,0.978,0.967,0.938,0.893,0.833,0.761,0.681,0.595,0.509,0.426,0.35,0.285,0.234,0.199,0.182,0.184,0.205,0.243,0.297,0.364,0.441,0.524,0.608,0.691,0.768,0.682,0.705,0.725,0.739,0.747,0.747,0.737,0.719,0.691,0.655,0.612,0.564,0.513,0.462,0.413,0.37,0.334,0.309,0.295,0.295,0.309,0.338,0.379,0.433,0.496,0.566,0.64,0.714,0.785,0.849,0.903,0.944,0.97,0.979,0.971,0.946,0.904,0.848,0.78,0.702,0.62,0.535,0.453,0.377,0.31,0.256,0.217,0.194,0.188,0.199,0.226,0.268,0.322,0.385,0.453,0.524,0.593,0.658,0.715,0.762,0.796,0.818,0.826,0.822,0.805,0.779,0.745,0.706,0.666,0.626,0.59,0.56,0.538,0.525,0.521,0.526,0.54,0.561,0.587,0.615,0.643,0.669,0.69,0.704,0.709,0.704,0.689,0.663,0.628,0.586,0.537,0.485,0.433,0.383,0.339,0.303,0.278,0.266,0.268,0.285,0.317,0.362,0.42,0.488,0.562,0.64,0.718,0.792,0.859,0.915,0.958,0.984,0.994,0.985,0.959,0.916,0.858,0.788,0.709,0.624,0.539,0.456,0.379,0.312,0.258,0.219,0.197,0.193,0.206,0.237,0.282,0.34,0.408,0.483,0.561,0.638,0.711,0.776,0.832,0.876,0.906,0.921,0.922,0.908,0.881,0.843,0.796,0.742,0.684,0.625,0.566,0.51,0.46,0.416,0.379,0.351,0.331,0.318,0.313,0.314,0.32,0.33,0.342,0.356,0.371,0.385,0.398,0.411,0.422,0.434,0.446,0.459,0.473,0.49,0.509,0.532,0.558,0.586,0.617,0.649,0.682,0.713,0.741,0.765,0.783,0.793,0.794,0.786,0.768,0.741,0.704,0.66,0.609,0.554,0.498,0.443,0.392,0.347,0.312,0.288,0.277,0.28,0.298,0.331,0.377,0.434,0.501,0.574,0.65,0.725,0.796,0.859,0.912,0.95,0.973,0.978,0.966,0.935,0.889,0.828,0.755,0.674,0.589,0.503,0.42,0.345,0.281,0.231,0.197,0.182,0.185,0.207,0.246,0.301,0.369,0.446,0.529,0.614,0.696,0.772,0.684,0.707,0.728,0.743,0.751,0.751,0.742,0.724,0.696,0.66,0.617,0.568,0.517,0.465,0.415,0.37,0.333,0.306,0.292,0.29,0.303,0.331,0.372,0.424,0.487,0.557,0.632,0.706,0.778,0.844,0.899,0.942,0.97,0.982,0.976,0.953,0.913,0.858,0.791,0.715,0.633,0.549,0.466,0.389,0.322,0.266,0.224,0.199,0.191,0.199,0.223,0.262,0.313,0.373,0.439,0.508,0.575,0.638,0.694,0.74,0.774,0.796,0.804,0.8,0.784,0.758,0.724,0.686,0.646,0.606,0.57,0.54,0.517,0.503,0.498,0.502,0.515,0.535,0.56,0.588,0.617,0.643,0.665,0.68,0.687,0.685,0.673,0.65,0.619,0.579,0.534,0.485,0.436,0.388,0.346,0.312,0.288,0.277,0.279,0.296,0.327,0.372,0.429,0.495,0.568,0.645,0.721,0.794,0.859,0.914,0.956,0.982,0.991,0.982,0.956,0.913,0.855,0.786,0.707,0.623,0.537,0.454,0.377,0.31,0.256,0.217,0.194,0.19,0.203,0.233,0.278,0.336,0.404,0.479,0.557,0.635,0.71,0.777,0.835,0.88,0.912,0.929,0.931,0.919,0.894,0.856,0.809,0.755,0.696,0.635,0.574,0.515,0.461,0.413,0.373,0.34,0.316,0.299,0.29,0.287,0.29,0.298,0.308,0.321,0.336,0.35,0.365,0.38,0.395,0.411,0.427,0.444,0.463,0.484,0.508,0.534,0.563,0.595,0.628,0.662,0.695,0.726,0.754,0.776,0.792,0.8,0.799,0.789,0.769,0.739,0.7,0.653,0.601,0.546,0.489,0.434,0.383,0.34,0.306,0.283,0.274,0.28,0.3,0.334,0.382,0.44,0.508,0.582,0.658,0.733,0.803,0.866,0.917,0.954,0.975,0.978,0.964,0.932,0.884,0.822,0.749,0.667,0.582,0.496,0.414,0.339,0.276,0.227,0.195,0.181,0.186,0.209,0.25,0.306,0.374,0.452,0.535,0.619,0.701,0.777,0.685,0.709,0.73,0.746,0.755,0.756,0.747,0.729,0.702,0.665,0.622,0.573,0.521,0.468,0.417,0.371,0.333,0.304,0.288,0.286,0.297,0.323,0.363,0.416,0.478,0.548,0.623,0.698,0.771,0.838,0.895,0.94,0.97,0.984,0.98,0.959,0.922,0.869,0.803,0.728,0.647,0.563,0.481,0.403,0.334,0.277,0.233,0.206,0.195,0.2,0.222,0.257,0.305,0.363,0.426,0.492,0.557,0.619,0.673,0.718,0.752,0.773,0.781,0.777,0.761,0.736,0.702,0.664,0.624,0.584,0.548,0.517,0.493,0.478,0.473,0.476,0.488,0.507,0.532,0.56,0.589,0.616,0.639,0.657,0.666,0.666,0.657,0.638,0.61,0.574,0.532,0.486,0.44,0.395,0.355,0.323,0.3,0.29,0.292,0.309,0.339,0.383,0.438,0.503,0.574,0.649,0.724,0.795,0.859,0.913,0.953,0.979,0.987,0.979,0.952,0.91,0.853,0.783,0.705,0.621,0.536,0.453,0.377,0.309,0.255,0.215,0.192,0.187,0.199,0.229,0.273,0.331,0.399,0.475,0.554,0.633,0.708,0.777,0.836,0.884,0.918,0.937,0.941,0.931,0.906,0.87,0.824,0.769,0.709,0.646,0.583,0.522,0.465,0.413,0.369,0.332,0.303,0.282,0.269,0.263,0.263,0.268,0.277,0.289,0.303,0.319,0.335,0.353,0.371,0.39,0.41,0.432,0.455,0.481,0.509,0.539,0.572,0.606,0.641,0.676,0.71,0.741,0.767,0.788,0.802,0.808,0.805,0.791,0.768,0.736,0.694,0.646,0.593,0.536,0.479,0.424,0.374,0.332,0.299,0.279,0.272,0.279,0.302,0.338,0.387,0.447,0.516,0.59,0.667,0.741,0.811,0.872,0.922,0.957,0.977,0.978,0.962,0.929,0.879,0.816,0.742,0.66,0.574,0.488,0.407,0.333,0.271,0.224,0.193,0.181,0.187,0.212,0.254,0.311,0.38,0.458,0.541,0.626,0.707,0.782,0.686,0.711,0.733,0.75,0.759,0.76,0.752,0.735,0.707,0.671,0.627,0.578,0.525,0.471,0.419,0.372,0.332,0.303,0.285,0.281,0.291,0.316,0.355,0.406,0.468,0.538,0.613,0.689,0.763,0.831,0.89,0.937,0.97,0.986,0.984,0.966,0.93,0.88,0.816,0.742,0.662,0.578,0.496,0.418,0.348,0.289,0.244,0.214,0.2,0.203,0.221,0.254,0.299,0.353,0.414,0.477,0.54,0.6,0.653,0.696,0.729,0.75,0.758,0.753,0.738,0.712,0.679,0.641,0.601,0.561,0.524,0.493,0.468,0.452,0.446,0.449,0.46,0.479,0.503,0.531,0.561,0.589,0.614,0.633,0.645,0.648,0.642,0.626,0.602,0.569,0.531,0.489,0.445,0.403,0.366,0.335,0.313,0.303,0.306,0.322,0.351,0.394,0.447,0.51,0.58,0.652,0.725,0.795,0.858,0.91,0.95,0.975,0.983,0.974,0.948,0.906,0.849,0.781,0.703,0.62,0.535,0.453,0.376,0.309,0.254,0.214,0.19,0.184,0.196,0.225,0.269,0.326,0.394,0.47,0.549,0.629,0.706,0.776,0.837,0.887,0.923,0.944,0.951,0.942,0.919,0.884,0.838,0.784,0.724,0.66,0.595,0.531,0.471,0.416,0.367,0.326,0.293,0.268,0.251,0.241,0.238,0.241,0.248,0.259,0.273,0.29,0.308,0.328,0.35,0.372,0.397,0.423,0.451,0.481,0.513,0.547,0.582,0.619,0.656,0.692,0.726,0.756,0.782,0.801,0.813,0.816,0.809,0.793,0.767,0.732,0.688,0.638,0.583,0.525,0.468,0.413,0.364,0.323,0.292,0.274,0.269,0.279,0.304,0.342,0.393,0.455,0.525,0.6,0.676,0.751,0.82,0.88,0.928,0.961,0.978,0.978,0.96,0.925,0.874,0.809,0.734,0.651,0.566,0.48,0.399,0.327,0.266,0.221,0.192,0.181,0.189,0.215,0.258,0.316,0.386,0.465,0.548,0.632,0.713,0.787,0.688,0.713,0.736,0.753,0.763,0.765,0.758,0.741,0.713,0.677,0.633,0.583,0.53,0.475,0.422,0.373,0.332,0.301,0.282,0.276,0.285,0.308,0.346,0.396,0.458,0.528,0.603,0.679,0.754,0.824,0.885,0.934,0.968,0.987,0.988,0.972,0.939,0.89,0.829,0.756,0.677,0.594,0.512,0.434,0.363,0.302,0.255,0.223,0.206,0.206,0.222,0.251,0.293,0.344,0.402,0.463,0.524,0.581,0.633,0.675,0.707,0.727,0.734,0.73,0.714,0.689,0.656,0.618,0.577,0.537,0.499,0.467,0.442,0.425,0.418,0.42,0.43,0.449,0.473,0.502,0.532,0.561,0.588,0.61,0.624,0.631,0.628,0.616,0.595,0.567,0.532,0.493,0.453,0.413,0.378,0.349,0.328,0.318,0.321,0.336,0.365,0.405,0.457,0.518,0.585,0.656,0.727,0.794,0.855,0.907,0.946,0.97,0.978,0.969,0.944,0.902,0.846,0.778,0.701,0.619,0.535,0.453,0.376,0.309,0.254,0.213,0.189,0.182,0.193,0.221,0.264,0.321,0.389,0.465,0.544,0.625,0.703,0.775,0.838,0.889,0.927,0.951,0.96,0.953,0.932,0.899,0.854,0.8,0.739,0.675,0.608,0.542,0.479,0.421,0.369,0.324,0.287,0.258,0.237,0.223,0.217,0.218,0.223,0.234,0.248,0.266,0.286,0.308,0.333,0.359,0.387,0.418,0.45,0.484,0.52,0.557,0.596,0.635,0.673,0.71,0.744,0.773,0.797,0.814,0.823,0.823,0.814,0.794,0.765,0.727,0.681,0.628,0.572,0.513,0.456,0.402,0.353,0.314,0.285,0.269,0.267,0.279,0.306,0.347,0.4,0.463,0.534,0.61,0.686,0.76,0.828,0.887,0.933,0.965,0.98,0.978,0.958,0.92,0.868,0.802,0.726,0.643,0.557,0.472,0.392,0.32,0.261,0.217,0.19,0.181,0.191,0.219,0.263,0.322,0.393,0.472,0.556,0.64,0.72,0.793,0.688,0.715,0.738,0.757,0.768,0.77,0.763,0.747,0.72,0.684,0.64,0.589,0.535,0.479,0.425,0.375,0.333,0.3,0.279,0.271,0.278,0.3,0.337,0.386,0.447,0.516,0.591,0.669,0.745,0.816,0.878,0.929,0.966,0.987,0.991,0.978,0.947,0.901,0.841,0.771,0.693,0.611,0.529,0.45,0.379,0.317,0.268,0.233,0.214,0.211,0.224,0.25,0.289,0.337,0.392,0.45,0.509,0.564,0.614,0.655,0.685,0.705,0.712,0.707,0.691,0.665,0.632,0.593,0.553,0.512,0.474,0.441,0.415,0.398,0.389,0.39,0.401,0.419,0.443,0.472,0.503,0.534,0.563,0.587,0.605,0.614,0.615,0.607,0.59,0.566,0.535,0.499,0.462,0.425,0.392,0.364,0.345,0.335,0.337,0.351,0.378,0.417,0.467,0.525,0.59,0.659,0.727,0.793,0.852,0.902,0.94,0.964,0.972,0.963,0.938,0.897,0.842,0.775,0.7,0.618,0.535,0.453,0.377,0.31,0.254,0.213,0.188,0.181,0.191,0.218,0.26,0.316,0.384,0.459,0.539,0.62,0.699,0.772,0.837,0.89,0.931,0.957,0.968,0.964,0.945,0.913,0.87,0.816,0.756,0.691,0.623,0.555,0.49,0.429,0.373,0.325,0.284,0.251,0.227,0.21,0.202,0.2,0.204,0.214,0.228,0.247,0.268,0.293,0.321,0.351,0.383,0.417,0.453,0.491,0.531,0.572,0.613,0.653,0.693,0.73,0.763,0.791,0.813,0.828,0.834,0.83,0.817,0.794,0.762,0.721,0.672,0.618,0.56,0.501,0.443,0.389,0.342,0.305,0.278,0.264,0.265,0.28,0.31,0.353,0.408,0.473,0.545,0.621,0.697,0.771,0.838,0.895,0.939,0.969,0.982,0.977,0.955,0.915,0.861,0.794,0.717,0.633,0.547,0.462,0.383,0.313,0.256,0.213,0.188,0.181,0.193,0.223,0.269,0.329,0.401,0.48,0.564,0.647,0.727,0.799,0.689,0.717,0.741,0.76,0.772,0.775,0.769,0.753,0.727,0.691,0.647,0.596,0.541,0.484,0.429,0.378,0.333,0.299,0.276,0.267,0.272,0.292,0.327,0.376,0.436,0.505,0.58,0.657,0.734,0.807,0.871,0.924,0.963,0.987,0.994,0.983,0.955,0.912,0.854,0.786,0.709,0.628,0.547,0.468,0.395,0.333,0.282,0.245,0.224,0.218,0.227,0.251,0.286,0.331,0.383,0.439,0.495,0.548,0.596,0.635,0.665,0.683,0.69,0.684,0.668,0.642,0.608,0.57,0.528,0.487,0.448,0.415,0.388,0.37,0.361,0.361,0.371,0.389,0.413,0.443,0.475,0.508,0.539,0.566,0.586,0.599,0.604,0.6,0.587,0.566,0.539,0.507,0.473,0.439,0.408,0.381,0.362,0.353,0.354,0.368,0.393,0.43,0.477,0.533,0.595,0.661,0.727,0.791,0.848,0.897,0.934,0.957,0.964,0.956,0.932,0.892,0.838,0.772,0.698,0.617,0.535,0.454,0.378,0.311,0.255,0.214,0.188,0.18,0.189,0.215,0.256,0.312,0.378,0.453,0.533,0.615,0.694,0.769,0.835,0.891,0.933,0.962,0.975,0.974,0.957,0.927,0.885,0.833,0.773,0.708,0.639,0.57,0.503,0.44,0.381,0.33,0.285,0.249,0.222,0.202,0.191,0.187,0.19,0.2,0.214,0.234,0.257,0.284,0.315,0.348,0.384,0.422,0.462,0.503,0.546,0.589,0.632,0.674,0.714,0.751,0.783,0.81,0.83,0.841,0.844,0.837,0.82,0.793,0.757,0.713,0.662,0.606,0.546,0.487,0.429,0.376,0.331,0.295,0.271,0.26,0.263,0.281,0.313,0.359,0.416,0.483,0.556,0.633,0.709,0.782,0.848,0.903,0.946,0.973,0.983,0.976,0.951,0.91,0.854,0.785,0.707,0.623,0.537,0.453,0.375,0.306,0.25,0.21,0.187,0.182,0.196,0.227,0.275,0.336,0.409,0.488,0.572,0.655,0.734,0.805,0.69,0.718,0.743,0.763,0.776,0.781,0.775,0.76,0.734,0.698,0.654,0.603,0.547,0.49,0.433,0.381,0.335,0.298,0.273,0.262,0.266,0.284,0.318,0.365,0.424,0.492,0.567,0.645,0.723,0.797,0.863,0.918,0.96,0.986,0.996,0.988,0.963,0.922,0.867,0.801,0.726,0.646,0.565,0.486,0.413,0.35,0.297,0.259,0.235,0.226,0.233,0.253,0.285,0.327,0.376,0.429,0.483,0.534,0.58,0.618,0.646,0.663,0.669,0.663,0.646,0.62,0.586,0.547,0.505,0.463,0.424,0.389,0.362,0.342,0.332,0.332,0.342,0.359,0.384,0.415,0.448,0.483,0.516,0.545,0.569,0.586,0.595,0.594,0.586,0.569,0.546,0.517,0.486,0.455,0.425,0.4,0.382,0.372,0.373,0.385,0.408,0.443,0.487,0.54,0.6,0.663,0.726,0.787,0.843,0.89,0.926,0.948,0.956,0.948,0.924,0.885,0.833,0.769,0.695,0.617,0.535,0.455,0.38,0.313,0.258,0.216,0.19,0.18,0.188,0.213,0.253,0.307,0.373,0.447,0.527,0.609,0.689,0.765,0.832,0.89,0.934,0.965,0.981,0.982,0.968,0.941,0.9,0.85,0.791,0.726,0.657,0.587,0.519,0.453,0.392,0.338,0.291,0.252,0.222,0.2,0.187,0.181,0.183,0.192,0.207,0.227,0.252,0.282,0.315,0.351,0.39,0.431,0.475,0.519,0.565,0.61,0.655,0.698,0.738,0.774,0.805,0.829,0.846,0.854,0.853,0.842,0.821,0.791,0.751,0.704,0.65,0.592,0.532,0.472,0.414,0.362,0.319,0.285,0.264,0.256,0.262,0.283,0.318,0.366,0.426,0.494,0.568,0.645,0.721,0.793,0.858,0.911,0.952,0.976,0.984,0.974,0.947,0.904,0.846,0.775,0.696,0.612,0.526,0.443,0.366,0.299,0.245,0.206,0.185,0.183,0.198,0.232,0.281,0.344,0.417,0.497,0.581,0.663,0.741,0.811,0.69,0.719,0.746,0.767,0.781,0.786,0.782,0.767,0.741,0.706,0.662,0.61,0.554,0.496,0.438,0.384,0.336,0.298,0.271,0.258,0.259,0.276,0.308,0.353,0.411,0.479,0.554,0.632,0.711,0.786,0.853,0.911,0.955,0.984,0.997,0.992,0.97,0.932,0.88,0.816,0.743,0.664,0.584,0.506,0.432,0.368,0.314,0.273,0.247,0.236,0.239,0.257,0.286,0.325,0.371,0.421,0.473,0.521,0.565,0.602,0.629,0.645,0.65,0.643,0.626,0.599,0.565,0.525,0.483,0.44,0.4,0.365,0.336,0.316,0.305,0.305,0.314,0.331,0.357,0.388,0.423,0.459,0.494,0.527,0.554,0.574,0.587,0.591,0.586,0.574,0.554,0.53,0.501,0.472,0.445,0.421,0.403,0.393,0.393,0.403,0.424,0.456,0.498,0.548,0.604,0.664,0.724,0.783,0.836,0.882,0.917,0.939,0.946,0.939,0.916,0.878,0.827,0.765,0.693,0.616,0.536,0.457,0.383,0.317,0.261,0.219,0.192,0.182,0.188,0.211,0.25,0.303,0.368,0.441,0.521,0.602,0.683,0.759,0.828,0.887,0.934,0.967,0.986,0.989,0.978,0.953,0.915,0.866,0.808,0.744,0.676,0.606,0.536,0.469,0.407,0.351,0.301,0.26,0.227,0.203,0.188,0.181,0.182,0.191,0.206,0.227,0.254,0.285,0.321,0.36,0.402,0.446,0.493,0.54,0.587,0.634,0.68,0.723,0.763,0.797,0.826,0.848,0.861,0.866,0.861,0.846,0.821,0.787,0.744,0.693,0.637,0.577,0.516,0.455,0.399,0.348,0.306,0.275,0.257,0.252,0.261,0.286,0.324,0.375,0.436,0.506,0.581,0.658,0.734,0.805,0.868,0.92,0.958,0.98,0.985,0.972,0.943,0.897,0.837,0.765,0.685,0.6,0.515,0.432,0.356,0.291,0.239,0.203,0.184,0.184,0.202,0.237,0.288,0.352,0.426,0.507,0.59,0.672,0.749,0.818,0.69,0.72,0.748,0.77,0.785,0.791,0.788,0.774,0.749,0.714,0.67,0.619,0.562,0.503,0.444,0.388,0.339,0.298,0.27,0.254,0.253,0.268,0.298,0.342,0.398,0.465,0.54,0.618,0.697,0.774,0.843,0.903,0.95,0.982,0.997,0.995,0.977,0.942,0.892,0.831,0.76,0.683,0.604,0.526,0.452,0.387,0.332,0.289,0.261,0.247,0.248,0.262,0.289,0.325,0.368,0.416,0.464,0.511,0.553,0.588,0.614,0.629,0.633,0.626,0.608,0.58,0.546,0.505,0.462,0.419,0.378,0.342,0.312,0.291,0.28,0.279,0.287,0.305,0.331,0.363,0.399,0.437,0.475,0.51,0.541,0.565,0.581,0.589,0.589,0.581,0.565,0.544,0.519,0.492,0.466,0.443,0.425,0.415,0.413,0.422,0.44,0.469,0.508,0.554,0.607,0.664,0.721,0.777,0.829,0.872,0.906,0.927,0.935,0.928,0.906,0.87,0.821,0.76,0.691,0.615,0.537,0.46,0.387,0.321,0.266,0.223,0.196,0.184,0.189,0.211,0.249,0.3,0.363,0.435,0.514,0.595,0.676,0.752,0.822,0.883,0.932,0.967,0.989,0.995,0.986,0.964,0.928,0.882,0.826,0.763,0.695,0.625,0.556,0.488,0.424,0.367,0.316,0.272,0.238,0.212,0.196,0.188,0.188,0.197,0.212,0.235,0.263,0.296,0.334,0.375,0.42,0.467,0.515,0.564,0.614,0.662,0.708,0.75,0.789,0.822,0.848,0.866,0.876,0.877,0.868,0.848,0.819,0.781,0.734,0.681,0.622,0.561,0.499,0.438,0.382,0.334,0.294,0.266,0.25,0.249,0.262,0.289,0.33,0.384,0.448,0.519,0.595,0.673,0.748,0.818,0.879,0.929,0.964,0.983,0.985,0.97,0.937,0.889,0.827,0.754,0.673,0.588,0.503,0.421,0.347,0.283,0.233,0.2,0.183,0.186,0.206,0.243,0.295,0.361,0.436,0.517,0.6,0.681,0.757,0.824,0.69,0.721,0.749,0.773,0.789,0.797,0.794,0.781,0.757,0.723,0.679,0.627,0.57,0.51,0.45,0.393,0.342,0.299,0.268,0.251,0.248,0.26,0.288,0.33,0.385,0.451,0.525,0.604,0.683,0.761,0.832,0.893,0.943,0.978,0.996,0.998,0.983,0.951,0.904,0.845,0.777,0.702,0.623,0.546,0.473,0.407,0.351,0.307,0.276,0.26,0.258,0.27,0.293,0.327,0.367,0.412,0.458,0.503,0.543,0.577,0.601,0.615,0.618,0.61,0.592,0.564,0.529,0.488,0.444,0.4,0.358,0.321,0.291,0.269,0.257,0.255,0.263,0.281,0.307,0.34,0.377,0.417,0.457,0.496,0.529,0.557,0.578,0.59,0.594,0.59,0.578,0.56,0.538,0.513,0.489,0.467,0.449,0.438,0.435,0.441,0.457,0.483,0.518,0.561,0.61,0.663,0.718,0.771,0.819,0.861,0.894,0.915,0.923,0.916,0.896,0.861,0.814,0.755,0.688,0.615,0.539,0.463,0.391,0.326,0.271,0.229,0.201,0.188,0.192,0.212,0.248,0.297,0.359,0.43,0.507,0.587,0.668,0.745,0.815,0.877,0.928,0.966,0.989,0.998,0.993,0.973,0.94,0.896,0.842,0.781,0.715,0.646,0.576,0.509,0.445,0.386,0.334,0.289,0.254,0.227,0.209,0.201,0.201,0.209,0.225,0.249,0.278,0.313,0.353,0.396,0.443,0.492,0.542,0.593,0.643,0.691,0.737,0.779,0.816,0.846,0.869,0.884,0.89,0.886,0.872,0.848,0.815,0.773,0.723,0.666,0.606,0.543,0.48,0.42,0.366,0.319,0.281,0.256,0.244,0.246,0.263,0.294,0.338,0.394,0.46,0.533,0.61,0.688,0.762,0.831,0.89,0.937,0.97,0.986,0.985,0.967,0.931,0.881,0.817,0.742,0.661,0.575,0.491,0.41,0.337,0.275,0.228,0.197,0.183,0.188,0.21,0.249,0.304,0.37,0.446,0.527,0.61,0.691,0.766,0.831,0.689,0.721,0.751,0.776,0.793,0.802,0.801,0.789,0.765,0.732,0.688,0.636,0.579,0.518,0.457,0.398,0.345,0.301,0.268,0.248,0.242,0.252,0.278,0.318,0.372,0.437,0.51,0.588,0.668,0.747,0.819,0.883,0.935,0.973,0.995,1.0,0.987,0.959,0.916,0.859,0.793,0.72,0.644,0.567,0.494,0.428,0.371,0.325,0.293,0.275,0.27,0.279,0.3,0.33,0.368,0.411,0.455,0.497,0.536,0.568,0.591,0.604,0.606,0.598,0.579,0.55,0.515,0.473,0.429,0.384,0.341,0.303,0.272,0.249,0.236,0.234,0.241,0.259,0.286,0.319,0.358,0.4,0.442,0.483,0.521,0.552,0.577,0.593,0.601,0.601,0.593,0.578,0.559,0.536,0.513,0.492,0.474,0.462,0.458,0.461,0.474,0.497,0.528,0.567,0.612,0.661,0.712,0.762,0.809,0.849,0.88,0.9,0.908,0.903,0.884,0.851,0.806,0.75,0.685,0.615,0.541,0.467,0.396,0.333,0.278,0.236,0.207,0.194,0.196,0.215,0.248,0.296,0.355,0.424,0.5,0.579,0.659,0.736,0.807,0.87,0.922,0.962,0.988,0.999,0.996,0.98,0.95,0.908,0.857,0.798,0.734,0.666,0.598,0.531,0.467,0.408,0.355,0.31,0.274,0.247,0.228,0.22,0.22,0.228,0.245,0.269,0.3,0.336,0.378,0.423,0.471,0.522,0.573,0.625,0.675,0.723,0.768,0.808,0.842,0.87,0.89,0.901,0.902,0.894,0.875,0.846,0.809,0.762,0.709,0.65,0.587,0.524,0.461,0.401,0.348,0.303,0.269,0.247,0.239,0.245,0.265,0.3,0.347,0.406,0.474,0.548,0.626,0.703,0.777,0.844,0.901,0.946,0.975,0.988,0.984,0.963,0.925,0.872,0.806,0.73,0.647,0.562,0.478,0.398,0.327,0.268,0.222,0.194,0.183,0.19,0.215,0.256,0.312,0.38,0.456,0.538,0.62,0.7,0.774,0.838,0.688,0.722,0.752,0.778,0.797,0.807,0.807,0.796,0.774,0.741,0.698,0.646,0.588,0.527,0.465,0.404,0.35,0.303,0.268,0.245,0.237,0.245,0.268,0.306,0.358,0.422,0.494,0.572,0.653,0.732,0.806,0.872,0.926,0.967,0.992,1.0,0.991,0.966,0.926,0.873,0.809,0.739,0.664,0.588,0.516,0.449,0.392,0.345,0.311,0.291,0.284,0.29,0.308,0.336,0.372,0.412,0.453,0.494,0.531,0.561,0.583,0.596,0.597,0.588,0.569,0.54,0.504,0.462,0.417,0.371,0.328,0.289,0.256,0.233,0.219,0.216,0.223,0.24,0.267,0.301,0.342,0.385,0.43,0.474,0.514,0.55,0.578,0.598,0.61,0.614,0.609,0.598,0.581,0.561,0.539,0.519,0.501,0.487,0.481,0.482,0.492,0.511,0.538,0.573,0.614,0.659,0.706,0.753,0.797,0.835,0.865,0.885,0.893,0.888,0.871,0.84,0.798,0.744,0.682,0.614,0.543,0.471,0.403,0.34,0.287,0.244,0.215,0.201,0.202,0.218,0.25,0.295,0.353,0.42,0.493,0.571,0.65,0.726,0.797,0.861,0.914,0.955,0.984,0.998,0.998,0.984,0.957,0.919,0.87,0.814,0.752,0.687,0.62,0.554,0.49,0.432,0.38,0.335,0.298,0.271,0.253,0.244,0.244,0.253,0.271,0.296,0.328,0.365,0.408,0.455,0.504,0.556,0.608,0.659,0.709,0.756,0.8,0.837,0.869,0.893,0.909,0.915,0.912,0.899,0.875,0.842,0.8,0.75,0.693,0.632,0.567,0.503,0.44,0.382,0.331,0.288,0.257,0.239,0.234,0.244,0.268,0.307,0.357,0.419,0.489,0.564,0.642,0.719,0.792,0.858,0.912,0.954,0.98,0.99,0.983,0.958,0.917,0.861,0.794,0.717,0.633,0.548,0.465,0.386,0.317,0.26,0.217,0.191,0.183,0.193,0.22,0.264,0.322,0.391,0.468,0.549,0.631,0.71,0.782,0.845,0.687,0.721,0.753,0.781,0.801,0.812,0.814,0.804,0.783,0.75,0.708,0.656,0.598,0.536,0.473,0.411,0.355,0.306,0.268,0.243,0.233,0.238,0.258,0.294,0.344,0.406,0.478,0.555,0.636,0.716,0.791,0.859,0.916,0.959,0.987,0.999,0.994,0.973,0.936,0.886,0.825,0.757,0.684,0.609,0.538,0.471,0.413,0.366,0.33,0.308,0.299,0.303,0.319,0.344,0.377,0.415,0.455,0.494,0.529,0.558,0.579,0.591,0.592,0.582,0.562,0.533,0.496,0.454,0.408,0.362,0.317,0.278,0.244,0.22,0.205,0.201,0.208,0.225,0.252,0.287,0.328,0.373,0.421,0.467,0.511,0.549,0.581,0.606,0.622,0.629,0.628,0.62,0.606,0.587,0.567,0.546,0.528,0.513,0.505,0.503,0.509,0.524,0.547,0.578,0.614,0.655,0.699,0.742,0.783,0.819,0.848,0.867,0.876,0.872,0.856,0.828,0.788,0.738,0.679,0.614,0.545,0.476,0.41,0.349,0.296,0.254,0.225,0.21,0.209,0.224,0.253,0.296,0.351,0.415,0.487,0.563,0.64,0.715,0.786,0.85,0.904,0.947,0.977,0.993,0.996,0.985,0.962,0.927,0.881,0.828,0.769,0.706,0.641,0.577,0.515,0.458,0.406,0.362,0.326,0.299,0.281,0.273,0.274,0.284,0.302,0.328,0.361,0.399,0.443,0.491,0.541,0.593,0.645,0.696,0.745,0.79,0.831,0.866,0.894,0.914,0.926,0.927,0.919,0.901,0.872,0.835,0.788,0.735,0.675,0.611,0.546,0.481,0.419,0.362,0.313,0.274,0.246,0.231,0.231,0.245,0.273,0.315,0.369,0.433,0.505,0.581,0.66,0.736,0.808,0.871,0.923,0.962,0.985,0.991,0.98,0.952,0.908,0.85,0.781,0.702,0.619,0.534,0.451,0.374,0.307,0.252,0.212,0.189,0.184,0.197,0.227,0.272,0.332,0.402,0.479,0.561,0.642,0.72,0.791,0.852,0.685,0.721,0.754,0.783,0.805,0.818,0.82,0.812,0.792,0.76,0.718,0.667,0.609,0.546,0.482,0.419,0.361,0.31,0.27,0.242,0.229,0.231,0.249,0.283,0.33,0.391,0.461,0.538,0.618,0.699,0.776,0.845,0.904,0.951,0.982,0.997,0.996,0.978,0.945,0.898,0.84,0.774,0.703,0.631,0.56,0.494,0.435,0.387,0.35,0.327,0.316,0.318,0.331,0.354,0.385,0.42,0.458,0.496,0.529,0.557,0.578,0.588,0.589,0.579,0.559,0.529,0.492,0.449,0.403,0.356,0.311,0.27,0.236,0.211,0.195,0.19,0.196,0.213,0.24,0.276,0.318,0.365,0.414,0.463,0.509,0.552,0.587,0.615,0.635,0.646,0.649,0.643,0.632,0.615,0.595,0.575,0.556,0.54,0.529,0.524,0.527,0.537,0.556,0.582,0.614,0.65,0.69,0.73,0.768,0.801,0.829,0.848,0.857,0.855,0.841,0.815,0.778,0.73,0.675,0.613,0.548,0.482,0.418,0.359,0.307,0.266,0.236,0.22,0.219,0.231,0.258,0.299,0.351,0.412,0.481,0.555,0.63,0.704,0.774,0.837,0.892,0.935,0.967,0.986,0.991,0.983,0.963,0.931,0.889,0.84,0.783,0.723,0.661,0.599,0.54,0.484,0.434,0.391,0.357,0.33,0.313,0.306,0.308,0.318,0.337,0.364,0.398,0.437,0.482,0.53,0.58,0.632,0.683,0.733,0.781,0.824,0.862,0.894,0.918,0.934,0.94,0.937,0.924,0.9,0.867,0.825,0.774,0.717,0.655,0.589,0.523,0.458,0.397,0.342,0.295,0.259,0.235,0.225,0.229,0.247,0.279,0.325,0.382,0.449,0.522,0.6,0.678,0.754,0.824,0.885,0.934,0.969,0.989,0.991,0.977,0.946,0.899,0.838,0.767,0.688,0.604,0.519,0.437,0.362,0.297,0.245,0.208,0.188,0.185,0.201,0.233,0.281,0.342,0.414,0.492,0.573,0.654,0.731,0.8,0.858,0.682,0.72,0.754,0.784,0.808,0.822,0.827,0.82,0.801,0.771,0.729,0.679,0.62,0.557,0.492,0.428,0.368,0.315,0.272,0.241,0.225,0.225,0.24,0.271,0.316,0.375,0.444,0.52,0.6,0.681,0.759,0.83,0.891,0.941,0.975,0.994,0.996,0.982,0.952,0.909,0.854,0.791,0.722,0.651,0.582,0.516,0.458,0.409,0.371,0.346,0.334,0.334,0.345,0.366,0.395,0.428,0.464,0.5,0.533,0.56,0.579,0.59,0.59,0.58,0.559,0.529,0.492,0.449,0.402,0.355,0.309,0.267,0.232,0.205,0.189,0.183,0.188,0.205,0.232,0.268,0.311,0.359,0.41,0.462,0.511,0.556,0.595,0.627,0.65,0.665,0.671,0.668,0.659,0.644,0.625,0.605,0.584,0.567,0.553,0.545,0.544,0.55,0.564,0.585,0.612,0.644,0.68,0.716,0.751,0.782,0.808,0.827,0.836,0.835,0.823,0.8,0.766,0.723,0.671,0.613,0.551,0.488,0.427,0.37,0.32,0.279,0.25,0.233,0.23,0.241,0.265,0.303,0.352,0.41,0.476,0.547,0.619,0.691,0.76,0.823,0.877,0.922,0.955,0.975,0.983,0.978,0.961,0.932,0.894,0.848,0.795,0.738,0.68,0.621,0.564,0.511,0.463,0.422,0.388,0.364,0.348,0.342,0.345,0.356,0.376,0.404,0.438,0.479,0.523,0.571,0.622,0.672,0.723,0.771,0.816,0.857,0.892,0.92,0.939,0.95,0.952,0.943,0.925,0.896,0.858,0.811,0.757,0.697,0.632,0.565,0.499,0.434,0.374,0.322,0.278,0.246,0.226,0.22,0.228,0.251,0.287,0.336,0.396,0.465,0.54,0.619,0.697,0.771,0.84,0.898,0.944,0.976,0.992,0.991,0.973,0.938,0.888,0.826,0.752,0.672,0.588,0.503,0.423,0.35,0.287,0.237,0.204,0.187,0.187,0.206,0.241,0.291,0.354,0.426,0.505,0.586,0.666,0.741,0.809,0.865,0.68,0.718,0.754,0.786,0.811,0.827,0.833,0.828,0.81,0.781,0.741,0.69,0.632,0.569,0.503,0.437,0.375,0.32,0.275,0.242,0.223,0.219,0.231,0.259,0.303,0.359,0.426,0.501,0.581,0.662,0.741,0.814,0.877,0.929,0.967,0.989,0.995,0.984,0.959,0.919,0.868,0.807,0.741,0.672,0.604,0.539,0.481,0.432,0.393,0.367,0.353,0.351,0.36,0.379,0.406,0.438,0.473,0.507,0.539,0.565,0.584,0.594,0.594,0.584,0.563,0.534,0.496,0.453,0.406,0.358,0.311,0.269,0.232,0.205,0.187,0.18,0.185,0.201,0.228,0.264,0.307,0.357,0.409,0.463,0.515,0.563,0.606,0.641,0.667,0.685,0.694,0.694,0.687,0.673,0.655,0.635,0.614,0.594,0.578,0.566,0.561,0.563,0.572,0.588,0.61,0.637,0.668,0.7,0.732,0.762,0.786,0.804,0.814,0.814,0.805,0.784,0.754,0.714,0.666,0.612,0.555,0.495,0.437,0.383,0.334,0.295,0.265,0.248,0.243,0.252,0.274,0.309,0.354,0.409,0.472,0.539,0.609,0.679,0.745,0.807,0.861,0.906,0.939,0.961,0.971,0.969,0.955,0.93,0.895,0.853,0.804,0.751,0.696,0.64,0.586,0.536,0.491,0.452,0.421,0.398,0.384,0.38,0.384,0.397,0.418,0.446,0.481,0.522,0.566,0.614,0.664,0.713,0.762,0.809,0.851,0.888,0.919,0.943,0.958,0.964,0.96,0.946,0.922,0.888,0.846,0.795,0.737,0.674,0.608,0.54,0.473,0.41,0.352,0.302,0.261,0.233,0.217,0.216,0.229,0.256,0.296,0.349,0.412,0.484,0.56,0.639,0.716,0.79,0.856,0.911,0.954,0.982,0.994,0.989,0.968,0.929,0.877,0.812,0.737,0.656,0.571,0.488,0.408,0.337,0.277,0.23,0.2,0.186,0.19,0.212,0.249,0.301,0.366,0.439,0.518,0.599,0.678,0.752,0.817,0.871,0.676,0.716,0.753,0.787,0.813,0.831,0.839,0.836,0.82,0.792,0.752,0.703,0.645,0.581,0.514,0.448,0.384,0.327,0.279,0.243,0.221,0.214,0.223,0.248,0.289,0.343,0.408,0.482,0.562,0.643,0.722,0.796,0.862,0.916,0.957,0.983,0.992,0.986,0.964,0.928,0.88,0.822,0.759,0.692,0.625,0.561,0.503,0.454,0.415,0.388,0.373,0.369,0.377,0.394,0.419,0.45,0.483,0.517,0.547,0.573,0.592,0.601,0.602,0.591,0.571,0.542,0.504,0.461,0.413,0.365,0.318,0.274,0.237,0.208,0.189,0.182,0.185,0.201,0.227,0.263,0.307,0.358,0.412,0.467,0.521,0.572,0.618,0.656,0.686,0.707,0.718,0.721,0.716,0.703,0.686,0.665,0.643,0.621,0.602,0.587,0.578,0.575,0.579,0.59,0.607,0.629,0.655,0.684,0.712,0.739,0.762,0.78,0.79,0.792,0.785,0.767,0.74,0.705,0.661,0.612,0.558,0.503,0.448,0.396,0.35,0.312,0.283,0.265,0.259,0.266,0.285,0.316,0.359,0.41,0.469,0.533,0.599,0.666,0.73,0.79,0.843,0.887,0.921,0.944,0.956,0.956,0.945,0.923,0.892,0.854,0.809,0.76,0.708,0.657,0.606,0.559,0.517,0.482,0.453,0.433,0.421,0.418,0.424,0.438,0.46,0.489,0.525,0.565,0.61,0.657,0.706,0.754,0.8,0.844,0.883,0.917,0.944,0.962,0.973,0.973,0.964,0.945,0.916,0.877,0.83,0.775,0.714,0.649,0.581,0.513,0.447,0.385,0.329,0.282,0.246,0.221,0.211,0.214,0.231,0.263,0.308,0.364,0.43,0.503,0.58,0.659,0.736,0.808,0.872,0.924,0.964,0.988,0.996,0.987,0.961,0.92,0.864,0.797,0.721,0.638,0.554,0.472,0.394,0.325,0.267,0.224,0.197,0.186,0.194,0.218,0.258,0.313,0.378,0.452,0.532,0.612,0.69,0.762,0.826,0.877,0.673,0.713,0.752,0.787,0.816,0.836,0.845,0.843,0.829,0.803,0.764,0.716,0.658,0.594,0.527,0.459,0.394,0.334,0.284,0.245,0.22,0.21,0.216,0.238,0.276,0.327,0.39,0.463,0.541,0.622,0.702,0.778,0.845,0.902,0.946,0.975,0.988,0.985,0.967,0.935,0.89,0.836,0.775,0.711,0.646,0.583,0.526,0.477,0.438,0.409,0.393,0.388,0.395,0.411,0.434,0.464,0.496,0.528,0.558,0.584,0.602,0.612,0.612,0.602,0.582,0.553,0.516,0.473,0.425,0.376,0.329,0.284,0.246,0.216,0.196,0.187,0.19,0.205,0.23,0.266,0.31,0.361,0.417,0.474,0.53,0.583,0.631,0.673,0.706,0.729,0.744,0.748,0.745,0.734,0.716,0.695,0.672,0.648,0.626,0.608,0.594,0.586,0.585,0.591,0.602,0.62,0.641,0.666,0.691,0.715,0.737,0.754,0.765,0.768,0.763,0.749,0.726,0.694,0.656,0.611,0.562,0.511,0.46,0.411,0.368,0.331,0.302,0.284,0.277,0.282,0.299,0.327,0.365,0.412,0.467,0.527,0.589,0.653,0.714,0.772,0.823,0.866,0.9,0.924,0.937,0.939,0.931,0.912,0.885,0.85,0.809,0.764,0.717,0.67,0.623,0.58,0.542,0.509,0.484,0.466,0.457,0.456,0.463,0.479,0.502,0.532,0.568,0.609,0.653,0.699,0.746,0.792,0.836,0.877,0.913,0.942,0.964,0.978,0.983,0.979,0.964,0.939,0.905,0.862,0.811,0.752,0.689,0.622,0.553,0.485,0.42,0.36,0.307,0.263,0.231,0.212,0.206,0.214,0.236,0.272,0.321,0.38,0.449,0.524,0.602,0.681,0.756,0.826,0.887,0.937,0.972,0.992,0.996,0.983,0.954,0.909,0.85,0.781,0.703,0.621,0.537,0.455,0.379,0.313,0.258,0.218,0.194,0.187,0.198,0.225,0.268,0.325,0.392,0.467,0.546,0.625,0.702,0.773,0.834,0.883,0.668,0.71,0.751,0.787,0.817,0.839,0.851,0.851,0.839,0.814,0.777,0.729,0.672,0.608,0.54,0.471,0.404,0.343,0.29,0.248,0.22,0.206,0.209,0.228,0.263,0.311,0.373,0.443,0.521,0.601,0.682,0.758,0.827,0.886,0.933,0.965,0.982,0.983,0.969,0.94,0.9,0.849,0.791,0.729,0.665,0.604,0.548,0.499,0.46,0.431,0.414,0.408,0.413,0.428,0.45,0.479,0.51,0.542,0.571,0.597,0.615,0.625,0.626,0.617,0.597,0.569,0.532,0.489,0.441,0.392,0.344,0.299,0.26,0.229,0.208,0.197,0.199,0.212,0.237,0.273,0.317,0.368,0.424,0.482,0.54,0.596,0.646,0.69,0.726,0.752,0.769,0.776,0.774,0.764,0.747,0.725,0.7,0.675,0.65,0.627,0.609,0.597,0.59,0.59,0.597,0.609,0.626,0.646,0.668,0.69,0.71,0.727,0.738,0.743,0.74,0.729,0.71,0.684,0.65,0.61,0.566,0.519,0.472,0.427,0.386,0.351,0.324,0.306,0.298,0.3,0.314,0.339,0.374,0.417,0.467,0.522,0.581,0.64,0.698,0.752,0.802,0.844,0.877,0.901,0.915,0.919,0.913,0.897,0.873,0.842,0.805,0.765,0.722,0.679,0.637,0.598,0.563,0.534,0.512,0.498,0.491,0.492,0.502,0.519,0.543,0.574,0.61,0.651,0.694,0.739,0.784,0.828,0.869,0.907,0.938,0.963,0.981,0.99,0.989,0.979,0.959,0.93,0.891,0.843,0.788,0.727,0.661,0.593,0.524,0.456,0.392,0.335,0.285,0.246,0.218,0.203,0.202,0.216,0.243,0.283,0.336,0.399,0.47,0.546,0.624,0.703,0.777,0.845,0.903,0.948,0.98,0.996,0.995,0.978,0.945,0.897,0.836,0.764,0.685,0.602,0.519,0.439,0.365,0.301,0.249,0.213,0.192,0.189,0.203,0.233,0.279,0.337,0.406,0.481,0.56,0.639,0.715,0.783,0.842,0.889,0.663,0.706,0.748,0.786,0.819,0.842,0.856,0.858,0.848,0.825,0.789,0.743,0.686,0.622,0.554,0.484,0.416,0.352,0.297,0.252,0.221,0.204,0.203,0.219,0.25,0.296,0.355,0.424,0.5,0.58,0.66,0.737,0.808,0.869,0.919,0.954,0.975,0.979,0.969,0.944,0.907,0.86,0.805,0.745,0.684,0.625,0.57,0.521,0.482,0.453,0.435,0.428,0.432,0.446,0.468,0.495,0.525,0.557,0.586,0.612,0.63,0.641,0.643,0.634,0.615,0.587,0.551,0.508,0.461,0.412,0.363,0.318,0.278,0.246,0.223,0.211,0.211,0.224,0.248,0.282,0.326,0.377,0.434,0.493,0.553,0.61,0.663,0.709,0.747,0.776,0.795,0.804,0.803,0.794,0.777,0.755,0.729,0.7,0.672,0.646,0.624,0.606,0.595,0.589,0.59,0.597,0.609,0.625,0.644,0.663,0.682,0.698,0.71,0.716,0.716,0.709,0.694,0.672,0.643,0.608,0.569,0.528,0.485,0.444,0.406,0.373,0.347,0.329,0.32,0.321,0.333,0.354,0.384,0.423,0.469,0.519,0.573,0.628,0.682,0.733,0.779,0.819,0.851,0.875,0.89,0.895,0.89,0.877,0.857,0.829,0.797,0.76,0.722,0.683,0.646,0.611,0.581,0.556,0.537,0.526,0.522,0.526,0.538,0.556,0.582,0.614,0.65,0.69,0.732,0.776,0.819,0.86,0.898,0.932,0.959,0.98,0.992,0.996,0.99,0.975,0.95,0.915,0.872,0.82,0.762,0.698,0.631,0.562,0.493,0.427,0.365,0.31,0.265,0.23,0.207,0.197,0.201,0.22,0.252,0.297,0.353,0.419,0.492,0.569,0.648,0.725,0.798,0.863,0.917,0.959,0.987,0.998,0.993,0.972,0.935,0.883,0.82,0.746,0.666,0.583,0.501,0.422,0.35,0.289,0.241,0.208,0.191,0.192,0.209,0.242,0.29,0.351,0.42,0.496,0.575,0.653,0.727,0.794,0.85,0.894,0.658,0.702,0.745,0.785,0.819,0.845,0.861,0.865,0.857,0.836,0.802,0.757,0.701,0.637,0.569,0.498,0.428,0.363,0.305,0.257,0.223,0.203,0.198,0.21,0.238,0.281,0.337,0.404,0.478,0.558,0.638,0.716,0.788,0.851,0.903,0.941,0.965,0.974,0.967,0.947,0.913,0.869,0.818,0.761,0.702,0.644,0.59,0.542,0.503,0.474,0.456,0.448,0.452,0.465,0.485,0.512,0.542,0.573,0.603,0.628,0.648,0.659,0.661,0.654,0.636,0.609,0.574,0.532,0.485,0.436,0.387,0.341,0.3,0.266,0.242,0.229,0.228,0.239,0.261,0.295,0.338,0.389,0.446,0.506,0.566,0.625,0.68,0.728,0.768,0.799,0.82,0.831,0.831,0.823,0.806,0.783,0.756,0.725,0.694,0.664,0.638,0.615,0.598,0.587,0.583,0.584,0.592,0.603,0.618,0.635,0.652,0.668,0.68,0.688,0.691,0.687,0.677,0.659,0.636,0.607,0.573,0.537,0.499,0.462,0.428,0.397,0.372,0.355,0.345,0.345,0.353,0.371,0.398,0.432,0.472,0.518,0.566,0.616,0.666,0.713,0.756,0.793,0.824,0.847,0.861,0.867,0.864,0.853,0.836,0.812,0.783,0.751,0.717,0.683,0.65,0.62,0.594,0.573,0.558,0.55,0.549,0.556,0.57,0.59,0.617,0.649,0.686,0.725,0.767,0.808,0.849,0.888,0.923,0.952,0.975,0.991,0.999,0.997,0.987,0.966,0.936,0.897,0.849,0.794,0.733,0.667,0.599,0.53,0.462,0.397,0.338,0.287,0.246,0.215,0.198,0.193,0.203,0.226,0.263,0.312,0.372,0.44,0.515,0.593,0.672,0.748,0.818,0.88,0.931,0.969,0.992,0.999,0.99,0.964,0.923,0.868,0.802,0.727,0.647,0.564,0.482,0.405,0.336,0.278,0.234,0.204,0.191,0.195,0.216,0.252,0.303,0.365,0.435,0.512,0.59,0.667,0.74,0.804,0.858,0.899,0.651,0.697,0.742,0.783,0.819,0.847,0.866,0.872,0.866,0.847,0.815,0.771,0.716,0.653,0.584,0.513,0.442,0.375,0.314,0.264,0.226,0.202,0.194,0.203,0.227,0.267,0.32,0.384,0.457,0.535,0.615,0.693,0.766,0.831,0.886,0.927,0.954,0.967,0.964,0.947,0.917,0.877,0.828,0.774,0.718,0.662,0.609,0.563,0.524,0.495,0.476,0.468,0.471,0.483,0.503,0.529,0.559,0.59,0.62,0.646,0.667,0.679,0.682,0.676,0.66,0.634,0.6,0.558,0.512,0.463,0.414,0.367,0.325,0.291,0.265,0.251,0.248,0.257,0.278,0.31,0.353,0.403,0.46,0.52,0.581,0.641,0.697,0.747,0.789,0.822,0.845,0.857,0.859,0.851,0.834,0.811,0.782,0.749,0.715,0.681,0.65,0.623,0.601,0.584,0.574,0.571,0.573,0.58,0.592,0.606,0.621,0.636,0.649,0.659,0.664,0.664,0.658,0.646,0.628,0.605,0.577,0.546,0.514,0.481,0.45,0.422,0.399,0.382,0.372,0.37,0.377,0.391,0.413,0.443,0.478,0.518,0.561,0.606,0.651,0.693,0.732,0.767,0.795,0.816,0.83,0.836,0.834,0.825,0.81,0.789,0.764,0.736,0.706,0.677,0.648,0.623,0.601,0.585,0.574,0.57,0.572,0.582,0.598,0.62,0.648,0.681,0.717,0.756,0.796,0.836,0.875,0.91,0.941,0.967,0.986,0.997,1.0,0.993,0.977,0.952,0.917,0.874,0.823,0.765,0.702,0.634,0.566,0.497,0.43,0.368,0.313,0.265,0.228,0.203,0.191,0.192,0.207,0.235,0.277,0.33,0.393,0.464,0.54,0.618,0.696,0.77,0.838,0.897,0.944,0.978,0.996,0.999,0.985,0.955,0.91,0.852,0.784,0.708,0.627,0.544,0.464,0.389,0.323,0.268,0.227,0.201,0.192,0.2,0.224,0.263,0.316,0.379,0.451,0.528,0.606,0.681,0.752,0.814,0.865,0.903,0.645,0.691,0.737,0.781,0.819,0.849,0.87,0.879,0.875,0.858,0.828,0.785,0.732,0.67,0.601,0.529,0.457,0.388,0.325,0.272,0.231,0.203,0.192,0.196,0.217,0.253,0.303,0.365,0.436,0.512,0.592,0.67,0.744,0.811,0.867,0.911,0.942,0.957,0.959,0.945,0.92,0.883,0.837,0.786,0.732,0.678,0.627,0.582,0.543,0.515,0.496,0.488,0.49,0.502,0.521,0.547,0.577,0.608,0.639,0.665,0.687,0.7,0.705,0.7,0.686,0.661,0.628,0.588,0.542,0.493,0.444,0.397,0.355,0.319,0.292,0.276,0.271,0.278,0.298,0.328,0.369,0.419,0.475,0.535,0.597,0.657,0.714,0.766,0.809,0.844,0.868,0.882,0.885,0.877,0.861,0.837,0.806,0.771,0.734,0.697,0.662,0.629,0.602,0.58,0.565,0.556,0.553,0.557,0.565,0.576,0.59,0.604,0.618,0.629,0.637,0.64,0.639,0.632,0.619,0.602,0.58,0.555,0.528,0.5,0.473,0.449,0.428,0.412,0.402,0.399,0.402,0.414,0.432,0.456,0.486,0.521,0.558,0.597,0.636,0.674,0.709,0.739,0.764,0.784,0.796,0.802,0.801,0.793,0.78,0.762,0.74,0.716,0.691,0.666,0.642,0.621,0.604,0.591,0.585,0.584,0.59,0.602,0.621,0.645,0.674,0.707,0.743,0.781,0.82,0.858,0.894,0.927,0.954,0.976,0.99,0.997,0.995,0.983,0.963,0.933,0.894,0.847,0.793,0.733,0.668,0.6,0.531,0.464,0.399,0.34,0.288,0.245,0.213,0.193,0.186,0.193,0.213,0.247,0.293,0.35,0.416,0.488,0.565,0.644,0.721,0.793,0.858,0.913,0.956,0.985,0.999,0.996,0.978,0.944,0.896,0.835,0.765,0.687,0.606,0.524,0.445,0.373,0.309,0.258,0.221,0.199,0.194,0.205,0.233,0.275,0.33,0.395,0.467,0.544,0.621,0.695,0.764,0.823,0.872,0.907,0.637,0.684,0.732,0.777,0.817,0.85,0.873,0.884,0.883,0.869,0.841,0.8,0.748,0.686,0.618,0.546,0.472,0.402,0.337,0.281,0.236,0.206,0.19,0.191,0.208,0.24,0.287,0.346,0.414,0.49,0.568,0.646,0.721,0.789,0.847,0.894,0.927,0.947,0.951,0.942,0.92,0.887,0.845,0.796,0.745,0.693,0.644,0.599,0.562,0.533,0.514,0.506,0.508,0.519,0.539,0.565,0.595,0.626,0.657,0.685,0.707,0.723,0.729,0.726,0.713,0.69,0.659,0.619,0.575,0.527,0.478,0.43,0.387,0.35,0.321,0.303,0.297,0.302,0.319,0.348,0.388,0.436,0.491,0.551,0.612,0.673,0.731,0.784,0.829,0.865,0.89,0.905,0.909,0.902,0.886,0.861,0.829,0.792,0.752,0.711,0.672,0.635,0.602,0.575,0.555,0.541,0.533,0.532,0.537,0.545,0.557,0.571,0.585,0.598,0.609,0.616,0.619,0.617,0.61,0.599,0.583,0.564,0.543,0.52,0.498,0.476,0.458,0.443,0.433,0.429,0.431,0.439,0.453,0.472,0.497,0.526,0.557,0.59,0.624,0.656,0.686,0.712,0.734,0.75,0.761,0.766,0.765,0.758,0.747,0.731,0.712,0.692,0.67,0.649,0.63,0.613,0.6,0.592,0.59,0.593,0.602,0.617,0.638,0.663,0.694,0.727,0.763,0.801,0.838,0.874,0.908,0.937,0.961,0.979,0.989,0.991,0.984,0.968,0.943,0.909,0.867,0.817,0.76,0.698,0.632,0.564,0.496,0.431,0.369,0.313,0.265,0.227,0.2,0.186,0.185,0.197,0.223,0.261,0.311,0.372,0.44,0.514,0.592,0.67,0.745,0.815,0.877,0.929,0.967,0.991,1.0,0.993,0.97,0.932,0.88,0.817,0.744,0.666,0.585,0.504,0.427,0.357,0.296,0.249,0.215,0.198,0.197,0.212,0.243,0.288,0.345,0.411,0.484,0.561,0.637,0.71,0.776,0.833,0.878,0.91,0.629,0.677,0.726,0.773,0.815,0.85,0.876,0.89,0.891,0.879,0.853,0.815,0.764,0.704,0.636,0.563,0.489,0.417,0.35,0.291,0.244,0.209,0.19,0.187,0.2,0.228,0.272,0.327,0.393,0.467,0.544,0.622,0.697,0.766,0.826,0.875,0.911,0.934,0.942,0.937,0.918,0.888,0.85,0.805,0.756,0.706,0.658,0.615,0.578,0.55,0.532,0.523,0.525,0.536,0.556,0.582,0.612,0.644,0.676,0.705,0.729,0.745,0.754,0.753,0.741,0.721,0.691,0.653,0.609,0.562,0.513,0.465,0.421,0.383,0.353,0.333,0.325,0.328,0.343,0.37,0.407,0.454,0.508,0.566,0.628,0.689,0.747,0.8,0.846,0.883,0.91,0.926,0.931,0.925,0.908,0.883,0.849,0.811,0.768,0.724,0.68,0.639,0.602,0.57,0.544,0.525,0.513,0.507,0.508,0.514,0.524,0.538,0.552,0.567,0.58,0.591,0.598,0.602,0.601,0.596,0.586,0.573,0.558,0.54,0.522,0.505,0.489,0.476,0.466,0.461,0.461,0.466,0.476,0.491,0.51,0.533,0.558,0.585,0.612,0.639,0.663,0.685,0.702,0.716,0.724,0.728,0.726,0.72,0.71,0.696,0.68,0.662,0.644,0.627,0.612,0.6,0.592,0.588,0.589,0.596,0.608,0.626,0.649,0.676,0.707,0.741,0.777,0.814,0.85,0.884,0.915,0.941,0.961,0.975,0.981,0.979,0.968,0.948,0.919,0.882,0.836,0.783,0.724,0.661,0.595,0.528,0.462,0.398,0.34,0.288,0.245,0.212,0.191,0.182,0.186,0.204,0.235,0.278,0.332,0.396,0.466,0.542,0.619,0.696,0.77,0.837,0.895,0.942,0.976,0.996,0.999,0.987,0.96,0.918,0.863,0.797,0.723,0.644,0.563,0.484,0.409,0.341,0.284,0.241,0.211,0.198,0.201,0.22,0.254,0.301,0.36,0.428,0.501,0.577,0.652,0.723,0.787,0.841,0.883,0.912,0.62,0.669,0.719,0.768,0.812,0.849,0.877,0.894,0.898,0.889,0.866,0.829,0.781,0.721,0.654,0.582,0.507,0.434,0.365,0.303,0.252,0.215,0.191,0.184,0.193,0.218,0.257,0.31,0.373,0.444,0.52,0.597,0.672,0.742,0.804,0.855,0.894,0.92,0.931,0.929,0.914,0.888,0.853,0.811,0.764,0.717,0.671,0.629,0.593,0.566,0.547,0.539,0.541,0.552,0.572,0.598,0.628,0.661,0.694,0.724,0.749,0.768,0.778,0.779,0.771,0.752,0.724,0.688,0.645,0.599,0.55,0.503,0.458,0.419,0.387,0.365,0.354,0.355,0.368,0.392,0.428,0.472,0.525,0.582,0.642,0.703,0.762,0.815,0.862,0.9,0.928,0.945,0.951,0.945,0.928,0.902,0.868,0.827,0.782,0.735,0.688,0.642,0.6,0.563,0.532,0.508,0.491,0.482,0.479,0.483,0.491,0.504,0.518,0.534,0.55,0.565,0.577,0.586,0.591,0.592,0.589,0.582,0.573,0.561,0.548,0.534,0.521,0.51,0.501,0.495,0.493,0.495,0.502,0.512,0.526,0.543,0.562,0.582,0.603,0.623,0.642,0.658,0.672,0.681,0.687,0.688,0.686,0.679,0.67,0.658,0.644,0.629,0.614,0.601,0.59,0.581,0.577,0.577,0.582,0.592,0.608,0.628,0.653,0.682,0.715,0.749,0.785,0.821,0.855,0.887,0.915,0.939,0.956,0.966,0.968,0.962,0.947,0.923,0.891,0.85,0.802,0.747,0.687,0.623,0.558,0.492,0.428,0.367,0.312,0.265,0.227,0.199,0.184,0.181,0.191,0.214,0.25,0.298,0.355,0.421,0.494,0.57,0.647,0.723,0.794,0.858,0.912,0.955,0.984,0.998,0.997,0.98,0.948,0.902,0.844,0.776,0.701,0.622,0.541,0.463,0.391,0.326,0.273,0.233,0.208,0.199,0.206,0.228,0.266,0.316,0.377,0.445,0.519,0.594,0.668,0.737,0.798,0.849,0.888,0.913,0.61,0.66,0.712,0.762,0.808,0.848,0.879,0.898,0.905,0.899,0.878,0.844,0.797,0.739,0.673,0.601,0.526,0.451,0.38,0.316,0.263,0.221,0.194,0.183,0.187,0.208,0.244,0.293,0.353,0.422,0.496,0.572,0.647,0.717,0.78,0.833,0.875,0.904,0.918,0.92,0.908,0.886,0.854,0.814,0.771,0.726,0.681,0.641,0.606,0.579,0.561,0.553,0.555,0.566,0.586,0.612,0.643,0.677,0.711,0.742,0.77,0.79,0.803,0.806,0.8,0.783,0.757,0.723,0.682,0.637,0.589,0.541,0.496,0.456,0.423,0.399,0.386,0.384,0.394,0.416,0.449,0.491,0.541,0.597,0.656,0.716,0.774,0.828,0.876,0.914,0.943,0.961,0.967,0.962,0.945,0.919,0.884,0.842,0.795,0.745,0.694,0.644,0.598,0.556,0.52,0.492,0.47,0.457,0.451,0.451,0.458,0.47,0.485,0.502,0.521,0.539,0.555,0.569,0.58,0.587,0.591,0.59,0.587,0.581,0.573,0.563,0.554,0.545,0.537,0.531,0.528,0.527,0.53,0.536,0.544,0.555,0.568,0.582,0.596,0.61,0.623,0.633,0.642,0.647,0.649,0.648,0.644,0.637,0.628,0.617,0.604,0.592,0.58,0.57,0.562,0.558,0.557,0.561,0.57,0.584,0.602,0.625,0.652,0.682,0.716,0.751,0.786,0.821,0.854,0.884,0.91,0.93,0.944,0.95,0.949,0.939,0.921,0.894,0.858,0.815,0.765,0.709,0.648,0.585,0.52,0.456,0.395,0.338,0.287,0.245,0.212,0.19,0.18,0.183,0.199,0.228,0.268,0.32,0.381,0.449,0.523,0.599,0.675,0.749,0.817,0.878,0.928,0.966,0.99,0.999,0.992,0.971,0.934,0.885,0.824,0.754,0.678,0.599,0.519,0.443,0.373,0.312,0.263,0.227,0.206,0.201,0.212,0.239,0.279,0.331,0.394,0.463,0.537,0.611,0.684,0.75,0.809,0.857,0.892,0.914,0.6,0.651,0.703,0.755,0.804,0.846,0.879,0.901,0.911,0.908,0.89,0.858,0.814,0.758,0.693,0.621,0.545,0.47,0.397,0.331,0.274,0.229,0.198,0.183,0.183,0.2,0.231,0.277,0.334,0.4,0.472,0.547,0.621,0.692,0.756,0.811,0.855,0.886,0.904,0.909,0.901,0.881,0.852,0.816,0.775,0.732,0.69,0.651,0.617,0.591,0.573,0.565,0.567,0.579,0.598,0.625,0.657,0.691,0.726,0.759,0.789,0.811,0.826,0.832,0.828,0.814,0.791,0.759,0.72,0.675,0.628,0.581,0.535,0.494,0.459,0.433,0.418,0.413,0.421,0.439,0.469,0.509,0.557,0.611,0.669,0.728,0.785,0.839,0.886,0.926,0.955,0.974,0.981,0.976,0.96,0.933,0.897,0.854,0.805,0.752,0.698,0.645,0.594,0.548,0.508,0.475,0.449,0.432,0.422,0.421,0.425,0.436,0.452,0.47,0.491,0.512,0.533,0.552,0.568,0.582,0.592,0.598,0.601,0.601,0.598,0.593,0.587,0.58,0.574,0.568,0.563,0.561,0.56,0.562,0.565,0.57,0.577,0.584,0.592,0.599,0.605,0.61,0.613,0.614,0.613,0.609,0.602,0.594,0.584,0.574,0.563,0.552,0.543,0.536,0.531,0.53,0.533,0.541,0.553,0.569,0.59,0.616,0.645,0.677,0.711,0.746,0.781,0.815,0.847,0.875,0.898,0.916,0.926,0.93,0.925,0.912,0.891,0.861,0.823,0.778,0.726,0.669,0.609,0.546,0.484,0.422,0.364,0.311,0.265,0.228,0.2,0.185,0.181,0.189,0.211,0.244,0.289,0.344,0.408,0.478,0.552,0.628,0.703,0.775,0.84,0.896,0.942,0.975,0.993,0.997,0.986,0.959,0.919,0.866,0.803,0.731,0.655,0.576,0.497,0.423,0.356,0.299,0.254,0.222,0.206,0.205,0.22,0.25,0.293,0.348,0.412,0.482,0.555,0.628,0.699,0.763,0.819,0.863,0.896,0.914,0.589,0.64,0.694,0.748,0.798,0.842,0.878,0.904,0.917,0.916,0.901,0.873,0.83,0.776,0.712,0.641,0.566,0.49,0.416,0.347,0.287,0.239,0.204,0.185,0.181,0.193,0.22,0.262,0.316,0.379,0.449,0.522,0.596,0.666,0.731,0.788,0.833,0.867,0.888,0.896,0.891,0.875,0.849,0.816,0.777,0.736,0.696,0.658,0.626,0.6,0.583,0.575,0.577,0.589,0.609,0.636,0.668,0.703,0.74,0.775,0.806,0.831,0.849,0.857,0.856,0.845,0.824,0.794,0.757,0.714,0.668,0.62,0.574,0.532,0.496,0.468,0.45,0.443,0.447,0.463,0.49,0.527,0.572,0.624,0.679,0.737,0.794,0.847,0.894,0.934,0.964,0.983,0.991,0.986,0.971,0.944,0.908,0.863,0.813,0.758,0.701,0.645,0.59,0.54,0.496,0.458,0.429,0.408,0.395,0.39,0.393,0.403,0.419,0.439,0.461,0.486,0.511,0.535,0.557,0.576,0.593,0.605,0.615,0.62,0.623,0.623,0.62,0.616,0.611,0.606,0.601,0.596,0.592,0.59,0.588,0.588,0.588,0.589,0.59,0.591,0.591,0.589,0.587,0.583,0.577,0.57,0.561,0.551,0.541,0.53,0.52,0.511,0.503,0.499,0.497,0.499,0.505,0.516,0.531,0.55,0.574,0.601,0.632,0.665,0.7,0.735,0.77,0.803,0.833,0.86,0.881,0.896,0.904,0.905,0.897,0.881,0.857,0.825,0.785,0.739,0.686,0.63,0.57,0.509,0.448,0.39,0.335,0.287,0.246,0.214,0.193,0.183,0.185,0.199,0.225,0.264,0.313,0.371,0.437,0.508,0.583,0.658,0.731,0.8,0.861,0.913,0.954,0.982,0.995,0.993,0.977,0.946,0.902,0.846,0.78,0.707,0.63,0.552,0.476,0.404,0.34,0.287,0.246,0.219,0.207,0.21,0.229,0.262,0.308,0.365,0.43,0.5,0.573,0.645,0.714,0.775,0.828,0.869,0.898,0.913,0.577,0.629,0.684,0.739,0.791,0.838,0.877,0.905,0.921,0.924,0.912,0.886,0.847,0.795,0.732,0.662,0.587,0.51,0.435,0.365,0.302,0.251,0.212,0.188,0.18,0.188,0.211,0.249,0.299,0.359,0.426,0.498,0.57,0.641,0.706,0.763,0.811,0.847,0.87,0.881,0.879,0.866,0.844,0.813,0.777,0.739,0.7,0.663,0.632,0.607,0.59,0.583,0.585,0.596,0.616,0.644,0.677,0.713,0.751,0.788,0.821,0.848,0.869,0.88,0.882,0.873,0.855,0.828,0.793,0.752,0.706,0.659,0.613,0.57,0.532,0.503,0.482,0.472,0.473,0.486,0.509,0.543,0.585,0.634,0.688,0.744,0.799,0.851,0.899,0.938,0.969,0.989,0.997,0.993,0.978,0.952,0.915,0.87,0.818,0.762,0.703,0.643,0.586,0.532,0.484,0.442,0.409,0.384,0.368,0.361,0.362,0.371,0.387,0.407,0.432,0.46,0.488,0.517,0.545,0.57,0.593,0.612,0.627,0.639,0.647,0.651,0.653,0.652,0.649,0.644,0.638,0.632,0.626,0.62,0.614,0.608,0.602,0.597,0.591,0.585,0.579,0.571,0.563,0.554,0.544,0.533,0.521,0.509,0.497,0.486,0.476,0.468,0.462,0.459,0.46,0.465,0.474,0.487,0.505,0.527,0.553,0.582,0.615,0.649,0.684,0.72,0.754,0.787,0.815,0.84,0.859,0.872,0.877,0.876,0.865,0.847,0.821,0.787,0.746,0.699,0.646,0.59,0.532,0.473,0.415,0.36,0.31,0.266,0.231,0.204,0.189,0.185,0.192,0.212,0.244,0.286,0.339,0.4,0.467,0.539,0.614,0.688,0.758,0.824,0.881,0.929,0.964,0.986,0.994,0.988,0.966,0.931,0.883,0.824,0.757,0.683,0.606,0.529,0.454,0.386,0.325,0.276,0.239,0.217,0.209,0.217,0.24,0.276,0.324,0.383,0.449,0.519,0.592,0.662,0.728,0.787,0.837,0.874,0.9,0.911,0.564,0.617,0.673,0.729,0.783,0.832,0.874,0.905,0.925,0.931,0.922,0.9,0.863,0.813,0.753,0.684,0.609,0.532,0.456,0.383,0.318,0.264,0.221,0.193,0.181,0.184,0.203,0.237,0.283,0.339,0.404,0.474,0.545,0.615,0.68,0.738,0.787,0.825,0.851,0.865,0.866,0.856,0.836,0.808,0.775,0.738,0.701,0.666,0.636,0.611,0.595,0.588,0.59,0.602,0.622,0.65,0.683,0.721,0.76,0.798,0.833,0.863,0.886,0.901,0.906,0.9,0.885,0.86,0.827,0.788,0.744,0.697,0.651,0.607,0.568,0.536,0.513,0.5,0.498,0.507,0.527,0.557,0.596,0.643,0.694,0.748,0.801,0.853,0.9,0.939,0.97,0.99,1.0,0.997,0.982,0.956,0.92,0.874,0.822,0.764,0.703,0.641,0.581,0.524,0.472,0.427,0.39,0.362,0.343,0.333,0.333,0.341,0.356,0.377,0.404,0.434,0.466,0.5,0.532,0.563,0.592,0.617,0.639,0.657,0.67,0.68,0.685,0.687,0.686,0.683,0.677,0.669,0.661,0.651,0.641,0.63,0.619,0.607,0.595,0.583,0.57,0.556,0.542,0.527,0.513,0.498,0.483,0.468,0.455,0.443,0.433,0.425,0.42,0.419,0.422,0.429,0.44,0.456,0.476,0.501,0.529,0.56,0.594,0.629,0.665,0.7,0.734,0.766,0.793,0.816,0.833,0.844,0.848,0.843,0.831,0.811,0.783,0.748,0.706,0.659,0.607,0.552,0.496,0.439,0.385,0.334,0.288,0.25,0.219,0.199,0.189,0.191,0.204,0.229,0.265,0.311,0.367,0.43,0.499,0.571,0.645,0.717,0.785,0.846,0.899,0.942,0.972,0.989,0.991,0.979,0.953,0.914,0.863,0.801,0.732,0.658,0.581,0.506,0.434,0.368,0.311,0.266,0.234,0.216,0.213,0.225,0.251,0.291,0.342,0.402,0.468,0.539,0.61,0.679,0.742,0.798,0.844,0.879,0.9,0.908,0.551,0.604,0.661,0.718,0.774,0.826,0.87,0.905,0.927,0.937,0.932,0.912,0.879,0.832,0.773,0.706,0.632,0.554,0.477,0.403,0.336,0.278,0.233,0.201,0.184,0.183,0.197,0.226,0.268,0.321,0.383,0.45,0.52,0.589,0.654,0.713,0.763,0.803,0.831,0.847,0.851,0.844,0.827,0.802,0.771,0.736,0.701,0.667,0.637,0.613,0.597,0.59,0.592,0.604,0.624,0.652,0.687,0.725,0.765,0.805,0.843,0.875,0.901,0.919,0.927,0.924,0.912,0.89,0.86,0.822,0.78,0.734,0.688,0.643,0.603,0.569,0.543,0.527,0.522,0.527,0.543,0.57,0.606,0.649,0.697,0.748,0.8,0.851,0.897,0.936,0.967,0.988,0.998,0.996,0.982,0.957,0.921,0.876,0.823,0.764,0.702,0.638,0.575,0.515,0.461,0.412,0.372,0.341,0.319,0.307,0.305,0.312,0.327,0.349,0.377,0.409,0.445,0.482,0.52,0.556,0.591,0.622,0.65,0.673,0.692,0.706,0.716,0.722,0.723,0.721,0.715,0.707,0.696,0.684,0.67,0.654,0.638,0.62,0.602,0.583,0.564,0.544,0.524,0.504,0.485,0.465,0.447,0.43,0.415,0.401,0.391,0.383,0.379,0.379,0.384,0.392,0.406,0.424,0.446,0.472,0.502,0.535,0.569,0.605,0.642,0.677,0.711,0.741,0.768,0.789,0.805,0.814,0.815,0.809,0.795,0.774,0.745,0.709,0.667,0.62,0.569,0.516,0.462,0.409,0.358,0.311,0.27,0.237,0.212,0.197,0.193,0.201,0.219,0.249,0.289,0.339,0.397,0.462,0.531,0.603,0.675,0.745,0.809,0.867,0.915,0.953,0.978,0.989,0.986,0.969,0.938,0.895,0.841,0.777,0.707,0.632,0.557,0.483,0.413,0.351,0.299,0.258,0.23,0.217,0.218,0.234,0.264,0.307,0.36,0.421,0.488,0.558,0.628,0.695,0.756,0.808,0.851,0.882,0.9,0.904,0.538,0.591,0.648,0.707,0.764,0.818,0.865,0.903,0.929,0.942,0.94,0.924,0.894,0.85,0.794,0.728,0.655,0.578,0.5,0.425,0.355,0.295,0.245,0.21,0.188,0.183,0.193,0.217,0.255,0.305,0.363,0.428,0.496,0.564,0.629,0.688,0.739,0.78,0.81,0.829,0.835,0.83,0.816,0.793,0.764,0.731,0.698,0.665,0.636,0.613,0.597,0.59,0.592,0.603,0.624,0.652,0.687,0.726,0.768,0.81,0.849,0.884,0.913,0.933,0.944,0.945,0.936,0.917,0.89,0.854,0.813,0.768,0.722,0.677,0.636,0.6,0.572,0.553,0.544,0.545,0.558,0.58,0.612,0.652,0.697,0.746,0.796,0.845,0.89,0.929,0.96,0.982,0.992,0.991,0.979,0.954,0.919,0.874,0.821,0.762,0.699,0.634,0.57,0.507,0.45,0.399,0.356,0.322,0.297,0.283,0.279,0.285,0.299,0.322,0.351,0.386,0.424,0.465,0.507,0.549,0.589,0.626,0.659,0.688,0.713,0.732,0.746,0.755,0.759,0.758,0.753,0.744,0.732,0.717,0.7,0.68,0.658,0.635,0.611,0.587,0.561,0.536,0.51,0.485,0.46,0.437,0.415,0.395,0.377,0.363,0.351,0.343,0.34,0.34,0.346,0.356,0.371,0.391,0.415,0.443,0.474,0.508,0.543,0.58,0.617,0.652,0.685,0.715,0.74,0.76,0.774,0.782,0.782,0.774,0.759,0.736,0.707,0.671,0.629,0.583,0.534,0.483,0.431,0.381,0.335,0.293,0.257,0.229,0.21,0.201,0.202,0.214,0.238,0.272,0.316,0.369,0.429,0.495,0.564,0.635,0.705,0.772,0.833,0.886,0.929,0.961,0.98,0.986,0.978,0.956,0.921,0.874,0.817,0.752,0.681,0.607,0.532,0.461,0.394,0.336,0.287,0.251,0.228,0.219,0.225,0.245,0.279,0.324,0.378,0.441,0.508,0.577,0.645,0.71,0.768,0.818,0.857,0.884,0.898,0.899,0.523,0.576,0.634,0.694,0.753,0.809,0.859,0.899,0.929,0.946,0.948,0.935,0.908,0.867,0.814,0.75,0.678,0.602,0.524,0.447,0.376,0.313,0.26,0.22,0.195,0.185,0.19,0.21,0.244,0.29,0.345,0.407,0.472,0.539,0.603,0.662,0.714,0.757,0.789,0.809,0.818,0.816,0.803,0.783,0.756,0.725,0.693,0.661,0.633,0.61,0.594,0.587,0.589,0.6,0.62,0.649,0.684,0.724,0.767,0.81,0.852,0.889,0.92,0.944,0.958,0.963,0.957,0.941,0.916,0.883,0.844,0.8,0.754,0.709,0.667,0.629,0.598,0.576,0.563,0.561,0.57,0.588,0.616,0.652,0.694,0.74,0.788,0.835,0.879,0.917,0.949,0.971,0.982,0.983,0.971,0.948,0.914,0.87,0.818,0.759,0.695,0.63,0.564,0.5,0.441,0.387,0.341,0.305,0.278,0.262,0.256,0.26,0.274,0.297,0.327,0.363,0.404,0.449,0.495,0.541,0.586,0.628,0.667,0.702,0.731,0.755,0.774,0.786,0.793,0.794,0.79,0.781,0.768,0.751,0.73,0.707,0.681,0.653,0.624,0.593,0.562,0.531,0.5,0.469,0.44,0.412,0.387,0.364,0.344,0.327,0.314,0.306,0.303,0.304,0.31,0.321,0.338,0.359,0.384,0.413,0.446,0.48,0.517,0.554,0.59,0.626,0.658,0.687,0.711,0.73,0.743,0.749,0.748,0.739,0.723,0.7,0.67,0.634,0.593,0.548,0.501,0.453,0.404,0.358,0.316,0.279,0.248,0.225,0.212,0.208,0.215,0.232,0.26,0.298,0.345,0.401,0.462,0.528,0.597,0.666,0.734,0.797,0.854,0.902,0.94,0.967,0.981,0.981,0.967,0.941,0.902,0.852,0.792,0.726,0.654,0.581,0.508,0.439,0.376,0.321,0.277,0.246,0.228,0.224,0.234,0.258,0.294,0.342,0.398,0.461,0.528,0.596,0.663,0.725,0.78,0.826,0.862,0.885,0.895,0.893,0.509,0.561,0.619,0.68,0.741,0.799,0.851,0.895,0.928,0.948,0.954,0.946,0.922,0.884,0.834,0.772,0.702,0.626,0.548,0.471,0.398,0.332,0.277,0.233,0.204,0.189,0.19,0.205,0.235,0.276,0.328,0.387,0.45,0.515,0.578,0.637,0.689,0.733,0.766,0.788,0.799,0.799,0.789,0.771,0.746,0.717,0.686,0.655,0.627,0.605,0.589,0.581,0.583,0.594,0.614,0.642,0.678,0.718,0.762,0.807,0.85,0.89,0.924,0.951,0.969,0.977,0.974,0.962,0.939,0.909,0.871,0.829,0.784,0.738,0.695,0.655,0.622,0.597,0.581,0.575,0.579,0.593,0.617,0.649,0.688,0.731,0.776,0.821,0.864,0.902,0.933,0.956,0.968,0.97,0.96,0.938,0.906,0.863,0.812,0.754,0.691,0.625,0.558,0.493,0.432,0.377,0.329,0.29,0.261,0.243,0.235,0.238,0.251,0.274,0.305,0.342,0.386,0.433,0.482,0.533,0.582,0.63,0.674,0.713,0.748,0.777,0.799,0.816,0.825,0.828,0.826,0.817,0.803,0.784,0.761,0.735,0.705,0.672,0.638,0.602,0.566,0.529,0.493,0.458,0.424,0.392,0.363,0.337,0.314,0.296,0.282,0.273,0.269,0.27,0.277,0.289,0.306,0.328,0.355,0.385,0.418,0.454,0.491,0.528,0.565,0.599,0.631,0.66,0.683,0.701,0.712,0.717,0.715,0.705,0.689,0.665,0.635,0.6,0.56,0.517,0.472,0.427,0.382,0.34,0.302,0.27,0.244,0.227,0.218,0.22,0.232,0.254,0.286,0.327,0.377,0.434,0.496,0.562,0.63,0.697,0.761,0.82,0.873,0.916,0.949,0.97,0.978,0.973,0.954,0.923,0.881,0.828,0.767,0.699,0.628,0.556,0.485,0.419,0.359,0.309,0.269,0.242,0.229,0.229,0.244,0.271,0.311,0.36,0.418,0.482,0.548,0.615,0.68,0.739,0.791,0.834,0.865,0.885,0.892,0.886,0.493,0.546,0.604,0.665,0.727,0.787,0.842,0.889,0.925,0.949,0.959,0.955,0.935,0.901,0.853,0.794,0.726,0.651,0.573,0.496,0.421,0.353,0.295,0.248,0.214,0.195,0.191,0.202,0.227,0.265,0.313,0.368,0.429,0.492,0.554,0.612,0.665,0.709,0.744,0.767,0.78,0.782,0.774,0.758,0.735,0.707,0.677,0.647,0.62,0.597,0.581,0.573,0.574,0.585,0.604,0.632,0.668,0.709,0.753,0.8,0.845,0.887,0.924,0.954,0.975,0.986,0.987,0.978,0.958,0.93,0.895,0.854,0.81,0.764,0.72,0.679,0.643,0.615,0.595,0.585,0.586,0.596,0.615,0.643,0.678,0.718,0.76,0.803,0.845,0.882,0.913,0.936,0.95,0.953,0.945,0.925,0.895,0.854,0.804,0.747,0.685,0.619,0.553,0.487,0.425,0.369,0.319,0.278,0.247,0.227,0.218,0.219,0.231,0.254,0.285,0.324,0.368,0.418,0.471,0.524,0.578,0.63,0.679,0.723,0.763,0.796,0.822,0.842,0.855,0.86,0.859,0.851,0.837,0.817,0.792,0.763,0.729,0.693,0.655,0.614,0.573,0.532,0.49,0.451,0.412,0.377,0.344,0.315,0.29,0.27,0.254,0.244,0.24,0.241,0.248,0.261,0.278,0.301,0.328,0.359,0.393,0.429,0.466,0.504,0.54,0.574,0.606,0.633,0.656,0.673,0.683,0.687,0.684,0.674,0.657,0.633,0.604,0.57,0.531,0.49,0.448,0.405,0.364,0.326,0.293,0.265,0.245,0.233,0.229,0.236,0.252,0.278,0.314,0.358,0.409,0.467,0.53,0.595,0.661,0.726,0.786,0.842,0.889,0.927,0.955,0.97,0.972,0.962,0.939,0.904,0.858,0.803,0.74,0.672,0.601,0.531,0.462,0.399,0.344,0.298,0.263,0.241,0.232,0.237,0.255,0.286,0.329,0.38,0.439,0.503,0.568,0.634,0.696,0.752,0.801,0.84,0.868,0.883,0.887,0.878,0.478,0.529,0.587,0.65,0.713,0.775,0.832,0.882,0.922,0.949,0.963,0.963,0.947,0.916,0.872,0.816,0.75,0.676,0.599,0.521,0.446,0.376,0.314,0.264,0.227,0.203,0.195,0.202,0.222,0.255,0.299,0.351,0.409,0.47,0.531,0.588,0.641,0.685,0.721,0.746,0.761,0.764,0.758,0.744,0.722,0.696,0.666,0.637,0.61,0.588,0.572,0.563,0.563,0.573,0.592,0.62,0.655,0.696,0.741,0.788,0.835,0.88,0.919,0.952,0.976,0.991,0.995,0.989,0.973,0.948,0.915,0.876,0.832,0.787,0.742,0.699,0.661,0.63,0.607,0.593,0.589,0.595,0.61,0.634,0.665,0.701,0.741,0.782,0.822,0.858,0.889,0.913,0.928,0.932,0.926,0.909,0.881,0.842,0.795,0.74,0.679,0.614,0.548,0.482,0.42,0.362,0.311,0.269,0.236,0.214,0.203,0.204,0.215,0.237,0.268,0.307,0.353,0.404,0.459,0.516,0.573,0.629,0.682,0.731,0.775,0.812,0.843,0.866,0.882,0.89,0.89,0.883,0.869,0.848,0.822,0.79,0.755,0.715,0.673,0.628,0.583,0.537,0.492,0.448,0.405,0.366,0.33,0.298,0.271,0.249,0.232,0.221,0.216,0.217,0.224,0.237,0.255,0.278,0.306,0.337,0.371,0.408,0.445,0.482,0.518,0.552,0.583,0.609,0.631,0.647,0.656,0.659,0.656,0.645,0.628,0.605,0.576,0.543,0.507,0.468,0.428,0.389,0.352,0.318,0.289,0.266,0.251,0.243,0.245,0.256,0.276,0.306,0.344,0.39,0.443,0.502,0.564,0.628,0.691,0.753,0.81,0.86,0.903,0.935,0.957,0.967,0.964,0.949,0.921,0.883,0.834,0.776,0.713,0.645,0.575,0.506,0.441,0.381,0.33,0.288,0.258,0.241,0.237,0.247,0.269,0.303,0.347,0.401,0.46,0.523,0.588,0.652,0.711,0.764,0.81,0.845,0.869,0.881,0.881,0.869,0.462,0.512,0.57,0.633,0.697,0.761,0.82,0.873,0.916,0.948,0.966,0.969,0.958,0.931,0.89,0.837,0.773,0.702,0.625,0.547,0.471,0.4,0.336,0.282,0.241,0.214,0.201,0.203,0.219,0.248,0.288,0.336,0.391,0.45,0.509,0.565,0.617,0.662,0.698,0.725,0.741,0.746,0.742,0.729,0.708,0.683,0.655,0.626,0.599,0.577,0.56,0.551,0.55,0.559,0.577,0.604,0.638,0.679,0.725,0.773,0.822,0.868,0.91,0.945,0.973,0.991,0.999,0.996,0.984,0.961,0.931,0.893,0.851,0.805,0.76,0.716,0.676,0.643,0.616,0.598,0.59,0.592,0.602,0.622,0.649,0.681,0.718,0.757,0.795,0.831,0.862,0.886,0.902,0.908,0.904,0.889,0.864,0.828,0.783,0.731,0.672,0.609,0.544,0.479,0.416,0.358,0.307,0.263,0.229,0.206,0.193,0.192,0.202,0.223,0.253,0.293,0.339,0.392,0.449,0.508,0.568,0.627,0.684,0.737,0.784,0.826,0.86,0.887,0.905,0.916,0.918,0.912,0.898,0.878,0.85,0.817,0.779,0.737,0.692,0.644,0.595,0.546,0.496,0.449,0.403,0.361,0.322,0.287,0.258,0.234,0.216,0.204,0.198,0.198,0.205,0.218,0.237,0.26,0.288,0.32,0.354,0.39,0.427,0.464,0.5,0.533,0.563,0.588,0.609,0.624,0.633,0.635,0.631,0.62,0.604,0.581,0.553,0.522,0.487,0.451,0.414,0.378,0.345,0.315,0.29,0.272,0.261,0.258,0.264,0.279,0.303,0.335,0.376,0.424,0.478,0.536,0.597,0.659,0.72,0.777,0.83,0.876,0.913,0.94,0.957,0.961,0.953,0.933,0.901,0.859,0.808,0.749,0.685,0.617,0.549,0.483,0.421,0.365,0.318,0.281,0.256,0.244,0.244,0.258,0.283,0.32,0.367,0.421,0.481,0.544,0.608,0.669,0.726,0.776,0.817,0.848,0.868,0.877,0.874,0.859,0.445,0.495,0.552,0.615,0.68,0.745,0.807,0.863,0.909,0.945,0.967,0.974,0.967,0.944,0.908,0.858,0.797,0.727,0.652,0.574,0.497,0.425,0.359,0.302,0.258,0.226,0.209,0.206,0.218,0.242,0.278,0.323,0.375,0.431,0.488,0.543,0.595,0.64,0.676,0.704,0.721,0.728,0.725,0.713,0.694,0.67,0.642,0.614,0.587,0.564,0.546,0.536,0.534,0.542,0.559,0.585,0.619,0.66,0.705,0.754,0.804,0.852,0.896,0.934,0.965,0.986,0.998,0.999,0.989,0.97,0.942,0.906,0.865,0.821,0.775,0.73,0.688,0.652,0.622,0.601,0.588,0.585,0.592,0.607,0.629,0.659,0.692,0.728,0.765,0.8,0.83,0.855,0.872,0.881,0.879,0.867,0.845,0.812,0.77,0.72,0.664,0.603,0.54,0.476,0.415,0.357,0.305,0.261,0.226,0.201,0.187,0.184,0.193,0.212,0.242,0.281,0.328,0.381,0.439,0.5,0.563,0.624,0.684,0.74,0.791,0.836,0.874,0.903,0.925,0.938,0.942,0.937,0.925,0.904,0.877,0.843,0.803,0.759,0.712,0.661,0.609,0.557,0.505,0.454,0.405,0.36,0.319,0.282,0.25,0.225,0.205,0.192,0.186,0.186,0.193,0.206,0.224,0.248,0.276,0.307,0.342,0.378,0.414,0.451,0.486,0.518,0.547,0.572,0.592,0.606,0.614,0.616,0.611,0.6,0.584,0.562,0.535,0.505,0.473,0.439,0.405,0.372,0.343,0.317,0.296,0.282,0.276,0.277,0.287,0.305,0.332,0.367,0.409,0.458,0.512,0.57,0.629,0.688,0.746,0.8,0.848,0.889,0.92,0.942,0.953,0.952,0.939,0.915,0.879,0.834,0.781,0.721,0.657,0.591,0.524,0.461,0.402,0.35,0.308,0.276,0.256,0.248,0.253,0.27,0.3,0.339,0.388,0.443,0.503,0.565,0.626,0.685,0.739,0.786,0.823,0.851,0.867,0.872,0.865,0.848,0.429,0.477,0.534,0.597,0.663,0.729,0.793,0.851,0.901,0.94,0.966,0.978,0.975,0.957,0.924,0.877,0.819,0.752,0.679,0.602,0.525,0.451,0.383,0.324,0.276,0.241,0.219,0.212,0.219,0.239,0.271,0.312,0.361,0.414,0.469,0.523,0.573,0.618,0.655,0.683,0.701,0.709,0.708,0.697,0.679,0.656,0.629,0.601,0.574,0.55,0.532,0.52,0.517,0.523,0.539,0.563,0.597,0.637,0.682,0.732,0.782,0.832,0.878,0.919,0.952,0.977,0.992,0.996,0.99,0.974,0.948,0.915,0.875,0.832,0.786,0.74,0.697,0.658,0.625,0.6,0.583,0.576,0.578,0.589,0.607,0.633,0.663,0.697,0.731,0.765,0.796,0.821,0.84,0.85,0.851,0.842,0.823,0.794,0.756,0.709,0.656,0.598,0.537,0.476,0.415,0.358,0.306,0.262,0.226,0.2,0.184,0.18,0.188,0.206,0.235,0.273,0.319,0.373,0.431,0.493,0.557,0.621,0.683,0.741,0.795,0.843,0.884,0.916,0.941,0.956,0.962,0.959,0.948,0.928,0.901,0.866,0.826,0.781,0.731,0.679,0.625,0.57,0.516,0.462,0.412,0.364,0.321,0.282,0.249,0.222,0.202,0.188,0.181,0.181,0.187,0.2,0.218,0.242,0.27,0.301,0.335,0.371,0.407,0.443,0.477,0.509,0.537,0.561,0.58,0.593,0.6,0.601,0.597,0.586,0.569,0.548,0.523,0.494,0.464,0.432,0.401,0.372,0.346,0.324,0.307,0.297,0.294,0.299,0.312,0.334,0.363,0.4,0.443,0.492,0.546,0.602,0.659,0.716,0.769,0.819,0.862,0.898,0.924,0.941,0.946,0.94,0.923,0.894,0.856,0.808,0.754,0.693,0.629,0.564,0.5,0.44,0.385,0.338,0.3,0.273,0.257,0.254,0.264,0.285,0.317,0.359,0.409,0.465,0.524,0.585,0.644,0.701,0.751,0.794,0.828,0.852,0.864,0.865,0.856,0.836,0.412,0.459,0.515,0.577,0.644,0.711,0.777,0.838,0.891,0.933,0.964,0.98,0.982,0.968,0.939,0.896,0.842,0.777,0.705,0.629,0.552,0.478,0.408,0.347,0.296,0.257,0.232,0.22,0.223,0.238,0.266,0.303,0.348,0.399,0.451,0.504,0.553,0.597,0.635,0.663,0.682,0.691,0.691,0.681,0.665,0.642,0.615,0.587,0.56,0.535,0.516,0.503,0.498,0.503,0.517,0.54,0.572,0.611,0.656,0.706,0.757,0.807,0.855,0.899,0.935,0.963,0.981,0.989,0.986,0.973,0.951,0.919,0.882,0.839,0.793,0.747,0.702,0.661,0.625,0.597,0.576,0.565,0.562,0.568,0.583,0.604,0.632,0.663,0.695,0.728,0.758,0.784,0.804,0.817,0.82,0.815,0.799,0.774,0.74,0.698,0.648,0.594,0.536,0.476,0.418,0.362,0.311,0.266,0.23,0.203,0.186,0.181,0.187,0.203,0.231,0.268,0.313,0.366,0.425,0.487,0.551,0.616,0.68,0.741,0.797,0.847,0.89,0.925,0.952,0.97,0.978,0.977,0.967,0.948,0.921,0.887,0.847,0.801,0.751,0.697,0.642,0.585,0.529,0.474,0.422,0.373,0.328,0.288,0.254,0.226,0.205,0.191,0.183,0.183,0.189,0.201,0.219,0.243,0.27,0.301,0.335,0.37,0.406,0.441,0.474,0.505,0.532,0.555,0.573,0.585,0.592,0.593,0.587,0.576,0.56,0.54,0.516,0.489,0.46,0.431,0.403,0.377,0.354,0.335,0.322,0.316,0.316,0.324,0.34,0.364,0.395,0.433,0.477,0.526,0.578,0.632,0.687,0.74,0.79,0.835,0.873,0.904,0.925,0.936,0.936,0.925,0.904,0.872,0.83,0.781,0.725,0.665,0.602,0.539,0.478,0.421,0.37,0.327,0.294,0.272,0.261,0.263,0.276,0.301,0.336,0.379,0.43,0.486,0.545,0.604,0.662,0.715,0.762,0.801,0.831,0.851,0.86,0.858,0.845,0.823,0.395,0.441,0.496,0.557,0.624,0.692,0.76,0.823,0.879,0.925,0.96,0.98,0.986,0.977,0.953,0.914,0.863,0.801,0.732,0.657,0.581,0.506,0.435,0.371,0.318,0.275,0.246,0.23,0.228,0.24,0.263,0.297,0.338,0.386,0.436,0.486,0.535,0.578,0.615,0.644,0.664,0.674,0.674,0.666,0.65,0.628,0.602,0.573,0.545,0.52,0.499,0.485,0.479,0.481,0.493,0.514,0.545,0.583,0.627,0.676,0.728,0.779,0.829,0.874,0.913,0.944,0.966,0.977,0.978,0.968,0.948,0.92,0.884,0.842,0.797,0.75,0.704,0.661,0.623,0.591,0.567,0.551,0.544,0.546,0.556,0.574,0.598,0.626,0.657,0.688,0.718,0.745,0.766,0.781,0.788,0.785,0.774,0.753,0.723,0.685,0.64,0.59,0.535,0.479,0.423,0.369,0.319,0.275,0.238,0.211,0.193,0.186,0.19,0.205,0.231,0.266,0.31,0.362,0.419,0.481,0.546,0.611,0.676,0.738,0.795,0.847,0.893,0.93,0.959,0.979,0.989,0.99,0.981,0.964,0.938,0.905,0.865,0.819,0.768,0.715,0.658,0.601,0.544,0.489,0.435,0.385,0.34,0.299,0.264,0.236,0.214,0.2,0.192,0.191,0.197,0.21,0.228,0.251,0.278,0.309,0.342,0.376,0.411,0.445,0.478,0.507,0.533,0.555,0.572,0.583,0.589,0.589,0.584,0.573,0.557,0.537,0.514,0.489,0.462,0.435,0.41,0.386,0.366,0.351,0.341,0.338,0.341,0.352,0.37,0.396,0.428,0.467,0.51,0.558,0.609,0.661,0.712,0.762,0.807,0.847,0.881,0.906,0.922,0.927,0.923,0.908,0.882,0.847,0.804,0.753,0.697,0.637,0.576,0.515,0.457,0.404,0.357,0.319,0.291,0.273,0.267,0.273,0.29,0.318,0.355,0.401,0.452,0.508,0.566,0.623,0.678,0.728,0.772,0.807,0.833,0.849,0.854,0.849,0.834,0.81,0.379,0.422,0.476,0.537,0.603,0.672,0.741,0.806,0.865,0.915,0.954,0.979,0.989,0.985,0.965,0.931,0.883,0.825,0.758,0.685,0.609,0.534,0.462,0.397,0.341,0.295,0.262,0.243,0.237,0.244,0.263,0.292,0.33,0.375,0.422,0.471,0.518,0.561,0.598,0.627,0.647,0.658,0.659,0.651,0.636,0.614,0.588,0.56,0.531,0.505,0.482,0.466,0.458,0.458,0.468,0.487,0.516,0.552,0.596,0.644,0.696,0.748,0.799,0.846,0.887,0.921,0.946,0.96,0.965,0.958,0.941,0.916,0.882,0.841,0.797,0.75,0.703,0.659,0.618,0.583,0.555,0.535,0.524,0.522,0.528,0.542,0.562,0.588,0.616,0.646,0.676,0.703,0.726,0.743,0.753,0.754,0.747,0.731,0.706,0.673,0.632,0.586,0.536,0.483,0.43,0.378,0.33,0.287,0.25,0.223,0.204,0.196,0.198,0.211,0.235,0.268,0.31,0.36,0.416,0.477,0.541,0.606,0.67,0.733,0.791,0.844,0.891,0.93,0.961,0.983,0.995,0.997,0.991,0.975,0.951,0.918,0.879,0.834,0.784,0.731,0.675,0.618,0.561,0.505,0.451,0.401,0.355,0.315,0.28,0.251,0.23,0.215,0.208,0.207,0.213,0.225,0.243,0.266,0.293,0.323,0.356,0.389,0.423,0.456,0.488,0.516,0.541,0.561,0.577,0.588,0.593,0.592,0.586,0.575,0.56,0.541,0.518,0.494,0.469,0.444,0.421,0.4,0.383,0.37,0.363,0.363,0.368,0.381,0.401,0.428,0.461,0.499,0.542,0.589,0.637,0.686,0.734,0.78,0.821,0.856,0.884,0.904,0.915,0.916,0.907,0.888,0.859,0.822,0.776,0.725,0.669,0.61,0.551,0.492,0.438,0.388,0.346,0.313,0.289,0.277,0.275,0.285,0.306,0.336,0.376,0.422,0.474,0.529,0.586,0.641,0.693,0.74,0.78,0.812,0.834,0.846,0.848,0.839,0.822,0.795,0.362,0.404,0.455,0.516,0.582,0.651,0.721,0.789,0.85,0.904,0.946,0.975,0.991,0.991,0.976,0.946,0.902,0.847,0.783,0.712,0.638,0.563,0.491,0.424,0.365,0.317,0.281,0.257,0.247,0.25,0.265,0.29,0.325,0.366,0.411,0.457,0.503,0.545,0.581,0.61,0.631,0.642,0.644,0.637,0.623,0.601,0.575,0.546,0.517,0.49,0.466,0.448,0.437,0.435,0.443,0.459,0.486,0.52,0.562,0.61,0.661,0.713,0.765,0.814,0.857,0.894,0.922,0.94,0.947,0.944,0.931,0.907,0.876,0.837,0.794,0.747,0.7,0.654,0.611,0.573,0.542,0.518,0.503,0.496,0.498,0.508,0.525,0.548,0.575,0.603,0.633,0.66,0.685,0.704,0.717,0.722,0.719,0.708,0.688,0.66,0.625,0.584,0.538,0.489,0.439,0.39,0.344,0.302,0.267,0.239,0.22,0.21,0.211,0.222,0.243,0.273,0.313,0.361,0.415,0.474,0.536,0.6,0.664,0.726,0.785,0.838,0.886,0.926,0.958,0.982,0.996,1.0,0.995,0.981,0.958,0.928,0.89,0.846,0.798,0.745,0.69,0.634,0.578,0.522,0.469,0.42,0.375,0.334,0.3,0.272,0.251,0.237,0.229,0.229,0.235,0.248,0.266,0.288,0.315,0.345,0.376,0.409,0.442,0.474,0.504,0.531,0.555,0.574,0.588,0.598,0.602,0.6,0.594,0.583,0.568,0.549,0.527,0.504,0.481,0.458,0.437,0.418,0.403,0.393,0.388,0.389,0.397,0.411,0.432,0.459,0.492,0.53,0.572,0.617,0.663,0.709,0.753,0.794,0.831,0.861,0.884,0.899,0.905,0.902,0.889,0.866,0.834,0.795,0.748,0.697,0.641,0.584,0.527,0.472,0.421,0.376,0.338,0.309,0.291,0.283,0.285,0.299,0.323,0.356,0.397,0.444,0.496,0.55,0.605,0.658,0.707,0.75,0.786,0.814,0.832,0.841,0.839,0.828,0.808,0.781,0.346,0.385,0.435,0.494,0.56,0.629,0.7,0.769,0.834,0.89,0.936,0.97,0.99,0.995,0.984,0.959,0.92,0.869,0.808,0.739,0.666,0.592,0.52,0.452,0.391,0.34,0.301,0.273,0.259,0.258,0.269,0.291,0.321,0.359,0.402,0.446,0.49,0.531,0.567,0.596,0.617,0.628,0.631,0.625,0.611,0.59,0.563,0.534,0.504,0.475,0.45,0.43,0.417,0.412,0.417,0.431,0.455,0.487,0.527,0.573,0.624,0.676,0.729,0.779,0.824,0.863,0.894,0.915,0.926,0.926,0.916,0.896,0.866,0.83,0.787,0.741,0.694,0.646,0.602,0.561,0.527,0.5,0.481,0.47,0.468,0.474,0.488,0.508,0.532,0.56,0.588,0.616,0.642,0.664,0.68,0.689,0.691,0.684,0.67,0.647,0.618,0.582,0.541,0.497,0.451,0.406,0.362,0.322,0.287,0.259,0.24,0.229,0.228,0.236,0.255,0.283,0.32,0.364,0.416,0.472,0.532,0.594,0.656,0.717,0.776,0.829,0.877,0.918,0.951,0.975,0.991,0.997,0.994,0.982,0.961,0.932,0.897,0.855,0.808,0.757,0.704,0.649,0.594,0.54,0.489,0.44,0.396,0.357,0.324,0.297,0.277,0.264,0.257,0.257,0.264,0.277,0.295,0.317,0.343,0.373,0.404,0.436,0.467,0.498,0.527,0.552,0.574,0.592,0.605,0.613,0.616,0.614,0.607,0.596,0.58,0.562,0.541,0.519,0.497,0.475,0.455,0.439,0.425,0.417,0.414,0.417,0.426,0.441,0.463,0.49,0.523,0.56,0.6,0.642,0.685,0.728,0.768,0.805,0.837,0.862,0.881,0.891,0.892,0.885,0.868,0.842,0.808,0.767,0.72,0.669,0.614,0.559,0.504,0.453,0.406,0.365,0.332,0.308,0.294,0.291,0.298,0.315,0.341,0.376,0.419,0.466,0.518,0.571,0.623,0.673,0.719,0.759,0.791,0.815,0.83,0.835,0.83,0.816,0.794,0.765,0.331,0.367,0.415,0.472,0.537,0.606,0.678,0.749,0.815,0.875,0.925,0.963,0.987,0.997,0.991,0.971,0.936,0.889,0.831,0.765,0.694,0.621,0.549,0.48,0.418,0.365,0.322,0.292,0.274,0.268,0.275,0.293,0.32,0.355,0.395,0.437,0.479,0.519,0.554,0.583,0.604,0.616,0.619,0.614,0.6,0.579,0.553,0.523,0.492,0.462,0.434,0.412,0.397,0.389,0.391,0.402,0.423,0.453,0.491,0.536,0.585,0.637,0.69,0.741,0.788,0.829,0.862,0.886,0.901,0.904,0.897,0.88,0.854,0.819,0.779,0.733,0.686,0.638,0.591,0.549,0.511,0.481,0.458,0.444,0.438,0.44,0.45,0.467,0.489,0.515,0.544,0.572,0.599,0.623,0.642,0.655,0.661,0.66,0.651,0.635,0.611,0.581,0.546,0.507,0.465,0.423,0.383,0.345,0.311,0.284,0.264,0.252,0.249,0.255,0.271,0.296,0.33,0.371,0.419,0.472,0.529,0.588,0.649,0.708,0.764,0.817,0.865,0.905,0.939,0.964,0.981,0.989,0.987,0.977,0.958,0.932,0.898,0.859,0.814,0.766,0.715,0.663,0.61,0.558,0.509,0.462,0.42,0.383,0.352,0.326,0.307,0.295,0.29,0.291,0.298,0.311,0.33,0.352,0.378,0.407,0.437,0.468,0.499,0.528,0.555,0.579,0.6,0.616,0.628,0.634,0.636,0.633,0.625,0.613,0.597,0.579,0.558,0.537,0.516,0.495,0.477,0.461,0.45,0.443,0.441,0.445,0.455,0.471,0.492,0.519,0.551,0.586,0.624,0.664,0.704,0.743,0.779,0.811,0.839,0.86,0.874,0.879,0.877,0.865,0.845,0.817,0.781,0.739,0.692,0.641,0.589,0.536,0.484,0.436,0.393,0.357,0.329,0.31,0.3,0.301,0.311,0.332,0.361,0.398,0.441,0.488,0.539,0.59,0.64,0.688,0.73,0.766,0.795,0.815,0.825,0.827,0.819,0.803,0.78,0.75,0.316,0.349,0.394,0.45,0.513,0.583,0.655,0.727,0.795,0.858,0.911,0.953,0.982,0.997,0.996,0.981,0.951,0.908,0.854,0.791,0.722,0.65,0.578,0.509,0.446,0.391,0.345,0.311,0.29,0.281,0.284,0.298,0.322,0.353,0.39,0.43,0.47,0.509,0.543,0.572,0.593,0.606,0.609,0.604,0.591,0.57,0.544,0.514,0.482,0.45,0.421,0.396,0.378,0.368,0.366,0.374,0.392,0.419,0.455,0.497,0.545,0.596,0.649,0.701,0.749,0.792,0.828,0.855,0.872,0.879,0.876,0.862,0.838,0.806,0.767,0.723,0.676,0.627,0.58,0.535,0.495,0.462,0.435,0.417,0.408,0.406,0.413,0.427,0.447,0.472,0.499,0.528,0.556,0.582,0.604,0.621,0.632,0.636,0.633,0.623,0.605,0.581,0.551,0.518,0.481,0.444,0.406,0.371,0.339,0.313,0.292,0.28,0.275,0.279,0.292,0.313,0.343,0.38,0.424,0.474,0.527,0.583,0.64,0.697,0.751,0.802,0.849,0.889,0.922,0.948,0.966,0.974,0.975,0.966,0.95,0.926,0.895,0.858,0.817,0.771,0.723,0.674,0.624,0.575,0.528,0.485,0.445,0.411,0.381,0.358,0.341,0.331,0.327,0.329,0.338,0.351,0.37,0.392,0.418,0.446,0.476,0.506,0.535,0.563,0.589,0.611,0.63,0.644,0.654,0.66,0.66,0.655,0.647,0.634,0.618,0.599,0.579,0.558,0.537,0.517,0.5,0.486,0.475,0.469,0.468,0.473,0.483,0.499,0.52,0.546,0.576,0.61,0.645,0.682,0.719,0.754,0.786,0.814,0.837,0.854,0.863,0.865,0.858,0.844,0.821,0.791,0.754,0.711,0.665,0.615,0.564,0.514,0.466,0.422,0.384,0.352,0.328,0.314,0.309,0.313,0.327,0.35,0.381,0.419,0.463,0.51,0.559,0.609,0.656,0.7,0.739,0.771,0.796,0.812,0.82,0.818,0.808,0.79,0.765,0.734,0.301,0.332,0.374,0.428,0.49,0.558,0.63,0.703,0.774,0.839,0.896,0.942,0.975,0.995,0.999,0.989,0.963,0.925,0.875,0.815,0.749,0.679,0.608,0.538,0.474,0.417,0.37,0.333,0.308,0.295,0.295,0.305,0.325,0.354,0.388,0.425,0.464,0.501,0.535,0.563,0.584,0.597,0.601,0.597,0.584,0.563,0.537,0.506,0.473,0.44,0.409,0.382,0.361,0.347,0.343,0.347,0.362,0.386,0.418,0.458,0.505,0.555,0.607,0.659,0.708,0.753,0.791,0.821,0.841,0.852,0.851,0.841,0.82,0.791,0.754,0.711,0.664,0.616,0.568,0.522,0.48,0.443,0.414,0.392,0.379,0.374,0.377,0.388,0.406,0.429,0.456,0.484,0.514,0.542,0.567,0.588,0.603,0.613,0.615,0.611,0.6,0.582,0.559,0.531,0.499,0.466,0.433,0.4,0.37,0.345,0.325,0.311,0.305,0.306,0.316,0.334,0.36,0.393,0.433,0.477,0.527,0.578,0.632,0.685,0.737,0.785,0.83,0.869,0.902,0.927,0.945,0.955,0.957,0.95,0.936,0.915,0.887,0.853,0.815,0.772,0.728,0.682,0.636,0.59,0.547,0.507,0.471,0.439,0.413,0.392,0.378,0.369,0.367,0.371,0.381,0.395,0.414,0.437,0.463,0.49,0.519,0.548,0.576,0.603,0.626,0.647,0.664,0.677,0.685,0.688,0.687,0.681,0.671,0.658,0.641,0.622,0.602,0.581,0.56,0.541,0.524,0.51,0.5,0.495,0.494,0.499,0.509,0.525,0.545,0.57,0.598,0.629,0.662,0.696,0.729,0.761,0.789,0.813,0.831,0.844,0.849,0.847,0.838,0.82,0.795,0.764,0.726,0.684,0.638,0.59,0.542,0.495,0.451,0.411,0.376,0.349,0.33,0.32,0.319,0.327,0.344,0.37,0.402,0.441,0.485,0.531,0.579,0.626,0.67,0.711,0.746,0.775,0.796,0.808,0.812,0.808,0.795,0.775,0.749,0.718,0.288,0.315,0.354,0.405,0.466,0.533,0.605,0.679,0.751,0.818,0.878,0.928,0.966,0.99,1.0,0.994,0.974,0.94,0.894,0.838,0.775,0.707,0.637,0.568,0.503,0.445,0.395,0.356,0.328,0.312,0.307,0.314,0.331,0.356,0.388,0.423,0.46,0.496,0.529,0.556,0.577,0.591,0.595,0.591,0.579,0.558,0.532,0.501,0.467,0.432,0.399,0.369,0.346,0.329,0.321,0.322,0.333,0.353,0.383,0.42,0.464,0.513,0.564,0.616,0.666,0.712,0.752,0.784,0.808,0.822,0.825,0.818,0.8,0.773,0.739,0.698,0.652,0.604,0.555,0.508,0.464,0.425,0.393,0.368,0.351,0.343,0.343,0.351,0.367,0.388,0.414,0.442,0.472,0.502,0.53,0.555,0.575,0.59,0.598,0.6,0.595,0.584,0.567,0.545,0.519,0.491,0.461,0.432,0.405,0.38,0.361,0.346,0.339,0.338,0.345,0.359,0.38,0.409,0.443,0.483,0.527,0.575,0.623,0.672,0.721,0.766,0.808,0.845,0.877,0.902,0.92,0.93,0.933,0.928,0.916,0.898,0.873,0.842,0.807,0.769,0.728,0.686,0.644,0.603,0.564,0.528,0.495,0.467,0.444,0.427,0.415,0.41,0.41,0.415,0.426,0.442,0.462,0.485,0.511,0.538,0.566,0.594,0.62,0.645,0.668,0.686,0.701,0.712,0.718,0.72,0.717,0.709,0.698,0.683,0.666,0.646,0.625,0.604,0.583,0.564,0.548,0.534,0.524,0.519,0.519,0.523,0.533,0.548,0.567,0.59,0.616,0.645,0.675,0.706,0.736,0.763,0.787,0.807,0.822,0.831,0.833,0.827,0.815,0.795,0.769,0.737,0.699,0.658,0.613,0.567,0.522,0.478,0.438,0.402,0.372,0.35,0.335,0.329,0.332,0.343,0.363,0.39,0.424,0.463,0.506,0.551,0.597,0.641,0.683,0.72,0.752,0.777,0.794,0.803,0.804,0.796,0.782,0.76,0.734,0.702],"radius":[1.182,1.122,1.078,1.054,1.051,1.073,1.118,1.186,1.276,1.384,1.508,1.642,1.782,1.922,2.057,2.181,2.29,2.38,2.446,2.486,2.499,2.484,2.442,2.375,2.286,2.179,2.057,1.927,1.793,1.659,1.533,1.417,1.316,1.233,1.17,1.129,1.11,1.112,1.133,1.171,1.222,1.284,1.351,1.419,1.485,1.544,1.593,1.628,1.649,1.653,1.64,1.61,1.565,1.506,1.436,1.358,1.276,1.193,1.114,1.041,0.978,0.927,0.892,0.873,0.872,0.887,0.92,0.968,1.029,1.101,1.181,1.265,1.35,1.433,1.509,1.577,1.633,1.676,1.703,1.713,1.707,1.684,1.646,1.593,1.529,1.455,1.375,1.29,1.205,1.122,1.045,0.976,0.918,0.872,0.841,0.825,0.825,0.843,0.876,0.925,0.989,1.065,1.152,1.249,1.353,1.461,1.571,1.681,1.79,1.893,1.991,2.08,2.161,2.23,2.288,2.334,2.366,2.386,2.393,2.387,2.368,2.338,2.297,2.245,2.184,2.115,2.038,1.956,1.868,1.778,1.685,1.59,1.497,1.405,1.315,1.23,1.151,1.077,1.012,0.954,0.907,0.869,0.842,0.826,0.821,0.827,0.845,0.874,0.913,0.961,1.018,1.082,1.153,1.228,1.305,1.384,1.462,1.538,1.61,1.676,1.735,1.785,1.825,1.854,1.871,1.875,1.867,1.847,1.814,1.77,1.716,1.652,1.581,1.504,1.423,1.34,1.256,1.175,1.098,1.027,0.964,0.911,0.869,0.84,0.823,0.821,0.832,0.857,0.896,0.948,1.011,1.085,1.167,1.257,1.351,1.449,1.547,1.645,1.739,1.828,1.91,1.984,2.048,2.1,2.14,2.168,2.183,2.184,2.173,2.15,2.115,2.07,2.016,1.954,1.886,1.814,1.74,1.665,1.592,1.521,1.455,1.396,1.345,1.303,1.271,1.25,1.241,1.244,1.258,1.285,1.322,1.37,1.426,1.49,1.559,1.632,1.706,1.78,1.851,1.916,1.174,1.12,1.083,1.067,1.073,1.103,1.156,1.231,1.327,1.441,1.567,1.703,1.842,1.98,2.11,2.228,2.329,2.409,2.464,2.492,2.493,2.466,2.413,2.335,2.236,2.12,1.992,1.857,1.72,1.586,1.461,1.348,1.252,1.175,1.12,1.087,1.076,1.086,1.115,1.16,1.217,1.284,1.354,1.425,1.492,1.55,1.597,1.631,1.648,1.648,1.631,1.598,1.549,1.488,1.417,1.34,1.259,1.179,1.104,1.037,0.981,0.939,0.912,0.903,0.911,0.936,0.977,1.033,1.101,1.178,1.261,1.347,1.432,1.513,1.586,1.648,1.698,1.732,1.749,1.75,1.734,1.701,1.652,1.591,1.518,1.436,1.35,1.26,1.172,1.088,1.01,0.942,0.886,0.844,0.817,0.806,0.812,0.834,0.873,0.926,0.994,1.073,1.163,1.26,1.364,1.471,1.579,1.686,1.789,1.888,1.98,2.063,2.136,2.199,2.251,2.291,2.318,2.333,2.336,2.327,2.307,2.276,2.236,2.186,2.127,2.062,1.99,1.913,1.832,1.747,1.661,1.574,1.487,1.401,1.318,1.239,1.165,1.096,1.034,0.98,0.935,0.899,0.873,0.858,0.853,0.86,0.877,0.905,0.943,0.991,1.047,1.111,1.181,1.257,1.335,1.416,1.496,1.574,1.649,1.719,1.782,1.836,1.881,1.914,1.936,1.946,1.942,1.926,1.897,1.857,1.805,1.743,1.673,1.596,1.514,1.429,1.343,1.257,1.175,1.099,1.029,0.968,0.918,0.879,0.854,0.841,0.843,0.858,0.887,0.93,0.984,1.049,1.124,1.206,1.294,1.387,1.481,1.576,1.668,1.757,1.839,1.915,1.981,2.037,2.082,2.116,2.137,2.146,2.142,2.127,2.101,2.064,2.018,1.965,1.905,1.84,1.772,1.702,1.633,1.566,1.503,1.444,1.392,1.348,1.314,1.289,1.274,1.271,1.279,1.298,1.328,1.367,1.416,1.472,1.535,1.602,1.672,1.742,1.81,1.874,1.168,1.121,1.092,1.084,1.098,1.135,1.196,1.278,1.379,1.497,1.626,1.762,1.9,2.034,2.16,2.27,2.362,2.432,2.476,2.493,2.481,2.442,2.377,2.289,2.181,2.058,1.924,1.785,1.647,1.513,1.39,1.282,1.191,1.121,1.074,1.049,1.046,1.065,1.102,1.154,1.218,1.289,1.363,1.436,1.503,1.561,1.606,1.637,1.651,1.647,1.627,1.59,1.54,1.477,1.405,1.328,1.25,1.174,1.103,1.043,0.994,0.96,0.942,0.942,0.959,0.993,1.043,1.106,1.18,1.262,1.348,1.435,1.519,1.597,1.666,1.722,1.764,1.79,1.798,1.789,1.762,1.719,1.662,1.591,1.511,1.423,1.331,1.238,1.148,1.063,0.986,0.92,0.867,0.829,0.806,0.8,0.811,0.838,0.881,0.938,1.009,1.09,1.18,1.277,1.379,1.483,1.587,1.688,1.786,1.878,1.962,2.038,2.104,2.159,2.204,2.237,2.259,2.269,2.269,2.258,2.237,2.206,2.167,2.12,2.066,2.005,1.94,1.869,1.796,1.719,1.641,1.562,1.483,1.406,1.33,1.258,1.19,1.127,1.07,1.02,0.977,0.944,0.919,0.905,0.9,0.906,0.922,0.949,0.986,1.032,1.087,1.15,1.219,1.294,1.373,1.454,1.535,1.615,1.693,1.765,1.832,1.89,1.939,1.977,2.004,2.018,2.019,2.008,1.983,1.946,1.898,1.838,1.77,1.694,1.611,1.525,1.436,1.348,1.262,1.18,1.104,1.036,0.978,0.931,0.896,0.875,0.867,0.872,0.892,0.924,0.969,1.026,1.092,1.167,1.248,1.335,1.424,1.514,1.604,1.69,1.772,1.848,1.916,1.974,2.023,2.061,2.087,2.102,2.106,2.098,2.079,2.05,2.013,1.967,1.915,1.858,1.796,1.733,1.669,1.606,1.546,1.489,1.438,1.394,1.357,1.329,1.31,1.302,1.304,1.316,1.339,1.371,1.412,1.461,1.517,1.577,1.641,1.707,1.772,1.835,1.166,1.125,1.104,1.103,1.125,1.17,1.237,1.326,1.432,1.553,1.684,1.82,1.955,2.085,2.204,2.307,2.39,2.449,2.482,2.486,2.463,2.413,2.337,2.239,2.122,1.992,1.854,1.712,1.573,1.441,1.321,1.217,1.133,1.071,1.032,1.016,1.023,1.05,1.095,1.154,1.224,1.299,1.377,1.451,1.519,1.576,1.619,1.647,1.658,1.651,1.627,1.588,1.535,1.471,1.399,1.323,1.248,1.176,1.111,1.057,1.016,0.99,0.982,0.991,1.017,1.06,1.117,1.187,1.266,1.351,1.44,1.527,1.609,1.684,1.748,1.797,1.832,1.848,1.847,1.828,1.792,1.74,1.673,1.595,1.508,1.415,1.319,1.223,1.132,1.047,0.972,0.909,0.86,0.826,0.808,0.807,0.823,0.854,0.901,0.961,1.033,1.115,1.205,1.3,1.398,1.497,1.595,1.69,1.78,1.863,1.939,2.006,2.063,2.11,2.147,2.174,2.19,2.196,2.192,2.179,2.158,2.129,2.092,2.049,2.0,1.946,1.888,1.826,1.761,1.694,1.626,1.556,1.487,1.419,1.352,1.287,1.226,1.169,1.117,1.072,1.033,1.001,0.978,0.964,0.959,0.964,0.979,1.004,1.039,1.083,1.136,1.197,1.265,1.338,1.416,1.497,1.578,1.66,1.739,1.814,1.883,1.944,1.997,2.04,2.071,2.09,2.096,2.089,2.069,2.036,1.991,1.935,1.869,1.794,1.712,1.625,1.535,1.444,1.355,1.268,1.187,1.113,1.048,0.994,0.95,0.92,0.903,0.899,0.909,0.932,0.967,1.015,1.072,1.139,1.213,1.293,1.376,1.461,1.547,1.63,1.71,1.785,1.853,1.913,1.964,2.005,2.035,2.055,2.064,2.063,2.051,2.03,2.0,1.962,1.918,1.868,1.813,1.757,1.698,1.64,1.584,1.53,1.481,1.437,1.4,1.37,1.348,1.336,1.332,1.339,1.354,1.379,1.413,1.455,1.503,1.558,1.616,1.677,1.738,1.798,1.166,1.133,1.118,1.125,1.154,1.206,1.28,1.374,1.484,1.608,1.739,1.874,2.007,2.132,2.244,2.339,2.412,2.46,2.481,2.474,2.439,2.377,2.291,2.184,2.06,1.924,1.782,1.638,1.499,1.37,1.254,1.157,1.08,1.026,0.996,0.989,1.005,1.04,1.093,1.16,1.235,1.315,1.395,1.471,1.539,1.595,1.637,1.662,1.669,1.659,1.632,1.59,1.535,1.47,1.399,1.325,1.252,1.185,1.126,1.079,1.046,1.029,1.029,1.047,1.082,1.133,1.198,1.273,1.357,1.446,1.535,1.621,1.702,1.772,1.83,1.873,1.899,1.907,1.897,1.869,1.823,1.762,1.687,1.602,1.509,1.412,1.313,1.216,1.125,1.042,0.969,0.91,0.865,0.836,0.823,0.827,0.847,0.883,0.932,0.994,1.067,1.148,1.235,1.327,1.42,1.513,1.604,1.69,1.771,1.845,1.91,1.967,2.015,2.054,2.082,2.102,2.112,2.114,2.107,2.093,2.072,2.045,2.012,1.975,1.933,1.886,1.837,1.785,1.73,1.674,1.616,1.558,1.499,1.44,1.383,1.327,1.273,1.223,1.177,1.136,1.1,1.071,1.049,1.035,1.03,1.034,1.047,1.069,1.101,1.142,1.192,1.25,1.315,1.387,1.463,1.542,1.623,1.705,1.785,1.861,1.933,1.997,2.053,2.1,2.136,2.159,2.17,2.168,2.153,2.124,2.083,2.03,1.967,1.894,1.813,1.727,1.637,1.544,1.452,1.362,1.277,1.198,1.126,1.065,1.014,0.975,0.95,0.937,0.938,0.951,0.978,1.016,1.065,1.123,1.189,1.261,1.338,1.418,1.498,1.578,1.655,1.727,1.794,1.854,1.906,1.949,1.982,2.006,2.02,2.024,2.018,2.004,1.981,1.95,1.913,1.87,1.823,1.773,1.721,1.669,1.617,1.567,1.52,1.478,1.441,1.41,1.387,1.371,1.363,1.365,1.374,1.393,1.42,1.454,1.496,1.543,1.595,1.651,1.708,1.764,1.169,1.143,1.135,1.149,1.186,1.244,1.324,1.422,1.536,1.661,1.793,1.926,2.055,2.175,2.28,2.365,2.428,2.466,2.475,2.456,2.41,2.337,2.241,2.125,1.995,1.854,1.709,1.565,1.427,1.301,1.19,1.099,1.03,0.985,0.965,0.968,0.993,1.037,1.098,1.171,1.252,1.336,1.419,1.496,1.564,1.619,1.658,1.68,1.685,1.671,1.641,1.597,1.54,1.475,1.404,1.333,1.264,1.201,1.148,1.108,1.083,1.075,1.084,1.11,1.154,1.212,1.283,1.364,1.452,1.543,1.632,1.718,1.795,1.861,1.912,1.948,1.966,1.965,1.946,1.908,1.854,1.785,1.703,1.612,1.514,1.414,1.313,1.217,1.126,1.045,0.976,0.921,0.881,0.857,0.85,0.859,0.883,0.922,0.974,1.037,1.109,1.188,1.272,1.358,1.445,1.53,1.612,1.688,1.759,1.822,1.877,1.923,1.961,1.99,2.01,2.022,2.027,2.025,2.016,2.001,1.982,1.958,1.93,1.898,1.864,1.827,1.788,1.746,1.703,1.658,1.613,1.566,1.518,1.471,1.423,1.376,1.331,1.288,1.248,1.211,1.178,1.151,1.13,1.116,1.11,1.112,1.122,1.141,1.17,1.207,1.253,1.307,1.369,1.437,1.51,1.588,1.668,1.749,1.829,1.906,1.979,2.046,2.105,2.156,2.195,2.223,2.239,2.242,2.231,2.207,2.171,2.122,2.062,1.992,1.914,1.828,1.738,1.646,1.552,1.46,1.371,1.287,1.211,1.143,1.086,1.04,1.006,0.985,0.977,0.982,0.999,1.029,1.069,1.118,1.177,1.241,1.311,1.384,1.459,1.534,1.607,1.676,1.741,1.799,1.851,1.895,1.93,1.956,1.973,1.982,1.981,1.972,1.955,1.931,1.901,1.866,1.826,1.782,1.737,1.69,1.644,1.599,1.556,1.516,1.48,1.45,1.425,1.407,1.397,1.393,1.398,1.411,1.431,1.459,1.493,1.534,1.58,1.629,1.681,1.734,1.175,1.155,1.155,1.176,1.219,1.283,1.368,1.471,1.587,1.713,1.844,1.975,2.099,2.213,2.31,2.387,2.439,2.465,2.463,2.433,2.375,2.292,2.187,2.064,1.927,1.783,1.636,1.492,1.356,1.234,1.13,1.046,0.986,0.95,0.939,0.952,0.987,1.04,1.109,1.189,1.275,1.363,1.448,1.526,1.593,1.646,1.683,1.702,1.704,1.687,1.654,1.608,1.55,1.484,1.415,1.346,1.28,1.223,1.176,1.143,1.126,1.127,1.144,1.179,1.231,1.296,1.373,1.459,1.549,1.641,1.731,1.814,1.887,1.948,1.993,2.021,2.03,2.021,1.992,1.946,1.884,1.808,1.72,1.624,1.523,1.42,1.32,1.224,1.136,1.058,0.994,0.944,0.909,0.891,0.888,0.902,0.93,0.972,1.025,1.088,1.159,1.235,1.314,1.394,1.472,1.548,1.62,1.685,1.744,1.795,1.838,1.873,1.9,1.92,1.932,1.937,1.936,1.93,1.92,1.905,1.888,1.868,1.846,1.822,1.796,1.769,1.741,1.711,1.681,1.649,1.615,1.581,1.546,1.509,1.472,1.435,1.398,1.362,1.327,1.295,1.266,1.24,1.22,1.205,1.197,1.196,1.203,1.218,1.242,1.275,1.316,1.366,1.423,1.487,1.557,1.631,1.709,1.789,1.868,1.946,2.02,2.089,2.151,2.204,2.248,2.28,2.301,2.308,2.303,2.284,2.252,2.208,2.152,2.085,2.01,1.927,1.838,1.745,1.651,1.557,1.466,1.379,1.299,1.226,1.163,1.111,1.07,1.041,1.025,1.022,1.031,1.052,1.084,1.125,1.175,1.232,1.295,1.361,1.43,1.499,1.567,1.632,1.693,1.75,1.8,1.843,1.879,1.907,1.926,1.938,1.941,1.937,1.925,1.907,1.883,1.854,1.821,1.785,1.746,1.706,1.665,1.625,1.586,1.55,1.517,1.487,1.463,1.444,1.431,1.424,1.425,1.432,1.447,1.468,1.496,1.53,1.569,1.612,1.659,1.707,1.184,1.17,1.176,1.204,1.253,1.323,1.413,1.518,1.637,1.763,1.893,2.02,2.14,2.246,2.335,2.402,2.445,2.459,2.446,2.405,2.336,2.243,2.13,2.0,1.858,1.711,1.563,1.42,1.288,1.171,1.074,0.998,0.947,0.921,0.92,0.943,0.987,1.05,1.126,1.212,1.303,1.394,1.481,1.56,1.626,1.678,1.712,1.728,1.726,1.706,1.671,1.622,1.563,1.498,1.43,1.363,1.302,1.25,1.21,1.184,1.175,1.184,1.21,1.253,1.311,1.383,1.465,1.555,1.647,1.74,1.828,1.908,1.977,2.032,2.07,2.09,2.092,2.073,2.037,1.983,1.913,1.83,1.738,1.638,1.535,1.431,1.331,1.237,1.153,1.08,1.021,0.976,0.947,0.935,0.938,0.956,0.988,1.031,1.085,1.147,1.215,1.287,1.36,1.432,1.502,1.567,1.627,1.681,1.727,1.765,1.796,1.819,1.835,1.844,1.848,1.847,1.841,1.832,1.82,1.807,1.792,1.777,1.762,1.746,1.73,1.714,1.698,1.681,1.664,1.645,1.625,1.604,1.581,1.556,1.53,1.502,1.473,1.444,1.415,1.387,1.36,1.336,1.316,1.3,1.289,1.285,1.288,1.298,1.317,1.344,1.38,1.424,1.475,1.535,1.6,1.671,1.746,1.823,1.901,1.978,2.053,2.123,2.187,2.244,2.291,2.328,2.353,2.365,2.365,2.352,2.325,2.285,2.234,2.172,2.1,2.019,1.933,1.842,1.748,1.654,1.561,1.472,1.388,1.312,1.244,1.186,1.139,1.104,1.081,1.071,1.072,1.085,1.109,1.142,1.184,1.234,1.289,1.348,1.41,1.473,1.536,1.596,1.654,1.707,1.754,1.796,1.831,1.859,1.879,1.893,1.899,1.898,1.891,1.878,1.86,1.837,1.81,1.781,1.748,1.715,1.68,1.645,1.612,1.579,1.549,1.522,1.499,1.48,1.466,1.457,1.454,1.457,1.466,1.481,1.503,1.53,1.563,1.6,1.641,1.684,1.194,1.187,1.199,1.233,1.288,1.363,1.457,1.565,1.685,1.811,1.939,2.062,2.176,2.275,2.356,2.413,2.445,2.448,2.424,2.371,2.293,2.191,2.07,1.934,1.788,1.639,1.491,1.351,1.223,1.112,1.022,0.955,0.914,0.898,0.908,0.941,0.994,1.065,1.149,1.241,1.337,1.431,1.52,1.598,1.663,1.713,1.744,1.757,1.751,1.728,1.69,1.639,1.58,1.515,1.449,1.385,1.328,1.281,1.248,1.229,1.228,1.245,1.279,1.329,1.394,1.472,1.558,1.651,1.745,1.837,1.923,2.0,2.064,2.112,2.143,2.156,2.149,2.122,2.077,2.016,1.94,1.852,1.755,1.653,1.548,1.446,1.347,1.257,1.177,1.109,1.056,1.018,0.996,0.989,0.997,1.02,1.054,1.1,1.154,1.214,1.278,1.344,1.41,1.473,1.532,1.586,1.634,1.674,1.707,1.732,1.75,1.761,1.766,1.766,1.761,1.753,1.743,1.731,1.719,1.708,1.697,1.687,1.679,1.672,1.667,1.663,1.659,1.656,1.652,1.648,1.641,1.633,1.623,1.61,1.594,1.576,1.556,1.533,1.509,1.485,1.46,1.437,1.416,1.398,1.384,1.376,1.374,1.379,1.391,1.412,1.441,1.479,1.524,1.578,1.638,1.704,1.775,1.849,1.926,2.002,2.076,2.147,2.213,2.272,2.323,2.364,2.393,2.411,2.416,2.408,2.387,2.353,2.306,2.249,2.181,2.104,2.021,1.932,1.84,1.746,1.653,1.563,1.477,1.398,1.326,1.264,1.212,1.172,1.143,1.126,1.12,1.126,1.142,1.168,1.203,1.245,1.293,1.345,1.4,1.457,1.514,1.569,1.621,1.67,1.715,1.754,1.787,1.814,1.834,1.848,1.856,1.858,1.854,1.845,1.832,1.815,1.794,1.77,1.744,1.717,1.689,1.66,1.632,1.604,1.578,1.554,1.533,1.515,1.5,1.49,1.484,1.484,1.489,1.499,1.514,1.536,1.562,1.593,1.627,1.665,1.207,1.205,1.224,1.263,1.324,1.404,1.501,1.611,1.732,1.857,1.981,2.1,2.208,2.3,2.371,2.419,2.439,2.432,2.397,2.334,2.246,2.136,2.008,1.867,1.718,1.567,1.421,1.283,1.161,1.057,0.975,0.918,0.887,0.882,0.902,0.945,1.008,1.087,1.178,1.275,1.375,1.472,1.562,1.64,1.704,1.75,1.778,1.788,1.779,1.753,1.712,1.659,1.599,1.535,1.47,1.41,1.357,1.316,1.289,1.278,1.284,1.308,1.35,1.407,1.478,1.561,1.651,1.745,1.84,1.931,2.014,2.087,2.145,2.187,2.211,2.216,2.2,2.166,2.114,2.046,1.964,1.871,1.772,1.668,1.564,1.463,1.368,1.282,1.207,1.146,1.099,1.068,1.052,1.052,1.065,1.092,1.129,1.176,1.229,1.286,1.346,1.405,1.463,1.516,1.564,1.606,1.64,1.667,1.686,1.697,1.702,1.7,1.694,1.684,1.671,1.657,1.643,1.63,1.618,1.609,1.603,1.599,1.6,1.603,1.609,1.617,1.626,1.637,1.647,1.656,1.664,1.669,1.671,1.67,1.665,1.656,1.643,1.627,1.608,1.586,1.563,1.54,1.518,1.497,1.48,1.466,1.459,1.457,1.463,1.476,1.498,1.529,1.567,1.614,1.669,1.73,1.796,1.867,1.94,2.015,2.089,2.16,2.227,2.289,2.342,2.387,2.421,2.444,2.454,2.452,2.436,2.408,2.367,2.315,2.252,2.18,2.1,2.014,1.924,1.832,1.74,1.649,1.563,1.482,1.408,1.343,1.287,1.242,1.208,1.185,1.174,1.173,1.183,1.203,1.23,1.265,1.306,1.352,1.4,1.451,1.501,1.55,1.598,1.642,1.682,1.717,1.748,1.772,1.792,1.805,1.814,1.817,1.816,1.81,1.8,1.788,1.772,1.754,1.734,1.713,1.691,1.669,1.646,1.624,1.603,1.583,1.564,1.548,1.534,1.523,1.516,1.513,1.514,1.519,1.53,1.545,1.565,1.589,1.618,1.65,1.221,1.225,1.25,1.295,1.36,1.444,1.544,1.656,1.776,1.9,2.021,2.135,2.236,2.32,2.382,2.419,2.429,2.412,2.365,2.293,2.196,2.078,1.944,1.798,1.648,1.497,1.353,1.219,1.103,1.006,0.933,0.886,0.866,0.871,0.902,0.955,1.027,1.115,1.212,1.315,1.418,1.517,1.607,1.685,1.747,1.79,1.815,1.821,1.808,1.779,1.735,1.681,1.62,1.557,1.494,1.437,1.389,1.353,1.332,1.328,1.342,1.373,1.421,1.485,1.562,1.648,1.741,1.837,1.932,2.021,2.101,2.169,2.221,2.256,2.272,2.269,2.246,2.204,2.145,2.071,1.984,1.889,1.787,1.683,1.581,1.482,1.392,1.311,1.243,1.189,1.15,1.126,1.117,1.123,1.141,1.171,1.211,1.258,1.309,1.363,1.418,1.47,1.518,1.561,1.597,1.625,1.645,1.658,1.662,1.66,1.651,1.638,1.621,1.601,1.581,1.562,1.544,1.529,1.519,1.512,1.511,1.515,1.524,1.538,1.555,1.576,1.599,1.624,1.648,1.671,1.693,1.711,1.725,1.735,1.74,1.74,1.734,1.723,1.708,1.689,1.667,1.644,1.619,1.595,1.573,1.555,1.54,1.532,1.53,1.536,1.55,1.572,1.603,1.643,1.69,1.745,1.807,1.873,1.944,2.016,2.089,2.16,2.228,2.292,2.348,2.396,2.435,2.463,2.478,2.482,2.472,2.45,2.415,2.368,2.311,2.244,2.168,2.086,1.999,1.91,1.819,1.73,1.644,1.562,1.487,1.42,1.361,1.313,1.275,1.248,1.232,1.226,1.23,1.243,1.265,1.294,1.328,1.367,1.409,1.453,1.497,1.541,1.582,1.621,1.657,1.688,1.714,1.736,1.753,1.765,1.773,1.777,1.776,1.773,1.766,1.757,1.746,1.733,1.719,1.703,1.688,1.671,1.655,1.638,1.622,1.607,1.592,1.578,1.566,1.556,1.548,1.543,1.541,1.543,1.549,1.558,1.572,1.591,1.613,1.639,1.237,1.247,1.277,1.327,1.396,1.484,1.586,1.699,1.818,1.94,2.057,2.165,2.26,2.335,2.388,2.415,2.415,2.386,2.33,2.248,2.143,2.018,1.879,1.73,1.578,1.429,1.287,1.159,1.049,0.961,0.898,0.861,0.851,0.868,0.909,0.972,1.053,1.148,1.252,1.36,1.466,1.566,1.657,1.733,1.792,1.832,1.853,1.855,1.839,1.806,1.76,1.704,1.643,1.58,1.52,1.466,1.422,1.392,1.377,1.38,1.4,1.438,1.493,1.562,1.643,1.733,1.829,1.925,2.018,2.105,2.181,2.243,2.289,2.317,2.326,2.315,2.284,2.235,2.17,2.091,2.001,1.903,1.8,1.698,1.597,1.503,1.418,1.344,1.284,1.237,1.206,1.19,1.188,1.2,1.224,1.257,1.299,1.345,1.395,1.444,1.492,1.536,1.575,1.606,1.629,1.644,1.65,1.648,1.638,1.621,1.6,1.574,1.546,1.518,1.491,1.467,1.446,1.431,1.422,1.42,1.424,1.436,1.454,1.478,1.508,1.542,1.578,1.617,1.655,1.692,1.727,1.758,1.784,1.804,1.819,1.826,1.827,1.821,1.809,1.792,1.77,1.745,1.718,1.69,1.663,1.638,1.617,1.601,1.591,1.588,1.593,1.607,1.63,1.662,1.702,1.751,1.806,1.868,1.935,2.005,2.076,2.147,2.216,2.28,2.339,2.391,2.434,2.466,2.487,2.497,2.493,2.477,2.448,2.408,2.356,2.295,2.224,2.147,2.064,1.978,1.89,1.803,1.718,1.637,1.561,1.493,1.433,1.383,1.342,1.311,1.291,1.281,1.281,1.289,1.306,1.329,1.358,1.391,1.427,1.465,1.503,1.54,1.576,1.609,1.639,1.665,1.687,1.705,1.719,1.729,1.735,1.737,1.737,1.734,1.73,1.723,1.716,1.707,1.698,1.688,1.678,1.668,1.658,1.647,1.637,1.626,1.616,1.606,1.596,1.587,1.58,1.574,1.57,1.569,1.57,1.575,1.584,1.596,1.613,1.633,1.254,1.269,1.304,1.359,1.433,1.523,1.627,1.74,1.858,1.977,2.09,2.192,2.279,2.346,2.389,2.407,2.396,2.357,2.291,2.2,2.087,1.957,1.813,1.662,1.51,1.362,1.225,1.102,1.0,0.921,0.867,0.841,0.843,0.87,0.922,0.995,1.085,1.187,1.297,1.409,1.517,1.619,1.708,1.782,1.839,1.876,1.893,1.89,1.87,1.834,1.785,1.728,1.666,1.604,1.545,1.495,1.456,1.431,1.422,1.431,1.458,1.502,1.563,1.637,1.722,1.815,1.911,2.007,2.098,2.182,2.253,2.31,2.349,2.37,2.371,2.352,2.315,2.259,2.188,2.105,2.012,1.913,1.811,1.71,1.614,1.525,1.447,1.38,1.328,1.29,1.267,1.259,1.265,1.283,1.311,1.348,1.391,1.437,1.483,1.528,1.569,1.604,1.632,1.651,1.661,1.662,1.653,1.637,1.612,1.582,1.548,1.51,1.473,1.436,1.403,1.374,1.352,1.337,1.33,1.332,1.343,1.362,1.39,1.425,1.467,1.514,1.564,1.615,1.668,1.718,1.765,1.808,1.846,1.876,1.899,1.914,1.92,1.918,1.909,1.893,1.87,1.843,1.813,1.78,1.747,1.715,1.686,1.662,1.643,1.631,1.628,1.632,1.647,1.67,1.703,1.745,1.794,1.851,1.913,1.98,2.049,2.12,2.189,2.255,2.316,2.371,2.418,2.455,2.481,2.496,2.499,2.489,2.467,2.433,2.388,2.332,2.267,2.195,2.117,2.035,1.95,1.866,1.783,1.703,1.629,1.561,1.5,1.449,1.407,1.374,1.351,1.338,1.334,1.339,1.351,1.369,1.393,1.421,1.452,1.484,1.516,1.548,1.578,1.605,1.629,1.65,1.667,1.681,1.69,1.697,1.7,1.701,1.699,1.697,1.693,1.688,1.683,1.678,1.673,1.668,1.664,1.659,1.655,1.651,1.646,1.641,1.636,1.63,1.624,1.617,1.611,1.605,1.6,1.596,1.594,1.595,1.599,1.606,1.616,1.63,1.273,1.293,1.332,1.391,1.468,1.561,1.666,1.779,1.896,2.011,2.119,2.215,2.294,2.353,2.387,2.394,2.373,2.325,2.25,2.15,2.03,1.895,1.748,1.595,1.444,1.299,1.166,1.05,0.956,0.886,0.843,0.828,0.841,0.88,0.942,1.024,1.122,1.231,1.346,1.461,1.572,1.674,1.762,1.834,1.887,1.92,1.932,1.925,1.901,1.861,1.81,1.751,1.689,1.627,1.571,1.524,1.489,1.469,1.466,1.481,1.514,1.564,1.63,1.708,1.796,1.891,1.988,2.082,2.171,2.251,2.317,2.367,2.4,2.413,2.407,2.381,2.336,2.275,2.2,2.113,2.018,1.919,1.819,1.721,1.63,1.547,1.476,1.418,1.374,1.346,1.332,1.332,1.345,1.369,1.403,1.442,1.486,1.531,1.574,1.613,1.647,1.673,1.689,1.696,1.693,1.679,1.656,1.625,1.586,1.543,1.496,1.448,1.401,1.357,1.318,1.285,1.262,1.247,1.243,1.25,1.268,1.296,1.333,1.38,1.433,1.492,1.555,1.62,1.685,1.748,1.808,1.862,1.909,1.949,1.979,2.0,2.011,2.013,2.005,1.989,1.965,1.935,1.9,1.863,1.823,1.784,1.747,1.714,1.686,1.665,1.652,1.648,1.653,1.668,1.692,1.727,1.77,1.821,1.879,1.943,2.01,2.079,2.148,2.215,2.278,2.336,2.387,2.428,2.46,2.481,2.49,2.486,2.471,2.443,2.404,2.355,2.296,2.229,2.156,2.079,1.999,1.918,1.838,1.761,1.688,1.621,1.562,1.51,1.467,1.434,1.41,1.395,1.388,1.39,1.399,1.414,1.434,1.457,1.483,1.51,1.537,1.563,1.588,1.609,1.628,1.643,1.655,1.663,1.668,1.67,1.669,1.667,1.664,1.66,1.655,1.651,1.648,1.646,1.644,1.644,1.644,1.646,1.647,1.649,1.65,1.651,1.651,1.65,1.648,1.645,1.64,1.635,1.63,1.625,1.621,1.618,1.617,1.619,1.624,1.632,1.292,1.317,1.361,1.424,1.503,1.598,1.704,1.816,1.931,2.042,2.145,2.234,2.306,2.355,2.38,2.377,2.347,2.289,2.205,2.098,1.972,1.832,1.682,1.53,1.38,1.238,1.111,1.003,0.917,0.857,0.825,0.822,0.845,0.895,0.967,1.059,1.165,1.28,1.399,1.518,1.63,1.731,1.817,1.886,1.935,1.963,1.971,1.96,1.931,1.888,1.834,1.773,1.711,1.65,1.596,1.552,1.521,1.506,1.508,1.529,1.568,1.623,1.693,1.775,1.865,1.961,2.057,2.15,2.236,2.311,2.371,2.415,2.441,2.447,2.433,2.4,2.349,2.282,2.203,2.114,2.018,1.92,1.822,1.729,1.644,1.569,1.506,1.457,1.423,1.403,1.399,1.408,1.428,1.459,1.496,1.539,1.583,1.626,1.665,1.699,1.724,1.74,1.746,1.74,1.723,1.695,1.658,1.613,1.56,1.504,1.445,1.387,1.331,1.28,1.236,1.202,1.177,1.164,1.164,1.176,1.2,1.237,1.284,1.341,1.406,1.478,1.553,1.63,1.707,1.782,1.853,1.917,1.973,2.021,2.058,2.084,2.099,2.103,2.096,2.079,2.053,2.02,1.98,1.937,1.89,1.844,1.798,1.756,1.719,1.688,1.665,1.652,1.648,1.654,1.671,1.697,1.734,1.78,1.833,1.893,1.957,2.025,2.093,2.161,2.226,2.287,2.341,2.387,2.424,2.45,2.465,2.468,2.459,2.438,2.406,2.363,2.311,2.25,2.183,2.11,2.035,1.958,1.882,1.808,1.738,1.673,1.615,1.565,1.522,1.489,1.464,1.449,1.441,1.441,1.448,1.46,1.477,1.497,1.519,1.542,1.565,1.586,1.605,1.621,1.634,1.644,1.65,1.652,1.652,1.649,1.644,1.638,1.631,1.625,1.619,1.615,1.612,1.611,1.613,1.616,1.621,1.627,1.634,1.642,1.649,1.656,1.662,1.666,1.669,1.669,1.668,1.665,1.66,1.654,1.648,1.642,1.638,1.635,1.634,1.637,1.312,1.341,1.389,1.455,1.538,1.634,1.74,1.851,1.963,2.07,2.167,2.25,2.313,2.354,2.369,2.357,2.317,2.25,2.158,2.045,1.913,1.769,1.618,1.466,1.318,1.182,1.061,0.96,0.884,0.835,0.814,0.821,0.856,0.916,0.999,1.099,1.212,1.333,1.456,1.577,1.689,1.789,1.873,1.939,1.983,2.007,2.009,1.993,1.959,1.913,1.856,1.794,1.731,1.671,1.619,1.578,1.551,1.541,1.548,1.574,1.617,1.677,1.751,1.836,1.928,2.024,2.119,2.209,2.291,2.361,2.416,2.453,2.471,2.469,2.448,2.409,2.352,2.281,2.198,2.107,2.012,1.916,1.822,1.734,1.656,1.589,1.535,1.496,1.472,1.462,1.467,1.485,1.513,1.549,1.591,1.636,1.68,1.721,1.756,1.783,1.801,1.807,1.801,1.782,1.752,1.711,1.659,1.6,1.535,1.466,1.396,1.329,1.265,1.208,1.161,1.124,1.099,1.088,1.092,1.109,1.141,1.186,1.243,1.31,1.387,1.469,1.556,1.645,1.733,1.819,1.899,1.972,2.037,2.09,2.133,2.163,2.181,2.186,2.179,2.161,2.132,2.095,2.05,2.0,1.947,1.892,1.839,1.787,1.741,1.7,1.668,1.645,1.631,1.629,1.637,1.657,1.687,1.726,1.775,1.831,1.893,1.959,2.027,2.095,2.162,2.225,2.282,2.333,2.374,2.406,2.427,2.436,2.434,2.42,2.394,2.358,2.311,2.257,2.195,2.129,2.058,1.986,1.914,1.844,1.777,1.715,1.66,1.611,1.571,1.538,1.514,1.499,1.491,1.491,1.497,1.508,1.523,1.54,1.56,1.579,1.598,1.615,1.629,1.64,1.648,1.652,1.652,1.649,1.642,1.634,1.624,1.613,1.603,1.593,1.585,1.579,1.576,1.576,1.579,1.585,1.593,1.604,1.616,1.63,1.643,1.656,1.668,1.678,1.686,1.691,1.693,1.692,1.689,1.684,1.677,1.669,1.661,1.654,1.649,1.646,1.333,1.366,1.418,1.487,1.571,1.668,1.774,1.883,1.992,2.094,2.186,2.261,2.317,2.349,2.355,2.333,2.284,2.209,2.11,1.99,1.854,1.707,1.555,1.404,1.26,1.128,1.014,0.923,0.856,0.818,0.808,0.827,0.873,0.944,1.035,1.144,1.264,1.39,1.516,1.638,1.75,1.849,1.93,1.991,2.03,2.049,2.046,2.024,1.986,1.935,1.876,1.812,1.748,1.689,1.639,1.601,1.578,1.572,1.584,1.615,1.663,1.727,1.804,1.891,1.984,2.079,2.172,2.259,2.337,2.401,2.449,2.479,2.49,2.481,2.453,2.407,2.345,2.27,2.185,2.094,1.999,1.906,1.817,1.736,1.665,1.607,1.563,1.534,1.52,1.522,1.536,1.562,1.598,1.64,1.686,1.732,1.776,1.815,1.845,1.866,1.875,1.871,1.854,1.823,1.78,1.725,1.66,1.587,1.51,1.43,1.35,1.274,1.204,1.142,1.091,1.053,1.029,1.021,1.028,1.052,1.091,1.144,1.21,1.287,1.374,1.467,1.565,1.664,1.762,1.857,1.946,2.027,2.098,2.157,2.204,2.237,2.256,2.262,2.254,2.233,2.202,2.16,2.11,2.053,1.993,1.93,1.867,1.807,1.751,1.702,1.66,1.627,1.605,1.594,1.594,1.606,1.629,1.663,1.707,1.759,1.818,1.882,1.949,2.018,2.086,2.151,2.212,2.266,2.312,2.349,2.376,2.391,2.395,2.387,2.368,2.338,2.299,2.25,2.195,2.134,2.069,2.002,1.934,1.868,1.805,1.747,1.694,1.649,1.61,1.58,1.558,1.544,1.537,1.537,1.543,1.554,1.568,1.585,1.603,1.62,1.636,1.649,1.659,1.666,1.669,1.667,1.661,1.652,1.64,1.626,1.61,1.594,1.579,1.565,1.553,1.545,1.54,1.54,1.544,1.551,1.563,1.577,1.594,1.613,1.632,1.652,1.67,1.686,1.699,1.709,1.715,1.718,1.717,1.713,1.706,1.696,1.686,1.676,1.666,1.658,1.354,1.391,1.446,1.518,1.604,1.701,1.806,1.913,2.018,2.116,2.201,2.27,2.317,2.34,2.337,2.307,2.249,2.166,2.06,1.935,1.795,1.646,1.494,1.345,1.205,1.08,0.973,0.89,0.834,0.806,0.808,0.838,0.895,0.976,1.077,1.193,1.319,1.449,1.578,1.701,1.812,1.908,1.985,2.042,2.076,2.088,2.08,2.053,2.01,1.955,1.893,1.827,1.763,1.705,1.656,1.621,1.601,1.6,1.616,1.651,1.703,1.77,1.85,1.938,2.031,2.126,2.216,2.3,2.372,2.43,2.472,2.494,2.498,2.482,2.447,2.395,2.329,2.25,2.164,2.072,1.98,1.891,1.807,1.733,1.671,1.622,1.589,1.571,1.568,1.58,1.604,1.639,1.682,1.729,1.779,1.827,1.87,1.906,1.932,1.946,1.946,1.932,1.904,1.861,1.805,1.737,1.66,1.575,1.486,1.396,1.307,1.223,1.147,1.082,1.028,0.99,0.968,0.962,0.974,1.003,1.049,1.11,1.185,1.272,1.368,1.471,1.578,1.686,1.793,1.896,1.992,2.079,2.155,2.218,2.268,2.303,2.323,2.328,2.319,2.296,2.26,2.213,2.157,2.094,2.026,1.956,1.885,1.816,1.751,1.692,1.641,1.599,1.568,1.549,1.541,1.546,1.563,1.591,1.63,1.678,1.734,1.796,1.863,1.931,2.001,2.068,2.131,2.189,2.24,2.282,2.313,2.335,2.345,2.343,2.33,2.307,2.273,2.231,2.182,2.126,2.067,2.005,1.942,1.88,1.822,1.767,1.718,1.676,1.641,1.614,1.594,1.582,1.578,1.58,1.587,1.598,1.613,1.63,1.646,1.662,1.676,1.687,1.695,1.697,1.695,1.689,1.678,1.663,1.645,1.624,1.602,1.58,1.559,1.541,1.525,1.513,1.506,1.504,1.508,1.516,1.53,1.547,1.568,1.592,1.617,1.642,1.666,1.689,1.708,1.724,1.735,1.741,1.743,1.741,1.734,1.725,1.713,1.699,1.686,1.673,1.376,1.416,1.474,1.547,1.635,1.732,1.836,1.941,2.042,2.134,2.214,2.275,2.314,2.328,2.316,2.277,2.211,2.121,2.009,1.879,1.736,1.587,1.436,1.289,1.154,1.035,0.937,0.863,0.818,0.801,0.814,0.856,0.923,1.014,1.123,1.246,1.377,1.511,1.642,1.765,1.875,1.967,2.04,2.091,2.12,2.126,2.111,2.078,2.03,1.972,1.906,1.839,1.774,1.716,1.669,1.637,1.621,1.623,1.644,1.682,1.738,1.808,1.889,1.978,2.071,2.163,2.251,2.33,2.397,2.448,2.483,2.498,2.494,2.471,2.43,2.373,2.302,2.222,2.134,2.044,1.954,1.869,1.792,1.726,1.673,1.635,1.612,1.605,1.614,1.636,1.67,1.713,1.763,1.816,1.869,1.918,1.961,1.994,2.015,2.022,2.014,1.99,1.951,1.896,1.828,1.748,1.659,1.563,1.464,1.364,1.268,1.178,1.097,1.028,0.974,0.936,0.915,0.913,0.93,0.965,1.017,1.086,1.169,1.264,1.368,1.48,1.595,1.711,1.825,1.934,2.036,2.127,2.207,2.274,2.325,2.361,2.381,2.384,2.373,2.346,2.306,2.254,2.193,2.123,2.048,1.97,1.891,1.814,1.74,1.672,1.613,1.562,1.523,1.495,1.48,1.478,1.489,1.512,1.546,1.59,1.643,1.704,1.769,1.838,1.908,1.977,2.043,2.104,2.159,2.205,2.242,2.268,2.284,2.288,2.282,2.264,2.237,2.201,2.157,2.107,2.052,1.996,1.938,1.881,1.827,1.777,1.732,1.693,1.662,1.638,1.622,1.613,1.612,1.616,1.626,1.639,1.655,1.673,1.69,1.706,1.719,1.729,1.734,1.733,1.728,1.717,1.701,1.68,1.656,1.629,1.601,1.573,1.546,1.521,1.5,1.484,1.474,1.47,1.472,1.48,1.495,1.515,1.539,1.567,1.597,1.628,1.658,1.687,1.713,1.734,1.751,1.762,1.768,1.768,1.763,1.753,1.74,1.725,1.708,1.691,1.397,1.441,1.501,1.576,1.664,1.761,1.863,1.965,2.063,2.15,2.223,2.276,2.307,2.313,2.293,2.246,2.172,2.075,1.957,1.824,1.679,1.529,1.379,1.237,1.107,0.995,0.905,0.842,0.807,0.802,0.826,0.878,0.956,1.056,1.173,1.303,1.439,1.575,1.707,1.829,1.936,2.025,2.093,2.138,2.16,2.16,2.139,2.1,2.047,1.984,1.915,1.846,1.781,1.724,1.678,1.648,1.636,1.641,1.666,1.708,1.766,1.838,1.921,2.01,2.102,2.192,2.276,2.35,2.411,2.456,2.483,2.491,2.479,2.45,2.402,2.34,2.266,2.184,2.096,2.007,1.921,1.842,1.772,1.714,1.671,1.644,1.632,1.637,1.656,1.689,1.733,1.785,1.841,1.899,1.955,2.005,2.047,2.077,2.093,2.093,2.077,2.044,1.994,1.928,1.849,1.758,1.658,1.552,1.444,1.336,1.233,1.138,1.053,0.982,0.928,0.89,0.872,0.874,0.895,0.936,0.995,1.07,1.161,1.263,1.375,1.493,1.615,1.737,1.857,1.971,2.076,2.171,2.254,2.322,2.374,2.409,2.428,2.429,2.415,2.384,2.34,2.283,2.216,2.14,2.058,1.973,1.886,1.801,1.719,1.644,1.576,1.518,1.471,1.436,1.414,1.405,1.41,1.427,1.457,1.498,1.548,1.606,1.671,1.74,1.81,1.881,1.949,2.013,2.071,2.122,2.163,2.195,2.216,2.225,2.224,2.212,2.191,2.16,2.121,2.077,2.028,1.976,1.923,1.871,1.821,1.775,1.734,1.7,1.673,1.653,1.64,1.636,1.638,1.645,1.658,1.675,1.694,1.713,1.732,1.749,1.763,1.772,1.775,1.773,1.765,1.75,1.729,1.704,1.674,1.641,1.606,1.571,1.538,1.507,1.48,1.459,1.445,1.437,1.437,1.444,1.459,1.48,1.507,1.539,1.573,1.61,1.646,1.681,1.713,1.741,1.763,1.78,1.79,1.793,1.79,1.782,1.769,1.752,1.732,1.712,1.419,1.465,1.527,1.604,1.693,1.789,1.889,1.988,2.081,2.162,2.229,2.275,2.298,2.296,2.267,2.212,2.131,2.028,1.906,1.769,1.622,1.473,1.326,1.187,1.064,0.959,0.879,0.826,0.802,0.808,0.843,0.906,0.994,1.103,1.227,1.362,1.502,1.641,1.773,1.893,1.997,2.081,2.144,2.182,2.198,2.19,2.163,2.118,2.059,1.992,1.92,1.849,1.783,1.727,1.683,1.655,1.645,1.654,1.682,1.727,1.788,1.862,1.945,2.034,2.124,2.211,2.29,2.359,2.414,2.452,2.472,2.472,2.454,2.417,2.365,2.298,2.221,2.137,2.05,1.964,1.882,1.809,1.747,1.698,1.665,1.649,1.649,1.665,1.696,1.739,1.792,1.852,1.915,1.978,2.036,2.087,2.127,2.154,2.165,2.159,2.135,2.092,2.033,1.957,1.867,1.766,1.657,1.542,1.425,1.311,1.203,1.104,1.017,0.945,0.89,0.855,0.839,0.845,0.871,0.917,0.982,1.063,1.16,1.268,1.386,1.51,1.637,1.764,1.887,2.005,2.113,2.21,2.293,2.361,2.412,2.447,2.463,2.462,2.444,2.41,2.361,2.3,2.227,2.145,2.057,1.965,1.872,1.779,1.69,1.607,1.532,1.467,1.413,1.371,1.343,1.328,1.327,1.34,1.366,1.403,1.451,1.507,1.571,1.639,1.71,1.782,1.852,1.919,1.98,2.034,2.08,2.116,2.142,2.156,2.16,2.154,2.137,2.111,2.078,2.038,1.993,1.946,1.897,1.85,1.804,1.762,1.726,1.696,1.673,1.657,1.649,1.649,1.655,1.667,1.684,1.705,1.727,1.75,1.772,1.791,1.806,1.816,1.819,1.816,1.805,1.788,1.763,1.733,1.698,1.659,1.618,1.576,1.536,1.498,1.465,1.438,1.418,1.407,1.403,1.409,1.422,1.444,1.473,1.508,1.546,1.587,1.63,1.671,1.709,1.743,1.772,1.794,1.809,1.817,1.817,1.81,1.797,1.779,1.758,1.734,1.44,1.489,1.553,1.631,1.719,1.815,1.912,2.008,2.096,2.172,2.232,2.271,2.286,2.276,2.239,2.176,2.089,1.981,1.854,1.715,1.568,1.419,1.275,1.142,1.025,0.929,0.858,0.815,0.802,0.819,0.865,0.939,1.036,1.153,1.284,1.424,1.567,1.707,1.838,1.956,2.056,2.135,2.191,2.223,2.231,2.216,2.182,2.131,2.067,1.995,1.92,1.847,1.781,1.725,1.682,1.657,1.65,1.662,1.693,1.74,1.804,1.879,1.962,2.05,2.137,2.221,2.296,2.359,2.407,2.438,2.45,2.443,2.418,2.375,2.317,2.247,2.167,2.083,1.997,1.914,1.837,1.77,1.716,1.678,1.655,1.65,1.662,1.689,1.731,1.785,1.847,1.915,1.984,2.051,2.112,2.163,2.202,2.225,2.231,2.218,2.186,2.136,2.067,1.982,1.883,1.773,1.655,1.533,1.41,1.29,1.178,1.076,0.987,0.915,0.862,0.829,0.816,0.826,0.856,0.907,0.977,1.064,1.166,1.279,1.402,1.53,1.66,1.79,1.916,2.035,2.144,2.241,2.324,2.391,2.441,2.473,2.487,2.483,2.461,2.423,2.37,2.304,2.226,2.139,2.045,1.947,1.848,1.749,1.654,1.565,1.483,1.412,1.351,1.304,1.27,1.25,1.244,1.253,1.274,1.309,1.354,1.408,1.471,1.539,1.61,1.683,1.755,1.824,1.888,1.945,1.994,2.034,2.064,2.084,2.092,2.09,2.078,2.056,2.027,1.992,1.951,1.908,1.863,1.82,1.778,1.74,1.708,1.682,1.663,1.652,1.649,1.653,1.664,1.681,1.703,1.728,1.755,1.782,1.807,1.83,1.847,1.859,1.863,1.86,1.848,1.829,1.802,1.767,1.727,1.683,1.635,1.587,1.54,1.495,1.455,1.422,1.396,1.379,1.372,1.374,1.386,1.408,1.437,1.474,1.516,1.562,1.609,1.656,1.701,1.742,1.777,1.805,1.825,1.838,1.841,1.837,1.825,1.807,1.785,1.759,1.461,1.512,1.578,1.656,1.744,1.838,1.934,2.025,2.109,2.179,2.232,2.264,2.271,2.253,2.209,2.14,2.047,1.933,1.803,1.662,1.515,1.368,1.228,1.1,0.99,0.903,0.841,0.809,0.807,0.835,0.892,0.976,1.082,1.206,1.344,1.488,1.633,1.773,1.903,2.018,2.113,2.186,2.235,2.26,2.26,2.238,2.196,2.139,2.07,1.994,1.916,1.841,1.773,1.718,1.677,1.654,1.649,1.664,1.697,1.748,1.812,1.888,1.971,2.057,2.142,2.221,2.291,2.348,2.39,2.413,2.418,2.404,2.372,2.323,2.26,2.187,2.105,2.021,1.937,1.857,1.786,1.727,1.681,1.652,1.641,1.647,1.67,1.709,1.762,1.826,1.897,1.972,2.047,2.117,2.18,2.232,2.269,2.288,2.29,2.271,2.232,2.173,2.096,2.003,1.896,1.778,1.653,1.525,1.397,1.273,1.158,1.055,0.966,0.895,0.843,0.812,0.804,0.817,0.852,0.907,0.982,1.073,1.179,1.296,1.421,1.552,1.684,1.815,1.942,2.061,2.169,2.265,2.346,2.411,2.459,2.488,2.499,2.491,2.466,2.424,2.367,2.296,2.214,2.122,2.024,1.921,1.817,1.713,1.613,1.518,1.431,1.354,1.289,1.236,1.197,1.173,1.163,1.167,1.186,1.217,1.26,1.313,1.374,1.441,1.513,1.586,1.659,1.73,1.797,1.857,1.909,1.953,1.986,2.009,2.021,2.023,2.015,1.997,1.972,1.94,1.903,1.863,1.822,1.782,1.744,1.709,1.681,1.659,1.644,1.637,1.638,1.647,1.663,1.685,1.713,1.743,1.775,1.807,1.838,1.864,1.886,1.9,1.907,1.905,1.893,1.873,1.843,1.806,1.762,1.712,1.659,1.604,1.549,1.498,1.451,1.41,1.378,1.355,1.343,1.341,1.351,1.371,1.401,1.439,1.483,1.533,1.585,1.638,1.689,1.736,1.778,1.812,1.839,1.856,1.864,1.863,1.853,1.836,1.812,1.784,1.482,1.534,1.601,1.68,1.768,1.86,1.953,2.041,2.119,2.183,2.23,2.254,2.254,2.229,2.178,2.102,2.003,1.885,1.753,1.61,1.464,1.32,1.184,1.062,0.96,0.881,0.83,0.808,0.817,0.856,0.924,1.017,1.131,1.263,1.405,1.552,1.699,1.839,1.966,2.077,2.167,2.234,2.276,2.292,2.284,2.255,2.206,2.142,2.067,1.986,1.905,1.829,1.761,1.706,1.666,1.645,1.643,1.66,1.696,1.748,1.814,1.89,1.973,2.057,2.139,2.214,2.278,2.329,2.364,2.38,2.377,2.356,2.317,2.263,2.196,2.119,2.036,1.952,1.871,1.795,1.73,1.678,1.642,1.623,1.623,1.64,1.675,1.725,1.788,1.862,1.941,2.023,2.103,2.177,2.241,2.293,2.328,2.344,2.341,2.316,2.271,2.205,2.121,2.02,1.906,1.782,1.651,1.518,1.386,1.26,1.144,1.04,0.952,0.883,0.834,0.806,0.801,0.818,0.857,0.916,0.994,1.089,1.197,1.316,1.443,1.575,1.708,1.838,1.964,2.081,2.188,2.281,2.359,2.421,2.465,2.491,2.498,2.487,2.458,2.413,2.352,2.278,2.192,2.096,1.994,1.888,1.779,1.672,1.567,1.468,1.377,1.296,1.227,1.17,1.127,1.099,1.085,1.086,1.102,1.13,1.171,1.222,1.282,1.349,1.421,1.495,1.569,1.641,1.71,1.772,1.827,1.874,1.91,1.936,1.951,1.956,1.951,1.937,1.914,1.885,1.851,1.814,1.775,1.738,1.702,1.671,1.646,1.627,1.616,1.613,1.619,1.632,1.653,1.681,1.714,1.75,1.789,1.827,1.862,1.894,1.92,1.939,1.949,1.949,1.939,1.918,1.888,1.848,1.8,1.746,1.687,1.626,1.565,1.506,1.451,1.404,1.364,1.335,1.317,1.311,1.317,1.335,1.364,1.402,1.449,1.501,1.558,1.616,1.673,1.727,1.775,1.816,1.849,1.872,1.884,1.887,1.88,1.864,1.84,1.811,1.502,1.556,1.624,1.703,1.79,1.88,1.97,2.053,2.127,2.185,2.225,2.243,2.236,2.203,2.145,2.063,1.96,1.838,1.703,1.56,1.415,1.274,1.143,1.028,0.934,0.865,0.823,0.812,0.832,0.882,0.959,1.061,1.184,1.321,1.468,1.618,1.765,1.903,2.028,2.134,2.218,2.278,2.311,2.32,2.304,2.266,2.21,2.139,2.059,1.974,1.89,1.812,1.743,1.689,1.651,1.631,1.632,1.652,1.69,1.743,1.81,1.886,1.968,2.05,2.128,2.198,2.257,2.301,2.329,2.338,2.328,2.3,2.255,2.195,2.124,2.045,1.961,1.878,1.799,1.729,1.67,1.626,1.599,1.59,1.6,1.629,1.675,1.736,1.809,1.892,1.979,2.067,2.152,2.229,2.294,2.345,2.378,2.392,2.384,2.354,2.302,2.23,2.14,2.033,1.913,1.784,1.649,1.513,1.379,1.252,1.135,1.032,0.946,0.879,0.833,0.809,0.808,0.829,0.871,0.933,1.014,1.111,1.221,1.341,1.468,1.599,1.73,1.858,1.981,2.095,2.198,2.288,2.363,2.42,2.461,2.483,2.486,2.471,2.439,2.39,2.327,2.249,2.161,2.063,1.958,1.849,1.738,1.627,1.52,1.418,1.324,1.24,1.167,1.107,1.061,1.03,1.013,1.012,1.025,1.051,1.09,1.14,1.199,1.265,1.336,1.411,1.486,1.559,1.629,1.693,1.75,1.799,1.838,1.866,1.884,1.891,1.888,1.876,1.856,1.829,1.797,1.761,1.725,1.689,1.656,1.627,1.604,1.588,1.58,1.581,1.59,1.609,1.635,1.668,1.707,1.749,1.794,1.838,1.88,1.918,1.95,1.974,1.988,1.991,1.984,1.964,1.934,1.893,1.842,1.785,1.721,1.654,1.586,1.52,1.458,1.402,1.355,1.319,1.295,1.283,1.285,1.3,1.327,1.365,1.413,1.468,1.528,1.591,1.653,1.713,1.768,1.816,1.855,1.884,1.902,1.909,1.905,1.891,1.869,1.839,1.521,1.577,1.645,1.724,1.81,1.898,1.984,2.064,2.132,2.185,2.218,2.229,2.215,2.176,2.112,2.024,1.916,1.792,1.655,1.513,1.37,1.232,1.107,0.998,0.912,0.852,0.821,0.821,0.851,0.911,0.998,1.109,1.238,1.381,1.531,1.683,1.83,1.967,2.087,2.188,2.265,2.317,2.343,2.342,2.318,2.272,2.208,2.131,2.045,1.956,1.869,1.789,1.721,1.667,1.63,1.613,1.616,1.638,1.678,1.733,1.801,1.876,1.956,2.035,2.11,2.175,2.228,2.266,2.286,2.288,2.271,2.236,2.185,2.121,2.046,1.965,1.881,1.799,1.724,1.658,1.606,1.57,1.552,1.554,1.575,1.614,1.671,1.742,1.825,1.916,2.01,2.104,2.193,2.273,2.339,2.389,2.42,2.431,2.418,2.384,2.327,2.25,2.154,2.042,1.918,1.785,1.647,1.509,1.375,1.248,1.132,1.032,0.948,0.885,0.842,0.822,0.824,0.848,0.893,0.958,1.041,1.138,1.248,1.368,1.493,1.622,1.75,1.875,1.993,2.103,2.201,2.286,2.356,2.409,2.445,2.463,2.463,2.444,2.409,2.358,2.292,2.213,2.122,2.023,1.917,1.806,1.694,1.582,1.473,1.37,1.274,1.188,1.113,1.051,1.002,0.969,0.95,0.946,0.957,0.981,1.018,1.067,1.125,1.19,1.262,1.336,1.411,1.486,1.557,1.622,1.681,1.731,1.772,1.802,1.822,1.831,1.829,1.819,1.8,1.774,1.743,1.708,1.673,1.638,1.606,1.578,1.557,1.543,1.537,1.541,1.554,1.577,1.608,1.646,1.691,1.74,1.791,1.842,1.891,1.936,1.974,2.004,2.023,2.031,2.027,2.01,1.981,1.939,1.887,1.827,1.759,1.687,1.612,1.539,1.47,1.406,1.352,1.308,1.276,1.259,1.255,1.266,1.29,1.328,1.376,1.432,1.496,1.563,1.63,1.697,1.758,1.813,1.859,1.894,1.918,1.929,1.929,1.918,1.897,1.867,1.54,1.597,1.665,1.744,1.828,1.914,1.997,2.073,2.136,2.183,2.209,2.213,2.193,2.147,2.077,1.985,1.873,1.746,1.609,1.467,1.326,1.193,1.074,0.973,0.895,0.845,0.824,0.834,0.875,0.944,1.04,1.159,1.295,1.442,1.595,1.748,1.894,2.028,2.144,2.238,2.308,2.352,2.369,2.36,2.326,2.272,2.201,2.117,2.026,1.933,1.844,1.762,1.693,1.64,1.605,1.59,1.595,1.619,1.661,1.717,1.785,1.861,1.939,2.015,2.086,2.146,2.193,2.224,2.238,2.232,2.208,2.167,2.11,2.041,1.963,1.88,1.796,1.717,1.645,1.584,1.539,1.511,1.503,1.514,1.546,1.596,1.663,1.744,1.836,1.935,2.035,2.134,2.227,2.308,2.375,2.424,2.453,2.46,2.444,2.405,2.344,2.262,2.162,2.046,1.919,1.784,1.645,1.507,1.373,1.248,1.135,1.038,0.958,0.898,0.86,0.843,0.849,0.876,0.924,0.99,1.073,1.171,1.279,1.396,1.519,1.643,1.767,1.887,2.0,2.104,2.196,2.275,2.34,2.388,2.419,2.432,2.428,2.407,2.37,2.316,2.249,2.169,2.078,1.978,1.872,1.762,1.649,1.537,1.429,1.325,1.229,1.142,1.066,1.002,0.952,0.917,0.896,0.891,0.9,0.923,0.958,1.006,1.063,1.128,1.198,1.272,1.348,1.423,1.494,1.561,1.621,1.672,1.714,1.746,1.766,1.776,1.776,1.766,1.747,1.722,1.691,1.656,1.621,1.586,1.554,1.527,1.506,1.493,1.489,1.495,1.512,1.538,1.573,1.616,1.667,1.722,1.78,1.838,1.895,1.947,1.992,2.029,2.055,2.068,2.068,2.055,2.027,1.987,1.934,1.871,1.8,1.723,1.644,1.564,1.487,1.415,1.353,1.301,1.262,1.238,1.228,1.234,1.255,1.29,1.338,1.396,1.461,1.532,1.605,1.676,1.744,1.806,1.858,1.9,1.93,1.947,1.952,1.943,1.924,1.895,1.558,1.615,1.684,1.762,1.845,1.928,2.008,2.079,2.137,2.178,2.199,2.196,2.169,2.118,2.043,1.946,1.831,1.702,1.564,1.424,1.286,1.158,1.044,0.951,0.882,0.841,0.831,0.851,0.902,0.981,1.085,1.211,1.352,1.504,1.659,1.812,1.956,2.086,2.197,2.285,2.347,2.382,2.39,2.371,2.329,2.266,2.188,2.098,2.002,1.905,1.813,1.73,1.661,1.609,1.575,1.562,1.57,1.596,1.64,1.697,1.766,1.84,1.916,1.99,2.056,2.111,2.153,2.177,2.183,2.171,2.14,2.092,2.03,1.957,1.876,1.792,1.709,1.632,1.564,1.509,1.471,1.451,1.451,1.473,1.514,1.575,1.651,1.742,1.842,1.947,2.054,2.157,2.252,2.335,2.402,2.45,2.477,2.481,2.462,2.419,2.354,2.268,2.165,2.047,1.918,1.782,1.644,1.507,1.375,1.253,1.144,1.05,0.975,0.919,0.885,0.873,0.882,0.912,0.961,1.028,1.111,1.207,1.313,1.426,1.544,1.663,1.781,1.894,2.0,2.097,2.183,2.256,2.314,2.356,2.382,2.392,2.384,2.361,2.321,2.267,2.199,2.12,2.029,1.931,1.826,1.717,1.606,1.495,1.388,1.285,1.189,1.103,1.027,0.963,0.912,0.876,0.855,0.848,0.855,0.877,0.912,0.958,1.014,1.078,1.148,1.222,1.297,1.372,1.444,1.511,1.572,1.624,1.666,1.698,1.72,1.73,1.73,1.719,1.7,1.674,1.643,1.607,1.571,1.535,1.502,1.474,1.453,1.441,1.438,1.445,1.463,1.492,1.531,1.579,1.635,1.696,1.761,1.827,1.891,1.951,2.004,2.048,2.081,2.101,2.106,2.097,2.073,2.035,1.982,1.918,1.845,1.764,1.679,1.593,1.509,1.43,1.359,1.299,1.252,1.22,1.205,1.205,1.222,1.254,1.3,1.358,1.425,1.499,1.576,1.653,1.727,1.795,1.855,1.903,1.94,1.963,1.972,1.968,1.951,1.923,1.575,1.633,1.702,1.779,1.86,1.941,2.017,2.083,2.136,2.172,2.186,2.178,2.145,2.088,2.008,1.907,1.789,1.659,1.521,1.383,1.249,1.125,1.018,0.933,0.873,0.842,0.841,0.872,0.932,1.02,1.133,1.265,1.411,1.566,1.722,1.874,2.016,2.141,2.246,2.327,2.381,2.407,2.405,2.377,2.326,2.255,2.169,2.073,1.972,1.872,1.777,1.694,1.625,1.574,1.542,1.531,1.541,1.57,1.615,1.674,1.742,1.816,1.89,1.96,2.022,2.072,2.107,2.125,2.125,2.105,2.068,2.015,1.948,1.871,1.788,1.703,1.62,1.545,1.481,1.432,1.401,1.389,1.399,1.43,1.481,1.551,1.637,1.735,1.843,1.954,2.066,2.173,2.27,2.354,2.421,2.467,2.492,2.493,2.47,2.424,2.356,2.268,2.163,2.043,1.914,1.779,1.642,1.508,1.38,1.262,1.157,1.069,0.999,0.948,0.919,0.91,0.923,0.955,1.005,1.072,1.153,1.246,1.348,1.457,1.568,1.681,1.791,1.896,1.994,2.084,2.162,2.227,2.278,2.315,2.336,2.342,2.332,2.306,2.266,2.212,2.145,2.066,1.978,1.882,1.78,1.674,1.566,1.458,1.353,1.252,1.158,1.073,0.998,0.935,0.884,0.848,0.826,0.818,0.825,0.845,0.879,0.924,0.979,1.042,1.111,1.185,1.26,1.335,1.407,1.474,1.535,1.587,1.63,1.662,1.683,1.693,1.692,1.681,1.661,1.634,1.601,1.564,1.525,1.487,1.453,1.423,1.401,1.387,1.384,1.391,1.411,1.442,1.483,1.535,1.596,1.663,1.734,1.807,1.879,1.947,2.008,2.061,2.101,2.128,2.141,2.137,2.117,2.081,2.031,1.967,1.891,1.808,1.718,1.626,1.535,1.449,1.37,1.302,1.247,1.207,1.184,1.179,1.19,1.219,1.263,1.32,1.389,1.465,1.545,1.627,1.707,1.782,1.848,1.904,1.947,1.976,1.99,1.99,1.976,1.95,1.591,1.65,1.719,1.794,1.873,1.951,2.024,2.086,2.134,2.164,2.173,2.158,2.12,2.057,1.973,1.868,1.748,1.617,1.481,1.344,1.214,1.096,0.996,0.919,0.868,0.846,0.856,0.896,0.965,1.062,1.182,1.32,1.47,1.628,1.784,1.935,2.073,2.194,2.292,2.365,2.41,2.426,2.415,2.378,2.318,2.239,2.145,2.043,1.937,1.834,1.738,1.653,1.585,1.535,1.505,1.497,1.509,1.54,1.587,1.647,1.715,1.788,1.86,1.927,1.985,2.03,2.059,2.07,2.063,2.037,1.994,1.935,1.863,1.783,1.698,1.612,1.531,1.459,1.399,1.356,1.332,1.328,1.346,1.386,1.446,1.525,1.619,1.725,1.839,1.956,2.072,2.181,2.28,2.364,2.43,2.475,2.498,2.496,2.471,2.422,2.351,2.262,2.155,2.036,1.908,1.775,1.641,1.511,1.387,1.275,1.176,1.094,1.029,0.984,0.959,0.955,0.97,1.004,1.054,1.12,1.199,1.288,1.385,1.486,1.591,1.695,1.796,1.893,1.982,2.062,2.132,2.19,2.235,2.266,2.282,2.284,2.272,2.245,2.205,2.152,2.087,2.011,1.926,1.834,1.736,1.634,1.53,1.426,1.325,1.227,1.137,1.054,0.98,0.918,0.869,0.833,0.811,0.802,0.808,0.828,0.86,0.904,0.958,1.021,1.089,1.162,1.237,1.311,1.383,1.45,1.511,1.563,1.605,1.637,1.658,1.667,1.665,1.653,1.631,1.601,1.566,1.526,1.485,1.444,1.407,1.374,1.349,1.334,1.329,1.336,1.355,1.387,1.431,1.486,1.55,1.623,1.7,1.78,1.859,1.936,2.006,2.067,2.116,2.151,2.17,2.173,2.159,2.127,2.079,2.016,1.94,1.854,1.76,1.663,1.566,1.472,1.386,1.309,1.246,1.198,1.168,1.155,1.161,1.186,1.227,1.283,1.351,1.429,1.513,1.599,1.684,1.765,1.838,1.901,1.95,1.986,2.006,2.011,2.001,1.977,1.607,1.666,1.734,1.808,1.886,1.961,2.029,2.087,2.13,2.155,2.158,2.137,2.094,2.026,1.938,1.831,1.709,1.578,1.442,1.308,1.183,1.071,0.978,0.908,0.867,0.854,0.873,0.923,1.001,1.106,1.232,1.376,1.53,1.688,1.845,1.993,2.127,2.242,2.333,2.398,2.434,2.441,2.42,2.373,2.304,2.217,2.116,2.008,1.898,1.792,1.694,1.609,1.542,1.493,1.466,1.46,1.475,1.508,1.557,1.618,1.686,1.758,1.828,1.892,1.945,1.985,2.008,2.014,2.0,1.968,1.918,1.854,1.778,1.695,1.608,1.523,1.443,1.374,1.319,1.281,1.263,1.267,1.294,1.342,1.41,1.497,1.599,1.712,1.831,1.953,2.071,2.183,2.282,2.366,2.431,2.474,2.495,2.491,2.463,2.412,2.34,2.249,2.143,2.025,1.899,1.77,1.64,1.515,1.398,1.292,1.2,1.124,1.066,1.026,1.006,1.006,1.023,1.058,1.108,1.172,1.247,1.331,1.421,1.515,1.611,1.706,1.797,1.884,1.963,2.034,2.095,2.145,2.183,2.208,2.221,2.22,2.206,2.179,2.139,2.088,2.027,1.955,1.875,1.788,1.695,1.599,1.5,1.402,1.305,1.213,1.125,1.046,0.975,0.915,0.867,0.832,0.81,0.801,0.807,0.826,0.857,0.9,0.953,1.014,1.082,1.154,1.228,1.302,1.373,1.44,1.5,1.552,1.594,1.625,1.645,1.653,1.649,1.635,1.611,1.579,1.54,1.497,1.452,1.407,1.366,1.33,1.301,1.283,1.275,1.28,1.298,1.33,1.375,1.432,1.5,1.576,1.659,1.746,1.833,1.917,1.996,2.066,2.124,2.167,2.195,2.205,2.197,2.17,2.125,2.064,1.989,1.901,1.805,1.704,1.601,1.5,1.406,1.321,1.25,1.193,1.155,1.135,1.135,1.154,1.191,1.245,1.313,1.392,1.478,1.568,1.659,1.745,1.825,1.894,1.951,1.993,2.019,2.029,2.024,2.003,1.622,1.68,1.748,1.821,1.896,1.968,2.033,2.087,2.125,2.144,2.141,2.116,2.067,1.996,1.903,1.794,1.671,1.54,1.406,1.275,1.154,1.048,0.962,0.901,0.869,0.866,0.894,0.953,1.04,1.152,1.284,1.432,1.589,1.748,1.904,2.049,2.178,2.287,2.37,2.426,2.452,2.449,2.419,2.363,2.285,2.189,2.082,1.969,1.855,1.746,1.647,1.562,1.496,1.449,1.425,1.422,1.439,1.475,1.526,1.587,1.656,1.727,1.795,1.855,1.905,1.939,1.957,1.956,1.936,1.898,1.843,1.774,1.694,1.609,1.521,1.435,1.357,1.291,1.24,1.208,1.197,1.209,1.243,1.299,1.375,1.469,1.577,1.695,1.82,1.945,2.066,2.178,2.278,2.361,2.424,2.465,2.483,2.477,2.447,2.394,2.321,2.231,2.126,2.011,1.888,1.763,1.64,1.521,1.411,1.312,1.228,1.159,1.108,1.074,1.059,1.062,1.082,1.117,1.165,1.226,1.296,1.374,1.457,1.542,1.628,1.713,1.794,1.869,1.938,1.999,2.051,2.093,2.124,2.144,2.153,2.15,2.135,2.109,2.071,2.024,1.966,1.9,1.826,1.745,1.66,1.57,1.478,1.386,1.295,1.208,1.126,1.05,0.983,0.925,0.879,0.844,0.823,0.815,0.82,0.838,0.868,0.91,0.962,1.022,1.089,1.16,1.233,1.306,1.377,1.443,1.503,1.554,1.595,1.625,1.644,1.651,1.645,1.629,1.602,1.566,1.524,1.477,1.427,1.378,1.332,1.291,1.258,1.235,1.223,1.225,1.242,1.272,1.317,1.375,1.445,1.525,1.613,1.705,1.799,1.892,1.979,2.058,2.125,2.178,2.214,2.232,2.231,2.21,2.17,2.112,2.038,1.95,1.852,1.747,1.639,1.532,1.43,1.338,1.258,1.193,1.146,1.119,1.112,1.125,1.158,1.209,1.275,1.354,1.443,1.536,1.631,1.723,1.809,1.885,1.949,1.998,2.031,2.046,2.045,2.027,1.635,1.694,1.761,1.833,1.905,1.974,2.036,2.085,2.118,2.132,2.124,2.094,2.04,1.965,1.869,1.758,1.634,1.503,1.372,1.245,1.129,1.029,0.951,0.898,0.874,0.88,0.918,0.985,1.08,1.199,1.337,1.488,1.647,1.806,1.96,2.102,2.226,2.327,2.402,2.449,2.466,2.453,2.412,2.347,2.26,2.157,2.044,1.925,1.808,1.697,1.597,1.513,1.448,1.404,1.382,1.382,1.402,1.441,1.493,1.557,1.625,1.695,1.761,1.819,1.864,1.894,1.906,1.899,1.873,1.829,1.769,1.696,1.613,1.525,1.436,1.351,1.275,1.212,1.166,1.139,1.134,1.153,1.194,1.257,1.34,1.44,1.554,1.677,1.805,1.932,2.055,2.168,2.266,2.348,2.409,2.448,2.463,2.455,2.423,2.37,2.297,2.208,2.105,1.993,1.875,1.756,1.639,1.528,1.426,1.336,1.259,1.199,1.154,1.127,1.117,1.123,1.144,1.179,1.226,1.282,1.347,1.417,1.491,1.567,1.642,1.715,1.785,1.849,1.907,1.958,2.001,2.035,2.06,2.075,2.08,2.075,2.061,2.036,2.002,1.959,1.908,1.848,1.781,1.708,1.63,1.549,1.465,1.38,1.296,1.215,1.138,1.066,1.003,0.948,0.904,0.871,0.85,0.842,0.847,0.864,0.893,0.934,0.985,1.043,1.109,1.179,1.251,1.323,1.393,1.459,1.518,1.568,1.609,1.638,1.656,1.66,1.653,1.634,1.604,1.565,1.518,1.466,1.412,1.357,1.305,1.259,1.22,1.192,1.176,1.173,1.186,1.214,1.258,1.316,1.387,1.47,1.562,1.659,1.76,1.86,1.955,2.043,2.12,2.182,2.228,2.254,2.261,2.247,2.212,2.158,2.087,1.999,1.9,1.792,1.68,1.567,1.459,1.358,1.27,1.196,1.141,1.106,1.091,1.098,1.126,1.174,1.238,1.317,1.406,1.502,1.601,1.699,1.791,1.873,1.944,2.0,2.039,2.061,2.064,2.051,1.648,1.707,1.773,1.843,1.913,1.979,2.037,2.082,2.11,2.119,2.107,2.071,2.013,1.934,1.836,1.723,1.599,1.469,1.34,1.217,1.106,1.013,0.942,0.898,0.882,0.898,0.944,1.019,1.122,1.246,1.389,1.544,1.704,1.863,2.014,2.151,2.269,2.364,2.43,2.467,2.474,2.451,2.401,2.326,2.231,2.121,2.001,1.878,1.757,1.644,1.544,1.461,1.398,1.357,1.338,1.342,1.365,1.407,1.462,1.526,1.595,1.664,1.728,1.783,1.824,1.849,1.856,1.844,1.813,1.763,1.698,1.621,1.535,1.445,1.355,1.271,1.197,1.138,1.096,1.074,1.076,1.1,1.148,1.218,1.307,1.412,1.531,1.658,1.788,1.917,2.039,2.151,2.249,2.328,2.387,2.423,2.436,2.425,2.392,2.339,2.266,2.179,2.08,1.972,1.861,1.748,1.639,1.537,1.444,1.362,1.295,1.242,1.206,1.185,1.179,1.188,1.21,1.244,1.288,1.34,1.398,1.46,1.524,1.589,1.653,1.714,1.771,1.824,1.871,1.911,1.945,1.971,1.99,2.0,2.003,1.998,1.985,1.963,1.933,1.896,1.851,1.799,1.741,1.677,1.608,1.535,1.46,1.383,1.307,1.233,1.161,1.095,1.036,0.984,0.942,0.91,0.89,0.882,0.887,0.903,0.931,0.971,1.02,1.077,1.141,1.21,1.281,1.353,1.422,1.487,1.545,1.595,1.635,1.663,1.679,1.682,1.673,1.651,1.617,1.574,1.523,1.467,1.407,1.346,1.288,1.235,1.19,1.155,1.133,1.125,1.133,1.158,1.199,1.256,1.327,1.411,1.506,1.608,1.715,1.822,1.925,2.022,2.108,2.18,2.235,2.271,2.286,2.28,2.252,2.203,2.134,2.048,1.949,1.839,1.723,1.606,1.491,1.383,1.286,1.204,1.14,1.096,1.074,1.075,1.097,1.14,1.202,1.279,1.369,1.467,1.57,1.672,1.77,1.859,1.936,1.999,2.045,2.073,2.082,2.073,1.66,1.718,1.783,1.852,1.92,1.983,2.037,2.077,2.101,2.106,2.088,2.049,1.987,1.904,1.804,1.689,1.565,1.437,1.31,1.191,1.086,0.999,0.936,0.9,0.894,0.918,0.972,1.055,1.164,1.295,1.442,1.599,1.759,1.917,2.065,2.198,2.309,2.395,2.453,2.481,2.477,2.444,2.384,2.3,2.197,2.08,1.955,1.828,1.704,1.59,1.491,1.409,1.348,1.31,1.295,1.302,1.329,1.373,1.431,1.497,1.566,1.635,1.697,1.749,1.787,1.807,1.809,1.792,1.755,1.701,1.631,1.55,1.462,1.37,1.28,1.197,1.125,1.069,1.031,1.015,1.022,1.052,1.106,1.181,1.276,1.386,1.508,1.637,1.769,1.898,2.02,2.131,2.226,2.302,2.358,2.391,2.402,2.389,2.355,2.302,2.231,2.146,2.051,1.949,1.844,1.74,1.64,1.547,1.463,1.392,1.334,1.29,1.26,1.246,1.244,1.256,1.279,1.311,1.351,1.398,1.448,1.501,1.555,1.608,1.66,1.708,1.753,1.793,1.829,1.859,1.884,1.903,1.916,1.923,1.924,1.919,1.908,1.89,1.866,1.836,1.799,1.756,1.707,1.653,1.594,1.531,1.465,1.397,1.329,1.262,1.197,1.136,1.08,1.032,0.992,0.962,0.943,0.934,0.938,0.954,0.981,1.018,1.066,1.122,1.185,1.252,1.322,1.392,1.461,1.525,1.583,1.632,1.671,1.699,1.713,1.715,1.703,1.679,1.642,1.595,1.54,1.478,1.412,1.345,1.28,1.219,1.167,1.125,1.096,1.082,1.085,1.104,1.141,1.196,1.266,1.351,1.448,1.554,1.665,1.778,1.889,1.995,2.09,2.172,2.237,2.282,2.307,2.308,2.287,2.244,2.18,2.097,1.998,1.887,1.769,1.647,1.526,1.411,1.306,1.216,1.143,1.091,1.061,1.054,1.07,1.108,1.166,1.242,1.332,1.431,1.537,1.643,1.746,1.842,1.926,1.996,2.049,2.083,2.097,2.093,1.671,1.729,1.793,1.859,1.925,1.985,2.035,2.072,2.092,2.091,2.07,2.026,1.96,1.875,1.772,1.657,1.533,1.407,1.283,1.169,1.069,0.989,0.933,0.905,0.907,0.94,1.002,1.093,1.208,1.344,1.494,1.653,1.813,1.969,2.113,2.24,2.345,2.423,2.471,2.489,2.476,2.433,2.363,2.27,2.159,2.035,1.905,1.774,1.649,1.534,1.435,1.356,1.298,1.263,1.252,1.263,1.294,1.342,1.402,1.469,1.54,1.608,1.668,1.718,1.752,1.768,1.766,1.743,1.702,1.643,1.57,1.485,1.394,1.302,1.212,1.13,1.06,1.007,0.974,0.962,0.974,1.01,1.069,1.149,1.247,1.361,1.485,1.616,1.748,1.877,1.997,2.105,2.198,2.271,2.323,2.354,2.361,2.347,2.312,2.259,2.19,2.109,2.019,1.923,1.826,1.73,1.64,1.557,1.484,1.423,1.375,1.34,1.318,1.309,1.313,1.326,1.349,1.379,1.415,1.455,1.497,1.54,1.583,1.624,1.663,1.698,1.73,1.758,1.782,1.802,1.818,1.831,1.839,1.844,1.844,1.84,1.832,1.82,1.802,1.78,1.752,1.719,1.681,1.637,1.589,1.536,1.48,1.422,1.362,1.302,1.243,1.188,1.136,1.091,1.053,1.024,1.005,0.997,1.0,1.014,1.039,1.075,1.121,1.175,1.236,1.302,1.371,1.441,1.509,1.572,1.629,1.678,1.717,1.744,1.758,1.758,1.744,1.717,1.678,1.627,1.567,1.499,1.427,1.354,1.281,1.214,1.153,1.103,1.067,1.045,1.041,1.055,1.087,1.138,1.206,1.29,1.388,1.496,1.611,1.73,1.848,1.961,2.066,2.157,2.232,2.288,2.322,2.332,2.319,2.282,2.223,2.144,2.047,1.936,1.815,1.69,1.564,1.442,1.33,1.231,1.15,1.089,1.051,1.036,1.045,1.078,1.132,1.206,1.295,1.395,1.503,1.613,1.721,1.823,1.913,1.99,2.05,2.09,2.111,2.112,1.682,1.738,1.801,1.866,1.929,1.986,2.033,2.066,2.081,2.076,2.05,2.003,1.934,1.846,1.742,1.626,1.503,1.378,1.258,1.149,1.054,0.981,0.933,0.913,0.923,0.964,1.034,1.131,1.252,1.392,1.545,1.705,1.865,2.018,2.158,2.279,2.376,2.446,2.485,2.493,2.469,2.417,2.337,2.236,2.118,1.988,1.853,1.719,1.592,1.478,1.38,1.303,1.248,1.218,1.211,1.227,1.262,1.313,1.375,1.445,1.516,1.584,1.643,1.69,1.721,1.734,1.727,1.7,1.654,1.591,1.514,1.427,1.334,1.24,1.15,1.07,1.003,0.953,0.923,0.916,0.933,0.973,1.037,1.121,1.223,1.339,1.465,1.596,1.727,1.854,1.972,2.077,2.165,2.235,2.283,2.31,2.315,2.299,2.264,2.212,2.145,2.068,1.984,1.895,1.807,1.721,1.641,1.569,1.507,1.457,1.419,1.393,1.378,1.376,1.383,1.398,1.42,1.448,1.479,1.512,1.545,1.577,1.608,1.636,1.662,1.684,1.703,1.719,1.732,1.742,1.75,1.756,1.761,1.763,1.764,1.762,1.759,1.752,1.742,1.729,1.711,1.689,1.662,1.63,1.593,1.551,1.505,1.456,1.405,1.352,1.3,1.249,1.202,1.16,1.124,1.096,1.077,1.067,1.069,1.082,1.105,1.139,1.183,1.235,1.295,1.359,1.427,1.496,1.563,1.626,1.683,1.732,1.77,1.797,1.81,1.809,1.794,1.765,1.723,1.669,1.604,1.531,1.453,1.373,1.293,1.217,1.149,1.09,1.045,1.015,1.003,1.01,1.036,1.082,1.147,1.229,1.326,1.436,1.555,1.678,1.802,1.923,2.036,2.137,2.222,2.287,2.331,2.351,2.347,2.317,2.264,2.189,2.095,1.984,1.863,1.734,1.604,1.476,1.357,1.25,1.16,1.091,1.044,1.021,1.024,1.05,1.1,1.17,1.258,1.359,1.468,1.582,1.694,1.801,1.898,1.982,2.048,2.096,2.123,2.129,1.691,1.747,1.809,1.872,1.932,1.986,2.03,2.058,2.07,2.061,2.031,1.98,1.908,1.818,1.712,1.596,1.474,1.352,1.236,1.131,1.043,0.976,0.935,0.923,0.941,0.99,1.067,1.171,1.297,1.44,1.596,1.756,1.914,2.064,2.2,2.314,2.404,2.465,2.494,2.492,2.458,2.396,2.308,2.198,2.073,1.937,1.798,1.662,1.534,1.42,1.325,1.251,1.2,1.174,1.172,1.192,1.232,1.286,1.352,1.424,1.496,1.564,1.622,1.667,1.695,1.704,1.693,1.662,1.612,1.545,1.465,1.375,1.281,1.186,1.097,1.018,0.953,0.906,0.881,0.878,0.899,0.944,1.011,1.098,1.202,1.32,1.446,1.576,1.706,1.83,1.944,2.045,2.129,2.194,2.239,2.262,2.264,2.246,2.211,2.16,2.097,2.024,1.946,1.866,1.786,1.711,1.642,1.581,1.531,1.492,1.464,1.447,1.44,1.443,1.454,1.47,1.492,1.516,1.541,1.566,1.59,1.611,1.63,1.645,1.657,1.666,1.672,1.675,1.678,1.679,1.68,1.68,1.682,1.683,1.685,1.687,1.688,1.689,1.688,1.684,1.677,1.666,1.651,1.631,1.605,1.575,1.54,1.5,1.457,1.412,1.365,1.32,1.276,1.236,1.202,1.174,1.154,1.144,1.144,1.155,1.176,1.208,1.249,1.3,1.357,1.42,1.487,1.555,1.621,1.684,1.742,1.79,1.829,1.856,1.869,1.868,1.852,1.821,1.777,1.719,1.651,1.573,1.489,1.402,1.315,1.231,1.154,1.086,1.032,0.993,0.972,0.971,0.99,1.03,1.09,1.169,1.265,1.375,1.496,1.623,1.753,1.88,2.001,2.111,2.206,2.281,2.335,2.365,2.37,2.348,2.302,2.232,2.141,2.032,1.911,1.78,1.646,1.513,1.387,1.273,1.174,1.096,1.041,1.01,1.005,1.025,1.07,1.136,1.222,1.322,1.433,1.549,1.666,1.778,1.881,1.971,2.045,2.099,2.132,2.144,1.7,1.755,1.815,1.876,1.935,1.986,2.026,2.051,2.058,2.045,2.012,1.957,1.883,1.79,1.684,1.568,1.448,1.328,1.215,1.115,1.033,0.973,0.94,0.935,0.961,1.017,1.101,1.21,1.341,1.488,1.645,1.805,1.961,2.108,2.238,2.346,2.427,2.479,2.499,2.487,2.443,2.371,2.274,2.157,2.025,1.885,1.742,1.604,1.476,1.363,1.27,1.2,1.154,1.132,1.136,1.161,1.205,1.264,1.333,1.407,1.48,1.548,1.606,1.649,1.674,1.68,1.665,1.63,1.576,1.506,1.423,1.331,1.236,1.141,1.053,0.975,0.913,0.869,0.847,0.848,0.873,0.921,0.991,1.081,1.186,1.304,1.43,1.558,1.685,1.806,1.916,2.011,2.09,2.15,2.19,2.209,2.209,2.19,2.154,2.105,2.045,1.978,1.906,1.834,1.765,1.7,1.643,1.594,1.556,1.528,1.51,1.503,1.503,1.511,1.525,1.543,1.563,1.583,1.602,1.619,1.633,1.642,1.648,1.65,1.648,1.644,1.637,1.629,1.621,1.614,1.608,1.604,1.603,1.604,1.608,1.615,1.622,1.631,1.639,1.646,1.651,1.652,1.649,1.641,1.627,1.608,1.583,1.552,1.518,1.479,1.439,1.397,1.357,1.319,1.285,1.257,1.237,1.225,1.223,1.231,1.25,1.279,1.318,1.366,1.421,1.483,1.548,1.615,1.682,1.745,1.802,1.852,1.891,1.919,1.932,1.931,1.915,1.884,1.837,1.778,1.705,1.624,1.534,1.441,1.346,1.254,1.168,1.091,1.027,0.979,0.949,0.939,0.95,0.983,1.037,1.112,1.205,1.314,1.436,1.566,1.7,1.833,1.962,2.08,2.184,2.27,2.334,2.374,2.388,2.375,2.336,2.272,2.186,2.079,1.958,1.826,1.689,1.551,1.419,1.298,1.192,1.105,1.041,1.002,0.989,1.002,1.041,1.104,1.187,1.286,1.397,1.516,1.636,1.753,1.862,1.959,2.039,2.1,2.139,2.157,1.708,1.762,1.821,1.88,1.936,1.984,2.021,2.042,2.046,2.03,1.993,1.935,1.858,1.764,1.657,1.542,1.423,1.306,1.197,1.102,1.026,0.973,0.947,0.949,0.982,1.045,1.135,1.25,1.385,1.535,1.692,1.852,2.006,2.148,2.273,2.373,2.447,2.489,2.499,2.477,2.424,2.343,2.238,2.113,1.975,1.83,1.685,1.546,1.418,1.307,1.217,1.151,1.109,1.094,1.102,1.133,1.182,1.246,1.318,1.395,1.47,1.538,1.595,1.636,1.659,1.662,1.644,1.605,1.548,1.475,1.39,1.296,1.2,1.105,1.017,0.942,0.882,0.841,0.822,0.826,0.855,0.906,0.978,1.069,1.176,1.293,1.417,1.543,1.666,1.781,1.886,1.976,2.049,2.104,2.138,2.153,2.15,2.129,2.094,2.047,1.99,1.929,1.865,1.802,1.743,1.69,1.644,1.608,1.582,1.565,1.558,1.559,1.567,1.58,1.597,1.615,1.632,1.648,1.661,1.669,1.672,1.67,1.663,1.652,1.636,1.619,1.6,1.581,1.563,1.548,1.536,1.528,1.526,1.528,1.535,1.547,1.561,1.579,1.597,1.615,1.632,1.645,1.655,1.659,1.657,1.649,1.634,1.612,1.585,1.553,1.518,1.48,1.442,1.405,1.372,1.343,1.321,1.307,1.302,1.307,1.323,1.349,1.386,1.431,1.485,1.545,1.609,1.675,1.742,1.805,1.864,1.914,1.955,1.983,1.998,1.998,1.982,1.951,1.904,1.842,1.767,1.681,1.587,1.488,1.386,1.286,1.191,1.105,1.032,0.973,0.933,0.914,0.916,0.941,0.988,1.058,1.147,1.254,1.375,1.507,1.644,1.783,1.918,2.045,2.158,2.254,2.328,2.378,2.402,2.398,2.367,2.309,2.228,2.125,2.005,1.873,1.733,1.592,1.454,1.326,1.212,1.117,1.044,0.996,0.976,0.982,1.015,1.073,1.153,1.25,1.362,1.482,1.605,1.727,1.841,1.944,2.031,2.098,2.145,2.168,1.715,1.768,1.826,1.883,1.937,1.982,2.015,2.033,2.033,2.014,1.973,1.913,1.834,1.739,1.632,1.517,1.4,1.286,1.181,1.091,1.021,0.974,0.955,0.965,1.005,1.074,1.17,1.29,1.428,1.58,1.738,1.896,2.048,2.186,2.304,2.397,2.462,2.495,2.496,2.464,2.402,2.311,2.198,2.067,1.924,1.775,1.628,1.488,1.361,1.252,1.166,1.104,1.068,1.058,1.073,1.11,1.164,1.232,1.309,1.388,1.465,1.533,1.59,1.63,1.65,1.651,1.63,1.588,1.528,1.452,1.364,1.27,1.172,1.078,0.992,0.918,0.86,0.822,0.806,0.814,0.845,0.898,0.973,1.064,1.17,1.286,1.407,1.529,1.648,1.758,1.856,1.94,2.007,2.055,2.084,2.095,2.088,2.066,2.031,1.986,1.934,1.879,1.822,1.769,1.72,1.679,1.646,1.622,1.608,1.603,1.606,1.615,1.63,1.648,1.667,1.685,1.7,1.711,1.717,1.716,1.708,1.694,1.675,1.65,1.621,1.591,1.56,1.53,1.503,1.481,1.464,1.454,1.451,1.455,1.466,1.484,1.507,1.533,1.562,1.592,1.621,1.647,1.669,1.685,1.695,1.697,1.692,1.679,1.659,1.632,1.601,1.566,1.53,1.494,1.459,1.429,1.405,1.388,1.38,1.382,1.394,1.417,1.45,1.493,1.545,1.603,1.666,1.732,1.799,1.863,1.922,1.975,2.017,2.048,2.064,2.066,2.052,2.021,1.974,1.911,1.834,1.746,1.647,1.543,1.435,1.327,1.224,1.128,1.045,0.976,0.926,0.896,0.889,0.905,0.944,1.007,1.092,1.196,1.315,1.448,1.588,1.731,1.872,2.005,2.127,2.232,2.317,2.377,2.411,2.416,2.394,2.343,2.268,2.169,2.051,1.919,1.778,1.633,1.491,1.356,1.235,1.131,1.05,0.994,0.965,0.965,0.991,1.044,1.12,1.216,1.327,1.448,1.574,1.7,1.819,1.928,2.021,2.095,2.148,2.178,1.721,1.774,1.83,1.886,1.937,1.979,2.009,2.024,2.021,1.998,1.955,1.892,1.811,1.714,1.607,1.493,1.378,1.267,1.167,1.082,1.017,0.977,0.965,0.982,1.029,1.104,1.206,1.33,1.471,1.624,1.782,1.939,2.087,2.22,2.332,2.417,2.474,2.498,2.489,2.447,2.376,2.277,2.156,2.019,1.871,1.719,1.57,1.43,1.305,1.199,1.117,1.06,1.031,1.027,1.048,1.091,1.151,1.224,1.304,1.386,1.465,1.534,1.59,1.629,1.648,1.646,1.622,1.578,1.515,1.437,1.348,1.252,1.154,1.061,0.975,0.903,0.848,0.813,0.8,0.81,0.844,0.899,0.974,1.066,1.171,1.284,1.402,1.519,1.632,1.736,1.827,1.904,1.963,2.005,2.029,2.035,2.025,2.001,1.967,1.924,1.876,1.827,1.779,1.735,1.698,1.668,1.648,1.636,1.634,1.64,1.653,1.672,1.693,1.715,1.736,1.754,1.766,1.772,1.77,1.76,1.741,1.715,1.682,1.644,1.603,1.56,1.518,1.478,1.443,1.415,1.394,1.382,1.38,1.386,1.402,1.427,1.458,1.495,1.535,1.577,1.618,1.656,1.69,1.718,1.739,1.752,1.755,1.75,1.736,1.714,1.687,1.654,1.618,1.582,1.546,1.514,1.486,1.466,1.454,1.452,1.461,1.48,1.51,1.55,1.599,1.655,1.718,1.783,1.85,1.916,1.977,2.031,2.076,2.109,2.129,2.133,2.121,2.091,2.045,1.983,1.905,1.814,1.713,1.604,1.49,1.375,1.264,1.16,1.066,0.987,0.926,0.886,0.868,0.875,0.906,0.962,1.04,1.139,1.257,1.388,1.53,1.676,1.822,1.963,2.092,2.207,2.301,2.371,2.415,2.43,2.416,2.374,2.305,2.211,2.096,1.965,1.823,1.675,1.529,1.388,1.26,1.149,1.06,0.995,0.958,0.95,0.97,1.017,1.089,1.182,1.292,1.414,1.542,1.671,1.795,1.91,2.009,2.09,2.149,2.185,1.727,1.779,1.833,1.887,1.936,1.976,2.003,2.015,2.008,1.982,1.936,1.871,1.788,1.691,1.584,1.471,1.358,1.251,1.154,1.075,1.016,0.982,0.977,1.0,1.053,1.134,1.241,1.369,1.513,1.667,1.825,1.979,2.123,2.251,2.356,2.434,2.482,2.496,2.478,2.427,2.347,2.24,2.112,1.969,1.817,1.662,1.512,1.373,1.25,1.149,1.071,1.02,0.997,1.0,1.028,1.077,1.143,1.221,1.305,1.391,1.471,1.542,1.598,1.635,1.653,1.648,1.622,1.575,1.51,1.43,1.339,1.243,1.145,1.052,0.969,0.898,0.846,0.813,0.803,0.816,0.851,0.908,0.983,1.074,1.177,1.287,1.401,1.512,1.619,1.715,1.799,1.868,1.92,1.954,1.972,1.973,1.96,1.935,1.901,1.861,1.818,1.775,1.735,1.701,1.675,1.657,1.649,1.651,1.661,1.678,1.701,1.727,1.755,1.781,1.803,1.82,1.829,1.829,1.819,1.8,1.77,1.732,1.687,1.636,1.582,1.528,1.475,1.426,1.384,1.35,1.326,1.313,1.312,1.323,1.344,1.376,1.416,1.463,1.515,1.569,1.622,1.673,1.719,1.758,1.79,1.811,1.823,1.824,1.816,1.798,1.773,1.741,1.705,1.667,1.629,1.594,1.563,1.539,1.522,1.516,1.52,1.535,1.561,1.598,1.645,1.7,1.761,1.827,1.895,1.961,2.025,2.082,2.13,2.166,2.189,2.197,2.188,2.161,2.117,2.055,1.978,1.886,1.783,1.67,1.551,1.43,1.312,1.199,1.096,1.007,0.935,0.884,0.856,0.852,0.874,0.921,0.992,1.087,1.2,1.33,1.472,1.621,1.771,1.917,2.054,2.177,2.28,2.361,2.414,2.44,2.435,2.401,2.338,2.25,2.139,2.01,1.867,1.718,1.568,1.422,1.288,1.169,1.072,0.999,0.954,0.937,0.95,0.992,1.059,1.149,1.258,1.38,1.51,1.642,1.771,1.89,1.996,2.083,2.149,2.191,1.732,1.783,1.836,1.888,1.935,1.972,1.996,2.005,1.995,1.966,1.918,1.851,1.767,1.669,1.562,1.451,1.34,1.236,1.144,1.069,1.016,0.989,0.989,1.019,1.078,1.165,1.276,1.407,1.553,1.708,1.865,2.017,2.157,2.279,2.377,2.447,2.486,2.492,2.464,2.405,2.315,2.201,2.067,1.918,1.763,1.606,1.456,1.318,1.198,1.1,1.028,0.984,0.967,0.977,1.012,1.068,1.14,1.223,1.312,1.401,1.483,1.555,1.611,1.648,1.664,1.657,1.629,1.58,1.513,1.431,1.339,1.242,1.145,1.053,0.971,0.903,0.853,0.823,0.815,0.83,0.867,0.924,0.999,1.089,1.189,1.295,1.404,1.509,1.608,1.697,1.772,1.833,1.877,1.904,1.915,1.911,1.895,1.868,1.834,1.797,1.759,1.722,1.691,1.668,1.652,1.647,1.651,1.665,1.687,1.715,1.748,1.782,1.815,1.845,1.868,1.884,1.889,1.883,1.865,1.836,1.796,1.746,1.688,1.625,1.559,1.493,1.431,1.374,1.325,1.287,1.261,1.248,1.249,1.264,1.292,1.332,1.382,1.44,1.503,1.568,1.634,1.697,1.754,1.804,1.845,1.875,1.893,1.9,1.896,1.881,1.857,1.826,1.789,1.748,1.707,1.668,1.633,1.603,1.582,1.571,1.57,1.581,1.604,1.637,1.681,1.735,1.795,1.861,1.93,1.998,2.064,2.124,2.176,2.216,2.244,2.255,2.25,2.227,2.186,2.127,2.051,1.96,1.855,1.739,1.617,1.491,1.365,1.244,1.133,1.034,0.952,0.89,0.85,0.836,0.848,0.886,0.95,1.037,1.147,1.274,1.415,1.565,1.718,1.869,2.013,2.144,2.256,2.346,2.41,2.445,2.45,2.424,2.369,2.286,2.18,2.053,1.912,1.761,1.608,1.458,1.317,1.191,1.086,1.005,0.952,0.928,0.934,0.969,1.031,1.118,1.225,1.346,1.478,1.612,1.745,1.869,1.981,2.074,2.147,2.195,1.737,1.787,1.839,1.889,1.933,1.968,1.989,1.995,1.983,1.951,1.9,1.831,1.746,1.648,1.542,1.432,1.323,1.223,1.135,1.065,1.018,0.996,1.003,1.039,1.104,1.196,1.311,1.445,1.592,1.747,1.903,2.052,2.187,2.304,2.395,2.457,2.488,2.484,2.448,2.379,2.282,2.161,2.02,1.867,1.708,1.551,1.401,1.265,1.148,1.056,0.989,0.951,0.942,0.959,1.001,1.064,1.142,1.231,1.324,1.416,1.501,1.574,1.63,1.667,1.681,1.673,1.643,1.592,1.523,1.44,1.347,1.25,1.154,1.063,0.982,0.916,0.869,0.841,0.836,0.853,0.891,0.948,1.023,1.11,1.207,1.309,1.411,1.51,1.601,1.681,1.747,1.799,1.834,1.854,1.858,1.849,1.829,1.801,1.768,1.733,1.7,1.67,1.648,1.634,1.63,1.637,1.653,1.679,1.713,1.752,1.793,1.835,1.874,1.906,1.931,1.944,1.946,1.934,1.908,1.869,1.818,1.756,1.686,1.611,1.534,1.458,1.386,1.322,1.268,1.226,1.199,1.187,1.191,1.211,1.246,1.295,1.354,1.423,1.497,1.575,1.652,1.726,1.794,1.854,1.903,1.941,1.965,1.977,1.976,1.962,1.939,1.906,1.867,1.823,1.778,1.734,1.694,1.659,1.633,1.616,1.61,1.616,1.635,1.665,1.707,1.758,1.818,1.884,1.954,2.025,2.093,2.157,2.213,2.258,2.29,2.307,2.307,2.289,2.252,2.197,2.123,2.033,1.928,1.811,1.686,1.556,1.424,1.296,1.176,1.068,0.975,0.902,0.852,0.827,0.828,0.857,0.912,0.993,1.096,1.22,1.359,1.509,1.665,1.82,1.969,2.107,2.228,2.327,2.401,2.446,2.461,2.444,2.396,2.32,2.218,2.095,1.955,1.804,1.648,1.494,1.348,1.216,1.103,1.014,0.953,0.921,0.919,0.948,1.005,1.088,1.192,1.313,1.445,1.582,1.718,1.848,1.964,2.064,2.143,2.198,1.741,1.79,1.84,1.889,1.931,1.963,1.982,1.985,1.97,1.936,1.883,1.812,1.726,1.628,1.522,1.414,1.308,1.211,1.127,1.063,1.021,1.005,1.018,1.06,1.13,1.226,1.345,1.481,1.63,1.785,1.939,2.084,2.215,2.325,2.41,2.464,2.486,2.474,2.428,2.352,2.247,2.119,1.973,1.816,1.655,1.496,1.347,1.214,1.102,1.014,0.954,0.923,0.921,0.946,0.996,1.065,1.15,1.244,1.342,1.438,1.525,1.599,1.655,1.691,1.705,1.695,1.663,1.61,1.54,1.456,1.363,1.266,1.17,1.08,1.002,0.938,0.893,0.868,0.865,0.884,0.923,0.98,1.053,1.138,1.231,1.327,1.423,1.514,1.597,1.668,1.725,1.767,1.794,1.805,1.803,1.788,1.765,1.735,1.702,1.67,1.641,1.619,1.605,1.601,1.608,1.627,1.656,1.694,1.738,1.787,1.838,1.886,1.93,1.965,1.99,2.001,1.998,1.98,1.946,1.898,1.836,1.763,1.682,1.596,1.508,1.422,1.342,1.271,1.213,1.168,1.141,1.131,1.139,1.165,1.207,1.265,1.334,1.413,1.499,1.588,1.676,1.761,1.839,1.907,1.964,2.008,2.037,2.052,2.053,2.04,2.015,1.98,1.938,1.89,1.84,1.791,1.744,1.704,1.672,1.649,1.638,1.639,1.654,1.681,1.72,1.77,1.829,1.895,1.966,2.039,2.111,2.179,2.239,2.29,2.328,2.351,2.357,2.344,2.313,2.262,2.192,2.104,2.001,1.884,1.757,1.623,1.487,1.353,1.225,1.108,1.006,0.922,0.861,0.825,0.815,0.834,0.88,0.952,1.05,1.168,1.305,1.454,1.611,1.77,1.924,2.068,2.197,2.305,2.389,2.443,2.467,2.46,2.42,2.351,2.255,2.135,1.997,1.846,1.688,1.531,1.38,1.242,1.122,1.025,0.956,0.916,0.907,0.929,0.981,1.06,1.161,1.281,1.413,1.552,1.691,1.825,1.947,2.053,2.137,2.198,1.744,1.792,1.842,1.888,1.928,1.958,1.975,1.975,1.958,1.921,1.866,1.794,1.707,1.609,1.504,1.397,1.294,1.201,1.121,1.061,1.025,1.015,1.034,1.081,1.156,1.256,1.378,1.517,1.667,1.821,1.972,2.114,2.24,2.345,2.422,2.468,2.482,2.461,2.407,2.322,2.21,2.076,1.925,1.765,1.602,1.443,1.296,1.166,1.058,0.976,0.923,0.899,0.905,0.938,0.995,1.072,1.163,1.263,1.366,1.464,1.554,1.629,1.686,1.722,1.734,1.723,1.689,1.635,1.563,1.478,1.385,1.288,1.193,1.105,1.029,0.968,0.925,0.903,0.902,0.922,0.961,1.018,1.09,1.172,1.26,1.351,1.44,1.522,1.596,1.657,1.705,1.737,1.755,1.758,1.748,1.728,1.701,1.67,1.637,1.608,1.584,1.568,1.563,1.569,1.587,1.617,1.658,1.707,1.763,1.822,1.881,1.936,1.984,2.021,2.046,2.055,2.048,2.023,1.981,1.923,1.851,1.767,1.675,1.578,1.48,1.386,1.299,1.222,1.16,1.114,1.087,1.08,1.093,1.125,1.175,1.241,1.321,1.411,1.507,1.607,1.705,1.8,1.886,1.962,2.026,2.074,2.107,2.124,2.125,2.112,2.085,2.047,2.0,1.948,1.892,1.836,1.784,1.737,1.698,1.67,1.653,1.65,1.66,1.683,1.72,1.768,1.826,1.893,1.966,2.041,2.117,2.189,2.255,2.311,2.355,2.385,2.398,2.392,2.366,2.321,2.256,2.172,2.071,1.955,1.828,1.693,1.553,1.413,1.279,1.154,1.042,0.949,0.877,0.829,0.809,0.817,0.853,0.917,1.007,1.12,1.253,1.401,1.558,1.719,1.877,2.028,2.164,2.28,2.372,2.437,2.47,2.472,2.441,2.379,2.289,2.173,2.037,1.887,1.729,1.568,1.413,1.269,1.143,1.039,0.961,0.914,0.897,0.913,0.959,1.033,1.131,1.249,1.382,1.522,1.664,1.801,1.928,2.04,2.131,2.198,1.747,1.795,1.843,1.887,1.926,1.953,1.968,1.965,1.946,1.907,1.85,1.777,1.689,1.591,1.487,1.382,1.282,1.192,1.117,1.062,1.03,1.026,1.05,1.102,1.181,1.286,1.411,1.551,1.701,1.854,2.004,2.142,2.263,2.361,2.431,2.47,2.475,2.446,2.384,2.291,2.172,2.032,1.878,1.714,1.55,1.392,1.247,1.12,1.017,0.942,0.896,0.88,0.894,0.935,1.0,1.084,1.182,1.287,1.394,1.496,1.588,1.665,1.722,1.757,1.768,1.755,1.72,1.664,1.592,1.506,1.413,1.317,1.223,1.137,1.063,1.004,0.964,0.944,0.945,0.966,1.006,1.063,1.132,1.211,1.294,1.379,1.46,1.534,1.598,1.65,1.687,1.71,1.718,1.712,1.695,1.67,1.639,1.606,1.574,1.547,1.528,1.519,1.522,1.538,1.567,1.608,1.66,1.721,1.787,1.855,1.922,1.983,2.035,2.074,2.098,2.105,2.093,2.061,2.011,1.944,1.862,1.768,1.665,1.559,1.452,1.35,1.256,1.175,1.11,1.064,1.039,1.035,1.052,1.091,1.149,1.225,1.314,1.414,1.521,1.631,1.739,1.842,1.936,2.019,2.087,2.139,2.174,2.192,2.192,2.177,2.147,2.105,2.053,1.995,1.933,1.871,1.811,1.758,1.712,1.678,1.655,1.647,1.652,1.672,1.706,1.753,1.811,1.878,1.952,2.03,2.109,2.186,2.258,2.32,2.371,2.408,2.428,2.43,2.412,2.373,2.314,2.235,2.138,2.025,1.898,1.762,1.62,1.477,1.336,1.204,1.084,0.981,0.898,0.84,0.809,0.806,0.832,0.887,0.969,1.076,1.204,1.349,1.506,1.668,1.83,1.985,2.128,2.252,2.353,2.427,2.47,2.48,2.458,2.404,2.32,2.209,2.076,1.928,1.769,1.606,1.447,1.298,1.165,1.054,0.969,0.914,0.89,0.899,0.939,1.008,1.103,1.219,1.351,1.492,1.636,1.777,1.909,2.026,2.122,2.195,1.75,1.796,1.843,1.886,1.923,1.948,1.96,1.956,1.934,1.893,1.835,1.76,1.672,1.574,1.471,1.368,1.271,1.184,1.113,1.063,1.036,1.037,1.066,1.123,1.207,1.315,1.442,1.584,1.734,1.886,2.033,2.167,2.283,2.375,2.438,2.469,2.466,2.428,2.359,2.259,2.134,1.989,1.83,1.665,1.5,1.343,1.201,1.078,0.981,0.912,0.873,0.865,0.887,0.937,1.009,1.101,1.205,1.316,1.427,1.533,1.627,1.705,1.762,1.796,1.807,1.793,1.756,1.699,1.625,1.539,1.446,1.35,1.258,1.174,1.102,1.047,1.009,0.992,0.995,1.017,1.057,1.113,1.18,1.255,1.333,1.411,1.485,1.55,1.604,1.646,1.672,1.685,1.683,1.669,1.645,1.614,1.579,1.544,1.513,1.488,1.474,1.471,1.482,1.508,1.547,1.599,1.663,1.734,1.81,1.887,1.961,2.028,2.083,2.124,2.147,2.151,2.134,2.096,2.038,1.962,1.87,1.766,1.654,1.538,1.423,1.314,1.215,1.131,1.064,1.018,0.995,0.995,1.018,1.064,1.13,1.215,1.314,1.424,1.54,1.659,1.776,1.886,1.987,2.075,2.147,2.201,2.237,2.254,2.253,2.234,2.2,2.153,2.095,2.03,1.962,1.892,1.826,1.765,1.713,1.672,1.644,1.63,1.632,1.648,1.679,1.724,1.782,1.85,1.926,2.006,2.089,2.171,2.248,2.317,2.376,2.42,2.449,2.458,2.448,2.417,2.365,2.293,2.2,2.091,1.967,1.831,1.688,1.541,1.396,1.258,1.13,1.018,0.926,0.857,0.815,0.801,0.817,0.862,0.936,1.036,1.159,1.3,1.455,1.618,1.782,1.942,2.09,2.222,2.331,2.414,2.466,2.486,2.472,2.426,2.348,2.243,2.114,1.967,1.808,1.643,1.481,1.327,1.188,1.07,0.978,0.915,0.884,0.886,0.92,0.984,1.076,1.189,1.32,1.462,1.609,1.753,1.889,2.011,2.113,2.192,1.753,1.798,1.843,1.885,1.92,1.943,1.953,1.946,1.922,1.88,1.82,1.744,1.656,1.558,1.457,1.356,1.261,1.177,1.11,1.065,1.043,1.049,1.083,1.144,1.232,1.343,1.473,1.616,1.766,1.916,2.06,2.19,2.301,2.386,2.442,2.465,2.455,2.41,2.332,2.226,2.095,1.946,1.784,1.617,1.452,1.297,1.157,1.039,0.947,0.885,0.854,0.855,0.885,0.943,1.024,1.122,1.233,1.349,1.465,1.574,1.67,1.748,1.806,1.84,1.849,1.834,1.795,1.737,1.662,1.576,1.483,1.388,1.298,1.216,1.147,1.094,1.059,1.044,1.049,1.073,1.113,1.168,1.232,1.304,1.377,1.448,1.513,1.569,1.614,1.644,1.661,1.663,1.651,1.628,1.597,1.56,1.521,1.485,1.454,1.432,1.421,1.425,1.444,1.479,1.528,1.591,1.665,1.747,1.833,1.918,1.998,2.07,2.128,2.17,2.192,2.193,2.171,2.127,2.061,1.976,1.875,1.762,1.641,1.517,1.395,1.28,1.176,1.089,1.022,0.977,0.956,0.96,0.99,1.043,1.118,1.211,1.319,1.438,1.564,1.691,1.815,1.932,2.038,2.13,2.204,2.26,2.295,2.31,2.306,2.283,2.244,2.19,2.126,2.054,1.978,1.902,1.828,1.76,1.701,1.654,1.62,1.601,1.598,1.611,1.64,1.684,1.741,1.809,1.886,1.97,2.057,2.143,2.226,2.302,2.368,2.421,2.458,2.476,2.475,2.452,2.408,2.343,2.257,2.152,2.032,1.898,1.755,1.606,1.458,1.314,1.179,1.059,0.958,0.879,0.826,0.802,0.807,0.842,0.907,1.0,1.116,1.254,1.406,1.569,1.735,1.898,2.051,2.19,2.307,2.398,2.459,2.488,2.483,2.444,2.374,2.274,2.149,2.004,1.846,1.681,1.515,1.357,1.213,1.089,0.989,0.919,0.881,0.876,0.904,0.963,1.05,1.161,1.291,1.433,1.581,1.728,1.868,1.995,2.103,2.187,1.755,1.799,1.843,1.884,1.916,1.938,1.946,1.937,1.911,1.867,1.806,1.729,1.641,1.544,1.443,1.344,1.252,1.172,1.109,1.067,1.051,1.061,1.1,1.165,1.257,1.371,1.502,1.646,1.796,1.944,2.085,2.211,2.316,2.396,2.444,2.46,2.442,2.389,2.305,2.193,2.056,1.903,1.738,1.57,1.406,1.252,1.116,1.003,0.918,0.863,0.84,0.849,0.887,0.953,1.042,1.148,1.265,1.387,1.506,1.618,1.716,1.795,1.853,1.886,1.894,1.877,1.837,1.778,1.702,1.616,1.523,1.43,1.341,1.261,1.195,1.145,1.113,1.101,1.108,1.133,1.173,1.227,1.289,1.356,1.424,1.488,1.545,1.592,1.626,1.646,1.652,1.643,1.622,1.59,1.552,1.509,1.466,1.428,1.397,1.377,1.372,1.381,1.408,1.452,1.511,1.584,1.668,1.759,1.854,1.947,2.033,2.109,2.17,2.212,2.233,2.231,2.204,2.154,2.08,1.987,1.878,1.756,1.627,1.495,1.366,1.246,1.14,1.051,0.983,0.94,0.922,0.932,0.967,1.028,1.111,1.213,1.33,1.457,1.591,1.725,1.856,1.978,2.088,2.182,2.258,2.313,2.346,2.359,2.35,2.322,2.277,2.217,2.146,2.066,1.983,1.899,1.818,1.743,1.677,1.624,1.585,1.561,1.553,1.563,1.589,1.631,1.688,1.757,1.836,1.922,2.012,2.104,2.192,2.275,2.349,2.41,2.455,2.483,2.491,2.478,2.443,2.385,2.307,2.208,2.092,1.961,1.819,1.671,1.52,1.372,1.232,1.104,0.994,0.906,0.843,0.808,0.802,0.828,0.884,0.968,1.078,1.21,1.36,1.521,1.688,1.853,2.012,2.156,2.28,2.379,2.449,2.487,2.491,2.46,2.397,2.303,2.182,2.04,1.883,1.717,1.55,1.388,1.239,1.108,1.002,0.925,0.88,0.868,0.889,0.943,1.026,1.134,1.262,1.404,1.554,1.704,1.847,1.978,2.091,2.182,1.757,1.8,1.843,1.882,1.913,1.933,1.939,1.928,1.9,1.854,1.792,1.715,1.626,1.53,1.43,1.333,1.244,1.167,1.108,1.071,1.059,1.074,1.116,1.186,1.281,1.397,1.531,1.675,1.824,1.97,2.108,2.23,2.33,2.403,2.445,2.453,2.428,2.368,2.277,2.159,2.018,1.86,1.694,1.525,1.362,1.211,1.079,0.971,0.892,0.844,0.829,0.847,0.894,0.968,1.064,1.177,1.3,1.427,1.551,1.665,1.765,1.845,1.902,1.934,1.941,1.922,1.881,1.82,1.744,1.657,1.565,1.473,1.386,1.309,1.245,1.198,1.169,1.16,1.169,1.196,1.236,1.289,1.348,1.411,1.474,1.531,1.58,1.617,1.641,1.651,1.646,1.627,1.596,1.555,1.509,1.461,1.414,1.374,1.343,1.326,1.324,1.34,1.374,1.426,1.494,1.577,1.671,1.771,1.874,1.974,2.066,2.146,2.209,2.252,2.271,2.265,2.233,2.177,2.096,1.995,1.878,1.748,1.611,1.473,1.339,1.214,1.105,1.015,0.948,0.907,0.894,0.909,0.951,1.019,1.109,1.22,1.345,1.48,1.621,1.762,1.897,2.024,2.136,2.231,2.306,2.36,2.391,2.399,2.385,2.351,2.299,2.232,2.154,2.067,1.976,1.884,1.796,1.714,1.642,1.583,1.538,1.51,1.498,1.505,1.529,1.569,1.625,1.694,1.775,1.863,1.957,2.053,2.147,2.237,2.318,2.387,2.442,2.479,2.497,2.494,2.468,2.419,2.349,2.258,2.147,2.021,1.881,1.734,1.582,1.431,1.286,1.152,1.034,0.937,0.864,0.819,0.803,0.818,0.865,0.94,1.043,1.17,1.316,1.475,1.642,1.809,1.971,2.121,2.252,2.359,2.437,2.483,2.495,2.473,2.417,2.329,2.213,2.075,1.919,1.753,1.584,1.419,1.265,1.129,1.016,0.932,0.88,0.861,0.876,0.925,1.003,1.108,1.235,1.377,1.527,1.679,1.826,1.961,2.079,2.175,1.758,1.801,1.843,1.88,1.91,1.928,1.932,1.919,1.89,1.842,1.779,1.701,1.613,1.517,1.419,1.324,1.237,1.163,1.108,1.075,1.067,1.086,1.133,1.207,1.304,1.423,1.558,1.702,1.85,1.995,2.129,2.247,2.341,2.408,2.444,2.445,2.412,2.346,2.249,2.125,1.98,1.819,1.651,1.482,1.32,1.172,1.044,0.942,0.87,0.83,0.823,0.848,0.904,0.987,1.091,1.21,1.339,1.471,1.598,1.715,1.816,1.896,1.953,1.984,1.989,1.969,1.926,1.864,1.786,1.699,1.608,1.517,1.432,1.357,1.297,1.253,1.228,1.221,1.233,1.261,1.302,1.353,1.41,1.469,1.526,1.576,1.617,1.645,1.659,1.658,1.642,1.613,1.572,1.523,1.469,1.415,1.365,1.323,1.292,1.277,1.279,1.301,1.342,1.402,1.479,1.571,1.674,1.783,1.893,2.0,2.097,2.18,2.245,2.287,2.305,2.295,2.259,2.196,2.109,2.001,1.875,1.738,1.595,1.45,1.312,1.184,1.073,0.983,0.918,0.88,0.871,0.891,0.94,1.015,1.113,1.231,1.364,1.506,1.653,1.799,1.939,2.068,2.181,2.276,2.35,2.401,2.428,2.431,2.411,2.371,2.312,2.237,2.151,2.056,1.957,1.859,1.763,1.675,1.597,1.532,1.483,1.45,1.435,1.438,1.46,1.499,1.554,1.624,1.705,1.796,1.893,1.993,2.093,2.189,2.277,2.355,2.418,2.465,2.493,2.499,2.484,2.445,2.383,2.3,2.196,2.075,1.94,1.794,1.642,1.489,1.341,1.202,1.077,0.971,0.889,0.834,0.808,0.814,0.85,0.917,1.013,1.133,1.275,1.431,1.597,1.766,1.931,2.085,2.222,2.336,2.422,2.477,2.498,2.483,2.434,2.353,2.242,2.107,1.953,1.788,1.617,1.449,1.291,1.15,1.031,0.941,0.882,0.856,0.865,0.908,0.982,1.084,1.208,1.349,1.5,1.654,1.804,1.944,2.067,2.167,1.76,1.802,1.843,1.879,1.907,1.923,1.925,1.911,1.88,1.831,1.767,1.688,1.6,1.505,1.408,1.315,1.23,1.16,1.108,1.079,1.075,1.099,1.149,1.226,1.327,1.448,1.583,1.728,1.875,2.017,2.148,2.262,2.351,2.412,2.441,2.436,2.396,2.323,2.221,2.092,1.942,1.779,1.609,1.441,1.28,1.136,1.012,0.916,0.851,0.819,0.82,0.854,0.918,1.008,1.12,1.246,1.381,1.516,1.647,1.766,1.868,1.948,2.004,2.034,2.037,2.015,1.97,1.906,1.828,1.741,1.65,1.56,1.477,1.406,1.348,1.308,1.286,1.283,1.297,1.327,1.368,1.419,1.474,1.529,1.58,1.624,1.656,1.675,1.679,1.667,1.641,1.601,1.551,1.494,1.433,1.373,1.319,1.275,1.245,1.231,1.237,1.264,1.312,1.38,1.465,1.566,1.677,1.794,1.911,2.024,2.126,2.212,2.278,2.32,2.335,2.322,2.281,2.212,2.118,2.003,1.871,1.727,1.578,1.428,1.286,1.156,1.044,0.954,0.891,0.857,0.852,0.878,0.934,1.016,1.121,1.246,1.386,1.534,1.686,1.836,1.979,2.109,2.223,2.317,2.388,2.435,2.457,2.454,2.428,2.38,2.313,2.231,2.137,2.035,1.929,1.823,1.721,1.627,1.544,1.474,1.42,1.383,1.365,1.366,1.385,1.423,1.477,1.547,1.629,1.721,1.821,1.925,2.03,2.131,2.227,2.312,2.385,2.441,2.479,2.495,2.49,2.461,2.409,2.335,2.239,2.124,1.994,1.851,1.7,1.547,1.396,1.252,1.122,1.009,0.918,0.854,0.818,0.813,0.84,0.899,0.986,1.1,1.236,1.39,1.554,1.724,1.891,2.049,2.191,2.312,2.406,2.468,2.497,2.491,2.449,2.374,2.269,2.138,1.986,1.821,1.65,1.48,1.318,1.172,1.048,0.951,0.885,0.853,0.856,0.893,0.963,1.061,1.183,1.323,1.475,1.63,1.783,1.926,2.053,2.159,1.761,1.802,1.842,1.877,1.903,1.918,1.919,1.903,1.87,1.82,1.755,1.676,1.588,1.493,1.398,1.307,1.225,1.158,1.109,1.084,1.084,1.111,1.166,1.246,1.349,1.472,1.608,1.752,1.898,2.038,2.166,2.275,2.359,2.414,2.437,2.425,2.379,2.3,2.192,2.059,1.906,1.74,1.57,1.402,1.244,1.102,0.984,0.894,0.835,0.811,0.82,0.863,0.935,1.033,1.151,1.284,1.424,1.564,1.697,1.818,1.921,2.001,2.055,2.083,2.084,2.06,2.013,1.948,1.868,1.781,1.69,1.602,1.521,1.453,1.399,1.362,1.344,1.344,1.361,1.393,1.435,1.485,1.538,1.589,1.635,1.672,1.697,1.707,1.701,1.679,1.642,1.593,1.533,1.467,1.4,1.334,1.277,1.23,1.2,1.189,1.198,1.23,1.284,1.359,1.452,1.561,1.68,1.804,1.928,2.046,2.152,2.241,2.307,2.349,2.362,2.345,2.299,2.225,2.125,2.003,1.865,1.715,1.56,1.407,1.261,1.13,1.017,0.929,0.868,0.838,0.839,0.871,0.932,1.021,1.134,1.265,1.411,1.564,1.721,1.874,2.018,2.148,2.261,2.352,2.42,2.462,2.478,2.469,2.435,2.38,2.306,2.216,2.114,2.005,1.892,1.78,1.672,1.572,1.484,1.41,1.352,1.312,1.29,1.289,1.306,1.343,1.396,1.465,1.548,1.642,1.744,1.851,1.96,2.067,2.169,2.261,2.342,2.408,2.455,2.482,2.487,2.469,2.427,2.362,2.275,2.167,2.042,1.904,1.756,1.603,1.45,1.303,1.168,1.048,0.95,0.876,0.832,0.817,0.835,0.884,0.963,1.07,1.201,1.351,1.514,1.683,1.851,2.013,2.16,2.287,2.388,2.458,2.495,2.496,2.462,2.393,2.293,2.166,2.018,1.854,1.682,1.51,1.345,1.194,1.065,0.962,0.889,0.851,0.848,0.88,0.945,1.039,1.159,1.298,1.449,1.606,1.762,1.908,2.04,2.15,1.762,1.803,1.842,1.875,1.9,1.914,1.912,1.895,1.861,1.81,1.744,1.665,1.577,1.483,1.389,1.299,1.22,1.156,1.111,1.089,1.093,1.124,1.181,1.264,1.37,1.494,1.631,1.775,1.92,2.058,2.182,2.286,2.365,2.415,2.431,2.414,2.362,2.277,2.164,2.026,1.871,1.703,1.532,1.365,1.209,1.072,0.958,0.874,0.823,0.806,0.824,0.874,0.954,1.06,1.185,1.324,1.469,1.612,1.748,1.87,1.973,2.052,2.105,2.131,2.13,2.103,2.054,1.986,1.906,1.818,1.728,1.641,1.563,1.497,1.447,1.415,1.401,1.404,1.424,1.458,1.501,1.551,1.602,1.65,1.691,1.721,1.738,1.739,1.724,1.692,1.646,1.586,1.518,1.444,1.369,1.299,1.237,1.189,1.159,1.149,1.162,1.198,1.258,1.34,1.441,1.557,1.683,1.814,1.944,2.067,2.176,2.267,2.334,2.374,2.385,2.365,2.314,2.235,2.129,2.001,1.857,1.702,1.543,1.386,1.238,1.105,0.993,0.907,0.849,0.823,0.829,0.867,0.935,1.031,1.149,1.287,1.438,1.596,1.755,1.91,2.054,2.184,2.294,2.382,2.445,2.481,2.491,2.474,2.434,2.371,2.289,2.191,2.083,1.967,1.847,1.729,1.617,1.512,1.42,1.342,1.281,1.238,1.214,1.21,1.226,1.261,1.314,1.382,1.465,1.56,1.664,1.773,1.886,1.997,2.104,2.204,2.292,2.366,2.423,2.46,2.476,2.468,2.436,2.381,2.303,2.204,2.086,1.952,1.808,1.656,1.503,1.354,1.214,1.089,0.984,0.902,0.848,0.825,0.833,0.873,0.944,1.044,1.169,1.315,1.475,1.643,1.813,1.977,2.128,2.261,2.368,2.446,2.49,2.499,2.472,2.41,2.316,2.193,2.047,1.885,1.713,1.539,1.372,1.217,1.082,0.973,0.895,0.851,0.841,0.868,0.928,1.019,1.136,1.274,1.425,1.583,1.74,1.89,2.026,2.141,1.763,1.803,1.841,1.874,1.897,1.909,1.907,1.888,1.852,1.801,1.734,1.654,1.566,1.473,1.38,1.293,1.216,1.154,1.113,1.094,1.102,1.136,1.197,1.282,1.39,1.516,1.653,1.797,1.94,2.075,2.196,2.296,2.371,2.414,2.425,2.402,2.344,2.254,2.136,1.995,1.836,1.668,1.497,1.331,1.177,1.044,0.936,0.858,0.814,0.804,0.83,0.888,0.976,1.089,1.221,1.365,1.514,1.661,1.799,1.922,2.025,2.103,2.154,2.177,2.173,2.143,2.091,2.022,1.94,1.851,1.762,1.677,1.601,1.538,1.492,1.464,1.454,1.462,1.485,1.521,1.566,1.615,1.665,1.71,1.746,1.771,1.78,1.773,1.748,1.707,1.651,1.582,1.505,1.423,1.342,1.266,1.201,1.151,1.121,1.112,1.128,1.169,1.235,1.323,1.431,1.554,1.687,1.824,1.959,2.086,2.198,2.29,2.358,2.397,2.405,2.382,2.326,2.242,2.131,1.998,1.848,1.688,1.525,1.366,1.216,1.083,0.972,0.888,0.834,0.813,0.824,0.868,0.942,1.043,1.168,1.311,1.466,1.627,1.788,1.944,2.088,2.216,2.323,2.406,2.463,2.493,2.496,2.472,2.424,2.353,2.264,2.159,2.044,1.922,1.797,1.674,1.557,1.449,1.354,1.273,1.209,1.164,1.139,1.133,1.147,1.181,1.232,1.3,1.383,1.478,1.582,1.693,1.808,1.923,2.035,2.141,2.236,2.318,2.384,2.431,2.456,2.459,2.438,2.393,2.324,2.234,2.123,1.996,1.855,1.707,1.554,1.404,1.261,1.131,1.019,0.931,0.868,0.836,0.835,0.866,0.929,1.022,1.141,1.281,1.438,1.605,1.775,1.942,2.097,2.234,2.347,2.432,2.483,2.5,2.48,2.424,2.336,2.218,2.075,1.915,1.743,1.568,1.398,1.24,1.1,0.986,0.902,0.851,0.836,0.857,0.913,1.0,1.114,1.25,1.401,1.56,1.72,1.872,2.011,2.131,1.764,1.803,1.84,1.872,1.895,1.905,1.901,1.881,1.844,1.791,1.724,1.644,1.556,1.464,1.372,1.287,1.212,1.153,1.115,1.1,1.11,1.148,1.211,1.3,1.409,1.536,1.674,1.817,1.959,2.091,2.209,2.305,2.375,2.413,2.418,2.389,2.326,2.232,2.109,1.965,1.804,1.634,1.463,1.299,1.148,1.019,0.916,0.844,0.807,0.805,0.838,0.904,1.0,1.12,1.258,1.407,1.56,1.71,1.85,1.973,2.075,2.151,2.2,2.22,2.213,2.18,2.125,2.053,1.97,1.88,1.791,1.707,1.634,1.575,1.533,1.509,1.504,1.516,1.543,1.582,1.628,1.678,1.726,1.769,1.801,1.819,1.822,1.807,1.773,1.723,1.657,1.579,1.494,1.404,1.317,1.236,1.168,1.116,1.086,1.079,1.098,1.143,1.214,1.308,1.422,1.551,1.69,1.833,1.973,2.103,2.218,2.312,2.379,2.417,2.423,2.395,2.336,2.246,2.13,1.992,1.838,1.674,1.508,1.346,1.196,1.063,0.954,0.873,0.823,0.806,0.822,0.872,0.952,1.059,1.189,1.336,1.495,1.658,1.821,1.976,2.119,2.243,2.346,2.424,2.475,2.498,2.494,2.462,2.406,2.328,2.232,2.121,1.999,1.872,1.743,1.616,1.496,1.385,1.287,1.205,1.139,1.093,1.066,1.059,1.072,1.104,1.154,1.221,1.303,1.397,1.502,1.614,1.73,1.848,1.964,2.074,2.175,2.264,2.338,2.394,2.43,2.443,2.432,2.397,2.339,2.257,2.155,2.034,1.899,1.754,1.603,1.452,1.307,1.174,1.056,0.961,0.891,0.85,0.84,0.863,0.917,1.002,1.115,1.251,1.404,1.569,1.739,1.907,2.065,2.207,2.326,2.417,2.475,2.499,2.486,2.437,2.354,2.24,2.101,1.943,1.772,1.596,1.424,1.262,1.118,0.999,0.909,0.853,0.832,0.848,0.899,0.982,1.094,1.228,1.379,1.538,1.699,1.855,1.997,2.121,1.765,1.804,1.84,1.871,1.892,1.901,1.896,1.875,1.837,1.783,1.715,1.635,1.547,1.455,1.365,1.281,1.209,1.153,1.117,1.105,1.118,1.159,1.225,1.316,1.427,1.555,1.693,1.836,1.976,2.106,2.221,2.313,2.378,2.411,2.411,2.377,2.309,2.21,2.083,1.935,1.773,1.602,1.431,1.269,1.121,0.996,0.899,0.833,0.803,0.808,0.849,0.922,1.025,1.151,1.295,1.449,1.606,1.758,1.899,2.022,2.123,2.197,2.243,2.26,2.249,2.212,2.154,2.079,1.994,1.904,1.815,1.732,1.662,1.606,1.569,1.55,1.549,1.566,1.597,1.639,1.688,1.738,1.786,1.826,1.854,1.867,1.863,1.84,1.799,1.739,1.665,1.579,1.485,1.388,1.295,1.209,1.138,1.085,1.054,1.048,1.07,1.119,1.195,1.295,1.414,1.549,1.694,1.842,1.986,2.12,2.237,2.331,2.398,2.434,2.437,2.406,2.343,2.248,2.128,1.985,1.827,1.66,1.491,1.328,1.177,1.046,0.939,0.86,0.814,0.802,0.824,0.879,0.965,1.077,1.212,1.363,1.524,1.689,1.852,2.006,2.146,2.267,2.365,2.437,2.481,2.497,2.485,2.446,2.382,2.297,2.194,2.077,1.95,1.818,1.686,1.556,1.434,1.322,1.223,1.139,1.074,1.026,0.999,0.991,1.003,1.033,1.082,1.148,1.228,1.321,1.425,1.537,1.654,1.773,1.891,2.005,2.111,2.206,2.288,2.352,2.397,2.42,2.419,2.395,2.346,2.274,2.18,2.067,1.938,1.797,1.649,1.499,1.352,1.216,1.094,0.992,0.915,0.866,0.848,0.862,0.909,0.986,1.092,1.223,1.372,1.535,1.705,1.874,2.034,2.18,2.304,2.401,2.466,2.496,2.49,2.447,2.37,2.261,2.126,1.969,1.799,1.623,1.449,1.284,1.137,1.013,0.918,0.856,0.83,0.84,0.887,0.966,1.075,1.207,1.357,1.517,1.679,1.837,1.983,2.11,1.766,1.804,1.84,1.869,1.89,1.898,1.891,1.868,1.83,1.775,1.706,1.626,1.538,1.448,1.358,1.276,1.206,1.152,1.119,1.11,1.127,1.17,1.239,1.332,1.445,1.573,1.712,1.853,1.992,2.12,2.231,2.319,2.38,2.409,2.404,2.364,2.291,2.188,2.058,1.908,1.743,1.572,1.402,1.241,1.097,0.976,0.884,0.824,0.8,0.813,0.861,0.941,1.051,1.183,1.332,1.49,1.65,1.805,1.946,2.069,2.168,2.24,2.283,2.296,2.281,2.24,2.178,2.1,2.012,1.921,1.832,1.751,1.683,1.631,1.598,1.585,1.59,1.612,1.647,1.693,1.744,1.795,1.842,1.88,1.905,1.913,1.903,1.873,1.824,1.756,1.674,1.579,1.477,1.374,1.275,1.185,1.111,1.056,1.025,1.021,1.045,1.098,1.178,1.283,1.408,1.548,1.698,1.85,1.998,2.134,2.253,2.348,2.414,2.449,2.449,2.415,2.347,2.249,2.124,1.977,1.815,1.646,1.475,1.311,1.16,1.03,0.925,0.851,0.809,0.802,0.829,0.889,0.98,1.097,1.236,1.39,1.553,1.719,1.881,2.033,2.17,2.286,2.379,2.444,2.481,2.489,2.469,2.423,2.352,2.26,2.151,2.029,1.898,1.763,1.628,1.497,1.374,1.261,1.163,1.079,1.014,0.967,0.939,0.931,0.941,0.971,1.018,1.082,1.16,1.251,1.353,1.464,1.58,1.7,1.819,1.936,2.046,2.146,2.234,2.305,2.359,2.391,2.4,2.386,2.348,2.285,2.2,2.095,1.972,1.836,1.691,1.542,1.396,1.257,1.131,1.024,0.941,0.884,0.858,0.864,0.903,0.973,1.073,1.198,1.343,1.503,1.672,1.841,2.004,2.153,2.282,2.384,2.455,2.492,2.492,2.456,2.384,2.28,2.148,1.995,1.826,1.649,1.474,1.306,1.155,1.026,0.927,0.859,0.828,0.834,0.875,0.951,1.057,1.187,1.336,1.496,1.66,1.82,1.969,2.1,1.767,1.804,1.839,1.868,1.887,1.894,1.887,1.863,1.823,1.767,1.698,1.618,1.53,1.44,1.352,1.271,1.203,1.152,1.121,1.115,1.134,1.18,1.252,1.346,1.461,1.59,1.729,1.87,2.006,2.132,2.24,2.325,2.381,2.405,2.396,2.352,2.274,2.167,2.034,1.881,1.715,1.544,1.375,1.216,1.075,0.958,0.871,0.817,0.8,0.819,0.874,0.962,1.077,1.215,1.369,1.531,1.694,1.85,1.992,2.114,2.211,2.28,2.319,2.327,2.307,2.262,2.196,2.115,2.024,1.932,1.843,1.763,1.698,1.65,1.622,1.613,1.624,1.652,1.692,1.742,1.796,1.848,1.895,1.932,1.954,1.958,1.942,1.905,1.849,1.773,1.683,1.58,1.472,1.362,1.257,1.164,1.086,1.03,0.999,0.996,1.023,1.079,1.163,1.273,1.403,1.548,1.702,1.858,2.009,2.148,2.268,2.363,2.428,2.461,2.458,2.421,2.35,2.247,2.118,1.968,1.803,1.631,1.459,1.295,1.145,1.017,0.915,0.844,0.806,0.804,0.836,0.902,0.998,1.119,1.261,1.417,1.582,1.748,1.908,2.057,2.19,2.301,2.387,2.446,2.476,2.476,2.449,2.395,2.317,2.219,2.105,1.979,1.845,1.708,1.572,1.44,1.317,1.206,1.108,1.026,0.962,0.916,0.888,0.88,0.89,0.919,0.964,1.025,1.101,1.189,1.289,1.397,1.512,1.63,1.75,1.868,1.98,2.084,2.177,2.256,2.316,2.357,2.376,2.372,2.343,2.29,2.214,2.117,2.001,1.871,1.73,1.584,1.437,1.297,1.168,1.057,0.967,0.904,0.871,0.869,0.9,0.963,1.056,1.175,1.316,1.474,1.641,1.81,1.975,2.127,2.259,2.367,2.444,2.487,2.493,2.463,2.397,2.297,2.169,2.018,1.851,1.674,1.497,1.328,1.173,1.04,0.936,0.864,0.827,0.828,0.865,0.937,1.04,1.168,1.316,1.476,1.641,1.803,1.955,2.089,1.768,1.805,1.839,1.867,1.885,1.891,1.882,1.858,1.817,1.76,1.691,1.61,1.523,1.433,1.346,1.267,1.201,1.151,1.124,1.12,1.142,1.19,1.264,1.36,1.476,1.606,1.744,1.885,2.02,2.143,2.249,2.33,2.382,2.402,2.388,2.339,2.258,2.147,2.011,1.856,1.689,1.517,1.349,1.193,1.055,0.942,0.86,0.812,0.801,0.827,0.888,0.982,1.104,1.247,1.405,1.571,1.736,1.893,2.034,2.155,2.25,2.315,2.35,2.354,2.329,2.279,2.209,2.123,2.03,1.935,1.846,1.767,1.705,1.661,1.638,1.636,1.653,1.686,1.732,1.786,1.843,1.898,1.945,1.98,2.0,2.0,1.979,1.936,1.873,1.79,1.692,1.583,1.467,1.352,1.242,1.144,1.064,1.007,0.976,0.974,1.003,1.062,1.151,1.264,1.399,1.548,1.707,1.866,2.02,2.16,2.281,2.376,2.44,2.471,2.466,2.425,2.35,2.244,2.111,1.958,1.791,1.617,1.444,1.28,1.131,1.005,0.906,0.839,0.806,0.808,0.846,0.916,1.016,1.142,1.286,1.445,1.609,1.774,1.933,2.079,2.207,2.312,2.392,2.443,2.465,2.458,2.423,2.362,2.279,2.175,2.057,1.927,1.792,1.654,1.518,1.387,1.266,1.156,1.061,0.982,0.92,0.875,0.849,0.841,0.851,0.878,0.921,0.98,1.052,1.137,1.233,1.338,1.45,1.566,1.685,1.802,1.916,2.023,2.12,2.204,2.271,2.32,2.348,2.352,2.333,2.29,2.223,2.134,2.026,1.902,1.765,1.622,1.477,1.336,1.205,1.089,0.995,0.926,0.885,0.876,0.9,0.955,1.042,1.155,1.292,1.446,1.611,1.781,1.946,2.101,2.237,2.349,2.432,2.481,2.493,2.468,2.408,2.313,2.188,2.04,1.874,1.698,1.52,1.349,1.191,1.054,0.945,0.869,0.827,0.823,0.856,0.924,1.024,1.151,1.297,1.458,1.623,1.787,1.941,2.079,1.769,1.806,1.839,1.866,1.884,1.889,1.879,1.853,1.811,1.754,1.684,1.603,1.516,1.427,1.341,1.263,1.198,1.151,1.126,1.124,1.149,1.199,1.275,1.373,1.49,1.621,1.759,1.899,2.032,2.154,2.256,2.334,2.382,2.398,2.38,2.328,2.243,2.128,1.99,1.833,1.665,1.493,1.326,1.172,1.037,0.928,0.851,0.809,0.804,0.836,0.903,1.003,1.13,1.278,1.44,1.609,1.775,1.933,2.074,2.193,2.285,2.347,2.377,2.376,2.346,2.291,2.215,2.125,2.028,1.931,1.841,1.764,1.704,1.665,1.648,1.651,1.675,1.714,1.766,1.825,1.886,1.943,1.991,2.025,2.042,2.039,2.013,1.965,1.895,1.806,1.701,1.585,1.464,1.343,1.228,1.127,1.045,0.986,0.955,0.955,0.986,1.048,1.14,1.257,1.396,1.549,1.711,1.874,2.03,2.172,2.293,2.387,2.45,2.479,2.471,2.427,2.349,2.24,2.104,1.948,1.778,1.603,1.429,1.266,1.119,0.995,0.899,0.836,0.808,0.815,0.857,0.932,1.036,1.165,1.312,1.471,1.636,1.8,1.955,2.097,2.22,2.319,2.392,2.436,2.451,2.436,2.394,2.327,2.237,2.13,2.008,1.876,1.74,1.602,1.467,1.339,1.221,1.115,1.023,0.947,0.888,0.846,0.822,0.815,0.824,0.85,0.891,0.947,1.016,1.096,1.188,1.289,1.396,1.509,1.625,1.741,1.855,1.963,2.063,2.151,2.224,2.28,2.315,2.329,2.319,2.285,2.227,2.147,2.046,1.928,1.797,1.657,1.513,1.373,1.24,1.122,1.023,0.948,0.901,0.885,0.901,0.95,1.03,1.138,1.27,1.421,1.584,1.753,1.919,2.076,2.215,2.332,2.419,2.473,2.492,2.473,2.417,2.327,2.206,2.06,1.896,1.721,1.542,1.369,1.208,1.068,0.955,0.874,0.828,0.819,0.848,0.913,1.01,1.134,1.28,1.44,1.606,1.772,1.928,2.068,1.77,1.806,1.84,1.866,1.882,1.886,1.875,1.849,1.806,1.748,1.677,1.597,1.51,1.421,1.336,1.26,1.196,1.151,1.128,1.128,1.155,1.208,1.285,1.385,1.503,1.634,1.772,1.911,2.044,2.163,2.263,2.337,2.382,2.395,2.373,2.316,2.228,2.111,1.97,1.811,1.642,1.471,1.305,1.153,1.021,0.916,0.844,0.807,0.807,0.845,0.918,1.023,1.155,1.308,1.473,1.644,1.813,1.971,2.111,2.228,2.317,2.375,2.4,2.394,2.358,2.297,2.215,2.121,2.02,1.92,1.829,1.753,1.696,1.662,1.65,1.66,1.691,1.737,1.795,1.859,1.923,1.983,2.032,2.067,2.082,2.076,2.046,1.992,1.917,1.821,1.71,1.588,1.461,1.335,1.216,1.112,1.027,0.968,0.937,0.937,0.971,1.036,1.131,1.252,1.394,1.551,1.716,1.881,2.039,2.182,2.303,2.397,2.459,2.485,2.475,2.428,2.347,2.234,2.095,1.937,1.766,1.589,1.416,1.253,1.108,0.986,0.894,0.835,0.811,0.823,0.87,0.949,1.057,1.188,1.337,1.497,1.661,1.823,1.975,2.112,2.23,2.323,2.388,2.425,2.432,2.411,2.362,2.289,2.194,2.083,1.959,1.826,1.69,1.554,1.422,1.297,1.183,1.082,0.995,0.923,0.868,0.829,0.807,0.802,0.811,0.836,0.875,0.927,0.992,1.068,1.154,1.249,1.352,1.46,1.572,1.685,1.798,1.906,2.007,2.098,2.176,2.238,2.281,2.302,2.301,2.276,2.227,2.155,2.062,1.951,1.825,1.689,1.548,1.407,1.274,1.153,1.05,0.97,0.918,0.895,0.905,0.947,1.021,1.123,1.251,1.398,1.559,1.726,1.893,2.051,2.194,2.314,2.406,2.466,2.489,2.475,2.425,2.339,2.222,2.079,1.916,1.742,1.563,1.388,1.225,1.082,0.965,0.879,0.829,0.816,0.841,0.902,0.996,1.119,1.263,1.423,1.59,1.757,1.915,2.058,1.771,1.807,1.84,1.866,1.881,1.884,1.872,1.845,1.801,1.743,1.671,1.59,1.504,1.416,1.331,1.256,1.194,1.151,1.129,1.132,1.161,1.216,1.295,1.396,1.515,1.647,1.785,1.923,2.054,2.172,2.269,2.34,2.382,2.391,2.365,2.306,2.214,2.094,1.951,1.791,1.621,1.45,1.286,1.135,1.007,0.906,0.838,0.806,0.811,0.855,0.933,1.043,1.18,1.336,1.505,1.678,1.847,2.005,2.144,2.259,2.345,2.399,2.419,2.407,2.365,2.297,2.21,2.11,2.004,1.902,1.81,1.734,1.681,1.651,1.645,1.663,1.701,1.754,1.818,1.888,1.957,2.019,2.07,2.104,2.118,2.109,2.075,2.017,1.937,1.836,1.719,1.591,1.459,1.328,1.206,1.098,1.012,0.951,0.921,0.922,0.958,1.025,1.123,1.247,1.393,1.553,1.721,1.888,2.048,2.192,2.313,2.406,2.466,2.49,2.477,2.428,2.343,2.228,2.086,1.926,1.753,1.576,1.403,1.241,1.098,0.979,0.891,0.836,0.816,0.833,0.884,0.967,1.078,1.212,1.362,1.522,1.685,1.844,1.993,2.125,2.236,2.323,2.381,2.411,2.411,2.382,2.328,2.249,2.151,2.037,1.911,1.779,1.644,1.51,1.382,1.262,1.154,1.058,0.977,0.911,0.86,0.826,0.807,0.802,0.812,0.836,0.872,0.921,0.981,1.051,1.131,1.22,1.317,1.419,1.526,1.636,1.745,1.852,1.954,2.047,2.128,2.195,2.244,2.273,2.279,2.263,2.223,2.159,2.074,1.969,1.849,1.717,1.579,1.44,1.306,1.183,1.077,0.993,0.935,0.907,0.91,0.946,1.013,1.11,1.233,1.377,1.535,1.702,1.869,2.028,2.173,2.297,2.393,2.457,2.486,2.477,2.431,2.35,2.237,2.096,1.936,1.762,1.582,1.406,1.241,1.095,0.975,0.885,0.831,0.814,0.835,0.893,0.984,1.104,1.247,1.407,1.574,1.742,1.903,2.048,1.772,1.808,1.84,1.866,1.881,1.883,1.87,1.841,1.797,1.738,1.666,1.585,1.498,1.411,1.327,1.253,1.192,1.151,1.131,1.136,1.166,1.223,1.304,1.406,1.526,1.658,1.796,1.934,2.064,2.179,2.274,2.343,2.382,2.387,2.359,2.296,2.201,2.079,1.934,1.773,1.603,1.432,1.268,1.12,0.994,0.897,0.833,0.805,0.816,0.864,0.948,1.062,1.203,1.363,1.534,1.709,1.879,2.037,2.175,2.287,2.369,2.418,2.434,2.416,2.368,2.293,2.2,2.093,1.983,1.877,1.783,1.708,1.657,1.633,1.634,1.659,1.705,1.766,1.837,1.912,1.985,2.051,2.103,2.138,2.15,2.139,2.102,2.04,1.955,1.848,1.726,1.594,1.457,1.322,1.196,1.086,0.998,0.937,0.907,0.91,0.946,1.017,1.117,1.245,1.393,1.556,1.726,1.895,2.056,2.2,2.321,2.413,2.472,2.494,2.479,2.426,2.339,2.22,2.077,1.914,1.74,1.563,1.39,1.23,1.089,0.974,0.889,0.838,0.823,0.843,0.899,0.985,1.099,1.235,1.386,1.545,1.707,1.863,2.008,2.135,2.24,2.32,2.372,2.394,2.387,2.352,2.292,2.209,2.107,1.991,1.865,1.734,1.602,1.472,1.349,1.235,1.133,1.044,0.969,0.91,0.865,0.835,0.819,0.817,0.828,0.85,0.884,0.929,0.983,1.048,1.121,1.203,1.292,1.388,1.489,1.593,1.699,1.803,1.904,1.998,2.082,2.152,2.206,2.242,2.256,2.247,2.215,2.159,2.082,1.984,1.87,1.743,1.608,1.47,1.337,1.212,1.104,1.016,0.953,0.919,0.916,0.946,1.008,1.1,1.218,1.358,1.514,1.679,1.846,2.006,2.153,2.28,2.38,2.449,2.482,2.478,2.437,2.359,2.25,2.112,1.953,1.78,1.601,1.424,1.257,1.108,0.984,0.891,0.833,0.812,0.83,0.884,0.973,1.091,1.233,1.392,1.56,1.729,1.891,2.039,1.774,1.809,1.841,1.866,1.88,1.881,1.868,1.838,1.793,1.733,1.661,1.58,1.493,1.406,1.323,1.25,1.191,1.15,1.132,1.138,1.171,1.229,1.311,1.415,1.536,1.668,1.806,1.943,2.072,2.186,2.279,2.346,2.382,2.384,2.352,2.287,2.19,2.065,1.918,1.756,1.585,1.415,1.253,1.106,0.983,0.889,0.829,0.806,0.821,0.873,0.961,1.08,1.225,1.387,1.561,1.737,1.908,2.065,2.201,2.311,2.39,2.434,2.445,2.421,2.366,2.285,2.185,2.072,1.956,1.845,1.749,1.675,1.627,1.608,1.617,1.65,1.704,1.773,1.851,1.932,2.009,2.078,2.132,2.167,2.179,2.166,2.126,2.06,1.97,1.86,1.733,1.596,1.455,1.316,1.188,1.076,0.986,0.925,0.895,0.899,0.937,1.01,1.113,1.243,1.394,1.559,1.731,1.902,2.064,2.208,2.329,2.42,2.477,2.497,2.479,2.423,2.333,2.213,2.067,1.903,1.728,1.551,1.379,1.22,1.082,0.969,0.888,0.841,0.83,0.855,0.914,1.004,1.12,1.257,1.408,1.567,1.727,1.88,2.02,2.143,2.242,2.315,2.36,2.375,2.362,2.321,2.256,2.169,2.065,1.948,1.822,1.693,1.564,1.44,1.322,1.215,1.121,1.039,0.972,0.92,0.881,0.857,0.845,0.845,0.856,0.878,0.909,0.949,0.999,1.056,1.122,1.196,1.277,1.366,1.459,1.557,1.658,1.759,1.858,1.951,2.036,2.11,2.169,2.209,2.23,2.229,2.205,2.157,2.087,1.996,1.887,1.765,1.633,1.498,1.365,1.24,1.129,1.038,0.971,0.932,0.924,0.948,1.004,1.091,1.205,1.341,1.494,1.658,1.824,1.985,2.134,2.264,2.367,2.44,2.477,2.478,2.441,2.368,2.261,2.127,1.969,1.797,1.618,1.44,1.271,1.12,0.994,0.897,0.835,0.811,0.825,0.876,0.962,1.079,1.219,1.378,1.546,1.716,1.88,2.03,1.775,1.811,1.842,1.866,1.88,1.88,1.866,1.836,1.79,1.729,1.657,1.575,1.488,1.401,1.319,1.247,1.189,1.15,1.133,1.141,1.175,1.235,1.318,1.423,1.545,1.678,1.816,1.952,2.08,2.192,2.284,2.348,2.381,2.381,2.347,2.279,2.179,2.053,1.904,1.741,1.57,1.4,1.239,1.094,0.973,0.882,0.826,0.806,0.826,0.882,0.974,1.097,1.244,1.41,1.585,1.763,1.933,2.09,2.224,2.332,2.407,2.447,2.452,2.423,2.362,2.274,2.167,2.047,1.924,1.808,1.709,1.634,1.59,1.578,1.595,1.637,1.699,1.776,1.861,1.947,2.03,2.102,2.158,2.193,2.204,2.189,2.147,2.078,1.984,1.87,1.739,1.597,1.452,1.311,1.18,1.066,0.976,0.914,0.884,0.889,0.93,1.004,1.11,1.242,1.396,1.563,1.737,1.909,2.071,2.216,2.336,2.426,2.481,2.498,2.478,2.42,2.327,2.204,2.057,1.892,1.716,1.539,1.368,1.211,1.075,0.966,0.888,0.845,0.838,0.866,0.929,1.022,1.14,1.279,1.43,1.588,1.746,1.895,2.031,2.148,2.242,2.308,2.346,2.355,2.336,2.29,2.22,2.13,2.024,1.907,1.783,1.656,1.532,1.413,1.303,1.204,1.117,1.044,0.985,0.94,0.909,0.89,0.882,0.885,0.897,0.918,0.946,0.983,1.026,1.077,1.135,1.2,1.273,1.352,1.438,1.529,1.624,1.72,1.816,1.908,1.994,2.069,2.131,2.177,2.204,2.209,2.192,2.152,2.088,2.004,1.902,1.784,1.656,1.524,1.391,1.266,1.153,1.059,0.988,0.945,0.932,0.951,1.002,1.084,1.193,1.326,1.477,1.638,1.804,1.966,2.117,2.248,2.355,2.431,2.473,2.477,2.444,2.375,2.272,2.139,1.984,1.813,1.634,1.455,1.285,1.132,1.003,0.903,0.838,0.81,0.821,0.87,0.953,1.067,1.207,1.365,1.533,1.704,1.869,2.021,1.777,1.812,1.843,1.867,1.88,1.88,1.865,1.834,1.787,1.726,1.653,1.571,1.484,1.397,1.315,1.244,1.187,1.149,1.133,1.143,1.178,1.239,1.324,1.43,1.553,1.686,1.824,1.96,2.087,2.198,2.288,2.35,2.381,2.379,2.342,2.271,2.17,2.041,1.892,1.728,1.557,1.387,1.227,1.084,0.965,0.877,0.823,0.807,0.83,0.89,0.986,1.112,1.262,1.43,1.607,1.785,1.956,2.111,2.244,2.349,2.421,2.457,2.457,2.422,2.355,2.261,2.146,2.019,1.889,1.766,1.663,1.588,1.548,1.543,1.569,1.62,1.691,1.776,1.868,1.96,2.046,2.121,2.179,2.215,2.226,2.209,2.165,2.093,1.996,1.878,1.743,1.598,1.45,1.306,1.173,1.057,0.966,0.904,0.875,0.882,0.924,1.0,1.108,1.243,1.398,1.568,1.743,1.916,2.079,2.223,2.342,2.43,2.484,2.499,2.476,2.416,2.321,2.196,2.047,1.88,1.705,1.528,1.358,1.203,1.069,0.963,0.889,0.849,0.846,0.878,0.944,1.04,1.16,1.299,1.451,1.608,1.762,1.909,2.04,2.152,2.239,2.3,2.332,2.334,2.309,2.259,2.185,2.092,1.986,1.869,1.747,1.624,1.505,1.393,1.29,1.199,1.121,1.058,1.008,0.971,0.947,0.934,0.93,0.936,0.949,0.969,0.995,1.027,1.064,1.108,1.158,1.214,1.278,1.348,1.425,1.508,1.596,1.687,1.779,1.869,1.954,2.03,2.095,2.145,2.177,2.188,2.178,2.144,2.088,2.01,1.913,1.801,1.677,1.546,1.416,1.29,1.176,1.08,1.006,0.958,0.941,0.955,1.001,1.078,1.183,1.313,1.461,1.621,1.786,1.948,2.1,2.234,2.343,2.422,2.468,2.476,2.447,2.381,2.281,2.151,1.998,1.828,1.649,1.469,1.298,1.143,1.011,0.909,0.841,0.81,0.818,0.863,0.945,1.057,1.196,1.353,1.521,1.693,1.86,2.013,1.779,1.814,1.845,1.868,1.881,1.88,1.864,1.832,1.785,1.723,1.649,1.567,1.48,1.393,1.312,1.241,1.184,1.148,1.133,1.144,1.181,1.243,1.33,1.436,1.559,1.693,1.831,1.967,2.093,2.203,2.291,2.352,2.381,2.377,2.338,2.265,2.162,2.032,1.881,1.716,1.545,1.375,1.216,1.075,0.958,0.872,0.821,0.808,0.834,0.898,0.996,1.125,1.277,1.447,1.625,1.804,1.975,2.129,2.261,2.363,2.432,2.464,2.46,2.42,2.347,2.246,2.125,1.99,1.852,1.722,1.613,1.537,1.501,1.504,1.54,1.602,1.682,1.774,1.872,1.97,2.06,2.138,2.197,2.234,2.244,2.226,2.18,2.105,2.005,1.884,1.746,1.598,1.447,1.301,1.166,1.05,0.958,0.896,0.868,0.876,0.919,0.998,1.108,1.244,1.402,1.573,1.749,1.923,2.086,2.23,2.348,2.435,2.486,2.499,2.474,2.411,2.314,2.187,2.037,1.869,1.693,1.517,1.348,1.195,1.064,0.961,0.89,0.854,0.854,0.89,0.959,1.057,1.179,1.319,1.47,1.625,1.778,1.921,2.048,2.154,2.236,2.29,2.316,2.313,2.283,2.228,2.151,2.057,1.949,1.834,1.715,1.596,1.483,1.378,1.283,1.201,1.133,1.079,1.038,1.01,0.993,0.986,0.988,0.996,1.011,1.03,1.053,1.08,1.112,1.148,1.189,1.237,1.291,1.352,1.42,1.494,1.575,1.66,1.747,1.834,1.917,1.994,2.061,2.114,2.15,2.167,2.162,2.135,2.085,2.014,1.922,1.815,1.694,1.567,1.438,1.313,1.198,1.099,1.022,0.971,0.949,0.959,1.001,1.074,1.175,1.301,1.447,1.605,1.769,1.931,2.084,2.22,2.332,2.414,2.463,2.474,2.449,2.386,2.289,2.161,2.01,1.841,1.662,1.483,1.31,1.153,1.019,0.914,0.843,0.81,0.815,0.858,0.937,1.048,1.185,1.342,1.511,1.683,1.851,2.006,1.78,1.816,1.847,1.869,1.882,1.88,1.864,1.831,1.783,1.721,1.646,1.564,1.476,1.39,1.308,1.238,1.182,1.146,1.133,1.145,1.183,1.247,1.334,1.442,1.565,1.699,1.838,1.973,2.099,2.208,2.295,2.354,2.381,2.375,2.335,2.26,2.155,2.024,1.872,1.706,1.535,1.366,1.207,1.067,0.952,0.868,0.82,0.809,0.838,0.904,1.005,1.136,1.291,1.462,1.641,1.82,1.991,2.144,2.274,2.374,2.44,2.469,2.461,2.416,2.338,2.232,2.104,1.962,1.816,1.677,1.56,1.481,1.451,1.465,1.513,1.584,1.673,1.772,1.876,1.978,2.072,2.151,2.212,2.249,2.259,2.24,2.191,2.114,2.012,1.888,1.747,1.597,1.444,1.296,1.159,1.042,0.951,0.889,0.862,0.871,0.916,0.996,1.108,1.247,1.406,1.578,1.756,1.93,2.092,2.236,2.353,2.438,2.488,2.499,2.472,2.407,2.307,2.179,2.027,1.859,1.682,1.506,1.339,1.187,1.059,0.959,0.891,0.859,0.863,0.902,0.973,1.073,1.197,1.337,1.488,1.642,1.792,1.931,2.054,2.155,2.232,2.28,2.301,2.293,2.258,2.199,2.119,2.024,1.916,1.802,1.687,1.573,1.466,1.368,1.282,1.209,1.151,1.106,1.074,1.055,1.046,1.046,1.052,1.064,1.079,1.098,1.118,1.141,1.167,1.196,1.229,1.267,1.311,1.362,1.421,1.487,1.559,1.638,1.719,1.803,1.884,1.96,2.028,2.084,2.124,2.145,2.146,2.125,2.081,2.015,1.929,1.826,1.71,1.585,1.457,1.333,1.218,1.118,1.038,0.984,0.958,0.964,1.002,1.071,1.168,1.291,1.434,1.591,1.754,1.916,2.07,2.207,2.321,2.406,2.457,2.472,2.45,2.39,2.296,2.171,2.021,1.853,1.674,1.494,1.321,1.163,1.027,0.919,0.846,0.81,0.812,0.853,0.93,1.04,1.176,1.332,1.501,1.674,1.842,1.999,1.782,1.818,1.849,1.871,1.883,1.881,1.864,1.83,1.782,1.719,1.644,1.561,1.473,1.386,1.305,1.235,1.18,1.145,1.132,1.145,1.184,1.249,1.337,1.446,1.57,1.705,1.843,1.978,2.104,2.212,2.298,2.356,2.382,2.374,2.332,2.256,2.15,2.017,1.865,1.698,1.527,1.358,1.2,1.061,0.947,0.865,0.818,0.81,0.841,0.909,1.012,1.145,1.301,1.473,1.654,1.833,2.003,2.156,2.284,2.382,2.446,2.472,2.46,2.412,2.33,2.219,2.086,1.938,1.783,1.634,1.506,1.422,1.401,1.429,1.488,1.569,1.665,1.77,1.879,1.984,2.081,2.162,2.224,2.261,2.27,2.25,2.2,2.121,2.016,1.89,1.747,1.595,1.44,1.29,1.153,1.036,0.944,0.883,0.857,0.867,0.914,0.996,1.11,1.25,1.411,1.584,1.762,1.937,2.099,2.242,2.358,2.442,2.489,2.499,2.469,2.402,2.3,2.17,2.017,1.848,1.672,1.497,1.33,1.181,1.054,0.957,0.893,0.864,0.871,0.912,0.987,1.089,1.213,1.354,1.504,1.657,1.804,1.94,2.059,2.156,2.227,2.27,2.285,2.272,2.233,2.171,2.09,1.993,1.886,1.775,1.662,1.554,1.453,1.363,1.286,1.222,1.173,1.138,1.116,1.105,1.104,1.11,1.121,1.136,1.153,1.171,1.189,1.208,1.227,1.249,1.273,1.302,1.337,1.378,1.427,1.484,1.549,1.62,1.697,1.776,1.855,1.93,1.998,2.055,2.099,2.124,2.13,2.114,2.075,2.015,1.934,1.835,1.723,1.601,1.475,1.351,1.236,1.135,1.053,0.996,0.967,0.97,1.003,1.069,1.163,1.283,1.424,1.578,1.741,1.903,2.057,2.195,2.311,2.398,2.452,2.47,2.451,2.394,2.302,2.179,2.03,1.863,1.685,1.505,1.331,1.171,1.034,0.924,0.849,0.81,0.81,0.849,0.925,1.033,1.168,1.323,1.492,1.665,1.835,1.993,1.785,1.82,1.851,1.873,1.884,1.882,1.864,1.83,1.781,1.717,1.642,1.558,1.47,1.383,1.302,1.232,1.177,1.143,1.131,1.145,1.185,1.25,1.339,1.449,1.574,1.709,1.848,1.983,2.108,2.216,2.301,2.358,2.383,2.374,2.331,2.254,2.146,2.012,1.859,1.692,1.52,1.351,1.194,1.055,0.943,0.862,0.817,0.811,0.843,0.913,1.018,1.152,1.309,1.482,1.663,1.842,2.012,2.164,2.291,2.388,2.449,2.473,2.459,2.408,2.323,2.209,2.072,1.919,1.758,1.6,1.456,1.361,1.355,1.4,1.47,1.558,1.66,1.77,1.882,1.99,2.088,2.171,2.233,2.27,2.278,2.257,2.205,2.125,2.018,1.89,1.745,1.592,1.436,1.285,1.147,1.03,0.938,0.878,0.853,0.865,0.913,0.997,1.112,1.254,1.416,1.59,1.769,1.944,2.106,2.248,2.363,2.445,2.491,2.498,2.466,2.397,2.294,2.162,2.007,1.838,1.662,1.487,1.322,1.174,1.05,0.956,0.894,0.868,0.878,0.923,0.999,1.103,1.229,1.37,1.519,1.67,1.815,1.948,2.063,2.155,2.222,2.26,2.271,2.253,2.211,2.146,2.062,1.965,1.86,1.75,1.642,1.538,1.444,1.362,1.293,1.239,1.199,1.174,1.161,1.159,1.165,1.177,1.193,1.211,1.229,1.247,1.263,1.277,1.291,1.306,1.322,1.342,1.367,1.399,1.439,1.487,1.544,1.608,1.678,1.753,1.829,1.902,1.971,2.029,2.075,2.104,2.114,2.102,2.069,2.013,1.937,1.843,1.734,1.615,1.491,1.368,1.252,1.15,1.067,1.008,0.976,0.975,1.006,1.067,1.159,1.276,1.414,1.568,1.729,1.891,2.045,2.184,2.302,2.391,2.448,2.468,2.451,2.396,2.306,2.185,2.038,1.872,1.695,1.515,1.34,1.179,1.04,0.929,0.851,0.81,0.809,0.846,0.919,1.026,1.16,1.316,1.484,1.658,1.828,1.988,1.787,1.823,1.853,1.875,1.886,1.883,1.865,1.831,1.78,1.716,1.64,1.556,1.468,1.38,1.299,1.229,1.175,1.141,1.13,1.144,1.185,1.251,1.341,1.451,1.577,1.712,1.851,1.987,2.111,2.219,2.304,2.36,2.384,2.374,2.33,2.252,2.144,2.009,1.855,1.688,1.516,1.347,1.19,1.052,0.94,0.86,0.816,0.811,0.844,0.916,1.021,1.156,1.315,1.488,1.669,1.848,2.018,2.169,2.296,2.391,2.451,2.474,2.458,2.405,2.318,2.202,2.063,1.908,1.745,1.581,1.425,1.299,1.328,1.385,1.462,1.555,1.66,1.772,1.886,1.995,2.094,2.177,2.239,2.276,2.283,2.261,2.208,2.126,2.018,1.888,1.742,1.587,1.43,1.279,1.141,1.024,0.933,0.874,0.85,0.863,0.914,0.999,1.116,1.259,1.422,1.597,1.776,1.951,2.113,2.254,2.367,2.448,2.492,2.497,2.463,2.392,2.287,2.153,1.998,1.828,1.652,1.478,1.314,1.168,1.046,0.954,0.895,0.872,0.885,0.932,1.011,1.116,1.243,1.384,1.533,1.682,1.825,1.955,2.066,2.155,2.217,2.251,2.257,2.236,2.19,2.123,2.038,1.941,1.836,1.729,1.624,1.526,1.439,1.363,1.303,1.258,1.227,1.211,1.207,1.213,1.226,1.245,1.265,1.286,1.306,1.323,1.337,1.348,1.356,1.364,1.373,1.384,1.4,1.423,1.454,1.493,1.542,1.599,1.664,1.734,1.806,1.878,1.946,2.005,2.053,2.085,2.098,2.091,2.062,2.011,1.939,1.848,1.743,1.626,1.504,1.382,1.267,1.164,1.08,1.018,0.984,0.98,1.008,1.067,1.156,1.27,1.407,1.558,1.719,1.88,2.035,2.175,2.294,2.385,2.443,2.466,2.451,2.398,2.31,2.191,2.045,1.88,1.703,1.523,1.347,1.186,1.045,0.933,0.853,0.811,0.807,0.843,0.915,1.021,1.154,1.309,1.477,1.651,1.823,1.983,1.79,1.825,1.856,1.878,1.889,1.885,1.866,1.831,1.781,1.716,1.639,1.554,1.465,1.378,1.296,1.226,1.172,1.138,1.128,1.142,1.184,1.251,1.341,1.452,1.578,1.714,1.854,1.989,2.114,2.222,2.306,2.362,2.386,2.376,2.33,2.252,2.142,2.007,1.853,1.685,1.513,1.344,1.187,1.049,0.938,0.858,0.815,0.81,0.845,0.917,1.023,1.159,1.317,1.491,1.672,1.851,2.02,2.171,2.297,2.391,2.451,2.472,2.456,2.403,2.316,2.2,2.061,1.906,1.744,1.583,1.434,1.33,1.337,1.391,1.466,1.559,1.664,1.776,1.89,2.0,2.099,2.182,2.243,2.279,2.285,2.262,2.207,2.124,2.015,1.884,1.737,1.581,1.424,1.273,1.136,1.019,0.929,0.871,0.849,0.863,0.915,1.002,1.12,1.264,1.428,1.604,1.784,1.958,2.119,2.259,2.372,2.451,2.493,2.496,2.46,2.387,2.28,2.146,1.989,1.819,1.643,1.469,1.306,1.162,1.042,0.952,0.896,0.876,0.891,0.941,1.021,1.128,1.256,1.397,1.546,1.694,1.834,1.961,2.069,2.154,2.212,2.243,2.245,2.22,2.172,2.102,2.016,1.919,1.816,1.711,1.61,1.517,1.435,1.367,1.315,1.277,1.256,1.248,1.252,1.266,1.286,1.31,1.335,1.359,1.38,1.397,1.409,1.416,1.42,1.422,1.423,1.427,1.435,1.449,1.471,1.502,1.543,1.594,1.653,1.718,1.787,1.857,1.924,1.984,2.033,2.067,2.083,2.08,2.055,2.008,1.939,1.852,1.75,1.636,1.516,1.395,1.28,1.177,1.091,1.028,0.992,0.986,1.011,1.067,1.153,1.266,1.4,1.551,1.71,1.871,2.026,2.166,2.286,2.379,2.439,2.463,2.45,2.4,2.314,2.196,2.051,1.887,1.71,1.53,1.354,1.191,1.05,0.936,0.855,0.811,0.806,0.84,0.911,1.016,1.149,1.303,1.472,1.646,1.818,1.979,1.792,1.828,1.859,1.881,1.891,1.888,1.868,1.833,1.781,1.715,1.638,1.553,1.464,1.376,1.294,1.223,1.169,1.135,1.125,1.14,1.182,1.25,1.341,1.452,1.579,1.716,1.855,1.992,2.117,2.225,2.309,2.365,2.388,2.377,2.332,2.252,2.143,2.007,1.852,1.684,1.511,1.342,1.185,1.047,0.936,0.857,0.814,0.81,0.845,0.917,1.023,1.159,1.318,1.491,1.672,1.851,2.019,2.17,2.295,2.389,2.448,2.47,2.454,2.401,2.315,2.2,2.064,1.913,1.756,1.604,1.471,1.387,1.375,1.413,1.482,1.57,1.673,1.783,1.896,2.004,2.102,2.184,2.244,2.279,2.284,2.259,2.204,2.12,2.009,1.878,1.731,1.575,1.417,1.267,1.13,1.014,0.925,0.869,0.848,0.864,0.917,1.005,1.125,1.271,1.436,1.612,1.792,1.966,2.126,2.265,2.376,2.453,2.493,2.495,2.457,2.382,2.274,2.138,1.981,1.81,1.634,1.461,1.299,1.156,1.038,0.951,0.897,0.879,0.896,0.948,1.03,1.139,1.267,1.409,1.557,1.704,1.843,1.967,2.072,2.154,2.209,2.235,2.234,2.207,2.156,2.084,1.998,1.9,1.798,1.696,1.599,1.51,1.434,1.372,1.327,1.297,1.283,1.283,1.295,1.315,1.342,1.371,1.4,1.427,1.449,1.466,1.476,1.48,1.48,1.476,1.471,1.468,1.468,1.474,1.489,1.513,1.547,1.591,1.645,1.706,1.772,1.839,1.905,1.965,2.015,2.051,2.07,2.069,2.048,2.004,1.939,1.855,1.755,1.644,1.525,1.405,1.291,1.187,1.101,1.037,0.999,0.991,1.014,1.068,1.152,1.263,1.395,1.544,1.703,1.863,2.018,2.159,2.28,2.374,2.435,2.461,2.45,2.401,2.316,2.199,2.056,1.892,1.716,1.535,1.359,1.196,1.054,0.939,0.857,0.812,0.805,0.838,0.908,1.012,1.144,1.299,1.467,1.642,1.814,1.976,1.795,1.831,1.862,1.884,1.894,1.89,1.87,1.834,1.782,1.716,1.638,1.552,1.462,1.373,1.291,1.22,1.166,1.132,1.122,1.137,1.18,1.248,1.339,1.451,1.579,1.716,1.856,1.993,2.118,2.227,2.311,2.367,2.39,2.38,2.334,2.254,2.144,2.009,1.853,1.685,1.512,1.343,1.185,1.047,0.936,0.857,0.814,0.809,0.843,0.915,1.022,1.157,1.315,1.488,1.669,1.847,2.015,2.165,2.29,2.385,2.444,2.466,2.451,2.4,2.316,2.204,2.072,1.926,1.777,1.636,1.518,1.442,1.421,1.447,1.506,1.588,1.685,1.792,1.902,2.008,2.104,2.184,2.243,2.276,2.28,2.254,2.198,2.113,2.002,1.87,1.723,1.567,1.41,1.26,1.124,1.009,0.922,0.867,0.848,0.865,0.92,1.01,1.131,1.278,1.443,1.62,1.799,1.973,2.133,2.271,2.38,2.456,2.494,2.494,2.454,2.377,2.268,2.131,1.973,1.801,1.625,1.453,1.292,1.15,1.034,0.948,0.897,0.881,0.901,0.954,1.038,1.148,1.277,1.419,1.566,1.712,1.85,1.973,2.075,2.154,2.206,2.23,2.226,2.196,2.142,2.069,1.982,1.885,1.784,1.684,1.589,1.505,1.433,1.377,1.338,1.315,1.308,1.315,1.333,1.36,1.392,1.426,1.459,1.488,1.511,1.528,1.537,1.539,1.534,1.526,1.516,1.506,1.499,1.499,1.506,1.524,1.551,1.59,1.639,1.696,1.759,1.825,1.889,1.949,2.0,2.037,2.058,2.06,2.041,2.0,1.938,1.857,1.759,1.65,1.533,1.414,1.3,1.197,1.11,1.044,1.005,0.996,1.017,1.069,1.151,1.26,1.392,1.54,1.697,1.857,2.012,2.154,2.275,2.369,2.432,2.459,2.449,2.401,2.318,2.202,2.059,1.896,1.72,1.54,1.364,1.2,1.057,0.941,0.858,0.812,0.805,0.837,0.906,1.009,1.141,1.295,1.463,1.638,1.811,1.974,1.798,1.834,1.866,1.888,1.898,1.893,1.873,1.837,1.784,1.717,1.638,1.551,1.461,1.372,1.289,1.218,1.163,1.129,1.118,1.134,1.176,1.245,1.337,1.449,1.577,1.715,1.856,1.993,2.12,2.228,2.313,2.369,2.393,2.383,2.337,2.258,2.148,2.012,1.856,1.688,1.514,1.345,1.187,1.048,0.936,0.857,0.813,0.808,0.841,0.913,1.018,1.153,1.31,1.483,1.662,1.84,2.008,2.158,2.283,2.377,2.437,2.461,2.447,2.398,2.317,2.21,2.083,1.944,1.803,1.672,1.565,1.494,1.468,1.484,1.534,1.608,1.7,1.802,1.908,2.011,2.104,2.182,2.238,2.27,2.273,2.246,2.189,2.103,1.992,1.86,1.713,1.558,1.402,1.253,1.118,1.005,0.92,0.866,0.849,0.868,0.924,1.016,1.138,1.285,1.451,1.628,1.808,1.981,2.14,2.276,2.384,2.458,2.495,2.493,2.451,2.373,2.262,2.124,1.965,1.793,1.617,1.445,1.285,1.144,1.03,0.946,0.896,0.882,0.904,0.959,1.045,1.155,1.285,1.428,1.575,1.72,1.857,1.978,2.079,2.155,2.204,2.225,2.219,2.187,2.132,2.058,1.969,1.873,1.772,1.674,1.582,1.501,1.433,1.382,1.348,1.331,1.329,1.342,1.366,1.398,1.435,1.473,1.509,1.54,1.564,1.581,1.589,1.589,1.582,1.569,1.554,1.539,1.527,1.521,1.523,1.534,1.557,1.591,1.635,1.689,1.749,1.813,1.876,1.936,1.987,2.025,2.048,2.051,2.034,1.996,1.936,1.858,1.762,1.654,1.539,1.421,1.307,1.204,1.117,1.051,1.011,1.0,1.02,1.071,1.151,1.259,1.389,1.536,1.693,1.853,2.007,2.149,2.271,2.366,2.429,2.457,2.448,2.401,2.319,2.204,2.062,1.899,1.723,1.543,1.367,1.203,1.059,0.943,0.859,0.812,0.804,0.835,0.904,1.007,1.138,1.292,1.461,1.636,1.809,1.972,1.801,1.838,1.869,1.891,1.902,1.897,1.877,1.839,1.786,1.718,1.639,1.551,1.46,1.37,1.287,1.215,1.16,1.125,1.114,1.13,1.172,1.241,1.333,1.446,1.575,1.713,1.855,1.993,2.12,2.229,2.315,2.372,2.396,2.386,2.341,2.262,2.152,2.016,1.861,1.692,1.518,1.348,1.19,1.051,0.938,0.857,0.813,0.806,0.839,0.909,1.013,1.147,1.303,1.474,1.653,1.83,1.997,2.147,2.272,2.367,2.428,2.453,2.442,2.396,2.319,2.217,2.095,1.964,1.832,1.71,1.61,1.543,1.514,1.523,1.564,1.63,1.715,1.812,1.913,2.012,2.102,2.177,2.231,2.261,2.262,2.234,2.177,2.091,1.98,1.848,1.702,1.548,1.394,1.246,1.113,1.002,0.918,0.866,0.851,0.872,0.93,1.022,1.145,1.293,1.46,1.637,1.816,1.989,2.146,2.282,2.388,2.461,2.496,2.492,2.449,2.369,2.257,2.117,1.958,1.786,1.609,1.438,1.278,1.139,1.025,0.943,0.895,0.883,0.906,0.963,1.05,1.162,1.292,1.435,1.583,1.728,1.863,1.983,2.082,2.157,2.204,2.223,2.215,2.181,2.124,2.049,1.96,1.863,1.763,1.666,1.576,1.497,1.433,1.385,1.355,1.342,1.346,1.363,1.391,1.427,1.468,1.509,1.548,1.581,1.607,1.623,1.631,1.629,1.62,1.604,1.586,1.567,1.551,1.54,1.537,1.544,1.562,1.592,1.633,1.684,1.742,1.804,1.866,1.925,1.976,2.015,2.039,2.044,2.029,1.992,1.934,1.857,1.764,1.657,1.543,1.426,1.313,1.21,1.122,1.056,1.015,1.004,1.022,1.072,1.152,1.259,1.388,1.534,1.691,1.85,2.004,2.146,2.268,2.363,2.427,2.456,2.447,2.401,2.319,2.205,2.063,1.901,1.725,1.545,1.368,1.204,1.06,0.943,0.859,0.812,0.804,0.835,0.903,1.005,1.137,1.291,1.459,1.635,1.808,1.971,1.804,1.842,1.873,1.896,1.906,1.901,1.88,1.843,1.789,1.721,1.64,1.552,1.46,1.369,1.285,1.212,1.156,1.121,1.11,1.125,1.167,1.236,1.329,1.442,1.571,1.71,1.853,1.992,2.12,2.23,2.317,2.374,2.4,2.39,2.346,2.268,2.158,2.023,1.867,1.698,1.524,1.354,1.195,1.055,0.941,0.859,0.813,0.805,0.836,0.904,1.007,1.138,1.293,1.463,1.64,1.816,1.983,2.133,2.258,2.354,2.416,2.443,2.435,2.393,2.32,2.223,2.108,1.983,1.859,1.745,1.651,1.586,1.555,1.558,1.592,1.651,1.73,1.82,1.916,2.01,2.096,2.168,2.22,2.248,2.248,2.22,2.162,2.076,1.966,1.835,1.69,1.538,1.385,1.239,1.108,0.999,0.917,0.868,0.854,0.876,0.936,1.029,1.153,1.302,1.469,1.646,1.824,1.996,2.153,2.287,2.392,2.463,2.497,2.491,2.446,2.365,2.251,2.111,1.951,1.778,1.602,1.43,1.272,1.133,1.021,0.939,0.893,0.882,0.907,0.965,1.054,1.167,1.298,1.441,1.589,1.734,1.869,1.988,2.086,2.159,2.205,2.223,2.213,2.177,2.119,2.043,1.954,1.856,1.757,1.66,1.571,1.494,1.432,1.387,1.359,1.35,1.356,1.377,1.408,1.448,1.491,1.535,1.575,1.61,1.636,1.654,1.661,1.658,1.647,1.63,1.609,1.587,1.568,1.554,1.548,1.551,1.567,1.594,1.632,1.681,1.737,1.797,1.859,1.917,1.968,2.008,2.032,2.038,2.024,1.989,1.932,1.856,1.764,1.658,1.545,1.429,1.317,1.214,1.126,1.06,1.019,1.007,1.025,1.074,1.153,1.259,1.388,1.534,1.69,1.848,2.002,2.144,2.266,2.361,2.426,2.454,2.446,2.4,2.319,2.205,2.063,1.901,1.726,1.545,1.369,1.205,1.061,0.944,0.86,0.812,0.803,0.834,0.902,1.005,1.136,1.29,1.459,1.634,1.808,1.972,1.807,1.845,1.877,1.9,1.91,1.906,1.885,1.847,1.792,1.723,1.642,1.553,1.46,1.368,1.283,1.209,1.153,1.117,1.105,1.12,1.162,1.23,1.323,1.437,1.567,1.706,1.85,1.989,2.118,2.23,2.318,2.377,2.403,2.395,2.352,2.274,2.166,2.03,1.875,1.706,1.532,1.361,1.201,1.06,0.945,0.861,0.813,0.803,0.832,0.898,0.999,1.128,1.281,1.449,1.625,1.8,1.966,2.115,2.241,2.338,2.402,2.431,2.426,2.387,2.319,2.228,2.119,2.001,1.884,1.776,1.687,1.624,1.591,1.589,1.617,1.669,1.741,1.825,1.916,2.006,2.088,2.157,2.206,2.232,2.231,2.202,2.144,2.059,1.95,1.82,1.677,1.526,1.376,1.232,1.104,0.997,0.917,0.87,0.858,0.882,0.943,1.038,1.162,1.312,1.478,1.655,1.833,2.004,2.16,2.293,2.396,2.466,2.497,2.49,2.444,2.361,2.247,2.105,1.944,1.771,1.595,1.423,1.265,1.127,1.016,0.935,0.89,0.881,0.907,0.966,1.056,1.17,1.302,1.446,1.594,1.739,1.874,1.993,2.09,2.163,2.208,2.224,2.213,2.177,2.118,2.04,1.95,1.852,1.753,1.656,1.567,1.491,1.43,1.386,1.36,1.352,1.36,1.383,1.416,1.458,1.503,1.548,1.59,1.626,1.653,1.671,1.678,1.675,1.664,1.646,1.623,1.6,1.579,1.563,1.555,1.557,1.57,1.595,1.632,1.679,1.734,1.794,1.855,1.912,1.963,2.003,2.027,2.033,2.02,1.985,1.93,1.855,1.763,1.658,1.546,1.43,1.318,1.216,1.129,1.063,1.022,1.009,1.027,1.076,1.155,1.261,1.389,1.534,1.69,1.848,2.002,2.143,2.265,2.36,2.425,2.453,2.445,2.399,2.318,2.204,2.062,1.9,1.725,1.545,1.368,1.204,1.06,0.943,0.859,0.812,0.803,0.834,0.902,1.005,1.137,1.291,1.459,1.635,1.809,1.973,1.811,1.849,1.882,1.905,1.915,1.911,1.889,1.851,1.796,1.726,1.645,1.554,1.46,1.367,1.281,1.207,1.149,1.112,1.1,1.114,1.156,1.224,1.317,1.431,1.561,1.701,1.845,1.986,2.117,2.229,2.319,2.379,2.407,2.401,2.358,2.282,2.174,2.04,1.885,1.716,1.542,1.37,1.209,1.066,0.95,0.864,0.814,0.802,0.828,0.892,0.989,1.117,1.267,1.433,1.607,1.781,1.946,2.095,2.22,2.318,2.384,2.416,2.414,2.379,2.316,2.23,2.127,2.016,1.905,1.802,1.717,1.655,1.62,1.615,1.637,1.683,1.749,1.827,1.912,1.997,2.076,2.141,2.188,2.213,2.211,2.181,2.124,2.04,1.932,1.804,1.663,1.515,1.367,1.226,1.1,0.995,0.918,0.873,0.863,0.889,0.951,1.047,1.172,1.322,1.488,1.665,1.842,2.012,2.167,2.298,2.4,2.468,2.498,2.489,2.442,2.358,2.242,2.1,1.938,1.765,1.588,1.417,1.259,1.121,1.01,0.931,0.887,0.878,0.906,0.966,1.057,1.172,1.305,1.45,1.599,1.744,1.879,1.998,2.095,2.167,2.212,2.228,2.216,2.179,2.119,2.041,1.95,1.851,1.751,1.653,1.564,1.488,1.426,1.382,1.357,1.349,1.358,1.381,1.415,1.457,1.503,1.549,1.592,1.628,1.656,1.674,1.682,1.68,1.668,1.65,1.628,1.605,1.584,1.567,1.559,1.56,1.572,1.597,1.633,1.679,1.733,1.793,1.853,1.91,1.961,2.0,2.024,2.03,2.017,1.982,1.927,1.852,1.761,1.657,1.545,1.43,1.318,1.217,1.13,1.064,1.024,1.011,1.03,1.079,1.158,1.263,1.391,1.536,1.692,1.85,2.003,2.144,2.265,2.36,2.424,2.453,2.444,2.398,2.316,2.202,2.06,1.898,1.723,1.543,1.367,1.203,1.059,0.942,0.858,0.811,0.803,0.834,0.903,1.006,1.138,1.292,1.461,1.637,1.811,1.974,1.814,1.853,1.886,1.91,1.92,1.916,1.895,1.856,1.801,1.73,1.648,1.556,1.461,1.367,1.28,1.204,1.145,1.107,1.094,1.108,1.149,1.216,1.309,1.423,1.554,1.695,1.84,1.982,2.114,2.228,2.319,2.382,2.411,2.406,2.366,2.291,2.184,2.051,1.896,1.728,1.553,1.381,1.219,1.075,0.956,0.868,0.816,0.801,0.824,0.885,0.979,1.104,1.251,1.415,1.587,1.759,1.922,2.071,2.197,2.295,2.363,2.397,2.398,2.368,2.309,2.228,2.131,2.026,1.92,1.822,1.739,1.678,1.643,1.634,1.651,1.692,1.752,1.824,1.904,1.985,2.059,2.122,2.167,2.189,2.187,2.158,2.101,2.018,1.912,1.787,1.648,1.503,1.358,1.22,1.097,0.995,0.921,0.878,0.869,0.897,0.96,1.057,1.183,1.332,1.499,1.674,1.851,2.02,2.173,2.303,2.404,2.47,2.499,2.488,2.44,2.355,2.238,2.095,1.932,1.759,1.582,1.41,1.252,1.115,1.005,0.926,0.883,0.875,0.903,0.965,1.056,1.172,1.307,1.452,1.602,1.748,1.884,2.003,2.101,2.173,2.218,2.233,2.221,2.184,2.123,2.044,1.952,1.853,1.751,1.653,1.562,1.484,1.422,1.376,1.349,1.34,1.348,1.37,1.404,1.445,1.491,1.537,1.58,1.617,1.646,1.664,1.673,1.672,1.662,1.645,1.624,1.602,1.581,1.566,1.558,1.56,1.573,1.598,1.635,1.681,1.735,1.794,1.854,1.911,1.961,1.999,2.023,2.029,2.015,1.98,1.924,1.85,1.758,1.654,1.542,1.428,1.317,1.215,1.129,1.064,1.024,1.013,1.032,1.081,1.16,1.266,1.395,1.54,1.695,1.853,2.006,2.146,2.267,2.361,2.424,2.452,2.443,2.396,2.314,2.199,2.057,1.895,1.72,1.54,1.364,1.2,1.057,0.941,0.857,0.811,0.803,0.835,0.904,1.008,1.14,1.294,1.464,1.64,1.813,1.977,1.818,1.858,1.891,1.915,1.926,1.922,1.9,1.862,1.806,1.735,1.651,1.559,1.463,1.368,1.279,1.202,1.142,1.103,1.088,1.101,1.141,1.208,1.301,1.415,1.546,1.687,1.834,1.977,2.11,2.226,2.319,2.384,2.415,2.412,2.374,2.3,2.195,2.063,1.909,1.741,1.566,1.393,1.23,1.085,0.964,0.874,0.818,0.8,0.82,0.877,0.968,1.089,1.234,1.394,1.564,1.734,1.896,2.044,2.17,2.269,2.338,2.375,2.379,2.353,2.299,2.223,2.131,2.03,1.929,1.835,1.755,1.695,1.658,1.646,1.659,1.695,1.749,1.816,1.891,1.967,2.038,2.098,2.141,2.163,2.16,2.131,2.076,1.995,1.891,1.769,1.633,1.491,1.349,1.215,1.095,0.996,0.924,0.884,0.877,0.907,0.971,1.068,1.194,1.344,1.509,1.684,1.86,2.027,2.179,2.308,2.407,2.472,2.499,2.488,2.437,2.351,2.234,2.09,1.927,1.753,1.576,1.404,1.246,1.109,0.999,0.921,0.878,0.871,0.9,0.962,1.055,1.172,1.307,1.453,1.604,1.751,1.888,2.008,2.106,2.18,2.225,2.241,2.229,2.191,2.13,2.051,1.958,1.857,1.754,1.654,1.561,1.481,1.416,1.368,1.338,1.327,1.332,1.352,1.384,1.423,1.468,1.513,1.555,1.592,1.621,1.641,1.651,1.651,1.643,1.629,1.61,1.59,1.572,1.56,1.554,1.558,1.573,1.6,1.637,1.684,1.739,1.798,1.858,1.914,1.963,2.001,2.024,2.029,2.014,1.978,1.921,1.846,1.754,1.65,1.538,1.424,1.313,1.212,1.127,1.063,1.024,1.014,1.033,1.084,1.164,1.27,1.399,1.544,1.7,1.857,2.01,2.15,2.27,2.363,2.425,2.452,2.442,2.394,2.311,2.195,2.053,1.891,1.715,1.535,1.359,1.196,1.054,0.938,0.856,0.81,0.804,0.836,0.906,1.01,1.143,1.298,1.468,1.643,1.817,1.981,1.821,1.862,1.896,1.921,1.932,1.928,1.907,1.868,1.811,1.74,1.656,1.562,1.465,1.368,1.278,1.2,1.138,1.097,1.082,1.093,1.132,1.199,1.291,1.405,1.536,1.679,1.826,1.971,2.106,2.224,2.319,2.385,2.42,2.419,2.382,2.311,2.208,2.077,1.924,1.756,1.582,1.408,1.244,1.096,0.973,0.88,0.822,0.8,0.817,0.87,0.957,1.074,1.215,1.372,1.539,1.707,1.868,2.014,2.14,2.24,2.31,2.349,2.356,2.333,2.283,2.212,2.125,2.029,1.932,1.841,1.763,1.703,1.664,1.65,1.659,1.69,1.739,1.802,1.872,1.945,2.012,2.07,2.111,2.132,2.13,2.102,2.048,1.97,1.869,1.75,1.618,1.48,1.341,1.211,1.094,0.998,0.929,0.891,0.887,0.917,0.983,1.08,1.206,1.355,1.521,1.694,1.869,2.035,2.185,2.312,2.41,2.473,2.499,2.486,2.435,2.348,2.23,2.085,1.922,1.747,1.57,1.398,1.24,1.103,0.993,0.915,0.872,0.866,0.895,0.958,1.052,1.169,1.306,1.453,1.605,1.753,1.891,2.013,2.113,2.187,2.233,2.25,2.239,2.201,2.14,2.06,1.967,1.864,1.759,1.656,1.561,1.477,1.409,1.357,1.324,1.309,1.31,1.327,1.355,1.392,1.434,1.477,1.519,1.555,1.585,1.606,1.617,1.62,1.614,1.603,1.588,1.572,1.558,1.549,1.547,1.554,1.572,1.601,1.641,1.69,1.745,1.805,1.864,1.92,1.969,2.005,2.026,2.03,2.013,1.976,1.918,1.842,1.749,1.644,1.532,1.418,1.308,1.208,1.124,1.061,1.023,1.014,1.035,1.087,1.168,1.275,1.405,1.551,1.706,1.863,2.015,2.154,2.273,2.366,2.426,2.452,2.44,2.391,2.307,2.191,2.048,1.885,1.709,1.53,1.354,1.192,1.05,0.935,0.854,0.809,0.804,0.838,0.909,1.014,1.147,1.302,1.472,1.648,1.822,1.985,1.825,1.866,1.902,1.927,1.939,1.935,1.913,1.874,1.818,1.746,1.66,1.566,1.468,1.37,1.278,1.198,1.134,1.092,1.075,1.085,1.123,1.189,1.281,1.394,1.526,1.669,1.817,1.963,2.1,2.22,2.318,2.387,2.424,2.425,2.391,2.323,2.221,2.092,1.94,1.773,1.599,1.424,1.259,1.11,0.985,0.889,0.827,0.801,0.813,0.863,0.946,1.058,1.195,1.349,1.512,1.678,1.836,1.982,2.107,2.208,2.279,2.32,2.329,2.31,2.264,2.196,2.113,2.021,1.928,1.839,1.763,1.703,1.663,1.646,1.652,1.679,1.724,1.782,1.848,1.917,1.982,2.037,2.077,2.098,2.097,2.07,2.019,1.943,1.846,1.731,1.603,1.469,1.334,1.208,1.095,1.003,0.936,0.9,0.898,0.93,0.996,1.094,1.219,1.368,1.532,1.705,1.877,2.042,2.191,2.316,2.412,2.474,2.499,2.485,2.433,2.345,2.226,2.081,1.917,1.742,1.565,1.393,1.235,1.097,0.988,0.91,0.867,0.86,0.89,0.954,1.047,1.166,1.303,1.452,1.605,1.755,1.895,2.018,2.12,2.195,2.243,2.262,2.251,2.214,2.153,2.073,1.978,1.874,1.767,1.661,1.562,1.475,1.402,1.345,1.307,1.286,1.283,1.295,1.319,1.352,1.391,1.432,1.471,1.507,1.537,1.559,1.572,1.578,1.576,1.568,1.558,1.547,1.538,1.534,1.537,1.549,1.571,1.603,1.646,1.697,1.754,1.814,1.874,1.929,1.976,2.011,2.031,2.032,2.014,1.974,1.915,1.837,1.743,1.637,1.524,1.41,1.301,1.202,1.119,1.057,1.021,1.014,1.037,1.09,1.173,1.281,1.412,1.558,1.713,1.871,2.022,2.16,2.278,2.369,2.428,2.452,2.439,2.389,2.303,2.186,2.042,1.878,1.702,1.523,1.348,1.186,1.045,0.932,0.851,0.808,0.804,0.839,0.912,1.018,1.152,1.308,1.478,1.654,1.828,1.99,1.828,1.871,1.907,1.933,1.945,1.942,1.921,1.882,1.825,1.752,1.666,1.571,1.471,1.371,1.278,1.196,1.131,1.087,1.068,1.077,1.113,1.178,1.269,1.383,1.514,1.658,1.807,1.955,2.093,2.216,2.316,2.388,2.427,2.432,2.401,2.335,2.236,2.108,1.958,1.792,1.618,1.443,1.276,1.125,0.998,0.898,0.833,0.803,0.811,0.856,0.934,1.042,1.175,1.325,1.485,1.647,1.803,1.947,2.072,2.172,2.244,2.287,2.299,2.282,2.239,2.175,2.096,2.007,1.916,1.83,1.755,1.695,1.654,1.635,1.637,1.66,1.701,1.755,1.818,1.883,1.946,2.0,2.04,2.061,2.061,2.037,1.988,1.916,1.822,1.711,1.588,1.458,1.329,1.206,1.097,1.008,0.945,0.912,0.911,0.944,1.01,1.108,1.233,1.381,1.544,1.715,1.886,2.049,2.196,2.32,2.414,2.475,2.498,2.483,2.43,2.342,2.222,2.077,1.912,1.737,1.56,1.387,1.229,1.092,0.982,0.904,0.861,0.854,0.884,0.948,1.042,1.161,1.299,1.449,1.604,1.756,1.897,2.023,2.126,2.204,2.254,2.274,2.266,2.229,2.169,2.088,1.992,1.887,1.777,1.668,1.565,1.473,1.394,1.332,1.288,1.261,1.252,1.258,1.276,1.304,1.339,1.377,1.415,1.45,1.479,1.502,1.518,1.527,1.529,1.527,1.522,1.517,1.514,1.516,1.525,1.543,1.57,1.607,1.653,1.706,1.765,1.826,1.886,1.941,1.987,2.02,2.037,2.036,2.015,1.973,1.911,1.831,1.735,1.628,1.515,1.401,1.292,1.194,1.112,1.052,1.018,1.013,1.038,1.094,1.178,1.288,1.42,1.567,1.723,1.88,2.031,2.168,2.284,2.373,2.431,2.453,2.437,2.385,2.298,2.179,2.034,1.87,1.694,1.514,1.34,1.179,1.039,0.927,0.849,0.807,0.805,0.842,0.915,1.023,1.158,1.315,1.485,1.661,1.834,1.996,1.832,1.875,1.912,1.939,1.952,1.949,1.929,1.89,1.833,1.759,1.672,1.576,1.475,1.374,1.279,1.195,1.128,1.082,1.061,1.068,1.103,1.166,1.256,1.37,1.501,1.645,1.796,1.945,2.085,2.21,2.313,2.388,2.431,2.439,2.411,2.347,2.251,2.126,1.977,1.812,1.638,1.463,1.296,1.143,1.012,0.91,0.841,0.807,0.81,0.85,0.923,1.026,1.154,1.3,1.456,1.614,1.768,1.91,2.034,2.134,2.206,2.25,2.264,2.25,2.21,2.149,2.072,1.987,1.898,1.814,1.739,1.679,1.637,1.615,1.615,1.635,1.672,1.722,1.782,1.845,1.906,1.959,1.998,2.021,2.022,2.001,1.956,1.887,1.798,1.692,1.574,1.45,1.325,1.207,1.102,1.017,0.956,0.925,0.926,0.959,1.026,1.124,1.248,1.394,1.556,1.725,1.894,2.055,2.2,2.322,2.415,2.474,2.497,2.481,2.427,2.338,2.218,2.072,1.908,1.733,1.555,1.383,1.224,1.086,0.976,0.898,0.854,0.848,0.877,0.941,1.036,1.155,1.294,1.446,1.602,1.755,1.899,2.027,2.133,2.214,2.266,2.289,2.282,2.247,2.187,2.106,2.01,1.902,1.79,1.677,1.57,1.472,1.388,1.319,1.268,1.234,1.218,1.217,1.229,1.251,1.281,1.316,1.351,1.384,1.414,1.438,1.457,1.469,1.477,1.48,1.482,1.483,1.488,1.497,1.513,1.537,1.57,1.611,1.662,1.718,1.779,1.841,1.901,1.955,1.999,2.03,2.045,2.04,2.016,1.971,1.906,1.824,1.726,1.618,1.504,1.39,1.281,1.184,1.104,1.046,1.015,1.012,1.04,1.098,1.184,1.296,1.429,1.577,1.733,1.89,2.04,2.176,2.291,2.378,2.433,2.453,2.436,2.381,2.292,2.172,2.026,1.861,1.684,1.505,1.331,1.171,1.033,0.922,0.846,0.806,0.806,0.844,0.92,1.028,1.165,1.322,1.493,1.669,1.842,2.003,1.835,1.88,1.918,1.946,1.96,1.957,1.937,1.898,1.841,1.767,1.68,1.582,1.479,1.377,1.28,1.194,1.125,1.077,1.054,1.058,1.092,1.154,1.243,1.355,1.487,1.632,1.783,1.933,2.076,2.204,2.309,2.387,2.434,2.445,2.421,2.361,2.267,2.145,1.998,1.834,1.661,1.486,1.317,1.162,1.029,0.924,0.85,0.812,0.81,0.845,0.913,1.011,1.133,1.274,1.426,1.581,1.732,1.871,1.993,2.093,2.166,2.21,2.226,2.213,2.176,2.118,2.044,1.96,1.874,1.79,1.716,1.655,1.612,1.588,1.585,1.602,1.636,1.684,1.741,1.802,1.861,1.914,1.954,1.978,1.982,1.963,1.922,1.859,1.775,1.674,1.561,1.442,1.322,1.209,1.109,1.027,0.969,0.94,0.942,0.977,1.044,1.141,1.264,1.408,1.568,1.735,1.902,2.061,2.204,2.324,2.415,2.473,2.494,2.478,2.424,2.334,2.214,2.068,1.904,1.729,1.551,1.378,1.219,1.081,0.971,0.892,0.848,0.841,0.87,0.934,1.028,1.149,1.288,1.441,1.599,1.754,1.9,2.031,2.14,2.224,2.279,2.304,2.299,2.266,2.207,2.127,2.03,1.921,1.805,1.689,1.577,1.474,1.383,1.307,1.248,1.206,1.182,1.173,1.178,1.195,1.219,1.249,1.282,1.314,1.343,1.369,1.39,1.407,1.42,1.43,1.438,1.448,1.46,1.477,1.501,1.532,1.571,1.619,1.673,1.733,1.796,1.859,1.919,1.972,2.014,2.042,2.053,2.046,2.017,1.969,1.901,1.815,1.716,1.606,1.491,1.377,1.269,1.173,1.095,1.04,1.011,1.011,1.041,1.102,1.191,1.305,1.44,1.589,1.745,1.902,2.051,2.186,2.299,2.384,2.437,2.454,2.434,2.377,2.286,2.163,2.016,1.85,1.673,1.494,1.321,1.162,1.025,0.917,0.843,0.805,0.807,0.848,0.925,1.035,1.173,1.331,1.502,1.678,1.85,2.011,1.838,1.884,1.924,1.952,1.967,1.966,1.946,1.907,1.85,1.776,1.688,1.589,1.485,1.38,1.281,1.193,1.122,1.072,1.046,1.049,1.08,1.141,1.229,1.34,1.472,1.617,1.769,1.921,2.066,2.196,2.304,2.386,2.436,2.451,2.431,2.374,2.284,2.164,2.02,1.858,1.685,1.51,1.34,1.184,1.049,0.94,0.862,0.819,0.812,0.841,0.904,0.996,1.113,1.249,1.396,1.547,1.695,1.832,1.952,2.05,2.123,2.168,2.184,2.173,2.138,2.082,2.01,1.928,1.843,1.76,1.686,1.625,1.58,1.555,1.549,1.563,1.594,1.639,1.694,1.754,1.812,1.865,1.907,1.932,1.939,1.925,1.888,1.83,1.752,1.657,1.55,1.437,1.322,1.214,1.118,1.04,0.985,0.958,0.961,0.996,1.063,1.159,1.28,1.423,1.58,1.745,1.909,2.066,2.207,2.325,2.415,2.471,2.491,2.474,2.419,2.33,2.21,2.064,1.9,1.725,1.547,1.374,1.215,1.077,0.966,0.886,0.841,0.834,0.862,0.926,1.02,1.141,1.281,1.435,1.594,1.752,1.901,2.034,2.146,2.233,2.292,2.32,2.318,2.287,2.23,2.15,2.052,1.942,1.824,1.704,1.587,1.478,1.38,1.296,1.229,1.179,1.146,1.129,1.127,1.136,1.155,1.18,1.209,1.24,1.269,1.297,1.321,1.343,1.361,1.378,1.394,1.412,1.433,1.458,1.49,1.529,1.575,1.629,1.688,1.751,1.817,1.881,1.94,1.991,2.031,2.056,2.063,2.051,2.019,1.966,1.894,1.806,1.703,1.592,1.476,1.362,1.254,1.16,1.085,1.032,1.006,1.01,1.043,1.107,1.199,1.316,1.452,1.602,1.759,1.915,2.064,2.197,2.307,2.39,2.44,2.454,2.431,2.372,2.278,2.154,2.005,1.838,1.661,1.482,1.31,1.152,1.017,0.911,0.839,0.804,0.809,0.851,0.931,1.043,1.182,1.341,1.512,1.688,1.86,2.019,1.842,1.889,1.929,1.959,1.975,1.975,1.955,1.917,1.86,1.785,1.696,1.597,1.491,1.385,1.284,1.194,1.12,1.067,1.039,1.039,1.068,1.127,1.213,1.324,1.455,1.6,1.753,1.907,2.054,2.187,2.299,2.384,2.438,2.457,2.44,2.388,2.302,2.185,2.043,1.883,1.711,1.536,1.366,1.208,1.07,0.958,0.876,0.828,0.816,0.839,0.896,0.983,1.094,1.224,1.366,1.513,1.657,1.791,1.909,2.006,2.078,2.123,2.14,2.13,2.096,2.041,1.971,1.891,1.807,1.725,1.65,1.588,1.542,1.515,1.507,1.518,1.547,1.59,1.643,1.702,1.76,1.814,1.857,1.885,1.896,1.886,1.855,1.802,1.73,1.641,1.541,1.433,1.325,1.222,1.13,1.055,1.004,0.978,0.983,1.018,1.083,1.178,1.298,1.438,1.592,1.754,1.916,2.07,2.208,2.324,2.412,2.468,2.487,2.469,2.414,2.325,2.205,2.06,1.896,1.721,1.544,1.371,1.212,1.073,0.961,0.881,0.835,0.827,0.855,0.918,1.012,1.132,1.273,1.428,1.589,1.749,1.9,2.036,2.152,2.243,2.304,2.336,2.337,2.309,2.254,2.175,2.078,1.966,1.845,1.722,1.6,1.485,1.38,1.288,1.213,1.154,1.112,1.087,1.076,1.078,1.091,1.111,1.137,1.165,1.195,1.224,1.252,1.278,1.303,1.327,1.351,1.378,1.408,1.442,1.483,1.53,1.583,1.642,1.706,1.773,1.84,1.905,1.963,2.013,2.049,2.07,2.073,2.057,2.02,1.963,1.887,1.794,1.689,1.576,1.459,1.345,1.239,1.146,1.073,1.023,1.001,1.008,1.046,1.113,1.208,1.327,1.465,1.616,1.774,1.93,2.077,2.209,2.317,2.397,2.444,2.455,2.429,2.366,2.27,2.143,1.993,1.825,1.647,1.469,1.298,1.142,1.009,0.905,0.835,0.803,0.81,0.856,0.938,1.051,1.192,1.352,1.524,1.699,1.87,2.028,1.845,1.893,1.935,1.966,1.984,1.984,1.965,1.927,1.87,1.795,1.706,1.605,1.498,1.39,1.287,1.194,1.118,1.062,1.032,1.029,1.056,1.112,1.197,1.307,1.437,1.582,1.736,1.891,2.04,2.176,2.291,2.38,2.439,2.462,2.45,2.402,2.319,2.206,2.067,1.909,1.739,1.564,1.394,1.234,1.094,0.978,0.892,0.839,0.822,0.839,0.89,0.971,1.076,1.201,1.338,1.48,1.619,1.75,1.866,1.961,2.032,2.076,2.094,2.085,2.052,1.998,1.929,1.849,1.766,1.684,1.609,1.546,1.498,1.469,1.459,1.468,1.495,1.536,1.588,1.646,1.705,1.76,1.805,1.837,1.852,1.847,1.821,1.775,1.709,1.628,1.534,1.433,1.33,1.232,1.145,1.074,1.025,1.001,1.006,1.041,1.106,1.198,1.316,1.453,1.605,1.763,1.922,2.073,2.209,2.323,2.409,2.463,2.481,2.463,2.408,2.319,2.2,2.055,1.892,1.718,1.541,1.369,1.209,1.07,0.957,0.876,0.83,0.82,0.847,0.909,1.003,1.123,1.264,1.42,1.582,1.744,1.898,2.038,2.157,2.251,2.317,2.353,2.358,2.332,2.28,2.202,2.105,1.992,1.87,1.743,1.616,1.495,1.383,1.284,1.2,1.132,1.081,1.047,1.028,1.023,1.029,1.044,1.066,1.093,1.123,1.153,1.185,1.216,1.247,1.278,1.312,1.347,1.386,1.43,1.479,1.534,1.595,1.66,1.729,1.799,1.867,1.932,1.989,2.036,2.069,2.086,2.084,2.062,2.02,1.958,1.877,1.781,1.673,1.558,1.44,1.326,1.221,1.131,1.06,1.014,0.996,1.007,1.049,1.12,1.218,1.34,1.48,1.633,1.791,1.946,2.092,2.222,2.327,2.404,2.448,2.455,2.425,2.36,2.26,2.132,1.979,1.81,1.633,1.454,1.284,1.13,0.999,0.898,0.832,0.803,0.813,0.861,0.945,1.061,1.203,1.364,1.536,1.711,1.881,2.038,1.847,1.898,1.941,1.974,1.992,1.993,1.976,1.938,1.881,1.806,1.716,1.615,1.506,1.396,1.291,1.196,1.116,1.058,1.024,1.019,1.043,1.097,1.18,1.288,1.418,1.563,1.718,1.874,2.026,2.164,2.283,2.376,2.438,2.467,2.459,2.415,2.337,2.228,2.093,1.937,1.768,1.594,1.423,1.262,1.12,1.001,0.911,0.853,0.83,0.842,0.886,0.961,1.06,1.179,1.31,1.447,1.582,1.71,1.822,1.915,1.985,2.029,2.046,2.037,2.005,1.952,1.883,1.804,1.721,1.638,1.563,1.499,1.45,1.419,1.407,1.414,1.439,1.479,1.53,1.588,1.648,1.704,1.752,1.788,1.807,1.808,1.789,1.749,1.691,1.616,1.529,1.435,1.338,1.246,1.163,1.096,1.049,1.027,1.032,1.067,1.13,1.22,1.335,1.469,1.617,1.772,1.927,2.075,2.208,2.319,2.404,2.456,2.474,2.456,2.401,2.313,2.194,2.051,1.889,1.715,1.539,1.367,1.207,1.068,0.955,0.872,0.825,0.814,0.84,0.901,0.993,1.113,1.255,1.411,1.574,1.738,1.895,2.038,2.161,2.259,2.329,2.369,2.378,2.356,2.306,2.231,2.134,2.021,1.897,1.767,1.636,1.509,1.391,1.284,1.191,1.115,1.055,1.012,0.984,0.972,0.971,0.981,1.0,1.025,1.055,1.087,1.122,1.158,1.196,1.235,1.277,1.322,1.37,1.423,1.481,1.544,1.612,1.683,1.756,1.828,1.898,1.962,2.018,2.061,2.09,2.102,2.095,2.067,2.019,1.952,1.866,1.766,1.655,1.538,1.42,1.306,1.202,1.114,1.047,1.005,0.99,1.006,1.052,1.127,1.229,1.354,1.497,1.651,1.809,1.964,2.108,2.235,2.338,2.412,2.451,2.455,2.422,2.352,2.25,2.119,1.965,1.795,1.617,1.439,1.27,1.118,0.99,0.891,0.828,0.802,0.815,0.867,0.953,1.071,1.215,1.377,1.549,1.724,1.893,2.048,1.85,1.902,1.947,1.981,2.001,2.003,1.987,1.95,1.893,1.818,1.728,1.625,1.515,1.403,1.296,1.198,1.116,1.054,1.017,1.009,1.03,1.082,1.162,1.269,1.398,1.543,1.698,1.856,2.009,2.15,2.273,2.37,2.437,2.47,2.468,2.429,2.355,2.25,2.118,1.966,1.799,1.626,1.455,1.293,1.148,1.026,0.932,0.87,0.841,0.847,0.885,0.953,1.046,1.158,1.284,1.416,1.547,1.67,1.78,1.87,1.938,1.981,1.998,1.989,1.956,1.904,1.835,1.756,1.673,1.59,1.514,1.448,1.398,1.365,1.351,1.357,1.38,1.419,1.47,1.528,1.589,1.648,1.699,1.739,1.764,1.77,1.758,1.725,1.674,1.607,1.528,1.44,1.35,1.263,1.185,1.121,1.077,1.056,1.061,1.094,1.155,1.243,1.354,1.484,1.628,1.78,1.931,2.075,2.205,2.314,2.396,2.448,2.465,2.447,2.393,2.305,2.188,2.046,1.885,1.713,1.537,1.366,1.207,1.067,0.953,0.87,0.821,0.809,0.833,0.892,0.984,1.103,1.244,1.401,1.566,1.731,1.89,2.036,2.163,2.265,2.34,2.384,2.397,2.38,2.333,2.26,2.165,2.052,1.927,1.795,1.66,1.528,1.403,1.289,1.188,1.103,1.034,0.983,0.947,0.927,0.92,0.925,0.941,0.964,0.993,1.028,1.066,1.108,1.152,1.199,1.249,1.303,1.361,1.423,1.49,1.56,1.634,1.71,1.787,1.862,1.932,1.995,2.048,2.088,2.112,2.118,2.105,2.071,2.017,1.944,1.853,1.749,1.635,1.516,1.397,1.283,1.182,1.096,1.033,0.995,0.985,1.006,1.056,1.136,1.242,1.37,1.515,1.67,1.828,1.983,2.126,2.25,2.35,2.42,2.455,2.455,2.417,2.344,2.238,2.105,1.949,1.777,1.599,1.422,1.255,1.105,0.979,0.884,0.824,0.802,0.819,0.873,0.963,1.083,1.228,1.391,1.563,1.738,1.906,2.059,1.852,1.906,1.952,1.988,2.009,2.013,1.998,1.962,1.906,1.831,1.74,1.636,1.525,1.412,1.302,1.201,1.116,1.051,1.011,0.999,1.017,1.066,1.144,1.249,1.376,1.521,1.676,1.835,1.991,2.135,2.261,2.362,2.434,2.473,2.475,2.442,2.373,2.273,2.145,1.995,1.831,1.659,1.488,1.326,1.179,1.053,0.956,0.889,0.855,0.854,0.886,0.948,1.034,1.141,1.26,1.387,1.513,1.632,1.738,1.826,1.892,1.934,1.949,1.94,1.907,1.854,1.786,1.707,1.623,1.54,1.462,1.395,1.343,1.309,1.293,1.297,1.319,1.357,1.408,1.467,1.529,1.591,1.646,1.691,1.721,1.734,1.729,1.704,1.661,1.602,1.53,1.449,1.366,1.284,1.21,1.15,1.107,1.087,1.092,1.124,1.183,1.267,1.374,1.5,1.64,1.786,1.934,2.074,2.2,2.307,2.387,2.438,2.454,2.436,2.383,2.297,2.181,2.04,1.881,1.71,1.536,1.365,1.207,1.067,0.953,0.868,0.818,0.804,0.827,0.885,0.975,1.093,1.233,1.39,1.556,1.723,1.884,2.033,2.163,2.27,2.349,2.398,2.416,2.403,2.36,2.29,2.197,2.085,1.96,1.825,1.687,1.551,1.42,1.299,1.191,1.098,1.021,0.961,0.917,0.89,0.877,0.878,0.89,0.912,0.941,0.978,1.019,1.066,1.117,1.171,1.23,1.293,1.359,1.43,1.505,1.583,1.662,1.743,1.823,1.899,1.969,2.03,2.08,2.115,2.134,2.134,2.114,2.073,2.013,1.933,1.838,1.729,1.612,1.491,1.372,1.259,1.16,1.078,1.018,0.985,0.98,1.006,1.062,1.146,1.256,1.388,1.535,1.691,1.85,2.003,2.144,2.266,2.362,2.428,2.459,2.454,2.412,2.335,2.226,2.089,1.931,1.759,1.581,1.404,1.238,1.091,0.968,0.877,0.821,0.802,0.822,0.88,0.973,1.095,1.242,1.406,1.579,1.753,1.919,2.071,1.854,1.909,1.958,1.995,2.018,2.024,2.01,1.975,1.919,1.845,1.753,1.649,1.536,1.421,1.308,1.205,1.116,1.048,1.004,0.989,1.004,1.049,1.125,1.227,1.353,1.497,1.653,1.813,1.971,2.118,2.248,2.353,2.43,2.474,2.482,2.454,2.391,2.295,2.171,2.025,1.864,1.694,1.523,1.36,1.212,1.084,0.982,0.91,0.871,0.865,0.891,0.945,1.026,1.126,1.239,1.36,1.482,1.596,1.699,1.784,1.848,1.888,1.902,1.892,1.859,1.805,1.737,1.657,1.572,1.488,1.409,1.341,1.287,1.251,1.234,1.236,1.257,1.295,1.346,1.406,1.47,1.535,1.594,1.644,1.68,1.701,1.702,1.686,1.651,1.599,1.535,1.462,1.385,1.309,1.239,1.182,1.141,1.121,1.126,1.155,1.211,1.292,1.395,1.516,1.651,1.792,1.935,2.071,2.194,2.298,2.376,2.425,2.442,2.424,2.371,2.287,2.173,2.034,1.877,1.708,1.535,1.366,1.208,1.069,0.954,0.869,0.817,0.801,0.822,0.878,0.966,1.083,1.222,1.379,1.544,1.713,1.876,2.028,2.162,2.273,2.357,2.411,2.433,2.425,2.386,2.32,2.23,2.119,1.994,1.859,1.718,1.578,1.443,1.316,1.201,1.1,1.015,0.948,0.897,0.863,0.845,0.841,0.85,0.87,0.9,0.938,0.983,1.035,1.092,1.154,1.221,1.292,1.367,1.446,1.528,1.612,1.697,1.781,1.863,1.94,2.009,2.067,2.113,2.143,2.156,2.149,2.121,2.074,2.006,1.921,1.82,1.707,1.587,1.465,1.345,1.234,1.137,1.058,1.003,0.975,0.976,1.007,1.069,1.158,1.272,1.407,1.556,1.714,1.872,2.025,2.164,2.282,2.374,2.436,2.462,2.452,2.406,2.325,2.212,2.072,1.912,1.739,1.561,1.385,1.221,1.076,0.957,0.869,0.817,0.803,0.827,0.888,0.984,1.109,1.257,1.422,1.595,1.768,1.934,2.083,1.856,1.913,1.963,2.002,2.027,2.034,2.022,1.988,1.933,1.859,1.767,1.662,1.548,1.431,1.316,1.21,1.118,1.046,0.999,0.979,0.991,1.033,1.105,1.205,1.33,1.473,1.629,1.79,1.949,2.099,2.232,2.343,2.424,2.473,2.487,2.465,2.407,2.317,2.198,2.056,1.898,1.73,1.56,1.397,1.247,1.116,1.011,0.935,0.891,0.879,0.898,0.946,1.02,1.114,1.221,1.337,1.453,1.563,1.662,1.744,1.806,1.843,1.857,1.845,1.811,1.758,1.688,1.608,1.522,1.437,1.357,1.287,1.231,1.193,1.174,1.175,1.195,1.233,1.284,1.345,1.412,1.48,1.544,1.599,1.642,1.669,1.679,1.671,1.644,1.601,1.545,1.479,1.408,1.337,1.272,1.217,1.178,1.159,1.162,1.189,1.242,1.318,1.416,1.532,1.661,1.797,1.935,2.066,2.185,2.286,2.362,2.41,2.426,2.409,2.358,2.275,2.164,2.028,1.873,1.707,1.536,1.368,1.211,1.072,0.956,0.871,0.818,0.8,0.819,0.872,0.958,1.073,1.211,1.367,1.532,1.701,1.867,2.021,2.158,2.273,2.362,2.421,2.449,2.445,2.411,2.349,2.262,2.154,2.03,1.894,1.752,1.61,1.47,1.338,1.217,1.11,1.018,0.944,0.887,0.847,0.823,0.815,0.821,0.841,0.871,0.911,0.96,1.016,1.079,1.148,1.222,1.301,1.384,1.47,1.559,1.648,1.738,1.825,1.908,1.984,2.051,2.106,2.147,2.171,2.176,2.162,2.127,2.071,1.997,1.905,1.799,1.682,1.559,1.436,1.316,1.207,1.112,1.038,0.988,0.966,0.973,1.01,1.077,1.171,1.29,1.428,1.58,1.738,1.897,2.048,2.184,2.299,2.387,2.444,2.465,2.45,2.399,2.313,2.196,2.054,1.892,1.718,1.54,1.365,1.204,1.061,0.946,0.862,0.814,0.804,0.832,0.897,0.996,1.124,1.274,1.439,1.612,1.785,1.948,2.096,1.857,1.916,1.968,2.009,2.036,2.045,2.034,2.002,1.948,1.874,1.783,1.677,1.562,1.442,1.325,1.216,1.121,1.045,0.994,0.97,0.977,1.016,1.085,1.183,1.305,1.447,1.602,1.764,1.926,2.078,2.215,2.33,2.417,2.471,2.491,2.475,2.423,2.339,2.225,2.087,1.932,1.767,1.598,1.435,1.284,1.152,1.043,0.963,0.913,0.896,0.909,0.951,1.018,1.105,1.207,1.317,1.428,1.534,1.629,1.708,1.766,1.802,1.814,1.801,1.766,1.712,1.641,1.56,1.474,1.387,1.305,1.234,1.176,1.137,1.116,1.116,1.135,1.172,1.224,1.287,1.356,1.428,1.496,1.557,1.607,1.642,1.659,1.659,1.641,1.607,1.558,1.5,1.435,1.37,1.308,1.256,1.219,1.199,1.2,1.225,1.273,1.345,1.437,1.547,1.67,1.801,1.933,2.059,2.174,2.272,2.346,2.393,2.409,2.392,2.343,2.262,2.153,2.02,1.869,1.705,1.537,1.371,1.215,1.077,0.961,0.874,0.82,0.801,0.817,0.868,0.951,1.064,1.2,1.354,1.52,1.689,1.855,2.012,2.152,2.271,2.364,2.428,2.461,2.463,2.434,2.377,2.294,2.189,2.066,1.931,1.789,1.645,1.502,1.366,1.241,1.128,1.03,0.95,0.887,0.842,0.814,0.802,0.806,0.824,0.855,0.897,0.95,1.01,1.079,1.154,1.235,1.321,1.411,1.503,1.598,1.692,1.784,1.873,1.956,2.031,2.095,2.145,2.18,2.197,2.195,2.173,2.129,2.066,1.984,1.886,1.775,1.654,1.529,1.404,1.286,1.178,1.087,1.018,0.973,0.957,0.97,1.014,1.087,1.186,1.309,1.451,1.605,1.764,1.922,2.072,2.205,2.317,2.4,2.451,2.467,2.447,2.391,2.3,2.18,2.034,1.87,1.695,1.517,1.345,1.185,1.046,0.934,0.855,0.811,0.806,0.838,0.907,1.009,1.14,1.291,1.458,1.631,1.802,1.964,2.109,1.857,1.918,1.973,2.016,2.045,2.056,2.047,2.016,1.964,1.89,1.799,1.692,1.576,1.455,1.335,1.223,1.124,1.045,0.989,0.962,0.965,0.999,1.065,1.159,1.279,1.42,1.575,1.737,1.9,2.055,2.196,2.315,2.407,2.468,2.493,2.484,2.438,2.359,2.251,2.118,1.967,1.804,1.638,1.475,1.323,1.189,1.078,0.993,0.939,0.916,0.923,0.959,1.02,1.101,1.196,1.301,1.406,1.508,1.599,1.675,1.731,1.764,1.774,1.76,1.724,1.669,1.598,1.515,1.427,1.339,1.256,1.183,1.124,1.082,1.06,1.058,1.077,1.114,1.166,1.231,1.303,1.378,1.452,1.519,1.575,1.617,1.643,1.652,1.642,1.616,1.576,1.525,1.466,1.406,1.349,1.299,1.262,1.242,1.241,1.262,1.306,1.372,1.459,1.562,1.679,1.803,1.929,2.05,2.161,2.255,2.327,2.373,2.389,2.373,2.326,2.248,2.142,2.012,1.864,1.704,1.538,1.375,1.221,1.083,0.968,0.881,0.825,0.803,0.817,0.865,0.946,1.056,1.19,1.342,1.506,1.675,1.842,2.0,2.143,2.266,2.363,2.432,2.471,2.478,2.455,2.402,2.324,2.222,2.103,1.97,1.828,1.683,1.539,1.4,1.271,1.154,1.051,0.966,0.898,0.848,0.817,0.803,0.805,0.822,0.854,0.898,0.953,1.018,1.092,1.173,1.26,1.352,1.448,1.546,1.645,1.742,1.837,1.926,2.008,2.08,2.14,2.185,2.213,2.222,2.212,2.181,2.129,2.058,1.969,1.864,1.747,1.623,1.496,1.371,1.253,1.149,1.062,0.997,0.959,0.949,0.969,1.019,1.098,1.204,1.331,1.476,1.632,1.792,1.949,2.097,2.227,2.334,2.413,2.458,2.469,2.443,2.381,2.286,2.161,2.013,1.847,1.672,1.494,1.323,1.166,1.03,0.922,0.848,0.809,0.808,0.845,0.918,1.024,1.157,1.31,1.477,1.65,1.82,1.98,2.122,1.857,1.92,1.977,2.023,2.054,2.067,2.06,2.031,1.98,1.907,1.816,1.709,1.592,1.469,1.347,1.231,1.129,1.046,0.986,0.954,0.952,0.982,1.044,1.135,1.253,1.392,1.546,1.709,1.873,2.031,2.175,2.298,2.395,2.462,2.494,2.491,2.452,2.379,2.277,2.149,2.002,1.843,1.678,1.516,1.364,1.229,1.115,1.027,0.968,0.939,0.941,0.971,1.025,1.1,1.19,1.289,1.389,1.486,1.574,1.646,1.699,1.731,1.739,1.724,1.687,1.63,1.558,1.474,1.385,1.295,1.211,1.135,1.075,1.031,1.007,1.005,1.022,1.059,1.112,1.179,1.254,1.333,1.411,1.484,1.547,1.598,1.632,1.649,1.648,1.63,1.598,1.554,1.502,1.447,1.393,1.345,1.309,1.287,1.284,1.301,1.34,1.4,1.48,1.576,1.686,1.803,1.923,2.038,2.145,2.235,2.305,2.349,2.365,2.351,2.306,2.231,2.129,2.003,1.859,1.703,1.541,1.38,1.228,1.092,0.977,0.889,0.832,0.809,0.82,0.865,0.942,1.049,1.18,1.33,1.492,1.66,1.827,1.987,2.132,2.257,2.359,2.433,2.476,2.489,2.472,2.425,2.351,2.254,2.139,2.008,1.868,1.724,1.579,1.439,1.307,1.187,1.081,0.992,0.92,0.867,0.833,0.816,0.817,0.835,0.867,0.913,0.971,1.04,1.119,1.205,1.297,1.394,1.495,1.597,1.699,1.799,1.894,1.982,2.062,2.13,2.185,2.223,2.244,2.245,2.225,2.185,2.125,2.045,1.949,1.838,1.717,1.589,1.46,1.335,1.22,1.118,1.036,0.977,0.945,0.942,0.969,1.026,1.112,1.223,1.355,1.503,1.661,1.821,1.978,2.123,2.249,2.352,2.425,2.465,2.469,2.437,2.37,2.27,2.142,1.99,1.823,1.646,1.469,1.3,1.146,1.014,0.911,0.841,0.807,0.811,0.853,0.931,1.039,1.175,1.33,1.498,1.67,1.839,1.997,2.136,1.856,1.922,1.981,2.029,2.063,2.079,2.074,2.046,1.996,1.925,1.834,1.727,1.609,1.484,1.36,1.241,1.135,1.048,0.983,0.947,0.94,0.966,1.023,1.111,1.226,1.362,1.516,1.678,1.844,2.004,2.151,2.279,2.382,2.454,2.492,2.496,2.464,2.398,2.301,2.179,2.037,1.881,1.719,1.559,1.407,1.27,1.154,1.063,1.0,0.966,0.962,0.986,1.035,1.104,1.188,1.281,1.377,1.47,1.553,1.622,1.673,1.702,1.709,1.692,1.654,1.596,1.523,1.438,1.348,1.256,1.17,1.093,1.03,0.985,0.959,0.955,0.972,1.009,1.063,1.131,1.209,1.292,1.375,1.454,1.524,1.582,1.625,1.65,1.658,1.649,1.625,1.587,1.541,1.491,1.44,1.394,1.358,1.335,1.329,1.342,1.375,1.428,1.501,1.59,1.692,1.802,1.914,2.024,2.126,2.212,2.28,2.323,2.339,2.327,2.284,2.213,2.114,1.993,1.854,1.702,1.544,1.387,1.238,1.103,0.989,0.901,0.843,0.817,0.825,0.867,0.941,1.044,1.171,1.318,1.478,1.644,1.811,1.971,2.117,2.246,2.351,2.429,2.478,2.496,2.484,2.443,2.376,2.284,2.173,2.046,1.909,1.766,1.622,1.481,1.348,1.227,1.119,1.027,0.953,0.897,0.861,0.843,0.843,0.861,0.894,0.942,1.003,1.076,1.158,1.249,1.345,1.447,1.551,1.656,1.76,1.86,1.955,2.042,2.118,2.181,2.229,2.26,2.272,2.264,2.235,2.186,2.116,2.029,1.925,1.808,1.682,1.552,1.422,1.298,1.185,1.087,1.01,0.958,0.933,0.937,0.972,1.036,1.128,1.244,1.381,1.532,1.692,1.852,2.007,2.149,2.272,2.37,2.437,2.471,2.469,2.431,2.358,2.253,2.12,1.966,1.797,1.62,1.444,1.277,1.126,0.998,0.899,0.834,0.806,0.816,0.862,0.944,1.056,1.194,1.351,1.519,1.691,1.859,2.014,2.15,1.855,1.923,1.984,2.035,2.071,2.09,2.087,2.062,2.014,1.943,1.853,1.746,1.627,1.501,1.374,1.253,1.143,1.051,0.982,0.94,0.929,0.95,1.003,1.086,1.198,1.332,1.484,1.647,1.813,1.975,2.125,2.258,2.365,2.444,2.489,2.499,2.474,2.415,2.325,2.209,2.071,1.92,1.761,1.602,1.451,1.313,1.195,1.101,1.034,0.996,0.987,1.006,1.049,1.112,1.19,1.278,1.369,1.458,1.537,1.604,1.652,1.679,1.684,1.666,1.627,1.568,1.493,1.408,1.316,1.223,1.135,1.056,0.991,0.944,0.917,0.911,0.927,0.964,1.019,1.088,1.169,1.256,1.344,1.429,1.506,1.572,1.622,1.656,1.673,1.672,1.655,1.625,1.585,1.539,1.491,1.447,1.41,1.385,1.375,1.383,1.41,1.457,1.522,1.602,1.696,1.798,1.904,2.007,2.103,2.186,2.251,2.294,2.31,2.299,2.259,2.192,2.098,1.982,1.848,1.701,1.548,1.395,1.249,1.116,1.004,0.915,0.856,0.828,0.833,0.872,0.942,1.04,1.164,1.307,1.464,1.628,1.793,1.952,2.1,2.23,2.338,2.421,2.474,2.498,2.493,2.458,2.396,2.31,2.204,2.082,1.948,1.808,1.666,1.527,1.394,1.272,1.163,1.07,0.995,0.938,0.9,0.882,0.882,0.9,0.935,0.985,1.049,1.124,1.21,1.304,1.404,1.509,1.615,1.722,1.826,1.926,2.019,2.102,2.173,2.231,2.271,2.294,2.297,2.279,2.241,2.182,2.103,2.007,1.897,1.774,1.645,1.512,1.382,1.259,1.149,1.056,0.985,0.939,0.922,0.934,0.976,1.048,1.146,1.269,1.409,1.563,1.724,1.885,2.038,2.177,2.295,2.387,2.448,2.476,2.467,2.422,2.344,2.234,2.097,1.94,1.769,1.592,1.417,1.252,1.105,0.982,0.888,0.829,0.806,0.821,0.873,0.958,1.074,1.215,1.373,1.542,1.713,1.879,2.031,2.164,1.853,1.923,1.987,2.04,2.08,2.101,2.101,2.078,2.032,1.963,1.873,1.766,1.647,1.519,1.39,1.265,1.152,1.056,0.982,0.935,0.919,0.934,0.982,1.062,1.169,1.301,1.451,1.613,1.78,1.944,2.097,2.234,2.347,2.431,2.483,2.5,2.482,2.43,2.347,2.237,2.105,1.958,1.803,1.646,1.496,1.358,1.239,1.142,1.072,1.03,1.016,1.029,1.066,1.124,1.197,1.28,1.367,1.451,1.527,1.591,1.636,1.662,1.665,1.646,1.606,1.546,1.471,1.384,1.291,1.196,1.106,1.025,0.959,0.909,0.881,0.874,0.889,0.925,0.981,1.052,1.135,1.225,1.319,1.409,1.493,1.566,1.625,1.667,1.692,1.699,1.69,1.667,1.632,1.59,1.545,1.502,1.464,1.437,1.424,1.426,1.447,1.485,1.542,1.614,1.699,1.793,1.891,1.988,2.078,2.157,2.219,2.261,2.278,2.269,2.232,2.169,2.08,1.97,1.841,1.7,1.552,1.404,1.262,1.132,1.021,0.933,0.873,0.843,0.845,0.88,0.945,1.039,1.158,1.297,1.45,1.611,1.774,1.932,2.08,2.211,2.322,2.407,2.466,2.495,2.495,2.467,2.411,2.332,2.231,2.115,1.986,1.85,1.711,1.575,1.444,1.323,1.214,1.121,1.046,0.988,0.951,0.932,0.933,0.952,0.988,1.04,1.106,1.184,1.273,1.37,1.472,1.579,1.687,1.794,1.897,1.995,2.084,2.163,2.228,2.278,2.311,2.324,2.317,2.29,2.241,2.172,2.085,1.981,1.864,1.736,1.603,1.469,1.339,1.219,1.112,1.025,0.96,0.922,0.912,0.933,0.983,1.062,1.168,1.295,1.44,1.597,1.759,1.918,2.069,2.205,2.318,2.404,2.459,2.479,2.464,2.413,2.328,2.213,2.072,1.912,1.74,1.563,1.39,1.228,1.084,0.965,0.877,0.824,0.807,0.827,0.884,0.974,1.094,1.237,1.396,1.565,1.736,1.899,2.049,2.178,1.85,1.922,1.989,2.045,2.087,2.111,2.114,2.094,2.05,1.983,1.894,1.788,1.667,1.539,1.407,1.28,1.163,1.062,0.983,0.931,0.909,0.919,0.962,1.037,1.141,1.269,1.417,1.578,1.745,1.911,2.067,2.207,2.325,2.416,2.474,2.498,2.488,2.443,2.367,2.264,2.138,1.995,1.844,1.69,1.541,1.404,1.283,1.185,1.112,1.066,1.047,1.055,1.088,1.14,1.209,1.287,1.369,1.45,1.523,1.584,1.627,1.651,1.653,1.633,1.592,1.531,1.455,1.367,1.273,1.177,1.085,1.002,0.933,0.882,0.852,0.843,0.857,0.893,0.949,1.022,1.107,1.201,1.299,1.395,1.485,1.566,1.632,1.683,1.716,1.731,1.729,1.712,1.683,1.645,1.602,1.559,1.521,1.491,1.473,1.47,1.483,1.513,1.561,1.624,1.7,1.785,1.875,1.965,2.05,2.124,2.184,2.224,2.242,2.235,2.202,2.144,2.061,1.956,1.834,1.699,1.557,1.414,1.277,1.15,1.041,0.954,0.893,0.861,0.861,0.891,0.952,1.041,1.155,1.288,1.436,1.594,1.753,1.91,2.057,2.188,2.301,2.389,2.452,2.486,2.492,2.469,2.421,2.348,2.254,2.144,2.021,1.89,1.756,1.623,1.495,1.376,1.269,1.178,1.103,1.047,1.01,0.993,0.995,1.015,1.053,1.107,1.175,1.255,1.345,1.444,1.548,1.655,1.763,1.869,1.971,2.065,2.15,2.223,2.281,2.323,2.346,2.35,2.332,2.294,2.236,2.157,2.061,1.95,1.826,1.694,1.559,1.424,1.295,1.177,1.076,0.994,0.937,0.906,0.905,0.934,0.993,1.08,1.192,1.325,1.473,1.632,1.795,1.953,2.102,2.233,2.341,2.421,2.469,2.482,2.459,2.401,2.31,2.19,2.045,1.883,1.71,1.533,1.362,1.203,1.063,0.95,0.867,0.819,0.808,0.835,0.897,0.992,1.115,1.26,1.421,1.59,1.759,1.92,2.067,2.192,1.846,1.921,1.99,2.05,2.095,2.122,2.128,2.11,2.069,2.003,1.916,1.81,1.69,1.56,1.426,1.296,1.175,1.07,0.986,0.928,0.901,0.905,0.943,1.013,1.112,1.237,1.382,1.542,1.709,1.876,2.035,2.179,2.301,2.398,2.463,2.494,2.491,2.454,2.385,2.289,2.169,2.032,1.885,1.734,1.587,1.45,1.329,1.229,1.153,1.104,1.082,1.085,1.113,1.161,1.225,1.299,1.377,1.454,1.524,1.582,1.624,1.647,1.648,1.627,1.585,1.524,1.447,1.358,1.263,1.165,1.072,0.987,0.916,0.863,0.831,0.82,0.833,0.869,0.925,0.998,1.086,1.183,1.285,1.386,1.483,1.57,1.644,1.703,1.744,1.766,1.771,1.761,1.736,1.702,1.661,1.619,1.579,1.546,1.523,1.513,1.519,1.541,1.58,1.633,1.699,1.775,1.857,1.939,2.018,2.088,2.145,2.184,2.203,2.198,2.169,2.116,2.039,1.941,1.826,1.699,1.563,1.426,1.294,1.171,1.064,0.978,0.917,0.884,0.88,0.906,0.962,1.046,1.154,1.281,1.424,1.577,1.732,1.886,2.031,2.162,2.275,2.366,2.432,2.471,2.482,2.466,2.423,2.357,2.271,2.167,2.051,1.926,1.798,1.669,1.546,1.431,1.327,1.238,1.166,1.112,1.077,1.061,1.065,1.087,1.126,1.182,1.252,1.334,1.426,1.525,1.63,1.737,1.844,1.947,2.046,2.135,2.214,2.28,2.33,2.363,2.376,2.369,2.341,2.293,2.224,2.136,2.032,1.913,1.784,1.649,1.511,1.376,1.25,1.136,1.039,0.964,0.915,0.893,0.901,0.939,1.006,1.1,1.219,1.357,1.509,1.67,1.832,1.989,2.134,2.261,2.363,2.436,2.477,2.482,2.452,2.387,2.29,2.165,2.017,1.852,1.678,1.502,1.333,1.177,1.042,0.934,0.857,0.816,0.811,0.843,0.911,1.01,1.137,1.284,1.446,1.615,1.783,1.942,2.085,2.206,1.842,1.919,1.991,2.053,2.102,2.132,2.141,2.127,2.088,2.025,1.939,1.834,1.713,1.582,1.447,1.314,1.189,1.079,0.99,0.927,0.894,0.892,0.924,0.988,1.083,1.204,1.347,1.505,1.671,1.839,2.0,2.147,2.275,2.377,2.448,2.487,2.492,2.462,2.401,2.312,2.198,2.067,1.925,1.777,1.633,1.497,1.376,1.275,1.197,1.145,1.119,1.118,1.142,1.185,1.245,1.315,1.39,1.464,1.531,1.587,1.628,1.649,1.65,1.628,1.586,1.525,1.447,1.358,1.261,1.162,1.067,0.981,0.908,0.853,0.818,0.806,0.818,0.852,0.908,0.982,1.072,1.172,1.277,1.384,1.486,1.58,1.661,1.727,1.775,1.805,1.817,1.812,1.792,1.761,1.722,1.68,1.639,1.602,1.574,1.557,1.555,1.568,1.597,1.64,1.696,1.763,1.836,1.911,1.983,2.049,2.103,2.141,2.161,2.158,2.134,2.086,2.015,1.925,1.818,1.698,1.57,1.439,1.312,1.194,1.091,1.006,0.945,0.91,0.903,0.926,0.977,1.054,1.156,1.277,1.414,1.56,1.711,1.86,2.003,2.133,2.245,2.338,2.406,2.449,2.465,2.454,2.419,2.36,2.281,2.185,2.076,1.958,1.836,1.714,1.596,1.485,1.386,1.301,1.232,1.181,1.149,1.135,1.141,1.166,1.207,1.264,1.336,1.419,1.512,1.611,1.715,1.821,1.925,2.026,2.12,2.204,2.276,2.333,2.374,2.397,2.4,2.382,2.344,2.284,2.206,2.109,1.996,1.871,1.737,1.599,1.461,1.327,1.203,1.094,1.003,0.936,0.895,0.882,0.899,0.946,1.022,1.124,1.249,1.392,1.547,1.709,1.871,2.026,2.168,2.289,2.385,2.451,2.483,2.481,2.444,2.372,2.269,2.138,1.987,1.82,1.645,1.471,1.303,1.152,1.021,0.919,0.849,0.814,0.816,0.854,0.926,1.03,1.16,1.31,1.473,1.641,1.807,1.963,2.103,2.22,1.836,1.915,1.99,2.056,2.108,2.142,2.154,2.143,2.107,2.046,1.962,1.858,1.738,1.606,1.469,1.333,1.205,1.091,0.997,0.928,0.888,0.881,0.906,0.965,1.054,1.171,1.31,1.466,1.632,1.8,1.963,2.114,2.246,2.353,2.431,2.477,2.489,2.468,2.414,2.332,2.226,2.1,1.963,1.82,1.678,1.544,1.423,1.322,1.242,1.187,1.158,1.154,1.174,1.213,1.269,1.335,1.407,1.478,1.544,1.598,1.638,1.658,1.658,1.637,1.595,1.533,1.455,1.365,1.268,1.168,1.072,0.984,0.909,0.851,0.814,0.8,0.81,0.843,0.899,0.974,1.064,1.167,1.276,1.387,1.494,1.594,1.682,1.755,1.811,1.847,1.865,1.866,1.851,1.822,1.785,1.742,1.699,1.658,1.625,1.601,1.59,1.594,1.613,1.646,1.692,1.748,1.812,1.879,1.945,2.006,2.057,2.094,2.115,2.115,2.095,2.053,1.99,1.907,1.808,1.696,1.577,1.454,1.333,1.22,1.12,1.038,0.977,0.941,0.932,0.95,0.995,1.067,1.161,1.275,1.405,1.545,1.69,1.834,1.972,2.1,2.212,2.304,2.374,2.42,2.441,2.436,2.407,2.355,2.283,2.195,2.093,1.983,1.869,1.754,1.642,1.538,1.444,1.364,1.3,1.253,1.224,1.214,1.222,1.249,1.293,1.352,1.424,1.508,1.601,1.7,1.803,1.906,2.007,2.103,2.191,2.268,2.333,2.381,2.413,2.425,2.417,2.388,2.338,2.269,2.18,2.075,1.955,1.824,1.687,1.546,1.408,1.276,1.156,1.052,0.969,0.91,0.878,0.874,0.901,0.957,1.041,1.151,1.282,1.429,1.588,1.751,1.912,2.064,2.201,2.316,2.405,2.464,2.488,2.478,2.433,2.354,2.245,2.11,1.955,1.786,1.611,1.438,1.274,1.126,1.001,0.905,0.841,0.813,0.821,0.865,0.944,1.052,1.185,1.337,1.5,1.668,1.832,1.985,2.121,2.233,1.829,1.911,1.989,2.058,2.113,2.151,2.167,2.159,2.126,2.069,1.987,1.884,1.764,1.632,1.493,1.355,1.223,1.104,1.005,0.93,0.884,0.87,0.89,0.942,1.026,1.138,1.273,1.427,1.591,1.759,1.924,2.078,2.214,2.326,2.411,2.464,2.484,2.47,2.425,2.35,2.251,2.132,2.0,1.861,1.722,1.59,1.471,1.369,1.288,1.231,1.199,1.192,1.208,1.244,1.297,1.36,1.429,1.498,1.562,1.615,1.653,1.674,1.674,1.653,1.611,1.549,1.472,1.382,1.284,1.183,1.085,0.995,0.918,0.859,0.819,0.803,0.811,0.843,0.898,0.972,1.064,1.168,1.28,1.395,1.508,1.613,1.707,1.787,1.849,1.892,1.916,1.922,1.91,1.885,1.849,1.805,1.759,1.715,1.675,1.644,1.625,1.619,1.627,1.649,1.685,1.731,1.785,1.844,1.904,1.959,2.008,2.044,2.065,2.069,2.053,2.017,1.962,1.888,1.798,1.695,1.584,1.469,1.356,1.249,1.153,1.073,1.013,0.976,0.964,0.978,1.018,1.083,1.17,1.277,1.399,1.531,1.669,1.807,1.94,2.064,2.174,2.266,2.337,2.385,2.409,2.409,2.386,2.341,2.277,2.197,2.104,2.002,1.895,1.788,1.684,1.587,1.5,1.425,1.366,1.324,1.299,1.293,1.305,1.335,1.381,1.441,1.515,1.599,1.691,1.789,1.89,1.99,2.086,2.177,2.258,2.328,2.383,2.422,2.443,2.444,2.425,2.385,2.325,2.245,2.147,2.034,1.908,1.772,1.632,1.49,1.353,1.224,1.109,1.012,0.936,0.886,0.863,0.87,0.907,0.972,1.065,1.181,1.318,1.47,1.63,1.794,1.953,2.102,2.234,2.343,2.425,2.475,2.491,2.473,2.419,2.334,2.218,2.079,1.921,1.75,1.576,1.404,1.244,1.1,0.981,0.891,0.834,0.813,0.828,0.879,0.962,1.075,1.211,1.365,1.529,1.696,1.857,2.007,2.139,2.246,1.821,1.906,1.986,2.059,2.118,2.159,2.179,2.175,2.146,2.091,2.012,1.911,1.791,1.659,1.519,1.378,1.243,1.12,1.015,0.934,0.882,0.862,0.874,0.92,0.998,1.105,1.236,1.387,1.549,1.717,1.883,2.039,2.179,2.297,2.388,2.448,2.475,2.469,2.432,2.365,2.273,2.161,2.034,1.9,1.765,1.636,1.517,1.416,1.334,1.276,1.242,1.232,1.245,1.278,1.327,1.388,1.455,1.522,1.584,1.637,1.675,1.696,1.696,1.676,1.634,1.574,1.497,1.407,1.309,1.207,1.108,1.016,0.937,0.875,0.834,0.815,0.821,0.851,0.904,0.979,1.071,1.176,1.29,1.409,1.525,1.636,1.736,1.821,1.889,1.939,1.968,1.978,1.971,1.948,1.912,1.868,1.82,1.77,1.725,1.687,1.658,1.642,1.64,1.651,1.675,1.711,1.756,1.807,1.859,1.91,1.955,1.99,2.013,2.019,2.009,1.979,1.932,1.867,1.786,1.693,1.592,1.486,1.38,1.28,1.189,1.112,1.054,1.016,1.002,1.012,1.046,1.104,1.183,1.282,1.395,1.519,1.649,1.78,1.907,2.026,2.133,2.223,2.294,2.343,2.37,2.375,2.357,2.318,2.262,2.189,2.105,2.012,1.914,1.815,1.719,1.63,1.55,1.483,1.43,1.393,1.374,1.372,1.388,1.42,1.468,1.531,1.605,1.689,1.78,1.876,1.974,2.07,2.161,2.245,2.319,2.38,2.426,2.455,2.465,2.455,2.425,2.374,2.303,2.214,2.108,1.987,1.855,1.716,1.573,1.432,1.297,1.172,1.063,0.973,0.906,0.865,0.853,0.87,0.916,0.991,1.092,1.216,1.358,1.513,1.675,1.838,1.995,2.14,2.266,2.369,2.443,2.484,2.492,2.465,2.404,2.311,2.19,2.046,1.885,1.714,1.54,1.37,1.213,1.075,0.962,0.879,0.829,0.815,0.837,0.894,0.983,1.1,1.239,1.394,1.558,1.724,1.883,2.029,2.156,2.258,1.812,1.899,1.983,2.058,2.121,2.167,2.191,2.191,2.165,2.114,2.037,1.938,1.82,1.687,1.546,1.403,1.265,1.137,1.027,0.941,0.882,0.855,0.86,0.9,0.971,1.072,1.199,1.346,1.506,1.674,1.84,1.998,2.142,2.265,2.361,2.428,2.463,2.465,2.436,2.377,2.292,2.187,2.066,1.937,1.806,1.68,1.563,1.462,1.38,1.321,1.285,1.273,1.284,1.314,1.361,1.419,1.484,1.55,1.611,1.664,1.702,1.723,1.725,1.705,1.665,1.606,1.529,1.44,1.342,1.24,1.14,1.047,0.966,0.901,0.857,0.836,0.839,0.867,0.919,0.992,1.084,1.19,1.306,1.427,1.547,1.662,1.767,1.858,1.932,1.987,2.021,2.036,2.032,2.01,1.976,1.93,1.879,1.825,1.774,1.728,1.69,1.664,1.651,1.651,1.664,1.689,1.724,1.766,1.812,1.857,1.899,1.933,1.957,1.967,1.961,1.939,1.9,1.844,1.773,1.691,1.599,1.503,1.406,1.313,1.228,1.155,1.098,1.06,1.044,1.05,1.079,1.13,1.201,1.291,1.395,1.51,1.631,1.754,1.874,1.987,2.089,2.176,2.245,2.295,2.324,2.332,2.319,2.287,2.237,2.173,2.097,2.012,1.924,1.834,1.747,1.666,1.594,1.535,1.489,1.458,1.444,1.447,1.467,1.503,1.553,1.617,1.692,1.776,1.866,1.959,2.053,2.144,2.229,2.306,2.372,2.424,2.46,2.479,2.478,2.457,2.416,2.354,2.273,2.175,2.061,1.934,1.797,1.655,1.512,1.372,1.24,1.121,1.018,0.936,0.879,0.848,0.846,0.874,0.93,1.014,1.123,1.253,1.4,1.558,1.721,1.883,2.038,2.178,2.298,2.393,2.459,2.492,2.49,2.455,2.385,2.286,2.159,2.011,1.847,1.676,1.503,1.336,1.183,1.051,0.944,0.868,0.825,0.819,0.848,0.911,1.005,1.126,1.268,1.424,1.588,1.752,1.909,2.051,2.173,2.27,1.802,1.891,1.978,2.057,2.124,2.173,2.202,2.206,2.185,2.137,2.063,1.966,1.849,1.717,1.575,1.43,1.289,1.157,1.042,0.95,0.884,0.85,0.848,0.88,0.945,1.041,1.162,1.305,1.463,1.629,1.795,1.955,2.102,2.229,2.332,2.405,2.447,2.457,2.436,2.385,2.308,2.21,2.096,1.972,1.845,1.722,1.608,1.507,1.426,1.366,1.328,1.315,1.323,1.352,1.396,1.453,1.516,1.581,1.642,1.695,1.734,1.756,1.759,1.741,1.703,1.645,1.57,1.481,1.383,1.281,1.18,1.086,1.003,0.936,0.889,0.865,0.865,0.891,0.94,1.012,1.103,1.209,1.327,1.449,1.573,1.691,1.801,1.897,1.976,2.035,2.075,2.093,2.092,2.072,2.038,1.992,1.937,1.879,1.821,1.767,1.721,1.684,1.66,1.649,1.651,1.665,1.69,1.723,1.762,1.802,1.84,1.874,1.898,1.912,1.911,1.896,1.866,1.82,1.76,1.688,1.607,1.521,1.433,1.348,1.269,1.201,1.146,1.109,1.091,1.093,1.117,1.161,1.224,1.304,1.398,1.503,1.614,1.728,1.84,1.946,2.042,2.125,2.192,2.241,2.271,2.282,2.273,2.246,2.203,2.146,2.078,2.003,1.923,1.843,1.765,1.694,1.631,1.579,1.541,1.517,1.509,1.517,1.541,1.581,1.634,1.699,1.774,1.857,1.945,2.035,2.125,2.21,2.289,2.359,2.416,2.458,2.484,2.492,2.48,2.448,2.396,2.325,2.235,2.128,2.007,1.875,1.735,1.591,1.449,1.311,1.184,1.071,0.976,0.903,0.855,0.835,0.844,0.882,0.949,1.042,1.158,1.295,1.446,1.606,1.77,1.93,2.08,2.215,2.329,2.416,2.472,2.496,2.486,2.441,2.364,2.258,2.126,1.974,1.808,1.636,1.465,1.302,1.153,1.027,0.927,0.858,0.823,0.824,0.86,0.929,1.029,1.154,1.298,1.456,1.619,1.781,1.934,2.073,2.189,2.28,1.79,1.882,1.972,2.055,2.125,2.179,2.212,2.221,2.204,2.16,2.09,1.995,1.88,1.748,1.606,1.459,1.315,1.179,1.059,0.961,0.889,0.847,0.838,0.863,0.921,1.01,1.126,1.264,1.419,1.583,1.749,1.911,2.06,2.191,2.299,2.379,2.428,2.446,2.432,2.389,2.32,2.229,2.122,2.004,1.882,1.762,1.65,1.551,1.47,1.41,1.372,1.357,1.363,1.39,1.433,1.488,1.551,1.615,1.676,1.729,1.77,1.793,1.798,1.782,1.746,1.69,1.617,1.529,1.432,1.33,1.229,1.133,1.048,0.979,0.929,0.902,0.899,0.922,0.969,1.038,1.128,1.234,1.351,1.476,1.601,1.723,1.836,1.936,2.019,2.084,2.127,2.149,2.151,2.133,2.099,2.051,1.993,1.931,1.866,1.804,1.749,1.702,1.667,1.644,1.635,1.638,1.653,1.678,1.709,1.744,1.779,1.811,1.837,1.854,1.859,1.851,1.829,1.794,1.745,1.684,1.615,1.54,1.462,1.385,1.313,1.25,1.199,1.162,1.143,1.142,1.16,1.196,1.251,1.322,1.406,1.5,1.601,1.705,1.807,1.905,1.994,2.072,2.135,2.182,2.212,2.224,2.218,2.196,2.159,2.11,2.05,1.983,1.913,1.842,1.774,1.711,1.657,1.614,1.584,1.567,1.566,1.58,1.608,1.651,1.707,1.773,1.849,1.93,2.016,2.103,2.188,2.267,2.339,2.401,2.449,2.482,2.498,2.495,2.472,2.43,2.367,2.286,2.188,2.074,1.947,1.811,1.669,1.525,1.384,1.25,1.128,1.022,0.936,0.873,0.836,0.827,0.847,0.896,0.972,1.074,1.198,1.34,1.494,1.656,1.819,1.977,2.123,2.252,2.358,2.436,2.484,2.498,2.479,2.425,2.341,2.227,2.09,1.935,1.768,1.596,1.427,1.267,1.124,1.004,0.911,0.85,0.823,0.831,0.874,0.95,1.054,1.183,1.33,1.488,1.65,1.81,1.96,2.094,2.205,2.29,1.777,1.871,1.964,2.051,2.125,2.184,2.221,2.235,2.222,2.183,2.116,2.025,1.912,1.781,1.639,1.49,1.343,1.204,1.079,0.974,0.895,0.846,0.83,0.847,0.898,0.98,1.09,1.224,1.374,1.536,1.702,1.864,2.016,2.15,2.263,2.349,2.405,2.431,2.425,2.39,2.329,2.245,2.144,2.032,1.915,1.799,1.69,1.593,1.513,1.453,1.414,1.398,1.403,1.429,1.47,1.525,1.586,1.651,1.713,1.767,1.809,1.835,1.842,1.829,1.795,1.741,1.67,1.584,1.488,1.387,1.285,1.188,1.101,1.03,0.977,0.947,0.941,0.96,1.003,1.07,1.158,1.263,1.38,1.505,1.632,1.756,1.872,1.975,2.063,2.131,2.178,2.203,2.207,2.191,2.157,2.108,2.047,1.98,1.909,1.84,1.775,1.718,1.672,1.638,1.617,1.61,1.615,1.63,1.654,1.683,1.715,1.746,1.773,1.793,1.804,1.804,1.791,1.766,1.729,1.68,1.623,1.559,1.491,1.424,1.36,1.302,1.254,1.219,1.199,1.195,1.208,1.238,1.284,1.345,1.418,1.501,1.591,1.683,1.776,1.864,1.945,2.016,2.075,2.119,2.147,2.16,2.156,2.138,2.106,2.063,2.011,1.953,1.891,1.83,1.771,1.718,1.674,1.639,1.617,1.608,1.613,1.633,1.666,1.712,1.77,1.838,1.914,1.994,2.077,2.16,2.24,2.314,2.378,2.431,2.471,2.494,2.499,2.486,2.453,2.4,2.329,2.239,2.133,2.013,1.881,1.742,1.599,1.457,1.319,1.19,1.075,0.977,0.9,0.848,0.822,0.824,0.855,0.915,1.0,1.111,1.241,1.388,1.545,1.708,1.87,2.024,2.165,2.287,2.385,2.454,2.492,2.497,2.468,2.406,2.314,2.194,2.052,1.894,1.726,1.555,1.388,1.233,1.096,0.982,0.897,0.844,0.825,0.841,0.891,0.972,1.082,1.214,1.362,1.521,1.682,1.839,1.986,2.114,2.22,2.299,1.763,1.859,1.955,2.045,2.124,2.187,2.229,2.248,2.24,2.205,2.143,2.055,1.944,1.815,1.673,1.523,1.374,1.231,1.101,0.99,0.905,0.848,0.824,0.834,0.877,0.952,1.055,1.183,1.33,1.489,1.653,1.816,1.969,2.107,2.224,2.316,2.379,2.412,2.414,2.387,2.333,2.257,2.163,2.057,1.945,1.833,1.727,1.632,1.553,1.493,1.455,1.438,1.442,1.467,1.508,1.561,1.623,1.688,1.751,1.806,1.85,1.879,1.889,1.879,1.848,1.797,1.729,1.645,1.551,1.45,1.348,1.25,1.162,1.088,1.032,0.998,0.988,1.003,1.044,1.108,1.193,1.295,1.411,1.536,1.664,1.789,1.908,2.014,2.105,2.176,2.227,2.255,2.261,2.246,2.212,2.161,2.098,2.026,1.949,1.872,1.798,1.732,1.675,1.63,1.598,1.579,1.574,1.581,1.597,1.621,1.65,1.679,1.707,1.731,1.747,1.755,1.751,1.737,1.711,1.675,1.63,1.578,1.522,1.464,1.408,1.357,1.314,1.281,1.26,1.253,1.261,1.284,1.322,1.373,1.435,1.506,1.584,1.665,1.746,1.824,1.896,1.959,2.012,2.051,2.077,2.089,2.087,2.072,2.044,2.007,1.962,1.912,1.859,1.807,1.757,1.714,1.678,1.653,1.639,1.638,1.65,1.675,1.713,1.763,1.824,1.892,1.968,2.047,2.127,2.206,2.281,2.348,2.405,2.45,2.48,2.494,2.489,2.466,2.423,2.361,2.281,2.183,2.071,1.946,1.811,1.671,1.528,1.388,1.254,1.132,1.024,0.935,0.869,0.827,0.813,0.827,0.869,0.939,1.034,1.152,1.288,1.439,1.599,1.761,1.921,2.071,2.206,2.32,2.41,2.47,2.498,2.493,2.454,2.384,2.284,2.158,2.012,1.852,1.683,1.513,1.35,1.199,1.068,0.961,0.884,0.839,0.828,0.852,0.909,0.997,1.111,1.246,1.396,1.555,1.714,1.869,2.011,2.134,2.234,2.306,1.747,1.846,1.945,2.038,2.121,2.189,2.236,2.26,2.258,2.227,2.169,2.085,1.977,1.85,1.708,1.558,1.406,1.26,1.125,1.009,0.917,0.853,0.821,0.822,0.858,0.925,1.022,1.144,1.286,1.442,1.604,1.766,1.921,2.062,2.183,2.28,2.349,2.389,2.399,2.38,2.334,2.265,2.178,2.078,1.971,1.864,1.761,1.669,1.591,1.532,1.493,1.476,1.48,1.504,1.544,1.598,1.66,1.725,1.789,1.847,1.894,1.925,1.938,1.932,1.905,1.858,1.792,1.711,1.618,1.519,1.417,1.318,1.228,1.152,1.093,1.056,1.042,1.053,1.089,1.149,1.231,1.331,1.445,1.568,1.696,1.822,1.942,2.051,2.145,2.219,2.273,2.303,2.311,2.297,2.263,2.211,2.145,2.069,1.986,1.902,1.819,1.743,1.675,1.619,1.577,1.547,1.532,1.53,1.539,1.557,1.582,1.611,1.64,1.667,1.689,1.704,1.71,1.706,1.692,1.669,1.636,1.597,1.552,1.505,1.458,1.414,1.376,1.345,1.325,1.316,1.319,1.336,1.365,1.406,1.457,1.517,1.582,1.651,1.72,1.786,1.848,1.902,1.948,1.982,2.004,2.014,2.012,1.998,1.975,1.942,1.903,1.86,1.816,1.772,1.732,1.698,1.672,1.655,1.65,1.656,1.675,1.706,1.749,1.802,1.865,1.935,2.01,2.087,2.165,2.24,2.309,2.369,2.419,2.456,2.477,2.481,2.467,2.434,2.383,2.312,2.224,2.12,2.002,1.874,1.737,1.596,1.456,1.319,1.191,1.076,0.977,0.898,0.842,0.813,0.81,0.835,0.889,0.968,1.072,1.197,1.339,1.493,1.654,1.816,1.972,2.117,2.245,2.352,2.432,2.482,2.5,2.485,2.437,2.358,2.251,2.12,1.97,1.808,1.639,1.471,1.312,1.166,1.041,0.942,0.873,0.837,0.834,0.866,0.93,1.023,1.141,1.279,1.431,1.589,1.747,1.898,2.035,2.153,2.247,2.313,1.73,1.831,1.932,2.029,2.117,2.189,2.242,2.271,2.274,2.249,2.196,2.116,2.011,1.886,1.745,1.595,1.441,1.292,1.153,1.031,0.932,0.861,0.821,0.814,0.841,0.9,0.99,1.106,1.243,1.394,1.554,1.716,1.871,2.014,2.139,2.241,2.316,2.363,2.38,2.368,2.33,2.269,2.188,2.095,1.993,1.89,1.791,1.702,1.626,1.567,1.529,1.512,1.516,1.539,1.579,1.633,1.695,1.762,1.828,1.888,1.937,1.972,1.989,1.987,1.964,1.921,1.859,1.781,1.69,1.592,1.49,1.391,1.3,1.221,1.159,1.118,1.1,1.106,1.138,1.194,1.271,1.368,1.479,1.601,1.728,1.854,1.975,2.086,2.181,2.258,2.314,2.347,2.357,2.344,2.31,2.256,2.188,2.107,2.019,1.928,1.837,1.752,1.674,1.608,1.554,1.514,1.489,1.478,1.48,1.493,1.514,1.541,1.571,1.601,1.629,1.651,1.667,1.674,1.672,1.662,1.642,1.616,1.583,1.547,1.51,1.473,1.44,1.413,1.393,1.383,1.382,1.393,1.414,1.445,1.485,1.532,1.584,1.64,1.696,1.751,1.802,1.846,1.883,1.911,1.928,1.935,1.932,1.919,1.898,1.869,1.836,1.8,1.763,1.727,1.696,1.671,1.653,1.645,1.648,1.662,1.687,1.724,1.771,1.828,1.893,1.964,2.039,2.115,2.189,2.26,2.323,2.378,2.42,2.449,2.461,2.457,2.434,2.392,2.332,2.254,2.16,2.05,1.929,1.798,1.661,1.521,1.384,1.252,1.131,1.024,0.934,0.866,0.822,0.804,0.813,0.85,0.914,1.003,1.115,1.247,1.393,1.55,1.711,1.87,2.023,2.162,2.283,2.381,2.451,2.491,2.499,2.473,2.416,2.329,2.215,2.079,1.926,1.762,1.594,1.429,1.274,1.134,1.017,0.925,0.865,0.837,0.843,0.882,0.953,1.051,1.174,1.314,1.466,1.624,1.779,1.926,2.059,2.171,2.258,2.317,1.712,1.814,1.918,2.019,2.111,2.188,2.246,2.281,2.289,2.27,2.222,2.146,2.045,1.922,1.783,1.633,1.478,1.326,1.183,1.056,0.95,0.872,0.823,0.808,0.827,0.878,0.96,1.069,1.2,1.347,1.504,1.664,1.82,1.965,2.093,2.199,2.28,2.333,2.357,2.353,2.322,2.268,2.195,2.107,2.011,1.913,1.817,1.731,1.657,1.6,1.562,1.545,1.548,1.571,1.612,1.666,1.729,1.797,1.865,1.928,1.981,2.019,2.041,2.043,2.024,1.985,1.927,1.853,1.765,1.668,1.568,1.469,1.376,1.295,1.23,1.184,1.162,1.163,1.19,1.241,1.314,1.406,1.514,1.634,1.759,1.885,2.006,2.117,2.214,2.293,2.351,2.386,2.397,2.385,2.351,2.297,2.226,2.142,2.049,1.951,1.853,1.758,1.671,1.594,1.53,1.48,1.446,1.426,1.421,1.428,1.445,1.471,1.502,1.535,1.568,1.598,1.623,1.641,1.651,1.653,1.647,1.634,1.614,1.589,1.562,1.534,1.507,1.483,1.465,1.453,1.45,1.454,1.467,1.489,1.517,1.552,1.592,1.634,1.677,1.719,1.758,1.792,1.819,1.839,1.851,1.854,1.848,1.835,1.815,1.79,1.761,1.731,1.7,1.673,1.649,1.632,1.623,1.623,1.634,1.655,1.687,1.729,1.781,1.841,1.908,1.98,2.054,2.128,2.2,2.266,2.324,2.373,2.408,2.429,2.434,2.421,2.39,2.34,2.273,2.189,2.089,1.975,1.851,1.719,1.583,1.446,1.313,1.188,1.074,0.976,0.897,0.84,0.808,0.802,0.823,0.871,0.946,1.044,1.163,1.3,1.45,1.608,1.769,1.925,2.073,2.206,2.318,2.406,2.467,2.496,2.493,2.458,2.392,2.297,2.177,2.036,1.88,1.716,1.549,1.387,1.237,1.103,0.993,0.91,0.859,0.839,0.854,0.901,0.978,1.082,1.208,1.35,1.503,1.659,1.812,1.955,2.082,2.188,2.268,2.32,1.692,1.796,1.903,2.007,2.103,2.185,2.248,2.289,2.304,2.29,2.247,2.176,2.079,1.96,1.822,1.672,1.517,1.362,1.215,1.083,0.971,0.885,0.829,0.805,0.815,0.858,0.932,1.034,1.159,1.301,1.455,1.613,1.768,1.914,2.044,2.155,2.241,2.3,2.331,2.334,2.31,2.263,2.196,2.115,2.025,1.931,1.839,1.755,1.683,1.628,1.591,1.574,1.578,1.601,1.641,1.696,1.76,1.83,1.9,1.966,2.022,2.065,2.091,2.098,2.085,2.051,1.997,1.926,1.842,1.747,1.648,1.549,1.455,1.372,1.303,1.254,1.226,1.223,1.244,1.289,1.357,1.445,1.549,1.665,1.788,1.912,2.032,2.144,2.242,2.322,2.382,2.419,2.432,2.421,2.387,2.332,2.259,2.172,2.074,1.97,1.865,1.762,1.666,1.579,1.505,1.446,1.402,1.374,1.361,1.363,1.377,1.401,1.432,1.468,1.506,1.543,1.577,1.606,1.629,1.644,1.651,1.651,1.644,1.631,1.614,1.595,1.575,1.556,1.54,1.527,1.521,1.52,1.526,1.538,1.555,1.578,1.605,1.633,1.663,1.692,1.718,1.74,1.757,1.769,1.773,1.771,1.762,1.748,1.728,1.705,1.68,1.654,1.63,1.609,1.593,1.584,1.583,1.591,1.608,1.637,1.675,1.722,1.778,1.842,1.911,1.983,2.056,2.129,2.197,2.259,2.313,2.355,2.384,2.397,2.394,2.374,2.336,2.28,2.206,2.116,2.012,1.896,1.771,1.639,1.505,1.373,1.245,1.127,1.022,0.934,0.866,0.821,0.801,0.807,0.84,0.899,0.983,1.09,1.216,1.358,1.51,1.668,1.827,1.98,2.122,2.247,2.351,2.429,2.478,2.497,2.484,2.439,2.364,2.261,2.135,1.99,1.833,1.668,1.504,1.346,1.2,1.074,0.972,0.898,0.855,0.844,0.867,0.921,1.005,1.114,1.243,1.387,1.54,1.694,1.844,1.982,2.104,2.203,2.277,2.322,1.67,1.776,1.885,1.993,2.093,2.18,2.249,2.296,2.316,2.309,2.272,2.206,2.114,1.998,1.863,1.714,1.557,1.401,1.25,1.113,0.996,0.902,0.838,0.806,0.807,0.841,0.907,1.001,1.119,1.256,1.405,1.561,1.715,1.861,1.994,2.108,2.199,2.264,2.301,2.311,2.294,2.254,2.194,2.119,2.034,1.945,1.857,1.776,1.706,1.652,1.615,1.599,1.603,1.626,1.667,1.722,1.788,1.86,1.932,2.001,2.062,2.109,2.14,2.152,2.144,2.115,2.067,2.0,1.919,1.827,1.729,1.63,1.536,1.45,1.379,1.325,1.293,1.283,1.299,1.338,1.4,1.483,1.582,1.694,1.813,1.935,2.055,2.166,2.264,2.346,2.407,2.446,2.46,2.45,2.416,2.361,2.287,2.197,2.095,1.986,1.874,1.764,1.659,1.563,1.48,1.411,1.358,1.322,1.303,1.299,1.309,1.331,1.363,1.402,1.444,1.489,1.531,1.571,1.605,1.633,1.654,1.667,1.673,1.673,1.667,1.656,1.644,1.63,1.616,1.604,1.595,1.589,1.588,1.591,1.598,1.609,1.623,1.638,1.654,1.669,1.682,1.692,1.699,1.7,1.697,1.689,1.676,1.659,1.639,1.616,1.594,1.572,1.552,1.538,1.528,1.526,1.532,1.548,1.572,1.607,1.651,1.703,1.763,1.83,1.9,1.973,2.046,2.116,2.182,2.24,2.288,2.325,2.347,2.355,2.345,2.318,2.273,2.211,2.133,2.039,1.932,1.815,1.69,1.56,1.429,1.302,1.181,1.071,0.976,0.899,0.842,0.809,0.801,0.819,0.864,0.933,1.026,1.141,1.272,1.418,1.572,1.73,1.885,2.033,2.168,2.285,2.38,2.448,2.486,2.494,2.47,2.416,2.332,2.222,2.091,1.943,1.784,1.62,1.458,1.305,1.166,1.047,0.953,0.888,0.854,0.852,0.883,0.945,1.034,1.148,1.28,1.425,1.578,1.73,1.876,2.009,2.124,2.217,2.284,2.322,1.647,1.754,1.866,1.977,2.081,2.173,2.248,2.3,2.327,2.326,2.296,2.236,2.148,2.036,1.904,1.756,1.6,1.442,1.288,1.147,1.023,0.923,0.851,0.81,0.802,0.827,0.884,0.97,1.081,1.212,1.357,1.509,1.662,1.808,1.943,2.059,2.154,2.224,2.267,2.284,2.274,2.24,2.187,2.118,2.038,1.954,1.87,1.791,1.724,1.671,1.635,1.619,1.624,1.647,1.688,1.744,1.812,1.885,1.961,2.033,2.097,2.15,2.186,2.204,2.201,2.178,2.135,2.073,1.996,1.907,1.811,1.712,1.617,1.53,1.455,1.397,1.36,1.345,1.354,1.386,1.442,1.519,1.612,1.72,1.835,1.955,2.072,2.182,2.281,2.363,2.425,2.465,2.481,2.472,2.439,2.384,2.308,2.216,2.111,1.998,1.88,1.763,1.651,1.547,1.455,1.377,1.316,1.272,1.245,1.236,1.243,1.263,1.295,1.336,1.383,1.434,1.485,1.535,1.581,1.622,1.655,1.682,1.701,1.713,1.718,1.717,1.712,1.704,1.694,1.682,1.672,1.662,1.655,1.649,1.646,1.646,1.646,1.648,1.65,1.651,1.651,1.649,1.644,1.635,1.623,1.608,1.59,1.57,1.548,1.525,1.504,1.485,1.47,1.46,1.457,1.461,1.474,1.496,1.527,1.567,1.616,1.673,1.737,1.806,1.878,1.951,2.023,2.092,2.155,2.209,2.253,2.284,2.301,2.302,2.287,2.254,2.204,2.137,2.055,1.958,1.85,1.732,1.609,1.482,1.356,1.235,1.122,1.022,0.937,0.871,0.826,0.805,0.809,0.839,0.894,0.974,1.075,1.196,1.333,1.481,1.635,1.791,1.943,2.085,2.213,2.321,2.405,2.462,2.49,2.486,2.452,2.388,2.296,2.18,2.044,1.894,1.734,1.572,1.413,1.265,1.132,1.021,0.936,0.88,0.856,0.863,0.902,0.971,1.066,1.183,1.318,1.464,1.615,1.765,1.906,2.034,2.143,2.229,2.289,2.32,1.623,1.731,1.845,1.958,2.067,2.164,2.244,2.303,2.337,2.342,2.318,2.264,2.182,2.075,1.945,1.8,1.644,1.485,1.329,1.183,1.053,0.946,0.866,0.817,0.8,0.816,0.864,0.942,1.046,1.17,1.31,1.458,1.609,1.755,1.89,2.009,2.108,2.182,2.231,2.253,2.25,2.223,2.176,2.112,2.038,1.958,1.877,1.802,1.737,1.685,1.65,1.635,1.639,1.663,1.705,1.762,1.83,1.906,1.984,2.06,2.129,2.186,2.228,2.251,2.255,2.238,2.2,2.143,2.07,1.985,1.891,1.794,1.698,1.608,1.531,1.469,1.426,1.405,1.407,1.433,1.482,1.552,1.64,1.742,1.853,1.968,2.083,2.192,2.29,2.372,2.435,2.477,2.494,2.487,2.455,2.4,2.324,2.231,2.123,2.006,1.884,1.761,1.641,1.53,1.43,1.344,1.275,1.223,1.19,1.176,1.178,1.197,1.229,1.272,1.323,1.38,1.439,1.499,1.556,1.609,1.656,1.695,1.727,1.752,1.768,1.777,1.78,1.778,1.772,1.762,1.75,1.738,1.725,1.712,1.699,1.687,1.675,1.664,1.652,1.64,1.626,1.611,1.594,1.575,1.554,1.531,1.507,1.482,1.458,1.434,1.414,1.397,1.385,1.379,1.381,1.391,1.409,1.437,1.474,1.519,1.573,1.634,1.701,1.772,1.846,1.919,1.991,2.057,2.117,2.168,2.208,2.234,2.246,2.242,2.221,2.183,2.129,2.059,1.974,1.876,1.767,1.651,1.53,1.407,1.287,1.174,1.07,0.979,0.905,0.851,0.818,0.809,0.825,0.866,0.932,1.02,1.129,1.256,1.396,1.545,1.699,1.852,1.999,2.135,2.254,2.352,2.426,2.472,2.488,2.474,2.43,2.357,2.257,2.135,1.995,1.843,1.683,1.523,1.369,1.226,1.101,0.999,0.922,0.876,0.86,0.876,0.923,0.999,1.099,1.221,1.358,1.504,1.653,1.8,1.937,2.059,2.161,2.24,2.292,2.316,1.597,1.706,1.822,1.938,2.051,2.152,2.238,2.304,2.344,2.357,2.339,2.292,2.216,2.113,1.987,1.844,1.69,1.53,1.371,1.222,1.087,0.974,0.886,0.828,0.802,0.809,0.848,0.917,1.013,1.131,1.265,1.409,1.556,1.701,1.837,1.958,2.059,2.138,2.192,2.22,2.222,2.202,2.16,2.103,2.033,1.958,1.881,1.808,1.745,1.694,1.66,1.645,1.65,1.674,1.716,1.774,1.843,1.921,2.002,2.081,2.155,2.217,2.264,2.294,2.304,2.293,2.261,2.21,2.142,2.06,1.969,1.873,1.777,1.686,1.605,1.539,1.491,1.464,1.459,1.478,1.52,1.582,1.663,1.759,1.865,1.977,2.088,2.195,2.292,2.374,2.438,2.48,2.499,2.493,2.463,2.409,2.333,2.239,2.13,2.01,1.884,1.756,1.631,1.512,1.405,1.312,1.235,1.177,1.138,1.118,1.117,1.133,1.165,1.209,1.264,1.327,1.394,1.463,1.53,1.595,1.654,1.707,1.752,1.788,1.816,1.836,1.847,1.851,1.849,1.842,1.83,1.815,1.797,1.777,1.755,1.733,1.71,1.685,1.66,1.635,1.608,1.58,1.55,1.52,1.49,1.458,1.428,1.398,1.37,1.345,1.324,1.308,1.299,1.296,1.302,1.316,1.34,1.372,1.414,1.465,1.523,1.588,1.657,1.73,1.805,1.878,1.949,2.014,2.071,2.119,2.155,2.177,2.184,2.175,2.15,2.109,2.051,1.978,1.891,1.793,1.685,1.572,1.454,1.338,1.224,1.119,1.024,0.944,0.882,0.839,0.819,0.822,0.849,0.901,0.976,1.072,1.188,1.319,1.461,1.611,1.763,1.912,2.053,2.181,2.291,2.379,2.442,2.477,2.482,2.457,2.403,2.321,2.215,2.088,1.945,1.791,1.632,1.475,1.326,1.189,1.072,0.978,0.912,0.874,0.868,0.893,0.948,1.03,1.135,1.26,1.398,1.544,1.691,1.834,1.966,2.082,2.177,2.248,2.293,2.31,1.57,1.68,1.797,1.916,2.032,2.139,2.23,2.302,2.349,2.369,2.359,2.318,2.248,2.151,2.03,1.89,1.736,1.576,1.416,1.263,1.124,1.004,0.909,0.843,0.808,0.805,0.835,0.895,0.983,1.093,1.221,1.361,1.505,1.648,1.783,1.905,2.009,2.092,2.15,2.184,2.192,2.177,2.141,2.089,2.024,1.953,1.879,1.809,1.747,1.698,1.665,1.65,1.655,1.679,1.721,1.779,1.85,1.93,2.014,2.097,2.174,2.242,2.295,2.331,2.348,2.343,2.318,2.272,2.209,2.131,2.043,1.948,1.852,1.76,1.677,1.607,1.553,1.52,1.508,1.52,1.554,1.609,1.682,1.771,1.872,1.978,2.086,2.19,2.286,2.367,2.432,2.475,2.496,2.492,2.463,2.411,2.336,2.242,2.132,2.01,1.881,1.749,1.619,1.495,1.382,1.282,1.198,1.134,1.089,1.064,1.059,1.073,1.104,1.15,1.208,1.275,1.349,1.427,1.504,1.58,1.651,1.716,1.774,1.822,1.862,1.891,1.912,1.923,1.926,1.921,1.91,1.893,1.871,1.844,1.815,1.783,1.749,1.712,1.675,1.636,1.596,1.555,1.514,1.472,1.432,1.392,1.354,1.318,1.286,1.259,1.237,1.221,1.213,1.213,1.222,1.24,1.268,1.305,1.351,1.406,1.467,1.535,1.607,1.682,1.757,1.831,1.9,1.964,2.018,2.063,2.095,2.114,2.117,2.105,2.076,2.031,1.971,1.897,1.81,1.712,1.607,1.497,1.384,1.274,1.168,1.072,0.987,0.918,0.867,0.836,0.828,0.843,0.881,0.943,1.026,1.13,1.25,1.385,1.529,1.678,1.827,1.971,2.105,2.224,2.325,2.402,2.453,2.477,2.471,2.435,2.372,2.282,2.169,2.038,1.892,1.738,1.581,1.428,1.284,1.155,1.046,0.961,0.904,0.876,0.879,0.913,0.975,1.062,1.172,1.3,1.439,1.584,1.728,1.867,1.993,2.103,2.191,2.255,2.292,2.301,1.542,1.651,1.77,1.892,2.011,2.123,2.22,2.298,2.352,2.379,2.376,2.343,2.28,2.188,2.072,1.935,1.784,1.625,1.463,1.308,1.164,1.038,0.936,0.861,0.817,0.806,0.826,0.877,0.956,1.059,1.18,1.314,1.455,1.595,1.73,1.853,1.959,2.044,2.107,2.145,2.158,2.149,2.118,2.071,2.011,1.943,1.873,1.805,1.745,1.697,1.665,1.65,1.654,1.678,1.72,1.779,1.851,1.932,2.019,2.105,2.187,2.26,2.319,2.361,2.385,2.387,2.368,2.329,2.271,2.198,2.112,2.02,1.924,1.831,1.745,1.671,1.612,1.572,1.554,1.557,1.583,1.63,1.696,1.778,1.872,1.973,2.077,2.178,2.271,2.352,2.417,2.462,2.484,2.482,2.456,2.405,2.332,2.239,2.13,2.007,1.876,1.741,1.608,1.479,1.36,1.254,1.165,1.094,1.043,1.014,1.005,1.017,1.047,1.094,1.154,1.226,1.306,1.391,1.478,1.564,1.647,1.724,1.793,1.854,1.904,1.944,1.973,1.992,2.0,1.999,1.988,1.97,1.945,1.914,1.877,1.836,1.792,1.744,1.694,1.643,1.59,1.537,1.484,1.432,1.381,1.333,1.287,1.246,1.209,1.178,1.155,1.139,1.131,1.133,1.144,1.165,1.196,1.237,1.287,1.344,1.409,1.479,1.554,1.629,1.705,1.778,1.847,1.909,1.961,2.003,2.032,2.047,2.047,2.032,2.0,1.954,1.892,1.817,1.731,1.635,1.533,1.427,1.321,1.218,1.121,1.033,0.959,0.901,0.862,0.843,0.846,0.871,0.92,0.991,1.082,1.192,1.316,1.453,1.597,1.744,1.888,2.027,2.153,2.263,2.353,2.419,2.459,2.471,2.454,2.409,2.336,2.239,2.121,1.985,1.838,1.685,1.531,1.382,1.244,1.123,1.022,0.947,0.899,0.881,0.894,0.935,1.004,1.098,1.211,1.341,1.48,1.624,1.765,1.899,2.02,2.122,2.203,2.259,2.289,2.291,1.512,1.622,1.741,1.865,1.988,2.104,2.207,2.291,2.353,2.387,2.392,2.366,2.31,2.225,2.114,1.981,1.833,1.674,1.512,1.354,1.206,1.075,0.966,0.884,0.831,0.81,0.821,0.863,0.933,1.028,1.142,1.27,1.406,1.544,1.677,1.8,1.907,1.996,2.062,2.104,2.122,2.118,2.092,2.05,1.994,1.93,1.863,1.797,1.739,1.691,1.659,1.644,1.648,1.671,1.713,1.772,1.845,1.928,2.016,2.106,2.192,2.27,2.335,2.384,2.414,2.423,2.411,2.378,2.326,2.258,2.176,2.086,1.991,1.897,1.809,1.731,1.667,1.621,1.595,1.59,1.608,1.646,1.704,1.779,1.866,1.961,2.06,2.158,2.249,2.329,2.394,2.439,2.463,2.464,2.44,2.392,2.322,2.231,2.122,2.0,1.869,1.732,1.596,1.463,1.34,1.229,1.135,1.059,1.003,0.969,0.957,0.966,0.995,1.042,1.104,1.18,1.265,1.357,1.452,1.548,1.641,1.729,1.81,1.882,1.943,1.993,2.031,2.057,2.071,2.073,2.065,2.047,2.019,1.984,1.941,1.892,1.838,1.781,1.72,1.656,1.592,1.527,1.463,1.4,1.339,1.281,1.228,1.181,1.139,1.105,1.079,1.062,1.054,1.057,1.07,1.093,1.127,1.17,1.223,1.283,1.351,1.423,1.498,1.575,1.651,1.724,1.791,1.851,1.902,1.941,1.968,1.98,1.977,1.959,1.926,1.878,1.816,1.741,1.657,1.564,1.466,1.365,1.265,1.17,1.082,1.005,0.941,0.894,0.866,0.858,0.872,0.908,0.966,1.045,1.143,1.257,1.385,1.522,1.665,1.808,1.948,2.079,2.197,2.297,2.376,2.431,2.46,2.46,2.433,2.377,2.297,2.193,2.07,1.931,1.784,1.631,1.481,1.337,1.206,1.093,1.002,0.936,0.899,0.89,0.911,0.961,1.036,1.135,1.252,1.383,1.522,1.663,1.801,1.93,2.044,2.14,2.213,2.261,2.283,2.279,1.481,1.591,1.711,1.837,1.963,2.083,2.191,2.282,2.35,2.392,2.405,2.387,2.339,2.26,2.155,2.027,1.882,1.725,1.563,1.403,1.252,1.116,1.0,0.91,0.849,0.819,0.82,0.853,0.914,1.0,1.107,1.229,1.36,1.494,1.625,1.748,1.856,1.946,2.015,2.061,2.084,2.084,2.063,2.025,1.973,1.913,1.848,1.785,1.727,1.68,1.648,1.632,1.635,1.658,1.7,1.758,1.831,1.916,2.006,2.099,2.189,2.272,2.343,2.398,2.435,2.451,2.446,2.42,2.374,2.311,2.233,2.145,2.052,1.957,1.867,1.785,1.716,1.664,1.631,1.618,1.627,1.657,1.706,1.773,1.852,1.941,2.035,2.129,2.218,2.296,2.361,2.408,2.434,2.437,2.417,2.372,2.305,2.217,2.111,1.99,1.859,1.722,1.584,1.449,1.323,1.208,1.109,1.028,0.968,0.93,0.914,0.92,0.948,0.994,1.058,1.137,1.226,1.324,1.427,1.531,1.634,1.732,1.823,1.906,1.978,2.037,2.084,2.118,2.138,2.144,2.138,2.121,2.092,2.053,2.005,1.95,1.888,1.821,1.75,1.676,1.6,1.524,1.449,1.376,1.306,1.24,1.179,1.125,1.078,1.04,1.011,0.993,0.984,0.987,1.001,1.026,1.062,1.108,1.163,1.225,1.294,1.368,1.444,1.522,1.597,1.669,1.736,1.794,1.843,1.88,1.904,1.914,1.909,1.889,1.854,1.806,1.744,1.671,1.589,1.499,1.406,1.311,1.219,1.132,1.053,0.986,0.933,0.897,0.88,0.883,0.907,0.953,1.019,1.105,1.208,1.326,1.455,1.592,1.732,1.871,2.005,2.128,2.236,2.326,2.394,2.437,2.454,2.444,2.406,2.341,2.253,2.143,2.016,1.876,1.729,1.579,1.432,1.295,1.171,1.067,0.985,0.929,0.901,0.903,0.932,0.989,1.071,1.174,1.294,1.426,1.564,1.702,1.836,1.959,2.067,2.155,2.22,2.261,2.276,2.264,1.45,1.558,1.679,1.806,1.935,2.059,2.173,2.27,2.345,2.395,2.416,2.406,2.365,2.294,2.196,2.073,1.931,1.777,1.615,1.454,1.3,1.159,1.038,0.94,0.871,0.832,0.824,0.846,0.898,0.976,1.075,1.19,1.316,1.447,1.575,1.696,1.805,1.897,1.968,2.018,2.044,2.049,2.032,1.998,1.95,1.892,1.83,1.768,1.712,1.665,1.632,1.616,1.618,1.639,1.68,1.738,1.811,1.896,1.989,2.084,2.178,2.266,2.342,2.404,2.447,2.471,2.473,2.454,2.414,2.356,2.282,2.198,2.106,2.011,1.919,1.834,1.76,1.702,1.661,1.64,1.641,1.662,1.702,1.76,1.832,1.915,2.003,2.092,2.178,2.256,2.32,2.368,2.396,2.403,2.386,2.345,2.282,2.197,2.095,1.976,1.847,1.711,1.573,1.437,1.308,1.191,1.088,1.004,0.939,0.897,0.878,0.881,0.907,0.953,1.017,1.098,1.191,1.293,1.402,1.514,1.625,1.733,1.834,1.926,2.008,2.077,2.132,2.173,2.199,2.211,2.208,2.191,2.162,2.121,2.069,2.008,1.939,1.864,1.784,1.7,1.615,1.529,1.444,1.361,1.282,1.208,1.14,1.079,1.028,0.986,0.954,0.933,0.924,0.927,0.941,0.967,1.004,1.051,1.108,1.172,1.242,1.317,1.394,1.471,1.546,1.618,1.683,1.74,1.786,1.821,1.843,1.851,1.844,1.823,1.788,1.74,1.679,1.608,1.528,1.443,1.355,1.267,1.182,1.104,1.034,0.977,0.935,0.909,0.902,0.916,0.949,1.003,1.077,1.168,1.276,1.396,1.526,1.661,1.797,1.931,2.057,2.172,2.27,2.349,2.406,2.437,2.443,2.421,2.374,2.301,2.206,2.091,1.961,1.82,1.674,1.527,1.385,1.255,1.139,1.044,0.972,0.926,0.908,0.918,0.956,1.021,1.108,1.215,1.337,1.469,1.605,1.741,1.869,1.986,2.087,2.168,2.225,2.258,2.265,2.247,1.417,1.524,1.645,1.773,1.905,2.033,2.151,2.255,2.337,2.395,2.424,2.423,2.39,2.327,2.235,2.118,1.981,1.829,1.669,1.507,1.351,1.206,1.079,0.974,0.897,0.849,0.831,0.845,0.887,0.956,1.047,1.155,1.276,1.401,1.527,1.647,1.755,1.848,1.921,1.974,2.004,2.012,1.999,1.969,1.924,1.869,1.809,1.748,1.692,1.645,1.612,1.594,1.595,1.615,1.654,1.711,1.784,1.869,1.963,2.061,2.158,2.25,2.332,2.4,2.45,2.481,2.49,2.478,2.445,2.392,2.324,2.242,2.152,2.058,1.964,1.876,1.798,1.733,1.686,1.657,1.649,1.66,1.692,1.741,1.805,1.881,1.963,2.048,2.131,2.206,2.271,2.32,2.35,2.36,2.347,2.311,2.253,2.173,2.074,1.96,1.834,1.7,1.563,1.427,1.297,1.178,1.073,0.985,0.917,0.871,0.849,0.849,0.872,0.917,0.982,1.063,1.159,1.265,1.379,1.497,1.615,1.731,1.841,1.942,2.033,2.11,2.174,2.222,2.255,2.271,2.272,2.257,2.228,2.185,2.131,2.066,1.991,1.909,1.821,1.73,1.635,1.54,1.446,1.355,1.267,1.186,1.111,1.045,0.988,0.942,0.908,0.885,0.874,0.876,0.891,0.917,0.955,1.003,1.061,1.126,1.197,1.272,1.349,1.426,1.501,1.571,1.635,1.69,1.734,1.767,1.788,1.794,1.786,1.764,1.729,1.681,1.622,1.553,1.477,1.397,1.315,1.233,1.156,1.086,1.026,0.979,0.946,0.931,0.934,0.957,0.999,1.06,1.14,1.236,1.346,1.467,1.596,1.728,1.86,1.987,2.105,2.21,2.298,2.366,2.411,2.431,2.426,2.394,2.337,2.257,2.155,2.036,1.904,1.763,1.619,1.476,1.341,1.218,1.111,1.025,0.963,0.927,0.919,0.938,0.984,1.055,1.147,1.257,1.381,1.512,1.646,1.778,1.901,2.012,2.105,2.178,2.228,2.253,2.253,2.229,1.384,1.489,1.609,1.739,1.872,2.004,2.127,2.236,2.326,2.392,2.429,2.436,2.412,2.357,2.272,2.162,2.03,1.882,1.723,1.562,1.403,1.255,1.123,1.012,0.927,0.87,0.844,0.847,0.881,0.94,1.023,1.124,1.238,1.359,1.481,1.599,1.706,1.8,1.875,1.929,1.962,1.974,1.965,1.937,1.895,1.843,1.785,1.725,1.669,1.622,1.587,1.568,1.567,1.585,1.622,1.678,1.75,1.835,1.93,2.03,2.13,2.226,2.313,2.387,2.444,2.481,2.498,2.493,2.466,2.42,2.356,2.278,2.19,2.097,2.002,1.912,1.829,1.759,1.704,1.667,1.65,1.653,1.676,1.716,1.772,1.84,1.916,1.996,2.075,2.149,2.213,2.264,2.297,2.31,2.302,2.271,2.218,2.144,2.051,1.941,1.819,1.689,1.554,1.419,1.29,1.17,1.063,0.973,0.902,0.853,0.827,0.825,0.846,0.889,0.952,1.034,1.131,1.24,1.357,1.48,1.605,1.727,1.845,1.954,2.053,2.138,2.209,2.265,2.303,2.325,2.329,2.317,2.289,2.246,2.19,2.121,2.043,1.955,1.861,1.762,1.661,1.558,1.456,1.357,1.263,1.174,1.094,1.022,0.961,0.911,0.874,0.849,0.837,0.838,0.852,0.879,0.917,0.966,1.024,1.089,1.161,1.236,1.312,1.389,1.463,1.531,1.594,1.647,1.69,1.721,1.739,1.744,1.735,1.713,1.678,1.631,1.574,1.508,1.436,1.361,1.285,1.21,1.141,1.08,1.029,0.991,0.968,0.962,0.974,1.005,1.054,1.122,1.206,1.306,1.417,1.538,1.664,1.793,1.919,2.039,2.148,2.243,2.32,2.376,2.41,2.419,2.402,2.361,2.296,2.208,2.102,1.98,1.847,1.707,1.566,1.428,1.299,1.184,1.086,1.01,0.958,0.932,0.933,0.961,1.014,1.091,1.188,1.301,1.425,1.555,1.686,1.813,1.931,2.035,2.121,2.186,2.227,2.245,2.238,2.208,1.35,1.453,1.572,1.702,1.838,1.972,2.1,2.215,2.312,2.385,2.431,2.447,2.432,2.385,2.308,2.205,2.078,1.934,1.778,1.618,1.458,1.307,1.17,1.053,0.961,0.896,0.86,0.855,0.879,0.929,1.004,1.097,1.204,1.32,1.438,1.553,1.66,1.753,1.829,1.886,1.921,1.935,1.929,1.905,1.866,1.815,1.758,1.7,1.644,1.596,1.56,1.538,1.535,1.55,1.586,1.639,1.71,1.794,1.889,1.991,2.093,2.193,2.284,2.364,2.427,2.472,2.496,2.498,2.478,2.438,2.379,2.306,2.22,2.128,2.033,1.94,1.854,1.778,1.717,1.672,1.646,1.64,1.653,1.684,1.732,1.792,1.862,1.937,2.013,2.084,2.148,2.2,2.236,2.253,2.249,2.225,2.178,2.11,2.024,1.92,1.804,1.678,1.546,1.415,1.286,1.167,1.059,0.967,0.894,0.843,0.814,0.808,0.826,0.867,0.929,1.01,1.107,1.218,1.338,1.464,1.593,1.721,1.845,1.961,2.067,2.16,2.238,2.3,2.344,2.371,2.379,2.37,2.344,2.302,2.245,2.174,2.093,2.001,1.902,1.798,1.69,1.581,1.473,1.368,1.267,1.173,1.087,1.011,0.946,0.893,0.853,0.826,0.813,0.813,0.827,0.853,0.891,0.94,0.998,1.064,1.135,1.21,1.286,1.361,1.434,1.501,1.561,1.613,1.654,1.683,1.7,1.704,1.694,1.672,1.637,1.592,1.537,1.474,1.407,1.336,1.266,1.199,1.137,1.084,1.041,1.012,0.998,1.001,1.021,1.059,1.115,1.187,1.275,1.377,1.488,1.608,1.731,1.854,1.973,2.085,2.184,2.269,2.335,2.38,2.402,2.4,2.374,2.323,2.25,2.157,2.046,1.922,1.789,1.651,1.514,1.382,1.26,1.153,1.065,0.999,0.957,0.941,0.951,0.987,1.048,1.13,1.23,1.345,1.469,1.598,1.725,1.847,1.959,2.055,2.134,2.19,2.224,2.234,2.221,2.185,1.315,1.416,1.534,1.664,1.801,1.938,2.07,2.191,2.294,2.375,2.43,2.455,2.448,2.41,2.342,2.246,2.126,1.986,1.834,1.674,1.515,1.361,1.221,1.098,0.999,0.926,0.881,0.867,0.881,0.923,0.988,1.074,1.175,1.285,1.399,1.511,1.615,1.708,1.785,1.843,1.881,1.897,1.894,1.872,1.835,1.787,1.731,1.672,1.616,1.567,1.529,1.505,1.499,1.512,1.544,1.595,1.664,1.747,1.842,1.944,2.048,2.151,2.247,2.331,2.401,2.452,2.483,2.492,2.48,2.446,2.393,2.324,2.242,2.151,2.056,1.961,1.871,1.791,1.723,1.671,1.636,1.621,1.625,1.647,1.686,1.739,1.802,1.871,1.943,2.013,2.076,2.129,2.168,2.189,2.191,2.173,2.133,2.073,1.994,1.897,1.787,1.667,1.541,1.413,1.287,1.169,1.062,0.969,0.895,0.841,0.809,0.801,0.816,0.854,0.913,0.993,1.089,1.2,1.321,1.45,1.582,1.714,1.842,1.964,2.075,2.175,2.259,2.327,2.377,2.408,2.421,2.416,2.392,2.351,2.294,2.223,2.139,2.046,1.943,1.835,1.723,1.609,1.496,1.386,1.28,1.182,1.092,1.012,0.944,0.888,0.845,0.817,0.802,0.802,0.815,0.841,0.879,0.928,0.986,1.051,1.122,1.195,1.271,1.345,1.416,1.481,1.54,1.589,1.628,1.656,1.671,1.674,1.664,1.641,1.607,1.563,1.511,1.451,1.388,1.323,1.259,1.198,1.144,1.098,1.064,1.043,1.037,1.047,1.074,1.118,1.179,1.256,1.346,1.448,1.558,1.675,1.793,1.91,2.022,2.124,2.214,2.288,2.343,2.377,2.388,2.375,2.339,2.281,2.201,2.103,1.989,1.864,1.732,1.597,1.464,1.339,1.225,1.127,1.049,0.992,0.96,0.954,0.973,1.017,1.084,1.171,1.274,1.39,1.513,1.639,1.763,1.879,1.984,2.073,2.144,2.192,2.218,2.221,2.201,2.16,1.281,1.379,1.495,1.624,1.761,1.901,2.037,2.163,2.273,2.362,2.425,2.459,2.462,2.433,2.373,2.285,2.172,2.038,1.889,1.732,1.572,1.417,1.273,1.146,1.04,0.96,0.907,0.883,0.888,0.921,0.978,1.056,1.149,1.253,1.363,1.471,1.574,1.666,1.743,1.802,1.841,1.86,1.859,1.84,1.805,1.758,1.702,1.644,1.587,1.536,1.496,1.47,1.46,1.469,1.498,1.546,1.612,1.694,1.787,1.889,1.995,2.101,2.2,2.29,2.365,2.423,2.461,2.477,2.472,2.445,2.398,2.333,2.254,2.166,2.071,1.975,1.882,1.797,1.723,1.664,1.621,1.597,1.592,1.605,1.635,1.68,1.736,1.8,1.868,1.936,1.999,2.053,2.094,2.12,2.128,2.116,2.084,2.032,1.961,1.873,1.771,1.658,1.537,1.414,1.293,1.177,1.071,0.979,0.903,0.848,0.813,0.802,0.814,0.849,0.905,0.982,1.076,1.186,1.307,1.436,1.57,1.705,1.836,1.962,2.078,2.182,2.272,2.345,2.4,2.437,2.454,2.452,2.431,2.392,2.337,2.266,2.182,2.087,1.983,1.872,1.757,1.64,1.524,1.41,1.301,1.199,1.107,1.024,0.953,0.896,0.852,0.822,0.806,0.805,0.818,0.844,0.882,0.93,0.987,1.052,1.122,1.194,1.268,1.341,1.41,1.473,1.53,1.577,1.614,1.64,1.654,1.655,1.644,1.622,1.589,1.546,1.496,1.44,1.381,1.321,1.262,1.208,1.16,1.122,1.095,1.082,1.083,1.099,1.132,1.182,1.246,1.325,1.416,1.517,1.626,1.738,1.851,1.961,2.065,2.158,2.237,2.3,2.344,2.367,2.367,2.345,2.3,2.234,2.149,2.046,1.931,1.806,1.675,1.545,1.418,1.299,1.194,1.105,1.037,0.99,0.968,0.971,0.999,1.05,1.122,1.213,1.319,1.435,1.557,1.68,1.799,1.909,2.007,2.088,2.151,2.191,2.21,2.205,2.18,2.134,1.246,1.341,1.454,1.582,1.72,1.862,2.002,2.133,2.249,2.345,2.416,2.459,2.472,2.452,2.402,2.322,2.216,2.088,1.944,1.789,1.631,1.475,1.328,1.197,1.085,0.997,0.937,0.904,0.901,0.924,0.972,1.042,1.128,1.226,1.33,1.435,1.535,1.626,1.703,1.763,1.803,1.824,1.825,1.808,1.774,1.728,1.674,1.615,1.558,1.505,1.462,1.432,1.419,1.424,1.449,1.493,1.556,1.635,1.727,1.829,1.935,2.043,2.145,2.239,2.32,2.384,2.429,2.452,2.454,2.434,2.393,2.333,2.259,2.172,2.079,1.982,1.887,1.797,1.718,1.652,1.601,1.569,1.554,1.559,1.58,1.617,1.666,1.725,1.788,1.853,1.916,1.971,2.015,2.046,2.06,2.055,2.031,1.988,1.926,1.848,1.754,1.649,1.536,1.42,1.303,1.191,1.087,0.996,0.92,0.863,0.827,0.813,0.821,0.852,0.905,0.978,1.07,1.177,1.296,1.425,1.559,1.694,1.828,1.956,2.075,2.183,2.277,2.355,2.415,2.456,2.477,2.479,2.461,2.425,2.371,2.302,2.219,2.124,2.02,1.908,1.792,1.673,1.555,1.44,1.329,1.225,1.131,1.047,0.975,0.916,0.871,0.841,0.825,0.823,0.836,0.861,0.899,0.947,1.003,1.067,1.136,1.207,1.279,1.35,1.417,1.478,1.532,1.578,1.613,1.636,1.648,1.649,1.637,1.615,1.582,1.541,1.493,1.44,1.385,1.329,1.276,1.228,1.186,1.155,1.134,1.127,1.134,1.157,1.194,1.247,1.314,1.394,1.485,1.584,1.689,1.797,1.903,2.006,2.1,2.184,2.253,2.305,2.338,2.35,2.34,2.309,2.256,2.184,2.093,1.988,1.872,1.748,1.621,1.495,1.374,1.264,1.167,1.088,1.029,0.993,0.981,0.993,1.028,1.086,1.163,1.257,1.364,1.48,1.6,1.719,1.832,1.936,2.027,2.1,2.154,2.187,2.198,2.187,2.156,2.105,1.212,1.302,1.413,1.54,1.678,1.821,1.963,2.099,2.221,2.324,2.404,2.456,2.478,2.468,2.427,2.356,2.258,2.137,1.998,1.847,1.69,1.534,1.385,1.25,1.133,1.039,0.971,0.93,0.917,0.932,0.971,1.033,1.112,1.203,1.302,1.403,1.5,1.589,1.666,1.726,1.768,1.79,1.793,1.777,1.745,1.7,1.646,1.587,1.528,1.473,1.427,1.394,1.376,1.377,1.397,1.437,1.496,1.572,1.662,1.762,1.869,1.977,2.083,2.18,2.266,2.336,2.388,2.418,2.427,2.413,2.379,2.325,2.255,2.171,2.079,1.982,1.885,1.792,1.708,1.635,1.577,1.536,1.513,1.508,1.521,1.55,1.592,1.645,1.705,1.767,1.829,1.885,1.932,1.967,1.988,1.991,1.976,1.942,1.89,1.822,1.738,1.642,1.538,1.428,1.318,1.211,1.11,1.021,0.946,0.888,0.85,0.833,0.837,0.865,0.913,0.982,1.07,1.173,1.289,1.415,1.548,1.683,1.816,1.946,2.067,2.178,2.274,2.356,2.419,2.464,2.489,2.495,2.481,2.448,2.397,2.331,2.25,2.156,2.053,1.942,1.826,1.708,1.589,1.473,1.362,1.258,1.163,1.079,1.007,0.948,0.903,0.873,0.857,0.856,0.868,0.894,0.931,0.978,1.034,1.097,1.164,1.234,1.304,1.373,1.438,1.497,1.548,1.591,1.623,1.645,1.655,1.654,1.642,1.619,1.587,1.547,1.502,1.452,1.4,1.348,1.3,1.257,1.221,1.195,1.18,1.178,1.191,1.217,1.258,1.314,1.382,1.462,1.551,1.647,1.748,1.85,1.949,2.043,2.129,2.202,2.26,2.302,2.324,2.326,2.307,2.268,2.208,2.13,2.037,1.93,1.814,1.692,1.568,1.448,1.334,1.232,1.145,1.076,1.027,1.001,0.998,1.018,1.061,1.124,1.206,1.302,1.41,1.524,1.641,1.756,1.864,1.961,2.044,2.109,2.155,2.18,2.184,2.167,2.13,2.076,1.178,1.264,1.371,1.496,1.633,1.777,1.922,2.062,2.19,2.3,2.388,2.449,2.481,2.481,2.449,2.387,2.298,2.184,2.05,1.903,1.749,1.594,1.444,1.306,1.184,1.084,1.008,0.96,0.938,0.944,0.975,1.029,1.1,1.185,1.279,1.375,1.469,1.556,1.632,1.692,1.735,1.758,1.763,1.748,1.718,1.674,1.619,1.56,1.499,1.442,1.392,1.355,1.333,1.329,1.344,1.379,1.434,1.506,1.592,1.691,1.797,1.906,2.013,2.114,2.204,2.28,2.338,2.375,2.391,2.384,2.356,2.308,2.242,2.163,2.072,1.976,1.877,1.782,1.693,1.614,1.549,1.501,1.469,1.456,1.46,1.481,1.516,1.563,1.618,1.678,1.738,1.796,1.846,1.886,1.913,1.924,1.918,1.894,1.853,1.795,1.722,1.637,1.542,1.441,1.338,1.236,1.14,1.054,0.98,0.922,0.882,0.862,0.863,0.886,0.93,0.994,1.076,1.175,1.287,1.409,1.538,1.671,1.803,1.932,2.053,2.165,2.264,2.347,2.414,2.462,2.491,2.5,2.49,2.461,2.414,2.35,2.272,2.182,2.081,1.972,1.858,1.741,1.624,1.51,1.4,1.297,1.203,1.12,1.049,0.991,0.947,0.918,0.903,0.902,0.915,0.94,0.977,1.024,1.08,1.141,1.207,1.275,1.344,1.41,1.472,1.528,1.577,1.617,1.647,1.666,1.674,1.672,1.658,1.635,1.603,1.565,1.52,1.473,1.424,1.376,1.332,1.293,1.262,1.241,1.231,1.234,1.25,1.279,1.323,1.379,1.448,1.526,1.613,1.706,1.801,1.896,1.988,2.073,2.149,2.212,2.26,2.292,2.304,2.296,2.269,2.222,2.157,2.075,1.978,1.871,1.756,1.637,1.519,1.405,1.299,1.205,1.128,1.068,1.03,1.013,1.019,1.047,1.096,1.165,1.25,1.348,1.455,1.568,1.681,1.791,1.892,1.982,2.057,2.115,2.153,2.17,2.167,2.144,2.103,2.045,1.145,1.226,1.329,1.451,1.587,1.731,1.879,2.022,2.155,2.272,2.368,2.438,2.479,2.489,2.468,2.415,2.334,2.228,2.101,1.959,1.808,1.654,1.504,1.363,1.238,1.132,1.05,0.994,0.964,0.961,0.984,1.029,1.093,1.172,1.26,1.352,1.443,1.527,1.602,1.662,1.705,1.73,1.735,1.722,1.693,1.649,1.595,1.534,1.472,1.412,1.359,1.317,1.291,1.281,1.291,1.32,1.369,1.437,1.52,1.616,1.72,1.829,1.937,2.041,2.135,2.216,2.279,2.323,2.346,2.347,2.325,2.283,2.223,2.147,2.059,1.964,1.865,1.767,1.674,1.59,1.519,1.463,1.423,1.401,1.397,1.41,1.438,1.479,1.53,1.587,1.646,1.705,1.758,1.803,1.836,1.855,1.858,1.845,1.815,1.769,1.707,1.633,1.549,1.457,1.362,1.268,1.177,1.094,1.022,0.964,0.923,0.901,0.899,0.917,0.955,1.013,1.09,1.182,1.288,1.405,1.53,1.659,1.788,1.914,2.035,2.146,2.245,2.33,2.398,2.449,2.481,2.494,2.487,2.462,2.419,2.36,2.286,2.199,2.102,1.997,1.886,1.773,1.659,1.547,1.44,1.34,1.249,1.168,1.099,1.043,1.001,0.973,0.96,0.96,0.974,1.0,1.038,1.084,1.139,1.199,1.264,1.33,1.396,1.459,1.519,1.572,1.618,1.655,1.682,1.699,1.705,1.7,1.685,1.662,1.63,1.592,1.549,1.503,1.456,1.412,1.371,1.336,1.309,1.292,1.285,1.291,1.31,1.342,1.387,1.443,1.511,1.587,1.67,1.758,1.847,1.935,2.019,2.095,2.162,2.215,2.253,2.274,2.277,2.261,2.226,2.173,2.103,2.017,1.92,1.813,1.7,1.585,1.473,1.366,1.268,1.184,1.116,1.066,1.037,1.03,1.044,1.079,1.134,1.207,1.295,1.394,1.5,1.61,1.719,1.823,1.918,2.0,2.068,2.117,2.147,2.157,2.148,2.119,2.074,2.014,1.112,1.188,1.287,1.405,1.54,1.684,1.832,1.979,2.117,2.24,2.344,2.423,2.473,2.494,2.482,2.44,2.368,2.27,2.15,2.014,1.867,1.715,1.565,1.422,1.294,1.183,1.095,1.031,0.994,0.983,0.997,1.035,1.091,1.163,1.245,1.333,1.42,1.503,1.575,1.635,1.679,1.704,1.711,1.699,1.67,1.627,1.573,1.511,1.447,1.384,1.328,1.281,1.249,1.234,1.238,1.261,1.304,1.366,1.445,1.537,1.64,1.748,1.857,1.962,2.06,2.145,2.214,2.265,2.294,2.302,2.287,2.252,2.197,2.125,2.041,1.947,1.848,1.749,1.653,1.564,1.487,1.424,1.376,1.346,1.334,1.339,1.36,1.395,1.441,1.495,1.554,1.613,1.669,1.718,1.758,1.785,1.798,1.796,1.777,1.743,1.694,1.631,1.558,1.477,1.391,1.304,1.22,1.141,1.072,1.016,0.974,0.949,0.943,0.956,0.989,1.041,1.11,1.196,1.295,1.405,1.524,1.647,1.771,1.894,2.012,2.121,2.219,2.304,2.373,2.426,2.46,2.476,2.473,2.452,2.414,2.359,2.29,2.208,2.115,2.015,1.909,1.8,1.691,1.584,1.482,1.386,1.298,1.221,1.156,1.103,1.064,1.039,1.028,1.03,1.045,1.072,1.11,1.157,1.211,1.27,1.333,1.397,1.461,1.521,1.578,1.628,1.67,1.704,1.728,1.742,1.745,1.738,1.722,1.697,1.665,1.627,1.585,1.54,1.496,1.454,1.415,1.383,1.359,1.345,1.341,1.35,1.37,1.403,1.448,1.503,1.569,1.642,1.721,1.803,1.886,1.967,2.042,2.109,2.166,2.209,2.238,2.25,2.244,2.22,2.179,2.121,2.047,1.96,1.862,1.756,1.647,1.537,1.431,1.331,1.242,1.167,1.109,1.069,1.049,1.051,1.073,1.115,1.175,1.251,1.34,1.439,1.544,1.65,1.754,1.852,1.94,2.015,2.074,2.116,2.138,2.141,2.126,2.092,2.044,1.981,1.081,1.151,1.244,1.359,1.491,1.635,1.784,1.933,2.076,2.205,2.316,2.403,2.463,2.494,2.492,2.46,2.398,2.309,2.197,2.067,1.924,1.775,1.626,1.482,1.351,1.236,1.143,1.073,1.028,1.009,1.015,1.045,1.094,1.159,1.236,1.318,1.402,1.482,1.553,1.613,1.656,1.683,1.69,1.68,1.652,1.609,1.554,1.492,1.425,1.36,1.299,1.248,1.21,1.189,1.186,1.203,1.24,1.296,1.369,1.458,1.557,1.663,1.772,1.879,1.979,2.068,2.143,2.199,2.235,2.25,2.242,2.213,2.165,2.098,2.017,1.926,1.828,1.727,1.629,1.536,1.454,1.384,1.33,1.292,1.272,1.27,1.284,1.313,1.354,1.405,1.462,1.521,1.579,1.633,1.679,1.715,1.738,1.746,1.74,1.718,1.681,1.631,1.57,1.5,1.425,1.346,1.269,1.196,1.13,1.075,1.033,1.006,0.997,1.005,1.032,1.076,1.138,1.216,1.307,1.409,1.52,1.636,1.754,1.871,1.984,2.09,2.186,2.27,2.339,2.392,2.429,2.447,2.447,2.43,2.396,2.347,2.283,2.207,2.12,2.026,1.926,1.823,1.72,1.619,1.522,1.432,1.35,1.278,1.218,1.169,1.134,1.113,1.105,1.109,1.127,1.155,1.193,1.24,1.294,1.352,1.413,1.475,1.536,1.594,1.647,1.694,1.733,1.763,1.784,1.794,1.795,1.786,1.767,1.741,1.708,1.669,1.627,1.583,1.54,1.5,1.463,1.433,1.412,1.399,1.397,1.407,1.428,1.461,1.505,1.559,1.621,1.691,1.765,1.841,1.917,1.989,2.056,2.115,2.162,2.196,2.216,2.219,2.206,2.176,2.129,2.066,1.99,1.902,1.805,1.702,1.597,1.493,1.393,1.302,1.222,1.156,1.108,1.077,1.067,1.076,1.105,1.153,1.217,1.296,1.386,1.484,1.586,1.688,1.787,1.878,1.959,2.026,2.077,2.111,2.126,2.123,2.102,2.064,2.012,1.949,1.051,1.114,1.203,1.313,1.442,1.584,1.734,1.885,2.031,2.166,2.284,2.379,2.449,2.489,2.498,2.476,2.424,2.344,2.24,2.117,1.979,1.834,1.686,1.543,1.41,1.292,1.193,1.117,1.065,1.039,1.038,1.06,1.101,1.16,1.231,1.309,1.389,1.466,1.536,1.594,1.638,1.665,1.674,1.664,1.637,1.594,1.54,1.476,1.407,1.339,1.274,1.218,1.175,1.147,1.137,1.147,1.177,1.226,1.294,1.377,1.473,1.577,1.685,1.792,1.895,1.987,2.066,2.128,2.171,2.193,2.192,2.17,2.127,2.066,1.99,1.901,1.804,1.704,1.604,1.508,1.421,1.346,1.284,1.239,1.212,1.202,1.209,1.232,1.269,1.316,1.371,1.431,1.492,1.55,1.602,1.645,1.678,1.697,1.703,1.694,1.67,1.633,1.585,1.527,1.462,1.393,1.324,1.256,1.195,1.142,1.1,1.072,1.059,1.062,1.082,1.12,1.173,1.242,1.324,1.417,1.519,1.626,1.737,1.847,1.954,2.055,2.147,2.228,2.296,2.349,2.386,2.407,2.41,2.397,2.367,2.323,2.265,2.195,2.116,2.028,1.936,1.84,1.745,1.651,1.561,1.478,1.402,1.337,1.282,1.24,1.21,1.192,1.188,1.196,1.216,1.246,1.285,1.333,1.386,1.443,1.503,1.563,1.621,1.676,1.726,1.769,1.804,1.83,1.847,1.854,1.851,1.839,1.819,1.79,1.756,1.716,1.674,1.63,1.588,1.548,1.513,1.484,1.464,1.452,1.452,1.461,1.483,1.514,1.557,1.608,1.667,1.732,1.8,1.87,1.939,2.004,2.062,2.112,2.15,2.176,2.187,2.183,2.163,2.127,2.076,2.01,1.933,1.845,1.75,1.651,1.551,1.453,1.361,1.278,1.207,1.151,1.112,1.09,1.088,1.105,1.14,1.193,1.261,1.341,1.431,1.528,1.626,1.724,1.817,1.901,1.974,2.033,2.077,2.103,2.111,2.102,2.075,2.034,1.98,1.916,1.023,1.08,1.162,1.267,1.392,1.532,1.682,1.834,1.983,2.123,2.248,2.351,2.43,2.48,2.5,2.488,2.446,2.376,2.281,2.165,2.033,1.892,1.747,1.604,1.47,1.349,1.246,1.164,1.106,1.073,1.064,1.079,1.113,1.165,1.23,1.303,1.38,1.454,1.523,1.58,1.624,1.652,1.661,1.652,1.626,1.584,1.529,1.464,1.394,1.322,1.254,1.193,1.143,1.109,1.092,1.094,1.116,1.159,1.22,1.298,1.389,1.49,1.596,1.703,1.807,1.903,1.986,2.053,2.102,2.13,2.137,2.122,2.086,2.03,1.959,1.874,1.779,1.679,1.578,1.48,1.389,1.309,1.241,1.19,1.155,1.138,1.139,1.155,1.187,1.231,1.284,1.344,1.406,1.468,1.526,1.578,1.619,1.65,1.667,1.671,1.661,1.637,1.602,1.556,1.503,1.444,1.383,1.323,1.266,1.216,1.175,1.145,1.129,1.127,1.141,1.17,1.215,1.274,1.346,1.429,1.52,1.618,1.719,1.821,1.921,2.015,2.102,2.179,2.245,2.296,2.334,2.355,2.361,2.351,2.327,2.288,2.236,2.173,2.101,2.021,1.937,1.85,1.763,1.677,1.596,1.521,1.453,1.395,1.348,1.312,1.288,1.276,1.276,1.288,1.311,1.343,1.384,1.432,1.485,1.542,1.6,1.658,1.713,1.765,1.811,1.85,1.881,1.903,1.916,1.919,1.913,1.898,1.874,1.843,1.807,1.766,1.723,1.679,1.636,1.597,1.562,1.534,1.514,1.503,1.502,1.512,1.532,1.562,1.602,1.65,1.705,1.764,1.827,1.89,1.952,2.009,2.059,2.101,2.131,2.149,2.153,2.142,2.117,2.076,2.021,1.954,1.876,1.79,1.698,1.603,1.509,1.418,1.334,1.26,1.198,1.152,1.121,1.109,1.114,1.138,1.179,1.235,1.305,1.387,1.476,1.57,1.664,1.757,1.843,1.92,1.986,2.037,2.073,2.091,2.093,2.078,2.047,2.003,1.948,1.883]}}}]} diff --git a/crates/latkit-cli/examples/cli-gallery/interference.json b/crates/latkit-cli/examples/cli-gallery/interference.json new file mode 100644 index 00000000..7d33c2f4 --- /dev/null +++ b/crates/latkit-cli/examples/cli-gallery/interference.json @@ -0,0 +1,42 @@ +{ + "space": { + "plane": { + "grid": "off" + } + }, + "ease": 0, + "theme": { + "background": "#080f1c", + "text": "#c7d5e4", + "font": "sans-serif", + "fontSize": 13, + "halo": 0, + "flow": "#d9fff0a0", + "flowSpacing": 100 + }, + "title": "02 / INTERFERENCE", + "subtitle": "33,600 particles / two wave sources / one interference field", + "marks": [ + { + "vertices": { + "of": [ + "art", + "Particle" + ], + "position": [ + "x", + "y" + ], + "radius": "radius", + "color": { + "colormap": "magma", + "value": "heat", + "domain": [ + 0, + 1 + ] + } + } + } + ] +} diff --git a/crates/latkit-cli/examples/cli-gallery/interference.png b/crates/latkit-cli/examples/cli-gallery/interference.png new file mode 100644 index 00000000..028269b6 Binary files /dev/null and b/crates/latkit-cli/examples/cli-gallery/interference.png differ diff --git a/crates/latkit-cli/examples/cli-gallery/tides.data.json b/crates/latkit-cli/examples/cli-gallery/tides.data.json new file mode 100644 index 00000000..779c1acf --- /dev/null +++ b/crates/latkit-cli/examples/cli-gallery/tides.data.json @@ -0,0 +1 @@ +{"name":"art","patch":[{"replace":{"table":"Contour","ids":{"count": 100},"fields":{"geometry":[[[192.1,-35.0],[192.5,-34.36],[192.82,-33.71],[193.07,-33.06],[193.25,-32.41],[193.36,-31.76],[193.4,-31.1],[193.38,-30.45],[193.29,-29.8],[193.15,-29.16],[192.94,-28.51],[192.68,-27.88],[192.36,-27.24],[192.0,-26.62],[191.6,-25.99],[191.16,-25.38],[190.68,-24.77],[190.17,-24.17],[189.64,-23.57],[189.08,-22.98],[188.51,-22.4],[187.92,-21.82],[187.33,-21.24],[186.73,-20.67],[186.14,-20.1],[185.54,-19.54],[184.95,-18.98],[184.37,-18.41],[183.81,-17.85],[183.25,-17.29],[182.72,-16.72],[182.19,-16.16],[181.69,-15.58],[181.2,-15.01],[180.74,-14.43],[180.29,-13.84],[179.85,-13.25],[179.43,-12.65],[179.03,-12.05],[178.64,-11.44],[178.26,-10.82],[177.88,-10.2],[177.52,-9.56],[177.15,-8.93],[176.78,-8.29],[176.4,-7.64],[176.02,-6.99],[175.62,-6.34],[175.21,-5.69],[174.78,-5.03],[174.32,-4.38],[173.84,-3.74],[173.33,-3.09],[172.78,-2.46],[172.2,-1.83],[171.57,-1.22],[170.91,-0.62],[170.2,-0.03],[169.44,0.54],[168.64,1.09],[167.79,1.62],[166.89,2.12],[165.94,2.6],[164.94,3.06],[163.89,3.49],[162.79,3.88],[161.64,4.25],[160.45,4.59],[159.21,4.89],[157.94,5.16],[156.62,5.39],[155.26,5.59],[153.87,5.76],[152.45,5.89],[151.0,5.99],[149.53,6.05],[148.04,6.09],[146.54,6.09],[145.02,6.06],[143.49,6.0],[141.96,5.92],[140.43,5.81],[138.91,5.68],[137.39,5.53],[135.88,5.36],[134.38,5.17],[132.9,4.97],[131.44,4.77],[130.01,4.55],[128.59,4.33],[127.2,4.11],[125.84,3.89],[124.51,3.67],[123.21,3.46],[121.93,3.26],[120.69,3.07],[119.48,2.89],[118.29,2.74],[117.14,2.59],[116.01,2.47],[114.91,2.37],[113.83,2.29],[112.77,2.24],[111.74,2.21],[110.72,2.21],[109.72,2.23],[108.74,2.28],[107.76,2.35],[106.79,2.45],[105.83,2.58],[104.87,2.73],[103.92,2.9],[102.96,3.09],[102.0,3.3],[101.03,3.53],[100.05,3.78],[99.07,4.04],[98.07,4.31],[97.06,4.59],[96.04,4.88],[95.0,5.17],[93.95,5.47],[92.88,5.76],[91.79,6.05],[90.69,6.33],[89.58,6.6],[88.45,6.86],[87.31,7.11],[86.15,7.35],[84.99,7.56],[83.81,7.76],[82.63,7.93],[81.44,8.08],[80.24,8.21],[79.04,8.31],[77.85,8.38],[76.65,8.43],[75.46,8.44],[74.27,8.44],[73.09,8.4],[71.92,8.33],[70.76,8.24],[69.61,8.12],[68.47,7.98],[67.35,7.81],[66.24,7.62],[65.15,7.41],[64.07,7.17],[63.01,6.92],[61.97,6.65],[60.94,6.37],[59.92,6.07],[58.92,5.76],[57.93,5.45],[56.95,5.12],[55.99,4.8],[55.02,4.47],[54.07,4.13],[53.12,3.8],[52.17,3.47],[51.21,3.15],[50.26,2.83],[49.29,2.52],[48.32,2.22],[47.33,1.92],[46.34,1.64],[45.32,1.36],[44.29,1.1],[43.23,0.84],[42.15,0.6],[41.05,0.37],[39.92,0.14],[38.77,-0.07],[37.59,-0.28],[36.38,-0.47],[35.14,-0.67],[33.88,-0.85],[32.58,-1.04],[31.27,-1.22],[29.93,-1.4],[28.56,-1.58],[27.18,-1.76],[25.78,-1.96],[24.36,-2.15],[22.93,-2.36],[21.5,-2.57],[20.06,-2.8],[18.62,-3.05],[17.19,-3.31],[15.77,-3.58],[14.36,-3.88],[12.98,-4.19],[11.61,-4.52],[10.28,-4.88],[8.99,-5.26],[7.73,-5.67],[6.52,-6.1],[5.36,-6.55],[4.25,-7.02],[3.2,-7.53],[2.21,-8.05],[1.29,-8.6],[0.44,-9.17],[-0.33,-9.77],[-1.03,-10.39],[-1.66,-11.02],[-2.2,-11.68],[-2.66,-12.35],[-3.04,-13.04],[-3.34,-13.75],[-3.56,-14.46],[-3.7,-15.19],[-3.75,-15.93],[-3.74,-16.68],[-3.64,-17.43],[-3.47,-18.18],[-3.24,-18.94],[-2.94,-19.7],[-2.57,-20.46],[-2.16,-21.22],[-1.68,-21.97],[-1.17,-22.71],[-0.6,-23.45],[-0.01,-24.19],[0.62,-24.91],[1.28,-25.62],[1.95,-26.32],[2.64,-27.02],[3.33,-27.7],[4.03,-28.37],[4.73,-29.02],[5.42,-29.67],[6.1,-30.3],[6.76,-30.92],[7.4,-31.53],[8.01,-32.13],[8.6,-32.72],[9.15,-33.3],[9.67,-33.88],[10.16,-34.44],[10.6,-35.0],[11.01,-35.55],[11.38,-36.1],[11.71,-36.65],[12.0,-37.19],[12.25,-37.73],[12.46,-38.27],[12.64,-38.81],[12.79,-39.35],[12.9,-39.89],[12.99,-40.43],[13.06,-40.98],[13.1,-41.53],[13.12,-42.08],[13.14,-42.63],[13.14,-43.19],[13.14,-43.75],[13.14,-44.32],[13.15,-44.88],[13.16,-45.45],[13.19,-46.03],[13.24,-46.6],[13.3,-47.17],[13.4,-47.75],[13.52,-48.32],[13.67,-48.89],[13.86,-49.45],[14.09,-50.01],[14.36,-50.57],[14.67,-51.12],[15.03,-51.66],[15.43,-52.2],[15.88,-52.72],[16.38,-53.23],[16.92,-53.73],[17.5,-54.22],[18.13,-54.7],[18.81,-55.16],[19.53,-55.61],[20.28,-56.05],[21.07,-56.47],[21.9,-56.88],[22.76,-57.27],[23.65,-57.65],[24.56,-58.01],[25.49,-58.36],[26.44,-58.7],[27.4,-59.03],[28.37,-59.35],[29.35,-59.66],[30.33,-59.96],[31.3,-60.26],[32.27,-60.55],[33.23,-60.84],[34.18,-61.13],[35.11,-61.42],[36.03,-61.71],[36.92,-62.01],[37.79,-62.31],[38.63,-62.62],[39.45,-62.94],[40.24,-63.28],[41.0,-63.62],[41.74,-63.98],[42.44,-64.36],[43.12,-64.76],[43.77,-65.17],[44.39,-65.61],[44.99,-66.06],[45.57,-66.54],[46.13,-67.04],[46.66,-67.56],[47.19,-68.1],[47.7,-68.67],[48.2,-69.25],[48.7,-69.86],[49.19,-70.48],[49.69,-71.13],[50.19,-71.79],[50.69,-72.46],[51.21,-73.15],[51.75,-73.85],[52.3,-74.56],[52.88,-75.27],[53.48,-75.99],[54.11,-76.71],[54.77,-77.43],[55.46,-78.15],[56.18,-78.86],[56.95,-79.56],[57.75,-80.24],[58.59,-80.91],[59.47,-81.56],[60.39,-82.2],[61.35,-82.8],[62.35,-83.38],[63.39,-83.94],[64.47,-84.46],[65.59,-84.95],[66.74,-85.4],[67.93,-85.82],[69.15,-86.2],[70.4,-86.54],[71.68,-86.84],[72.99,-87.1],[74.31,-87.31],[75.66,-87.49],[77.02,-87.63],[78.4,-87.72],[79.79,-87.78],[81.18,-87.79],[82.58,-87.77],[83.99,-87.71],[85.39,-87.61],[86.79,-87.48],[88.18,-87.32],[89.57,-87.13],[90.94,-86.92],[92.31,-86.68],[93.66,-86.41],[95.0,-86.13],[96.32,-85.83],[97.63,-85.51],[98.92,-85.18],[100.19,-84.85],[101.45,-84.5],[102.69,-84.16],[103.92,-83.8],[105.12,-83.45],[106.32,-83.11],[107.5,-82.76],[108.67,-82.43],[109.83,-82.1],[110.98,-81.78],[112.12,-81.47],[113.26,-81.17],[114.39,-80.88],[115.51,-80.6],[116.64,-80.34],[117.77,-80.09],[118.89,-79.85],[120.02,-79.63],[121.15,-79.42],[122.29,-79.21],[123.43,-79.02],[124.58,-78.83],[125.73,-78.66],[126.89,-78.48],[128.05,-78.31],[129.22,-78.15],[130.39,-77.98],[131.57,-77.81],[132.74,-77.64],[133.92,-77.47],[135.09,-77.28],[136.26,-77.09],[137.42,-76.88],[138.58,-76.67],[139.72,-76.43],[140.85,-76.18],[141.96,-75.92],[143.06,-75.63],[144.13,-75.33],[145.17,-75.0],[146.19,-74.65],[147.17,-74.28],[148.12,-73.88],[149.04,-73.46],[149.91,-73.02],[150.75,-72.56],[151.54,-72.07],[152.29,-71.56],[152.99,-71.02],[153.65,-70.47],[154.25,-69.9],[154.81,-69.31],[155.32,-68.7],[155.79,-68.08],[156.2,-67.44],[156.57,-66.8],[156.9,-66.14],[157.19,-65.47],[157.43,-64.8],[157.64,-64.13],[157.81,-63.45],[157.96,-62.77],[158.07,-62.1],[158.17,-61.43],[158.24,-60.76],[158.31,-60.1],[158.36,-59.46],[158.4,-58.82],[158.45,-58.19],[158.5,-57.58],[158.56,-56.98],[158.64,-56.39],[158.74,-55.82],[158.85,-55.27],[159.0,-54.73],[159.18,-54.21],[159.4,-53.7],[159.65,-53.21],[159.95,-52.74],[160.29,-52.28],[160.68,-51.84],[161.13,-51.4],[161.62,-50.98],[162.17,-50.58],[162.77,-50.18],[163.42,-49.79],[164.12,-49.4],[164.88,-49.02],[165.69,-48.65],[166.55,-48.28],[167.45,-47.91],[168.39,-47.53],[169.38,-47.16],[170.4,-46.78],[171.45,-46.39],[172.53,-46.0],[173.63,-45.6],[174.75,-45.19],[175.88,-44.77],[177.02,-44.34],[178.16,-43.89],[179.29,-43.43],[180.41,-42.96],[181.51,-42.48],[182.6,-41.98],[183.65,-41.47],[184.68,-40.94],[185.66,-40.4],[186.6,-39.84],[187.49,-39.28],[188.34,-38.7],[189.12,-38.1],[189.85,-37.5],[190.51,-36.89],[191.11,-36.27],[191.64,-35.64],[192.1,-35.0]],[[197.13,-35.0],[197.56,-34.32],[197.92,-33.64],[198.21,-32.96],[198.42,-32.27],[198.55,-31.59],[198.61,-30.9],[198.6,-30.21],[198.52,-29.53],[198.38,-28.85],[198.17,-28.17],[197.89,-27.5],[197.57,-26.83],[197.19,-26.17],[196.76,-25.51],[196.29,-24.87],[195.78,-24.22],[195.23,-23.59],[194.66,-22.96],[194.06,-22.35],[193.44,-21.73],[192.8,-21.13],[192.15,-20.52],[191.5,-19.93],[190.84,-19.34],[190.18,-18.75],[189.53,-18.16],[188.89,-17.58],[188.26,-16.99],[187.64,-16.41],[187.03,-15.82],[186.45,-15.24],[185.88,-14.65],[185.32,-14.05],[184.79,-13.46],[184.28,-12.85],[183.78,-12.24],[183.3,-11.63],[182.84,-11.01],[182.39,-10.38],[181.96,-9.75],[181.53,-9.1],[181.11,-8.46],[180.69,-7.8],[180.27,-7.14],[179.85,-6.48],[179.42,-5.81],[178.98,-5.14],[178.53,-4.47],[178.06,-3.8],[177.57,-3.13],[177.05,-2.46],[176.5,-1.8],[175.92,-1.15],[175.3,-0.5],[174.65,0.14],[173.95,0.76],[173.21,1.37],[172.42,1.96],[171.59,2.53],[170.7,3.08],[169.77,3.61],[168.78,4.11],[167.75,4.59],[166.66,5.03],[165.52,5.45],[164.34,5.84],[163.1,6.19],[161.82,6.51],[160.5,6.8],[159.14,7.05],[157.73,7.26],[156.3,7.44],[154.82,7.58],[153.33,7.69],[151.8,7.76],[150.26,7.8],[148.7,7.81],[147.12,7.78],[145.54,7.73],[143.95,7.65],[142.36,7.54],[140.77,7.4],[139.19,7.25],[137.62,7.07],[136.06,6.88],[134.52,6.68],[133.0,6.46],[131.5,6.24],[130.02,6.01],[128.58,5.78],[127.16,5.54],[125.77,5.32],[124.41,5.09],[123.08,4.88],[121.78,4.68],[120.51,4.49],[119.27,4.32],[118.07,4.17],[116.89,4.04],[115.74,3.93],[114.61,3.85],[113.51,3.79],[112.43,3.75],[111.37,3.75],[110.33,3.77],[109.3,3.81],[108.28,3.89],[107.28,3.99],[106.28,4.12],[105.28,4.28],[104.28,4.46],[103.29,4.66],[102.29,4.89],[101.28,5.13],[100.26,5.39],[99.24,5.67],[98.2,5.96],[97.15,6.26],[96.08,6.57],[95.0,6.89],[93.9,7.21],[92.79,7.53],[91.65,7.84],[90.5,8.15],[89.34,8.45],[88.16,8.74],[86.96,9.02],[85.75,9.28],[84.52,9.53],[83.29,9.75],[82.04,9.95],[80.79,10.13],[79.53,10.28],[78.27,10.41],[77.01,10.51],[75.74,10.58],[74.48,10.62],[73.22,10.63],[71.97,10.61],[70.73,10.56],[69.5,10.48],[68.28,10.37],[67.08,10.24],[65.88,10.08],[64.71,9.89],[63.55,9.68],[62.4,9.45],[61.28,9.19],[60.17,8.92],[59.07,8.63],[58.0,8.33],[56.93,8.01],[55.88,7.68],[54.85,7.34],[53.83,7.0],[52.81,6.65],[51.8,6.3],[50.8,5.95],[49.8,5.6],[48.8,5.25],[47.79,4.91],[46.79,4.58],[45.77,4.25],[44.74,3.93],[43.7,3.62],[42.65,3.32],[41.58,3.02],[40.48,2.74],[39.37,2.48],[38.23,2.22],[37.07,1.97],[35.88,1.73],[34.66,1.5],[33.41,1.27],[32.14,1.06],[30.83,0.85],[29.5,0.64],[28.15,0.44],[26.77,0.23],[25.36,0.03],[23.94,-0.18],[22.49,-0.39],[21.03,-0.61],[19.56,-0.83],[18.08,-1.07],[16.6,-1.32],[15.11,-1.58],[13.63,-1.86],[12.16,-2.15],[10.71,-2.46],[9.27,-2.8],[7.86,-3.15],[6.48,-3.53],[5.13,-3.93],[3.83,-4.36],[2.57,-4.81],[1.36,-5.28],[0.21,-5.78],[-0.89,-6.3],[-1.91,-6.85],[-2.87,-7.43],[-3.76,-8.03],[-4.57,-8.65],[-5.31,-9.29],[-5.96,-9.96],[-6.53,-10.64],[-7.01,-11.34],[-7.41,-12.06],[-7.73,-12.8],[-7.96,-13.55],[-8.1,-14.31],[-8.17,-15.08],[-8.15,-15.86],[-8.05,-16.64],[-7.87,-17.43],[-7.62,-18.23],[-7.3,-19.02],[-6.92,-19.81],[-6.47,-20.6],[-5.97,-21.39],[-5.42,-22.17],[-4.82,-22.95],[-4.18,-23.71],[-3.51,-24.47],[-2.81,-25.21],[-2.09,-25.95],[-1.35,-26.67],[-0.6,-27.38],[0.15,-28.08],[0.9,-28.77],[1.65,-29.44],[2.38,-30.1],[3.09,-30.75],[3.79,-31.39],[4.46,-32.01],[5.1,-32.63],[5.7,-33.24],[6.27,-33.83],[6.81,-34.42],[7.3,-35.0],[7.75,-35.57],[8.16,-36.14],[8.52,-36.71],[8.84,-37.27],[9.12,-37.83],[9.36,-38.39],[9.56,-38.95],[9.73,-39.51],[9.86,-40.07],[9.96,-40.63],[10.03,-41.2],[10.07,-41.77],[10.1,-42.34],[10.11,-42.91],[10.1,-43.49],[10.09,-44.08],[10.08,-44.67],[10.07,-45.26],[10.06,-45.85],[10.07,-46.45],[10.09,-47.05],[10.14,-47.65],[10.2,-48.24],[10.3,-48.84],[10.43,-49.44],[10.59,-50.04],[10.79,-50.63],[11.03,-51.21],[11.32,-51.79],[11.65,-52.37],[12.03,-52.93],[12.45,-53.49],[12.93,-54.03],[13.45,-54.57],[14.02,-55.09],[14.64,-55.6],[15.3,-56.09],[16.01,-56.57],[16.76,-57.04],[17.56,-57.49],[18.38,-57.93],[19.25,-58.35],[20.14,-58.76],[21.06,-59.15],[22.01,-59.53],[22.98,-59.9],[23.96,-60.26],[24.95,-60.6],[25.96,-60.94],[26.96,-61.26],[27.97,-61.58],[28.97,-61.9],[29.97,-62.21],[30.95,-62.52],[31.92,-62.83],[32.88,-63.14],[33.81,-63.45],[34.72,-63.77],[35.61,-64.1],[36.47,-64.44],[37.3,-64.79],[38.11,-65.16],[38.89,-65.54],[39.64,-65.93],[40.36,-66.34],[41.05,-66.78],[41.72,-67.23],[42.36,-67.7],[42.98,-68.2],[43.57,-68.71],[44.15,-69.25],[44.71,-69.82],[45.26,-70.4],[45.8,-71.01],[46.34,-71.64],[46.87,-72.28],[47.4,-72.95],[47.93,-73.64],[48.48,-74.34],[49.03,-75.05],[49.6,-75.78],[50.19,-76.52],[50.8,-77.26],[51.43,-78.01],[52.1,-78.76],[52.79,-79.51],[53.52,-80.26],[54.29,-81.0],[55.09,-81.73],[55.93,-82.45],[56.81,-83.15],[57.74,-83.83],[58.7,-84.49],[59.71,-85.13],[60.76,-85.74],[61.85,-86.32],[62.98,-86.87],[64.15,-87.39],[65.36,-87.87],[66.6,-88.31],[67.88,-88.71],[69.2,-89.07],[70.54,-89.38],[71.9,-89.66],[73.29,-89.89],[74.71,-90.08],[76.14,-90.22],[77.58,-90.32],[79.04,-90.38],[80.5,-90.4],[81.97,-90.37],[83.44,-90.31],[84.92,-90.21],[86.38,-90.07],[87.85,-89.89],[89.3,-89.69],[90.75,-89.46],[92.18,-89.2],[93.6,-88.91],[95.0,-88.6],[96.39,-88.28],[97.76,-87.93],[99.11,-87.58],[100.44,-87.21],[101.75,-86.83],[103.05,-86.45],[104.33,-86.07],[105.59,-85.69],[106.84,-85.3],[108.07,-84.92],[109.28,-84.55],[110.49,-84.19],[111.68,-83.83],[112.86,-83.48],[114.04,-83.15],[115.21,-82.83],[116.38,-82.52],[117.54,-82.23],[118.7,-81.95],[119.87,-81.68],[121.03,-81.43],[122.2,-81.19],[123.37,-80.96],[124.54,-80.74],[125.73,-80.53],[126.91,-80.33],[128.11,-80.14],[129.31,-79.96],[130.51,-79.77],[131.72,-79.59],[132.93,-79.41],[134.15,-79.23],[135.36,-79.04],[136.57,-78.85],[137.79,-78.64],[138.99,-78.43],[140.19,-78.21],[141.38,-77.97],[142.55,-77.71],[143.71,-77.44],[144.86,-77.15],[145.97,-76.84],[147.07,-76.51],[148.13,-76.16],[149.17,-75.78],[150.17,-75.38],[151.14,-74.96],[152.07,-74.51],[152.95,-74.04],[153.79,-73.54],[154.59,-73.02],[155.34,-72.48],[156.04,-71.92],[156.7,-71.34],[157.3,-70.74],[157.86,-70.12],[158.36,-69.48],[158.82,-68.83],[159.23,-68.17],[159.59,-67.49],[159.91,-66.81],[160.19,-66.12],[160.43,-65.43],[160.64,-64.73],[160.81,-64.03],[160.95,-63.33],[161.07,-62.64],[161.16,-61.95],[161.24,-61.27],[161.31,-60.6],[161.38,-59.93],[161.44,-59.28],[161.51,-58.64],[161.58,-58.02],[161.67,-57.41],[161.78,-56.81],[161.91,-56.24],[162.07,-55.67],[162.26,-55.13],[162.49,-54.6],[162.75,-54.09],[163.07,-53.59],[163.43,-53.11],[163.84,-52.64],[164.3,-52.19],[164.81,-51.75],[165.38,-51.32],[166.01,-50.9],[166.69,-50.49],[167.42,-50.09],[168.21,-49.69],[169.06,-49.3],[169.95,-48.91],[170.9,-48.52],[171.89,-48.13],[172.92,-47.74],[173.99,-47.34],[175.1,-46.94],[176.24,-46.52],[177.4,-46.11],[178.58,-45.68],[179.77,-45.24],[180.97,-44.79],[182.18,-44.32],[183.38,-43.84],[184.57,-43.35],[185.74,-42.84],[186.89,-42.32],[188.02,-41.78],[189.11,-41.23],[190.16,-40.67],[191.17,-40.08],[192.13,-39.49],[193.04,-38.88],[193.88,-38.26],[194.67,-37.63],[195.39,-36.98],[196.04,-36.33],[196.62,-35.67],[197.13,-35.0]],[[202.2,-35.0],[202.67,-34.29],[203.07,-33.58],[203.39,-32.86],[203.62,-32.14],[203.78,-31.41],[203.86,-30.69],[203.86,-29.97],[203.79,-29.25],[203.65,-28.53],[203.43,-27.82],[203.16,-27.11],[202.82,-26.41],[202.42,-25.72],[201.97,-25.03],[201.46,-24.35],[200.92,-23.67],[200.34,-23.01],[199.72,-22.35],[199.07,-21.7],[198.4,-21.06],[197.71,-20.43],[197.01,-19.8],[196.29,-19.18],[195.57,-18.56],[194.85,-17.95],[194.13,-17.34],[193.42,-16.73],[192.72,-16.13],[192.03,-15.53],[191.36,-14.92],[190.7,-14.32],[190.06,-13.71],[189.44,-13.1],[188.84,-12.48],[188.26,-11.87],[187.7,-11.24],[187.16,-10.61],[186.63,-9.97],[186.12,-9.33],[185.63,-8.68],[185.14,-8.02],[184.67,-7.36],[184.19,-6.69],[183.73,-6.02],[183.26,-5.34],[182.78,-4.65],[182.3,-3.96],[181.8,-3.28],[181.29,-2.59],[180.76,-1.9],[180.2,-1.21],[179.62,-0.53],[179.0,0.14],[178.35,0.81],[177.66,1.47],[176.93,2.11],[176.16,2.74],[175.34,3.35],[174.47,3.94],[173.55,4.52],[172.59,5.06],[171.57,5.59],[170.5,6.08],[169.38,6.55],[168.2,6.99],[166.98,7.39],[165.71,7.77],[164.39,8.1],[163.02,8.41],[161.62,8.67],[160.17,8.9],[158.68,9.09],[157.17,9.25],[155.62,9.37],[154.04,9.45],[152.45,9.5],[150.83,9.51],[149.2,9.49],[147.56,9.44],[145.91,9.36],[144.26,9.25],[142.62,9.12],[140.98,8.96],[139.35,8.78],[137.73,8.59],[136.13,8.38],[134.55,8.15],[132.99,7.92],[131.45,7.68],[129.95,7.44],[128.47,7.2],[127.02,6.96],[125.6,6.73],[124.22,6.5],[122.86,6.29],[121.54,6.09],[120.25,5.91],[119.0,5.75],[117.77,5.61],[116.57,5.49],[115.4,5.4],[114.25,5.33],[113.13,5.3],[112.02,5.29],[110.94,5.3],[109.87,5.35],[108.81,5.43],[107.76,5.53],[106.72,5.67],[105.69,5.83],[104.65,6.02],[103.62,6.23],[102.58,6.47],[101.53,6.73],[100.47,7.01],[99.41,7.3],[98.33,7.61],[97.24,7.94],[96.13,8.27],[95.0,8.61],[93.86,8.95],[92.69,9.3],[91.51,9.64],[90.31,9.98],[89.1,10.31],[87.86,10.63],[86.61,10.94],[85.34,11.23],[84.06,11.51],[82.76,11.76],[81.46,11.99],[80.14,12.2],[78.82,12.38],[77.49,12.53],[76.16,12.65],[74.83,12.74],[73.5,12.81],[72.17,12.84],[70.85,12.84],[69.54,12.81],[68.23,12.74],[66.94,12.65],[65.66,12.53],[64.4,12.37],[63.15,12.19],[61.92,11.99],[60.71,11.75],[59.52,11.5],[58.34,11.22],[57.18,10.93],[56.04,10.62],[54.91,10.29],[53.81,9.95],[52.71,9.6],[51.63,9.24],[50.56,8.87],[49.5,8.5],[48.44,8.13],[47.39,7.76],[46.34,7.39],[45.3,7.03],[44.24,6.66],[43.18,6.31],[42.12,5.96],[41.04,5.63],[39.94,5.3],[38.83,4.98],[37.7,4.67],[36.55,4.37],[35.38,4.08],[34.18,3.81],[32.96,3.54],[31.7,3.28],[30.42,3.03],[29.11,2.79],[27.78,2.56],[26.41,2.32],[25.02,2.1],[23.6,1.87],[22.16,1.64],[20.7,1.41],[19.21,1.18],[17.71,0.94],[16.2,0.69],[14.68,0.43],[13.15,0.16],[11.62,-0.12],[10.1,-0.42],[8.58,-0.73],[7.08,-1.06],[5.6,-1.42],[4.14,-1.79],[2.71,-2.19],[1.32,-2.61],[-0.03,-3.06],[-1.34,-3.53],[-2.59,-4.03],[-3.79,-4.55],[-4.93,-5.1],[-6.0,-5.67],[-7.0,-6.27],[-7.92,-6.89],[-8.77,-7.54],[-9.53,-8.21],[-10.22,-8.9],[-10.81,-9.61],[-11.32,-10.34],[-11.74,-11.09],[-12.07,-11.86],[-12.31,-12.64],[-12.47,-13.43],[-12.53,-14.24],[-12.51,-15.05],[-12.41,-15.87],[-12.22,-16.69],[-11.96,-17.52],[-11.62,-18.35],[-11.22,-19.17],[-10.75,-20.0],[-10.22,-20.82],[-9.63,-21.63],[-9.0,-22.44],[-8.32,-23.24],[-7.61,-24.03],[-6.86,-24.81],[-6.09,-25.57],[-5.31,-26.33],[-4.51,-27.07],[-3.7,-27.8],[-2.89,-28.52],[-2.09,-29.22],[-1.31,-29.91],[-0.53,-30.58],[0.22,-31.25],[0.94,-31.9],[1.63,-32.54],[2.29,-33.17],[2.91,-33.79],[3.49,-34.4],[4.03,-35.0],[4.52,-35.6],[4.97,-36.19],[5.37,-36.77],[5.73,-37.35],[6.04,-37.93],[6.31,-38.51],[6.53,-39.09],[6.71,-39.67],[6.85,-40.25],[6.96,-40.83],[7.04,-41.42],[7.09,-42.0],[7.11,-42.6],[7.12,-43.19],[7.11,-43.79],[7.08,-44.4],[7.06,-45.01],[7.03,-45.62],[7.0,-46.24],[6.99,-46.86],[6.98,-47.49],[7.0,-48.11],[7.04,-48.74],[7.1,-49.37],[7.2,-49.99],[7.33,-50.62],[7.51,-51.24],[7.72,-51.85],[7.97,-52.47],[8.28,-53.07],[8.63,-53.67],[9.03,-54.25],[9.48,-54.83],[9.98,-55.4],[10.53,-55.95],[11.13,-56.5],[11.78,-57.02],[12.48,-57.54],[13.22,-58.04],[14.01,-58.52],[14.84,-58.99],[15.7,-59.44],[16.6,-59.88],[17.53,-60.31],[18.49,-60.72],[19.47,-61.11],[20.47,-61.5],[21.48,-61.87],[22.51,-62.23],[23.54,-62.58],[24.58,-62.93],[25.61,-63.26],[26.64,-63.6],[27.66,-63.93],[28.67,-64.26],[29.66,-64.59],[30.64,-64.93],[31.59,-65.27],[32.52,-65.62],[33.43,-65.97],[34.31,-66.34],[35.16,-66.72],[35.98,-67.12],[36.78,-67.53],[37.54,-67.96],[38.28,-68.41],[38.99,-68.87],[39.68,-69.37],[40.34,-69.88],[40.98,-70.41],[41.6,-70.97],[42.2,-71.55],[42.8,-72.16],[43.37,-72.79],[43.95,-73.43],[44.52,-74.1],[45.09,-74.79],[45.66,-75.5],[46.24,-76.23],[46.83,-76.97],[47.44,-77.72],[48.06,-78.49],[48.71,-79.26],[49.38,-80.04],[50.08,-80.82],[50.82,-81.6],[51.58,-82.37],[52.39,-83.15],[53.23,-83.91],[54.11,-84.66],[55.04,-85.39],[56.0,-86.1],[57.01,-86.8],[58.07,-87.46],[59.17,-88.1],[60.31,-88.71],[61.49,-89.29],[62.71,-89.83],[63.98,-90.33],[65.28,-90.79],[66.62,-91.22],[67.99,-91.6],[69.39,-91.93],[70.82,-92.22],[72.28,-92.46],[73.75,-92.66],[75.25,-92.82],[76.76,-92.92],[78.29,-92.98],[79.82,-93.0],[81.36,-92.97],[82.9,-92.9],[84.44,-92.8],[85.98,-92.65],[87.51,-92.46],[89.04,-92.24],[90.55,-91.99],[92.05,-91.71],[93.53,-91.41],[95.0,-91.07],[96.45,-90.72],[97.88,-90.35],[99.29,-89.97],[100.68,-89.57],[102.06,-89.16],[103.41,-88.74],[104.74,-88.33],[106.05,-87.91],[107.35,-87.49],[108.63,-87.07],[109.89,-86.66],[111.14,-86.26],[112.38,-85.87],[113.6,-85.49],[114.82,-85.12],[116.03,-84.76],[117.23,-84.42],[118.43,-84.09],[119.63,-83.78],[120.82,-83.48],[122.02,-83.2],[123.22,-82.93],[124.43,-82.67],[125.64,-82.43],[126.85,-82.2],[128.07,-81.98],[129.3,-81.77],[130.53,-81.56],[131.77,-81.36],[133.02,-81.17],[134.26,-80.97],[135.52,-80.78],[136.77,-80.58],[138.02,-80.37],[139.28,-80.16],[140.53,-79.94],[141.77,-79.71],[143.0,-79.47],[144.22,-79.21],[145.43,-78.94],[146.62,-78.64],[147.78,-78.33],[148.93,-78.0],[150.05,-77.64],[151.13,-77.26],[152.19,-76.86],[153.2,-76.43],[154.18,-75.98],[155.12,-75.5],[156.02,-75.0],[156.86,-74.48],[157.67,-73.93],[158.42,-73.36],[159.12,-72.77],[159.77,-72.15],[160.38,-71.52],[160.93,-70.88],[161.43,-70.21],[161.88,-69.54],[162.28,-68.85],[162.64,-68.15],[162.96,-67.44],[163.23,-66.73],[163.47,-66.01],[163.67,-65.29],[163.84,-64.58],[163.98,-63.86],[164.1,-63.15],[164.21,-62.44],[164.3,-61.75],[164.38,-61.06],[164.46,-60.39],[164.54,-59.72],[164.63,-59.07],[164.74,-58.44],[164.86,-57.82],[165.0,-57.22],[165.17,-56.63],[165.38,-56.06],[165.62,-55.51],[165.9,-54.97],[166.23,-54.46],[166.61,-53.95],[167.03,-53.46],[167.52,-52.99],[168.05,-52.53],[168.64,-52.08],[169.29,-51.64],[170.0,-51.21],[170.77,-50.79],[171.59,-50.37],[172.47,-49.96],[173.41,-49.55],[174.39,-49.14],[175.43,-48.73],[176.51,-48.32],[177.63,-47.91],[178.79,-47.48],[179.98,-47.06],[181.2,-46.62],[182.44,-46.17],[183.69,-45.71],[184.96,-45.24],[186.23,-44.75],[187.5,-44.26],[188.75,-43.74],[190.0,-43.21],[191.22,-42.67],[192.42,-42.11],[193.58,-41.53],[194.7,-40.94],[195.78,-40.33],[196.8,-39.71],[197.77,-39.07],[198.68,-38.42],[199.53,-37.76],[200.3,-37.08],[201.01,-36.4],[201.64,-35.7],[202.2,-35.0]],[[207.29,-35.0],[207.81,-34.26],[208.25,-33.51],[208.6,-32.75],[208.87,-32.0],[209.05,-31.24],[209.15,-30.48],[209.17,-29.72],[209.1,-28.97],[208.96,-28.22],[208.74,-27.47],[208.46,-26.72],[208.1,-25.99],[207.69,-25.26],[207.21,-24.54],[206.68,-23.83],[206.1,-23.12],[205.48,-22.43],[204.81,-21.74],[204.12,-21.06],[203.4,-20.39],[202.65,-19.73],[201.89,-19.07],[201.11,-18.43],[200.33,-17.78],[199.54,-17.15],[198.75,-16.52],[197.97,-15.89],[197.2,-15.27],[196.44,-14.64],[195.69,-14.02],[194.96,-13.4],[194.25,-12.77],[193.56,-12.15],[192.88,-11.51],[192.23,-10.88],[191.6,-10.24],[190.99,-9.6],[190.4,-8.94],[189.82,-8.29],[189.26,-7.62],[188.72,-6.95],[188.19,-6.27],[187.66,-5.59],[187.14,-4.9],[186.62,-4.21],[186.09,-3.51],[185.56,-2.8],[185.02,-2.1],[184.47,-1.39],[183.89,-0.69],[183.3,0.01],[182.68,0.71],[182.02,1.41],[181.34,2.09],[180.61,2.77],[179.85,3.43],[179.05,4.08],[178.19,4.71],[177.3,5.33],[176.35,5.92],[175.35,6.49],[174.3,7.03],[173.2,7.55],[172.04,8.04],[170.83,8.5],[169.57,8.92],[168.27,9.31],[166.91,9.67],[165.5,9.99],[164.06,10.27],[162.57,10.52],[161.04,10.72],[159.47,10.89],[157.88,11.02],[156.26,11.12],[154.61,11.17],[152.94,11.19],[151.26,11.18],[149.56,11.13],[147.86,11.06],[146.16,10.95],[144.45,10.82],[142.76,10.66],[141.07,10.48],[139.39,10.28],[137.73,10.07],[136.09,9.84],[134.47,9.6],[132.88,9.35],[131.32,9.1],[129.78,8.85],[128.27,8.6],[126.8,8.36],[125.36,8.13],[123.95,7.9],[122.58,7.7],[121.24,7.51],[119.93,7.33],[118.65,7.19],[117.4,7.06],[116.18,6.96],[114.99,6.89],[113.82,6.84],[112.68,6.83],[111.55,6.85],[110.44,6.89],[109.34,6.97],[108.25,7.08],[107.17,7.22],[106.09,7.39],[105.02,7.59],[103.94,7.81],[102.87,8.06],[101.78,8.33],[100.68,8.63],[99.58,8.94],[98.46,9.27],[97.32,9.62],[96.17,9.97],[95.0,10.34],[93.81,10.71],[92.6,11.08],[91.37,11.45],[90.12,11.82],[88.85,12.18],[87.56,12.53],[86.26,12.87],[84.93,13.19],[83.59,13.5],[82.23,13.78],[80.86,14.04],[79.48,14.28],[78.1,14.49],[76.7,14.67],[75.3,14.82],[73.9,14.93],[72.5,15.02],[71.1,15.07],[69.71,15.09],[68.32,15.08],[66.95,15.03],[65.58,14.95],[64.23,14.84],[62.9,14.7],[61.58,14.52],[60.28,14.32],[59.0,14.09],[57.73,13.84],[56.49,13.56],[55.26,13.26],[54.05,12.94],[52.87,12.6],[51.7,12.25],[50.54,11.89],[49.4,11.51],[48.27,11.13],[47.16,10.74],[46.05,10.35],[44.95,9.95],[43.86,9.56],[42.76,9.17],[41.66,8.78],[40.56,8.4],[39.45,8.03],[38.34,7.66],[37.2,7.3],[36.06,6.95],[34.89,6.62],[33.71,6.29],[32.5,5.97],[31.27,5.67],[30.01,5.37],[28.73,5.08],[27.42,4.81],[26.08,4.53],[24.71,4.27],[23.31,4.01],[21.88,3.76],[20.43,3.5],[18.96,3.25],[17.46,3.0],[15.94,2.74],[14.4,2.48],[12.85,2.21],[11.29,1.93],[9.72,1.64],[8.15,1.33],[6.59,1.01],[5.03,0.68],[3.49,0.32],[1.96,-0.05],[0.46,-0.45],[-1.02,-0.87],[-2.45,-1.31],[-3.85,-1.77],[-5.2,-2.27],[-6.5,-2.79],[-7.74,-3.33],[-8.92,-3.9],[-10.03,-4.5],[-11.06,-5.12],[-12.03,-5.77],[-12.91,-6.44],[-13.71,-7.14],[-14.42,-7.86],[-15.04,-8.6],[-15.57,-9.36],[-16.01,-10.14],[-16.36,-10.93],[-16.62,-11.74],[-16.78,-12.57],[-16.85,-13.4],[-16.83,-14.25],[-16.72,-15.1],[-16.53,-15.96],[-16.26,-16.82],[-15.91,-17.68],[-15.48,-18.54],[-14.99,-19.4],[-14.43,-20.25],[-13.81,-21.1],[-13.14,-21.94],[-12.43,-22.77],[-11.67,-23.59],[-10.88,-24.41],[-10.07,-25.2],[-9.23,-25.99],[-8.38,-26.76],[-7.52,-27.52],[-6.66,-28.27],[-5.8,-29.0],[-4.96,-29.72],[-4.13,-30.42],[-3.33,-31.11],[-2.55,-31.78],[-1.8,-32.45],[-1.09,-33.1],[-0.42,-33.74],[0.21,-34.38],[0.79,-35.0],[1.33,-35.62],[1.82,-36.23],[2.26,-36.83],[2.65,-37.43],[2.99,-38.03],[3.29,-38.63],[3.53,-39.23],[3.73,-39.83],[3.89,-40.42],[4.01,-41.03],[4.09,-41.63],[4.15,-42.24],[4.17,-42.85],[4.17,-43.47],[4.15,-44.09],[4.11,-44.72],[4.07,-45.35],[4.02,-45.99],[3.97,-46.63],[3.93,-47.27],[3.9,-47.92],[3.89,-48.58],[3.9,-49.23],[3.93,-49.88],[4.0,-50.54],[4.1,-51.19],[4.24,-51.84],[4.42,-52.49],[4.64,-53.13],[4.91,-53.77],[5.23,-54.4],[5.6,-55.02],[6.02,-55.63],[6.5,-56.23],[7.03,-56.82],[7.61,-57.4],[8.24,-57.96],[8.92,-58.51],[9.65,-59.04],[10.43,-59.56],[11.25,-60.06],[12.12,-60.55],[13.02,-61.02],[13.95,-61.48],[14.92,-61.92],[15.91,-62.34],[16.93,-62.76],[17.96,-63.16],[19.01,-63.55],[20.07,-63.92],[21.13,-64.29],[22.19,-64.66],[23.26,-65.01],[24.31,-65.37],[25.36,-65.72],[26.39,-66.07],[27.41,-66.43],[28.41,-66.79],[29.38,-67.16],[30.33,-67.53],[31.26,-67.92],[32.15,-68.31],[33.02,-68.73],[33.86,-69.15],[34.68,-69.6],[35.46,-70.07],[36.22,-70.55],[36.95,-71.06],[37.66,-71.59],[38.35,-72.14],[39.01,-72.72],[39.66,-73.32],[40.29,-73.94],[40.92,-74.59],[41.53,-75.25],[42.14,-75.95],[42.75,-76.66],[43.36,-77.39],[43.98,-78.14],[44.61,-78.9],[45.26,-79.68],[45.92,-80.47],[46.61,-81.27],[47.32,-82.07],[48.06,-82.88],[48.83,-83.69],[49.64,-84.5],[50.48,-85.3],[51.37,-86.09],[52.29,-86.87],[53.26,-87.63],[54.27,-88.37],[55.33,-89.09],[56.43,-89.79],[57.58,-90.46],[58.77,-91.09],[60.0,-91.7],[61.28,-92.26],[62.6,-92.79],[63.96,-93.28],[65.35,-93.72],[66.79,-94.12],[68.25,-94.47],[69.74,-94.78],[71.26,-95.03],[72.8,-95.24],[74.37,-95.4],[75.95,-95.52],[77.54,-95.58],[79.14,-95.6],[80.75,-95.57],[82.36,-95.5],[83.97,-95.38],[85.58,-95.22],[87.18,-95.03],[88.77,-94.79],[90.35,-94.52],[91.92,-94.22],[93.47,-93.89],[95.0,-93.54],[96.51,-93.16],[98.01,-92.76],[99.48,-92.34],[100.93,-91.91],[102.36,-91.47],[103.77,-91.03],[105.15,-90.57],[106.52,-90.12],[107.86,-89.66],[109.19,-89.21],[110.5,-88.76],[111.79,-88.32],[113.07,-87.89],[114.33,-87.47],[115.59,-87.06],[116.83,-86.67],[118.07,-86.29],[119.31,-85.93],[120.54,-85.59],[121.77,-85.26],[123.0,-84.94],[124.23,-84.65],[125.47,-84.36],[126.71,-84.09],[127.96,-83.84],[129.21,-83.59],[130.47,-83.36],[131.73,-83.14],[133.01,-82.92],[134.28,-82.71],[135.57,-82.5],[136.86,-82.29],[138.15,-82.08],[139.44,-81.87],[140.73,-81.65],[142.02,-81.42],[143.31,-81.19],[144.59,-80.94],[145.85,-80.68],[147.11,-80.4],[148.34,-80.1],[149.56,-79.79],[150.75,-79.45],[151.92,-79.09],[153.06,-78.71],[154.17,-78.31],[155.24,-77.88],[156.27,-77.42],[157.26,-76.94],[158.21,-76.44],[159.11,-75.91],[159.97,-75.36],[160.77,-74.78],[161.53,-74.18],[162.23,-73.56],[162.88,-72.92],[163.48,-72.27],[164.03,-71.59],[164.53,-70.9],[164.97,-70.2],[165.37,-69.49],[165.73,-68.76],[166.04,-68.03],[166.31,-67.3],[166.55,-66.56],[166.75,-65.82],[166.92,-65.09],[167.07,-64.36],[167.2,-63.63],[167.31,-62.91],[167.42,-62.2],[167.52,-61.5],[167.62,-60.82],[167.73,-60.14],[167.85,-59.49],[167.98,-58.84],[168.14,-58.22],[168.33,-57.6],[168.55,-57.01],[168.81,-56.44],[169.11,-55.88],[169.45,-55.33],[169.84,-54.81],[170.29,-54.3],[170.79,-53.8],[171.34,-53.32],[171.96,-52.85],[172.63,-52.39],[173.37,-51.94],[174.16,-51.49],[175.02,-51.06],[175.93,-50.63],[176.91,-50.2],[177.93,-49.77],[179.01,-49.35],[180.14,-48.91],[181.31,-48.48],[182.51,-48.04],[183.76,-47.59],[185.03,-47.14],[186.33,-46.67],[187.65,-46.19],[188.98,-45.7],[190.32,-45.19],[191.65,-44.67],[192.98,-44.13],[194.29,-43.58],[195.58,-43.01],[196.84,-42.43],[198.08,-41.83],[199.27,-41.21],[200.41,-40.57],[201.5,-39.92],[202.54,-39.26],[203.51,-38.58],[204.42,-37.88],[205.25,-37.18],[206.01,-36.46],[206.69,-35.74],[207.29,-35.0]],[[212.42,-35.0],[212.99,-34.22],[213.46,-33.44],[213.85,-32.65],[214.14,-31.86],[214.35,-31.06],[214.47,-30.27],[214.5,-29.48],[214.45,-28.68],[214.31,-27.9],[214.09,-27.11],[213.79,-26.34],[213.43,-25.56],[212.99,-24.8],[212.49,-24.05],[211.93,-23.3],[211.31,-22.56],[210.65,-21.84],[209.94,-21.12],[209.2,-20.41],[208.42,-19.71],[207.62,-19.02],[206.79,-18.34],[205.95,-17.67],[205.1,-17.0],[204.25,-16.35],[203.39,-15.69],[202.53,-15.04],[201.69,-14.4],[200.85,-13.76],[200.03,-13.12],[199.22,-12.48],[198.43,-11.84],[197.66,-11.19],[196.91,-10.55],[196.19,-9.9],[195.48,-9.25],[194.8,-8.59],[194.14,-7.92],[193.5,-7.25],[192.87,-6.58],[192.26,-5.89],[191.67,-5.2],[191.08,-4.5],[190.5,-3.8],[189.93,-3.09],[189.35,-2.38],[188.77,-1.66],[188.19,-0.94],[187.59,-0.22],[186.97,0.5],[186.33,1.22],[185.67,1.94],[184.98,2.65],[184.26,3.35],[183.51,4.04],[182.71,4.73],[181.87,5.4],[180.99,6.05],[180.06,6.68],[179.08,7.3],[178.05,7.89],[176.97,8.45],[175.84,8.99],[174.65,9.5],[173.41,9.98],[172.12,10.42],[170.77,10.83],[169.38,11.2],[167.94,11.54],[166.45,11.84],[164.92,12.1],[163.35,12.33],[161.75,12.51],[160.11,12.65],[158.44,12.76],[156.74,12.83],[155.03,12.86],[153.29,12.85],[151.55,12.81],[149.79,12.74],[148.04,12.64],[146.28,12.51],[144.52,12.35],[142.78,12.17],[141.05,11.97],[139.33,11.75],[137.63,11.52],[135.96,11.27],[134.31,11.02],[132.68,10.76],[131.09,10.51],[129.53,10.25],[128.0,10.0],[126.51,9.75],[125.04,9.52],[123.62,9.31],[122.23,9.11],[120.87,8.93],[119.54,8.77],[118.24,8.63],[116.98,8.53],[115.74,8.45],[114.52,8.4],[113.33,8.38],[112.16,8.4],[111.01,8.45],[109.87,8.53],[108.74,8.64],[107.62,8.78],[106.5,8.96],[105.39,9.16],[104.28,9.4],[103.16,9.66],[102.03,9.94],[100.9,10.26],[99.75,10.59],[98.59,10.94],[97.41,11.3],[96.21,11.68],[95.0,12.07],[93.76,12.47],[92.51,12.87],[91.23,13.27],[89.93,13.67],[88.61,14.06],[87.26,14.44],[85.9,14.81],[84.52,15.16],[83.12,15.5],[81.7,15.82],[80.27,16.11],[78.82,16.37],[77.37,16.61],[75.91,16.82],[74.44,17.0],[72.97,17.14],[71.49,17.25],[70.02,17.33],[68.56,17.37],[67.1,17.38],[65.65,17.35],[64.21,17.28],[62.79,17.18],[61.38,17.05],[59.99,16.89],[58.61,16.69],[57.26,16.46],[55.92,16.21],[54.61,15.93],[53.31,15.62],[52.04,15.3],[50.79,14.95],[49.55,14.59],[48.34,14.21],[47.14,13.82],[45.96,13.42],[44.78,13.01],[43.63,12.6],[42.47,12.18],[41.33,11.76],[40.19,11.34],[39.05,10.93],[37.9,10.52],[36.76,10.12],[35.6,9.72],[34.43,9.33],[33.25,8.95],[32.05,8.58],[30.83,8.22],[29.6,7.88],[28.33,7.54],[27.05,7.21],[25.73,6.89],[24.39,6.59],[23.02,6.29],[21.62,5.99],[20.2,5.71],[18.74,5.42],[17.26,5.14],[15.75,4.86],[14.22,4.58],[12.67,4.3],[11.1,4.01],[9.52,3.72],[7.92,3.41],[6.32,3.1],[4.71,2.77],[3.11,2.43],[1.51,2.07],[-0.08,1.7],[-1.64,1.3],[-3.19,0.89],[-4.7,0.45],[-6.18,-0.02],[-7.62,-0.51],[-9.01,-1.02],[-10.35,-1.56],[-11.64,-2.13],[-12.85,-2.72],[-14.0,-3.34],[-15.08,-3.99],[-16.08,-4.66],[-16.99,-5.36],[-17.82,-6.08],[-18.57,-6.83],[-19.22,-7.6],[-19.77,-8.38],[-20.23,-9.19],[-20.6,-10.02],[-20.87,-10.86],[-21.04,-11.71],[-21.12,-12.58],[-21.1,-13.45],[-20.99,-14.34],[-20.79,-15.23],[-20.51,-16.12],[-20.14,-17.02],[-19.7,-17.91],[-19.18,-18.8],[-18.6,-19.69],[-17.95,-20.57],[-17.25,-21.44],[-16.5,-22.31],[-15.7,-23.16],[-14.87,-24.01],[-14.01,-24.84],[-13.12,-25.65],[-12.22,-26.46],[-11.31,-27.25],[-10.39,-28.02],[-9.48,-28.78],[-8.58,-29.52],[-7.7,-30.25],[-6.84,-30.97],[-6.01,-31.67],[-5.21,-32.36],[-4.44,-33.03],[-3.72,-33.7],[-3.04,-34.35],[-2.41,-35.0],[-1.83,-35.64],[-1.3,-36.27],[-0.82,-36.89],[-0.39,-37.51],[-0.02,-38.13],[0.3,-38.75],[0.57,-39.36],[0.79,-39.98],[0.96,-40.6],[1.09,-41.22],[1.18,-41.84],[1.24,-42.47],[1.26,-43.1],[1.25,-43.74],[1.22,-44.38],[1.17,-45.03],[1.11,-45.69],[1.04,-46.35],[0.97,-47.01],[0.91,-47.68],[0.85,-48.36],[0.81,-49.04],[0.78,-49.72],[0.79,-50.4],[0.81,-51.08],[0.88,-51.77],[0.98,-52.45],[1.12,-53.13],[1.31,-53.8],[1.55,-54.47],[1.83,-55.14],[2.17,-55.79],[2.56,-56.44],[3.01,-57.07],[3.51,-57.7],[4.06,-58.31],[4.68,-58.91],[5.34,-59.49],[6.06,-60.06],[6.82,-60.61],[7.63,-61.15],[8.49,-61.67],[9.39,-62.17],[10.33,-62.66],[11.3,-63.13],[12.3,-63.59],[13.33,-64.03],[14.38,-64.46],[15.45,-64.88],[16.53,-65.29],[17.62,-65.69],[18.72,-66.07],[19.81,-66.46],[20.9,-66.83],[21.99,-67.21],[23.06,-67.58],[24.12,-67.96],[25.16,-68.34],[26.17,-68.73],[27.17,-69.12],[28.14,-69.52],[29.09,-69.94],[30.01,-70.37],[30.9,-70.81],[31.76,-71.27],[32.59,-71.76],[33.4,-72.26],[34.18,-72.78],[34.94,-73.32],[35.67,-73.89],[36.38,-74.49],[37.08,-75.1],[37.76,-75.74],[38.42,-76.41],[39.08,-77.1],[39.74,-77.81],[40.39,-78.54],[41.04,-79.29],[41.71,-80.06],[42.38,-80.85],[43.06,-81.65],[43.77,-82.46],[44.49,-83.29],[45.25,-84.12],[46.03,-84.95],[46.84,-85.79],[47.69,-86.62],[48.58,-87.45],[49.5,-88.27],[50.47,-89.08],[51.48,-89.87],[52.54,-90.64],[53.64,-91.39],[54.79,-92.11],[55.99,-92.81],[57.23,-93.47],[58.52,-94.1],[59.85,-94.69],[61.22,-95.24],[62.64,-95.75],[64.09,-96.21],[65.59,-96.63],[67.11,-97.0],[68.67,-97.32],[70.25,-97.59],[71.86,-97.81],[73.49,-97.98],[75.13,-98.1],[76.79,-98.17],[78.46,-98.19],[80.14,-98.16],[81.82,-98.08],[83.5,-97.96],[85.18,-97.79],[86.85,-97.58],[88.51,-97.33],[90.15,-97.05],[91.79,-96.73],[93.4,-96.37],[95.0,-95.99],[96.58,-95.59],[98.13,-95.16],[99.66,-94.72],[101.17,-94.25],[102.66,-93.78],[104.12,-93.29],[105.56,-92.8],[106.97,-92.31],[108.37,-91.82],[109.74,-91.33],[111.1,-90.84],[112.43,-90.36],[113.75,-89.89],[115.06,-89.44],[116.35,-88.99],[117.63,-88.56],[118.91,-88.15],[120.18,-87.75],[121.44,-87.37],[122.7,-87.01],[123.96,-86.66],[125.23,-86.33],[126.49,-86.02],[127.77,-85.73],[129.04,-85.45],[130.32,-85.18],[131.61,-84.92],[132.91,-84.68],[134.22,-84.45],[135.53,-84.22],[136.84,-83.99],[138.17,-83.77],[139.5,-83.55],[140.83,-83.33],[142.16,-83.1],[143.49,-82.87],[144.81,-82.63],[146.14,-82.37],[147.45,-82.11],[148.75,-81.83],[150.03,-81.53],[151.3,-81.21],[152.54,-80.88],[153.76,-80.52],[154.95,-80.14],[156.11,-79.73],[157.24,-79.3],[158.33,-78.85],[159.37,-78.36],[160.38,-77.86],[161.34,-77.33],[162.25,-76.77],[163.11,-76.19],[163.91,-75.59],[164.67,-74.96],[165.37,-74.32],[166.03,-73.65],[166.62,-72.97],[167.17,-72.27],[167.66,-71.55],[168.11,-70.83],[168.51,-70.09],[168.86,-69.34],[169.17,-68.59],[169.44,-67.84],[169.68,-67.08],[169.88,-66.33],[170.06,-65.58],[170.22,-64.83],[170.36,-64.09],[170.49,-63.36],[170.61,-62.64],[170.74,-61.93],[170.87,-61.23],[171.0,-60.55],[171.16,-59.88],[171.34,-59.23],[171.54,-58.59],[171.77,-57.98],[172.05,-57.38],[172.36,-56.79],[172.72,-56.23],[173.13,-55.68],[173.59,-55.14],[174.11,-54.63],[174.69,-54.12],[175.33,-53.63],[176.03,-53.15],[176.79,-52.68],[177.61,-52.21],[178.5,-51.76],[179.45,-51.31],[180.46,-50.86],[181.52,-50.41],[182.64,-49.96],[183.81,-49.52],[185.03,-49.06],[186.29,-48.6],[187.58,-48.13],[188.91,-47.66],[190.27,-47.17],[191.65,-46.67],[193.04,-46.16],[194.44,-45.63],[195.84,-45.09],[197.23,-44.53],[198.61,-43.96],[199.97,-43.36],[201.3,-42.75],[202.6,-42.13],[203.86,-41.48],[205.07,-40.82],[206.23,-40.14],[207.33,-39.45],[208.37,-38.74],[209.33,-38.01],[210.23,-37.28],[211.04,-36.53],[211.77,-35.77],[212.42,-35.0]],[[217.58,-35.0],[218.19,-34.19],[218.7,-33.37],[219.12,-32.55],[219.45,-31.72],[219.68,-30.89],[219.82,-30.06],[219.87,-29.23],[219.82,-28.4],[219.68,-27.58],[219.46,-26.76],[219.16,-25.94],[218.78,-25.14],[218.32,-24.34],[217.79,-23.55],[217.2,-22.77],[216.55,-22.0],[215.85,-21.24],[215.1,-20.5],[214.3,-19.76],[213.47,-19.03],[212.61,-18.31],[211.72,-17.61],[210.82,-16.91],[209.9,-16.22],[208.97,-15.54],[208.04,-14.86],[207.11,-14.2],[206.18,-13.53],[205.26,-12.87],[204.36,-12.21],[203.47,-11.56],[202.61,-10.9],[201.76,-10.24],[200.93,-9.58],[200.13,-8.92],[199.35,-8.26],[198.59,-7.58],[197.85,-6.91],[197.14,-6.23],[196.44,-5.54],[195.77,-4.84],[195.11,-4.14],[194.46,-3.43],[193.82,-2.72],[193.19,-2.0],[192.56,-1.27],[191.93,-0.54],[191.29,0.19],[190.65,0.93],[189.99,1.66],[189.31,2.4],[188.61,3.13],[187.88,3.86],[187.13,4.58],[186.33,5.29],[185.51,5.99],[184.64,6.68],[183.72,7.35],[182.76,8.01],[181.75,8.64],[180.69,9.25],[179.58,9.84],[178.42,10.4],[177.2,10.92],[175.93,11.42],[174.61,11.89],[173.23,12.32],[171.81,12.71],[170.33,13.07],[168.81,13.39],[167.24,13.67],[165.63,13.9],[163.99,14.1],[162.31,14.26],[160.59,14.38],[158.85,14.46],[157.09,14.5],[155.31,14.51],[153.52,14.48],[151.71,14.41],[149.9,14.31],[148.09,14.19],[146.28,14.03],[144.48,13.85],[142.7,13.65],[140.92,13.43],[139.17,13.2],[137.44,12.95],[135.73,12.69],[134.05,12.43],[132.4,12.16],[130.79,11.9],[129.2,11.64],[127.65,11.39],[126.14,11.15],[124.66,10.92],[123.22,10.71],[121.81,10.52],[120.43,10.36],[119.09,10.22],[117.77,10.11],[116.49,10.02],[115.23,9.97],[113.99,9.95],[112.78,9.96],[111.58,10.01],[110.4,10.09],[109.23,10.2],[108.07,10.35],[106.92,10.53],[105.76,10.75],[104.61,10.99],[103.45,11.27],[102.29,11.57],[101.11,11.89],[99.92,12.24],[98.72,12.61],[97.5,13.0],[96.26,13.41],[95.0,13.82],[93.72,14.24],[92.41,14.67],[91.09,15.1],[89.74,15.53],[88.36,15.95],[86.96,16.36],[85.54,16.76],[84.1,17.15],[82.64,17.52],[81.16,17.87],[79.67,18.19],[78.16,18.49],[76.64,18.76],[75.11,19.0],[73.57,19.2],[72.02,19.37],[70.48,19.51],[68.94,19.61],[67.4,19.67],[65.86,19.7],[64.34,19.69],[62.82,19.64],[61.32,19.56],[59.84,19.43],[58.37,19.28],[56.92,19.09],[55.5,18.86],[54.09,18.61],[52.7,18.33],[51.34,18.02],[50.0,17.69],[48.68,17.33],[47.38,16.96],[46.1,16.57],[44.85,16.16],[43.6,15.74],[42.38,15.31],[41.16,14.88],[39.96,14.44],[38.77,13.99],[37.58,13.55],[36.4,13.1],[35.21,12.67],[34.02,12.23],[32.83,11.8],[31.63,11.38],[30.41,10.97],[29.18,10.57],[27.93,10.18],[26.66,9.8],[25.37,9.43],[24.06,9.07],[22.72,8.72],[21.35,8.38],[19.95,8.05],[18.53,7.72],[17.08,7.4],[15.6,7.09],[14.09,6.78],[12.55,6.47],[10.99,6.17],[9.41,5.86],[7.81,5.54],[6.2,5.22],[4.57,4.89],[2.93,4.55],[1.29,4.2],[-0.35,3.84],[-1.98,3.46],[-3.6,3.06],[-5.21,2.64],[-6.79,2.2],[-8.35,1.74],[-9.87,1.25],[-11.35,0.74],[-12.78,0.21],[-14.16,-0.35],[-15.48,-0.94],[-16.74,-1.56],[-17.92,-2.2],[-19.04,-2.88],[-20.07,-3.57],[-21.02,-4.29],[-21.88,-5.04],[-22.65,-5.81],[-23.33,-6.61],[-23.91,-7.42],[-24.39,-8.26],[-24.78,-9.11],[-25.06,-9.98],[-25.24,-10.87],[-25.33,-11.77],[-25.31,-12.67],[-25.21,-13.59],[-25.0,-14.51],[-24.71,-15.43],[-24.33,-16.36],[-23.87,-17.29],[-23.34,-18.21],[-22.73,-19.13],[-22.05,-20.05],[-21.32,-20.95],[-20.53,-21.85],[-19.69,-22.74],[-18.82,-23.61],[-17.91,-24.47],[-16.98,-25.32],[-16.03,-26.15],[-15.06,-26.97],[-14.1,-27.77],[-13.13,-28.56],[-12.18,-29.33],[-11.24,-30.09],[-10.33,-30.83],[-9.44,-31.56],[-8.58,-32.27],[-7.77,-32.97],[-6.99,-33.66],[-6.26,-34.33],[-5.59,-35.0],[-4.96,-35.66],[-4.39,-36.31],[-3.87,-36.95],[-3.41,-37.59],[-3.01,-38.23],[-2.66,-38.87],[-2.37,-39.5],[-2.12,-40.14],[-1.94,-40.77],[-1.79,-41.41],[-1.7,-42.05],[-1.64,-42.7],[-1.62,-43.35],[-1.63,-44.01],[-1.67,-44.67],[-1.74,-45.34],[-1.81,-46.02],[-1.9,-46.7],[-2.0,-47.39],[-2.09,-48.09],[-2.18,-48.79],[-2.25,-49.49],[-2.31,-50.2],[-2.35,-50.91],[-2.36,-51.62],[-2.33,-52.34],[-2.27,-53.05],[-2.16,-53.76],[-2.01,-54.47],[-1.82,-55.17],[-1.57,-55.87],[-1.27,-56.56],[-0.91,-57.24],[-0.5,-57.91],[-0.03,-58.57],[0.5,-59.22],[1.09,-59.85],[1.73,-60.47],[2.43,-61.08],[3.18,-61.67],[3.98,-62.24],[4.83,-62.8],[5.72,-63.34],[6.66,-63.86],[7.63,-64.36],[8.64,-64.86],[9.68,-65.33],[10.75,-65.79],[11.83,-66.24],[12.94,-66.68],[14.05,-67.1],[15.18,-67.52],[16.3,-67.92],[17.43,-68.33],[18.55,-68.73],[19.66,-69.12],[20.76,-69.52],[21.84,-69.92],[22.91,-70.33],[23.95,-70.74],[24.97,-71.16],[25.97,-71.59],[26.93,-72.04],[27.88,-72.5],[28.79,-72.98],[29.67,-73.48],[30.53,-73.99],[31.36,-74.53],[32.17,-75.09],[32.95,-75.67],[33.72,-76.28],[34.46,-76.92],[35.19,-77.57],[35.9,-78.25],[36.61,-78.96],[37.31,-79.69],[38.01,-80.44],[38.71,-81.21],[39.41,-82.0],[40.13,-82.81],[40.86,-83.63],[41.6,-84.47],[42.37,-85.32],[43.17,-86.17],[43.99,-87.03],[44.85,-87.89],[45.74,-88.75],[46.67,-89.61],[47.64,-90.45],[48.65,-91.29],[49.71,-92.11],[50.81,-92.91],[51.96,-93.68],[53.16,-94.43],[54.41,-95.16],[55.7,-95.84],[57.04,-96.5],[58.42,-97.11],[59.85,-97.69],[61.33,-98.22],[62.84,-98.7],[64.39,-99.14],[65.98,-99.52],[67.59,-99.86],[69.24,-100.14],[70.91,-100.37],[72.61,-100.55],[74.32,-100.67],[76.05,-100.75],[77.79,-100.77],[79.53,-100.73],[81.28,-100.65],[83.03,-100.52],[84.78,-100.35],[86.51,-100.12],[88.24,-99.86],[89.96,-99.56],[91.66,-99.22],[93.34,-98.84],[95.0,-98.44],[96.64,-98.01],[98.26,-97.55],[99.85,-97.07],[101.42,-96.58],[102.96,-96.07],[104.47,-95.55],[105.96,-95.03],[107.43,-94.5],[108.87,-93.96],[110.29,-93.43],[111.69,-92.91],[113.07,-92.39],[114.43,-91.88],[115.77,-91.38],[117.1,-90.9],[118.42,-90.43],[119.73,-89.98],[121.03,-89.55],[122.33,-89.13],[123.62,-88.73],[124.91,-88.36],[126.21,-88.0],[127.5,-87.65],[128.8,-87.33],[130.11,-87.02],[131.42,-86.73],[132.74,-86.46],[134.06,-86.19],[135.4,-85.94],[136.74,-85.69],[138.09,-85.45],[139.45,-85.22],[140.81,-84.99],[142.18,-84.76],[143.55,-84.52],[144.92,-84.28],[146.29,-84.04],[147.65,-83.78],[149.01,-83.51],[150.35,-83.23],[151.69,-82.93],[153.0,-82.61],[154.3,-82.28],[155.57,-81.92],[156.82,-81.54],[158.03,-81.13],[159.21,-80.7],[160.35,-80.25],[161.46,-79.77],[162.52,-79.26],[163.53,-78.73],[164.5,-78.17],[165.42,-77.59],[166.29,-76.99],[167.1,-76.36],[167.86,-75.7],[168.56,-75.03],[169.21,-74.34],[169.81,-73.63],[170.36,-72.91],[170.85,-72.17],[171.29,-71.42],[171.69,-70.66],[172.04,-69.9],[172.36,-69.12],[172.63,-68.35],[172.87,-67.58],[173.09,-66.81],[173.28,-66.04],[173.45,-65.28],[173.6,-64.53],[173.75,-63.78],[173.9,-63.05],[174.05,-62.33],[174.21,-61.62],[174.39,-60.93],[174.58,-60.26],[174.8,-59.6],[175.06,-58.96],[175.35,-58.33],[175.68,-57.73],[176.05,-57.14],[176.48,-56.56],[176.96,-56.01],[177.5,-55.47],[178.1,-54.94],[178.76,-54.42],[179.48,-53.92],[180.27,-53.43],[181.12,-52.94],[182.04,-52.47],[183.02,-52.0],[184.06,-51.53],[185.16,-51.06],[186.32,-50.59],[187.53,-50.12],[188.8,-49.65],[190.1,-49.17],[191.45,-48.68],[192.84,-48.19],[194.25,-47.68],[195.68,-47.16],[197.13,-46.63],[198.6,-46.08],[200.06,-45.51],[201.52,-44.93],[202.96,-44.33],[204.39,-43.72],[205.79,-43.08],[207.16,-42.43],[208.49,-41.76],[209.76,-41.07],[210.99,-40.36],[212.15,-39.64],[213.25,-38.9],[214.28,-38.14],[215.23,-37.38],[216.1,-36.6],[216.88,-35.8],[217.58,-35.0]],[[222.76,-35.0],[223.41,-34.15],[223.97,-33.3],[224.42,-32.44],[224.78,-31.58],[225.04,-30.71],[225.2,-29.85],[225.26,-28.98],[225.22,-28.12],[225.09,-27.25],[224.86,-26.4],[224.55,-25.55],[224.16,-24.71],[223.68,-23.88],[223.13,-23.05],[222.51,-22.24],[221.82,-21.44],[221.07,-20.65],[220.27,-19.87],[219.43,-19.1],[218.54,-18.35],[217.62,-17.6],[216.67,-16.87],[215.69,-16.15],[214.7,-15.44],[213.7,-14.73],[212.69,-14.04],[211.68,-13.35],[210.68,-12.66],[209.68,-11.99],[208.69,-11.31],[207.72,-10.64],[206.77,-9.97],[205.84,-9.3],[204.93,-8.62],[204.05,-7.95],[203.19,-7.27],[202.35,-6.59],[201.54,-5.9],[200.75,-5.21],[199.98,-4.51],[199.24,-3.81],[198.51,-3.09],[197.8,-2.37],[197.09,-1.65],[196.4,-0.92],[195.72,-0.18],[195.03,0.56],[194.34,1.31],[193.65,2.06],[192.94,2.81],[192.22,3.55],[191.48,4.3],[190.72,5.04],[189.92,5.78],[189.1,6.51],[188.24,7.23],[187.33,7.94],[186.39,8.63],[185.4,9.3],[184.36,9.95],[183.28,10.58],[182.14,11.19],[180.95,11.77],[179.7,12.32],[178.4,12.84],[177.05,13.32],[175.64,13.78],[174.19,14.19],[172.68,14.57],[171.12,14.9],[169.52,15.2],[167.88,15.46],[166.19,15.67],[164.47,15.85],[162.72,15.98],[160.94,16.08],[159.13,16.13],[157.31,16.14],[155.46,16.12],[153.61,16.07],[151.75,15.98],[149.89,15.85],[148.03,15.7],[146.18,15.53],[144.34,15.33],[142.51,15.11],[140.7,14.87],[138.92,14.62],[137.16,14.36],[135.42,14.09],[133.72,13.82],[132.05,13.55],[130.41,13.29],[128.81,13.03],[127.24,12.78],[125.71,12.55],[124.22,12.33],[122.76,12.13],[121.33,11.96],[119.94,11.82],[118.58,11.7],[117.24,11.61],[115.94,11.55],[114.66,11.53],[113.4,11.54],[112.16,11.59],[110.94,11.67],[109.73,11.78],[108.53,11.94],[107.33,12.13],[106.14,12.35],[104.95,12.6],[103.75,12.89],[102.54,13.2],[101.33,13.55],[100.1,13.91],[98.85,14.3],[97.59,14.71],[96.3,15.14],[95.0,15.58],[93.67,16.03],[92.32,16.48],[90.94,16.94],[89.54,17.4],[88.11,17.85],[86.66,18.3],[85.19,18.73],[83.69,19.15],[82.16,19.55],[80.62,19.93],[79.06,20.29],[77.49,20.62],[75.9,20.92],[74.3,21.19],[72.69,21.42],[71.07,21.62],[69.46,21.79],[67.84,21.91],[66.22,22.0],[64.61,22.05],[63.01,22.06],[61.42,22.02],[59.84,21.95],[58.28,21.84],[56.74,21.7],[55.22,21.51],[53.71,21.3],[52.23,21.04],[50.77,20.76],[49.34,20.45],[47.93,20.11],[46.54,19.75],[45.18,19.36],[43.84,18.95],[42.52,18.53],[41.22,18.09],[39.94,17.65],[38.67,17.19],[37.42,16.72],[36.18,16.25],[34.94,15.78],[33.71,15.31],[32.49,14.84],[31.26,14.37],[30.03,13.91],[28.79,13.46],[27.54,13.01],[26.28,12.58],[25.01,12.15],[23.71,11.74],[22.39,11.33],[21.05,10.94],[19.69,10.55],[18.29,10.18],[16.88,9.81],[15.43,9.45],[13.95,9.1],[12.45,8.76],[10.92,8.42],[9.36,8.08],[7.77,7.74],[6.17,7.41],[4.54,7.06],[2.9,6.72],[1.24,6.36],[-0.42,6.0],[-2.1,5.62],[-3.77,5.23],[-5.43,4.83],[-7.09,4.41],[-8.73,3.96],[-10.35,3.5],[-11.94,3.02],[-13.5,2.51],[-15.01,1.98],[-16.49,1.42],[-17.9,0.83],[-19.26,0.22],[-20.56,-0.42],[-21.78,-1.08],[-22.93,-1.78],[-24.0,-2.5],[-24.98,-3.25],[-25.87,-4.02],[-26.67,-4.82],[-27.38,-5.64],[-27.98,-6.48],[-28.49,-7.34],[-28.89,-8.22],[-29.19,-9.12],[-29.39,-10.04],[-29.48,-10.96],[-29.47,-11.9],[-29.36,-12.85],[-29.16,-13.8],[-28.86,-14.76],[-28.47,-15.71],[-28.0,-16.67],[-27.44,-17.63],[-26.81,-18.58],[-26.11,-19.53],[-25.34,-20.47],[-24.52,-21.4],[-23.65,-22.31],[-22.74,-23.22],[-21.78,-24.11],[-20.81,-24.99],[-19.81,-25.85],[-18.79,-26.7],[-17.78,-27.53],[-16.76,-28.35],[-15.75,-29.14],[-14.76,-29.93],[-13.79,-30.69],[-12.85,-31.44],[-11.94,-32.18],[-11.07,-32.9],[-10.24,-33.61],[-9.47,-34.31],[-8.74,-35.0],[-8.07,-35.68],[-7.45,-36.35],[-6.9,-37.01],[-6.4,-37.67],[-5.97,-38.33],[-5.59,-38.98],[-5.27,-39.63],[-5.01,-40.29],[-4.81,-40.94],[-4.66,-41.6],[-4.55,-42.26],[-4.49,-42.93],[-4.48,-43.6],[-4.5,-44.28],[-4.55,-44.96],[-4.62,-45.65],[-4.72,-46.35],[-4.83,-47.06],[-4.95,-47.77],[-5.07,-48.49],[-5.19,-49.21],[-5.3,-49.95],[-5.39,-50.68],[-5.47,-51.42],[-5.51,-52.16],[-5.53,-52.91],[-5.51,-53.65],[-5.45,-54.4],[-5.34,-55.14],[-5.18,-55.87],[-4.98,-56.61],[-4.71,-57.33],[-4.39,-58.05],[-4.02,-58.76],[-3.58,-59.45],[-3.08,-60.14],[-2.53,-60.81],[-1.91,-61.47],[-1.23,-62.11],[-0.5,-62.74],[0.28,-63.35],[1.12,-63.94],[2.01,-64.51],[2.94,-65.07],[3.92,-65.61],[4.93,-66.14],[5.98,-66.65],[7.06,-67.14],[8.16,-67.62],[9.28,-68.09],[10.42,-68.54],[11.57,-68.98],[12.73,-69.42],[13.89,-69.85],[15.05,-70.27],[16.2,-70.69],[17.34,-71.11],[18.47,-71.53],[19.58,-71.96],[20.67,-72.39],[21.74,-72.83],[22.78,-73.28],[23.8,-73.74],[24.8,-74.22],[25.76,-74.71],[26.7,-75.23],[27.61,-75.76],[28.5,-76.31],[29.36,-76.89],[30.19,-77.48],[31.01,-78.11],[31.8,-78.75],[32.58,-79.43],[33.35,-80.12],[34.1,-80.84],[34.85,-81.59],[35.6,-82.36],[36.35,-83.15],[37.1,-83.96],[37.86,-84.78],[38.64,-85.63],[39.43,-86.49],[40.24,-87.35],[41.08,-88.23],[41.95,-89.11],[42.85,-90.0],[43.79,-90.88],[44.76,-91.76],[45.77,-92.63],[46.83,-93.49],[47.94,-94.34],[49.09,-95.17],[50.29,-95.97],[51.53,-96.74],[52.83,-97.49],[54.17,-98.21],[55.57,-98.88],[57.01,-99.52],[58.49,-100.12],[60.02,-100.67],[61.59,-101.17],[63.2,-101.63],[64.85,-102.03],[66.53,-102.38],[68.24,-102.67],[69.98,-102.92],[71.74,-103.1],[73.52,-103.23],[75.31,-103.31],[77.12,-103.33],[78.93,-103.3],[80.75,-103.21],[82.57,-103.07],[84.38,-102.89],[86.18,-102.66],[87.98,-102.38],[89.76,-102.06],[91.53,-101.7],[93.27,-101.3],[95.0,-100.87],[96.7,-100.41],[98.38,-99.93],[100.03,-99.42],[101.66,-98.89],[103.25,-98.35],[104.82,-97.8],[106.37,-97.23],[107.88,-96.66],[109.37,-96.09],[110.84,-95.52],[112.28,-94.96],[113.7,-94.4],[115.1,-93.85],[116.49,-93.31],[117.85,-92.79],[119.21,-92.28],[120.55,-91.79],[121.88,-91.32],[123.21,-90.87],[124.53,-90.44],[125.85,-90.02],[127.17,-89.63],[128.49,-89.26],[129.82,-88.91],[131.15,-88.57],[132.49,-88.26],[133.84,-87.96],[135.19,-87.67],[136.56,-87.4],[137.93,-87.14],[139.31,-86.88],[140.7,-86.64],[142.1,-86.39],[143.5,-86.15],[144.91,-85.91],[146.32,-85.66],[147.73,-85.41],[149.13,-85.15],[150.53,-84.88],[151.93,-84.6],[153.31,-84.3],[154.67,-83.98],[156.02,-83.65],[157.35,-83.29],[158.64,-82.91],[159.92,-82.51],[161.15,-82.09],[162.35,-81.63],[163.52,-81.16],[164.64,-80.65],[165.71,-80.12],[166.74,-79.56],[167.72,-78.98],[168.64,-78.37],[169.51,-77.74],[170.33,-77.09],[171.09,-76.41],[171.8,-75.71],[172.45,-75.0],[173.05,-74.26],[173.6,-73.52],[174.09,-72.75],[174.54,-71.98],[174.94,-71.21],[175.29,-70.42],[175.61,-69.63],[175.89,-68.84],[176.14,-68.05],[176.37,-67.27],[176.57,-66.49],[176.76,-65.71],[176.94,-64.95],[177.11,-64.19],[177.29,-63.45],[177.47,-62.72],[177.67,-62.01],[177.88,-61.31],[178.12,-60.62],[178.4,-59.96],[178.7,-59.31],[179.05,-58.68],[179.45,-58.06],[179.89,-57.47],[180.39,-56.89],[180.95,-56.32],[181.57,-55.77],[182.25,-55.23],[183.0,-54.71],[183.81,-54.19],[184.69,-53.69],[185.63,-53.19],[186.64,-52.7],[187.72,-52.21],[188.86,-51.72],[190.05,-51.23],[191.31,-50.74],[192.61,-50.25],[193.97,-49.75],[195.37,-49.24],[196.8,-48.72],[198.27,-48.19],[199.76,-47.65],[201.27,-47.1],[202.79,-46.53],[204.32,-45.94],[205.84,-45.33],[207.35,-44.71],[208.84,-44.07],[210.31,-43.41],[211.74,-42.73],[213.14,-42.03],[214.48,-41.32],[215.77,-40.58],[217.0,-39.83],[218.16,-39.06],[219.25,-38.28],[220.25,-37.48],[221.18,-36.66],[222.02,-35.84],[222.76,-35.0]],[[227.96,-35.0],[228.65,-34.12],[229.25,-33.23],[229.74,-32.34],[230.13,-31.44],[230.41,-30.54],[230.59,-29.63],[230.66,-28.73],[230.64,-27.83],[230.51,-26.93],[230.28,-26.04],[229.96,-25.16],[229.55,-24.28],[229.06,-23.41],[228.48,-22.56],[227.83,-21.71],[227.1,-20.88],[226.32,-20.05],[225.47,-19.24],[224.57,-18.45],[223.62,-17.66],[222.64,-16.89],[221.62,-16.13],[220.58,-15.39],[219.52,-14.65],[218.44,-13.92],[217.35,-13.21],[216.26,-12.5],[215.17,-11.8],[214.09,-11.1],[213.02,-10.41],[211.97,-9.72],[210.93,-9.04],[209.91,-8.35],[208.92,-7.67],[207.95,-6.98],[207.0,-6.29],[206.08,-5.6],[205.19,-4.9],[204.32,-4.2],[203.48,-3.49],[202.66,-2.78],[201.86,-2.06],[201.08,-1.33],[200.32,-0.6],[199.57,0.15],[198.82,0.89],[198.08,1.65],[197.34,2.4],[196.59,3.16],[195.84,3.92],[195.08,4.69],[194.29,5.45],[193.49,6.2],[192.66,6.96],[191.8,7.7],[190.9,8.44],[189.97,9.16],[189.0,9.87],[187.98,10.56],[186.91,11.23],[185.8,11.89],[184.63,12.51],[183.41,13.11],[182.14,13.68],[180.82,14.22],[179.44,14.73],[178.0,15.2],[176.52,15.64],[174.98,16.04],[173.39,16.39],[171.76,16.71],[170.08,16.99],[168.36,17.22],[166.61,17.41],[164.82,17.56],[163.0,17.67],[161.15,17.74],[159.28,17.77],[157.39,17.76],[155.5,17.71],[153.59,17.63],[151.68,17.51],[149.77,17.37],[147.87,17.2],[145.98,17.0],[144.1,16.78],[142.24,16.55],[140.4,16.29],[138.59,16.03],[136.8,15.76],[135.04,15.49],[133.32,15.21],[131.63,14.94],[129.97,14.68],[128.35,14.42],[126.77,14.18],[125.22,13.96],[123.71,13.76],[122.24,13.58],[120.8,13.43],[119.39,13.3],[118.01,13.21],[116.66,13.15],[115.33,13.12],[114.03,13.13],[112.75,13.18],[111.49,13.26],[110.23,13.38],[108.99,13.54],[107.75,13.73],[106.52,13.96],[105.29,14.23],[104.05,14.53],[102.8,14.86],[101.54,15.21],[100.27,15.6],[98.98,16.01],[97.68,16.44],[96.35,16.89],[95.0,17.35],[93.63,17.83],[92.22,18.31],[90.8,18.8],[89.34,19.28],[87.86,19.77],[86.36,20.25],[84.82,20.71],[83.26,21.17],[81.68,21.6],[80.08,22.01],[78.45,22.4],[76.81,22.77],[75.15,23.1],[73.48,23.4],[71.8,23.67],[70.11,23.89],[68.42,24.09],[66.73,24.24],[65.04,24.35],[63.35,24.42],[61.67,24.45],[60.0,24.43],[58.35,24.38],[56.71,24.28],[55.09,24.14],[53.49,23.97],[51.91,23.75],[50.35,23.51],[48.82,23.22],[47.32,22.91],[45.84,22.56],[44.38,22.19],[42.95,21.79],[41.55,21.37],[40.17,20.93],[38.81,20.48],[37.47,20.01],[36.15,19.53],[34.84,19.04],[33.55,18.54],[32.27,18.04],[31.0,17.54],[29.73,17.03],[28.47,16.54],[27.2,16.04],[25.93,15.55],[24.65,15.07],[23.36,14.6],[22.05,14.14],[20.73,13.69],[19.39,13.25],[18.03,12.82],[16.64,12.39],[15.23,11.98],[13.79,11.58],[12.32,11.19],[10.82,10.81],[9.3,10.43],[7.75,10.06],[6.17,9.69],[4.56,9.32],[2.93,8.95],[1.29,8.58],[-0.38,8.2],[-2.06,7.82],[-3.75,7.43],[-5.45,7.03],[-7.15,6.61],[-8.85,6.18],[-10.54,5.74],[-12.21,5.27],[-13.86,4.79],[-15.48,4.28],[-17.08,3.75],[-18.63,3.19],[-20.13,2.61],[-21.59,2.0],[-22.98,1.37],[-24.31,0.71],[-25.57,0.02],[-26.76,-0.7],[-27.86,-1.44],[-28.87,-2.22],[-29.8,-3.01],[-30.63,-3.84],[-31.36,-4.68],[-31.99,-5.55],[-32.52,-6.44],[-32.94,-7.35],[-33.26,-8.28],[-33.47,-9.22],[-33.57,-10.17],[-33.57,-11.14],[-33.47,-12.12],[-33.26,-13.1],[-32.96,-14.09],[-32.56,-15.08],[-32.07,-16.07],[-31.5,-17.05],[-30.85,-18.04],[-30.12,-19.02],[-29.33,-19.98],[-28.48,-20.95],[-27.57,-21.89],[-26.62,-22.83],[-25.63,-23.75],[-24.6,-24.66],[-23.56,-25.55],[-22.5,-26.43],[-21.43,-27.29],[-20.36,-28.13],[-19.3,-28.96],[-18.25,-29.77],[-17.23,-30.56],[-16.23,-31.33],[-15.27,-32.09],[-14.35,-32.84],[-13.47,-33.57],[-12.65,-34.29],[-11.87,-35.0],[-11.16,-35.7],[-10.5,-36.39],[-9.91,-37.07],[-9.38,-37.75],[-8.91,-38.43],[-8.5,-39.1],[-8.16,-39.77],[-7.88,-40.44],[-7.66,-41.11],[-7.5,-41.79],[-7.39,-42.47],[-7.33,-43.15],[-7.31,-43.84],[-7.34,-44.54],[-7.4,-45.25],[-7.49,-45.96],[-7.6,-46.68],[-7.74,-47.41],[-7.88,-48.14],[-8.04,-48.89],[-8.19,-49.64],[-8.33,-50.4],[-8.47,-51.16],[-8.58,-51.93],[-8.67,-52.7],[-8.73,-53.48],[-8.75,-54.25],[-8.73,-55.03],[-8.67,-55.8],[-8.56,-56.58],[-8.39,-57.34],[-8.17,-58.11],[-7.89,-58.86],[-7.55,-59.61],[-7.15,-60.34],[-6.69,-61.06],[-6.17,-61.77],[-5.58,-62.47],[-4.93,-63.15],[-4.22,-63.82],[-3.45,-64.46],[-2.63,-65.09],[-1.75,-65.71],[-0.82,-66.3],[0.15,-66.88],[1.17,-67.44],[2.22,-67.98],[3.31,-68.51],[4.43,-69.02],[5.57,-69.52],[6.73,-70.0],[7.91,-70.48],[9.09,-70.94],[10.29,-71.4],[11.48,-71.84],[12.67,-72.29],[13.85,-72.73],[15.03,-73.18],[16.18,-73.62],[17.32,-74.07],[18.44,-74.53],[19.54,-75.0],[20.61,-75.48],[21.66,-75.97],[22.68,-76.48],[23.68,-77.01],[24.65,-77.55],[25.59,-78.12],[26.5,-78.71],[27.39,-79.32],[28.26,-79.96],[29.11,-80.62],[29.95,-81.3],[30.77,-82.01],[31.57,-82.75],[32.37,-83.51],[33.17,-84.29],[33.97,-85.1],[34.77,-85.93],[35.58,-86.77],[36.4,-87.63],[37.24,-88.51],[38.1,-89.4],[38.99,-90.3],[39.9,-91.2],[40.85,-92.11],[41.83,-93.02],[42.85,-93.92],[43.91,-94.81],[45.02,-95.7],[46.17,-96.57],[47.37,-97.42],[48.62,-98.24],[49.91,-99.05],[51.26,-99.82],[52.66,-100.55],[54.1,-101.26],[55.6,-101.92],[57.14,-102.53],[58.72,-103.1],[60.35,-103.63],[62.02,-104.1],[63.73,-104.52],[65.47,-104.88],[67.24,-105.19],[69.05,-105.44],[70.87,-105.64],[72.72,-105.78],[74.58,-105.86],[76.45,-105.88],[78.33,-105.84],[80.22,-105.75],[82.1,-105.61],[83.98,-105.42],[85.86,-105.17],[87.72,-104.88],[89.57,-104.54],[91.4,-104.16],[93.21,-103.74],[95.0,-103.29],[96.76,-102.81],[98.5,-102.29],[100.21,-101.75],[101.9,-101.19],[103.55,-100.62],[105.17,-100.03],[106.77,-99.42],[108.33,-98.82],[109.87,-98.21],[111.38,-97.6],[112.87,-96.99],[114.33,-96.39],[115.77,-95.8],[117.19,-95.22],[118.59,-94.66],[119.98,-94.11],[121.35,-93.58],[122.72,-93.07],[124.07,-92.58],[125.42,-92.12],[126.77,-91.67],[128.12,-91.24],[129.47,-90.84],[130.82,-90.46],[132.18,-90.1],[133.55,-89.76],[134.92,-89.43],[136.3,-89.12],[137.69,-88.83],[139.1,-88.55],[140.51,-88.28],[141.93,-88.02],[143.36,-87.77],[144.8,-87.52],[146.24,-87.27],[147.69,-87.02],[149.14,-86.76],[150.59,-86.5],[152.03,-86.23],[153.47,-85.94],[154.9,-85.64],[156.31,-85.33],[157.71,-85.0],[159.09,-84.64],[160.44,-84.27],[161.77,-83.87],[163.07,-83.45],[164.33,-83.0],[165.55,-82.53],[166.73,-82.03],[167.87,-81.5],[168.96,-80.94],[170.0,-80.36],[170.99,-79.75],[171.92,-79.12],[172.8,-78.46],[173.62,-77.78],[174.39,-77.08],[175.1,-76.36],[175.75,-75.62],[176.36,-74.87],[176.9,-74.1],[177.4,-73.32],[177.85,-72.53],[178.25,-71.73],[178.62,-70.92],[178.94,-70.12],[179.23,-69.31],[179.5,-68.51],[179.74,-67.71],[179.96,-66.91],[180.17,-66.13],[180.37,-65.35],[180.58,-64.59],[180.79,-63.83],[181.01,-63.1],[181.25,-62.37],[181.51,-61.67],[181.8,-60.98],[182.13,-60.3],[182.5,-59.65],[182.91,-59.01],[183.37,-58.39],[183.89,-57.78],[184.47,-57.19],[185.11,-56.62],[185.81,-56.06],[186.58,-55.51],[187.41,-54.97],[188.32,-54.44],[189.29,-53.92],[190.33,-53.41],[191.44,-52.9],[192.61,-52.39],[193.84,-51.88],[195.14,-51.37],[196.48,-50.85],[197.88,-50.33],[199.33,-49.8],[200.81,-49.26],[202.33,-48.71],[203.88,-48.15],[205.44,-47.57],[207.02,-46.98],[208.61,-46.37],[210.19,-45.74],[211.77,-45.09],[213.32,-44.43],[214.86,-43.74],[216.35,-43.04],[217.81,-42.31],[219.22,-41.57],[220.58,-40.8],[221.87,-40.02],[223.09,-39.22],[224.23,-38.41],[225.3,-37.58],[226.28,-36.73],[227.17,-35.87],[227.96,-35.0]],[[233.17,-35.0],[233.91,-34.09],[234.55,-33.16],[235.07,-32.23],[235.49,-31.3],[235.8,-30.36],[236.0,-29.42],[236.09,-28.48],[236.07,-27.54],[235.95,-26.61],[235.72,-25.68],[235.39,-24.76],[234.97,-23.85],[234.45,-22.95],[233.85,-22.06],[233.16,-21.18],[232.4,-20.31],[231.57,-19.46],[230.68,-18.61],[229.72,-17.79],[228.72,-16.98],[227.67,-16.18],[226.59,-15.39],[225.47,-14.62],[224.34,-13.86],[223.18,-13.11],[222.01,-12.38],[220.84,-11.65],[219.67,-10.93],[218.5,-10.22],[217.34,-9.51],[216.19,-8.81],[215.07,-8.11],[213.96,-7.41],[212.88,-6.72],[211.82,-6.02],[210.79,-5.32],[209.79,-4.62],[208.81,-3.92],[207.87,-3.2],[206.94,-2.49],[206.05,-1.77],[205.18,-1.04],[204.33,-0.3],[203.49,0.44],[202.68,1.19],[201.87,1.95],[201.07,2.71],[200.27,3.47],[199.48,4.25],[198.68,5.02],[197.87,5.79],[197.04,6.57],[196.19,7.34],[195.33,8.1],[194.43,8.86],[193.5,9.61],[192.54,10.36],[191.54,11.08],[190.49,11.79],[189.4,12.48],[188.26,13.16],[187.07,13.8],[185.82,14.42],[184.53,15.02],[183.18,15.58],[181.77,16.11],[180.31,16.6],[178.8,17.06],[177.24,17.48],[175.62,17.85],[173.96,18.19],[172.25,18.49],[170.5,18.74],[168.71,18.95],[166.89,19.12],[165.03,19.24],[163.14,19.33],[161.24,19.37],[159.31,19.37],[157.37,19.34],[155.42,19.27],[153.46,19.16],[151.51,19.03],[149.56,18.86],[147.62,18.67],[145.69,18.46],[143.78,18.22],[141.89,17.97],[140.02,17.71],[138.18,17.44],[136.37,17.16],[134.59,16.88],[132.85,16.61],[131.14,16.34],[129.47,16.08],[127.84,15.84],[126.24,15.61],[124.68,15.4],[123.15,15.22],[121.66,15.06],[120.21,14.93],[118.78,14.83],[117.39,14.77],[116.02,14.74],[114.67,14.75],[113.35,14.79],[112.04,14.88],[110.74,15.0],[109.46,15.16],[108.18,15.36],[106.91,15.6],[105.63,15.87],[104.35,16.18],[103.06,16.53],[101.76,16.9],[100.45,17.3],[99.12,17.73],[97.77,18.18],[96.4,18.65],[95.0,19.14],[93.58,19.64],[92.13,20.15],[90.65,20.67],[89.15,21.19],[87.61,21.7],[86.05,22.21],[84.46,22.71],[82.84,23.2],[81.2,23.67],[79.53,24.11],[77.84,24.54],[76.13,24.93],[74.4,25.3],[72.66,25.63],[70.91,25.93],[69.15,26.19],[67.38,26.4],[65.61,26.58],[63.84,26.72],[62.08,26.81],[60.32,26.86],[58.57,26.86],[56.84,26.82],[55.12,26.74],[53.42,26.62],[51.74,26.45],[50.09,26.24],[48.45,26.0],[46.85,25.71],[45.27,25.39],[43.72,25.04],[42.19,24.66],[40.7,24.25],[39.23,23.82],[37.78,23.36],[36.36,22.89],[34.97,22.4],[33.59,21.89],[32.24,21.38],[30.9,20.85],[29.57,20.32],[28.25,19.79],[26.95,19.26],[25.64,18.72],[24.34,18.19],[23.04,17.67],[21.73,17.15],[20.41,16.64],[19.08,16.14],[17.73,15.65],[16.37,15.17],[14.98,14.7],[13.58,14.25],[12.15,13.8],[10.69,13.36],[9.2,12.93],[7.69,12.51],[6.15,12.1],[4.58,11.69],[2.98,11.29],[1.36,10.89],[-0.28,10.48],[-1.95,10.08],[-3.64,9.68],[-5.34,9.26],[-7.05,8.85],[-8.78,8.42],[-10.5,7.98],[-12.22,7.52],[-13.94,7.05],[-15.64,6.56],[-17.32,6.05],[-18.98,5.52],[-20.6,4.97],[-22.18,4.39],[-23.72,3.78],[-25.21,3.15],[-26.64,2.5],[-28.0,1.81],[-29.3,1.1],[-30.52,0.36],[-31.65,-0.41],[-32.7,-1.2],[-33.66,-2.02],[-34.51,-2.87],[-35.27,-3.74],[-35.93,-4.64],[-36.48,-5.55],[-36.93,-6.49],[-37.26,-7.44],[-37.48,-8.41],[-37.6,-9.4],[-37.61,-10.39],[-37.51,-11.4],[-37.3,-12.41],[-37.0,-13.43],[-36.6,-14.45],[-36.1,-15.47],[-35.51,-16.48],[-34.84,-17.5],[-34.09,-18.51],[-33.28,-19.51],[-32.39,-20.5],[-31.45,-21.48],[-30.46,-22.45],[-29.43,-23.4],[-28.37,-24.34],[-27.28,-25.26],[-26.17,-26.16],[-25.05,-27.05],[-23.94,-27.92],[-22.82,-28.77],[-21.73,-29.6],[-20.65,-30.42],[-19.6,-31.22],[-18.59,-32.01],[-17.61,-32.77],[-16.69,-33.53],[-15.81,-34.27],[-14.99,-35.0],[-14.23,-35.72],[-13.54,-36.43],[-12.9,-37.13],[-12.33,-37.83],[-11.83,-38.52],[-11.4,-39.21],[-11.04,-39.9],[-10.74,-40.59],[-10.5,-41.28],[-10.32,-41.98],[-10.21,-42.67],[-10.14,-43.38],[-10.13,-44.09],[-10.16,-44.8],[-10.24,-45.53],[-10.34,-46.26],[-10.48,-47.01],[-10.63,-47.76],[-10.81,-48.52],[-10.99,-49.29],[-11.18,-50.06],[-11.36,-50.85],[-11.53,-51.64],[-11.69,-52.44],[-11.82,-53.24],[-11.92,-54.05],[-11.99,-54.85],[-12.02,-55.66],[-12.0,-56.47],[-11.94,-57.28],[-11.82,-58.09],[-11.64,-58.88],[-11.41,-59.68],[-11.11,-60.46],[-10.75,-61.23],[-10.33,-62.0],[-9.84,-62.75],[-9.28,-63.48],[-8.66,-64.2],[-7.97,-64.91],[-7.23,-65.59],[-6.42,-66.26],[-5.56,-66.92],[-4.64,-67.55],[-3.67,-68.16],[-2.65,-68.76],[-1.59,-69.34],[-0.5,-69.9],[0.63,-70.45],[1.79,-70.98],[2.98,-71.49],[4.18,-72.0],[5.39,-72.49],[6.62,-72.97],[7.85,-73.45],[9.08,-73.92],[10.3,-74.38],[11.52,-74.85],[12.73,-75.32],[13.92,-75.79],[15.09,-76.26],[16.24,-76.75],[17.37,-77.25],[18.47,-77.75],[19.55,-78.28],[20.6,-78.82],[21.63,-79.38],[22.63,-79.96],[23.6,-80.56],[24.55,-81.18],[25.48,-81.83],[26.39,-82.51],[27.28,-83.2],[28.15,-83.93],[29.01,-84.68],[29.87,-85.45],[30.72,-86.25],[31.57,-87.07],[32.42,-87.91],[33.29,-88.77],[34.16,-89.65],[35.05,-90.54],[35.96,-91.45],[36.89,-92.37],[37.85,-93.29],[38.85,-94.22],[39.88,-95.15],[40.95,-96.07],[42.06,-96.99],[43.21,-97.89],[44.41,-98.79],[45.66,-99.66],[46.95,-100.51],[48.3,-101.34],[49.7,-102.13],[51.15,-102.89],[52.65,-103.61],[54.19,-104.3],[55.79,-104.93],[57.43,-105.52],[59.12,-106.07],[60.85,-106.56],[62.62,-106.99],[64.42,-107.37],[66.26,-107.69],[68.12,-107.95],[70.01,-108.16],[71.92,-108.3],[73.85,-108.38],[75.79,-108.41],[77.74,-108.37],[79.69,-108.28],[81.64,-108.13],[83.59,-107.92],[85.53,-107.67],[87.46,-107.36],[89.38,-107.01],[91.27,-106.61],[93.15,-106.17],[95.0,-105.69],[96.83,-105.18],[98.63,-104.64],[100.39,-104.07],[102.13,-103.48],[103.84,-102.86],[105.52,-102.24],[107.17,-101.6],[108.78,-100.95],[110.37,-100.3],[111.92,-99.65],[113.45,-99.01],[114.95,-98.37],[116.43,-97.73],[117.89,-97.12],[119.32,-96.51],[120.74,-95.92],[122.15,-95.35],[123.54,-94.8],[124.93,-94.28],[126.31,-93.77],[127.68,-93.29],[129.05,-92.83],[130.43,-92.4],[131.81,-91.98],[133.19,-91.59],[134.58,-91.23],[135.98,-90.88],[137.39,-90.55],[138.81,-90.24],[140.24,-89.94],[141.68,-89.65],[143.13,-89.38],[144.59,-89.11],[146.06,-88.85],[147.54,-88.6],[149.03,-88.34],[150.52,-88.08],[152.01,-87.81],[153.49,-87.54],[154.98,-87.26],[156.46,-86.96],[157.92,-86.65],[159.37,-86.32],[160.81,-85.97],[162.22,-85.6],[163.6,-85.21],[164.96,-84.79],[166.28,-84.35],[167.56,-83.88],[168.81,-83.39],[170.01,-82.86],[171.16,-82.31],[172.27,-81.73],[173.32,-81.13],[174.32,-80.5],[175.26,-79.84],[176.15,-79.16],[176.98,-78.45],[177.75,-77.73],[178.47,-76.99],[179.13,-76.22],[179.73,-75.45],[180.28,-74.66],[180.79,-73.86],[181.24,-73.05],[181.65,-72.23],[182.03,-71.41],[182.36,-70.59],[182.67,-69.76],[182.95,-68.95],[183.21,-68.13],[183.45,-67.33],[183.69,-66.53],[183.92,-65.74],[184.16,-64.97],[184.41,-64.21],[184.67,-63.46],[184.96,-62.73],[185.27,-62.02],[185.62,-61.32],[186.01,-60.64],[186.44,-59.97],[186.93,-59.33],[187.46,-58.7],[188.06,-58.08],[188.72,-57.49],[189.44,-56.9],[190.23,-56.33],[191.09,-55.77],[192.02,-55.21],[193.01,-54.67],[194.08,-54.13],[195.22,-53.6],[196.42,-53.07],[197.69,-52.54],[199.02,-52.0],[200.41,-51.46],[201.85,-50.92],[203.34,-50.37],[204.87,-49.81],[206.44,-49.24],[208.03,-48.65],[209.65,-48.05],[211.29,-47.43],[212.93,-46.8],[214.58,-46.15],[216.21,-45.48],[217.83,-44.79],[219.43,-44.08],[220.99,-43.34],[222.51,-42.59],[223.98,-41.82],[225.4,-41.03],[226.75,-40.22],[228.03,-39.39],[229.24,-38.54],[230.36,-37.68],[231.39,-36.8],[232.33,-35.9],[233.17,-35.0]],[[238.4,-35.0],[239.18,-34.05],[239.85,-33.09],[240.42,-32.13],[240.86,-31.15],[241.2,-30.18],[241.42,-29.2],[241.52,-28.23],[241.51,-27.25],[241.39,-26.28],[241.16,-25.32],[240.83,-24.36],[240.39,-23.42],[239.85,-22.48],[239.22,-21.55],[238.51,-20.64],[237.71,-19.74],[236.83,-18.86],[235.89,-17.99],[234.88,-17.13],[233.82,-16.29],[232.71,-15.46],[231.56,-14.65],[230.37,-13.86],[229.16,-13.07],[227.92,-12.3],[226.67,-11.55],[225.41,-10.8],[224.15,-10.06],[222.89,-9.33],[221.65,-8.61],[220.41,-7.9],[219.19,-7.19],[217.99,-6.48],[216.82,-5.77],[215.67,-5.07],[214.55,-4.36],[213.46,-3.65],[212.4,-2.94],[211.37,-2.22],[210.37,-1.49],[209.39,-0.77],[208.44,-0.03],[207.52,0.71],[206.62,1.46],[205.73,2.22],[204.86,2.98],[204.0,3.75],[203.15,4.53],[202.3,5.31],[201.45,6.09],[200.59,6.87],[199.72,7.66],[198.84,8.44],[197.93,9.22],[197.0,10.0],[196.04,10.76],[195.04,11.52],[194.01,12.26],[192.94,12.99],[191.82,13.7],[190.66,14.39],[189.44,15.06],[188.18,15.7],[186.86,16.32],[185.48,16.9],[184.06,17.45],[182.58,17.97],[181.04,18.45],[179.45,18.89],[177.81,19.29],[176.12,19.65],[174.39,19.97],[172.61,20.24],[170.79,20.47],[168.93,20.66],[167.04,20.8],[165.12,20.9],[163.17,20.96],[161.21,20.98],[159.23,20.96],[157.23,20.9],[155.24,20.81],[153.24,20.68],[151.24,20.52],[149.25,20.34],[147.27,20.13],[145.31,19.9],[143.37,19.65],[141.46,19.39],[139.57,19.12],[137.7,18.84],[135.88,18.56],[134.08,18.29],[132.32,18.02],[130.6,17.75],[128.91,17.5],[127.27,17.27],[125.65,17.06],[124.08,16.87],[122.54,16.71],[121.04,16.57],[119.57,16.47],[118.12,16.41],[116.71,16.38],[115.32,16.38],[113.95,16.43],[112.6,16.51],[111.26,16.64],[109.93,16.81],[108.61,17.01],[107.3,17.26],[105.98,17.54],[104.66,17.86],[103.33,18.22],[101.98,18.61],[100.63,19.03],[99.25,19.47],[97.86,19.95],[96.44,20.44],[95.0,20.95],[93.53,21.48],[92.03,22.02],[90.5,22.56],[88.95,23.11],[87.36,23.66],[85.74,24.2],[84.09,24.73],[82.41,25.25],[80.71,25.75],[78.97,26.23],[77.22,26.69],[75.44,27.12],[73.65,27.51],[71.83,27.88],[70.01,28.21],[68.17,28.5],[66.33,28.74],[64.48,28.95],[62.63,29.11],[60.79,29.23],[58.95,29.3],[57.12,29.32],[55.31,29.3],[53.51,29.23],[51.73,29.11],[49.98,28.96],[48.24,28.75],[46.53,28.51],[44.85,28.23],[43.2,27.91],[41.57,27.55],[39.98,27.16],[38.42,26.74],[36.88,26.3],[35.37,25.82],[33.89,25.33],[32.44,24.82],[31.01,24.29],[29.6,23.74],[28.21,23.19],[26.84,22.63],[25.48,22.07],[24.13,21.5],[22.79,20.93],[21.46,20.37],[20.12,19.8],[18.78,19.25],[17.44,18.7],[16.08,18.16],[14.72,17.63],[13.33,17.11],[11.93,16.6],[10.5,16.11],[9.06,15.62],[7.58,15.14],[6.09,14.67],[4.56,14.22],[3.0,13.77],[1.42,13.32],[-0.19,12.88],[-1.82,12.45],[-3.48,12.01],[-5.17,11.58],[-6.87,11.14],[-8.59,10.7],[-10.32,10.25],[-12.06,9.79],[-13.81,9.32],[-15.55,8.84],[-17.29,8.34],[-19.02,7.83],[-20.73,7.29],[-22.41,6.74],[-24.06,6.16],[-25.68,5.56],[-27.25,4.93],[-28.77,4.28],[-30.23,3.6],[-31.63,2.9],[-32.95,2.16],[-34.2,1.4],[-35.37,0.61],[-36.45,-0.21],[-37.44,-1.06],[-38.33,-1.93],[-39.11,-2.82],[-39.8,-3.74],[-40.37,-4.68],[-40.84,-5.64],[-41.19,-6.62],[-41.43,-7.62],[-41.56,-8.63],[-41.58,-9.65],[-41.49,-10.69],[-41.29,-11.73],[-40.98,-12.77],[-40.57,-13.82],[-40.07,-14.87],[-39.47,-15.92],[-38.79,-16.97],[-38.02,-18.01],[-37.18,-19.04],[-36.27,-20.06],[-35.3,-21.07],[-34.28,-22.06],[-33.21,-23.05],[-32.1,-24.01],[-30.97,-24.96],[-29.82,-25.9],[-28.66,-26.81],[-27.49,-27.71],[-26.33,-28.59],[-25.18,-29.44],[-24.05,-30.29],[-22.95,-31.11],[-21.89,-31.92],[-20.87,-32.71],[-19.89,-33.49],[-18.97,-34.25],[-18.1,-35.0],[-17.3,-35.74],[-16.56,-36.47],[-15.89,-37.19],[-15.28,-37.91],[-14.75,-38.62],[-14.29,-39.33],[-13.9,-40.03],[-13.58,-40.74],[-13.33,-41.45],[-13.14,-42.16],[-13.02,-42.88],[-12.95,-43.6],[-12.94,-44.33],[-12.98,-45.07],[-13.06,-45.81],[-13.19,-46.57],[-13.34,-47.33],[-13.52,-48.11],[-13.72,-48.89],[-13.94,-49.68],[-14.16,-50.49],[-14.38,-51.3],[-14.59,-52.12],[-14.79,-52.94],[-14.97,-53.78],[-15.12,-54.62],[-15.23,-55.46],[-15.31,-56.3],[-15.35,-57.15],[-15.33,-57.99],[-15.26,-58.83],[-15.13,-59.67],[-14.94,-60.5],[-14.69,-61.32],[-14.37,-62.13],[-13.99,-62.93],[-13.54,-63.73],[-13.02,-64.5],[-12.43,-65.26],[-11.77,-66.01],[-11.05,-66.74],[-10.26,-67.45],[-9.41,-68.14],[-8.5,-68.81],[-7.54,-69.46],[-6.53,-70.1],[-5.46,-70.72],[-4.36,-71.31],[-3.22,-71.89],[-2.04,-72.46],[-0.84,-73.01],[0.38,-73.54],[1.63,-74.06],[2.89,-74.57],[4.15,-75.08],[5.42,-75.57],[6.69,-76.06],[7.95,-76.55],[9.21,-77.04],[10.45,-77.53],[11.67,-78.03],[12.88,-78.53],[14.06,-79.04],[15.22,-79.57],[16.36,-80.11],[17.47,-80.66],[18.56,-81.23],[19.62,-81.83],[20.65,-82.44],[21.67,-83.08],[22.65,-83.74],[23.62,-84.42],[24.57,-85.13],[25.5,-85.86],[26.43,-86.62],[27.34,-87.41],[28.25,-88.22],[29.15,-89.05],[30.06,-89.91],[30.98,-90.78],[31.9,-91.68],[32.85,-92.58],[33.81,-93.51],[34.79,-94.44],[35.8,-95.38],[36.85,-96.33],[37.93,-97.28],[39.05,-98.22],[40.2,-99.16],[41.41,-100.08],[42.66,-101.0],[43.95,-101.89],[45.3,-102.77],[46.7,-103.61],[48.15,-104.43],[49.65,-105.21],[51.2,-105.95],[52.8,-106.66],[54.46,-107.31],[56.16,-107.92],[57.9,-108.48],[59.69,-108.99],[61.51,-109.44],[63.38,-109.83],[65.28,-110.17],[67.21,-110.44],[69.16,-110.65],[71.13,-110.8],[73.13,-110.89],[75.13,-110.91],[77.15,-110.88],[79.17,-110.78],[81.19,-110.62],[83.2,-110.41],[85.21,-110.14],[87.2,-109.82],[89.18,-109.45],[91.15,-109.04],[93.09,-108.58],[95.0,-108.08],[96.89,-107.54],[98.75,-106.97],[100.57,-106.37],[102.37,-105.74],[104.13,-105.1],[105.86,-104.43],[107.56,-103.76],[109.22,-103.07],[110.85,-102.38],[112.45,-101.69],[114.03,-101.0],[115.57,-100.32],[117.08,-99.65],[118.58,-98.99],[120.05,-98.34],[121.5,-97.71],[122.94,-97.1],[124.36,-96.51],[125.77,-95.95],[127.18,-95.41],[128.58,-94.89],[129.97,-94.39],[131.37,-93.93],[132.78,-93.48],[134.18,-93.07],[135.6,-92.67],[137.02,-92.3],[138.46,-91.95],[139.9,-91.61],[141.36,-91.3],[142.83,-91.0],[144.31,-90.71],[145.8,-90.43],[147.31,-90.16],[148.82,-89.9],[150.34,-89.64],[151.87,-89.37],[153.4,-89.1],[154.93,-88.83],[156.46,-88.55],[157.99,-88.26],[159.5,-87.95],[161.01,-87.62],[162.49,-87.28],[163.96,-86.92],[165.41,-86.53],[166.82,-86.12],[168.21,-85.68],[169.55,-85.22],[170.86,-84.73],[172.13,-84.22],[173.35,-83.67],[174.52,-83.1],[175.64,-82.5],[176.71,-81.87],[177.72,-81.21],[178.67,-80.53],[179.57,-79.83],[180.41,-79.1],[181.19,-78.35],[181.91,-77.59],[182.58,-76.8],[183.19,-76.01],[183.75,-75.2],[184.26,-74.38],[184.72,-73.55],[185.15,-72.71],[185.53,-71.88],[185.88,-71.04],[186.2,-70.2],[186.5,-69.37],[186.79,-68.55],[187.06,-67.73],[187.33,-66.92],[187.6,-66.12],[187.87,-65.34],[188.16,-64.57],[188.47,-63.81],[188.81,-63.08],[189.18,-62.35],[189.59,-61.65],[190.05,-60.96],[190.55,-60.29],[191.11,-59.63],[191.72,-58.99],[192.4,-58.37],[193.14,-57.76],[193.95,-57.16],[194.83,-56.58],[195.78,-56.0],[196.81,-55.43],[197.9,-54.87],[199.07,-54.31],[200.3,-53.76],[201.6,-53.2],[202.96,-52.65],[204.39,-52.09],[205.87,-51.52],[207.4,-50.95],[208.97,-50.36],[210.59,-49.77],[212.24,-49.16],[213.91,-48.53],[215.6,-47.89],[217.3,-47.24],[219.0,-46.56],[220.69,-45.86],[222.37,-45.15],[224.03,-44.41],[225.65,-43.65],[227.23,-42.87],[228.77,-42.07],[230.24,-41.25],[231.66,-40.41],[233.0,-39.55],[234.26,-38.67],[235.44,-37.78],[236.52,-36.86],[237.51,-35.94],[238.4,-35.0]],[[243.63,-35.0],[244.45,-34.02],[245.17,-33.02],[245.76,-32.02],[246.24,-31.01],[246.6,-30.0],[246.84,-28.99],[246.96,-27.98],[246.96,-26.97],[246.84,-25.96],[246.61,-24.96],[246.27,-23.97],[245.82,-22.98],[245.26,-22.01],[244.6,-21.05],[243.86,-20.11],[243.02,-19.17],[242.1,-18.26],[241.11,-17.36],[240.05,-16.47],[238.92,-15.6],[237.75,-14.75],[236.53,-13.91],[235.27,-13.09],[233.97,-12.29],[232.66,-11.49],[231.32,-10.72],[229.98,-9.95],[228.63,-9.2],[227.28,-8.45],[225.94,-7.72],[224.61,-6.99],[223.3,-6.27],[222.01,-5.55],[220.74,-4.83],[219.5,-4.12],[218.29,-3.4],[217.1,-2.68],[215.95,-1.96],[214.84,-1.24],[213.75,-0.51],[212.69,0.22],[211.67,0.96],[210.67,1.71],[209.69,2.47],[208.74,3.23],[207.8,4.0],[206.88,4.77],[205.97,5.56],[205.07,6.34],[204.16,7.14],[203.26,7.93],[202.34,8.73],[201.42,9.52],[200.47,10.31],[199.5,11.1],[198.51,11.88],[197.48,12.65],[196.42,13.42],[195.32,14.16],[194.18,14.89],[192.99,15.6],[191.76,16.29],[190.47,16.95],[189.13,17.59],[187.74,18.19],[186.29,18.77],[184.79,19.31],[183.23,19.81],[181.62,20.27],[179.96,20.7],[178.25,21.08],[176.49,21.42],[174.68,21.71],[172.83,21.97],[170.95,22.18],[169.02,22.34],[167.07,22.46],[165.09,22.54],[163.09,22.57],[161.07,22.57],[159.04,22.52],[157.0,22.44],[154.96,22.33],[152.92,22.18],[150.89,22.01],[148.86,21.81],[146.85,21.58],[144.87,21.34],[142.9,21.08],[140.96,20.81],[139.05,20.54],[137.17,20.26],[135.32,19.98],[133.51,19.71],[131.74,19.44],[130.0,19.19],[128.3,18.95],[126.64,18.74],[125.02,18.54],[123.43,18.38],[121.88,18.24],[120.36,18.14],[118.87,18.07],[117.41,18.04],[115.97,18.04],[114.56,18.09],[113.16,18.18],[111.78,18.3],[110.41,18.47],[109.05,18.69],[107.69,18.94],[106.33,19.23],[104.97,19.56],[103.59,19.93],[102.21,20.34],[100.81,20.77],[99.39,21.24],[97.95,21.73],[96.49,22.25],[95.0,22.78],[93.48,23.33],[91.93,23.9],[90.35,24.47],[88.74,25.05],[87.1,25.63],[85.43,26.2],[83.72,26.76],[81.98,27.32],[80.21,27.85],[78.42,28.37],[76.59,28.86],[74.75,29.32],[72.88,29.75],[71.0,30.15],[69.1,30.51],[67.19,30.83],[65.27,31.1],[63.34,31.34],[61.41,31.52],[59.49,31.66],[57.57,31.75],[55.67,31.8],[53.77,31.79],[51.89,31.74],[50.03,31.64],[48.19,31.49],[46.38,31.29],[44.59,31.05],[42.84,30.77],[41.11,30.45],[39.41,30.09],[37.74,29.69],[36.11,29.26],[34.51,28.8],[32.94,28.31],[31.4,27.79],[29.88,27.26],[28.4,26.7],[26.94,26.14],[25.5,25.55],[24.08,24.96],[22.68,24.36],[21.29,23.76],[19.92,23.16],[18.55,22.56],[17.18,21.96],[15.82,21.36],[14.45,20.77],[13.07,20.19],[11.68,19.62],[10.28,19.06],[8.86,18.51],[7.42,17.97],[5.96,17.44],[4.48,16.92],[2.97,16.42],[1.43,15.92],[-0.14,15.43],[-1.73,14.95],[-3.35,14.47],[-4.99,14.0],[-6.66,13.53],[-8.36,13.06],[-10.07,12.59],[-11.81,12.12],[-13.55,11.64],[-15.31,11.15],[-17.07,10.65],[-18.84,10.14],[-20.6,9.62],[-22.34,9.08],[-24.08,8.52],[-25.78,7.94],[-27.46,7.34],[-29.11,6.71],[-30.7,6.06],[-32.25,5.39],[-33.75,4.69],[-35.18,3.96],[-36.53,3.2],[-37.82,2.42],[-39.01,1.6],[-40.13,0.76],[-41.14,-0.11],[-42.06,-1.0],[-42.88,-1.92],[-43.59,-2.86],[-44.19,-3.83],[-44.68,-4.81],[-45.05,-5.82],[-45.31,-6.84],[-45.46,-7.88],[-45.49,-8.93],[-45.4,-9.99],[-45.21,-11.06],[-44.91,-12.13],[-44.5,-13.21],[-43.99,-14.29],[-43.38,-15.37],[-42.68,-16.44],[-41.9,-17.51],[-41.04,-18.57],[-40.1,-19.62],[-39.11,-20.66],[-38.05,-21.69],[-36.95,-22.7],[-35.81,-23.69],[-34.64,-24.67],[-33.45,-25.63],[-32.24,-26.57],[-31.03,-27.5],[-29.82,-28.4],[-28.62,-29.29],[-27.45,-30.15],[-26.3,-31.0],[-25.18,-31.83],[-24.11,-32.65],[-23.09,-33.44],[-22.12,-34.23],[-21.21,-35.0],[-20.36,-35.76],[-19.58,-36.51],[-18.87,-37.25],[-18.23,-37.99],[-17.67,-38.71],[-17.18,-39.44],[-16.76,-40.17],[-16.42,-40.89],[-16.15,-41.62],[-15.96,-42.35],[-15.82,-43.08],[-15.76,-43.82],[-15.75,-44.57],[-15.79,-45.33],[-15.89,-46.1],[-16.03,-46.87],[-16.2,-47.66],[-16.41,-48.45],[-16.64,-49.26],[-16.89,-50.08],[-17.14,-50.91],[-17.4,-51.75],[-17.66,-52.6],[-17.9,-53.45],[-18.12,-54.32],[-18.32,-55.19],[-18.49,-56.06],[-18.62,-56.94],[-18.7,-57.82],[-18.74,-58.7],[-18.72,-59.58],[-18.64,-60.45],[-18.5,-61.32],[-18.3,-62.18],[-18.02,-63.04],[-17.68,-63.88],[-17.27,-64.71],[-16.79,-65.53],[-16.23,-66.33],[-15.6,-67.12],[-14.91,-67.89],[-14.14,-68.64],[-13.31,-69.38],[-12.42,-70.09],[-11.46,-70.78],[-10.45,-71.46],[-9.39,-72.11],[-8.28,-72.75],[-7.13,-73.36],[-5.94,-73.96],[-4.72,-74.55],[-3.47,-75.11],[-2.2,-75.67],[-0.91,-76.21],[0.39,-76.74],[1.7,-77.26],[3.01,-77.77],[4.32,-78.29],[5.62,-78.8],[6.92,-79.31],[8.19,-79.82],[9.46,-80.34],[10.7,-80.87],[11.92,-81.41],[13.12,-81.97],[14.29,-82.53],[15.44,-83.12],[16.57,-83.72],[17.66,-84.35],[18.74,-84.99],[19.79,-85.66],[20.82,-86.36],[21.83,-87.08],[22.83,-87.82],[23.81,-88.59],[24.79,-89.39],[25.75,-90.21],[26.72,-91.05],[27.68,-91.92],[28.66,-92.8],[29.64,-93.71],[30.63,-94.63],[31.65,-95.57],[32.69,-96.52],[33.75,-97.47],[34.85,-98.44],[35.98,-99.4],[37.15,-100.36],[38.36,-101.32],[39.61,-102.26],[40.91,-103.2],[42.26,-104.11],[43.66,-105.0],[45.11,-105.87],[46.61,-106.71],[48.16,-107.51],[49.77,-108.27],[51.43,-109.0],[53.13,-109.67],[54.89,-110.3],[56.69,-110.88],[58.54,-111.4],[60.42,-111.87],[62.35,-112.27],[64.31,-112.62],[66.3,-112.9],[68.32,-113.12],[70.35,-113.27],[72.41,-113.37],[74.48,-113.39],[76.56,-113.36],[78.65,-113.26],[80.73,-113.1],[82.82,-112.88],[84.89,-112.6],[86.95,-112.27],[89.0,-111.88],[91.02,-111.44],[93.02,-110.96],[95.0,-110.44],[96.95,-109.87],[98.87,-109.28],[100.75,-108.65],[102.6,-107.99],[104.42,-107.31],[106.2,-106.61],[107.95,-105.9],[109.66,-105.17],[111.34,-104.45],[112.98,-103.71],[114.6,-102.98],[116.18,-102.26],[117.73,-101.55],[119.26,-100.84],[120.76,-100.15],[122.25,-99.48],[123.71,-98.83],[125.16,-98.2],[126.6,-97.6],[128.04,-97.02],[129.46,-96.46],[130.88,-95.94],[132.31,-95.43],[133.73,-94.96],[135.16,-94.51],[136.6,-94.09],[138.04,-93.69],[139.5,-93.32],[140.97,-92.96],[142.46,-92.63],[143.95,-92.31],[145.46,-92.01],[146.99,-91.72],[148.52,-91.45],[150.07,-91.17],[151.63,-90.91],[153.19,-90.64],[154.77,-90.37],[156.34,-90.1],[157.92,-89.82],[159.49,-89.53],[161.06,-89.22],[162.61,-88.91],[164.16,-88.57],[165.68,-88.21],[167.19,-87.83],[168.66,-87.43],[170.11,-87.0],[171.52,-86.55],[172.9,-86.07],[174.24,-85.56],[175.52,-85.02],[176.77,-84.45],[177.96,-83.86],[179.09,-83.24],[180.17,-82.58],[181.2,-81.91],[182.16,-81.2],[183.07,-80.48],[183.92,-79.73],[184.71,-78.96],[185.44,-78.17],[186.11,-77.37],[186.74,-76.55],[187.31,-75.72],[187.83,-74.88],[188.3,-74.04],[188.74,-73.18],[189.14,-72.33],[189.51,-71.48],[189.85,-70.63],[190.18,-69.79],[190.49,-68.95],[190.79,-68.12],[191.1,-67.3],[191.4,-66.49],[191.72,-65.7],[192.06,-64.92],[192.42,-64.16],[192.82,-63.41],[193.25,-62.68],[193.73,-61.96],[194.25,-61.27],[194.83,-60.59],[195.46,-59.92],[196.16,-59.27],[196.92,-58.63],[197.75,-58.01],[198.65,-57.4],[199.62,-56.8],[200.67,-56.21],[201.79,-55.62],[202.98,-55.04],[204.24,-54.46],[205.57,-53.88],[206.97,-53.3],[208.42,-52.72],[209.94,-52.13],[211.51,-51.53],[213.13,-50.92],[214.79,-50.3],[216.48,-49.67],[218.2,-49.02],[219.94,-48.36],[221.69,-47.68],[223.45,-46.98],[225.2,-46.25],[226.93,-45.51],[228.65,-44.75],[230.33,-43.96],[231.97,-43.15],[233.56,-42.33],[235.1,-41.48],[236.57,-40.6],[237.97,-39.71],[239.29,-38.8],[240.52,-37.88],[241.66,-36.93],[242.69,-35.97],[243.63,-35.0]],[[248.86,-35.0],[249.73,-33.98],[250.48,-32.95],[251.11,-31.91],[251.62,-30.87],[252.0,-29.82],[252.26,-28.77],[252.4,-27.72],[252.41,-26.68],[252.29,-25.64],[252.06,-24.6],[251.71,-23.57],[251.24,-22.55],[250.66,-21.54],[249.98,-20.55],[249.2,-19.57],[248.33,-18.61],[247.36,-17.66],[246.32,-16.73],[245.2,-15.81],[244.02,-14.91],[242.78,-14.03],[241.49,-13.17],[240.15,-12.33],[238.78,-11.5],[237.38,-10.69],[235.96,-9.89],[234.53,-9.11],[233.09,-8.34],[231.65,-7.58],[230.21,-6.83],[228.79,-6.09],[227.38,-5.35],[225.99,-4.62],[224.63,-3.9],[223.29,-3.17],[221.99,-2.45],[220.71,-1.73],[219.47,-1.0],[218.26,-0.28],[217.09,0.46],[215.95,1.2],[214.84,1.94],[213.76,2.69],[212.71,3.45],[211.69,4.22],[210.69,5.0],[209.7,5.78],[208.73,6.57],[207.77,7.36],[206.81,8.16],[205.86,8.96],[204.9,9.77],[203.93,10.57],[202.95,11.38],[201.94,12.18],[200.92,12.97],[199.86,13.76],[198.77,14.54],[197.65,15.3],[196.48,16.05],[195.27,16.78],[194.01,17.48],[192.71,18.17],[191.35,18.83],[189.94,19.45],[188.47,20.05],[186.95,20.61],[185.38,21.14],[183.75,21.63],[182.07,22.08],[180.33,22.48],[178.55,22.85],[176.72,23.17],[174.85,23.44],[172.94,23.67],[170.99,23.86],[169.01,24.0],[167.0,24.1],[164.96,24.15],[162.91,24.17],[160.84,24.14],[158.76,24.07],[156.68,23.97],[154.6,23.84],[152.52,23.67],[150.45,23.48],[148.4,23.27],[146.36,23.03],[144.35,22.78],[142.36,22.52],[140.4,22.24],[138.47,21.97],[136.58,21.69],[134.72,21.42],[132.89,21.15],[131.1,20.9],[129.36,20.66],[127.65,20.44],[125.97,20.24],[124.34,20.08],[122.74,19.94],[121.17,19.83],[119.63,19.76],[118.12,19.73],[116.64,19.73],[115.18,19.78],[113.74,19.87],[112.32,20.0],[110.9,20.17],[109.5,20.39],[108.09,20.65],[106.69,20.95],[105.28,21.29],[103.87,21.67],[102.44,22.09],[100.99,22.54],[99.53,23.02],[98.05,23.54],[96.54,24.07],[95.0,24.63],[93.43,25.21],[91.83,25.8],[90.2,26.4],[88.54,27.01],[86.84,27.62],[85.11,28.22],[83.34,28.82],[81.54,29.4],[79.71,29.97],[77.85,30.52],[75.96,31.04],[74.05,31.54],[72.11,32.0],[70.15,32.43],[68.18,32.82],[66.19,33.17],[64.2,33.48],[62.19,33.74],[60.19,33.95],[58.18,34.12],[56.18,34.23],[54.19,34.3],[52.22,34.31],[50.26,34.27],[48.32,34.18],[46.4,34.04],[44.5,33.85],[42.64,33.62],[40.8,33.34],[39.0,33.01],[37.23,32.64],[35.49,32.24],[33.78,31.8],[32.11,31.32],[30.48,30.82],[28.88,30.28],[27.3,29.72],[25.76,29.15],[24.25,28.55],[22.76,27.94],[21.3,27.31],[19.86,26.68],[18.43,26.04],[17.02,25.4],[15.62,24.76],[14.22,24.12],[12.83,23.49],[11.44,22.86],[10.04,22.23],[8.63,21.62],[7.21,21.02],[5.78,20.42],[4.33,19.84],[2.86,19.27],[1.37,18.71],[-0.15,18.16],[-1.7,17.62],[-3.27,17.09],[-4.87,16.57],[-6.49,16.05],[-8.14,15.54],[-9.82,15.04],[-11.53,14.53],[-13.25,14.03],[-14.99,13.52],[-16.75,13.01],[-18.52,12.49],[-20.3,11.97],[-22.07,11.43],[-23.85,10.87],[-25.62,10.31],[-27.37,9.72],[-29.1,9.12],[-30.8,8.49],[-32.47,7.84],[-34.09,7.17],[-35.67,6.47],[-37.19,5.75],[-38.65,5.0],[-40.04,4.22],[-41.35,3.41],[-42.58,2.58],[-43.72,1.71],[-44.77,0.82],[-45.72,-0.09],[-46.56,-1.03],[-47.3,-2.0],[-47.93,-2.99],[-48.44,-4.0],[-48.84,-5.03],[-49.12,-6.08],[-49.28,-7.14],[-49.32,-8.22],[-49.25,-9.3],[-49.07,-10.4],[-48.77,-11.5],[-48.36,-12.61],[-47.85,-13.71],[-47.24,-14.82],[-46.53,-15.92],[-45.73,-17.02],[-44.86,-18.11],[-43.9,-19.19],[-42.88,-20.26],[-41.8,-21.31],[-40.67,-22.35],[-39.49,-23.37],[-38.29,-24.38],[-37.05,-25.37],[-35.8,-26.34],[-34.55,-27.29],[-33.29,-28.22],[-32.05,-29.13],[-30.83,-30.02],[-29.63,-30.89],[-28.47,-31.75],[-27.35,-32.58],[-26.28,-33.4],[-25.26,-34.21],[-24.31,-35.0],[-23.42,-35.78],[-22.6,-36.55],[-21.85,-37.31],[-21.18,-38.06],[-20.58,-38.81],[-20.06,-39.56],[-19.62,-40.3],[-19.26,-41.04],[-18.98,-41.79],[-18.77,-42.53],[-18.63,-43.29],[-18.56,-44.05],[-18.56,-44.82],[-18.61,-45.59],[-18.72,-46.38],[-18.87,-47.18],[-19.07,-47.98],[-19.3,-48.8],[-19.56,-49.64],[-19.84,-50.48],[-20.13,-51.33],[-20.43,-52.2],[-20.73,-53.08],[-21.01,-53.96],[-21.29,-54.86],[-21.53,-55.76],[-21.75,-56.67],[-21.93,-57.58],[-22.07,-58.49],[-22.16,-59.41],[-22.19,-60.33],[-22.17,-61.24],[-22.08,-62.15],[-21.93,-63.05],[-21.7,-63.95],[-21.41,-64.84],[-21.04,-65.71],[-20.59,-66.57],[-20.07,-67.42],[-19.48,-68.25],[-18.81,-69.06],[-18.07,-69.86],[-17.26,-70.63],[-16.38,-71.39],[-15.44,-72.12],[-14.44,-72.84],[-13.38,-73.53],[-12.27,-74.2],[-11.11,-74.86],[-9.9,-75.49],[-8.66,-76.11],[-7.39,-76.71],[-6.09,-77.29],[-4.77,-77.86],[-3.44,-78.42],[-2.09,-78.97],[-0.73,-79.52],[0.62,-80.05],[1.98,-80.58],[3.32,-81.12],[4.66,-81.65],[5.98,-82.19],[7.28,-82.74],[8.56,-83.29],[9.82,-83.86],[11.06,-84.44],[12.28,-85.03],[13.47,-85.65],[14.63,-86.28],[15.77,-86.94],[16.89,-87.62],[17.99,-88.32],[19.07,-89.05],[20.13,-89.8],[21.17,-90.58],[22.21,-91.38],[23.24,-92.21],[24.27,-93.06],[25.29,-93.94],[26.32,-94.84],[27.36,-95.75],[28.42,-96.69],[29.49,-97.63],[30.58,-98.6],[31.7,-99.57],[32.85,-100.54],[34.04,-101.52],[35.26,-102.5],[36.52,-103.47],[37.83,-104.43],[39.18,-105.38],[40.58,-106.32],[42.03,-107.23],[43.53,-108.11],[45.08,-108.97],[46.69,-109.79],[48.35,-110.57],[50.06,-111.31],[51.82,-112.01],[53.64,-112.65],[55.5,-113.25],[57.4,-113.78],[59.35,-114.26],[61.33,-114.68],[63.35,-115.04],[65.4,-115.33],[67.48,-115.56],[69.58,-115.72],[71.71,-115.82],[73.84,-115.85],[75.99,-115.81],[78.14,-115.71],[80.29,-115.54],[82.43,-115.32],[84.57,-115.03],[86.7,-114.68],[88.81,-114.28],[90.9,-113.83],[92.96,-113.33],[95.0,-112.78],[97.01,-112.19],[98.99,-111.56],[100.93,-110.9],[102.84,-110.21],[104.71,-109.5],[106.54,-108.77],[108.34,-108.02],[110.1,-107.26],[111.82,-106.49],[113.51,-105.72],[115.16,-104.95],[116.78,-104.18],[118.37,-103.42],[119.94,-102.68],[121.47,-101.95],[122.99,-101.23],[124.48,-100.54],[125.96,-99.87],[127.43,-99.23],[128.88,-98.61],[130.33,-98.02],[131.78,-97.46],[133.22,-96.92],[134.67,-96.42],[136.12,-95.94],[137.58,-95.49],[139.05,-95.07],[140.53,-94.67],[142.03,-94.29],[143.53,-93.94],[145.06,-93.61],[146.59,-93.29],[148.15,-92.99],[149.72,-92.7],[151.3,-92.42],[152.89,-92.15],[154.49,-91.88],[156.11,-91.61],[157.73,-91.34],[159.35,-91.06],[160.97,-90.78],[162.59,-90.48],[164.2,-90.17],[165.8,-89.84],[167.38,-89.49],[168.95,-89.12],[170.49,-88.73],[172.0,-88.31],[173.48,-87.87],[174.92,-87.4],[176.33,-86.9],[177.69,-86.37],[179.0,-85.81],[180.27,-85.22],[181.48,-84.6],[182.63,-83.96],[183.73,-83.28],[184.77,-82.58],[185.75,-81.86],[186.67,-81.11],[187.52,-80.34],[188.32,-79.55],[189.07,-78.74],[189.75,-77.92],[190.39,-77.08],[190.97,-76.23],[191.5,-75.37],[191.99,-74.51],[192.45,-73.64],[192.87,-72.78],[193.26,-71.91],[193.63,-71.05],[193.98,-70.19],[194.32,-69.34],[194.66,-68.5],[195.0,-67.67],[195.35,-66.85],[195.72,-66.05],[196.11,-65.26],[196.53,-64.49],[196.99,-63.73],[197.48,-62.99],[198.03,-62.27],[198.62,-61.56],[199.28,-60.87],[199.99,-60.19],[200.77,-59.53],[201.62,-58.88],[202.54,-58.24],[203.54,-57.61],[204.6,-57.0],[205.74,-56.38],[206.96,-55.78],[208.25,-55.17],[209.6,-54.57],[211.03,-53.96],[212.52,-53.36],[214.07,-52.74],[215.67,-52.12],[217.33,-51.49],[219.03,-50.85],[220.76,-50.19],[222.53,-49.52],[224.32,-48.83],[226.12,-48.12],[227.92,-47.39],[229.73,-46.65],[231.52,-45.88],[233.29,-45.09],[235.03,-44.27],[236.73,-43.44],[238.38,-42.58],[239.97,-41.7],[241.5,-40.8],[242.95,-39.88],[244.32,-38.94],[245.61,-37.98],[246.79,-37.0],[247.88,-36.01],[248.86,-35.0]],[[254.09,-35.0],[255.0,-33.95],[255.78,-32.88],[256.45,-31.81],[256.99,-30.73],[257.4,-29.65],[257.67,-28.56],[257.82,-27.47],[257.84,-26.39],[257.73,-25.31],[257.5,-24.24],[257.14,-23.17],[256.66,-22.12],[256.06,-21.08],[255.35,-20.05],[254.54,-19.04],[253.63,-18.04],[252.62,-17.06],[251.53,-16.1],[250.36,-15.15],[249.11,-14.23],[247.8,-13.32],[246.44,-12.43],[245.03,-11.57],[243.58,-10.72],[242.1,-9.88],[240.59,-9.07],[239.07,-8.26],[237.54,-7.48],[236.0,-6.7],[234.47,-5.94],[232.95,-5.19],[231.44,-4.44],[229.96,-3.7],[228.49,-2.97],[227.06,-2.24],[225.66,-1.51],[224.29,-0.78],[222.95,-0.05],[221.65,0.68],[220.39,1.42],[219.16,2.16],[217.97,2.91],[216.81,3.66],[215.69,4.42],[214.59,5.2],[213.52,5.97],[212.46,6.76],[211.43,7.55],[210.41,8.35],[209.4,9.16],[208.4,9.97],[207.39,10.78],[206.38,11.6],[205.36,12.41],[204.32,13.23],[203.26,14.03],[202.17,14.84],[201.06,15.63],[199.91,16.41],[198.72,17.17],[197.49,17.92],[196.21,18.65],[194.89,19.36],[193.51,20.03],[192.08,20.69],[190.6,21.31],[189.07,21.89],[187.48,22.44],[185.83,22.96],[184.13,23.43],[182.38,23.86],[180.58,24.25],[178.73,24.6],[176.84,24.9],[174.9,25.15],[172.93,25.36],[170.92,25.53],[168.88,25.65],[166.82,25.72],[164.73,25.76],[162.63,25.75],[160.52,25.7],[158.4,25.62],[156.28,25.5],[154.16,25.35],[152.05,25.17],[149.95,24.96],[147.87,24.74],[145.81,24.49],[143.78,24.23],[141.77,23.97],[139.79,23.69],[137.84,23.42],[135.93,23.15],[134.06,22.88],[132.22,22.63],[130.42,22.39],[128.66,22.17],[126.94,21.97],[125.26,21.8],[123.61,21.66],[121.99,21.55],[120.41,21.48],[118.85,21.44],[117.32,21.45],[115.82,21.5],[114.33,21.59],[112.86,21.72],[111.4,21.9],[109.95,22.12],[108.5,22.39],[107.06,22.7],[105.6,23.05],[104.14,23.44],[102.67,23.87],[101.18,24.34],[99.67,24.84],[98.14,25.37],[96.59,25.93],[95.0,26.51],[93.38,27.11],[91.73,27.73],[90.05,28.35],[88.33,28.99],[86.58,29.63],[84.79,30.26],[82.96,30.89],[81.1,31.51],[79.21,32.11],[77.28,32.69],[75.33,33.25],[73.34,33.78],[71.34,34.28],[69.31,34.74],[67.26,35.16],[65.19,35.54],[63.12,35.88],[61.04,36.17],[58.95,36.4],[56.86,36.59],[54.78,36.73],[52.71,36.81],[50.65,36.84],[48.61,36.82],[46.59,36.74],[44.58,36.62],[42.61,36.43],[40.66,36.2],[38.75,35.92],[36.87,35.6],[35.02,35.22],[33.21,34.81],[31.44,34.36],[29.7,33.87],[28.0,33.35],[26.33,32.79],[24.7,32.21],[23.11,31.61],[21.54,30.98],[20.01,30.34],[18.5,29.69],[17.01,29.02],[15.55,28.34],[14.1,27.67],[12.67,26.98],[11.24,26.3],[9.82,25.63],[8.41,24.95],[6.99,24.29],[5.57,23.63],[4.14,22.98],[2.69,22.34],[1.23,21.71],[-0.25,21.1],[-1.75,20.49],[-3.27,19.9],[-4.82,19.32],[-6.39,18.75],[-7.99,18.18],[-9.62,17.63],[-11.28,17.08],[-12.96,16.54],[-14.67,15.99],[-16.39,15.45],[-18.14,14.91],[-19.91,14.37],[-21.69,13.82],[-23.47,13.26],[-25.26,12.69],[-27.05,12.11],[-28.83,11.52],[-30.6,10.9],[-32.35,10.27],[-34.07,9.62],[-35.76,8.95],[-37.41,8.26],[-39.01,7.53],[-40.56,6.79],[-42.05,6.01],[-43.46,5.21],[-44.81,4.38],[-46.07,3.53],[-47.24,2.64],[-48.32,1.73],[-49.29,0.79],[-50.17,-0.17],[-50.93,-1.16],[-51.59,-2.17],[-52.13,-3.2],[-52.55,-4.26],[-52.85,-5.33],[-53.03,-6.42],[-53.09,-7.52],[-53.04,-8.63],[-52.86,-9.75],[-52.57,-10.88],[-52.17,-12.01],[-51.66,-13.15],[-51.04,-14.28],[-50.33,-15.41],[-49.52,-16.54],[-48.63,-17.65],[-47.66,-18.76],[-46.62,-19.86],[-45.51,-20.94],[-44.35,-22.01],[-43.15,-23.06],[-41.91,-24.09],[-40.64,-25.11],[-39.35,-26.1],[-38.05,-27.08],[-36.76,-28.03],[-35.47,-28.97],[-34.2,-29.88],[-32.96,-30.78],[-31.75,-31.66],[-30.59,-32.52],[-29.47,-33.36],[-28.41,-34.19],[-27.41,-35.0],[-26.48,-35.8],[-25.62,-36.59],[-24.84,-37.37],[-24.13,-38.14],[-23.5,-38.91],[-22.96,-39.67],[-22.5,-40.43],[-22.11,-41.19],[-21.81,-41.95],[-21.59,-42.72],[-21.45,-43.49],[-21.38,-44.27],[-21.37,-45.06],[-21.43,-45.86],[-21.55,-46.66],[-21.72,-47.48],[-21.94,-48.31],[-22.19,-49.15],[-22.48,-50.01],[-22.8,-50.88],[-23.13,-51.76],[-23.47,-52.65],[-23.81,-53.56],[-24.14,-54.47],[-24.46,-55.4],[-24.76,-56.33],[-25.03,-57.28],[-25.27,-58.22],[-25.46,-59.17],[-25.6,-60.13],[-25.69,-61.08],[-25.72,-62.04],[-25.69,-62.99],[-25.58,-63.93],[-25.41,-64.87],[-25.16,-65.8],[-24.84,-66.72],[-24.44,-67.62],[-23.96,-68.51],[-23.4,-69.39],[-22.76,-70.24],[-22.05,-71.08],[-21.26,-71.9],[-20.4,-72.7],[-19.47,-73.48],[-18.48,-74.23],[-17.42,-74.97],[-16.31,-75.68],[-15.14,-76.37],[-13.93,-77.04],[-12.67,-77.7],[-11.37,-78.33],[-10.05,-78.95],[-8.7,-79.55],[-7.32,-80.14],[-5.94,-80.72],[-4.54,-81.29],[-3.14,-81.85],[-1.73,-82.4],[-0.33,-82.96],[1.06,-83.51],[2.44,-84.07],[3.8,-84.63],[5.15,-85.2],[6.48,-85.78],[7.78,-86.37],[9.06,-86.98],[10.32,-87.6],[11.56,-88.25],[12.77,-88.91],[13.95,-89.6],[15.12,-90.31],[16.27,-91.04],[17.4,-91.8],[18.51,-92.58],[19.61,-93.39],[20.71,-94.23],[21.8,-95.09],[22.89,-95.97],[23.98,-96.88],[25.08,-97.8],[26.2,-98.74],[27.33,-99.7],[28.48,-100.67],[29.66,-101.65],[30.86,-102.64],[32.1,-103.63],[33.38,-104.63],[34.69,-105.61],[36.05,-106.59],[37.45,-107.56],[38.91,-108.51],[40.41,-109.43],[41.97,-110.34],[43.57,-111.21],[45.23,-112.05],[46.95,-112.85],[48.71,-113.6],[50.53,-114.32],[52.4,-114.98],[54.31,-115.59],[56.28,-116.14],[58.28,-116.63],[60.32,-117.06],[62.4,-117.43],[64.52,-117.74],[66.66,-117.97],[68.82,-118.14],[71.01,-118.24],[73.21,-118.27],[75.42,-118.23],[77.63,-118.13],[79.85,-117.96],[82.06,-117.73],[84.26,-117.43],[86.45,-117.07],[88.62,-116.66],[90.77,-116.19],[92.9,-115.66],[95.0,-115.09],[97.07,-114.48],[99.1,-113.83],[101.1,-113.14],[103.07,-112.42],[104.99,-111.67],[106.88,-110.91],[108.72,-110.12],[110.53,-109.32],[112.3,-108.51],[114.03,-107.7],[115.72,-106.89],[117.38,-106.08],[119.01,-105.28],[120.61,-104.49],[122.17,-103.72],[123.72,-102.97],[125.24,-102.24],[126.75,-101.53],[128.24,-100.84],[129.72,-100.18],[131.19,-99.56],[132.66,-98.96],[134.13,-98.39],[135.6,-97.85],[137.07,-97.34],[138.55,-96.87],[140.04,-96.42],[141.55,-95.99],[143.06,-95.6],[144.59,-95.23],[146.14,-94.88],[147.71,-94.55],[149.29,-94.24],[150.89,-93.94],[152.5,-93.65],[154.13,-93.38],[155.77,-93.11],[157.43,-92.84],[159.09,-92.57],[160.76,-92.29],[162.43,-92.01],[164.09,-91.72],[165.76,-91.41],[167.42,-91.09],[169.06,-90.75],[170.69,-90.4],[172.29,-90.01],[173.87,-89.61],[175.42,-89.17],[176.93,-88.71],[178.41,-88.22],[179.85,-87.71],[181.23,-87.16],[182.57,-86.58],[183.86,-85.97],[185.09,-85.33],[186.26,-84.66],[187.38,-83.97],[188.43,-83.25],[189.43,-82.5],[190.36,-81.73],[191.23,-80.94],[192.05,-80.13],[192.8,-79.3],[193.5,-78.45],[194.15,-77.6],[194.74,-76.73],[195.29,-75.85],[195.8,-74.97],[196.28,-74.09],[196.72,-73.21],[197.14,-72.33],[197.53,-71.45],[197.92,-70.58],[198.3,-69.72],[198.67,-68.87],[199.06,-68.03],[199.46,-67.2],[199.88,-66.39],[200.32,-65.59],[200.8,-64.81],[201.32,-64.04],[201.89,-63.29],[202.5,-62.55],[203.18,-61.83],[203.91,-61.13],[204.71,-60.44],[205.58,-59.76],[206.51,-59.1],[207.52,-58.45],[208.61,-57.8],[209.77,-57.16],[211.01,-56.53],[212.32,-55.9],[213.7,-55.27],[215.15,-54.64],[216.67,-54.0],[218.25,-53.37],[219.89,-52.72],[221.58,-52.06],[223.32,-51.39],[225.09,-50.71],[226.9,-50.01],[228.73,-49.3],[230.58,-48.57],[232.43,-47.81],[234.29,-47.04],[236.13,-46.24],[237.95,-45.43],[239.74,-44.59],[241.49,-43.72],[243.2,-42.84],[244.85,-41.93],[246.43,-40.99],[247.94,-40.04],[249.36,-39.07],[250.7,-38.08],[251.93,-37.07],[253.07,-36.04],[254.09,-35.0]],[[259.31,-35.0],[260.26,-33.91],[261.08,-32.81],[261.78,-31.7],[262.34,-30.59],[262.78,-29.47],[263.08,-28.35],[263.24,-27.22],[263.27,-26.1],[263.16,-24.99],[262.92,-23.88],[262.56,-22.78],[262.06,-21.69],[261.45,-20.61],[260.71,-19.55],[259.87,-18.5],[258.91,-17.47],[257.86,-16.46],[256.72,-15.47],[255.49,-14.5],[254.19,-13.54],[252.82,-12.61],[251.38,-11.7],[249.89,-10.81],[248.36,-9.93],[246.8,-9.08],[245.2,-8.24],[243.59,-7.43],[241.96,-6.62],[240.33,-5.83],[238.7,-5.06],[237.08,-4.29],[235.48,-3.54],[233.89,-2.79],[232.33,-2.05],[230.79,-1.31],[229.29,-0.58],[227.82,0.15],[226.39,0.89],[225.0,1.62],[223.65,2.36],[222.33,3.11],[221.05,3.86],[219.81,4.61],[218.61,5.38],[217.43,6.15],[216.29,6.93],[215.17,7.72],[214.08,8.52],[213.0,9.32],[211.93,10.14],[210.88,10.95],[209.82,11.77],[208.77,12.6],[207.71,13.42],[206.63,14.25],[205.54,15.07],[204.42,15.88],[203.28,16.69],[202.11,17.49],[200.9,18.27],[199.65,19.04],[198.35,19.78],[197.01,20.51],[195.62,21.21],[194.18,21.89],[192.68,22.53],[191.13,23.14],[189.53,23.72],[187.87,24.26],[186.16,24.76],[184.39,25.22],[182.58,25.64],[180.71,26.01],[178.8,26.33],[176.84,26.62],[174.85,26.85],[172.82,27.04],[170.75,27.18],[168.66,27.28],[166.55,27.34],[164.42,27.35],[162.27,27.32],[160.11,27.26],[157.96,27.15],[155.8,27.02],[153.65,26.85],[151.51,26.66],[149.39,26.45],[147.28,26.21],[145.2,25.96],[143.14,25.7],[141.12,25.44],[139.12,25.17],[137.17,24.9],[135.24,24.63],[133.36,24.38],[131.51,24.14],[129.7,23.92],[127.93,23.73],[126.19,23.55],[124.49,23.41],[122.83,23.3],[121.19,23.23],[119.59,23.19],[118.01,23.2],[116.46,23.25],[114.93,23.34],[113.41,23.48],[111.91,23.66],[110.41,23.88],[108.92,24.16],[107.43,24.47],[105.93,24.84],[104.42,25.24],[102.91,25.68],[101.37,26.16],[99.82,26.68],[98.24,27.23],[96.63,27.81],[95.0,28.41],[93.33,29.03],[91.63,29.68],[89.9,30.33],[88.12,30.99],[86.31,31.66],[84.47,32.32],[82.58,32.98],[80.66,33.63],[78.7,34.27],[76.71,34.88],[74.69,35.47],[72.63,36.03],[70.55,36.56],[68.45,37.06],[66.33,37.51],[64.19,37.92],[62.03,38.29],[59.87,38.61],[57.7,38.87],[55.54,39.09],[53.37,39.25],[51.22,39.35],[49.08,39.4],[46.95,39.39],[44.84,39.33],[42.76,39.21],[40.7,39.04],[38.68,38.81],[36.68,38.53],[34.72,38.2],[32.8,37.82],[30.92,37.4],[29.07,36.94],[27.26,36.44],[25.5,35.9],[23.77,35.32],[22.08,34.72],[20.43,34.09],[18.81,33.44],[17.23,32.76],[15.67,32.07],[14.14,31.37],[12.64,30.66],[11.16,29.94],[9.7,29.22],[8.24,28.5],[6.8,27.78],[5.37,27.06],[3.93,26.35],[2.49,25.64],[1.05,24.95],[-0.4,24.26],[-1.87,23.59],[-3.35,22.93],[-4.86,22.28],[-6.38,21.64],[-7.93,21.01],[-9.51,20.4],[-11.11,19.79],[-12.73,19.19],[-14.39,18.6],[-16.07,18.02],[-17.78,17.44],[-19.51,16.86],[-21.26,16.29],[-23.02,15.71],[-24.81,15.12],[-26.6,14.53],[-28.4,13.93],[-30.2,13.32],[-31.99,12.7],[-33.77,12.06],[-35.54,11.41],[-37.28,10.73],[-38.99,10.03],[-40.66,9.32],[-42.28,8.57],[-43.85,7.8],[-45.37,7.01],[-46.81,6.19],[-48.18,5.34],[-49.47,4.46],[-50.67,3.55],[-51.78,2.62],[-52.79,1.66],[-53.69,0.68],[-54.49,-0.33],[-55.17,-1.37],[-55.73,-2.42],[-56.18,-3.5],[-56.51,-4.59],[-56.71,-5.71],[-56.79,-6.83],[-56.75,-7.97],[-56.59,-9.12],[-56.31,-10.27],[-55.91,-11.43],[-55.41,-12.59],[-54.79,-13.75],[-54.08,-14.91],[-53.26,-16.06],[-52.36,-17.2],[-51.38,-18.34],[-50.32,-19.46],[-49.2,-20.57],[-48.01,-21.67],[-46.78,-22.75],[-45.51,-23.81],[-44.21,-24.85],[-42.88,-25.87],[-41.55,-26.87],[-40.21,-27.85],[-38.89,-28.81],[-37.58,-29.75],[-36.29,-30.67],[-35.04,-31.57],[-33.83,-32.45],[-32.67,-33.32],[-31.57,-34.17],[-30.53,-35.0],[-29.55,-35.82],[-28.65,-36.63],[-27.83,-37.43],[-27.09,-38.22],[-26.44,-39.0],[-25.86,-39.78],[-25.38,-40.56],[-24.98,-41.34],[-24.66,-42.12],[-24.43,-42.91],[-24.28,-43.7],[-24.2,-44.5],[-24.2,-45.3],[-24.27,-46.12],[-24.4,-46.95],[-24.58,-47.79],[-24.82,-48.64],[-25.1,-49.5],[-25.42,-50.38],[-25.77,-51.28],[-26.14,-52.19],[-26.52,-53.11],[-26.9,-54.04],[-27.28,-54.99],[-27.65,-55.94],[-28.01,-56.91],[-28.33,-57.89],[-28.62,-58.87],[-28.87,-59.86],[-29.07,-60.85],[-29.21,-61.85],[-29.3,-62.84],[-29.32,-63.83],[-29.27,-64.82],[-29.15,-65.8],[-28.95,-66.77],[-28.68,-67.73],[-28.32,-68.68],[-27.88,-69.62],[-27.36,-70.54],[-26.75,-71.44],[-26.07,-72.32],[-25.31,-73.18],[-24.47,-74.03],[-23.55,-74.85],[-22.57,-75.65],[-21.52,-76.42],[-20.4,-77.18],[-19.23,-77.91],[-18.01,-78.62],[-16.73,-79.31],[-15.42,-79.98],[-14.07,-80.63],[-12.69,-81.26],[-11.28,-81.88],[-9.85,-82.49],[-8.41,-83.08],[-6.96,-83.67],[-5.5,-84.25],[-4.05,-84.82],[-2.6,-85.4],[-1.16,-85.97],[0.27,-86.55],[1.68,-87.13],[3.08,-87.73],[4.45,-88.33],[5.8,-88.95],[7.13,-89.58],[8.44,-90.23],[9.72,-90.91],[10.98,-91.6],[12.22,-92.31],[13.44,-93.05],[14.64,-93.82],[15.82,-94.61],[16.99,-95.42],[18.16,-96.26],[19.32,-97.13],[20.47,-98.01],[21.63,-98.92],[22.8,-99.86],[23.97,-100.8],[25.16,-101.77],[26.38,-102.75],[27.61,-103.74],[28.87,-104.74],[30.17,-105.74],[31.5,-106.74],[32.87,-107.74],[34.29,-108.73],[35.74,-109.71],[37.25,-110.68],[38.81,-111.62],[40.42,-112.54],[42.08,-113.42],[43.79,-114.28],[45.56,-115.09],[47.38,-115.87],[49.25,-116.6],[51.18,-117.27],[53.15,-117.9],[55.17,-118.46],[57.23,-118.97],[59.33,-119.41],[61.47,-119.79],[63.64,-120.11],[65.85,-120.35],[68.07,-120.52],[70.32,-120.63],[72.58,-120.66],[74.85,-120.63],[77.13,-120.52],[79.41,-120.35],[81.68,-120.11],[83.95,-119.8],[86.2,-119.43],[88.44,-119.0],[90.65,-118.52],[92.84,-117.98],[95.0,-117.39],[97.13,-116.75],[99.22,-116.07],[101.28,-115.35],[103.29,-114.6],[105.27,-113.82],[107.21,-113.02],[109.1,-112.2],[110.96,-111.36],[112.77,-110.52],[114.54,-109.67],[116.28,-108.81],[117.97,-107.97],[119.64,-107.12],[121.27,-106.29],[122.87,-105.48],[124.45,-104.68],[126.0,-103.91],[127.53,-103.16],[129.05,-102.44],[130.55,-101.74],[132.05,-101.07],[133.54,-100.44],[135.02,-99.84],[136.51,-99.27],[138.01,-98.73],[139.51,-98.22],[141.02,-97.75],[142.54,-97.3],[144.08,-96.89],[145.64,-96.5],[147.21,-96.13],[148.8,-95.79],[150.41,-95.46],[152.04,-95.16],[153.69,-94.86],[155.35,-94.58],[157.03,-94.31],[158.72,-94.04],[160.43,-93.77],[162.14,-93.5],[163.86,-93.22],[165.58,-92.94],[167.3,-92.64],[169.02,-92.33],[170.72,-92.0],[172.41,-91.66],[174.08,-91.29],[175.73,-90.89],[177.35,-90.47],[178.93,-90.02],[180.48,-89.55],[181.99,-89.04],[183.46,-88.5],[184.88,-87.94],[186.24,-87.34],[187.55,-86.71],[188.81,-86.05],[190.0,-85.36],[191.14,-84.64],[192.21,-83.9],[193.22,-83.13],[194.17,-82.34],[195.05,-81.53],[195.88,-80.69],[196.65,-79.84],[197.37,-78.98],[198.03,-78.1],[198.64,-77.22],[199.21,-76.33],[199.74,-75.43],[200.24,-74.53],[200.71,-73.63],[201.15,-72.74],[201.58,-71.85],[202.0,-70.96],[202.42,-70.09],[202.84,-69.23],[203.27,-68.37],[203.72,-67.54],[204.19,-66.71],[204.7,-65.9],[205.24,-65.11],[205.83,-64.33],[206.46,-63.57],[207.16,-62.82],[207.91,-62.09],[208.72,-61.37],[209.61,-60.67],[210.56,-59.98],[211.59,-59.29],[212.69,-58.62],[213.87,-57.95],[215.13,-57.29],[216.46,-56.64],[217.86,-55.98],[219.34,-55.32],[220.88,-54.66],[222.49,-54.0],[224.16,-53.32],[225.88,-52.64],[227.65,-51.95],[229.46,-51.24],[231.31,-50.52],[233.18,-49.77],[235.07,-49.02],[236.97,-48.24],[238.87,-47.44],[240.76,-46.61],[242.63,-45.77],[244.47,-44.9],[246.27,-44.01],[248.03,-43.09],[249.73,-42.15],[251.36,-41.19],[252.92,-40.21],[254.4,-39.2],[255.78,-38.18],[257.07,-37.13],[258.24,-36.07],[259.31,-35.0]],[[264.52,-35.0],[265.5,-33.88],[266.36,-32.74],[267.09,-31.6],[267.68,-30.45],[268.14,-29.29],[268.46,-28.13],[268.63,-26.97],[268.67,-25.82],[268.57,-24.67],[268.33,-23.52],[267.95,-22.39],[267.45,-21.26],[266.81,-20.15],[266.05,-19.05],[265.17,-17.97],[264.18,-16.91],[263.09,-15.87],[261.9,-14.84],[260.61,-13.84],[259.25,-12.86],[257.81,-11.9],[256.3,-10.97],[254.74,-10.05],[253.13,-9.16],[251.48,-8.28],[249.79,-7.43],[248.09,-6.59],[246.37,-5.77],[244.64,-4.97],[242.91,-4.18],[241.19,-3.41],[239.48,-2.64],[237.79,-1.89],[236.13,-1.14],[234.49,-0.4],[232.89,0.34],[231.32,1.08],[229.8,1.82],[228.31,2.55],[226.86,3.3],[225.45,4.04],[224.09,4.79],[222.76,5.55],[221.48,6.32],[220.23,7.09],[219.01,7.87],[217.82,8.67],[216.66,9.47],[215.53,10.27],[214.4,11.09],[213.3,11.91],[212.19,12.74],[211.1,13.57],[209.99,14.4],[208.88,15.24],[207.76,16.07],[206.61,16.9],[205.44,17.72],[204.25,18.53],[203.02,19.34],[201.75,20.12],[200.44,20.89],[199.08,21.64],[197.68,22.36],[196.22,23.06],[194.72,23.73],[193.16,24.37],[191.54,24.97],[189.87,25.54],[188.15,26.07],[186.37,26.55],[184.54,27.0],[182.66,27.4],[180.74,27.75],[178.76,28.06],[176.75,28.32],[174.7,28.54],[172.61,28.71],[170.5,28.83],[168.36,28.91],[166.19,28.95],[164.02,28.94],[161.83,28.9],[159.64,28.82],[157.45,28.7],[155.26,28.55],[153.08,28.37],[150.91,28.17],[148.76,27.95],[146.64,27.71],[144.54,27.46],[142.46,27.2],[140.42,26.94],[138.42,26.67],[136.44,26.41],[134.51,26.16],[132.61,25.93],[130.75,25.71],[128.93,25.51],[127.14,25.34],[125.39,25.2],[123.68,25.09],[122.0,25.02],[120.34,24.98],[118.72,24.99],[117.12,25.03],[115.54,25.13],[113.98,25.27],[112.42,25.45],[110.88,25.68],[109.34,25.96],[107.81,26.29],[106.26,26.66],[104.71,27.07],[103.15,27.52],[101.57,28.02],[99.96,28.55],[98.34,29.12],[96.68,29.71],[95.0,30.34],[93.28,30.98],[91.53,31.65],[89.74,32.33],[87.91,33.02],[86.05,33.71],[84.14,34.41],[82.2,35.1],[80.21,35.78],[78.19,36.44],[76.13,37.09],[74.04,37.71],[71.92,38.31],[69.77,38.87],[67.59,39.4],[65.39,39.88],[63.17,40.33],[60.94,40.72],[58.7,41.07],[56.45,41.36],[54.2,41.6],[51.95,41.78],[49.71,41.9],[47.49,41.97],[45.28,41.98],[43.09,41.93],[40.92,41.82],[38.78,41.65],[36.67,41.43],[34.6,41.15],[32.56,40.82],[30.56,40.44],[28.61,40.01],[26.69,39.54],[24.81,39.02],[22.98,38.46],[21.19,37.87],[19.44,37.24],[17.73,36.59],[16.06,35.9],[14.43,35.2],[12.83,34.48],[11.26,33.74],[9.72,32.99],[8.2,32.23],[6.71,31.47],[5.23,30.7],[3.77,29.94],[2.31,29.17],[0.86,28.41],[-0.59,27.66],[-2.04,26.92],[-3.5,26.19],[-4.97,25.47],[-6.46,24.76],[-7.96,24.06],[-9.49,23.38],[-11.04,22.7],[-12.61,22.04],[-14.2,21.39],[-15.83,20.75],[-17.48,20.12],[-19.15,19.49],[-20.86,18.87],[-22.58,18.26],[-24.33,17.64],[-26.1,17.03],[-27.88,16.41],[-29.68,15.79],[-31.48,15.16],[-33.29,14.52],[-35.09,13.86],[-36.88,13.2],[-38.66,12.52],[-40.41,11.82],[-42.14,11.09],[-43.83,10.35],[-45.47,9.58],[-47.07,8.79],[-48.6,7.98],[-50.07,7.13],[-51.47,6.26],[-52.79,5.36],[-54.02,4.44],[-55.16,3.49],[-56.2,2.51],[-57.13,1.5],[-57.95,0.47],[-58.67,-0.58],[-59.26,-1.66],[-59.73,-2.76],[-60.08,-3.88],[-60.31,-5.01],[-60.41,-6.16],[-60.39,-7.32],[-60.25,-8.49],[-59.98,-9.67],[-59.6,-10.85],[-59.1,-12.04],[-58.49,-13.22],[-57.78,-14.41],[-56.96,-15.59],[-56.05,-16.76],[-55.06,-17.92],[-53.99,-19.07],[-52.85,-20.21],[-51.64,-21.33],[-50.39,-22.43],[-49.09,-23.52],[-47.76,-24.59],[-46.41,-25.64],[-45.04,-26.66],[-43.67,-27.67],[-42.3,-28.65],[-40.95,-29.62],[-39.62,-30.56],[-38.33,-31.49],[-37.08,-32.39],[-35.88,-33.28],[-34.73,-34.15],[-33.65,-35.0],[-32.64,-35.84],[-31.7,-36.67],[-30.85,-37.49],[-30.08,-38.3],[-29.39,-39.1],[-28.79,-39.9],[-28.28,-40.7],[-27.86,-41.5],[-27.53,-42.3],[-27.29,-43.1],[-27.13,-43.91],[-27.05,-44.72],[-27.05,-45.55],[-27.12,-46.39],[-27.26,-47.23],[-27.47,-48.09],[-27.73,-48.97],[-28.03,-49.86],[-28.38,-50.76],[-28.76,-51.68],[-29.17,-52.62],[-29.59,-53.56],[-30.02,-54.53],[-30.45,-55.5],[-30.87,-56.49],[-31.27,-57.49],[-31.65,-58.5],[-32.0,-59.52],[-32.3,-60.55],[-32.56,-61.58],[-32.76,-62.61],[-32.91,-63.65],[-32.98,-64.68],[-32.99,-65.71],[-32.92,-66.73],[-32.78,-67.75],[-32.55,-68.76],[-32.24,-69.75],[-31.84,-70.73],[-31.36,-71.7],[-30.79,-72.65],[-30.14,-73.58],[-29.4,-74.48],[-28.59,-75.37],[-27.69,-76.24],[-26.72,-77.08],[-25.67,-77.9],[-24.56,-78.7],[-23.38,-79.47],[-22.15,-80.22],[-20.86,-80.94],[-19.52,-81.65],[-18.15,-82.34],[-16.73,-83.0],[-15.29,-83.65],[-13.82,-84.29],[-12.34,-84.91],[-10.84,-85.52],[-9.33,-86.12],[-7.82,-86.72],[-6.31,-87.31],[-4.81,-87.91],[-3.31,-88.5],[-1.83,-89.1],[-0.37,-89.7],[1.07,-90.32],[2.5,-90.95],[3.9,-91.59],[5.28,-92.25],[6.64,-92.93],[7.97,-93.62],[9.29,-94.35],[10.58,-95.09],[11.85,-95.86],[13.11,-96.65],[14.36,-97.47],[15.59,-98.31],[16.82,-99.18],[18.05,-100.07],[19.27,-100.98],[20.5,-101.91],[21.75,-102.87],[23.0,-103.84],[24.27,-104.82],[25.57,-105.82],[26.89,-106.83],[28.25,-107.84],[29.64,-108.85],[31.07,-109.86],[32.53,-110.86],[34.05,-111.85],[35.61,-112.83],[37.22,-113.78],[38.88,-114.71],[40.6,-115.61],[42.37,-116.48],[44.19,-117.31],[46.06,-118.1],[47.99,-118.84],[49.97,-119.54],[52.0,-120.17],[54.07,-120.75],[56.19,-121.27],[58.35,-121.73],[60.55,-122.12],[62.78,-122.44],[65.04,-122.69],[67.33,-122.87],[69.64,-122.98],[71.96,-123.02],[74.3,-122.99],[76.64,-122.88],[78.98,-122.7],[81.32,-122.46],[83.65,-122.14],[85.96,-121.76],[88.26,-121.32],[90.53,-120.82],[92.78,-120.26],[95.0,-119.65],[97.19,-118.99],[99.34,-118.29],[101.45,-117.54],[103.52,-116.76],[105.55,-115.95],[107.53,-115.12],[109.48,-114.26],[111.38,-113.39],[113.24,-112.5],[115.05,-111.61],[116.83,-110.72],[118.56,-109.83],[120.26,-108.95],[121.93,-108.08],[123.56,-107.22],[125.16,-106.38],[126.74,-105.57],[128.3,-104.78],[129.84,-104.01],[131.37,-103.28],[132.89,-102.58],[134.4,-101.91],[135.91,-101.27],[137.42,-100.67],[138.93,-100.1],[140.45,-99.56],[141.98,-99.06],[143.53,-98.59],[145.09,-98.15],[146.67,-97.75],[148.26,-97.36],[149.88,-97.01],[151.52,-96.67],[153.18,-96.36],[154.86,-96.06],[156.55,-95.77],[158.27,-95.49],[160.0,-95.22],[161.75,-94.96],[163.51,-94.69],[165.28,-94.42],[167.05,-94.15],[168.83,-93.86],[170.6,-93.56],[172.36,-93.24],[174.12,-92.91],[175.85,-92.55],[177.57,-92.17],[179.26,-91.76],[180.92,-91.33],[182.55,-90.87],[184.14,-90.37],[185.68,-89.85],[187.18,-89.29],[188.63,-88.71],[190.02,-88.09],[191.36,-87.44],[192.64,-86.76],[193.85,-86.05],[195.01,-85.31],[196.1,-84.54],[197.13,-83.75],[198.09,-82.94],[199.0,-82.1],[199.84,-81.25],[200.63,-80.38],[201.36,-79.5],[202.04,-78.6],[202.67,-77.7],[203.27,-76.79],[203.82,-75.88],[204.34,-74.96],[204.84,-74.05],[205.31,-73.14],[205.78,-72.23],[206.24,-71.34],[206.69,-70.45],[207.16,-69.57],[207.64,-68.71],[208.15,-67.86],[208.68,-67.02],[209.24,-66.2],[209.85,-65.4],[210.51,-64.61],[211.22,-63.83],[211.99,-63.07],[212.82,-62.32],[213.72,-61.59],[214.69,-60.87],[215.74,-60.16],[216.86,-59.46],[218.05,-58.76],[219.32,-58.07],[220.67,-57.39],[222.09,-56.7],[223.59,-56.02],[225.16,-55.33],[226.79,-54.64],[228.48,-53.94],[230.23,-53.23],[232.03,-52.51],[233.87,-51.77],[235.75,-51.02],[237.66,-50.25],[239.59,-49.47],[241.53,-48.66],[243.47,-47.83],[245.4,-46.98],[247.32,-46.11],[249.21,-45.21],[251.06,-44.29],[252.87,-43.35],[254.62,-42.38],[256.3,-41.39],[257.91,-40.37],[259.43,-39.33],[260.86,-38.28],[262.19,-37.2],[263.41,-36.11],[264.52,-35.0]],[[269.7,-35.0],[270.73,-33.84],[271.62,-32.67],[272.38,-31.49],[273.0,-30.31],[273.48,-29.12],[273.81,-27.92],[274.01,-26.73],[274.05,-25.53],[273.95,-24.35],[273.71,-23.16],[273.33,-21.99],[272.81,-20.83],[272.15,-19.69],[271.37,-18.56],[270.46,-17.44],[269.43,-16.35],[268.29,-15.28],[267.05,-14.22],[265.71,-13.19],[264.28,-12.18],[262.78,-11.2],[261.2,-10.24],[259.56,-9.3],[257.87,-8.38],[256.13,-7.49],[254.36,-6.61],[252.56,-5.76],[250.74,-4.93],[248.92,-4.11],[247.09,-3.31],[245.27,-2.52],[243.46,-1.75],[241.67,-0.99],[239.9,-0.23],[238.16,0.51],[236.45,1.26],[234.79,2.0],[233.16,2.73],[231.57,3.47],[230.03,4.22],[228.53,4.96],[227.08,5.71],[225.67,6.47],[224.3,7.24],[222.97,8.01],[221.68,8.8],[220.42,9.59],[219.2,10.39],[218.0,11.2],[216.82,12.02],[215.66,12.85],[214.51,13.68],[213.36,14.52],[212.22,15.36],[211.07,16.21],[209.92,17.05],[208.74,17.89],[207.55,18.73],[206.33,19.55],[205.08,20.37],[203.79,21.18],[202.47,21.97],[201.1,22.74],[199.68,23.48],[198.22,24.21],[196.71,24.9],[195.14,25.57],[193.51,26.2],[191.84,26.79],[190.1,27.35],[188.32,27.86],[186.48,28.34],[184.59,28.77],[182.65,29.15],[180.66,29.49],[178.63,29.78],[176.56,30.03],[174.46,30.22],[172.32,30.38],[170.16,30.48],[167.97,30.54],[165.77,30.56],[163.55,30.54],[161.33,30.48],[159.1,30.38],[156.87,30.25],[154.66,30.09],[152.45,29.91],[150.26,29.7],[148.09,29.48],[145.95,29.23],[143.83,28.98],[141.74,28.73],[139.68,28.47],[137.66,28.22],[135.68,27.97],[133.73,27.74],[131.82,27.53],[129.95,27.33],[128.11,27.16],[126.31,27.02],[124.55,26.91],[122.82,26.84],[121.11,26.8],[119.44,26.81],[117.79,26.86],[116.16,26.95],[114.55,27.09],[112.95,27.28],[111.36,27.52],[109.78,27.8],[108.19,28.13],[106.6,28.51],[105.0,28.93],[103.39,29.4],[101.76,29.91],[100.11,30.46],[98.44,31.04],[96.73,31.65],[95.0,32.29],[93.23,32.96],[91.43,33.65],[89.58,34.35],[87.7,35.07],[85.78,35.79],[83.81,36.51],[81.81,37.23],[79.76,37.94],[77.67,38.64],[75.55,39.32],[73.39,39.97],[71.2,40.6],[68.97,41.2],[66.72,41.75],[64.45,42.27],[62.15,42.74],[59.84,43.17],[57.52,43.54],[55.19,43.86],[52.85,44.12],[50.53,44.33],[48.2,44.47],[45.89,44.56],[43.6,44.58],[41.32,44.54],[39.07,44.45],[36.85,44.29],[34.66,44.07],[32.51,43.79],[30.39,43.46],[28.32,43.08],[26.28,42.64],[24.29,42.15],[22.35,41.62],[20.45,41.05],[18.59,40.43],[16.79,39.78],[15.02,39.1],[13.3,38.39],[11.61,37.65],[9.97,36.89],[8.36,36.12],[6.78,35.33],[5.24,34.53],[3.71,33.73],[2.21,32.91],[0.72,32.1],[-0.75,31.29],[-2.22,30.49],[-3.68,29.69],[-5.14,28.9],[-6.6,28.12],[-8.08,27.34],[-9.56,26.59],[-11.07,25.84],[-12.59,25.11],[-14.13,24.39],[-15.69,23.68],[-17.28,22.98],[-18.9,22.29],[-20.54,21.62],[-22.21,20.95],[-23.91,20.29],[-25.63,19.64],[-27.37,18.98],[-29.13,18.33],[-30.91,17.68],[-32.71,17.02],[-34.51,16.36],[-36.32,15.69],[-38.12,15.01],[-39.92,14.31],[-41.71,13.6],[-43.48,12.87],[-45.22,12.13],[-46.92,11.36],[-48.59,10.57],[-50.2,9.76],[-51.76,8.92],[-53.26,8.06],[-54.68,7.17],[-56.02,6.25],[-57.28,5.3],[-58.45,4.33],[-59.52,3.33],[-60.48,2.31],[-61.34,1.26],[-62.08,0.18],[-62.7,-0.92],[-63.21,-2.04],[-63.59,-3.17],[-63.84,-4.33],[-63.97,-5.5],[-63.97,-6.68],[-63.84,-7.88],[-63.6,-9.08],[-63.23,-10.29],[-62.74,-11.5],[-62.14,-12.71],[-61.43,-13.92],[-60.61,-15.12],[-59.71,-16.32],[-58.71,-17.5],[-57.63,-18.68],[-56.47,-19.84],[-55.25,-20.99],[-53.98,-22.12],[-52.66,-23.24],[-51.3,-24.33],[-49.92,-25.4],[-48.52,-26.46],[-47.11,-27.49],[-45.71,-28.5],[-44.33,-29.48],[-42.96,-30.45],[-41.63,-31.4],[-40.34,-32.33],[-39.1,-33.23],[-37.92,-34.12],[-36.8,-35.0],[-35.75,-35.86],[-34.78,-36.71],[-33.89,-37.55],[-33.08,-38.38],[-32.37,-39.2],[-31.74,-40.02],[-31.21,-40.83],[-30.77,-41.65],[-30.42,-42.47],[-30.17,-43.29],[-30.0,-44.12],[-29.92,-44.95],[-29.92,-45.8],[-30.0,-46.65],[-30.15,-47.52],[-30.37,-48.41],[-30.65,-49.3],[-30.98,-50.21],[-31.36,-51.14],[-31.77,-52.09],[-32.22,-53.05],[-32.68,-54.02],[-33.15,-55.02],[-33.63,-56.02],[-34.1,-57.05],[-34.56,-58.08],[-35.0,-59.12],[-35.4,-60.18],[-35.76,-61.24],[-36.08,-62.31],[-36.34,-63.39],[-36.54,-64.46],[-36.68,-65.54],[-36.74,-66.61],[-36.73,-67.68],[-36.64,-68.74],[-36.46,-69.79],[-36.2,-70.83],[-35.85,-71.86],[-35.41,-72.87],[-34.88,-73.87],[-34.26,-74.84],[-33.55,-75.8],[-32.75,-76.73],[-31.87,-77.64],[-30.92,-78.53],[-29.88,-79.39],[-28.77,-80.23],[-27.59,-81.05],[-26.34,-81.84],[-25.04,-82.6],[-23.69,-83.35],[-22.29,-84.07],[-20.84,-84.77],[-19.37,-85.45],[-17.86,-86.12],[-16.33,-86.77],[-14.78,-87.4],[-13.22,-88.03],[-11.65,-88.65],[-10.08,-89.26],[-8.51,-89.87],[-6.95,-90.48],[-5.4,-91.09],[-3.87,-91.71],[-2.35,-92.34],[-0.85,-92.97],[0.63,-93.62],[2.08,-94.29],[3.52,-94.97],[4.93,-95.67],[6.32,-96.4],[7.69,-97.14],[9.05,-97.91],[10.38,-98.71],[11.7,-99.52],[13.01,-100.37],[14.31,-101.23],[15.61,-102.13],[16.91,-103.04],[18.21,-103.98],[19.52,-104.93],[20.84,-105.91],[22.18,-106.89],[23.54,-107.9],[24.92,-108.91],[26.34,-109.92],[27.79,-110.94],[29.27,-111.96],[30.8,-112.97],[32.37,-113.97],[33.99,-114.95],[35.65,-115.92],[37.37,-116.86],[39.14,-117.78],[40.96,-118.66],[42.84,-119.5],[44.77,-120.3],[46.75,-121.06],[48.78,-121.76],[50.87,-122.42],[53.0,-123.01],[55.17,-123.54],[57.39,-124.01],[59.65,-124.41],[61.94,-124.74],[64.26,-125.0],[66.6,-125.19],[68.97,-125.3],[71.36,-125.34],[73.75,-125.31],[76.15,-125.2],[78.56,-125.02],[80.96,-124.77],[83.35,-124.45],[85.72,-124.06],[88.08,-123.6],[90.41,-123.09],[92.72,-122.51],[95.0,-121.88],[97.24,-121.2],[99.45,-120.48],[101.62,-119.71],[103.74,-118.9],[105.82,-118.06],[107.86,-117.19],[109.85,-116.3],[111.8,-115.39],[113.7,-114.47],[115.56,-113.54],[117.37,-112.61],[119.14,-111.68],[120.88,-110.76],[122.58,-109.84],[124.24,-108.95],[125.88,-108.07],[127.48,-107.21],[129.07,-106.38],[130.63,-105.58],[132.18,-104.8],[133.72,-104.06],[135.25,-103.36],[136.78,-102.69],[138.31,-102.05],[139.84,-101.45],[141.38,-100.89],[142.94,-100.36],[144.5,-99.87],[146.08,-99.41],[147.68,-98.98],[149.3,-98.58],[150.95,-98.21],[152.61,-97.86],[154.3,-97.54],[156.01,-97.23],[157.74,-96.94],[159.5,-96.67],[161.27,-96.4],[163.06,-96.13],[164.86,-95.87],[166.68,-95.61],[168.51,-95.34],[170.34,-95.06],[172.17,-94.77],[173.99,-94.47],[175.81,-94.15],[177.62,-93.81],[179.41,-93.44],[181.17,-93.05],[182.91,-92.63],[184.61,-92.18],[186.28,-91.7],[187.91,-91.19],[189.49,-90.65],[191.02,-90.08],[192.5,-89.47],[193.92,-88.83],[195.29,-88.16],[196.59,-87.46],[197.83,-86.73],[199.01,-85.97],[200.12,-85.18],[201.16,-84.37],[202.15,-83.53],[203.07,-82.67],[203.93,-81.8],[204.74,-80.91],[205.49,-80.01],[206.19,-79.09],[206.85,-78.17],[207.46,-77.24],[208.04,-76.31],[208.59,-75.38],[209.12,-74.45],[209.63,-73.53],[210.13,-72.61],[210.63,-71.7],[211.13,-70.8],[211.65,-69.91],[212.18,-69.03],[212.74,-68.17],[213.33,-67.32],[213.97,-66.49],[214.64,-65.67],[215.37,-64.86],[216.16,-64.07],[217.01,-63.29],[217.92,-62.53],[218.91,-61.78],[219.96,-61.04],[221.09,-60.31],[222.3,-59.58],[223.59,-58.86],[224.95,-58.15],[226.39,-57.44],[227.9,-56.72],[229.49,-56.01],[231.14,-55.29],[232.85,-54.56],[234.63,-53.82],[236.45,-53.07],[238.33,-52.31],[240.24,-51.53],[242.18,-50.74],[244.14,-49.92],[246.12,-49.09],[248.1,-48.23],[250.07,-47.35],[252.03,-46.45],[253.96,-45.53],[255.86,-44.58],[257.71,-43.6],[259.5,-42.6],[261.23,-41.58],[262.88,-40.54],[264.45,-39.47],[265.92,-38.38],[267.3,-37.27],[268.56,-36.14],[269.7,-35.0]],[[274.87,-35.0],[275.93,-33.81],[276.85,-32.6],[277.64,-31.39],[278.29,-30.17],[278.79,-28.94],[279.14,-27.71],[279.35,-26.48],[279.4,-25.25],[279.3,-24.03],[279.06,-22.81],[278.67,-21.6],[278.13,-20.41],[277.46,-19.23],[276.65,-18.06],[275.71,-16.92],[274.64,-15.79],[273.46,-14.69],[272.17,-13.6],[270.78,-12.54],[269.29,-11.51],[267.72,-10.5],[266.07,-9.51],[264.35,-8.55],[262.58,-7.61],[260.76,-6.7],[258.9,-5.8],[257.01,-4.94],[255.09,-4.09],[253.17,-3.26],[251.24,-2.45],[249.32,-1.65],[247.4,-0.87],[245.51,-0.1],[243.63,0.66],[241.79,1.41],[239.98,2.16],[238.21,2.9],[236.48,3.64],[234.8,4.38],[233.16,5.12],[231.57,5.87],[230.02,6.62],[228.52,7.38],[227.07,8.14],[225.66,8.92],[224.3,9.7],[222.97,10.49],[221.67,11.3],[220.41,12.11],[219.17,12.93],[217.96,13.76],[216.76,14.6],[215.57,15.44],[214.39,16.29],[213.21,17.15],[212.02,18.0],[210.82,18.85],[209.6,19.7],[208.36,20.55],[207.09,21.38],[205.78,22.21],[204.45,23.02],[203.07,23.81],[201.64,24.58],[200.17,25.33],[198.65,26.05],[197.07,26.74],[195.45,27.4],[193.76,28.02],[192.02,28.61],[190.23,29.15],[188.39,29.66],[186.49,30.12],[184.54,30.53],[182.54,30.9],[180.5,31.23],[178.41,31.5],[176.29,31.73],[174.14,31.91],[171.95,32.05],[169.74,32.14],[167.51,32.18],[165.27,32.19],[163.02,32.15],[160.76,32.08],[158.5,31.97],[156.24,31.83],[154.0,31.66],[151.77,31.47],[149.56,31.26],[147.37,31.03],[145.21,30.79],[143.07,30.55],[140.97,30.3],[138.9,30.06],[136.87,29.82],[134.87,29.59],[132.91,29.38],[130.99,29.19],[129.1,29.02],[127.25,28.88],[125.44,28.77],[123.65,28.7],[121.9,28.66],[120.18,28.67],[118.48,28.72],[116.8,28.82],[115.14,28.96],[113.49,29.15],[111.85,29.39],[110.22,29.68],[108.59,30.02],[106.95,30.4],[105.3,30.84],[103.64,31.31],[101.96,31.83],[100.26,32.39],[98.54,32.99],[96.79,33.62],[95.0,34.28],[93.18,34.97],[91.32,35.68],[89.42,36.41],[87.48,37.15],[85.5,37.89],[83.48,38.64],[81.41,39.39],[79.3,40.13],[77.15,40.86],[74.96,41.57],[72.73,42.25],[70.47,42.91],[68.17,43.54],[65.85,44.12],[63.5,44.67],[61.12,45.17],[58.73,45.62],[56.33,46.03],[53.92,46.37],[51.5,46.66],[49.09,46.89],[46.68,47.05],[44.29,47.16],[41.91,47.2],[39.55,47.17],[37.21,47.09],[34.91,46.93],[32.64,46.72],[30.4,46.45],[28.21,46.11],[26.05,45.72],[23.95,45.28],[21.88,44.78],[19.87,44.23],[17.9,43.64],[15.99,43.01],[14.12,42.33],[12.29,41.62],[10.52,40.88],[8.79,40.11],[7.1,39.32],[5.45,38.51],[3.84,37.68],[2.25,36.84],[0.7,35.99],[-0.82,35.14],[-2.33,34.28],[-3.82,33.42],[-5.3,32.57],[-6.77,31.72],[-8.24,30.87],[-9.71,30.04],[-11.18,29.22],[-12.66,28.41],[-14.16,27.61],[-15.68,26.83],[-17.21,26.06],[-18.76,25.3],[-20.34,24.56],[-21.95,23.83],[-23.58,23.11],[-25.24,22.4],[-26.92,21.69],[-28.63,21.0],[-30.36,20.3],[-32.12,19.61],[-33.89,18.92],[-35.68,18.23],[-37.48,17.54],[-39.29,16.83],[-41.1,16.12],[-42.9,15.4],[-44.69,14.66],[-46.47,13.91],[-48.22,13.14],[-49.94,12.35],[-51.62,11.54],[-53.25,10.7],[-54.83,9.84],[-56.35,8.96],[-57.8,8.05],[-59.17,7.11],[-60.46,6.14],[-61.66,5.15],[-62.76,4.13],[-63.75,3.09],[-64.64,2.02],[-65.41,0.93],[-66.07,-0.19],[-66.6,-1.33],[-67.01,-2.49],[-67.29,-3.66],[-67.45,-4.85],[-67.47,-6.06],[-67.37,-7.27],[-67.14,-8.5],[-66.79,-9.73],[-66.32,-10.96],[-65.73,-12.2],[-65.03,-13.43],[-64.22,-14.66],[-63.32,-15.88],[-62.32,-17.09],[-61.23,-18.3],[-60.07,-19.48],[-58.84,-20.66],[-57.55,-21.81],[-56.21,-22.95],[-54.83,-24.07],[-53.42,-25.17],[-52.0,-26.25],[-50.56,-27.3],[-49.13,-28.34],[-47.71,-29.35],[-46.31,-30.34],[-44.94,-31.31],[-43.62,-32.26],[-42.34,-33.19],[-41.12,-34.1],[-39.96,-35.0],[-38.88,-35.88],[-37.87,-36.75],[-36.95,-37.61],[-36.12,-38.46],[-35.37,-39.3],[-34.72,-40.14],[-34.17,-40.97],[-33.71,-41.8],[-33.35,-42.64],[-33.08,-43.48],[-32.91,-44.33],[-32.82,-45.18],[-32.83,-46.05],[-32.91,-46.93],[-33.08,-47.82],[-33.31,-48.72],[-33.61,-49.64],[-33.96,-50.57],[-34.37,-51.53],[-34.82,-52.5],[-35.3,-53.49],[-35.8,-54.49],[-36.32,-55.51],[-36.85,-56.55],[-37.37,-57.6],[-37.88,-58.67],[-38.37,-59.75],[-38.83,-60.84],[-39.25,-61.94],[-39.63,-63.05],[-39.95,-64.17],[-40.21,-65.28],[-40.41,-66.4],[-40.53,-67.52],[-40.57,-68.63],[-40.54,-69.74],[-40.41,-70.84],[-40.2,-71.93],[-39.89,-73.0],[-39.5,-74.06],[-39.0,-75.1],[-38.42,-76.13],[-37.74,-77.13],[-36.97,-78.11],[-36.11,-79.07],[-35.17,-80.0],[-34.14,-80.91],[-33.03,-81.79],[-31.85,-82.65],[-30.6,-83.48],[-29.28,-84.29],[-27.91,-85.07],[-26.48,-85.82],[-25.01,-86.56],[-23.5,-87.27],[-21.95,-87.97],[-20.37,-88.65],[-18.78,-89.31],[-17.16,-89.96],[-15.53,-90.6],[-13.9,-91.23],[-12.27,-91.86],[-10.64,-92.49],[-9.02,-93.11],[-7.41,-93.74],[-5.82,-94.38],[-4.24,-95.02],[-2.69,-95.68],[-1.15,-96.35],[0.37,-97.04],[1.86,-97.74],[3.33,-98.47],[4.78,-99.21],[6.21,-99.98],[7.63,-100.78],[9.03,-101.59],[10.42,-102.44],[11.79,-103.3],[13.17,-104.19],[14.54,-105.11],[15.91,-106.04],[17.29,-107.0],[18.68,-107.97],[20.08,-108.96],[21.51,-109.96],[22.96,-110.98],[24.44,-112.0],[25.95,-113.02],[27.49,-114.04],[29.08,-115.06],[30.71,-116.06],[32.38,-117.06],[34.1,-118.03],[35.88,-118.99],[37.7,-119.91],[39.58,-120.8],[41.51,-121.66],[43.49,-122.47],[45.53,-123.24],[47.62,-123.96],[49.75,-124.62],[51.94,-125.22],[54.17,-125.77],[56.44,-126.25],[58.76,-126.66],[61.1,-127.0],[63.48,-127.26],[65.89,-127.46],[68.32,-127.58],[70.76,-127.62],[73.21,-127.59],[75.68,-127.48],[78.14,-127.3],[80.6,-127.05],[83.05,-126.72],[85.49,-126.32],[87.9,-125.86],[90.3,-125.33],[92.66,-124.74],[95.0,-124.09],[97.3,-123.39],[99.56,-122.64],[101.78,-121.84],[103.96,-121.01],[106.09,-120.14],[108.18,-119.24],[110.22,-118.32],[112.21,-117.37],[114.16,-116.42],[116.06,-115.45],[117.91,-114.48],[119.72,-113.51],[121.49,-112.55],[123.22,-111.6],[124.92,-110.66],[126.58,-109.74],[128.22,-108.84],[129.83,-107.97],[131.42,-107.13],[132.99,-106.32],[134.55,-105.54],[136.1,-104.8],[137.65,-104.09],[139.2,-103.42],[140.75,-102.79],[142.31,-102.2],[143.88,-101.65],[145.46,-101.13],[147.07,-100.65],[148.69,-100.2],[150.33,-99.79],[152.0,-99.4],[153.69,-99.04],[155.41,-98.71],[157.15,-98.4],[158.92,-98.1],[160.71,-97.82],[162.52,-97.56],[164.35,-97.3],[166.2,-97.04],[168.07,-96.78],[169.95,-96.52],[171.83,-96.26],[173.72,-95.98],[175.61,-95.69],[177.5,-95.38],[179.37,-95.05],[181.23,-94.7],[183.07,-94.33],[184.89,-93.93],[186.67,-93.5],[188.43,-93.04],[190.14,-92.54],[191.8,-92.01],[193.42,-91.45],[194.99,-90.86],[196.5,-90.23],[197.95,-89.57],[199.34,-88.88],[200.67,-88.16],[201.94,-87.4],[203.14,-86.62],[204.27,-85.81],[205.34,-84.97],[206.34,-84.12],[207.28,-83.24],[208.16,-82.34],[208.99,-81.43],[209.76,-80.51],[210.49,-79.58],[211.16,-78.63],[211.81,-77.69],[212.41,-76.74],[212.99,-75.79],[213.55,-74.85],[214.1,-73.91],[214.64,-72.97],[215.19,-72.05],[215.74,-71.13],[216.3,-70.23],[216.89,-69.34],[217.51,-68.46],[218.16,-67.6],[218.86,-66.75],[219.61,-65.91],[220.41,-65.09],[221.28,-64.28],[222.2,-63.49],[223.2,-62.71],[224.27,-61.93],[225.41,-61.17],[226.63,-60.42],[227.93,-59.67],[229.3,-58.92],[230.75,-58.18],[232.28,-57.44],[233.88,-56.69],[235.55,-55.94],[237.28,-55.19],[239.07,-54.42],[240.92,-53.64],[242.82,-52.85],[244.75,-52.05],[246.72,-51.22],[248.72,-50.38],[250.72,-49.52],[252.74,-48.63],[254.75,-47.73],[256.74,-46.8],[258.72,-45.84],[260.65,-44.86],[262.54,-43.86],[264.38,-42.83],[266.15,-41.78],[267.85,-40.7],[269.46,-39.6],[270.97,-38.48],[272.39,-37.34],[273.69,-36.18],[274.87,-35.0]],[[280.01,-35.0],[281.1,-33.77],[282.05,-32.54],[282.87,-31.29],[283.54,-30.03],[284.06,-28.77],[284.43,-27.5],[284.65,-26.23],[284.71,-24.97],[284.62,-23.71],[284.37,-22.46],[283.97,-21.22],[283.43,-19.99],[282.73,-18.77],[281.9,-17.58],[280.92,-16.4],[279.82,-15.24],[278.6,-14.1],[277.26,-12.99],[275.81,-11.9],[274.26,-10.84],[272.62,-9.8],[270.9,-8.79],[269.11,-7.8],[267.26,-6.85],[265.35,-5.91],[263.4,-5.0],[261.42,-4.12],[259.41,-3.25],[257.39,-2.41],[255.36,-1.59],[253.33,-0.78],[251.31,0.01],[249.31,0.79],[247.33,1.55],[245.39,2.31],[243.47,3.05],[241.6,3.8],[239.77,4.54],[237.98,5.28],[236.24,6.02],[234.56,6.77],[232.92,7.51],[231.33,8.27],[229.8,9.03],[228.31,9.81],[226.86,10.59],[225.46,11.38],[224.1,12.18],[222.77,13.0],[221.48,13.82],[220.21,14.65],[218.96,15.49],[217.73,16.34],[216.5,17.2],[215.28,18.06],[214.06,18.93],[212.83,19.79],[211.59,20.65],[210.33,21.51],[209.04,22.37],[207.72,23.21],[206.37,24.04],[204.99,24.85],[203.55,25.65],[202.08,26.42],[200.55,27.17],[198.97,27.88],[197.34,28.57],[195.65,29.23],[193.91,29.84],[192.12,30.42],[190.27,30.96],[188.36,31.45],[186.41,31.9],[184.4,32.3],[182.35,32.66],[180.25,32.97],[178.12,33.23],[175.95,33.44],[173.75,33.61],[171.52,33.73],[169.26,33.8],[166.99,33.83],[164.71,33.82],[162.42,33.78],[160.13,33.69],[157.85,33.58],[155.57,33.43],[153.3,33.26],[151.05,33.06],[148.81,32.85],[146.61,32.63],[144.43,32.39],[142.28,32.16],[140.16,31.92],[138.08,31.69],[136.03,31.47],[134.02,31.26],[132.05,31.08],[130.11,30.91],[128.21,30.78],[126.34,30.67],[124.51,30.6],[122.71,30.57],[120.93,30.58],[119.18,30.63],[117.45,30.73],[115.74,30.87],[114.04,31.06],[112.35,31.31],[110.67,31.6],[108.99,31.94],[107.3,32.34],[105.6,32.78],[103.89,33.26],[102.17,33.79],[100.42,34.36],[98.64,34.97],[96.84,35.62],[95.0,36.3],[93.13,37.01],[91.21,37.74],[89.26,38.48],[87.26,39.25],[85.23,40.02],[83.14,40.79],[81.01,41.57],[78.84,42.34],[76.63,43.09],[74.37,43.83],[72.07,44.55],[69.74,45.24],[67.37,45.89],[64.97,46.51],[62.54,47.09],[60.09,47.62],[57.62,48.1],[55.14,48.52],[52.64,48.9],[50.15,49.21],[47.65,49.46],[45.16,49.64],[42.68,49.77],[40.21,49.82],[37.77,49.81],[35.35,49.74],[32.96,49.59],[30.61,49.38],[28.29,49.11],[26.01,48.78],[23.78,48.38],[21.6,47.93],[19.47,47.42],[17.38,46.86],[15.35,46.25],[13.37,45.59],[11.44,44.89],[9.56,44.16],[7.73,43.39],[5.95,42.59],[4.22,41.76],[2.53,40.91],[0.88,40.04],[-0.74,39.16],[-2.32,38.26],[-3.87,37.36],[-5.39,36.46],[-6.9,35.55],[-8.39,34.64],[-9.86,33.74],[-11.34,32.85],[-12.8,31.97],[-14.28,31.09],[-15.76,30.23],[-17.25,29.38],[-18.75,28.55],[-20.27,27.73],[-21.82,26.92],[-23.38,26.13],[-24.97,25.35],[-26.59,24.58],[-28.23,23.83],[-29.9,23.08],[-31.6,22.34],[-33.32,21.61],[-35.06,20.88],[-36.82,20.15],[-38.6,19.42],[-40.4,18.69],[-42.2,17.96],[-44.01,17.22],[-45.81,16.46],[-47.61,15.7],[-49.39,14.92],[-51.15,14.12],[-52.88,13.31],[-54.57,12.47],[-56.22,11.62],[-57.82,10.74],[-59.36,9.83],[-60.84,8.9],[-62.23,7.94],[-63.55,6.96],[-64.77,5.95],[-65.9,4.92],[-66.93,3.85],[-67.85,2.77],[-68.66,1.65],[-69.35,0.52],[-69.91,-0.64],[-70.35,-1.82],[-70.67,-3.01],[-70.85,-4.22],[-70.91,-5.45],[-70.83,-6.68],[-70.63,-7.93],[-70.3,-9.18],[-69.85,-10.44],[-69.27,-11.69],[-68.59,-12.95],[-67.79,-14.2],[-66.89,-15.45],[-65.89,-16.69],[-64.81,-17.91],[-63.64,-19.13],[-62.4,-20.33],[-61.1,-21.51],[-59.75,-22.67],[-58.36,-23.81],[-56.93,-24.94],[-55.48,-26.04],[-54.02,-27.12],[-52.56,-28.18],[-51.11,-29.22],[-49.68,-30.23],[-48.28,-31.22],[-46.92,-32.2],[-45.61,-33.15],[-44.35,-34.08],[-43.16,-35.0],[-42.04,-35.9],[-41.0,-36.79],[-40.05,-37.67],[-39.19,-38.54],[-38.41,-39.4],[-37.74,-40.26],[-37.16,-41.11],[-36.69,-41.96],[-36.31,-42.82],[-36.03,-43.68],[-35.85,-44.54],[-35.76,-45.42],[-35.77,-46.3],[-35.86,-47.2],[-36.03,-48.11],[-36.28,-49.04],[-36.6,-49.98],[-36.98,-50.94],[-37.41,-51.92],[-37.89,-52.91],[-38.41,-53.93],[-38.95,-54.96],[-39.52,-56.01],[-40.09,-57.08],[-40.66,-58.17],[-41.23,-59.27],[-41.77,-60.38],[-42.29,-61.51],[-42.77,-62.65],[-43.21,-63.8],[-43.59,-64.95],[-43.91,-66.11],[-44.17,-67.27],[-44.35,-68.43],[-44.45,-69.59],[-44.47,-70.75],[-44.4,-71.89],[-44.24,-73.03],[-43.98,-74.15],[-43.63,-75.26],[-43.18,-76.35],[-42.63,-77.42],[-41.98,-78.48],[-41.24,-79.5],[-40.4,-80.51],[-39.47,-81.49],[-38.45,-82.44],[-37.35,-83.37],[-36.17,-84.27],[-34.91,-85.14],[-33.58,-85.99],[-32.19,-86.81],[-30.74,-87.6],[-29.24,-88.37],[-27.69,-89.12],[-26.1,-89.85],[-24.48,-90.56],[-22.83,-91.25],[-21.16,-91.92],[-19.47,-92.58],[-17.78,-93.24],[-16.08,-93.88],[-14.38,-94.52],[-12.69,-95.16],[-11.0,-95.8],[-9.33,-96.45],[-7.68,-97.1],[-6.04,-97.76],[-4.42,-98.44],[-2.82,-99.13],[-1.24,-99.83],[0.31,-100.56],[1.85,-101.3],[3.36,-102.07],[4.86,-102.86],[6.34,-103.68],[7.81,-104.51],[9.26,-105.38],[10.72,-106.26],[12.16,-107.17],[13.61,-108.11],[15.06,-109.06],[16.52,-110.03],[18.0,-111.02],[19.49,-112.02],[21.01,-113.03],[22.55,-114.06],[24.12,-115.08],[25.73,-116.1],[27.38,-117.13],[29.06,-118.14],[30.79,-119.14],[32.57,-120.12],[34.4,-121.08],[36.28,-122.01],[38.21,-122.92],[40.2,-123.78],[42.24,-124.6],[44.33,-125.38],[46.47,-126.11],[48.66,-126.78],[50.9,-127.4],[53.19,-127.95],[55.52,-128.44],[57.88,-128.86],[60.29,-129.21],[62.72,-129.49],[65.19,-129.69],[67.67,-129.82],[70.17,-129.86],[72.69,-129.83],[75.21,-129.73],[77.73,-129.55],[80.25,-129.29],[82.76,-128.95],[85.25,-128.55],[87.73,-128.07],[90.18,-127.53],[92.61,-126.93],[95.0,-126.26],[97.36,-125.54],[99.67,-124.77],[101.95,-123.95],[104.18,-123.09],[106.36,-122.2],[108.5,-121.27],[110.58,-120.31],[112.62,-119.33],[114.61,-118.34],[116.55,-117.34],[118.44,-116.33],[120.29,-115.33],[122.1,-114.32],[123.86,-113.33],[125.59,-112.35],[127.28,-111.39],[128.94,-110.46],[130.58,-109.55],[132.19,-108.67],[133.79,-107.82],[135.37,-107.0],[136.94,-106.22],[138.51,-105.48],[140.08,-104.78],[141.65,-104.12],[143.22,-103.5],[144.81,-102.92],[146.42,-102.38],[148.04,-101.88],[149.69,-101.41],[151.35,-100.98],[153.04,-100.58],[154.76,-100.21],[156.51,-99.87],[158.28,-99.55],[160.08,-99.25],[161.91,-98.97],[163.76,-98.7],[165.64,-98.45],[167.53,-98.2],[169.45,-97.95],[171.38,-97.7],[173.32,-97.44],[175.27,-97.18],[177.23,-96.9],[179.18,-96.61],[181.12,-96.3],[183.06,-95.97],[184.97,-95.61],[186.87,-95.23],[188.74,-94.81],[190.57,-94.37],[192.37,-93.89],[194.12,-93.38],[195.83,-92.84],[197.49,-92.26],[199.09,-91.64],[200.64,-91.0],[202.12,-90.31],[203.54,-89.6],[204.9,-88.85],[206.19,-88.08],[207.41,-87.27],[208.56,-86.44],[209.65,-85.58],[210.68,-84.7],[211.64,-83.8],[212.54,-82.88],[213.39,-81.95],[214.18,-81.0],[214.93,-80.05],[215.64,-79.09],[216.3,-78.12],[216.94,-77.16],[217.56,-76.19],[218.15,-75.23],[218.74,-74.27],[219.32,-73.32],[219.91,-72.38],[220.51,-71.45],[221.13,-70.53],[221.77,-69.62],[222.45,-68.73],[223.17,-67.85],[223.93,-66.98],[224.75,-66.13],[225.63,-65.29],[226.57,-64.47],[227.58,-63.65],[228.66,-62.85],[229.81,-62.05],[231.04,-61.27],[232.34,-60.49],[233.73,-59.71],[235.19,-58.94],[236.72,-58.16],[238.33,-57.39],[240.01,-56.61],[241.76,-55.82],[243.57,-55.03],[245.43,-54.22],[247.35,-53.4],[249.31,-52.56],[251.3,-51.71],[253.32,-50.84],[255.35,-49.95],[257.4,-49.04],[259.44,-48.1],[261.47,-47.14],[263.47,-46.16],[265.45,-45.15],[267.38,-44.11],[269.25,-43.05],[271.06,-41.97],[272.8,-40.86],[274.45,-39.73],[276.0,-38.58],[277.45,-37.4],[278.79,-36.21],[280.01,-35.0]],[[285.11,-35.0],[286.23,-33.74],[287.21,-32.47],[288.06,-31.18],[288.75,-29.89],[289.29,-28.59],[289.68,-27.29],[289.91,-25.99],[289.98,-24.69],[289.89,-23.4],[289.64,-22.11],[289.23,-20.83],[288.67,-19.57],[287.96,-18.32],[287.1,-17.09],[286.1,-15.88],[284.96,-14.69],[283.7,-13.52],[282.31,-12.38],[280.81,-11.26],[279.2,-10.17],[277.49,-9.11],[275.7,-8.07],[273.84,-7.07],[271.9,-6.09],[269.91,-5.13],[267.87,-4.21],[265.8,-3.3],[263.69,-2.43],[261.57,-1.57],[259.44,-0.74],[257.31,0.08],[255.19,0.88],[253.08,1.66],[251.0,2.43],[248.94,3.19],[246.92,3.94],[244.95,4.68],[243.01,5.43],[241.12,6.16],[239.29,6.9],[237.5,7.65],[235.77,8.39],[234.1,9.15],[232.47,9.91],[230.9,10.68],[229.38,11.46],[227.9,12.25],[226.47,13.05],[225.08,13.86],[223.73,14.69],[222.4,15.52],[221.1,16.37],[219.83,17.22],[218.56,18.09],[217.31,18.95],[216.05,19.83],[214.8,20.7],[213.53,21.58],[212.25,22.45],[210.94,23.32],[209.61,24.18],[208.25,25.03],[206.86,25.87],[205.42,26.69],[203.94,27.49],[202.41,28.26],[200.83,29.01],[199.2,29.73],[197.51,30.41],[195.77,31.06],[193.97,31.67],[192.12,32.24],[190.21,32.77],[188.25,33.25],[186.24,33.69],[184.19,34.08],[182.08,34.43],[179.94,34.72],[177.75,34.97],[175.54,35.17],[173.29,35.32],[171.02,35.43],[168.73,35.49],[166.42,35.51],[164.1,35.49],[161.78,35.43],[159.46,35.34],[157.15,35.21],[154.84,35.06],[152.55,34.89],[150.28,34.7],[148.03,34.49],[145.8,34.27],[143.61,34.05],[141.44,33.82],[139.31,33.6],[137.21,33.39],[135.15,33.19],[133.13,33.01],[131.14,32.85],[129.19,32.72],[127.27,32.61],[125.38,32.54],[123.53,32.51],[121.7,32.52],[119.9,32.58],[118.12,32.68],[116.36,32.82],[114.61,33.02],[112.87,33.27],[111.13,33.56],[109.4,33.91],[107.66,34.31],[105.91,34.75],[104.15,35.25],[102.38,35.79],[100.57,36.37],[98.75,36.99],[96.89,37.66],[95.0,38.35],[93.07,39.07],[91.11,39.82],[89.1,40.59],[87.04,41.37],[84.94,42.17],[82.8,42.97],[80.61,43.77],[78.38,44.56],[76.09,45.35],[73.77,46.11],[71.4,46.86],[69.0,47.58],[66.56,48.26],[64.08,48.91],[61.58,49.51],[59.05,50.07],[56.5,50.58],[53.94,51.03],[51.36,51.43],[48.78,51.77],[46.2,52.04],[43.62,52.25],[41.06,52.39],[38.51,52.46],[35.98,52.46],[33.48,52.39],[31.01,52.26],[28.57,52.05],[26.17,51.78],[23.82,51.45],[21.51,51.05],[19.25,50.59],[17.04,50.07],[14.88,49.49],[12.78,48.86],[10.74,48.19],[8.75,47.46],[6.81,46.7],[4.93,45.9],[3.11,45.07],[1.33,44.2],[-0.4,43.31],[-2.09,42.4],[-3.73,41.48],[-5.34,40.54],[-6.91,39.59],[-8.45,38.64],[-9.97,37.68],[-11.47,36.72],[-12.96,35.77],[-14.43,34.83],[-15.9,33.89],[-17.37,32.96],[-18.84,32.05],[-20.32,31.15],[-21.81,30.26],[-23.32,29.39],[-24.85,28.53],[-26.4,27.69],[-27.97,26.86],[-29.57,26.04],[-31.19,25.24],[-32.84,24.45],[-34.52,23.66],[-36.23,22.89],[-37.95,22.12],[-39.7,21.36],[-41.47,20.59],[-43.26,19.83],[-45.05,19.06],[-46.85,18.28],[-48.65,17.5],[-50.45,16.71],[-52.23,15.9],[-54.0,15.08],[-55.74,14.24],[-57.45,13.38],[-59.11,12.51],[-60.73,11.6],[-62.29,10.68],[-63.78,9.73],[-65.21,8.76],[-66.55,7.76],[-67.8,6.73],[-68.97,5.67],[-70.03,4.6],[-70.98,3.49],[-71.82,2.36],[-72.54,1.21],[-73.14,0.03],[-73.62,-1.16],[-73.96,-2.37],[-74.18,-3.6],[-74.27,-4.85],[-74.22,-6.1],[-74.05,-7.37],[-73.75,-8.64],[-73.32,-9.92],[-72.77,-11.2],[-72.1,-12.48],[-71.31,-13.75],[-70.42,-15.02],[-69.44,-16.28],[-68.35,-17.53],[-67.19,-18.77],[-65.95,-19.99],[-64.64,-21.2],[-63.28,-22.39],[-61.87,-23.56],[-60.43,-24.71],[-58.96,-25.83],[-57.48,-26.94],[-56.0,-28.02],[-54.52,-29.08],[-53.06,-30.12],[-51.63,-31.13],[-50.24,-32.13],[-48.9,-33.1],[-47.61,-34.06],[-46.39,-35.0],[-45.24,-35.92],[-44.17,-36.83],[-43.19,-37.73],[-42.3,-38.62],[-41.5,-39.5],[-40.8,-40.38],[-40.2,-41.25],[-39.7,-42.12],[-39.31,-43.0],[-39.02,-43.88],[-38.83,-44.76],[-38.74,-45.66],[-38.75,-46.56],[-38.85,-47.48],[-39.03,-48.41],[-39.29,-49.36],[-39.63,-50.32],[-40.03,-51.31],[-40.49,-52.31],[-41.01,-53.33],[-41.56,-54.37],[-42.14,-55.44],[-42.75,-56.52],[-43.37,-57.62],[-44.0,-58.73],[-44.61,-59.87],[-45.21,-61.02],[-45.79,-62.19],[-46.33,-63.36],[-46.82,-64.55],[-47.27,-65.75],[-47.65,-66.95],[-47.97,-68.15],[-48.21,-69.36],[-48.37,-70.57],[-48.44,-71.77],[-48.43,-72.96],[-48.32,-74.14],[-48.11,-75.32],[-47.8,-76.47],[-47.39,-77.61],[-46.88,-78.73],[-46.26,-79.84],[-45.55,-80.91],[-44.73,-81.97],[-43.82,-82.99],[-42.81,-83.99],[-41.72,-84.97],[-40.53,-85.91],[-39.27,-86.83],[-37.93,-87.71],[-36.52,-88.57],[-35.05,-89.41],[-33.51,-90.21],[-31.93,-90.99],[-30.3,-91.75],[-28.63,-92.49],[-26.93,-93.21],[-25.21,-93.9],[-23.46,-94.59],[-21.7,-95.26],[-19.94,-95.93],[-18.17,-96.58],[-16.4,-97.23],[-14.64,-97.89],[-12.88,-98.54],[-11.15,-99.2],[-9.42,-99.87],[-7.72,-100.55],[-6.04,-101.24],[-4.37,-101.94],[-2.73,-102.67],[-1.11,-103.41],[0.49,-104.17],[2.07,-104.96],[3.64,-105.77],[5.19,-106.6],[6.73,-107.46],[8.26,-108.34],[9.79,-109.24],[11.31,-110.17],[12.84,-111.12],[14.37,-112.09],[15.92,-113.07],[17.48,-114.07],[19.07,-115.08],[20.68,-116.1],[22.31,-117.12],[23.98,-118.15],[25.69,-119.17],[27.44,-120.19],[29.23,-121.19],[31.06,-122.18],[32.95,-123.14],[34.89,-124.08],[36.87,-124.99],[38.91,-125.87],[41.0,-126.7],[43.15,-127.49],[45.34,-128.22],[47.59,-128.91],[49.88,-129.53],[52.22,-130.1],[54.61,-130.6],[57.03,-131.03],[59.49,-131.38],[61.98,-131.67],[64.5,-131.88],[67.04,-132.01],[69.6,-132.06],[72.17,-132.04],[74.75,-131.93],[77.33,-131.75],[79.9,-131.49],[82.47,-131.15],[85.03,-130.74],[87.56,-130.25],[90.07,-129.7],[92.55,-129.09],[95.0,-128.41],[97.41,-127.67],[99.78,-126.88],[102.11,-126.04],[104.39,-125.15],[106.63,-124.23],[108.81,-123.27],[110.94,-122.28],[113.03,-121.28],[115.06,-120.25],[117.04,-119.21],[118.97,-118.17],[120.86,-117.12],[122.7,-116.08],[124.5,-115.05],[126.25,-114.04],[127.97,-113.04],[129.66,-112.06],[131.33,-111.11],[132.96,-110.19],[134.58,-109.31],[136.18,-108.46],[137.78,-107.64],[139.36,-106.87],[140.95,-106.14],[142.54,-105.45],[144.13,-104.8],[145.74,-104.19],[147.37,-103.62],[149.01,-103.1],[150.68,-102.61],[152.36,-102.16],[154.08,-101.75],[155.83,-101.37],[157.6,-101.02],[159.4,-100.69],[161.24,-100.39],[163.1,-100.11],[164.99,-99.85],[166.91,-99.59],[168.86,-99.35],[170.82,-99.11],[172.81,-98.87],[174.81,-98.62],[176.82,-98.37],[178.83,-98.11],[180.85,-97.84],[182.87,-97.54],[184.88,-97.23],[186.87,-96.89],[188.85,-96.52],[190.8,-96.13],[192.72,-95.7],[194.61,-95.24],[196.45,-94.75],[198.25,-94.23],[200.0,-93.66],[201.7,-93.06],[203.34,-92.43],[204.92,-91.76],[206.44,-91.06],[207.89,-90.32],[209.27,-89.55],[210.58,-88.75],[211.83,-87.92],[213.01,-87.06],[214.12,-86.18],[215.17,-85.27],[216.15,-84.35],[217.08,-83.41],[217.95,-82.46],[218.76,-81.49],[219.54,-80.51],[220.27,-79.53],[220.96,-78.55],[221.63,-77.56],[222.28,-76.58],[222.91,-75.6],[223.54,-74.62],[224.17,-73.66],[224.8,-72.7],[225.45,-71.75],[226.12,-70.81],[226.82,-69.89],[227.56,-68.98],[228.35,-68.08],[229.18,-67.19],[230.07,-66.32],[231.02,-65.46],[232.04,-64.62],[233.12,-63.78],[234.28,-62.95],[235.52,-62.13],[236.83,-61.32],[238.22,-60.51],[239.68,-59.71],[241.23,-58.9],[242.84,-58.09],[244.53,-57.28],[246.29,-56.46],[248.11,-55.64],[249.99,-54.8],[251.92,-53.95],[253.89,-53.09],[255.9,-52.2],[257.94,-51.3],[260.0,-50.38],[262.07,-49.44],[264.14,-48.48],[266.19,-47.49],[268.23,-46.47],[270.24,-45.43],[272.2,-44.37],[274.11,-43.28],[275.96,-42.16],[277.73,-41.02],[279.41,-39.86],[281.0,-38.68],[282.49,-37.47],[283.86,-36.24],[285.11,-35.0]],[[290.17,-35.0],[291.32,-33.71],[292.33,-32.4],[293.2,-31.08],[293.92,-29.76],[294.48,-28.42],[294.88,-27.09],[295.12,-25.75],[295.2,-24.42],[295.11,-23.09],[294.86,-21.76],[294.45,-20.45],[293.87,-19.16],[293.14,-17.87],[292.26,-16.61],[291.23,-15.37],[290.06,-14.14],[288.75,-12.95],[287.31,-11.78],[285.76,-10.63],[284.09,-9.51],[282.32,-8.42],[280.46,-7.36],[278.52,-6.33],[276.51,-5.33],[274.43,-4.36],[272.31,-3.42],[270.14,-2.5],[267.94,-1.61],[265.72,-0.74],[263.49,0.11],[261.26,0.93],[259.03,1.74],[256.82,2.53],[254.63,3.3],[252.46,4.06],[250.34,4.81],[248.25,5.56],[246.22,6.3],[244.23,7.04],[242.29,7.78],[240.41,8.52],[238.58,9.26],[236.82,10.01],[235.11,10.77],[233.45,11.53],[231.85,12.31],[230.3,13.1],[228.8,13.9],[227.34,14.71],[225.93,15.54],[224.55,16.37],[223.2,17.22],[221.87,18.08],[220.57,18.95],[219.28,19.82],[217.99,20.71],[216.71,21.59],[215.42,22.48],[214.12,23.37],[212.8,24.26],[211.46,25.14],[210.09,26.01],[208.68,26.86],[207.24,27.71],[205.76,28.53],[204.23,29.33],[202.65,30.11],[201.02,30.86],[199.33,31.57],[197.59,32.26],[195.8,32.9],[193.95,33.51],[192.04,34.07],[190.08,34.59],[188.07,35.07],[186.01,35.5],[183.9,35.88],[181.75,36.21],[179.56,36.49],[177.33,36.73],[175.06,36.92],[172.77,37.06],[170.46,37.15],[168.13,37.2],[165.79,37.21],[163.44,37.18],[161.09,37.12],[158.74,37.02],[156.4,36.89],[154.07,36.74],[151.76,36.57],[149.47,36.38],[147.2,36.18],[144.96,35.97],[142.75,35.76],[140.57,35.55],[138.42,35.34],[136.31,35.15],[134.23,34.98],[132.19,34.83],[130.19,34.7],[128.22,34.6],[126.28,34.53],[124.37,34.51],[122.49,34.52],[120.63,34.57],[118.8,34.67],[116.98,34.82],[115.18,35.02],[113.39,35.27],[111.6,35.57],[109.82,35.92],[108.03,36.32],[106.23,36.77],[104.42,37.28],[102.59,37.82],[100.73,38.42],[98.85,39.05],[96.94,39.72],[95.0,40.43],[93.02,41.17],[90.99,41.94],[88.93,42.72],[86.82,43.53],[84.66,44.35],[82.46,45.17],[80.21,45.99],[77.91,46.81],[75.56,47.62],[73.17,48.42],[70.73,49.19],[68.26,49.93],[65.74,50.65],[63.2,51.32],[60.62,51.95],[58.01,52.54],[55.38,53.07],[52.74,53.55],[50.08,53.97],[47.41,54.33],[44.75,54.63],[42.09,54.85],[39.44,55.01],[36.8,55.1],[34.19,55.11],[31.6,55.06],[29.05,54.93],[26.53,54.73],[24.05,54.46],[21.61,54.12],[19.23,53.72],[16.89,53.25],[14.61,52.72],[12.38,52.13],[10.22,51.48],[8.11,50.79],[6.06,50.04],[4.07,49.25],[2.13,48.42],[0.26,47.55],[-1.57,46.65],[-3.34,45.72],[-5.06,44.77],[-6.73,43.8],[-8.36,42.82],[-9.96,41.82],[-11.52,40.82],[-13.05,39.81],[-14.56,38.8],[-16.05,37.8],[-17.52,36.8],[-18.99,35.81],[-20.45,34.83],[-21.91,33.86],[-23.38,32.9],[-24.86,31.96],[-26.35,31.04],[-27.86,30.13],[-29.39,29.23],[-30.94,28.35],[-32.52,27.49],[-34.12,26.64],[-35.75,25.8],[-37.41,24.97],[-39.09,24.15],[-40.8,23.34],[-42.53,22.54],[-44.29,21.74],[-46.06,20.94],[-47.84,20.13],[-49.63,19.33],[-51.43,18.52],[-53.22,17.69],[-55.0,16.86],[-56.77,16.01],[-58.52,15.15],[-60.24,14.27],[-61.92,13.37],[-63.55,12.45],[-65.13,11.5],[-66.64,10.54],[-68.09,9.54],[-69.46,8.53],[-70.75,7.48],[-71.94,6.41],[-73.03,5.32],[-74.02,4.2],[-74.89,3.05],[-75.65,1.88],[-76.29,0.69],[-76.8,-0.52],[-77.19,-1.75],[-77.44,-3.0],[-77.56,-4.26],[-77.55,-5.54],[-77.41,-6.82],[-77.13,-8.11],[-76.73,-9.41],[-76.21,-10.71],[-75.56,-12.01],[-74.8,-13.31],[-73.92,-14.6],[-72.95,-15.88],[-71.88,-17.16],[-70.72,-18.42],[-69.48,-19.67],[-68.17,-20.9],[-66.81,-22.11],[-65.39,-23.3],[-63.94,-24.47],[-62.46,-25.63],[-60.96,-26.75],[-59.46,-27.86],[-57.96,-28.94],[-56.47,-30.01],[-55.02,-31.05],[-53.6,-32.06],[-52.23,-33.06],[-50.91,-34.04],[-49.66,-35.0],[-48.48,-35.94],[-47.38,-36.88],[-46.37,-37.79],[-45.45,-38.7],[-44.63,-39.6],[-43.91,-40.5],[-43.29,-41.39],[-42.77,-42.28],[-42.37,-43.18],[-42.07,-44.08],[-41.87,-44.98],[-41.78,-45.9],[-41.78,-46.82],[-41.88,-47.76],[-42.08,-48.72],[-42.35,-49.69],[-42.71,-50.67],[-43.13,-51.68],[-43.62,-52.71],[-44.16,-53.76],[-44.75,-54.83],[-45.37,-55.92],[-46.02,-57.03],[-46.69,-58.16],[-47.36,-59.31],[-48.03,-60.48],[-48.69,-61.67],[-49.32,-62.87],[-49.92,-64.08],[-50.48,-65.31],[-50.98,-66.55],[-51.43,-67.79],[-51.8,-69.04],[-52.1,-70.29],[-52.32,-71.55],[-52.46,-72.79],[-52.49,-74.04],[-52.44,-75.27],[-52.28,-76.49],[-52.01,-77.7],[-51.65,-78.89],[-51.17,-80.06],[-50.59,-81.21],[-49.9,-82.34],[-49.11,-83.44],[-48.22,-84.51],[-47.22,-85.56],[-46.13,-86.58],[-44.95,-87.57],[-43.68,-88.53],[-42.33,-89.46],[-40.9,-90.36],[-39.4,-91.23],[-37.84,-92.07],[-36.22,-92.89],[-34.55,-93.68],[-32.84,-94.44],[-31.09,-95.19],[-29.31,-95.91],[-27.5,-96.62],[-25.67,-97.31],[-23.84,-97.99],[-22.0,-98.67],[-20.15,-99.33],[-18.31,-99.99],[-16.48,-100.66],[-14.65,-101.32],[-12.85,-101.99],[-11.06,-102.67],[-9.28,-103.36],[-7.53,-104.07],[-5.8,-104.79],[-4.09,-105.53],[-2.4,-106.29],[-0.73,-107.07],[0.92,-107.87],[2.56,-108.7],[4.19,-109.55],[5.8,-110.42],[7.41,-111.32],[9.01,-112.24],[10.62,-113.18],[12.23,-114.14],[13.85,-115.11],[15.49,-116.11],[17.14,-117.11],[18.82,-118.13],[20.52,-119.15],[22.26,-120.17],[24.03,-121.19],[25.83,-122.21],[27.68,-123.21],[29.58,-124.2],[31.52,-125.17],[33.51,-126.12],[35.55,-127.03],[37.65,-127.91],[39.79,-128.75],[41.99,-129.55],[44.24,-130.3],[46.54,-130.99],[48.88,-131.62],[51.28,-132.2],[53.71,-132.71],[56.19,-133.14],[58.7,-133.51],[61.25,-133.8],[63.82,-134.02],[66.42,-134.16],[69.03,-134.21],[71.66,-134.19],[74.3,-134.09],[76.93,-133.91],[79.57,-133.64],[82.19,-133.3],[84.8,-132.89],[87.39,-132.4],[89.96,-131.84],[92.5,-131.21],[95.0,-130.51],[97.47,-129.76],[99.89,-128.95],[102.27,-128.09],[104.6,-127.18],[106.89,-126.23],[109.12,-125.25],[111.3,-124.24],[113.43,-123.2],[115.5,-122.14],[117.53,-121.07],[119.5,-119.99],[121.42,-118.91],[123.29,-117.83],[125.13,-116.76],[126.91,-115.71],[128.67,-114.67],[130.38,-113.66],[132.07,-112.67],[133.73,-111.71],[135.37,-110.79],[136.99,-109.9],[138.61,-109.05],[140.21,-108.25],[141.82,-107.48],[143.43,-106.76],[145.04,-106.08],[146.67,-105.45],[148.31,-104.86],[149.97,-104.31],[151.66,-103.81],[153.37,-103.34],[155.11,-102.92],[156.88,-102.52],[158.69,-102.16],[160.52,-101.83],[162.39,-101.53],[164.29,-101.25],[166.22,-100.98],[168.18,-100.73],[170.17,-100.5],[172.19,-100.26],[174.23,-100.03],[176.28,-99.8],[178.35,-99.57],[180.44,-99.32],[182.53,-99.06],[184.61,-98.78],[186.7,-98.49],[188.77,-98.17],[190.83,-97.82],[192.87,-97.45],[194.88,-97.04],[196.85,-96.6],[198.79,-96.13],[200.69,-95.62],[202.53,-95.08],[204.33,-94.49],[206.07,-93.87],[207.74,-93.22],[209.36,-92.53],[210.91,-91.8],[212.39,-91.04],[213.8,-90.24],[215.14,-89.41],[216.41,-88.56],[217.61,-87.68],[218.75,-86.77],[219.81,-85.84],[220.82,-84.9],[221.77,-83.93],[222.66,-82.95],[223.5,-81.96],[224.3,-80.97],[225.06,-79.96],[225.79,-78.96],[226.49,-77.95],[227.17,-76.95],[227.84,-75.95],[228.51,-74.95],[229.18,-73.97],[229.86,-72.99],[230.56,-72.02],[231.29,-71.07],[232.05,-70.13],[232.85,-69.2],[233.7,-68.28],[234.6,-67.37],[235.56,-66.48],[236.58,-65.6],[237.67,-64.73],[238.84,-63.87],[240.07,-63.01],[241.39,-62.17],[242.78,-61.32],[244.25,-60.48],[245.79,-59.65],[247.41,-58.81],[249.11,-57.96],[250.87,-57.11],[252.69,-56.26],[254.58,-55.39],[256.52,-54.51],[258.51,-53.61],[260.53,-52.7],[262.59,-51.77],[264.66,-50.82],[266.75,-49.85],[268.84,-48.85],[270.92,-47.83],[272.99,-46.79],[275.02,-45.72],[277.01,-44.62],[278.95,-43.5],[280.83,-42.36],[282.63,-41.19],[284.35,-39.99],[285.97,-38.77],[287.49,-37.54],[288.89,-36.28],[290.17,-35.0]],[[295.19,-35.0],[296.37,-33.67],[297.41,-32.33],[298.3,-30.98],[299.03,-29.62],[299.61,-28.25],[300.03,-26.88],[300.28,-25.51],[300.36,-24.14],[300.28,-22.78],[300.02,-21.42],[299.6,-20.08],[299.02,-18.75],[298.27,-17.43],[297.36,-16.13],[296.3,-14.86],[295.1,-13.61],[293.75,-12.38],[292.27,-11.18],[290.66,-10.0],[288.94,-8.86],[287.11,-7.75],[285.18,-6.66],[283.16,-5.61],[281.07,-4.59],[278.91,-3.6],[276.7,-2.63],[274.44,-1.7],[272.15,-0.79],[269.83,0.09],[267.5,0.94],[265.16,1.78],[262.83,2.59],[260.51,3.38],[258.21,4.16],[255.95,4.93],[253.71,5.68],[251.52,6.43],[249.38,7.17],[247.29,7.9],[245.25,8.64],[243.27,9.37],[241.35,10.11],[239.49,10.86],[237.69,11.61],[235.95,12.38],[234.27,13.15],[232.65,13.94],[231.08,14.73],[229.56,15.54],[228.08,16.37],[226.64,17.2],[225.24,18.05],[223.87,18.92],[222.53,19.79],[221.2,20.67],[219.88,21.56],[218.57,22.46],[217.26,23.36],[215.94,24.27],[214.61,25.17],[213.26,26.06],[211.88,26.96],[210.47,27.84],[209.03,28.7],[207.54,29.55],[206.01,30.38],[204.44,31.19],[202.81,31.97],[201.13,32.72],[199.39,33.44],[197.6,34.12],[195.76,34.76],[193.86,35.36],[191.9,35.92],[189.89,36.44],[187.83,36.9],[185.71,37.32],[183.56,37.69],[181.35,38.01],[179.12,38.29],[176.84,38.51],[174.54,38.69],[172.21,38.82],[169.86,38.9],[167.49,38.95],[165.12,38.95],[162.74,38.91],[160.36,38.84],[157.98,38.74],[155.62,38.62],[153.27,38.47],[150.93,38.3],[148.62,38.12],[146.34,37.92],[144.08,37.73],[141.85,37.53],[139.65,37.34],[137.49,37.16],[135.36,36.99],[133.27,36.85],[131.21,36.72],[129.19,36.63],[127.19,36.57],[125.23,36.54],[123.3,36.56],[121.39,36.62],[119.5,36.72],[117.63,36.87],[115.77,37.07],[113.93,37.32],[112.09,37.62],[110.25,37.98],[108.4,38.38],[106.55,38.84],[104.69,39.35],[102.8,39.9],[100.9,40.5],[98.96,41.14],[97.0,41.83],[95.0,42.55],[92.96,43.3],[90.88,44.08],[88.76,44.89],[86.59,45.71],[84.37,46.55],[82.11,47.39],[79.79,48.24],[77.43,49.08],[75.02,49.92],[72.56,50.73],[70.06,51.53],[67.51,52.3],[64.93,53.04],[62.3,53.75],[59.65,54.4],[56.96,55.02],[54.26,55.58],[51.53,56.08],[48.79,56.53],[46.04,56.91],[43.3,57.22],[40.55,57.47],[37.82,57.64],[35.1,57.74],[32.4,57.77],[29.72,57.72],[27.08,57.6],[24.48,57.41],[21.92,57.14],[19.41,56.8],[16.94,56.39],[14.53,55.92],[12.18,55.38],[9.88,54.77],[7.64,54.11],[5.47,53.39],[3.36,52.62],[1.31,51.8],[-0.67,50.94],[-2.6,50.03],[-4.46,49.1],[-6.27,48.13],[-8.03,47.14],[-9.73,46.13],[-11.39,45.09],[-13.0,44.05],[-14.58,43.0],[-16.12,41.94],[-17.64,40.88],[-19.13,39.82],[-20.61,38.77],[-22.07,37.72],[-23.52,36.68],[-24.97,35.66],[-26.43,34.65],[-27.89,33.65],[-29.36,32.67],[-30.85,31.71],[-32.35,30.76],[-33.88,29.83],[-35.43,28.92],[-37.01,28.02],[-38.62,27.13],[-40.25,26.26],[-41.91,25.4],[-43.6,24.55],[-45.31,23.7],[-47.04,22.86],[-48.8,22.02],[-50.57,21.19],[-52.35,20.35],[-54.13,19.5],[-55.92,18.65],[-57.7,17.79],[-59.47,16.92],[-61.22,16.03],[-62.95,15.13],[-64.64,14.21],[-66.28,13.27],[-67.88,12.3],[-69.42,11.32],[-70.89,10.31],[-72.29,9.27],[-73.6,8.21],[-74.82,7.13],[-75.95,6.02],[-76.97,4.88],[-77.89,3.72],[-78.68,2.54],[-79.36,1.33],[-79.91,0.1],[-80.33,-1.14],[-80.63,-2.41],[-80.79,-3.69],[-80.81,-4.98],[-80.71,-6.28],[-80.47,-7.59],[-80.1,-8.91],[-79.6,-10.23],[-78.98,-11.55],[-78.24,-12.87],[-77.39,-14.18],[-76.43,-15.49],[-75.38,-16.78],[-74.23,-18.07],[-73.0,-19.34],[-71.7,-20.59],[-70.33,-21.83],[-68.91,-23.04],[-67.45,-24.24],[-65.96,-25.42],[-64.45,-26.57],[-62.93,-27.7],[-61.42,-28.81],[-59.91,-29.89],[-58.43,-30.96],[-56.99,-32.0],[-55.59,-33.02],[-54.25,-34.02],[-52.97,-35.0],[-51.77,-35.97],[-50.64,-36.92],[-49.6,-37.86],[-48.66,-38.79],[-47.81,-39.71],[-47.07,-40.62],[-46.43,-41.54],[-45.9,-42.45],[-45.48,-43.36],[-45.16,-44.28],[-44.96,-45.21],[-44.86,-46.14],[-44.87,-47.09],[-44.97,-48.05],[-45.17,-49.03],[-45.46,-50.02],[-45.83,-51.03],[-46.28,-52.06],[-46.79,-53.11],[-47.37,-54.19],[-47.99,-55.29],[-48.65,-56.4],[-49.34,-57.55],[-50.05,-58.71],[-50.78,-59.89],[-51.5,-61.1],[-52.21,-62.32],[-52.89,-63.56],[-53.55,-64.81],[-54.17,-66.08],[-54.73,-67.36],[-55.24,-68.65],[-55.67,-69.94],[-56.04,-71.24],[-56.31,-72.54],[-56.5,-73.83],[-56.6,-75.12],[-56.59,-76.4],[-56.49,-77.67],[-56.27,-78.93],[-55.94,-80.17],[-55.51,-81.4],[-54.96,-82.6],[-54.3,-83.77],[-53.54,-84.92],[-52.66,-86.05],[-51.68,-87.15],[-50.6,-88.21],[-49.41,-89.25],[-48.14,-90.25],[-46.78,-91.22],[-45.33,-92.16],[-43.81,-93.07],[-42.22,-93.95],[-40.57,-94.8],[-38.85,-95.63],[-37.09,-96.42],[-35.29,-97.19],[-33.45,-97.94],[-31.58,-98.67],[-29.69,-99.39],[-27.78,-100.09],[-25.87,-100.77],[-23.94,-101.45],[-22.02,-102.12],[-20.1,-102.79],[-18.2,-103.46],[-16.3,-104.14],[-14.42,-104.82],[-12.56,-105.51],[-10.71,-106.21],[-8.89,-106.93],[-7.09,-107.66],[-5.3,-108.41],[-3.54,-109.19],[-1.8,-109.98],[-0.07,-110.8],[1.64,-111.64],[3.34,-112.5],[5.03,-113.39],[6.72,-114.3],[8.41,-115.23],[10.1,-116.18],[11.79,-117.15],[13.5,-118.13],[15.23,-119.13],[16.98,-120.14],[18.75,-121.15],[20.55,-122.17],[22.38,-123.19],[24.25,-124.2],[26.16,-125.21],[28.12,-126.2],[30.12,-127.17],[32.16,-128.12],[34.26,-129.04],[36.41,-129.92],[38.61,-130.77],[40.86,-131.57],[43.16,-132.32],[45.51,-133.02],[47.91,-133.67],[50.35,-134.25],[52.84,-134.77],[55.37,-135.21],[57.94,-135.59],[60.54,-135.89],[63.16,-136.11],[65.81,-136.26],[68.48,-136.32],[71.16,-136.3],[73.85,-136.2],[76.55,-136.02],[79.24,-135.76],[81.92,-135.42],[84.58,-135.0],[87.23,-134.5],[89.85,-133.93],[92.44,-133.29],[95.0,-132.59],[97.52,-131.82],[100.0,-130.99],[102.43,-130.11],[104.81,-129.19],[107.15,-128.22],[109.43,-127.21],[111.65,-126.16],[113.83,-125.1],[115.94,-124.01],[118.01,-122.91],[120.02,-121.79],[121.98,-120.68],[123.89,-119.57],[125.75,-118.46],[127.57,-117.37],[129.35,-116.29],[131.1,-115.24],[132.81,-114.22],[134.49,-113.22],[136.16,-112.26],[137.8,-111.34],[139.44,-110.46],[141.06,-109.62],[142.68,-108.82],[144.31,-108.07],[145.94,-107.37],[147.59,-106.71],[149.25,-106.1],[150.94,-105.53],[152.64,-105.0],[154.38,-104.52],[156.14,-104.08],[157.94,-103.68],[159.77,-103.31],[161.63,-102.97],[163.54,-102.66],[165.47,-102.38],[167.44,-102.12],[169.45,-101.87],[171.49,-101.64],[173.55,-101.42],[175.64,-101.2],[177.76,-100.98],[179.89,-100.76],[182.04,-100.53],[184.2,-100.29],[186.36,-100.03],[188.52,-99.75],[190.68,-99.45],[192.82,-99.13],[194.94,-98.77],[197.04,-98.39],[199.11,-97.97],[201.14,-97.52],[203.14,-97.03],[205.08,-96.5],[206.98,-95.94],[208.82,-95.33],[210.59,-94.69],[212.31,-94.01],[213.96,-93.29],[215.54,-92.54],[217.05,-91.75],[218.49,-90.93],[219.86,-90.08],[221.15,-89.2],[222.38,-88.29],[223.53,-87.36],[224.63,-86.4],[225.65,-85.43],[226.62,-84.44],[227.54,-83.44],[228.41,-82.43],[229.23,-81.41],[230.02,-80.38],[230.77,-79.35],[231.51,-78.33],[232.22,-77.3],[232.93,-76.28],[233.64,-75.26],[234.36,-74.26],[235.08,-73.26],[235.84,-72.27],[236.62,-71.3],[237.44,-70.33],[238.3,-69.38],[239.21,-68.44],[240.18,-67.51],[241.21,-66.6],[242.3,-65.69],[243.47,-64.8],[244.71,-63.91],[246.02,-63.03],[247.41,-62.15],[248.88,-61.28],[250.42,-60.4],[252.04,-59.53],[253.73,-58.65],[255.49,-57.77],[257.32,-56.88],[259.21,-55.98],[261.16,-55.07],[263.15,-54.14],[265.18,-53.2],[267.25,-52.24],[269.34,-51.25],[271.44,-50.25],[273.55,-49.23],[275.65,-48.18],[277.74,-47.1],[279.79,-46.0],[281.81,-44.88],[283.77,-43.73],[285.68,-42.55],[287.51,-41.35],[289.26,-40.12],[290.91,-38.87],[292.45,-37.6],[293.89,-36.31],[295.19,-35.0]],[[300.17,-35.0],[301.37,-33.64],[302.42,-32.27],[303.33,-30.88],[304.09,-29.49],[304.68,-28.09],[305.11,-26.68],[305.38,-25.28],[305.47,-23.87],[305.38,-22.47],[305.13,-21.08],[304.7,-19.71],[304.1,-18.34],[303.34,-16.99],[302.41,-15.66],[301.32,-14.36],[300.08,-13.07],[298.69,-11.81],[297.17,-10.58],[295.51,-9.38],[293.73,-8.21],[291.84,-7.07],[289.85,-5.97],[287.76,-4.89],[285.59,-3.85],[283.35,-2.84],[281.05,-1.86],[278.7,-0.91],[276.31,0.01],[273.9,0.9],[271.47,1.77],[269.03,2.61],[266.59,3.43],[264.17,4.23],[261.76,5.01],[259.39,5.78],[257.05,6.53],[254.76,7.28],[252.51,8.02],[250.31,8.75],[248.17,9.49],[246.1,10.22],[244.08,10.96],[242.13,11.7],[240.24,12.45],[238.42,13.2],[236.66,13.97],[234.96,14.76],[233.31,15.55],[231.72,16.36],[230.19,17.18],[228.69,18.02],[227.24,18.87],[225.83,19.73],[224.44,20.61],[223.08,21.5],[221.73,22.4],[220.39,23.31],[219.06,24.22],[217.72,25.14],[216.38,26.06],[215.01,26.97],[213.63,27.88],[212.22,28.79],[210.77,29.68],[209.29,30.56],[207.76,31.41],[206.19,32.25],[204.57,33.06],[202.9,33.85],[201.17,34.6],[199.39,35.32],[197.55,36.0],[195.65,36.64],[193.7,37.24],[191.69,37.79],[189.63,38.3],[187.52,38.76],[185.36,39.17],[183.15,39.54],[180.91,39.85],[178.62,40.11],[176.31,40.33],[173.96,40.5],[171.6,40.62],[169.21,40.7],[166.81,40.73],[164.4,40.73],[161.99,40.69],[159.59,40.62],[157.19,40.52],[154.8,40.39],[152.42,40.25],[150.07,40.09],[147.74,39.91],[145.43,39.74],[143.16,39.55],[140.91,39.38],[138.7,39.21],[136.52,39.05],[134.37,38.91],[132.26,38.8],[130.18,38.71],[128.13,38.65],[126.11,38.63],[124.12,38.65],[122.16,38.71],[120.21,38.81],[118.29,38.96],[116.38,39.16],[114.48,39.42],[112.58,39.72],[110.69,40.08],[108.79,40.49],[106.88,40.95],[104.96,41.46],[103.02,42.02],[101.06,42.62],[99.07,43.28],[97.06,43.97],[95.0,44.7],[92.91,45.47],[90.77,46.26],[88.59,47.08],[86.36,47.92],[84.08,48.78],[81.76,49.64],[79.38,50.51],[76.95,51.37],[74.48,52.23],[71.95,53.07],[69.38,53.89],[66.76,54.69],[64.1,55.45],[61.41,56.18],[58.67,56.86],[55.91,57.5],[53.13,58.09],[50.32,58.61],[47.5,59.08],[44.67,59.48],[41.84,59.82],[39.01,60.08],[36.19,60.27],[33.39,60.39],[30.6,60.43],[27.85,60.39],[25.12,60.28],[22.44,60.09],[19.79,59.82],[17.2,59.48],[14.66,59.07],[12.17,58.58],[9.74,58.03],[7.38,57.41],[5.07,56.73],[2.84,55.99],[0.67,55.19],[-1.44,54.35],[-3.48,53.45],[-5.45,52.52],[-7.36,51.55],[-9.21,50.54],[-11.0,49.51],[-12.73,48.45],[-14.41,47.37],[-16.05,46.28],[-17.64,45.17],[-19.19,44.06],[-20.71,42.95],[-22.21,41.84],[-23.68,40.73],[-25.13,39.63],[-26.58,38.53],[-28.02,37.45],[-29.45,36.39],[-30.9,35.33],[-32.35,34.3],[-33.81,33.28],[-35.29,32.28],[-36.79,31.3],[-38.32,30.33],[-39.87,29.38],[-41.44,28.45],[-43.05,27.53],[-44.68,26.62],[-46.34,25.73],[-48.03,24.84],[-49.74,23.96],[-51.48,23.09],[-53.23,22.21],[-55.0,21.34],[-56.77,20.47],[-58.55,19.59],[-60.33,18.7],[-62.09,17.8],[-63.85,16.89],[-65.58,15.97],[-67.28,15.02],[-68.94,14.06],[-70.55,13.08],[-72.11,12.08],[-73.6,11.05],[-75.02,10.0],[-76.37,8.92],[-77.62,7.82],[-78.78,6.7],[-79.84,5.55],[-80.79,4.37],[-81.63,3.17],[-82.35,1.95],[-82.94,0.71],[-83.41,-0.55],[-83.74,-1.83],[-83.94,-3.12],[-84.01,-4.43],[-83.94,-5.75],[-83.74,-7.08],[-83.41,-8.42],[-82.95,-9.75],[-82.36,-11.09],[-81.65,-12.43],[-80.82,-13.77],[-79.89,-15.09],[-78.85,-16.41],[-77.72,-17.72],[-76.5,-19.01],[-75.21,-20.29],[-73.85,-21.55],[-72.44,-22.79],[-70.98,-24.01],[-69.48,-25.21],[-67.96,-26.38],[-66.43,-27.54],[-64.9,-28.67],[-63.38,-29.78],[-61.89,-30.86],[-60.42,-31.93],[-59.0,-32.97],[-57.64,-33.99],[-56.33,-35.0],[-55.1,-35.99],[-53.95,-36.96],[-52.89,-37.92],[-51.92,-38.87],[-51.05,-39.82],[-50.29,-40.75],[-49.63,-41.69],[-49.08,-42.62],[-48.65,-43.55],[-48.32,-44.49],[-48.11,-45.44],[-48.01,-46.39],[-48.01,-47.36],[-48.12,-48.34],[-48.33,-49.34],[-48.63,-50.36],[-49.01,-51.39],[-49.48,-52.45],[-50.02,-53.53],[-50.62,-54.63],[-51.28,-55.75],[-51.97,-56.9],[-52.71,-58.07],[-53.46,-59.27],[-54.23,-60.48],[-55.0,-61.72],[-55.77,-62.98],[-56.51,-64.26],[-57.22,-65.55],[-57.9,-66.86],[-58.52,-68.18],[-59.09,-69.51],[-59.59,-70.85],[-60.01,-72.19],[-60.34,-73.54],[-60.59,-74.88],[-60.74,-76.22],[-60.79,-77.55],[-60.73,-78.87],[-60.56,-80.18],[-60.28,-81.47],[-59.89,-82.74],[-59.37,-84.0],[-58.74,-85.22],[-58.0,-86.43],[-57.15,-87.6],[-56.18,-88.74],[-55.1,-89.86],[-53.92,-90.94],[-52.64,-91.99],[-51.27,-93.0],[-49.81,-93.99],[-48.26,-94.94],[-46.64,-95.85],[-44.95,-96.74],[-43.2,-97.6],[-41.39,-98.42],[-39.54,-99.22],[-37.64,-100.0],[-35.71,-100.75],[-33.75,-101.48],[-31.77,-102.2],[-29.78,-102.9],[-27.77,-103.59],[-25.77,-104.27],[-23.77,-104.95],[-21.77,-105.63],[-19.78,-106.3],[-17.81,-106.98],[-15.85,-107.67],[-13.92,-108.37],[-12.0,-109.08],[-10.1,-109.81],[-8.22,-110.55],[-6.37,-111.31],[-4.53,-112.1],[-2.71,-112.9],[-0.91,-113.73],[0.88,-114.58],[2.66,-115.46],[4.43,-116.35],[6.2,-117.27],[7.97,-118.21],[9.75,-119.17],[11.53,-120.14],[13.33,-121.13],[15.15,-122.13],[16.99,-123.13],[18.86,-124.15],[20.76,-125.16],[22.69,-126.17],[24.66,-127.17],[26.68,-128.16],[28.74,-129.13],[30.84,-130.08],[32.99,-131.0],[35.19,-131.89],[37.45,-132.74],[39.75,-133.55],[42.1,-134.31],[44.51,-135.01],[46.96,-135.67],[49.45,-136.26],[51.99,-136.78],[54.57,-137.24],[57.19,-137.62],[59.84,-137.93],[62.52,-138.16],[65.22,-138.31],[67.94,-138.38],[70.68,-138.37],[73.42,-138.27],[76.17,-138.09],[78.91,-137.83],[81.65,-137.49],[84.37,-137.07],[87.07,-136.57],[89.74,-135.99],[92.39,-135.34],[95.0,-134.63],[97.57,-133.85],[100.1,-133.01],[102.59,-132.11],[105.02,-131.16],[107.4,-130.17],[109.73,-129.14],[112.0,-128.07],[114.22,-126.98],[116.38,-125.86],[118.48,-124.73],[120.53,-123.58],[122.53,-122.43],[124.48,-121.29],[126.37,-120.15],[128.22,-119.02],[130.03,-117.91],[131.81,-116.82],[133.54,-115.76],[135.25,-114.73],[136.94,-113.74],[138.61,-112.78],[140.26,-111.86],[141.91,-110.99],[143.55,-110.16],[145.2,-109.38],[146.85,-108.65],[148.51,-107.97],[150.19,-107.33],[151.9,-106.74],[153.63,-106.2],[155.38,-105.7],[157.17,-105.24],[158.99,-104.83],[160.85,-104.45],[162.75,-104.11],[164.68,-103.8],[166.66,-103.51],[168.67,-103.25],[170.72,-103.01],[172.8,-102.79],[174.92,-102.57],[177.06,-102.36],[179.24,-102.16],[181.43,-101.95],[183.65,-101.74],[185.88,-101.51],[188.11,-101.27],[190.35,-101.02],[192.59,-100.74],[194.82,-100.43],[197.03,-100.1],[199.22,-99.74],[201.38,-99.34],[203.51,-98.91],[205.6,-98.44],[207.65,-97.93],[209.65,-97.39],[211.59,-96.8],[213.47,-96.18],[215.29,-95.51],[217.04,-94.81],[218.73,-94.06],[220.34,-93.28],[221.88,-92.47],[223.35,-91.62],[224.74,-90.74],[226.06,-89.83],[227.31,-88.9],[228.49,-87.94],[229.6,-86.95],[230.65,-85.96],[231.64,-84.94],[232.58,-83.91],[233.48,-82.87],[234.32,-81.83],[235.14,-80.78],[235.93,-79.73],[236.69,-78.68],[237.44,-77.63],[238.19,-76.59],[238.94,-75.55],[239.7,-74.52],[240.47,-73.5],[241.28,-72.49],[242.11,-71.49],[242.99,-70.51],[243.91,-69.53],[244.88,-68.57],[245.92,-67.62],[247.01,-66.67],[248.18,-65.74],[249.41,-64.82],[250.72,-63.9],[252.11,-62.99],[253.57,-62.08],[255.11,-61.17],[256.72,-60.26],[258.41,-59.35],[260.17,-58.43],[261.99,-57.51],[263.88,-56.58],[265.83,-55.63],[267.82,-54.67],[269.86,-53.7],[271.93,-52.7],[274.03,-51.69],[276.14,-50.66],[278.26,-49.6],[280.37,-48.52],[282.47,-47.42],[284.55,-46.29],[286.59,-45.13],[288.57,-43.95],[290.5,-42.74],[292.35,-41.51],[294.13,-40.25],[295.8,-38.97],[297.37,-37.67],[298.83,-36.34],[300.17,-35.0]],[[305.08,-35.0],[306.3,-33.61],[307.38,-32.2],[308.31,-30.78],[309.08,-29.36],[309.69,-27.92],[310.14,-26.48],[310.41,-25.04],[310.5,-23.61],[310.42,-22.17],[310.17,-20.75],[309.73,-19.34],[309.12,-17.94],[308.34,-16.56],[307.39,-15.2],[306.28,-13.86],[305.01,-12.55],[303.58,-11.26],[302.01,-10.0],[300.3,-8.77],[298.47,-7.57],[296.52,-6.41],[294.46,-5.28],[292.3,-4.18],[290.06,-3.12],[287.74,-2.09],[285.35,-1.09],[282.91,-0.13],[280.43,0.81],[277.92,1.71],[275.39,2.59],[272.85,3.44],[270.31,4.26],[267.78,5.07],[265.28,5.85],[262.8,6.62],[260.35,7.38],[257.95,8.13],[255.6,8.86],[253.3,9.59],[251.06,10.32],[248.88,11.05],[246.77,11.78],[244.73,12.52],[242.75,13.27],[240.84,14.02],[239.0,14.78],[237.22,15.56],[235.51,16.35],[233.85,17.16],[232.25,17.98],[230.7,18.81],[229.2,19.67],[227.74,20.53],[226.31,21.42],[224.91,22.31],[223.53,23.22],[222.17,24.13],[220.82,25.06],[219.46,25.99],[218.1,26.92],[216.73,27.86],[215.34,28.79],[213.93,29.72],[212.48,30.63],[211.0,31.54],[209.48,32.43],[207.92,33.3],[206.3,34.14],[204.64,34.96],[202.92,35.75],[201.15,36.51],[199.32,37.23],[197.43,37.91],[195.49,38.55],[193.49,39.14],[191.43,39.69],[189.32,40.2],[187.16,40.65],[184.95,41.06],[182.7,41.41],[180.41,41.72],[178.09,41.98],[175.73,42.19],[173.35,42.35],[170.94,42.46],[168.52,42.54],[166.09,42.57],[163.65,42.56],[161.21,42.52],[158.78,42.45],[156.35,42.35],[153.94,42.23],[151.54,42.09],[149.17,41.94],[146.81,41.78],[144.49,41.62],[142.19,41.46],[139.93,41.3],[137.7,41.16],[135.5,41.03],[133.33,40.92],[131.19,40.84],[129.09,40.79],[127.02,40.77],[124.97,40.79],[122.95,40.85],[120.95,40.96],[118.96,41.11],[117.0,41.31],[115.04,41.56],[113.09,41.87],[111.14,42.23],[109.18,42.64],[107.22,43.1],[105.24,43.61],[103.25,44.18],[101.23,44.79],[99.19,45.45],[97.11,46.15],[95.0,46.89],[92.85,47.66],[90.65,48.47],[88.42,49.3],[86.13,50.16],[83.79,51.03],[81.4,51.91],[78.96,52.79],[76.47,53.68],[73.93,54.56],[71.34,55.42],[68.69,56.26],[66.01,57.08],[63.28,57.87],[60.51,58.62],[57.7,59.33],[54.86,59.99],[52.0,60.6],[49.11,61.15],[46.21,61.64],[43.3,62.06],[40.38,62.42],[37.47,62.7],[34.57,62.9],[31.68,63.03],[28.81,63.09],[25.97,63.06],[23.16,62.95],[20.39,62.77],[17.67,62.5],[14.99,62.16],[12.37,61.74],[9.81,61.25],[7.31,60.68],[4.87,60.05],[2.5,59.35],[0.2,58.59],[-2.03,57.77],[-4.19,56.89],[-6.28,55.97],[-8.3,55.0],[-10.25,53.99],[-12.14,52.95],[-13.96,51.87],[-15.72,50.77],[-17.43,49.64],[-19.08,48.5],[-20.69,47.35],[-22.25,46.18],[-23.78,45.02],[-25.27,43.85],[-26.74,42.68],[-28.19,41.52],[-29.62,40.37],[-31.04,39.24],[-32.46,38.11],[-33.88,37.0],[-35.31,35.91],[-36.75,34.84],[-38.2,33.78],[-39.67,32.74],[-41.17,31.73],[-42.69,30.73],[-44.23,29.74],[-45.81,28.78],[-47.41,27.82],[-49.04,26.88],[-50.7,25.96],[-52.39,25.04],[-54.1,24.13],[-55.83,23.22],[-57.58,22.31],[-59.34,21.41],[-61.11,20.5],[-62.88,19.58],[-64.64,18.66],[-66.39,17.72],[-68.13,16.77],[-69.83,15.81],[-71.5,14.83],[-73.13,13.83],[-74.71,12.81],[-76.23,11.77],[-77.67,10.7],[-79.05,9.61],[-80.34,8.5],[-81.53,7.36],[-82.63,6.19],[-83.62,5.0],[-84.5,3.79],[-85.26,2.56],[-85.9,1.3],[-86.41,0.03],[-86.79,-1.26],[-87.03,-2.57],[-87.14,-3.9],[-87.12,-5.23],[-86.96,-6.58],[-86.67,-7.93],[-86.25,-9.29],[-85.7,-10.64],[-85.02,-12.0],[-84.23,-13.36],[-83.32,-14.7],[-82.31,-16.04],[-81.2,-17.37],[-80.0,-18.68],[-78.73,-19.98],[-77.38,-21.27],[-75.97,-22.53],[-74.51,-23.77],[-73.02,-25.0],[-71.5,-26.2],[-69.96,-27.38],[-68.42,-28.53],[-66.89,-29.66],[-65.38,-30.77],[-63.9,-31.86],[-62.46,-32.93],[-61.07,-33.97],[-59.75,-35.0],[-58.5,-36.01],[-57.33,-37.01],[-56.24,-37.99],[-55.25,-38.96],[-54.36,-39.92],[-53.57,-40.88],[-52.9,-41.84],[-52.33,-42.79],[-51.88,-43.74],[-51.55,-44.71],[-51.33,-45.67],[-51.22,-46.65],[-51.22,-47.64],[-51.33,-48.64],[-51.55,-49.66],[-51.86,-50.7],[-52.26,-51.76],[-52.74,-52.84],[-53.3,-53.95],[-53.93,-55.07],[-54.62,-56.23],[-55.35,-57.4],[-56.12,-58.6],[-56.92,-59.83],[-57.74,-61.08],[-58.56,-62.35],[-59.37,-63.65],[-60.17,-64.96],[-60.94,-66.3],[-61.67,-67.64],[-62.35,-69.01],[-62.98,-70.38],[-63.54,-71.76],[-64.02,-73.15],[-64.41,-74.55],[-64.72,-75.94],[-64.92,-77.32],[-65.02,-78.71],[-65.02,-80.08],[-64.9,-81.44],[-64.66,-82.78],[-64.3,-84.11],[-63.82,-85.41],[-63.23,-86.69],[-62.51,-87.94],[-61.67,-89.16],[-60.72,-90.36],[-59.65,-91.52],[-58.47,-92.65],[-57.19,-93.74],[-55.81,-94.8],[-54.33,-95.83],[-52.76,-96.82],[-51.11,-97.77],[-49.38,-98.69],[-47.59,-99.58],[-45.73,-100.44],[-43.83,-101.27],[-41.87,-102.07],[-39.87,-102.85],[-37.85,-103.6],[-35.79,-104.33],[-33.72,-105.05],[-31.64,-105.75],[-29.55,-106.44],[-27.46,-107.12],[-25.37,-107.8],[-23.29,-108.48],[-21.23,-109.16],[-19.17,-109.85],[-17.14,-110.54],[-15.12,-111.25],[-13.13,-111.96],[-11.16,-112.7],[-9.2,-113.45],[-7.27,-114.22],[-5.36,-115.01],[-3.46,-115.83],[-1.58,-116.66],[0.29,-117.52],[2.15,-118.4],[4.0,-119.3],[5.86,-120.23],[7.72,-121.17],[9.58,-122.13],[11.46,-123.11],[13.35,-124.1],[15.26,-125.09],[17.2,-126.1],[19.16,-127.1],[21.16,-128.1],[23.19,-129.1],[25.27,-130.08],[27.38,-131.05],[29.54,-132.0],[31.75,-132.92],[34.01,-133.81],[36.31,-134.66],[38.67,-135.48],[41.07,-136.24],[43.52,-136.96],[46.03,-137.61],[48.57,-138.21],[51.16,-138.74],[53.79,-139.21],[56.46,-139.6],[59.16,-139.92],[61.89,-140.15],[64.64,-140.31],[67.42,-140.39],[70.2,-140.38],[73.0,-140.29],[75.8,-140.12],[78.59,-139.86],[81.38,-139.52],[84.16,-139.09],[86.91,-138.59],[89.64,-138.01],[92.34,-137.36],[95.0,-136.63],[97.62,-135.84],[100.21,-134.99],[102.74,-134.08],[105.22,-133.11],[107.65,-132.1],[110.03,-131.05],[112.35,-129.96],[114.61,-128.84],[116.81,-127.69],[118.96,-126.53],[121.04,-125.36],[123.08,-124.18],[125.06,-123.0],[126.99,-121.83],[128.87,-120.66],[130.71,-119.52],[132.51,-118.4],[134.28,-117.3],[136.01,-116.24],[137.72,-115.21],[139.41,-114.22],[141.09,-113.27],[142.75,-112.36],[144.42,-111.51],[146.08,-110.7],[147.75,-109.94],[149.44,-109.23],[151.14,-108.57],[152.86,-107.95],[154.61,-107.39],[156.39,-106.88],[158.2,-106.41],[160.05,-105.98],[161.94,-105.6],[163.87,-105.25],[165.83,-104.93],[167.84,-104.65],[169.9,-104.39],[171.99,-104.15],[174.12,-103.93],[176.29,-103.73],[178.49,-103.53],[180.72,-103.34],[182.98,-103.15],[185.26,-102.95],[187.56,-102.75],[189.87,-102.53],[192.19,-102.29],[194.51,-102.03],[196.82,-101.75],[199.12,-101.44],[201.41,-101.1],[203.67,-100.73],[205.9,-100.32],[208.09,-99.87],[210.24,-99.38],[212.34,-98.85],[214.39,-98.29],[216.38,-97.68],[218.3,-97.03],[220.16,-96.33],[221.95,-95.6],[223.67,-94.83],[225.32,-94.02],[226.89,-93.18],[228.38,-92.3],[229.8,-91.39],[231.14,-90.46],[232.41,-89.49],[233.61,-88.5],[234.75,-87.49],[235.82,-86.46],[236.83,-85.42],[237.79,-84.37],[238.71,-83.3],[239.58,-82.23],[240.42,-81.16],[241.24,-80.08],[242.04,-79.0],[242.82,-77.93],[243.61,-76.86],[244.4,-75.8],[245.2,-74.75],[246.02,-73.71],[246.87,-72.67],[247.76,-71.65],[248.69,-70.64],[249.67,-69.64],[250.71,-68.65],[251.8,-67.67],[252.96,-66.7],[254.19,-65.74],[255.5,-64.78],[256.87,-63.84],[258.33,-62.89],[259.86,-61.94],[261.46,-61.0],[263.14,-60.05],[264.89,-59.1],[266.71,-58.14],[268.59,-57.18],[270.52,-56.2],[272.51,-55.21],[274.55,-54.2],[276.62,-53.17],[278.72,-52.13],[280.84,-51.06],[282.96,-49.98],[285.09,-48.86],[287.2,-47.73],[289.29,-46.57],[291.34,-45.38],[293.34,-44.17],[295.29,-42.93],[297.16,-41.67],[298.95,-40.38],[300.65,-39.06],[302.25,-37.73],[303.73,-36.37],[305.08,-35.0]],[[309.94,-35.0],[311.18,-33.58],[312.28,-32.14],[313.22,-30.69],[314.01,-29.23],[314.63,-27.76],[315.09,-26.29],[315.37,-24.81],[315.47,-23.34],[315.39,-21.88],[315.13,-20.42],[314.69,-18.98],[314.07,-17.55],[313.28,-16.13],[312.3,-14.74],[311.17,-13.37],[309.86,-12.03],[308.4,-10.71],[306.79,-9.42],[305.04,-8.17],[303.15,-6.94],[301.14,-5.76],[299.02,-4.6],[296.79,-3.48],[294.47,-2.4],[292.07,-1.35],[289.6,-0.33],[287.08,0.65],[284.51,1.59],[281.9,2.51],[279.28,3.4],[276.64,4.25],[273.99,5.09],[271.36,5.9],[268.75,6.69],[266.16,7.46],[263.61,8.22],[261.11,8.96],[258.65,9.7],[256.25,10.43],[253.91,11.15],[251.63,11.88],[249.42,12.6],[247.29,13.33],[245.22,14.07],[243.23,14.82],[241.3,15.58],[239.45,16.35],[237.66,17.14],[235.94,17.94],[234.28,18.76],[232.67,19.6],[231.12,20.45],[229.61,21.32],[228.14,22.2],[226.71,23.1],[225.3,24.02],[223.91,24.94],[222.53,25.88],[221.16,26.82],[219.79,27.77],[218.41,28.73],[217.02,29.68],[215.6,30.63],[214.16,31.57],[212.69,32.5],[211.17,33.42],[209.62,34.32],[208.01,35.2],[206.36,36.06],[204.66,36.89],[202.89,37.68],[201.08,38.44],[199.2,39.17],[197.26,39.85],[195.27,40.49],[193.22,41.08],[191.12,41.63],[188.96,42.13],[186.76,42.58],[184.51,42.98],[182.21,43.33],[179.88,43.64],[177.51,43.89],[175.11,44.09],[172.69,44.25],[170.25,44.36],[167.79,44.43],[165.33,44.46],[162.86,44.45],[160.39,44.41],[157.93,44.34],[155.48,44.25],[153.04,44.14],[150.62,44.01],[148.22,43.87],[145.85,43.73],[143.51,43.58],[141.19,43.44],[138.9,43.31],[136.65,43.19],[134.43,43.09],[132.23,43.02],[130.07,42.97],[127.94,42.96],[125.84,42.98],[123.75,43.04],[121.7,43.15],[119.66,43.3],[117.63,43.51],[115.61,43.76],[113.6,44.06],[111.59,44.42],[109.58,44.83],[107.56,45.3],[105.53,45.81],[103.48,46.38],[101.4,47.0],[99.3,47.66],[97.17,48.37],[95.0,49.11],[92.79,49.9],[90.54,50.71],[88.24,51.56],[85.89,52.42],[83.49,53.31],[81.04,54.2],[78.54,55.1],[75.98,56.01],[73.38,56.9],[70.72,57.79],[68.01,58.65],[65.25,59.49],[62.45,60.3],[59.6,61.07],[56.72,61.8],[53.81,62.49],[50.86,63.12],[47.9,63.69],[44.92,64.2],[41.92,64.64],[38.93,65.01],[35.93,65.31],[32.94,65.53],[29.97,65.68],[27.02,65.74],[24.09,65.72],[21.2,65.62],[18.35,65.44],[15.55,65.18],[12.8,64.83],[10.1,64.41],[7.46,63.91],[4.89,63.33],[2.38,62.68],[-0.06,61.96],[-2.42,61.18],[-4.71,60.34],[-6.93,59.43],[-9.07,58.48],[-11.14,57.48],[-13.14,56.43],[-15.06,55.35],[-16.92,54.23],[-18.71,53.08],[-20.44,51.91],[-22.11,50.72],[-23.73,49.51],[-25.3,48.29],[-26.83,47.07],[-28.33,45.85],[-29.79,44.63],[-31.23,43.41],[-32.65,42.2],[-34.05,41.01],[-35.45,39.83],[-36.85,38.66],[-38.25,37.51],[-39.66,36.38],[-41.08,35.27],[-42.52,34.18],[-43.98,33.1],[-45.47,32.05],[-46.98,31.02],[-48.52,30.0],[-50.09,29.01],[-51.69,28.02],[-53.32,27.05],[-54.98,26.09],[-56.66,25.14],[-58.37,24.2],[-60.1,23.26],[-61.84,22.32],[-63.59,21.38],[-65.35,20.44],[-67.11,19.49],[-68.86,18.53],[-70.6,17.56],[-72.31,16.57],[-73.99,15.57],[-75.63,14.56],[-77.23,13.52],[-78.77,12.46],[-80.24,11.38],[-81.64,10.27],[-82.96,9.15],[-84.2,8.0],[-85.33,6.82],[-86.36,5.62],[-87.29,4.4],[-88.09,3.15],[-88.78,1.88],[-89.33,0.59],[-89.76,-0.71],[-90.06,-2.04],[-90.22,-3.37],[-90.24,-4.72],[-90.13,-6.08],[-89.89,-7.45],[-89.51,-8.82],[-89.0,-10.2],[-88.36,-11.57],[-87.61,-12.95],[-86.73,-14.31],[-85.75,-15.67],[-84.67,-17.02],[-83.5,-18.36],[-82.24,-19.68],[-80.91,-20.99],[-79.51,-22.27],[-78.06,-23.54],[-76.58,-24.78],[-75.06,-26.01],[-73.52,-27.21],[-71.98,-28.39],[-70.44,-29.55],[-68.92,-30.68],[-67.42,-31.79],[-65.97,-32.88],[-64.57,-33.95],[-63.23,-35.0],[-61.95,-36.03],[-60.76,-37.05],[-59.66,-38.06],[-58.64,-39.05],[-57.73,-40.04],[-56.93,-41.01],[-56.23,-41.99],[-55.65,-42.97],[-55.19,-43.94],[-54.84,-44.92],[-54.61,-45.91],[-54.5,-46.91],[-54.5,-47.92],[-54.61,-48.95],[-54.83,-49.99],[-55.15,-51.05],[-55.56,-52.14],[-56.07,-53.24],[-56.65,-54.37],[-57.3,-55.53],[-58.02,-56.71],[-58.78,-57.91],[-59.59,-59.15],[-60.43,-60.4],[-61.29,-61.69],[-62.16,-62.99],[-63.02,-64.33],[-63.87,-65.68],[-64.7,-67.05],[-65.49,-68.44],[-66.23,-69.84],[-66.91,-71.26],[-67.53,-72.69],[-68.07,-74.12],[-68.52,-75.56],[-68.88,-77.0],[-69.14,-78.44],[-69.3,-79.87],[-69.34,-81.3],[-69.26,-82.71],[-69.07,-84.1],[-68.75,-85.48],[-68.31,-86.83],[-67.74,-88.16],[-67.05,-89.47],[-66.23,-90.74],[-65.29,-91.99],[-64.24,-93.2],[-63.06,-94.37],[-61.77,-95.51],[-60.38,-96.62],[-58.88,-97.68],[-57.29,-98.71],[-55.61,-99.71],[-53.85,-100.67],[-52.02,-101.59],[-50.11,-102.48],[-48.15,-103.33],[-46.14,-104.16],[-44.08,-104.96],[-41.98,-105.73],[-39.85,-106.48],[-37.7,-107.21],[-35.54,-107.93],[-33.36,-108.63],[-31.18,-109.32],[-29.0,-110.0],[-26.83,-110.68],[-24.66,-111.36],[-22.51,-112.04],[-20.38,-112.73],[-18.27,-113.42],[-16.17,-114.13],[-14.1,-114.85],[-12.05,-115.59],[-10.02,-116.35],[-8.01,-117.12],[-6.01,-117.92],[-4.04,-118.74],[-2.08,-119.58],[-0.13,-120.45],[1.82,-121.33],[3.76,-122.24],[5.7,-123.16],[7.64,-124.11],[9.59,-125.07],[11.56,-126.04],[13.55,-127.03],[15.55,-128.02],[17.59,-129.01],[19.65,-130.01],[21.75,-131.0],[23.88,-131.97],[26.05,-132.94],[28.27,-133.88],[30.54,-134.8],[32.85,-135.69],[35.2,-136.55],[37.61,-137.36],[40.07,-138.13],[42.57,-138.85],[45.12,-139.51],[47.72,-140.12],[50.35,-140.66],[53.03,-141.13],[55.75,-141.53],[58.5,-141.85],[61.28,-142.1],[64.08,-142.26],[66.9,-142.35],[69.74,-142.35],[72.59,-142.26],[75.44,-142.09],[78.28,-141.84],[81.12,-141.5],[83.95,-141.08],[86.75,-140.57],[89.53,-139.99],[92.28,-139.33],[95.0,-138.6],[97.68,-137.8],[100.31,-136.94],[102.89,-136.01],[105.42,-135.03],[107.9,-134.01],[110.32,-132.93],[112.69,-131.82],[114.99,-130.68],[117.24,-129.51],[119.42,-128.32],[121.55,-127.12],[123.62,-125.91],[125.64,-124.7],[127.61,-123.5],[129.52,-122.3],[131.39,-121.12],[133.22,-119.97],[135.01,-118.84],[136.77,-117.74],[138.51,-116.68],[140.22,-115.65],[141.92,-114.67],[143.6,-113.74],[145.29,-112.85],[146.97,-112.01],[148.66,-111.23],[150.36,-110.49],[152.09,-109.81],[153.83,-109.17],[155.6,-108.59],[157.4,-108.06],[159.24,-107.58],[161.11,-107.14],[163.03,-106.75],[164.99,-106.39],[166.99,-106.07],[169.04,-105.79],[171.13,-105.53],[173.27,-105.3],[175.44,-105.09],[177.66,-104.89],[179.92,-104.71],[182.21,-104.53],[184.53,-104.35],[186.88,-104.17],[189.25,-103.98],[191.64,-103.79],[194.04,-103.57],[196.44,-103.33],[198.84,-103.07],[201.24,-102.79],[203.61,-102.47],[205.97,-102.12],[208.3,-101.73],[210.6,-101.31],[212.85,-100.84],[215.06,-100.33],[217.21,-99.78],[219.31,-99.19],[221.35,-98.56],[223.32,-97.88],[225.22,-97.16],[227.05,-96.4],[228.8,-95.6],[230.47,-94.76],[232.07,-93.89],[233.58,-92.98],[235.03,-92.04],[236.39,-91.07],[237.68,-90.07],[238.9,-89.05],[240.06,-88.01],[241.15,-86.96],[242.18,-85.88],[243.17,-84.8],[244.1,-83.71],[245.0,-82.61],[245.87,-81.51],[246.71,-80.4],[247.54,-79.3],[248.36,-78.2],[249.18,-77.11],[250.01,-76.02],[250.85,-74.95],[251.72,-73.88],[252.62,-72.82],[253.56,-71.77],[254.54,-70.73],[255.58,-69.7],[256.67,-68.69],[257.82,-67.68],[259.05,-66.68],[260.34,-65.68],[261.7,-64.7],[263.14,-63.71],[264.66,-62.73],[266.25,-61.75],[267.91,-60.76],[269.65,-59.78],[271.45,-58.78],[273.32,-57.78],[275.25,-56.77],[277.23,-55.74],[279.26,-54.7],[281.33,-53.64],[283.42,-52.57],[285.54,-51.47],[287.66,-50.35],[289.79,-49.21],[291.91,-48.04],[294.0,-46.85],[296.07,-45.63],[298.08,-44.39],[300.04,-43.12],[301.93,-41.82],[303.74,-40.5],[305.45,-39.16],[307.07,-37.79],[308.57,-36.41],[309.94,-35.0]],[[314.73,-35.0],[315.99,-33.54],[317.1,-32.07],[318.06,-30.59],[318.87,-29.1],[319.5,-27.6],[319.96,-26.09],[320.25,-24.59],[320.36,-23.09],[320.28,-21.59],[320.02,-20.1],[319.57,-18.62],[318.94,-17.16],[318.13,-15.71],[317.14,-14.29],[315.98,-12.89],[314.65,-11.51],[313.15,-10.17],[311.5,-8.85],[309.7,-7.57],[307.76,-6.32],[305.7,-5.11],[303.51,-3.93],[301.22,-2.79],[298.83,-1.69],[296.35,-0.62],[293.81,0.41],[291.2,1.41],[288.54,2.37],[285.84,3.3],[283.11,4.2],[280.38,5.06],[277.63,5.9],[274.9,6.72],[272.18,7.51],[269.49,8.29],[266.84,9.04],[264.23,9.79],[261.67,10.52],[259.16,11.25],[256.72,11.97],[254.35,12.69],[252.04,13.41],[249.81,14.14],[247.66,14.87],[245.58,15.61],[243.57,16.36],[241.64,17.13],[239.78,17.91],[237.99,18.71],[236.27,19.53],[234.61,20.36],[233.0,21.22],[231.45,22.09],[229.94,22.97],[228.47,23.88],[227.03,24.8],[225.62,25.74],[224.22,26.68],[222.83,27.64],[221.45,28.61],[220.06,29.58],[218.67,30.55],[217.25,31.53],[215.81,32.49],[214.34,33.46],[212.84,34.4],[211.29,35.34],[209.7,36.25],[208.06,37.14],[206.37,38.01],[204.62,38.85],[202.82,39.65],[200.96,40.42],[199.03,41.14],[197.05,41.83],[195.02,42.47],[192.92,43.07],[190.77,43.61],[188.57,44.11],[186.31,44.56],[184.02,44.96],[181.68,45.3],[179.3,45.6],[176.89,45.85],[174.45,46.05],[171.99,46.2],[169.52,46.31],[167.03,46.38],[164.53,46.41],[162.03,46.4],[159.53,46.37],[157.04,46.3],[154.57,46.22],[152.1,46.12],[149.66,46.0],[147.24,45.88],[144.84,45.75],[142.48,45.62],[140.14,45.51],[137.83,45.4],[135.55,45.31],[133.3,45.24],[131.08,45.21],[128.89,45.2],[126.72,45.22],[124.58,45.29],[122.46,45.4],[120.36,45.55],[118.28,45.76],[116.2,46.01],[114.13,46.31],[112.06,46.67],[109.99,47.08],[107.91,47.54],[105.82,48.06],[103.71,48.63],[101.58,49.24],[99.42,49.91],[97.23,50.62],[95.0,51.37],[92.73,52.16],[90.42,52.98],[88.06,53.84],[85.65,54.71],[83.19,55.61],[80.68,56.52],[78.12,57.43],[75.49,58.35],[72.82,59.26],[70.09,60.17],[67.32,61.05],[64.49,61.91],[61.61,62.74],[58.7,63.53],[55.74,64.28],[52.75,64.99],[49.73,65.64],[46.69,66.23],[43.63,66.76],[40.55,67.22],[37.47,67.61],[34.4,67.92],[31.32,68.16],[28.27,68.31],[25.23,68.39],[22.23,68.38],[19.25,68.28],[16.32,68.1],[13.44,67.84],[10.6,67.49],[7.83,67.06],[5.11,66.56],[2.47,65.97],[-0.11,65.3],[-2.61,64.57],[-5.04,63.76],[-7.39,62.9],[-9.66,61.97],[-11.86,60.98],[-13.97,59.94],[-16.01,58.86],[-17.97,57.74],[-19.86,56.57],[-21.68,55.38],[-23.44,54.16],[-25.13,52.92],[-26.76,51.66],[-28.34,50.4],[-29.87,49.12],[-31.36,47.84],[-32.82,46.56],[-34.25,45.29],[-35.65,44.02],[-37.04,42.77],[-38.42,41.53],[-39.79,40.3],[-41.16,39.09],[-42.54,37.91],[-43.93,36.74],[-45.33,35.59],[-46.76,34.47],[-48.21,33.36],[-49.68,32.28],[-51.19,31.21],[-52.72,30.17],[-54.29,29.14],[-55.89,28.13],[-57.51,27.13],[-59.17,26.14],[-60.85,25.16],[-62.55,24.18],[-64.28,23.21],[-66.01,22.24],[-67.76,21.27],[-69.51,20.29],[-71.25,19.31],[-72.99,18.32],[-74.7,17.31],[-76.39,16.29],[-78.05,15.26],[-79.66,14.2],[-81.22,13.13],[-82.72,12.04],[-84.15,10.92],[-85.51,9.78],[-86.78,8.61],[-87.95,7.43],[-89.03,6.22],[-90.0,4.98],[-90.85,3.72],[-91.58,2.45],[-92.19,1.15],[-92.67,-0.17],[-93.02,-1.51],[-93.23,-2.86],[-93.31,-4.22],[-93.25,-5.6],[-93.05,-6.98],[-92.72,-8.37],[-92.26,-9.76],[-91.67,-11.15],[-90.96,-12.54],[-90.12,-13.93],[-89.18,-15.31],[-88.13,-16.68],[-86.99,-18.03],[-85.76,-19.38],[-84.45,-20.7],[-83.07,-22.01],[-81.64,-23.3],[-80.16,-24.57],[-78.65,-25.82],[-77.12,-27.04],[-75.57,-28.25],[-74.03,-29.43],[-72.5,-30.58],[-71.0,-31.72],[-69.54,-32.83],[-68.12,-33.93],[-66.77,-35.0],[-65.48,-36.06],[-64.27,-37.1],[-63.14,-38.13],[-62.11,-39.14],[-61.18,-40.15],[-60.36,-41.15],[-59.65,-42.15],[-59.05,-43.14],[-58.58,-44.14],[-58.22,-45.15],[-57.98,-46.16],[-57.86,-47.18],[-57.86,-48.21],[-57.97,-49.26],[-58.19,-50.33],[-58.52,-51.41],[-58.94,-52.52],[-59.46,-53.65],[-60.06,-54.81],[-60.74,-55.99],[-61.48,-57.2],[-62.28,-58.43],[-63.12,-59.7],[-64.0,-60.99],[-64.9,-62.3],[-65.81,-63.65],[-66.72,-65.01],[-67.63,-66.4],[-68.5,-67.81],[-69.35,-69.24],[-70.14,-70.69],[-70.88,-72.15],[-71.56,-73.62],[-72.15,-75.11],[-72.66,-76.59],[-73.08,-78.08],[-73.4,-79.57],[-73.6,-81.05],[-73.7,-82.52],[-73.67,-83.99],[-73.52,-85.43],[-73.24,-86.86],[-72.83,-88.27],[-72.3,-89.65],[-71.63,-91.01],[-70.83,-92.33],[-69.91,-93.63],[-68.86,-94.89],[-67.68,-96.11],[-66.39,-97.3],[-64.99,-98.45],[-63.48,-99.56],[-61.86,-100.63],[-60.16,-101.66],[-58.36,-102.65],[-56.48,-103.61],[-54.53,-104.53],[-52.51,-105.42],[-50.44,-106.27],[-48.31,-107.09],[-46.14,-107.88],[-43.94,-108.65],[-41.71,-109.39],[-39.46,-110.12],[-37.2,-110.83],[-34.92,-111.52],[-32.65,-112.21],[-30.38,-112.89],[-28.12,-113.56],[-25.87,-114.24],[-23.64,-114.92],[-21.42,-115.61],[-19.22,-116.3],[-17.05,-117.01],[-14.9,-117.73],[-12.76,-118.47],[-10.65,-119.23],[-8.56,-120.01],[-6.49,-120.81],[-4.44,-121.64],[-2.39,-122.48],[-0.36,-123.35],[1.67,-124.23],[3.69,-125.14],[5.72,-126.07],[7.75,-127.01],[9.8,-127.97],[11.86,-128.94],[13.93,-129.91],[16.04,-130.9],[18.17,-131.88],[20.33,-132.86],[22.52,-133.83],[24.76,-134.78],[27.03,-135.72],[29.35,-136.64],[31.71,-137.53],[34.12,-138.38],[36.58,-139.2],[39.09,-139.97],[41.64,-140.69],[44.24,-141.36],[46.88,-141.97],[49.57,-142.52],[52.3,-142.99],[55.06,-143.4],[57.86,-143.74],[60.68,-143.99],[63.53,-144.16],[66.41,-144.26],[69.29,-144.26],[72.19,-144.19],[75.09,-144.02],[77.98,-143.77],[80.87,-143.44],[83.75,-143.02],[86.6,-142.51],[89.43,-141.93],[92.23,-141.27],[95.0,-140.53],[97.73,-139.73],[100.41,-138.86],[103.04,-137.92],[105.62,-136.93],[108.15,-135.89],[110.61,-134.8],[113.02,-133.67],[115.37,-132.5],[117.66,-131.31],[119.89,-130.1],[122.06,-128.87],[124.17,-127.64],[126.22,-126.4],[128.22,-125.16],[130.17,-123.94],[132.07,-122.73],[133.93,-121.54],[135.75,-120.38],[137.53,-119.25],[139.29,-118.15],[141.03,-117.1],[142.75,-116.08],[144.45,-115.12],[146.16,-114.2],[147.86,-113.34],[149.57,-112.52],[151.3,-111.76],[153.04,-111.06],[154.8,-110.4],[156.6,-109.8],[158.42,-109.26],[160.28,-108.76],[162.19,-108.31],[164.13,-107.91],[166.12,-107.55],[168.16,-107.22],[170.24,-106.94],[172.37,-106.68],[174.55,-106.46],[176.78,-106.25],[179.05,-106.06],[181.36,-105.89],[183.71,-105.73],[186.1,-105.56],[188.51,-105.4],[190.96,-105.23],[193.42,-105.05],[195.9,-104.86],[198.39,-104.65],[200.88,-104.41],[203.36,-104.15],[205.84,-103.85],[208.29,-103.52],[210.73,-103.16],[213.13,-102.76],[215.49,-102.31],[217.8,-101.83],[220.07,-101.3],[222.28,-100.72],[224.43,-100.11],[226.51,-99.44],[228.52,-98.74],[230.46,-97.99],[232.32,-97.2],[234.1,-96.36],[235.8,-95.49],[237.43,-94.59],[238.97,-93.64],[240.43,-92.67],[241.82,-91.67],[243.13,-90.64],[244.36,-89.59],[245.54,-88.52],[246.65,-87.43],[247.7,-86.32],[248.7,-85.21],[249.66,-84.09],[250.58,-82.96],[251.47,-81.83],[252.34,-80.7],[253.2,-79.57],[254.05,-78.44],[254.9,-77.32],[255.77,-76.21],[256.65,-75.1],[257.56,-74.0],[258.5,-72.92],[259.49,-71.84],[260.52,-70.77],[261.61,-69.72],[262.76,-68.67],[263.97,-67.63],[265.25,-66.59],[266.6,-65.57],[268.02,-64.54],[269.52,-63.52],[271.09,-62.5],[272.74,-61.48],[274.45,-60.46],[276.24,-59.43],[278.09,-58.39],[280.0,-57.34],[281.97,-56.28],[283.98,-55.21],[286.04,-54.11],[288.12,-53.01],[290.23,-51.88],[292.36,-50.72],[294.48,-49.55],[296.6,-48.35],[298.7,-47.13],[300.76,-45.88],[302.78,-44.6],[304.75,-43.3],[306.65,-41.98],[308.47,-40.63],[310.2,-39.25],[311.83,-37.86],[313.34,-36.44],[314.73,-35.0]],[[319.46,-35.0],[320.73,-33.51],[321.85,-32.01],[322.83,-30.5],[323.64,-28.97],[324.29,-27.44],[324.76,-25.9],[325.05,-24.37],[325.16,-22.83],[325.09,-21.3],[324.82,-19.78],[324.37,-18.27],[323.73,-16.78],[322.91,-15.3],[321.9,-13.85],[320.72,-12.42],[319.36,-11.01],[317.83,-9.64],[316.14,-8.29],[314.3,-6.98],[312.31,-5.71],[310.19,-4.47],[307.95,-3.27],[305.59,-2.11],[303.13,-0.98],[300.58,0.1],[297.95,1.15],[295.26,2.16],[292.51,3.14],[289.72,4.08],[286.91,4.99],[284.07,5.86],[281.23,6.71],[278.4,7.53],[275.58,8.33],[272.78,9.1],[270.03,9.86],[267.31,10.6],[264.65,11.33],[262.04,12.06],[259.5,12.78],[257.03,13.49],[254.63,14.21],[252.31,14.93],[250.06,15.65],[247.9,16.39],[245.81,17.14],[243.8,17.9],[241.87,18.68],[240.02,19.47],[238.23,20.29],[236.51,21.12],[234.86,21.97],[233.25,22.84],[231.7,23.73],[230.2,24.64],[228.73,25.57],[227.29,26.51],[225.87,27.47],[224.47,28.45],[223.08,29.43],[221.69,30.42],[220.29,31.41],[218.87,32.41],[217.44,33.4],[215.98,34.39],[214.48,35.37],[212.95,36.34],[211.37,37.29],[209.75,38.22],[208.07,39.13],[206.34,40.0],[204.55,40.85],[202.71,41.66],[200.8,42.44],[198.83,43.17],[196.81,43.86],[194.72,44.5],[192.58,45.1],[190.38,45.65],[188.13,46.14],[185.83,46.59],[183.49,46.98],[181.11,47.33],[178.69,47.62],[176.24,47.87],[173.76,48.06],[171.26,48.22],[168.75,48.32],[166.23,48.39],[163.7,48.42],[161.16,48.42],[158.64,48.39],[156.12,48.34],[153.61,48.26],[151.13,48.17],[148.66,48.07],[146.21,47.96],[143.79,47.86],[141.4,47.75],[139.03,47.66],[136.69,47.58],[134.39,47.53],[132.11,47.49],[129.86,47.49],[127.63,47.52],[125.43,47.59],[123.25,47.7],[121.09,47.86],[118.94,48.06],[116.8,48.31],[114.67,48.61],[112.54,48.97],[110.41,49.37],[108.27,49.84],[106.12,50.35],[103.95,50.92],[101.76,51.54],[99.54,52.2],[97.29,52.91],[95.0,53.67],[92.67,54.46],[90.3,55.29],[87.88,56.15],[85.41,57.03],[82.89,57.94],[80.32,58.86],[77.69,59.78],[75.0,60.71],[72.26,61.64],[69.47,62.56],[66.62,63.46],[63.72,64.33],[60.78,65.18],[57.79,65.99],[54.76,66.76],[51.69,67.48],[48.6,68.15],[45.48,68.76],[42.34,69.31],[39.18,69.79],[36.02,70.19],[32.86,70.52],[29.71,70.77],[26.57,70.94],[23.45,71.02],[20.36,71.02],[17.31,70.93],[14.3,70.76],[11.33,70.49],[8.42,70.15],[5.57,69.71],[2.78,69.19],[0.06,68.59],[-2.59,67.92],[-5.16,67.16],[-7.65,66.34],[-10.06,65.44],[-12.38,64.49],[-14.63,63.47],[-16.79,62.4],[-18.87,61.28],[-20.87,60.12],[-22.8,58.91],[-24.64,57.68],[-26.42,56.41],[-28.13,55.12],[-29.77,53.81],[-31.36,52.49],[-32.9,51.16],[-34.38,49.82],[-35.83,48.48],[-37.25,47.15],[-38.64,45.83],[-40.0,44.51],[-41.36,43.21],[-42.7,41.93],[-44.04,40.66],[-45.39,39.42],[-46.74,38.19],[-48.11,36.99],[-49.5,35.81],[-50.91,34.65],[-52.35,33.52],[-53.81,32.4],[-55.31,31.31],[-56.84,30.23],[-58.4,29.18],[-59.99,28.14],[-61.62,27.11],[-63.27,26.09],[-64.94,25.08],[-66.64,24.08],[-68.36,23.08],[-70.09,22.08],[-71.83,21.07],[-73.57,20.07],[-75.3,19.05],[-77.02,18.03],[-78.72,16.99],[-80.39,15.94],[-82.01,14.87],[-83.6,13.78],[-85.12,12.67],[-86.58,11.54],[-87.97,10.39],[-89.28,9.21],[-90.5,8.02],[-91.62,6.8],[-92.63,5.55],[-93.53,4.28],[-94.32,2.99],[-94.98,1.68],[-95.52,0.36],[-95.92,-0.99],[-96.19,-2.35],[-96.32,-3.73],[-96.32,-5.12],[-96.18,-6.51],[-95.9,-7.92],[-95.49,-9.32],[-94.95,-10.73],[-94.29,-12.14],[-93.5,-13.54],[-92.6,-14.94],[-91.59,-16.33],[-90.48,-17.71],[-89.28,-19.07],[-88.0,-20.42],[-86.65,-21.75],[-85.24,-23.06],[-83.77,-24.36],[-82.28,-25.63],[-80.75,-26.88],[-79.21,-28.1],[-77.67,-29.31],[-76.15,-30.49],[-74.64,-31.65],[-73.17,-32.78],[-71.74,-33.9],[-70.37,-35.0],[-69.07,-36.08],[-67.84,-37.15],[-66.7,-38.2],[-65.66,-39.24],[-64.71,-40.27],[-63.87,-41.29],[-63.15,-42.31],[-62.54,-43.33],[-62.04,-44.35],[-61.67,-45.38],[-61.43,-46.41],[-61.3,-47.45],[-61.29,-48.51],[-61.4,-49.58],[-61.63,-50.67],[-61.96,-51.78],[-62.39,-52.92],[-62.92,-54.07],[-63.54,-55.25],[-64.24,-56.46],[-65.01,-57.7],[-65.83,-58.96],[-66.71,-60.26],[-67.62,-61.58],[-68.56,-62.93],[-69.52,-64.31],[-70.48,-65.71],[-71.43,-67.14],[-72.36,-68.59],[-73.25,-70.06],[-74.1,-71.55],[-74.9,-73.05],[-75.63,-74.57],[-76.28,-76.1],[-76.85,-77.63],[-77.32,-79.17],[-77.69,-80.7],[-77.94,-82.24],[-78.09,-83.76],[-78.1,-85.27],[-78.0,-86.77],[-77.76,-88.25],[-77.39,-89.71],[-76.88,-91.15],[-76.24,-92.56],[-75.46,-93.93],[-74.55,-95.28],[-73.51,-96.59],[-72.34,-97.86],[-71.04,-99.09],[-69.63,-100.29],[-68.1,-101.44],[-66.47,-102.55],[-64.73,-103.62],[-62.89,-104.65],[-60.97,-105.65],[-58.97,-106.6],[-56.9,-107.51],[-54.76,-108.39],[-52.57,-109.23],[-50.33,-110.05],[-48.06,-110.83],[-45.74,-111.59],[-43.41,-112.33],[-41.06,-113.04],[-38.69,-113.74],[-36.32,-114.43],[-33.96,-115.11],[-31.59,-115.78],[-29.24,-116.45],[-26.91,-117.12],[-24.59,-117.8],[-22.28,-118.48],[-20.0,-119.17],[-17.75,-119.88],[-15.51,-120.6],[-13.3,-121.34],[-11.11,-122.1],[-8.94,-122.88],[-6.78,-123.68],[-4.65,-124.51],[-2.52,-125.35],[-0.4,-126.22],[1.71,-127.1],[3.82,-128.01],[5.93,-128.93],[8.06,-129.87],[10.19,-130.82],[12.34,-131.78],[14.51,-132.75],[16.71,-133.71],[18.93,-134.68],[21.19,-135.64],[23.49,-136.59],[25.82,-137.52],[28.19,-138.43],[30.61,-139.31],[33.07,-140.17],[35.58,-140.98],[38.13,-141.76],[40.74,-142.48],[43.38,-143.15],[46.07,-143.77],[48.81,-144.32],[51.58,-144.81],[54.39,-145.22],[57.23,-145.56],[60.1,-145.83],[63.0,-146.01],[65.92,-146.11],[68.85,-146.13],[71.8,-146.06],[74.74,-145.9],[77.69,-145.66],[80.62,-145.33],[83.55,-144.91],[86.45,-144.41],[89.33,-143.83],[92.19,-143.17],[95.0,-142.43],[97.77,-141.62],[100.5,-140.74],[103.19,-139.8],[105.81,-138.8],[108.39,-137.74],[110.9,-136.64],[113.36,-135.49],[115.75,-134.31],[118.08,-133.1],[120.35,-131.86],[122.56,-130.61],[124.71,-129.35],[126.8,-128.08],[128.83,-126.82],[130.81,-125.57],[132.75,-124.33],[134.63,-123.11],[136.48,-121.92],[138.3,-120.76],[140.08,-119.63],[141.84,-118.54],[143.58,-117.5],[145.31,-116.51],[147.04,-115.56],[148.76,-114.67],[150.49,-113.83],[152.24,-113.04],[154.0,-112.32],[155.79,-111.64],[157.6,-111.03],[159.45,-110.46],[161.34,-109.95],[163.27,-109.49],[165.24,-109.08],[167.26,-108.71],[169.33,-108.39],[171.46,-108.1],[173.63,-107.85],[175.85,-107.62],[178.12,-107.42],[180.45,-107.25],[182.81,-107.08],[185.23,-106.93],[187.68,-106.79],[190.16,-106.64],[192.68,-106.49],[195.22,-106.33],[197.78,-106.16],[200.35,-105.97],[202.93,-105.76],[205.51,-105.52],[208.08,-105.24],[210.64,-104.94],[213.17,-104.6],[215.68,-104.22],[218.15,-103.8],[220.58,-103.34],[222.96,-102.83],[225.28,-102.27],[227.54,-101.67],[229.74,-101.03],[231.86,-100.33],[233.91,-99.59],[235.89,-98.81],[237.78,-97.99],[239.59,-97.12],[241.32,-96.22],[242.97,-95.27],[244.53,-94.3],[246.01,-93.29],[247.41,-92.25],[248.74,-91.19],[249.99,-90.1],[251.18,-88.99],[252.3,-87.87],[253.37,-86.74],[254.39,-85.59],[255.37,-84.43],[256.31,-83.27],[257.22,-82.11],[258.11,-80.95],[259.0,-79.79],[259.88,-78.64],[260.76,-77.49],[261.66,-76.34],[262.58,-75.21],[263.53,-74.08],[264.51,-72.97],[265.55,-71.86],[266.63,-70.76],[267.76,-69.67],[268.96,-68.59],[270.22,-67.52],[271.55,-66.45],[272.96,-65.39],[274.43,-64.33],[275.98,-63.27],[277.6,-62.21],[279.29,-61.15],[281.06,-60.08],[282.89,-59.0],[284.78,-57.92],[286.72,-56.82],[288.72,-55.71],[290.75,-54.59],[292.83,-53.44],[294.92,-52.28],[297.03,-51.1],[299.15,-49.89],[301.26,-48.66],[303.36,-47.41],[305.42,-46.13],[307.45,-44.82],[309.42,-43.49],[311.32,-42.13],[313.15,-40.75],[314.89,-39.35],[316.53,-37.92],[318.06,-36.47],[319.46,-35.0]],[[324.11,-35.0],[325.39,-33.48],[326.53,-31.95],[327.51,-30.4],[328.33,-28.85],[328.99,-27.29],[329.47,-25.72],[329.77,-24.15],[329.88,-22.58],[329.81,-21.02],[329.54,-19.47],[329.09,-17.93],[328.44,-16.4],[327.6,-14.89],[326.58,-13.41],[325.37,-11.95],[323.99,-10.52],[322.43,-9.11],[320.7,-7.74],[318.82,-6.41],[316.79,-5.11],[314.61,-3.84],[312.31,-2.62],[309.89,-1.43],[307.37,-0.29],[304.75,0.82],[302.04,1.88],[299.27,2.91],[296.44,3.9],[293.56,4.85],[290.65,5.77],[287.73,6.65],[284.79,7.51],[281.85,8.33],[278.93,9.13],[276.04,9.91],[273.18,10.67],[270.36,11.41],[267.6,12.14],[264.89,12.86],[262.25,13.57],[259.68,14.28],[257.19,15.0],[254.77,15.71],[252.44,16.43],[250.19,17.16],[248.02,17.9],[245.94,18.66],[243.93,19.43],[242.01,20.22],[240.16,21.03],[238.39,21.86],[236.68,22.71],[235.03,23.58],[233.44,24.48],[231.9,25.39],[230.4,26.33],[228.94,27.28],[227.5,28.25],[226.09,29.24],[224.68,30.24],[223.29,31.24],[221.89,32.26],[220.47,33.28],[219.05,34.3],[217.59,35.32],[216.11,36.33],[214.59,37.33],[213.03,38.32],[211.42,39.29],[209.76,40.23],[208.05,41.15],[206.28,42.05],[204.45,42.9],[202.56,43.72],[200.61,44.51],[198.6,45.25],[196.52,45.94],[194.39,46.59],[192.2,47.19],[189.96,47.74],[187.66,48.23],[185.32,48.68],[182.93,49.07],[180.5,49.41],[178.04,49.71],[175.55,49.95],[173.03,50.15],[170.5,50.3],[167.95,50.41],[165.39,50.48],[162.82,50.52],[160.26,50.52],[157.7,50.5],[155.15,50.45],[152.62,50.39],[150.1,50.31],[147.61,50.22],[145.13,50.14],[142.68,50.05],[140.26,49.97],[137.87,49.91],[135.5,49.86],[133.16,49.84],[130.85,49.84],[128.56,49.88],[126.3,49.95],[124.06,50.06],[121.83,50.21],[119.62,50.41],[117.42,50.66],[115.23,50.96],[113.03,51.31],[110.84,51.72],[108.64,52.18],[106.43,52.69],[104.19,53.25],[101.94,53.87],[99.66,54.53],[97.35,55.25],[95.0,56.0],[92.61,56.8],[90.18,57.63],[87.7,58.49],[85.17,59.38],[82.58,60.29],[79.95,61.22],[77.25,62.15],[74.5,63.09],[71.7,64.03],[68.84,64.96],[65.92,65.88],[62.96,66.77],[59.94,67.63],[56.88,68.46],[53.78,69.24],[50.64,69.98],[47.47,70.67],[44.27,71.29],[41.05,71.86],[37.82,72.35],[34.58,72.77],[31.34,73.11],[28.1,73.38],[24.88,73.55],[21.68,73.65],[18.51,73.65],[15.38,73.57],[12.28,73.4],[9.24,73.13],[6.25,72.78],[3.32,72.34],[0.46,71.82],[-2.33,71.21],[-5.05,70.51],[-7.68,69.74],[-10.24,68.9],[-12.71,67.98],[-15.09,67.0],[-17.39,65.95],[-19.6,64.84],[-21.72,63.69],[-23.76,62.48],[-25.71,61.24],[-27.59,59.96],[-29.38,58.64],[-31.11,57.3],[-32.77,55.94],[-34.36,54.56],[-35.9,53.18],[-37.38,51.79],[-38.83,50.39],[-40.23,49.0],[-41.6,47.62],[-42.94,46.25],[-44.27,44.89],[-45.59,43.54],[-46.9,42.22],[-48.21,40.91],[-49.53,39.63],[-50.86,38.37],[-52.21,37.14],[-53.58,35.92],[-54.97,34.74],[-56.4,33.57],[-57.85,32.43],[-59.34,31.31],[-60.86,30.21],[-62.42,29.12],[-64.01,28.05],[-65.63,27.0],[-67.27,25.96],[-68.95,24.92],[-70.65,23.89],[-72.36,22.86],[-74.08,21.83],[-75.81,20.8],[-77.54,19.76],[-79.26,18.72],[-80.97,17.66],[-82.64,16.59],[-84.29,15.51],[-85.89,14.41],[-87.44,13.28],[-88.93,12.14],[-90.36,10.98],[-91.7,9.8],[-92.96,8.59],[-94.13,7.36],[-95.19,6.1],[-96.15,4.83],[-96.99,3.53],[-97.71,2.21],[-98.3,0.87],[-98.76,-0.48],[-99.09,-1.86],[-99.29,-3.25],[-99.34,-4.64],[-99.26,-6.05],[-99.05,-7.47],[-98.69,-8.89],[-98.21,-10.32],[-97.6,-11.74],[-96.86,-13.16],[-96.01,-14.58],[-95.04,-15.98],[-93.97,-17.38],[-92.81,-18.77],[-91.57,-20.14],[-90.25,-21.49],[-88.86,-22.82],[-87.42,-24.14],[-85.94,-25.43],[-84.43,-26.71],[-82.9,-27.96],[-81.37,-29.19],[-79.84,-30.39],[-78.34,-31.57],[-76.86,-32.74],[-75.43,-33.88],[-74.05,-35.0],[-72.74,-36.1],[-71.5,-37.19],[-70.35,-38.27],[-69.29,-39.33],[-68.33,-40.38],[-67.47,-41.43],[-66.73,-42.48],[-66.1,-43.52],[-65.6,-44.56],[-65.22,-45.61],[-64.96,-46.67],[-64.82,-47.73],[-64.81,-48.81],[-64.92,-49.91],[-65.14,-51.02],[-65.48,-52.16],[-65.92,-53.32],[-66.46,-54.5],[-67.1,-55.71],[-67.81,-56.95],[-68.6,-58.21],[-69.46,-59.5],[-70.36,-60.83],[-71.31,-62.18],[-72.29,-63.57],[-73.28,-64.98],[-74.29,-66.42],[-75.28,-67.88],[-76.26,-69.37],[-77.2,-70.88],[-78.11,-72.41],[-78.95,-73.96],[-79.74,-75.52],[-80.44,-77.09],[-81.06,-78.68],[-81.59,-80.26],[-82.01,-81.85],[-82.32,-83.43],[-82.51,-85.01],[-82.57,-86.57],[-82.5,-88.12],[-82.3,-89.66],[-81.97,-91.17],[-81.49,-92.65],[-80.87,-94.11],[-80.12,-95.54],[-79.22,-96.94],[-78.19,-98.3],[-77.02,-99.62],[-75.72,-100.9],[-74.3,-102.14],[-72.75,-103.33],[-71.09,-104.49],[-69.33,-105.6],[-67.46,-106.67],[-65.49,-107.69],[-63.44,-108.68],[-61.32,-109.62],[-59.12,-110.52],[-56.86,-111.39],[-54.55,-112.22],[-52.19,-113.03],[-49.8,-113.8],[-47.38,-114.54],[-44.94,-115.27],[-42.48,-115.97],[-40.01,-116.66],[-37.55,-117.34],[-35.08,-118.0],[-32.63,-118.67],[-30.18,-119.33],[-27.76,-119.99],[-25.35,-120.66],[-22.96,-121.34],[-20.6,-122.03],[-18.26,-122.73],[-15.94,-123.45],[-13.65,-124.19],[-11.38,-124.94],[-9.12,-125.72],[-6.89,-126.52],[-4.67,-127.34],[-2.46,-128.18],[-0.26,-129.04],[1.94,-129.93],[4.14,-130.83],[6.34,-131.74],[8.55,-132.67],[10.77,-133.62],[13.02,-134.56],[15.28,-135.52],[17.57,-136.47],[19.89,-137.41],[22.24,-138.35],[24.63,-139.27],[27.06,-140.18],[29.53,-141.06],[32.05,-141.91],[34.61,-142.72],[37.21,-143.49],[39.86,-144.22],[42.55,-144.89],[45.29,-145.51],[48.07,-146.07],[50.88,-146.57],[53.74,-146.99],[56.63,-147.34],[59.54,-147.61],[62.49,-147.8],[65.45,-147.91],[68.43,-147.94],[71.41,-147.88],[74.41,-147.73],[77.4,-147.49],[80.38,-147.17],[83.36,-146.76],[86.31,-146.27],[89.24,-145.69],[92.14,-145.03],[95.0,-144.29],[97.82,-143.48],[100.6,-142.59],[103.33,-141.65],[106.01,-140.64],[108.63,-139.57],[111.19,-138.46],[113.69,-137.3],[116.12,-136.1],[118.5,-134.87],[120.81,-133.61],[123.06,-132.34],[125.24,-131.06],[127.37,-129.77],[129.44,-128.48],[131.46,-127.2],[133.42,-125.93],[135.34,-124.68],[137.22,-123.46],[139.06,-122.27],[140.87,-121.11],[142.66,-120.0],[144.42,-118.93],[146.18,-117.91],[147.92,-116.93],[149.67,-116.01],[151.42,-115.15],[153.19,-114.34],[154.97,-113.59],[156.78,-112.9],[158.62,-112.26],[160.49,-111.68],[162.41,-111.16],[164.36,-110.69],[166.37,-110.27],[168.42,-109.89],[170.53,-109.56],[172.68,-109.27],[174.9,-109.02],[177.17,-108.8],[179.49,-108.61],[181.86,-108.44],[184.28,-108.29],[186.76,-108.15],[189.27,-108.02],[191.83,-107.89],[194.41,-107.76],[197.03,-107.62],[199.68,-107.47],[202.33,-107.3],[205.0,-107.11],[207.68,-106.9],[210.35,-106.65],[213.0,-106.37],[215.64,-106.06],[218.26,-105.7],[220.84,-105.3],[223.38,-104.86],[225.87,-104.37],[228.31,-103.84],[230.69,-103.26],[233.0,-102.62],[235.24,-101.95],[237.41,-101.22],[239.5,-100.45],[241.51,-99.63],[243.43,-98.77],[245.27,-97.87],[247.02,-96.92],[248.68,-95.94],[250.26,-94.93],[251.76,-93.88],[253.17,-92.81],[254.51,-91.71],[255.78,-90.59],[256.98,-89.44],[258.12,-88.29],[259.2,-87.11],[260.23,-85.93],[261.22,-84.75],[262.18,-83.55],[263.11,-82.36],[264.03,-81.16],[264.93,-79.97],[265.84,-78.79],[266.75,-77.61],[267.68,-76.43],[268.63,-75.27],[269.62,-74.11],[270.64,-72.96],[271.71,-71.82],[272.83,-70.69],[274.01,-69.57],[275.26,-68.45],[276.57,-67.34],[277.94,-66.24],[279.39,-65.14],[280.91,-64.04],[282.51,-62.94],[284.17,-61.84],[285.91,-60.73],[287.71,-59.62],[289.57,-58.5],[291.49,-57.37],[293.46,-56.22],[295.47,-55.06],[297.52,-53.88],[299.6,-52.69],[301.7,-51.47],[303.8,-50.23],[305.9,-48.97],[307.99,-47.68],[310.05,-46.37],[312.07,-45.03],[314.04,-43.67],[315.94,-42.28],[317.78,-40.87],[319.52,-39.44],[321.17,-37.98],[322.7,-36.5],[324.11,-35.0]],[[328.69,-35.0],[329.97,-33.45],[331.12,-31.89],[332.11,-30.31],[332.94,-28.73],[333.6,-27.13],[334.09,-25.53],[334.39,-23.93],[334.51,-22.34],[334.43,-20.74],[334.17,-19.16],[333.71,-17.59],[333.05,-16.03],[332.21,-14.5],[331.17,-12.98],[329.94,-11.49],[328.53,-10.03],[326.94,-8.6],[325.18,-7.2],[323.26,-5.84],[321.19,-4.51],[318.97,-3.23],[316.61,-1.98],[314.13,-0.77],[311.54,0.39],[308.85,1.52],[306.08,2.6],[303.23,3.64],[300.31,4.65],[297.35,5.61],[294.35,6.54],[291.33,7.43],[288.3,8.29],[285.27,9.12],[282.25,9.93],[279.26,10.71],[276.3,11.47],[273.38,12.21],[270.52,12.94],[267.71,13.65],[264.97,14.36],[262.31,15.07],[259.72,15.78],[257.21,16.48],[254.79,17.2],[252.46,17.92],[250.21,18.66],[248.05,19.41],[245.97,20.18],[243.98,20.96],[242.07,21.77],[240.24,22.6],[238.48,23.45],[236.79,24.32],[235.16,25.22],[233.58,26.13],[232.05,27.07],[230.56,28.04],[229.11,29.02],[227.68,30.02],[226.27,31.03],[224.86,32.06],[223.46,33.1],[222.06,34.14],[220.63,35.19],[219.19,36.24],[217.72,37.28],[216.22,38.31],[214.67,39.34],[213.08,40.35],[211.44,41.34],[209.75,42.3],[208.0,43.24],[206.19,44.14],[204.32,45.01],[202.39,45.85],[200.39,46.64],[198.33,47.38],[196.21,48.08],[194.03,48.74],[191.8,49.34],[189.51,49.89],[187.16,50.39],[184.77,50.83],[182.34,51.23],[179.87,51.57],[177.36,51.86],[174.83,52.11],[172.27,52.3],[169.7,52.46],[167.11,52.57],[164.51,52.64],[161.91,52.68],[159.31,52.69],[156.72,52.68],[154.14,52.65],[151.58,52.59],[149.03,52.53],[146.51,52.47],[144.0,52.4],[141.52,52.34],[139.07,52.29],[136.64,52.25],[134.24,52.23],[131.86,52.24],[129.51,52.28],[127.19,52.36],[124.88,52.47],[122.59,52.62],[120.31,52.82],[118.05,53.07],[115.79,53.37],[113.54,53.71],[111.28,54.11],[109.01,54.57],[106.74,55.08],[104.44,55.63],[102.13,56.25],[99.78,56.91],[97.41,57.62],[95.0,58.37],[92.55,59.16],[90.05,59.99],[87.51,60.86],[84.92,61.75],[82.27,62.67],[79.57,63.6],[76.82,64.54],[74.0,65.49],[71.13,66.44],[68.21,67.38],[65.22,68.3],[62.19,69.21],[59.1,70.08],[55.97,70.92],[52.8,71.72],[49.58,72.48],[46.34,73.18],[43.06,73.82],[39.77,74.4],[36.46,74.9],[33.14,75.34],[29.82,75.69],[26.5,75.97],[23.2,76.16],[19.92,76.26],[16.67,76.27],[13.45,76.19],[10.28,76.02],[7.16,75.76],[4.09,75.4],[1.09,74.96],[-1.85,74.42],[-4.71,73.8],[-7.49,73.09],[-10.2,72.3],[-12.81,71.44],[-15.34,70.5],[-17.78,69.49],[-20.13,68.41],[-22.38,67.27],[-24.55,66.08],[-26.62,64.84],[-28.61,63.55],[-30.51,62.22],[-32.33,60.86],[-34.07,59.47],[-35.74,58.06],[-37.34,56.63],[-38.88,55.19],[-40.36,53.74],[-41.79,52.29],[-43.18,50.84],[-44.54,49.39],[-45.86,47.96],[-47.16,46.54],[-48.44,45.14],[-49.72,43.75],[-51.0,42.39],[-52.28,41.05],[-53.57,39.73],[-54.87,38.44],[-56.2,37.18],[-57.55,35.94],[-58.93,34.72],[-60.34,33.53],[-61.79,32.36],[-63.27,31.22],[-64.79,30.09],[-66.34,28.98],[-67.93,27.89],[-69.54,26.81],[-71.19,25.74],[-72.86,24.68],[-74.56,23.62],[-76.27,22.57],[-77.99,21.51],[-79.71,20.45],[-81.43,19.39],[-83.14,18.31],[-84.83,17.23],[-86.49,16.13],[-88.11,15.01],[-89.68,13.88],[-91.21,12.73],[-92.66,11.55],[-94.05,10.36],[-95.35,9.14],[-96.57,7.9],[-97.68,6.64],[-98.69,5.36],[-99.59,4.05],[-100.37,2.72],[-101.02,1.38],[-101.55,0.01],[-101.94,-1.37],[-102.2,-2.77],[-102.32,-4.18],[-102.31,-5.6],[-102.15,-7.03],[-101.87,-8.47],[-101.44,-9.9],[-100.89,-11.34],[-100.21,-12.78],[-99.41,-14.21],[-98.5,-15.64],[-97.48,-17.06],[-96.36,-18.46],[-95.15,-19.85],[-93.87,-21.22],[-92.51,-22.58],[-91.1,-23.92],[-89.65,-25.24],[-88.16,-26.53],[-86.64,-27.81],[-85.12,-29.06],[-83.61,-30.29],[-82.1,-31.5],[-80.63,-32.69],[-79.2,-33.85],[-77.81,-35.0],[-76.49,-36.13],[-75.24,-37.24],[-74.08,-38.34],[-73.0,-39.43],[-72.03,-40.51],[-71.16,-41.58],[-70.4,-42.65],[-69.77,-43.71],[-69.25,-44.78],[-68.85,-45.85],[-68.58,-46.93],[-68.44,-48.02],[-68.42,-49.13],[-68.53,-50.25],[-68.75,-51.38],[-69.09,-52.54],[-69.53,-53.73],[-70.09,-54.94],[-70.73,-56.17],[-71.46,-57.44],[-72.27,-58.73],[-73.15,-60.05],[-74.08,-61.41],[-75.06,-62.8],[-76.07,-64.21],[-77.11,-65.66],[-78.15,-67.13],[-79.19,-68.63],[-80.21,-70.16],[-81.2,-71.71],[-82.15,-73.29],[-83.05,-74.88],[-83.89,-76.48],[-84.65,-78.1],[-85.32,-79.73],[-85.9,-81.36],[-86.37,-83.0],[-86.72,-84.63],[-86.96,-86.26],[-87.07,-87.88],[-87.04,-89.48],[-86.88,-91.07],[-86.58,-92.63],[-86.13,-94.17],[-85.54,-95.68],[-84.8,-97.16],[-83.92,-98.61],[-82.89,-100.01],[-81.73,-101.38],[-80.43,-102.71],[-78.99,-104.0],[-77.43,-105.24],[-75.75,-106.43],[-73.95,-107.59],[-72.04,-108.69],[-70.04,-109.75],[-67.94,-110.77],[-65.76,-111.74],[-63.5,-112.67],[-61.17,-113.56],[-58.79,-114.41],[-56.35,-115.23],[-53.88,-116.02],[-51.37,-116.77],[-48.83,-117.5],[-46.28,-118.21],[-43.72,-118.9],[-41.15,-119.57],[-38.58,-120.24],[-36.02,-120.89],[-33.47,-121.54],[-30.93,-122.19],[-28.42,-122.85],[-25.92,-123.51],[-23.45,-124.18],[-21.0,-124.86],[-18.58,-125.55],[-16.18,-126.27],[-13.81,-127.0],[-11.45,-127.75],[-9.12,-128.52],[-6.8,-129.32],[-4.5,-130.13],[-2.21,-130.97],[0.08,-131.82],[2.36,-132.7],[4.64,-133.59],[6.93,-134.5],[9.23,-135.42],[11.55,-136.35],[13.88,-137.28],[16.24,-138.22],[18.62,-139.15],[21.03,-140.07],[23.48,-140.98],[25.96,-141.88],[28.49,-142.75],[31.05,-143.59],[33.66,-144.41],[36.31,-145.18],[39.01,-145.9],[41.75,-146.58],[44.53,-147.21],[47.35,-147.77],[50.21,-148.27],[53.11,-148.7],[56.04,-149.06],[59.0,-149.34],[61.98,-149.54],[64.99,-149.66],[68.01,-149.7],[71.05,-149.65],[74.08,-149.51],[77.12,-149.28],[80.15,-148.97],[83.17,-148.57],[86.17,-148.08],[89.14,-147.5],[92.09,-146.85],[95.0,-146.11],[97.87,-145.3],[100.7,-144.42],[103.47,-143.47],[106.19,-142.45],[108.86,-141.38],[111.47,-140.25],[114.01,-139.08],[116.49,-137.87],[118.91,-136.63],[121.26,-135.35],[123.55,-134.06],[125.78,-132.76],[127.95,-131.45],[130.05,-130.13],[132.1,-128.83],[134.1,-127.54],[136.05,-126.26],[137.96,-125.01],[139.83,-123.79],[141.67,-122.61],[143.48,-121.47],[145.27,-120.37],[147.05,-119.32],[148.82,-118.32],[150.59,-117.37],[152.36,-116.48],[154.15,-115.65],[155.96,-114.88],[157.79,-114.17],[159.65,-113.52],[161.55,-112.92],[163.49,-112.38],[165.47,-111.9],[167.51,-111.47],[169.59,-111.09],[171.73,-110.76],[173.93,-110.47],[176.19,-110.22],[178.5,-110.0],[180.87,-109.81],[183.29,-109.65],[185.77,-109.51],[188.31,-109.39],[190.89,-109.27],[193.51,-109.16],[196.17,-109.05],[198.87,-108.93],[201.59,-108.8],[204.34,-108.65],[207.1,-108.49],[209.87,-108.3],[212.64,-108.07],[215.4,-107.82],[218.14,-107.53],[220.86,-107.2],[223.56,-106.82],[226.21,-106.4],[228.82,-105.94],[231.37,-105.42],[233.87,-104.86],[236.3,-104.24],[238.66,-103.58],[240.95,-102.87],[243.16,-102.1],[245.28,-101.29],[247.31,-100.44],[249.26,-99.54],[251.12,-98.6],[252.89,-97.61],[254.57,-96.59],[256.17,-95.54],[257.67,-94.45],[259.1,-93.34],[260.45,-92.2],[261.72,-91.04],[262.93,-89.86],[264.08,-88.66],[265.17,-87.46],[266.21,-86.24],[267.21,-85.02],[268.18,-83.79],[269.13,-82.56],[270.06,-81.33],[270.99,-80.11],[271.91,-78.89],[272.85,-77.67],[273.81,-76.47],[274.79,-75.27],[275.81,-74.08],[276.87,-72.89],[277.97,-71.72],[279.13,-70.56],[280.35,-69.4],[281.64,-68.25],[282.98,-67.1],[284.4,-65.96],[285.89,-64.82],[287.45,-63.68],[289.08,-62.53],[290.78,-61.39],[292.55,-60.24],[294.38,-59.08],[296.27,-57.91],[298.21,-56.73],[300.19,-55.53],[302.22,-54.32],[304.27,-53.09],[306.34,-51.84],[308.43,-50.57],[310.51,-49.27],[312.58,-47.95],[314.63,-46.61],[316.64,-45.24],[318.6,-43.85],[320.51,-42.44],[322.34,-40.99],[324.08,-39.53],[325.73,-38.04],[327.27,-36.53],[328.69,-35.0]],[[333.18,-35.0],[334.47,-33.42],[335.62,-31.83],[336.61,-30.22],[337.45,-28.61],[338.12,-26.98],[338.61,-25.36],[338.92,-23.73],[339.04,-22.1],[338.97,-20.47],[338.7,-18.86],[338.23,-17.26],[337.57,-15.67],[336.72,-14.11],[335.66,-12.56],[334.42,-11.04],[332.99,-9.55],[331.37,-8.1],[329.58,-6.67],[327.62,-5.28],[325.51,-3.93],[323.24,-2.62],[320.84,-1.35],[318.3,-0.12],[315.65,1.06],[312.9,2.21],[310.05,3.31],[307.13,4.37],[304.13,5.38],[301.09,6.36],[298.01,7.3],[294.9,8.2],[291.77,9.07],[288.65,9.91],[285.54,10.72],[282.44,11.5],[279.39,12.26],[276.37,13.0],[273.41,13.73],[270.5,14.44],[267.67,15.15],[264.91,15.85],[262.23,16.55],[259.63,17.25],[257.12,17.96],[254.7,18.68],[252.37,19.41],[250.14,20.15],[247.99,20.91],[245.93,21.7],[243.96,22.5],[242.07,23.32],[240.26,24.17],[238.52,25.05],[236.85,25.94],[235.24,26.87],[233.68,27.81],[232.17,28.78],[230.7,29.78],[229.25,30.79],[227.83,31.82],[226.43,32.87],[225.03,33.92],[223.62,34.99],[222.21,36.07],[220.78,37.14],[219.32,38.22],[217.83,39.29],[216.3,40.35],[214.74,41.4],[213.12,42.43],[211.45,43.44],[209.72,44.43],[207.93,45.38],[206.08,46.3],[204.17,47.19],[202.19,48.03],[200.15,48.83],[198.04,49.59],[195.88,50.29],[193.65,50.95],[191.36,51.56],[189.02,52.11],[186.63,52.61],[184.2,53.06],[181.72,53.45],[179.2,53.8],[176.65,54.09],[174.07,54.34],[171.47,54.54],[168.85,54.69],[166.23,54.81],[163.59,54.89],[160.96,54.93],[158.32,54.95],[155.7,54.95],[153.09,54.93],[150.49,54.89],[147.91,54.85],[145.35,54.8],[142.81,54.75],[140.3,54.72],[137.81,54.69],[135.34,54.69],[132.9,54.7],[130.49,54.75],[128.09,54.82],[125.72,54.94],[123.37,55.09],[121.02,55.29],[118.69,55.53],[116.37,55.82],[114.05,56.16],[111.72,56.56],[109.39,57.01],[107.05,57.51],[104.7,58.06],[102.32,58.67],[99.91,59.32],[97.47,60.03],[95.0,60.77],[92.49,61.56],[89.93,62.39],[87.33,63.26],[84.67,64.15],[81.96,65.07],[79.2,66.0],[76.38,66.95],[73.5,67.9],[70.56,68.86],[67.57,69.8],[64.52,70.74],[61.42,71.65],[58.27,72.54],[55.06,73.39],[51.82,74.2],[48.53,74.97],[45.21,75.68],[41.86,76.34],[38.49,76.93],[35.1,77.45],[31.71,77.89],[28.31,78.26],[24.91,78.54],[21.53,78.74],[18.17,78.85],[14.84,78.87],[11.55,78.79],[8.3,78.62],[5.09,78.36],[1.95,78.0],[-1.13,77.55],[-4.14,77.01],[-7.07,76.37],[-9.92,75.65],[-12.69,74.85],[-15.37,73.96],[-17.95,72.99],[-20.45,71.96],[-22.84,70.85],[-25.15,69.68],[-27.35,68.45],[-29.46,67.17],[-31.48,65.84],[-33.41,64.47],[-35.25,63.06],[-37.01,61.62],[-38.69,60.16],[-40.3,58.68],[-41.84,57.18],[-43.31,55.67],[-44.74,54.17],[-46.11,52.66],[-47.45,51.15],[-48.74,49.66],[-50.02,48.18],[-51.27,46.72],[-52.52,45.27],[-53.75,43.85],[-54.99,42.45],[-56.24,41.08],[-57.5,39.73],[-58.79,38.41],[-60.09,37.12],[-61.43,35.85],[-62.79,34.61],[-64.19,33.39],[-65.63,32.2],[-67.11,31.03],[-68.62,29.88],[-70.17,28.75],[-71.75,27.64],[-73.37,26.54],[-75.02,25.44],[-76.69,24.36],[-78.39,23.28],[-80.09,22.2],[-81.81,21.12],[-83.53,20.03],[-85.24,18.94],[-86.93,17.84],[-88.61,16.72],[-90.25,15.6],[-91.85,14.45],[-93.41,13.29],[-94.9,12.11],[-96.32,10.9],[-97.67,9.68],[-98.93,8.43],[-100.1,7.17],[-101.17,5.87],[-102.13,4.56],[-102.97,3.23],[-103.69,1.87],[-104.28,0.5],[-104.74,-0.89],[-105.07,-2.3],[-105.26,-3.72],[-105.32,-5.15],[-105.23,-6.59],[-105.01,-8.04],[-104.66,-9.49],[-104.17,-10.95],[-103.55,-12.4],[-102.81,-13.85],[-101.96,-15.29],[-100.99,-16.73],[-99.92,-18.15],[-98.76,-19.56],[-97.52,-20.96],[-96.2,-22.34],[-94.83,-23.7],[-93.4,-25.04],[-91.93,-26.36],[-90.44,-27.66],[-88.94,-28.94],[-87.43,-30.19],[-85.94,-31.42],[-84.47,-32.64],[-83.04,-33.83],[-81.65,-35.0],[-80.33,-36.15],[-79.07,-37.29],[-77.9,-38.42],[-76.81,-39.53],[-75.83,-40.63],[-74.95,-41.73],[-74.18,-42.82],[-73.52,-43.91],[-72.99,-45.0],[-72.59,-46.1],[-72.31,-47.2],[-72.15,-48.32],[-72.13,-49.45],[-72.22,-50.59],[-72.44,-51.75],[-72.78,-52.94],[-73.23,-54.15],[-73.79,-55.38],[-74.44,-56.65],[-75.19,-57.94],[-76.02,-59.26],[-76.91,-60.62],[-77.87,-62.0],[-78.88,-63.42],[-79.92,-64.87],[-80.99,-66.35],[-82.07,-67.86],[-83.15,-69.4],[-84.21,-70.97],[-85.25,-72.56],[-86.25,-74.17],[-87.19,-75.8],[-88.08,-77.46],[-88.89,-79.12],[-89.61,-80.8],[-90.23,-82.48],[-90.75,-84.16],[-91.16,-85.84],[-91.44,-87.52],[-91.59,-89.19],[-91.6,-90.84],[-91.48,-92.48],[-91.21,-94.1],[-90.79,-95.69],[-90.22,-97.25],[-89.5,-98.79],[-88.63,-100.28],[-87.62,-101.74],[-86.45,-103.16],[-85.15,-104.53],[-83.7,-105.87],[-82.12,-107.15],[-80.42,-108.39],[-78.59,-109.58],[-76.65,-110.72],[-74.6,-111.82],[-72.45,-112.86],[-70.21,-113.86],[-67.89,-114.82],[-65.5,-115.74],[-63.04,-116.61],[-60.53,-117.44],[-57.97,-118.24],[-55.37,-119.01],[-52.74,-119.74],[-50.09,-120.46],[-47.43,-121.15],[-44.76,-121.82],[-42.09,-122.47],[-39.42,-123.12],[-36.76,-123.76],[-34.11,-124.39],[-31.49,-125.03],[-28.88,-125.67],[-26.3,-126.32],[-23.74,-126.98],[-21.21,-127.65],[-18.71,-128.34],[-16.22,-129.04],[-13.77,-129.77],[-11.33,-130.51],[-8.92,-131.28],[-6.52,-132.06],[-4.13,-132.87],[-1.76,-133.7],[0.61,-134.55],[2.97,-135.41],[5.34,-136.3],[7.72,-137.19],[10.11,-138.1],[12.51,-139.01],[14.93,-139.93],[17.38,-140.84],[19.85,-141.75],[22.36,-142.65],[24.9,-143.53],[27.47,-144.4],[30.09,-145.23],[32.74,-146.04],[35.44,-146.81],[38.18,-147.54],[40.97,-148.22],[43.79,-148.84],[46.66,-149.41],[49.56,-149.92],[52.5,-150.36],[55.47,-150.72],[58.47,-151.02],[61.5,-151.23],[64.55,-151.36],[67.61,-151.41],[70.69,-151.37],[73.77,-151.24],[76.85,-151.02],[79.92,-150.72],[82.98,-150.33],[86.03,-149.85],[89.05,-149.28],[92.04,-148.63],[95.0,-147.9],[97.92,-147.09],[100.79,-146.21],[103.61,-145.26],[106.38,-144.24],[109.09,-143.16],[111.75,-142.03],[114.34,-140.85],[116.86,-139.63],[119.32,-138.37],[121.72,-137.09],[124.05,-135.78],[126.31,-134.45],[128.52,-133.12],[130.66,-131.79],[132.75,-130.46],[134.78,-129.15],[136.76,-127.85],[138.7,-126.57],[140.6,-125.33],[142.47,-124.12],[144.31,-122.95],[146.13,-121.82],[147.93,-120.75],[149.72,-119.72],[151.52,-118.75],[153.32,-117.84],[155.13,-116.99],[156.96,-116.19],[158.81,-115.46],[160.7,-114.79],[162.63,-114.18],[164.59,-113.63],[166.61,-113.13],[168.67,-112.69],[170.79,-112.31],[172.96,-111.97],[175.2,-111.68],[177.5,-111.43],[179.85,-111.22],[182.27,-111.04],[184.75,-110.88],[187.29,-110.75],[189.88,-110.64],[192.52,-110.54],[195.22,-110.45],[197.95,-110.35],[200.73,-110.25],[203.53,-110.15],[206.37,-110.02],[209.22,-109.88],[212.08,-109.71],[214.95,-109.51],[217.82,-109.28],[220.67,-109.01],[223.5,-108.71],[226.3,-108.36],[229.07,-107.96],[231.8,-107.51],[234.47,-107.02],[237.09,-106.48],[239.64,-105.88],[242.12,-105.23],[244.53,-104.53],[246.85,-103.78],[249.09,-102.98],[251.25,-102.13],[253.31,-101.23],[255.28,-100.29],[257.16,-99.3],[258.94,-98.28],[260.63,-97.22],[262.23,-96.12],[263.75,-94.99],[265.18,-93.84],[266.54,-92.66],[267.82,-91.45],[269.03,-90.23],[270.18,-89.0],[271.27,-87.75],[272.32,-86.5],[273.33,-85.24],[274.31,-83.97],[275.27,-82.71],[276.21,-81.45],[277.15,-80.19],[278.1,-78.93],[279.06,-77.68],[280.04,-76.44],[281.04,-75.21],[282.09,-73.98],[283.18,-72.76],[284.31,-71.56],[285.51,-70.35],[286.76,-69.16],[288.07,-67.97],[289.46,-66.78],[290.91,-65.6],[292.43,-64.42],[294.02,-63.24],[295.69,-62.05],[297.41,-60.86],[299.2,-59.66],[301.05,-58.45],[302.96,-57.24],[304.91,-56.0],[306.9,-54.76],[308.92,-53.49],[310.96,-52.21],[313.02,-50.9],[315.08,-49.57],[317.13,-48.23],[319.16,-46.85],[321.16,-45.45],[323.11,-44.03],[325.01,-42.58],[326.83,-41.11],[328.57,-39.62],[330.22,-38.1],[331.76,-36.56],[333.18,-35.0]],[[337.59,-35.0],[338.88,-33.39],[340.03,-31.77],[341.03,-30.14],[341.87,-28.49],[342.54,-26.84],[343.03,-25.18],[343.34,-23.52],[343.47,-21.86],[343.4,-20.21],[343.13,-18.57],[342.66,-16.94],[341.99,-15.32],[341.13,-13.73],[340.06,-12.15],[338.8,-10.61],[337.35,-9.09],[335.71,-7.6],[333.89,-6.15],[331.9,-4.73],[329.75,-3.36],[327.44,-2.02],[324.99,-0.73],[322.4,0.52],[319.69,1.73],[316.88,2.89],[313.96,4.0],[310.97,5.08],[307.9,6.11],[304.78,7.1],[301.61,8.05],[298.42,8.96],[295.2,9.84],[291.99,10.68],[288.78,11.49],[285.6,12.28],[282.44,13.04],[279.33,13.78],[276.27,14.51],[273.27,15.22],[270.34,15.92],[267.49,16.62],[264.71,17.32],[262.03,18.01],[259.43,18.72],[256.93,19.43],[254.52,20.15],[252.21,20.89],[249.99,21.65],[247.87,22.42],[245.84,23.22],[243.89,24.04],[242.03,24.89],[240.25,25.77],[238.53,26.67],[236.89,27.59],[235.3,28.55],[233.77,29.53],[232.27,30.53],[230.82,31.55],[229.39,32.6],[227.98,33.67],[226.58,34.75],[225.18,35.84],[223.77,36.94],[222.35,38.05],[220.91,39.16],[219.44,40.26],[217.93,41.36],[216.38,42.45],[214.79,43.53],[213.14,44.58],[211.44,45.62],[209.67,46.62],[207.85,47.59],[205.95,48.53],[204.0,49.43],[201.98,50.29],[199.89,51.1],[197.73,51.86],[195.52,52.58],[193.24,53.24],[190.9,53.85],[188.51,54.41],[186.07,54.91],[183.59,55.36],[181.06,55.76],[178.49,56.1],[175.9,56.4],[173.27,56.65],[170.63,56.85],[167.97,57.01],[165.3,57.13],[162.63,57.21],[159.96,57.27],[157.28,57.3],[154.62,57.31],[151.97,57.3],[149.34,57.28],[146.72,57.25],[144.12,57.22],[141.55,57.2],[139.0,57.19],[136.47,57.19],[133.97,57.22],[131.48,57.27],[129.02,57.35],[126.58,57.46],[124.16,57.61],[121.75,57.8],[119.35,58.04],[116.96,58.33],[114.57,58.67],[112.18,59.05],[109.78,59.49],[107.38,59.99],[104.95,60.53],[102.51,61.13],[100.04,61.78],[97.54,62.47],[95.0,63.21],[92.42,64.0],[89.8,64.82],[87.14,65.68],[84.42,66.57],[81.65,67.49],[78.82,68.42],[75.94,69.37],[72.99,70.33],[69.99,71.28],[66.93,72.24],[63.82,73.17],[60.65,74.1],[57.43,74.99],[54.16,75.85],[50.84,76.68],[47.48,77.45],[44.09,78.18],[40.67,78.84],[37.22,79.44],[33.76,79.97],[30.28,80.43],[26.81,80.81],[23.34,81.1],[19.88,81.3],[16.44,81.42],[13.03,81.44],[9.66,81.37],[6.33,81.2],[3.05,80.94],[-0.17,80.58],[-3.32,80.12],[-6.4,79.57],[-9.41,78.92],[-12.33,78.19],[-15.16,77.37],[-17.9,76.46],[-20.54,75.47],[-23.09,74.41],[-25.54,73.27],[-27.89,72.07],[-30.13,70.8],[-32.28,69.48],[-34.33,68.11],[-36.29,66.7],[-38.15,65.24],[-39.93,63.75],[-41.62,62.24],[-43.23,60.7],[-44.77,59.15],[-46.24,57.59],[-47.65,56.03],[-49.01,54.46],[-50.33,52.9],[-51.6,51.34],[-52.85,49.8],[-54.07,48.28],[-55.28,46.78],[-56.48,45.3],[-57.67,43.84],[-58.88,42.41],[-60.1,41.0],[-61.33,39.63],[-62.59,38.28],[-63.88,36.96],[-65.2,35.67],[-66.55,34.41],[-67.94,33.17],[-69.38,31.96],[-70.85,30.77],[-72.36,29.6],[-73.91,28.45],[-75.49,27.31],[-77.11,26.19],[-78.76,25.07],[-80.44,23.97],[-82.13,22.86],[-83.84,21.76],[-85.55,20.66],[-87.27,19.55],[-88.97,18.43],[-90.66,17.3],[-92.32,16.16],[-93.95,15.01],[-95.53,13.83],[-97.06,12.64],[-98.53,11.43],[-99.92,10.2],[-101.24,8.95],[-102.46,7.67],[-103.58,6.38],[-104.6,5.06],[-105.51,3.72],[-106.3,2.36],[-106.96,0.98],[-107.5,-0.42],[-107.9,-1.84],[-108.17,-3.27],[-108.3,-4.71],[-108.29,-6.16],[-108.14,-7.62],[-107.85,-9.08],[-107.44,-10.55],[-106.89,-12.02],[-106.21,-13.49],[-105.42,-14.95],[-104.51,-16.4],[-103.5,-17.84],[-102.4,-19.27],[-101.2,-20.69],[-99.93,-22.09],[-98.59,-23.47],[-97.2,-24.84],[-95.76,-26.18],[-94.3,-27.51],[-92.82,-28.81],[-91.33,-30.09],[-89.85,-31.35],[-88.39,-32.58],[-86.96,-33.8],[-85.58,-35.0],[-84.26,-36.18],[-83.0,-37.34],[-81.82,-38.49],[-80.72,-39.63],[-79.72,-40.76],[-78.83,-41.88],[-78.05,-43.0],[-77.38,-44.11],[-76.84,-45.23],[-76.42,-46.35],[-76.13,-47.48],[-75.96,-48.62],[-75.93,-49.77],[-76.02,-50.94],[-76.23,-52.13],[-76.57,-53.34],[-77.02,-54.58],[-77.58,-55.84],[-78.24,-57.13],[-79.0,-58.45],[-79.84,-59.8],[-80.75,-61.19],[-81.73,-62.6],[-82.76,-64.05],[-83.83,-65.54],[-84.93,-67.05],[-86.04,-68.6],[-87.16,-70.17],[-88.26,-71.78],[-89.34,-73.41],[-90.38,-75.07],[-91.38,-76.74],[-92.31,-78.44],[-93.16,-80.15],[-93.93,-81.87],[-94.6,-83.6],[-95.17,-85.33],[-95.62,-87.06],[-95.94,-88.79],[-96.13,-90.51],[-96.19,-92.22],[-96.1,-93.91],[-95.86,-95.58],[-95.46,-97.22],[-94.92,-98.83],[-94.22,-100.42],[-93.36,-101.96],[-92.36,-103.47],[-91.19,-104.94],[-89.88,-106.36],[-88.43,-107.74],[-86.83,-109.07],[-85.1,-110.35],[-83.24,-111.58],[-81.27,-112.76],[-79.17,-113.89],[-76.98,-114.97],[-74.68,-116.0],[-72.3,-116.98],[-69.84,-117.92],[-67.31,-118.81],[-64.71,-119.66],[-62.07,-120.47],[-59.38,-121.25],[-56.66,-121.99],[-53.91,-122.71],[-51.15,-123.4],[-48.37,-124.06],[-45.6,-124.71],[-42.82,-125.35],[-40.05,-125.98],[-37.29,-126.6],[-34.56,-127.21],[-31.84,-127.83],[-29.14,-128.46],[-26.48,-129.09],[-23.83,-129.74],[-21.22,-130.4],[-18.63,-131.08],[-16.07,-131.77],[-13.53,-132.48],[-11.01,-133.22],[-8.52,-133.97],[-6.04,-134.75],[-3.58,-135.55],[-1.12,-136.37],[1.33,-137.21],[3.78,-138.06],[6.23,-138.93],[8.69,-139.81],[11.17,-140.7],[13.65,-141.6],[16.16,-142.49],[18.7,-143.39],[21.26,-144.27],[23.86,-145.14],[26.49,-145.99],[29.15,-146.82],[31.86,-147.62],[34.6,-148.39],[37.39,-149.12],[40.21,-149.8],[43.08,-150.42],[45.98,-151.0],[48.93,-151.51],[51.91,-151.96],[54.92,-152.33],[57.96,-152.63],[61.03,-152.86],[64.12,-153.0],[67.22,-153.06],[70.34,-153.03],[73.46,-152.92],[76.58,-152.72],[79.7,-152.42],[82.81,-152.04],[85.89,-151.57],[88.96,-151.02],[92.0,-150.37],[95.0,-149.65],[97.96,-148.85],[100.88,-147.97],[103.75,-147.02],[106.56,-146.0],[109.32,-144.92],[112.02,-143.79],[114.66,-142.6],[117.23,-141.37],[119.73,-140.11],[122.17,-138.81],[124.54,-137.49],[126.85,-136.15],[129.09,-134.8],[131.27,-133.45],[133.4,-132.1],[135.46,-130.76],[137.48,-129.44],[139.45,-128.14],[141.38,-126.87],[143.28,-125.64],[145.15,-124.44],[146.99,-123.29],[148.82,-122.19],[150.64,-121.14],[152.46,-120.15],[154.28,-119.21],[156.12,-118.34],[157.98,-117.53],[159.86,-116.77],[161.77,-116.09],[163.72,-115.46],[165.71,-114.89],[167.76,-114.39],[169.85,-113.94],[172.0,-113.55],[174.22,-113.21],[176.49,-112.91],[178.83,-112.66],[181.23,-112.45],[183.7,-112.28],[186.23,-112.14],[188.82,-112.02],[191.47,-111.91],[194.18,-111.83],[196.95,-111.75],[199.76,-111.67],[202.61,-111.59],[205.5,-111.51],[208.42,-111.41],[211.37,-111.29],[214.33,-111.14],[217.29,-110.97],[220.26,-110.76],[223.22,-110.52],[226.17,-110.24],[229.08,-109.91],[231.97,-109.53],[234.81,-109.11],[237.61,-108.64],[240.34,-108.11],[243.02,-107.53],[245.62,-106.9],[248.15,-106.21],[250.6,-105.47],[252.96,-104.68],[255.23,-103.84],[257.4,-102.94],[259.49,-102.0],[261.47,-101.02],[263.36,-99.99],[265.16,-98.92],[266.85,-97.81],[268.46,-96.67],[269.98,-95.49],[271.41,-94.29],[272.77,-93.07],[274.04,-91.83],[275.25,-90.56],[276.4,-89.29],[277.5,-88.0],[278.55,-86.71],[279.56,-85.41],[280.55,-84.11],[281.51,-82.8],[282.46,-81.5],[283.42,-80.21],[284.37,-78.92],[285.35,-77.63],[286.34,-76.35],[287.37,-75.08],[288.44,-73.82],[289.55,-72.57],[290.71,-71.32],[291.93,-70.08],[293.21,-68.85],[294.55,-67.62],[295.97,-66.39],[297.44,-65.17],[298.99,-63.94],[300.61,-62.71],[302.29,-61.48],[304.04,-60.24],[305.84,-59.0],[307.7,-57.74],[309.61,-56.47],[311.57,-55.19],[313.55,-53.89],[315.56,-52.57],[317.59,-51.23],[319.62,-49.88],[321.64,-48.49],[323.65,-47.09],[325.63,-45.66],[327.56,-44.21],[329.44,-42.73],[331.26,-41.23],[332.99,-39.7],[334.63,-38.16],[336.17,-36.59],[337.59,-35.0]],[[341.9,-35.0],[343.19,-33.37],[344.34,-31.72],[345.34,-30.05],[346.18,-28.38],[346.85,-26.7],[347.35,-25.01],[347.66,-23.32],[347.79,-21.63],[347.72,-19.95],[347.45,-18.28],[346.98,-16.62],[346.31,-14.98],[345.44,-13.35],[344.36,-11.75],[343.09,-10.18],[341.62,-8.63],[339.96,-7.12],[338.12,-5.64],[336.1,-4.2],[333.91,-2.8],[331.56,-1.44],[329.06,-0.12],[326.43,1.15],[323.67,2.37],[320.79,3.56],[317.82,4.69],[314.75,5.78],[311.61,6.83],[308.42,7.83],[305.17,8.79],[301.89,9.71],[298.59,10.6],[295.29,11.45],[291.99,12.27],[288.72,13.05],[285.47,13.82],[282.26,14.56],[279.11,15.28],[276.02,15.99],[272.99,16.69],[270.05,17.39],[267.18,18.08],[264.41,18.77],[261.73,19.47],[259.15,20.17],[256.66,20.89],[254.27,21.62],[251.98,22.37],[249.8,23.15],[247.7,23.94],[245.7,24.76],[243.79,25.61],[241.96,26.48],[240.21,27.38],[238.53,28.32],[236.91,29.28],[235.35,30.26],[233.84,31.28],[232.37,32.32],[230.93,33.38],[229.52,34.46],[228.12,35.56],[226.73,36.68],[225.33,37.81],[223.92,38.95],[222.5,40.09],[221.04,41.24],[219.56,42.37],[218.03,43.51],[216.46,44.62],[214.84,45.73],[213.16,46.81],[211.42,47.86],[209.62,48.89],[207.75,49.88],[205.81,50.84],[203.81,51.75],[201.74,52.62],[199.6,53.44],[197.4,54.22],[195.13,54.94],[192.8,55.61],[190.41,56.23],[187.97,56.79],[185.48,57.29],[182.94,57.75],[180.36,58.15],[177.75,58.49],[175.11,58.79],[172.44,59.04],[169.75,59.25],[167.05,59.41],[164.33,59.54],[161.62,59.63],[158.9,59.69],[156.19,59.73],[153.49,59.75],[150.8,59.76],[148.12,59.75],[145.47,59.74],[142.83,59.74],[140.22,59.74],[137.62,59.75],[135.05,59.79],[132.5,59.84],[129.97,59.92],[127.46,60.04],[124.97,60.19],[122.49,60.38],[120.02,60.61],[117.56,60.89],[115.1,61.22],[112.65,61.6],[110.18,62.03],[107.71,62.51],[105.22,63.05],[102.7,63.63],[100.17,64.27],[97.6,64.96],[95.0,65.69],[92.36,66.47],[89.68,67.28],[86.94,68.14],[84.16,69.02],[81.33,69.93],[78.44,70.86],[75.49,71.81],[72.48,72.76],[69.42,73.72],[66.3,74.67],[63.12,75.62],[59.88,76.54],[56.59,77.44],[53.25,78.31],[49.86,79.14],[46.44,79.93],[42.97,80.66],[39.48,81.33],[35.96,81.94],[32.42,82.48],[28.87,82.95],[25.32,83.33],[21.77,83.63],[18.23,83.85],[14.72,83.97],[11.23,83.99],[7.78,83.92],[4.38,83.76],[1.02,83.49],[-2.27,83.13],[-5.49,82.66],[-8.65,82.1],[-11.72,81.45],[-14.7,80.7],[-17.6,79.86],[-20.4,78.93],[-23.1,77.92],[-25.71,76.83],[-28.2,75.67],[-30.6,74.43],[-32.89,73.13],[-35.07,71.77],[-37.16,70.36],[-39.14,68.9],[-41.02,67.4],[-42.81,65.87],[-44.51,64.3],[-46.13,62.71],[-47.67,61.11],[-49.14,59.49],[-50.54,57.87],[-51.88,56.24],[-53.18,54.62],[-54.43,53.01],[-55.65,51.41],[-56.84,49.83],[-58.01,48.26],[-59.17,46.72],[-60.32,45.2],[-61.48,43.72],[-62.65,42.25],[-63.84,40.82],[-65.05,39.42],[-66.29,38.05],[-67.56,36.71],[-68.86,35.4],[-70.21,34.12],[-71.6,32.86],[-73.02,31.63],[-74.5,30.42],[-76.01,29.24],[-77.56,28.07],[-79.15,26.91],[-80.78,25.77],[-82.43,24.64],[-84.11,23.51],[-85.81,22.39],[-87.52,21.26],[-89.23,20.14],[-90.94,19.0],[-92.65,17.86],[-94.33,16.71],[-95.98,15.54],[-97.59,14.36],[-99.16,13.16],[-100.67,11.95],[-102.11,10.71],[-103.47,9.45],[-104.75,8.17],[-105.94,6.87],[-107.03,5.54],[-108.0,4.2],[-108.86,2.83],[-109.6,1.45],[-110.21,0.04],[-110.69,-1.38],[-111.04,-2.82],[-111.24,-4.27],[-111.31,-5.73],[-111.25,-7.2],[-111.04,-8.68],[-110.7,-10.16],[-110.22,-11.64],[-109.62,-13.12],[-108.9,-14.6],[-108.06,-16.07],[-107.11,-17.53],[-106.06,-18.98],[-104.92,-20.42],[-103.7,-21.84],[-102.4,-23.25],[-101.05,-24.63],[-99.65,-26.0],[-98.22,-27.35],[-96.77,-28.68],[-95.3,-29.98],[-93.84,-31.27],[-92.39,-32.53],[-90.98,-33.78],[-89.6,-35.0],[-88.27,-36.21],[-87.01,-37.4],[-85.83,-38.57],[-84.73,-39.74],[-83.72,-40.89],[-82.82,-42.04],[-82.02,-43.18],[-81.35,-44.32],[-80.79,-45.47],[-80.36,-46.61],[-80.05,-47.77],[-79.88,-48.93],[-79.83,-50.11],[-79.91,-51.31],[-80.12,-52.52],[-80.45,-53.76],[-80.9,-55.02],[-81.46,-56.31],[-82.13,-57.63],[-82.89,-58.98],[-83.74,-60.36],[-84.67,-61.77],[-85.66,-63.22],[-86.71,-64.7],[-87.81,-66.22],[-88.93,-67.76],[-90.08,-69.35],[-91.23,-70.96],[-92.37,-72.6],[-93.48,-74.27],[-94.57,-75.97],[-95.6,-77.69],[-96.57,-79.43],[-97.47,-81.18],[-98.28,-82.95],[-99.0,-84.72],[-99.61,-86.5],[-100.1,-88.29],[-100.47,-90.06],[-100.7,-91.84],[-100.79,-93.59],[-100.73,-95.34],[-100.52,-97.06],[-100.16,-98.75],[-99.63,-100.42],[-98.95,-102.05],[-98.11,-103.65],[-97.11,-105.21],[-95.95,-106.73],[-94.63,-108.2],[-93.16,-109.62],[-91.55,-110.99],[-89.8,-112.31],[-87.91,-113.58],[-85.89,-114.8],[-83.76,-115.96],[-81.51,-117.08],[-79.16,-118.14],[-76.71,-119.14],[-74.18,-120.1],[-71.58,-121.02],[-68.91,-121.88],[-66.18,-122.71],[-63.4,-123.49],[-60.59,-124.24],[-57.74,-124.96],[-54.87,-125.65],[-51.99,-126.31],[-49.11,-126.95],[-46.22,-127.58],[-43.34,-128.19],[-40.47,-128.8],[-37.62,-129.39],[-34.79,-129.99],[-31.98,-130.6],[-29.2,-131.2],[-26.44,-131.82],[-23.72,-132.45],[-21.02,-133.1],[-18.35,-133.76],[-15.71,-134.44],[-13.09,-135.14],[-10.5,-135.87],[-7.92,-136.61],[-5.37,-137.38],[-2.82,-138.17],[-0.29,-138.97],[2.24,-139.8],[4.77,-140.64],[7.31,-141.49],[9.85,-142.36],[12.41,-143.23],[14.98,-144.1],[17.58,-144.98],[20.2,-145.85],[22.85,-146.7],[25.53,-147.54],[28.25,-148.36],[31.0,-149.16],[33.79,-149.92],[36.62,-150.64],[39.48,-151.32],[42.39,-151.95],[45.34,-152.53],[48.32,-153.05],[51.34,-153.5],[54.39,-153.89],[57.47,-154.2],[60.57,-154.43],[63.7,-154.59],[66.85,-154.66],[70.0,-154.65],[73.16,-154.55],[76.33,-154.36],[79.48,-154.08],[82.63,-153.71],[85.76,-153.26],[88.87,-152.71],[91.95,-152.08],[95.0,-151.37],[98.01,-150.57],[100.97,-149.7],[103.89,-148.75],[106.75,-147.74],[109.55,-146.66],[112.29,-145.53],[114.97,-144.34],[117.59,-143.11],[120.14,-141.83],[122.62,-140.53],[125.03,-139.19],[127.38,-137.84],[129.66,-136.48],[131.89,-135.11],[134.05,-133.74],[136.15,-132.39],[138.2,-131.05],[140.21,-129.73],[142.17,-128.43],[144.1,-127.18],[146.0,-125.96],[147.87,-124.79],[149.73,-123.66],[151.58,-122.59],[153.42,-121.57],[155.27,-120.61],[157.13,-119.72],[159.01,-118.89],[160.92,-118.12],[162.86,-117.41],[164.84,-116.77],[166.86,-116.19],[168.93,-115.67],[171.06,-115.22],[173.25,-114.82],[175.5,-114.47],[177.81,-114.17],[180.19,-113.92],[182.64,-113.72],[185.15,-113.55],[187.74,-113.41],[190.39,-113.3],[193.1,-113.21],[195.87,-113.14],[198.71,-113.07],[201.59,-113.02],[204.52,-112.96],[207.5,-112.89],[210.51,-112.81],[213.54,-112.71],[216.6,-112.59],[219.67,-112.44],[222.74,-112.26],[225.81,-112.04],[228.86,-111.78],[231.89,-111.48],[234.9,-111.13],[237.86,-110.73],[240.77,-110.27],[243.63,-109.77],[246.43,-109.21],[249.16,-108.59],[251.81,-107.92],[254.38,-107.19],[256.86,-106.4],[259.25,-105.57],[261.55,-104.68],[263.74,-103.74],[265.84,-102.75],[267.84,-101.71],[269.73,-100.64],[271.53,-99.52],[273.23,-98.36],[274.84,-97.17],[276.35,-95.95],[277.78,-94.71],[279.13,-93.44],[280.4,-92.15],[281.6,-90.84],[282.75,-89.53],[283.84,-88.2],[284.88,-86.86],[285.89,-85.52],[286.88,-84.18],[287.84,-82.84],[288.8,-81.5],[289.75,-80.16],[290.72,-78.83],[291.7,-77.51],[292.71,-76.2],[293.75,-74.89],[294.84,-73.59],[295.97,-72.29],[297.15,-71.01],[298.39,-69.73],[299.69,-68.46],[301.05,-67.18],[302.49,-65.92],[303.98,-64.65],[305.55,-63.38],[307.18,-62.11],[308.88,-60.83],[310.64,-59.54],[312.45,-58.25],[314.31,-56.94],[316.22,-55.62],[318.16,-54.29],[320.13,-52.94],[322.12,-51.56],[324.11,-50.17],[326.11,-48.76],[328.08,-47.32],[330.04,-45.86],[331.95,-44.38],[333.81,-42.87],[335.61,-41.34],[337.33,-39.79],[338.96,-38.21],[340.49,-36.62],[341.9,-35.0]],[[346.12,-35.0],[347.4,-33.34],[348.55,-31.66],[349.55,-29.97],[350.39,-28.27],[351.06,-26.56],[351.56,-24.84],[351.88,-23.13],[352.0,-21.41],[351.94,-19.7],[351.67,-18.0],[351.2,-16.31],[350.52,-14.64],[349.64,-12.99],[348.56,-11.36],[347.27,-9.76],[345.79,-8.19],[344.11,-6.65],[342.24,-5.14],[340.2,-3.68],[337.98,-2.25],[335.59,-0.87],[333.06,0.47],[330.38,1.76],[327.57,3.01],[324.64,4.21],[321.6,5.37],[318.48,6.47],[315.27,7.53],[312.0,8.55],[308.68,9.52],[305.32,10.45],[301.94,11.35],[298.56,12.2],[295.17,13.03],[291.81,13.82],[288.47,14.59],[285.17,15.33],[281.93,16.05],[278.74,16.76],[275.63,17.46],[272.59,18.15],[269.64,18.83],[266.78,19.52],[264.02,20.21],[261.35,20.91],[258.79,21.62],[256.33,22.35],[253.97,23.1],[251.71,23.87],[249.56,24.66],[247.5,25.48],[245.54,26.32],[243.66,27.2],[241.87,28.1],[240.16,29.04],[238.51,30.0],[236.93,31.0],[235.4,32.02],[233.92,33.08],[232.48,34.15],[231.06,35.26],[229.66,36.38],[228.27,37.52],[226.89,38.68],[225.49,39.85],[224.08,41.03],[222.65,42.21],[221.19,43.39],[219.68,44.56],[218.14,45.72],[216.54,46.87],[214.88,48.0],[213.17,49.11],[211.4,50.19],[209.55,51.24],[207.64,52.25],[205.66,53.22],[203.61,54.15],[201.49,55.04],[199.3,55.87],[197.04,56.66],[194.72,57.39],[192.34,58.06],[189.9,58.69],[187.4,59.25],[184.85,59.76],[182.26,60.22],[179.63,60.62],[176.97,60.97],[174.27,61.27],[171.55,61.52],[168.82,61.73],[166.07,61.9],[163.31,62.03],[160.55,62.13],[157.79,62.21],[155.03,62.25],[152.29,62.29],[149.56,62.31],[146.84,62.32],[144.14,62.33],[141.46,62.35],[138.8,62.37],[136.16,62.41],[133.54,62.47],[130.94,62.56],[128.36,62.67],[125.8,62.82],[123.25,63.01],[120.71,63.23],[118.18,63.51],[115.65,63.83],[113.12,64.19],[110.59,64.61],[108.04,65.09],[105.48,65.61],[102.9,66.18],[100.3,66.81],[97.67,67.48],[95.0,68.2],[92.29,68.97],[89.55,69.77],[86.75,70.61],[83.91,71.49],[81.01,72.39],[78.05,73.32],[75.04,74.26],[71.97,75.21],[68.84,76.17],[65.66,77.12],[62.41,78.06],[59.11,78.99],[55.75,79.89],[52.35,80.77],[48.89,81.6],[45.4,82.39],[41.86,83.13],[38.3,83.81],[34.7,84.43],[31.09,84.98],[27.47,85.45],[23.84,85.84],[20.22,86.14],[16.61,86.36],[13.02,86.49],[9.46,86.52],[5.93,86.45],[2.45,86.28],[-0.98,86.01],[-4.34,85.65],[-7.64,85.18],[-10.86,84.61],[-14.0,83.94],[-17.06,83.18],[-20.02,82.32],[-22.88,81.37],[-25.64,80.34],[-28.29,79.23],[-30.84,78.03],[-33.28,76.77],[-35.61,75.43],[-37.83,74.04],[-39.95,72.59],[-41.96,71.09],[-43.86,69.54],[-45.67,67.96],[-47.38,66.34],[-49.0,64.7],[-50.54,63.04],[-52.0,61.37],[-53.4,59.69],[-54.73,58.01],[-56.0,56.33],[-57.22,54.66],[-58.41,53.0],[-59.57,51.35],[-60.7,49.73],[-61.82,48.13],[-62.93,46.55],[-64.05,45.01],[-65.17,43.49],[-66.31,42.0],[-67.47,40.55],[-68.66,39.13],[-69.88,37.73],[-71.13,36.38],[-72.43,35.05],[-73.77,33.75],[-75.15,32.48],[-76.58,31.23],[-78.06,30.0],[-79.57,28.8],[-81.13,27.62],[-82.73,26.45],[-84.36,25.29],[-86.03,24.14],[-87.71,22.99],[-89.42,21.85],[-91.13,20.7],[-92.85,19.56],[-94.57,18.4],[-96.27,17.24],[-97.94,16.06],[-99.59,14.87],[-101.19,13.67],[-102.74,12.45],[-104.23,11.2],[-105.65,9.94],[-106.99,8.65],[-108.24,7.35],[-109.4,6.02],[-110.44,4.67],[-111.38,3.3],[-112.19,1.91],[-112.89,0.5],[-113.45,-0.93],[-113.88,-2.37],[-114.17,-3.83],[-114.32,-5.3],[-114.34,-6.78],[-114.21,-8.27],[-113.95,-9.77],[-113.56,-11.26],[-113.04,-12.76],[-112.39,-14.25],[-111.62,-15.74],[-110.74,-17.22],[-109.75,-18.69],[-108.67,-20.14],[-107.51,-21.59],[-106.27,-23.02],[-104.96,-24.43],[-103.61,-25.82],[-102.21,-27.19],[-100.79,-28.54],[-99.35,-29.88],[-97.91,-31.19],[-96.48,-32.48],[-95.08,-33.75],[-93.71,-35.0],[-92.39,-36.23],[-91.13,-37.45],[-89.95,-38.66],[-88.84,-39.85],[-87.83,-41.03],[-86.92,-42.2],[-86.11,-43.37],[-85.42,-44.54],[-84.85,-45.71],[-84.4,-46.88],[-84.09,-48.06],[-83.9,-49.25],[-83.84,-50.46],[-83.91,-51.68],[-84.11,-52.92],[-84.43,-54.19],[-84.88,-55.47],[-85.44,-56.79],[-86.1,-58.14],[-86.87,-59.51],[-87.73,-60.92],[-88.66,-62.37],[-89.67,-63.84],[-90.74,-65.36],[-91.85,-66.91],[-93.0,-68.49],[-94.17,-70.11],[-95.35,-71.76],[-96.52,-73.44],[-97.67,-75.15],[-98.79,-76.88],[-99.86,-78.64],[-100.88,-80.42],[-101.82,-82.22],[-102.67,-84.04],[-103.43,-85.86],[-104.08,-87.69],[-104.61,-89.52],[-105.01,-91.35],[-105.28,-93.17],[-105.4,-94.98],[-105.38,-96.77],[-105.2,-98.54],[-104.86,-100.29],[-104.36,-102.01],[-103.69,-103.69],[-102.86,-105.34],[-101.86,-106.95],[-100.7,-108.51],[-99.38,-110.03],[-97.91,-111.5],[-96.28,-112.92],[-94.5,-114.28],[-92.58,-115.59],[-90.53,-116.84],[-88.35,-118.04],[-86.05,-119.19],[-83.64,-120.28],[-81.13,-121.31],[-78.53,-122.29],[-75.85,-123.22],[-73.1,-124.11],[-70.29,-124.94],[-67.42,-125.74],[-64.51,-126.49],[-61.57,-127.21],[-58.6,-127.9],[-55.61,-128.56],[-52.62,-129.19],[-49.62,-129.81],[-46.63,-130.4],[-43.64,-130.99],[-40.68,-131.57],[-37.73,-132.15],[-34.81,-132.72],[-31.91,-133.3],[-29.04,-133.89],[-26.2,-134.49],[-23.4,-135.11],[-20.62,-135.73],[-17.87,-136.38],[-15.15,-137.05],[-12.46,-137.74],[-9.78,-138.45],[-7.13,-139.18],[-4.5,-139.93],[-1.88,-140.71],[0.74,-141.5],[3.35,-142.31],[5.96,-143.14],[8.57,-143.98],[11.19,-144.82],[13.83,-145.67],[16.49,-146.53],[19.17,-147.37],[21.87,-148.22],[24.6,-149.04],[27.37,-149.85],[30.17,-150.64],[33.0,-151.39],[35.87,-152.11],[38.78,-152.79],[41.73,-153.42],[44.72,-154.0],[47.74,-154.53],[50.79,-154.99],[53.88,-155.38],[56.99,-155.71],[60.14,-155.95],[63.3,-156.12],[66.48,-156.21],[69.67,-156.21],[72.87,-156.13],[76.08,-155.95],[79.27,-155.69],[82.46,-155.34],[85.64,-154.9],[88.79,-154.37],[91.91,-153.75],[95.0,-153.05],[98.05,-152.26],[101.06,-151.4],[104.02,-150.46],[106.92,-149.46],[109.77,-148.38],[112.56,-147.25],[115.29,-146.06],[117.95,-144.83],[120.54,-143.55],[123.07,-142.24],[125.52,-140.9],[127.91,-139.54],[130.24,-138.16],[132.5,-136.78],[134.7,-135.4],[136.84,-134.02],[138.93,-132.66],[140.97,-131.33],[142.97,-130.01],[144.93,-128.74],[146.86,-127.5],[148.76,-126.3],[150.65,-125.15],[152.53,-124.06],[154.4,-123.02],[156.28,-122.04],[158.16,-121.13],[160.07,-120.27],[162.01,-119.49],[163.97,-118.76],[165.98,-118.11],[168.03,-117.51],[170.14,-116.99],[172.3,-116.52],[174.52,-116.11],[176.8,-115.76],[179.16,-115.46],[181.58,-115.21],[184.07,-115.01],[186.64,-114.84],[189.27,-114.71],[191.98,-114.61],[194.76,-114.53],[197.6,-114.47],[200.5,-114.42],[203.46,-114.38],[206.47,-114.34],[209.52,-114.29],[212.62,-114.23],[215.75,-114.16],[218.9,-114.06],[222.07,-113.94],[225.25,-113.78],[228.42,-113.58],[231.59,-113.35],[234.74,-113.07],[237.86,-112.74],[240.94,-112.36],[243.98,-111.93],[246.96,-111.44],[249.88,-110.9],[252.73,-110.3],[255.51,-109.64],[258.2,-108.92],[260.81,-108.15],[263.32,-107.31],[265.73,-106.43],[268.05,-105.49],[270.26,-104.5],[272.36,-103.46],[274.36,-102.37],[276.26,-101.25],[278.05,-100.08],[279.75,-98.87],[281.35,-97.63],[282.85,-96.37],[284.27,-95.07],[285.6,-93.75],[286.86,-92.42],[288.05,-91.07],[289.19,-89.7],[290.27,-88.33],[291.3,-86.95],[292.3,-85.57],[293.28,-84.19],[294.24,-82.81],[295.2,-81.43],[296.15,-80.05],[297.12,-78.68],[298.11,-77.32],[299.13,-75.97],[300.18,-74.62],[301.27,-73.28],[302.41,-71.95],[303.61,-70.62],[304.86,-69.3],[306.17,-67.98],[307.55,-66.67],[309.0,-65.36],[310.51,-64.05],[312.09,-62.73],[313.73,-61.41],[315.43,-60.09],[317.19,-58.76],[318.99,-57.41],[320.85,-56.06],[322.74,-54.69],[324.67,-53.3],[326.61,-51.89],[328.56,-50.47],[330.52,-49.02],[332.46,-47.55],[334.38,-46.06],[336.27,-44.55],[338.1,-43.02],[339.88,-41.46],[341.58,-39.87],[343.2,-38.27],[344.72,-36.64],[346.12,-35.0]],[[350.25,-35.0],[351.52,-33.31],[352.66,-31.61],[353.65,-29.89],[354.49,-28.16],[355.16,-26.42],[355.66,-24.68],[355.98,-22.94],[356.11,-21.2],[356.04,-19.46],[355.77,-17.73],[355.3,-16.01],[354.62,-14.32],[353.74,-12.64],[352.65,-10.98],[351.35,-9.35],[349.86,-7.75],[348.16,-6.18],[346.28,-4.65],[344.21,-3.16],[341.96,-1.71],[339.55,-0.31],[336.97,1.05],[334.25,2.37],[331.39,3.64],[328.42,4.86],[325.33,6.03],[322.14,7.15],[318.87,8.23],[315.53,9.26],[312.14,10.24],[308.71,11.19],[305.25,12.09],[301.79,12.95],[298.32,13.78],[294.87,14.58],[291.44,15.35],[288.06,16.09],[284.72,16.82],[281.45,17.52],[278.25,18.22],[275.12,18.91],[272.09,19.59],[269.14,20.27],[266.3,20.96],[263.55,21.65],[260.91,22.36],[258.38,23.08],[255.95,23.82],[253.63,24.59],[251.42,25.38],[249.31,26.19],[247.29,27.04],[245.37,27.91],[243.54,28.82],[241.79,29.76],[240.12,30.73],[238.51,31.73],[236.97,32.77],[235.47,33.84],[234.02,34.93],[232.6,36.05],[231.2,37.2],[229.82,38.37],[228.44,39.55],[227.06,40.75],[225.67,41.96],[224.26,43.18],[222.82,44.4],[221.34,45.62],[219.82,46.83],[218.25,48.02],[216.62,49.21],[214.93,50.37],[213.18,51.5],[211.37,52.61],[209.48,53.68],[207.52,54.71],[205.49,55.7],[203.39,56.65],[201.22,57.54],[198.97,58.39],[196.66,59.19],[194.28,59.92],[191.84,60.61],[189.34,61.23],[186.79,61.81],[184.19,62.32],[181.54,62.78],[178.86,63.18],[176.14,63.53],[173.39,63.84],[170.62,64.09],[167.83,64.31],[165.03,64.48],[162.22,64.62],[159.42,64.73],[156.61,64.81],[153.81,64.87],[151.02,64.91],[148.24,64.95],[145.48,64.98],[142.73,65.01],[140.0,65.04],[137.29,65.09],[134.61,65.16],[131.94,65.25],[129.28,65.36],[126.65,65.51],[124.02,65.69],[121.41,65.91],[118.8,66.17],[116.2,66.48],[113.6,66.84],[111.0,67.25],[108.38,67.7],[105.75,68.21],[103.11,68.77],[100.43,69.38],[97.73,70.04],[95.0,70.75],[92.23,71.5],[89.41,72.29],[86.56,73.12],[83.65,73.98],[80.68,74.87],[77.67,75.79],[74.59,76.72],[71.46,77.67],[68.27,78.62],[65.02,79.57],[61.71,80.51],[58.34,81.43],[54.92,82.34],[51.45,83.21],[47.93,84.05],[44.36,84.84],[40.76,85.58],[37.12,86.27],[33.46,86.89],[29.78,87.44],[26.08,87.92],[22.38,88.32],[18.69,88.63],[15.0,88.85],[11.34,88.98],[7.7,89.01],[4.1,88.94],[0.55,88.78],[-2.95,88.51],[-6.39,88.13],[-9.76,87.66],[-13.05,87.08],[-16.26,86.4],[-19.38,85.63],[-22.4,84.75],[-25.32,83.79],[-28.14,82.73],[-30.85,81.59],[-33.44,80.37],[-35.93,79.07],[-38.3,77.71],[-40.56,76.28],[-42.7,74.79],[-44.74,73.24],[-46.67,71.65],[-48.49,70.02],[-50.21,68.36],[-51.84,66.67],[-53.38,64.96],[-54.84,63.23],[-56.22,61.49],[-57.53,59.75],[-58.79,58.01],[-59.99,56.28],[-61.14,54.56],[-62.27,52.86],[-63.36,51.18],[-64.44,49.52],[-65.51,47.88],[-66.58,46.28],[-67.65,44.7],[-68.74,43.16],[-69.85,41.65],[-70.99,40.18],[-72.15,38.74],[-73.36,37.33],[-74.61,35.96],[-75.9,34.61],[-77.23,33.3],[-78.62,32.02],[-80.05,30.76],[-81.53,29.52],[-83.06,28.3],[-84.63,27.1],[-86.24,25.92],[-87.89,24.74],[-89.56,23.58],[-91.26,22.42],[-92.98,21.26],[-94.7,20.09],[-96.43,18.93],[-98.15,17.75],[-99.85,16.57],[-101.53,15.37],[-103.17,14.16],[-104.76,12.93],[-106.3,11.68],[-107.78,10.41],[-109.18,9.13],[-110.49,7.82],[-111.72,6.49],[-112.84,5.13],[-113.85,3.76],[-114.75,2.36],[-115.52,0.95],[-116.17,-0.49],[-116.69,-1.94],[-117.07,-3.4],[-117.31,-4.88],[-117.42,-6.37],[-117.38,-7.87],[-117.21,-9.37],[-116.9,-10.88],[-116.46,-12.39],[-115.89,-13.9],[-115.2,-15.4],[-114.4,-16.9],[-113.48,-18.39],[-112.47,-19.87],[-111.37,-21.33],[-110.18,-22.78],[-108.93,-24.22],[-107.62,-25.63],[-106.27,-27.03],[-104.88,-28.41],[-103.48,-29.77],[-102.07,-31.11],[-100.66,-32.42],[-99.27,-33.72],[-97.92,-35.0],[-96.61,-36.26],[-95.35,-37.51],[-94.17,-38.74],[-93.06,-39.96],[-92.04,-41.17],[-91.12,-42.37],[-90.31,-43.57],[-89.6,-44.76],[-89.02,-45.96],[-88.56,-47.16],[-88.23,-48.36],[-88.03,-49.58],[-87.96,-50.81],[-88.01,-52.06],[-88.2,-53.33],[-88.52,-54.62],[-88.95,-55.94],[-89.51,-57.28],[-90.17,-58.66],[-90.94,-60.06],[-91.8,-61.5],[-92.74,-62.97],[-93.76,-64.48],[-94.84,-66.03],[-95.97,-67.61],[-97.13,-69.23],[-98.33,-70.88],[-99.53,-72.56],[-100.73,-74.28],[-101.91,-76.03],[-103.06,-77.8],[-104.17,-79.61],[-105.21,-81.43],[-106.19,-83.27],[-107.08,-85.13],[-107.88,-87.0],[-108.57,-88.87],[-109.13,-90.75],[-109.57,-92.63],[-109.88,-94.5],[-110.03,-96.36],[-110.04,-98.2],[-109.89,-100.03],[-109.57,-101.83],[-109.09,-103.6],[-108.43,-105.33],[-107.61,-107.03],[-106.62,-108.69],[-105.46,-110.3],[-104.14,-111.86],[-102.65,-113.38],[-101.0,-114.84],[-99.2,-116.25],[-97.25,-117.59],[-95.16,-118.89],[-92.93,-120.12],[-90.59,-121.3],[-88.12,-122.41],[-85.55,-123.48],[-82.88,-124.48],[-80.13,-125.43],[-77.29,-126.33],[-74.39,-127.18],[-71.44,-127.98],[-68.43,-128.74],[-65.39,-129.46],[-62.32,-130.15],[-59.22,-130.8],[-56.12,-131.43],[-53.01,-132.03],[-49.9,-132.61],[-46.81,-133.18],[-43.72,-133.74],[-40.66,-134.29],[-37.62,-134.84],[-34.61,-135.39],[-31.62,-135.95],[-28.67,-136.52],[-25.75,-137.1],[-22.87,-137.69],[-20.01,-138.31],[-17.19,-138.94],[-14.39,-139.59],[-11.62,-140.26],[-8.88,-140.96],[-6.15,-141.67],[-3.44,-142.41],[-0.74,-143.17],[1.95,-143.95],[4.63,-144.75],[7.32,-145.55],[10.01,-146.37],[12.71,-147.2],[15.43,-148.03],[18.17,-148.86],[20.92,-149.68],[23.71,-150.49],[26.52,-151.29],[29.37,-152.06],[32.24,-152.81],[35.16,-153.53],[38.11,-154.21],[41.09,-154.84],[44.12,-155.42],[47.17,-155.95],[50.26,-156.42],[53.39,-156.82],[56.54,-157.16],[59.71,-157.42],[62.91,-157.6],[66.13,-157.71],[69.36,-157.72],[72.59,-157.66],[75.83,-157.5],[79.07,-157.26],[82.3,-156.92],[85.51,-156.5],[88.7,-155.98],[91.87,-155.38],[95.0,-154.7],[98.09,-153.92],[101.15,-153.07],[104.15,-152.15],[107.1,-151.15],[110.0,-150.08],[112.83,-148.96],[115.6,-147.77],[118.3,-146.54],[120.94,-145.26],[123.51,-143.94],[126.01,-142.6],[128.45,-141.23],[130.82,-139.85],[133.12,-138.46],[135.36,-137.06],[137.54,-135.67],[139.67,-134.3],[141.74,-132.94],[143.78,-131.61],[145.77,-130.32],[147.73,-129.06],[149.67,-127.84],[151.59,-126.67],[153.49,-125.56],[155.4,-124.5],[157.3,-123.5],[159.22,-122.56],[161.16,-121.69],[163.12,-120.89],[165.11,-120.15],[167.15,-119.48],[169.23,-118.87],[171.37,-118.33],[173.56,-117.85],[175.82,-117.44],[178.14,-117.08],[180.53,-116.78],[183.0,-116.53],[185.54,-116.33],[188.15,-116.16],[190.84,-116.04],[193.61,-115.94],[196.44,-115.88],[199.35,-115.83],[202.32,-115.8],[205.35,-115.77],[208.44,-115.75],[211.58,-115.72],[214.77,-115.68],[217.99,-115.63],[221.24,-115.55],[224.51,-115.45],[227.79,-115.31],[231.07,-115.14],[234.35,-114.93],[237.61,-114.67],[240.85,-114.37],[244.06,-114.01],[247.22,-113.6],[250.32,-113.13],[253.37,-112.61],[256.35,-112.02],[259.25,-111.38],[262.07,-110.67],[264.8,-109.9],[267.43,-109.08],[269.96,-108.2],[272.39,-107.26],[274.72,-106.27],[276.93,-105.22],[279.04,-104.13],[281.04,-102.99],[282.93,-101.81],[284.71,-100.59],[286.4,-99.33],[287.98,-98.04],[289.47,-96.72],[290.87,-95.38],[292.18,-94.01],[293.42,-92.63],[294.6,-91.23],[295.71,-89.82],[296.77,-88.4],[297.79,-86.98],[298.78,-85.55],[299.75,-84.13],[300.7,-82.7],[301.64,-81.28],[302.59,-79.87],[303.56,-78.46],[304.54,-77.05],[305.56,-75.66],[306.61,-74.27],[307.71,-72.89],[308.86,-71.52],[310.06,-70.15],[311.32,-68.79],[312.64,-67.43],[314.03,-66.07],[315.48,-64.72],[316.99,-63.36],[318.57,-62.0],[320.21,-60.63],[321.91,-59.26],[323.66,-57.88],[325.46,-56.49],[327.3,-55.08],[329.17,-53.66],[331.06,-52.22],[332.97,-50.76],[334.88,-49.28],[336.78,-47.78],[338.66,-46.26],[340.52,-44.72],[342.32,-43.15],[344.08,-41.57],[345.76,-39.96],[347.35,-38.32],[348.86,-36.67],[350.25,-35.0]],[[354.27,-35.0],[355.53,-33.28],[356.66,-31.55],[357.65,-29.81],[358.48,-28.05],[359.15,-26.29],[359.65,-24.52],[359.97,-22.75],[360.09,-20.98],[360.03,-19.22],[359.76,-17.47],[359.29,-15.72],[358.61,-14.0],[357.72,-12.29],[356.63,-10.61],[355.33,-8.95],[353.82,-7.33],[352.11,-5.73],[350.21,-4.18],[348.12,-2.66],[345.85,-1.19],[343.41,0.24],[340.8,1.63],[338.05,2.96],[335.15,4.25],[332.12,5.49],[328.99,6.68],[325.75,7.82],[322.42,8.91],[319.02,9.96],[315.56,10.96],[312.06,11.91],[308.53,12.82],[304.98,13.69],[301.43,14.53],[297.9,15.33],[294.39,16.11],[290.92,16.85],[287.5,17.58],[284.14,18.28],[280.86,18.98],[277.65,19.66],[274.53,20.34],[271.5,21.02],[268.57,21.7],[265.75,22.39],[263.04,23.09],[260.43,23.81],[257.94,24.55],[255.55,25.31],[253.28,26.09],[251.11,26.91],[249.05,27.75],[247.09,28.63],[245.22,29.54],[243.43,30.48],[241.73,31.46],[240.1,32.47],[238.54,33.52],[237.03,34.6],[235.57,35.71],[234.15,36.85],[232.75,38.02],[231.38,39.21],[230.01,40.43],[228.64,41.66],[227.27,42.9],[225.88,44.16],[224.46,45.42],[223.0,46.68],[221.51,47.93],[219.96,49.18],[218.37,50.41],[216.71,51.63],[214.99,52.82],[213.2,53.98],[211.34,55.11],[209.4,56.21],[207.4,57.26],[205.31,58.27],[203.16,59.23],[200.93,60.15],[198.62,61.0],[196.25,61.81],[193.81,62.55],[191.31,63.24],[188.76,63.88],[186.14,64.45],[183.48,64.97],[180.78,65.43],[178.03,65.84],[175.26,66.19],[172.45,66.5],[169.63,66.76],[166.79,66.97],[163.93,67.15],[161.07,67.29],[158.21,67.41],[155.36,67.5],[152.51,67.57],[149.67,67.63],[146.84,67.68],[144.03,67.72],[141.23,67.77],[138.45,67.83],[135.69,67.9],[132.95,67.99],[130.22,68.1],[127.51,68.25],[124.81,68.42],[122.12,68.64],[119.44,68.89],[116.77,69.19],[114.09,69.53],[111.42,69.92],[108.73,70.37],[106.03,70.86],[103.31,71.4],[100.57,71.99],[97.8,72.64],[95.0,73.32],[92.16,74.06],[89.28,74.83],[86.36,75.65],[83.38,76.5],[80.36,77.37],[77.28,78.28],[74.14,79.2],[70.94,80.13],[67.69,81.08],[64.37,82.02],[61.0,82.95],[57.57,83.87],[54.09,84.77],[50.55,85.65],[46.96,86.48],[43.33,87.28],[39.66,88.02],[35.96,88.71],[32.23,89.33],[28.48,89.89],[24.71,90.37],[20.94,90.77],[17.17,91.08],[13.41,91.31],[9.68,91.44],[5.97,91.47],[2.3,91.4],[-1.33,91.24],[-4.9,90.96],[-8.41,90.59],[-11.85,90.1],[-15.21,89.52],[-18.48,88.83],[-21.67,88.04],[-24.75,87.15],[-27.73,86.17],[-30.6,85.09],[-33.37,83.93],[-36.01,82.68],[-38.54,81.35],[-40.95,79.95],[-43.25,78.48],[-45.43,76.96],[-47.49,75.37],[-49.44,73.74],[-51.28,72.06],[-53.01,70.35],[-54.65,68.61],[-56.19,66.85],[-57.64,65.06],[-59.01,63.27],[-60.31,61.48],[-61.54,59.68],[-62.72,57.89],[-63.84,56.11],[-64.93,54.35],[-65.99,52.61],[-67.03,50.89],[-68.05,49.2],[-69.07,47.53],[-70.1,45.9],[-71.14,44.31],[-72.19,42.74],[-73.28,41.22],[-74.39,39.73],[-75.55,38.27],[-76.74,36.85],[-77.98,35.46],[-79.27,34.11],[-80.61,32.78],[-82.01,31.49],[-83.45,30.22],[-84.94,28.97],[-86.48,27.74],[-88.07,26.53],[-89.69,25.33],[-91.36,24.15],[-93.05,22.97],[-94.76,21.79],[-96.49,20.61],[-98.23,19.44],[-99.97,18.25],[-101.7,17.06],[-103.41,15.85],[-105.09,14.64],[-106.73,13.4],[-108.32,12.15],[-109.85,10.88],[-111.31,9.59],[-112.7,8.28],[-113.99,6.94],[-115.19,5.59],[-116.29,4.21],[-117.27,2.81],[-118.13,1.39],[-118.87,-0.04],[-119.48,-1.5],[-119.95,-2.97],[-120.29,-4.46],[-120.49,-5.96],[-120.55,-7.46],[-120.47,-8.98],[-120.25,-10.5],[-119.9,-12.02],[-119.42,-13.55],[-118.81,-15.07],[-118.09,-16.58],[-117.25,-18.09],[-116.31,-19.59],[-115.28,-21.07],[-114.16,-22.55],[-112.96,-24.0],[-111.71,-25.45],[-110.4,-26.87],[-109.06,-28.27],[-107.69,-29.66],[-106.31,-31.02],[-104.93,-32.37],[-103.57,-33.69],[-102.23,-35.0],[-100.93,-36.29],[-99.68,-37.56],[-98.5,-38.82],[-97.39,-40.07],[-96.37,-41.31],[-95.44,-42.54],[-94.62,-43.76],[-93.91,-44.99],[-93.31,-46.21],[-92.84,-47.44],[-92.49,-48.67],[-92.27,-49.92],[-92.18,-51.18],[-92.23,-52.46],[-92.4,-53.75],[-92.7,-55.07],[-93.13,-56.41],[-93.67,-57.79],[-94.33,-59.19],[-95.09,-60.62],[-95.95,-62.09],[-96.9,-63.59],[-97.92,-65.13],[-99.01,-66.71],[-100.15,-68.32],[-101.33,-69.97],[-102.54,-71.66],[-103.76,-73.38],[-104.98,-75.13],[-106.19,-76.92],[-107.37,-78.74],[-108.51,-80.58],[-109.59,-82.44],[-110.6,-84.33],[-111.52,-86.23],[-112.35,-88.15],[-113.07,-90.07],[-113.68,-91.99],[-114.15,-93.92],[-114.48,-95.84],[-114.67,-97.75],[-114.7,-99.64],[-114.58,-101.52],[-114.28,-103.37],[-113.82,-105.19],[-113.18,-106.97],[-112.37,-108.72],[-111.38,-110.43],[-110.22,-112.09],[-108.89,-113.7],[-107.38,-115.26],[-105.72,-116.76],[-103.89,-118.21],[-101.91,-119.6],[-99.78,-120.93],[-97.52,-122.2],[-95.12,-123.4],[-92.6,-124.55],[-89.96,-125.64],[-87.23,-126.66],[-84.4,-127.64],[-81.48,-128.55],[-78.5,-129.41],[-75.45,-130.22],[-72.35,-130.99],[-69.2,-131.71],[-66.03,-132.39],[-62.83,-133.04],[-59.61,-133.66],[-56.39,-134.25],[-53.17,-134.81],[-49.96,-135.36],[-46.76,-135.9],[-43.58,-136.43],[-40.42,-136.95],[-37.29,-137.47],[-34.19,-138.0],[-31.12,-138.53],[-28.09,-139.08],[-25.09,-139.63],[-22.13,-140.21],[-19.2,-140.8],[-16.3,-141.42],[-13.43,-142.05],[-10.59,-142.71],[-7.77,-143.39],[-4.98,-144.09],[-2.19,-144.81],[0.58,-145.56],[3.34,-146.32],[6.1,-147.09],[8.86,-147.88],[11.62,-148.68],[14.4,-149.49],[17.2,-150.3],[20.01,-151.1],[22.84,-151.9],[25.7,-152.68],[28.59,-153.44],[31.52,-154.18],[34.47,-154.89],[37.46,-155.57],[40.48,-156.2],[43.54,-156.79],[46.63,-157.32],[49.76,-157.8],[52.91,-158.21],[56.1,-158.56],[59.31,-158.83],[62.54,-159.03],[65.79,-159.15],[69.05,-159.19],[72.32,-159.14],[75.6,-159.0],[78.87,-158.78],[82.14,-158.46],[85.39,-158.06],[88.62,-157.56],[91.83,-156.98],[95.0,-156.31],[98.14,-155.56],[101.23,-154.72],[104.28,-153.81],[107.28,-152.82],[110.21,-151.77],[113.09,-150.65],[115.91,-149.47],[118.66,-148.24],[121.34,-146.97],[123.96,-145.65],[126.51,-144.3],[128.98,-142.93],[131.39,-141.54],[133.74,-140.14],[136.02,-138.74],[138.24,-137.34],[140.41,-135.95],[142.53,-134.58],[144.6,-133.23],[146.63,-131.92],[148.62,-130.64],[150.59,-129.41],[152.54,-128.22],[154.48,-127.09],[156.41,-126.01],[158.35,-124.99],[160.3,-124.04],[162.26,-123.15],[164.26,-122.32],[166.28,-121.57],[168.35,-120.88],[170.47,-120.26],[172.63,-119.71],[174.86,-119.22],[177.15,-118.8],[179.52,-118.44],[181.95,-118.13],[184.46,-117.88],[187.04,-117.68],[189.71,-117.52],[192.45,-117.4],[195.27,-117.31],[198.17,-117.25],[201.14,-117.22],[204.18,-117.19],[207.29,-117.18],[210.45,-117.18],[213.68,-117.17],[216.95,-117.15],[220.26,-117.12],[223.61,-117.06],[226.98,-116.98],[230.36,-116.87],[233.76,-116.72],[237.15,-116.53],[240.53,-116.3],[243.88,-116.02],[247.2,-115.68],[250.49,-115.29],[253.72,-114.84],[256.89,-114.33],[260.0,-113.76],[263.02,-113.13],[265.97,-112.44],[268.82,-111.68],[271.58,-110.86],[274.24,-109.99],[276.78,-109.05],[279.22,-108.06],[281.55,-107.01],[283.77,-105.91],[285.87,-104.76],[287.86,-103.56],[289.73,-102.32],[291.5,-101.05],[293.16,-99.73],[294.72,-98.39],[296.18,-97.02],[297.56,-95.62],[298.85,-94.2],[300.06,-92.77],[301.21,-91.32],[302.3,-89.86],[303.34,-88.4],[304.34,-86.93],[305.3,-85.46],[306.25,-83.99],[307.18,-82.52],[308.12,-81.06],[309.05,-79.6],[310.01,-78.15],[310.99,-76.71],[312.0,-75.27],[313.05,-73.84],[314.14,-72.42],[315.29,-71.0],[316.49,-69.6],[317.75,-68.19],[319.07,-66.79],[320.46,-65.39],[321.91,-63.99],[323.42,-62.59],[324.99,-61.18],[326.62,-59.77],[328.31,-58.34],[330.04,-56.91],[331.82,-55.47],[333.63,-54.01],[335.47,-52.54],[337.32,-51.05],[339.18,-49.54],[341.04,-48.01],[342.88,-46.46],[344.69,-44.89],[346.46,-43.29],[348.18,-41.67],[349.84,-40.04],[351.41,-38.38],[352.9,-36.7],[354.27,-35.0]],[[358.19,-35.0],[359.44,-33.26],[360.55,-31.5],[361.53,-29.73],[362.36,-27.95],[363.02,-26.16],[363.52,-24.37],[363.83,-22.57],[363.96,-20.78],[363.9,-18.99],[363.63,-17.21],[363.16,-15.44],[362.48,-13.69],[361.59,-11.96],[360.5,-10.25],[359.19,-8.57],[357.68,-6.91],[355.96,-5.3],[354.05,-3.72],[351.94,-2.17],[349.65,-0.68],[347.19,0.78],[344.55,2.18],[341.76,3.54],[338.83,4.85],[335.76,6.11],[332.58,7.32],[329.29,8.48],[325.91,9.59],[322.45,10.65],[318.93,11.66],[315.36,12.62],[311.76,13.55],[308.14,14.43],[304.52,15.27],[300.91,16.08],[297.32,16.86],[293.77,17.61],[290.27,18.33],[286.83,19.04],[283.46,19.73],[280.17,20.42],[276.96,21.09],[273.86,21.77],[270.85,22.45],[267.95,23.13],[265.16,23.83],[262.49,24.54],[259.93,25.28],[257.48,26.03],[255.15,26.82],[252.93,27.63],[250.82,28.47],[248.81,29.35],[246.9,30.26],[245.08,31.21],[243.35,32.19],[241.7,33.22],[240.12,34.27],[238.6,35.37],[237.13,36.5],[235.7,37.66],[234.31,38.85],[232.94,40.06],[231.59,41.31],[230.23,42.57],[228.88,43.85],[227.5,45.14],[226.11,46.44],[224.68,47.75],[223.21,49.05],[221.7,50.35],[220.13,51.63],[218.5,52.9],[216.81,54.15],[215.04,55.37],[213.21,56.57],[211.3,57.72],[209.32,58.84],[207.26,59.91],[205.12,60.94],[202.9,61.92],[200.61,62.84],[198.25,63.71],[195.81,64.53],[193.31,65.28],[190.75,65.98],[188.12,66.61],[185.45,67.19],[182.72,67.71],[179.96,68.17],[177.15,68.58],[174.32,68.94],[171.45,69.25],[168.57,69.51],[165.67,69.73],[162.76,69.91],[159.85,70.06],[156.94,70.18],[154.02,70.28],[151.12,70.36],[148.23,70.43],[145.35,70.49],[142.48,70.55],[139.63,70.62],[136.79,70.7],[133.98,70.79],[131.18,70.9],[128.39,71.04],[125.61,71.21],[122.85,71.42],[120.1,71.66],[117.35,71.94],[114.6,72.27],[111.84,72.65],[109.08,73.07],[106.31,73.55],[103.52,74.07],[100.71,74.64],[97.87,75.26],[95.0,75.93],[92.09,76.65],[89.15,77.4],[86.16,78.2],[83.12,79.03],[80.03,79.89],[76.89,80.78],[73.69,81.69],[70.43,82.61],[67.11,83.54],[63.73,84.47],[60.3,85.4],[56.8,86.31],[53.26,87.2],[49.66,88.07],[46.01,88.9],[42.31,89.7],[38.57,90.44],[34.8,91.13],[31.01,91.75],[27.19,92.31],[23.35,92.79],[19.51,93.19],[15.68,93.51],[11.85,93.73],[8.04,93.86],[4.26,93.9],[0.52,93.83],[-3.18,93.66],[-6.82,93.38],[-10.4,93.0],[-13.91,92.51],[-17.33,91.92],[-20.67,91.22],[-23.92,90.42],[-27.06,89.51],[-30.1,88.51],[-33.03,87.41],[-35.85,86.22],[-38.54,84.95],[-41.12,83.59],[-43.57,82.16],[-45.9,80.66],[-48.11,79.1],[-50.2,77.47],[-52.17,75.8],[-54.03,74.07],[-55.77,72.32],[-57.41,70.53],[-58.95,68.71],[-60.4,66.88],[-61.76,65.03],[-63.05,63.18],[-64.26,61.32],[-65.41,59.48],[-66.51,57.64],[-67.56,55.82],[-68.59,54.02],[-69.58,52.24],[-70.56,50.49],[-71.54,48.77],[-72.51,47.09],[-73.5,45.43],[-74.5,43.82],[-75.53,42.24],[-76.59,40.7],[-77.69,39.19],[-78.84,37.73],[-80.03,36.3],[-81.27,34.9],[-82.56,33.54],[-83.91,32.21],[-85.32,30.9],[-86.78,29.62],[-88.29,28.37],[-89.85,27.13],[-91.45,25.91],[-93.1,24.7],[-94.79,23.5],[-96.5,22.31],[-98.24,21.12],[-99.99,19.93],[-101.74,18.74],[-103.5,17.53],[-105.24,16.32],[-106.96,15.1],[-108.64,13.86],[-110.29,12.61],[-111.88,11.33],[-113.4,10.04],[-114.86,8.73],[-116.23,7.39],[-117.51,6.03],[-118.69,4.66],[-119.76,3.26],[-120.71,1.83],[-121.54,0.39],[-122.25,-1.07],[-122.82,-2.54],[-123.26,-4.04],[-123.56,-5.54],[-123.71,-7.06],[-123.73,-8.58],[-123.61,-10.12],[-123.36,-11.65],[-122.97,-13.19],[-122.45,-14.73],[-121.82,-16.26],[-121.06,-17.79],[-120.2,-19.3],[-119.24,-20.81],[-118.19,-22.31],[-117.06,-23.79],[-115.86,-25.25],[-114.61,-26.7],[-113.31,-28.13],[-111.99,-29.54],[-110.64,-30.94],[-109.3,-32.31],[-107.96,-33.66],[-106.64,-35.0],[-105.36,-36.32],[-104.12,-37.62],[-102.95,-38.91],[-101.84,-40.19],[-100.82,-41.46],[-99.88,-42.72],[-99.05,-43.97],[-98.32,-45.22],[-97.72,-46.47],[-97.23,-47.73],[-96.86,-48.99],[-96.63,-50.27],[-96.52,-51.55],[-96.55,-52.86],[-96.71,-54.18],[-97.0,-55.53],[-97.41,-56.9],[-97.94,-58.3],[-98.59,-59.73],[-99.34,-61.19],[-100.19,-62.69],[-101.14,-64.23],[-102.16,-65.8],[-103.25,-67.4],[-104.4,-69.05],[-105.59,-70.73],[-106.81,-72.45],[-108.05,-74.21],[-109.29,-76.0],[-110.52,-77.82],[-111.72,-79.68],[-112.88,-81.56],[-113.99,-83.47],[-115.03,-85.39],[-115.99,-87.34],[-116.85,-89.3],[-117.6,-91.27],[-118.23,-93.24],[-118.74,-95.21],[-119.1,-97.18],[-119.31,-99.14],[-119.37,-101.08],[-119.27,-103.01],[-118.99,-104.9],[-118.54,-106.77],[-117.92,-108.61],[-117.11,-110.41],[-116.13,-112.16],[-114.97,-113.87],[-113.63,-115.53],[-112.11,-117.13],[-110.43,-118.68],[-108.57,-120.17],[-106.56,-121.6],[-104.4,-122.96],[-102.09,-124.27],[-99.64,-125.51],[-97.06,-126.68],[-94.36,-127.79],[-91.56,-128.84],[-88.65,-129.83],[-85.66,-130.76],[-82.59,-131.64],[-79.45,-132.46],[-76.25,-133.23],[-73.01,-133.95],[-69.73,-134.63],[-66.42,-135.27],[-63.1,-135.88],[-59.76,-136.46],[-56.43,-137.01],[-53.1,-137.54],[-49.78,-138.05],[-46.48,-138.55],[-43.2,-139.04],[-39.96,-139.54],[-36.74,-140.03],[-33.56,-140.53],[-30.41,-141.04],[-27.3,-141.56],[-24.23,-142.09],[-21.19,-142.65],[-18.19,-143.22],[-15.22,-143.81],[-12.28,-144.43],[-9.37,-145.07],[-6.48,-145.73],[-3.62,-146.42],[-0.77,-147.13],[2.07,-147.85],[4.9,-148.6],[7.73,-149.36],[10.57,-150.13],[13.41,-150.91],[16.26,-151.69],[19.12,-152.47],[22.01,-153.25],[24.92,-154.02],[27.85,-154.77],[30.81,-155.5],[33.81,-156.2],[36.83,-156.88],[39.89,-157.51],[42.98,-158.1],[46.11,-158.64],[49.27,-159.12],[52.46,-159.55],[55.67,-159.9],[58.91,-160.19],[62.18,-160.41],[65.46,-160.54],[68.76,-160.6],[72.06,-160.57],[75.37,-160.46],[78.68,-160.25],[81.98,-159.96],[85.27,-159.57],[88.54,-159.1],[91.79,-158.54],[95.0,-157.89],[98.18,-157.16],[101.32,-156.34],[104.41,-155.45],[107.45,-154.47],[110.43,-153.43],[113.36,-152.33],[116.22,-151.16],[119.02,-149.94],[121.74,-148.67],[124.41,-147.36],[127.0,-146.01],[129.52,-144.64],[131.98,-143.24],[134.36,-141.84],[136.69,-140.43],[138.95,-139.02],[141.16,-137.62],[143.32,-136.24],[145.43,-134.88],[147.49,-133.55],[149.53,-132.26],[151.53,-131.01],[153.52,-129.8],[155.49,-128.65],[157.46,-127.55],[159.42,-126.52],[161.4,-125.54],[163.4,-124.64],[165.43,-123.8],[167.48,-123.03],[169.58,-122.32],[171.73,-121.69],[173.93,-121.13],[176.2,-120.63],[178.53,-120.2],[180.93,-119.83],[183.4,-119.52],[185.95,-119.27],[188.59,-119.06],[191.3,-118.9],[194.1,-118.79],[196.97,-118.71],[199.93,-118.66],[202.97,-118.63],[206.08,-118.62],[209.26,-118.63],[212.5,-118.64],[215.81,-118.64],[219.17,-118.64],[222.57,-118.63],[226.01,-118.6],[229.48,-118.54],[232.97,-118.45],[236.47,-118.32],[239.98,-118.16],[243.47,-117.95],[246.94,-117.68],[250.39,-117.37],[253.79,-117.0],[257.15,-116.57],[260.45,-116.08],[263.68,-115.52],[266.84,-114.9],[269.91,-114.22],[272.89,-113.47],[275.77,-112.66],[278.55,-111.79],[281.21,-110.85],[283.77,-109.86],[286.21,-108.81],[288.54,-107.7],[290.74,-106.54],[292.83,-105.33],[294.79,-104.07],[296.65,-102.78],[298.39,-101.44],[300.02,-100.07],[301.55,-98.67],[302.98,-97.24],[304.32,-95.79],[305.58,-94.32],[306.76,-92.84],[307.87,-91.34],[308.93,-89.83],[309.94,-88.32],[310.91,-86.8],[311.85,-85.29],[312.77,-83.77],[313.68,-82.26],[314.59,-80.75],[315.51,-79.25],[316.45,-77.76],[317.42,-76.28],[318.41,-74.8],[319.45,-73.33],[320.54,-71.86],[321.68,-70.41],[322.87,-68.95],[324.12,-67.51],[325.44,-66.06],[326.82,-64.62],[328.26,-63.17],[329.76,-61.72],[331.32,-60.27],[332.93,-58.81],[334.59,-57.34],[336.3,-55.86],[338.05,-54.36],[339.82,-52.86],[341.62,-51.33],[343.42,-49.79],[345.23,-48.23],[347.02,-46.65],[348.79,-45.05],[350.52,-43.42],[352.21,-41.78],[353.83,-40.12],[355.38,-38.43],[356.84,-36.72],[358.19,-35.0]],[[362.01,-35.0],[363.23,-33.23],[364.33,-31.45],[365.3,-29.66],[366.12,-27.85],[366.78,-26.04],[367.27,-24.22],[367.58,-22.4],[367.71,-20.58],[367.64,-18.77],[367.38,-16.96],[366.91,-15.17],[366.24,-13.39],[365.35,-11.63],[364.25,-9.9],[362.95,-8.19],[361.43,-6.51],[359.71,-4.87],[357.79,-3.26],[355.67,-1.7],[353.36,-0.18],[350.88,1.3],[348.22,2.73],[345.4,4.11],[342.44,5.44],[339.34,6.72],[336.11,7.95],[332.78,9.13],[329.34,10.25],[325.83,11.33],[322.26,12.35],[318.63,13.33],[314.96,14.26],[311.28,15.15],[307.58,16.01],[303.9,16.82],[300.24,17.6],[296.61,18.36],[293.03,19.09],[289.51,19.79],[286.06,20.49],[282.69,21.17],[279.4,21.84],[276.22,22.52],[273.14,23.19],[270.16,23.88],[267.3,24.57],[264.56,25.28],[261.93,26.01],[259.43,26.76],[257.04,27.54],[254.76,28.35],[252.6,29.2],[250.55,30.08],[248.6,30.99],[246.75,31.94],[244.99,32.94],[243.32,33.97],[241.72,35.04],[240.18,36.14],[238.71,37.29],[237.28,38.47],[235.89,39.68],[234.52,40.92],[233.18,42.2],[231.84,43.49],[230.5,44.8],[229.15,46.14],[227.77,47.48],[226.37,48.83],[224.93,50.18],[223.44,51.52],[221.9,52.86],[220.3,54.19],[218.64,55.49],[216.91,56.78],[215.1,58.03],[213.22,59.25],[211.26,60.43],[209.22,61.58],[207.1,62.67],[204.9,63.71],[202.62,64.71],[200.27,65.64],[197.84,66.52],[195.33,67.35],[192.77,68.11],[190.13,68.81],[187.44,69.45],[184.7,70.03],[181.91,70.55],[179.08,71.01],[176.21,71.42],[173.31,71.78],[170.38,72.09],[167.44,72.35],[164.48,72.57],[161.51,72.75],[158.54,72.91],[155.57,73.03],[152.6,73.14],[149.64,73.23],[146.69,73.31],[143.75,73.38],[140.83,73.46],[137.92,73.54],[135.03,73.64],[132.15,73.75],[129.28,73.89],[126.43,74.05],[123.59,74.25],[120.76,74.48],[117.93,74.75],[115.1,75.06],[112.28,75.42],[109.44,75.82],[106.59,76.28],[103.73,76.78],[100.85,77.33],[97.94,77.93],[95.0,78.57],[92.03,79.26],[89.01,80.0],[85.96,80.77],[82.85,81.58],[79.7,82.42],[76.49,83.29],[73.23,84.18],[69.91,85.09],[66.53,86.0],[63.09,86.92],[59.59,87.83],[56.04,88.74],[52.43,89.62],[48.77,90.48],[45.05,91.31],[41.3,92.09],[37.5,92.83],[33.66,93.52],[29.8,94.14],[25.91,94.7],[22.01,95.18],[18.11,95.58],[14.2,95.9],[10.31,96.12],[6.43,96.25],[2.58,96.28],[-1.23,96.22],[-5.0,96.04],[-8.71,95.76],[-12.36,95.37],[-15.93,94.88],[-19.42,94.28],[-22.83,93.57],[-26.13,92.75],[-29.34,91.83],[-32.44,90.81],[-35.42,89.7],[-38.29,88.48],[-41.03,87.19],[-43.65,85.8],[-46.14,84.34],[-48.51,82.8],[-50.75,81.2],[-52.87,79.54],[-54.86,77.82],[-56.74,76.06],[-58.49,74.25],[-60.14,72.41],[-61.68,70.55],[-63.13,68.66],[-64.48,66.76],[-65.75,64.86],[-66.94,62.95],[-68.07,61.04],[-69.14,59.15],[-70.16,57.27],[-71.14,55.41],[-72.1,53.58],[-73.04,51.77],[-73.96,49.99],[-74.89,48.25],[-75.82,46.54],[-76.78,44.88],[-77.75,43.24],[-78.76,41.65],[-79.81,40.1],[-80.9,38.59],[-82.04,37.12],[-83.23,35.68],[-84.48,34.28],[-85.78,32.91],[-87.15,31.57],[-88.57,30.26],[-90.05,28.98],[-91.58,27.71],[-93.17,26.47],[-94.8,25.24],[-96.48,24.02],[-98.19,22.82],[-99.93,21.61],[-101.69,20.41],[-103.47,19.21],[-105.25,18.0],[-107.02,16.78],[-108.78,15.55],[-110.51,14.31],[-112.21,13.05],[-113.86,11.78],[-115.45,10.48],[-116.98,9.17],[-118.43,7.83],[-119.79,6.47],[-121.06,5.1],[-122.22,3.69],[-123.27,2.27],[-124.2,0.83],[-125.0,-0.64],[-125.68,-2.12],[-126.22,-3.62],[-126.62,-5.13],[-126.88,-6.65],[-127.01,-8.19],[-126.99,-9.73],[-126.84,-11.28],[-126.55,-12.83],[-126.13,-14.38],[-125.58,-15.93],[-124.92,-17.48],[-124.14,-19.02],[-123.26,-20.55],[-122.28,-22.06],[-121.22,-23.57],[-120.09,-25.06],[-118.9,-26.53],[-117.65,-27.99],[-116.38,-29.43],[-115.07,-30.85],[-113.76,-32.25],[-112.45,-33.63],[-111.16,-35.0],[-109.89,-36.35],[-108.67,-37.68],[-107.5,-39.0],[-106.4,-40.31],[-105.38,-41.61],[-104.44,-42.9],[-103.6,-44.18],[-102.86,-45.46],[-102.24,-46.74],[-101.74,-48.03],[-101.36,-49.32],[-101.1,-50.62],[-100.98,-51.94],[-100.99,-53.27],[-101.13,-54.62],[-101.4,-56.0],[-101.79,-57.4],[-102.31,-58.83],[-102.94,-60.29],[-103.68,-61.78],[-104.53,-63.31],[-105.46,-64.87],[-106.48,-66.47],[-107.57,-68.11],[-108.72,-69.79],[-109.92,-71.5],[-111.15,-73.26],[-112.39,-75.05],[-113.65,-76.87],[-114.89,-78.73],[-116.11,-80.63],[-117.3,-82.55],[-118.43,-84.49],[-119.49,-86.46],[-120.47,-88.45],[-121.36,-90.45],[-122.14,-92.47],[-122.8,-94.49],[-123.33,-96.51],[-123.72,-98.52],[-123.96,-100.53],[-124.04,-102.52],[-123.95,-104.49],[-123.69,-106.44],[-123.26,-108.36],[-122.64,-110.24],[-121.85,-112.09],[-120.87,-113.89],[-119.7,-115.65],[-118.35,-117.35],[-116.82,-119.0],[-115.12,-120.59],[-113.24,-122.12],[-111.2,-123.59],[-109.0,-124.99],[-106.64,-126.33],[-104.14,-127.6],[-101.51,-128.8],[-98.75,-129.94],[-95.87,-131.02],[-92.89,-132.02],[-89.82,-132.97],[-86.66,-133.86],[-83.43,-134.69],[-80.14,-135.46],[-76.8,-136.18],[-73.41,-136.86],[-70.0,-137.5],[-66.56,-138.09],[-63.12,-138.65],[-59.66,-139.19],[-56.22,-139.7],[-52.78,-140.19],[-49.36,-140.66],[-45.97,-141.13],[-42.6,-141.59],[-39.27,-142.05],[-35.97,-142.51],[-32.71,-142.98],[-29.48,-143.46],[-26.3,-143.95],[-23.15,-144.47],[-20.05,-145.0],[-16.98,-145.55],[-13.94,-146.13],[-10.94,-146.72],[-7.96,-147.35],[-5.01,-147.99],[-2.08,-148.66],[0.84,-149.35],[3.74,-150.06],[6.64,-150.79],[9.54,-151.53],[12.44,-152.28],[15.35,-153.04],[18.27,-153.8],[21.2,-154.56],[24.16,-155.31],[27.13,-156.05],[30.14,-156.77],[33.17,-157.46],[36.23,-158.13],[39.33,-158.76],[42.45,-159.36],[45.61,-159.9],[48.8,-160.39],[52.02,-160.83],[55.27,-161.2],[58.54,-161.5],[61.83,-161.73],[65.14,-161.89],[68.47,-161.96],[71.81,-161.96],[75.15,-161.86],[78.49,-161.68],[81.83,-161.41],[85.15,-161.06],[88.46,-160.61],[91.75,-160.07],[95.0,-159.44],[98.22,-158.73],[101.4,-157.94],[104.53,-157.06],[107.62,-156.11],[110.65,-155.08],[113.62,-153.99],[116.53,-152.84],[119.37,-151.63],[122.14,-150.37],[124.85,-149.06],[127.49,-147.72],[130.06,-146.35],[132.56,-144.96],[135.0,-143.55],[137.36,-142.14],[139.67,-140.72],[141.92,-139.32],[144.12,-137.92],[146.27,-136.55],[148.38,-135.21],[150.45,-133.9],[152.49,-132.64],[154.51,-131.42],[156.52,-130.25],[158.52,-129.13],[160.53,-128.08],[162.54,-127.09],[164.57,-126.17],[166.63,-125.31],[168.72,-124.52],[170.85,-123.81],[173.03,-123.16],[175.27,-122.59],[177.57,-122.08],[179.94,-121.64],[182.38,-121.26],[184.89,-120.95],[187.49,-120.69],[190.17,-120.48],[192.93,-120.33],[195.78,-120.21],[198.72,-120.14],[201.74,-120.1],[204.84,-120.08],[208.01,-120.08],[211.27,-120.1],[214.59,-120.12],[217.98,-120.15],[221.42,-120.16],[224.92,-120.17],[228.45,-120.16],[232.02,-120.12],[235.62,-120.05],[239.23,-119.95],[242.84,-119.8],[246.45,-119.61],[250.04,-119.37],[253.61,-119.07],[257.13,-118.72],[260.62,-118.31],[264.04,-117.84],[267.4,-117.3],[270.68,-116.69],[273.88,-116.02],[276.99,-115.28],[279.99,-114.48],[282.89,-113.61],[285.68,-112.67],[288.36,-111.68],[290.91,-110.62],[293.34,-109.5],[295.65,-108.33],[297.84,-107.11],[299.9,-105.84],[301.84,-104.52],[303.66,-103.16],[305.37,-101.77],[306.96,-100.34],[308.45,-98.88],[309.84,-97.4],[311.14,-95.89],[312.36,-94.37],[313.5,-92.83],[314.57,-91.28],[315.59,-89.72],[316.56,-88.16],[317.49,-86.6],[318.4,-85.03],[319.29,-83.47],[320.17,-81.92],[321.05,-80.37],[321.95,-78.82],[322.86,-77.29],[323.81,-75.76],[324.79,-74.24],[325.81,-72.72],[326.88,-71.22],[328.0,-69.72],[329.18,-68.22],[330.42,-66.73],[331.72,-65.24],[333.09,-63.75],[334.51,-62.26],[335.99,-60.77],[337.53,-59.27],[339.12,-57.76],[340.75,-56.24],[342.43,-54.71],[344.13,-53.17],[345.86,-51.61],[347.6,-50.04],[349.35,-48.45],[351.09,-46.84],[352.81,-45.21],[354.5,-43.56],[356.14,-41.88],[357.73,-40.19],[359.24,-38.48],[360.67,-36.75],[362.01,-35.0]],[[365.72,-35.0],[366.92,-33.21],[368.0,-31.4],[368.95,-29.59],[369.76,-27.76],[370.41,-25.92],[370.89,-24.08],[371.21,-22.23],[371.33,-20.39],[371.27,-18.55],[371.01,-16.72],[370.54,-14.9],[369.87,-13.1],[368.99,-11.32],[367.89,-9.56],[366.59,-7.83],[365.07,-6.12],[363.35,-4.46],[361.42,-2.83],[359.29,-1.24],[356.98,0.31],[354.47,1.81],[351.8,3.26],[348.96,4.67],[345.97,6.02],[342.84,7.32],[339.58,8.57],[336.2,9.76],[332.73,10.9],[329.17,11.99],[325.54,13.04],[321.85,14.03],[318.13,14.97],[314.38,15.87],[310.62,16.73],[306.87,17.56],[303.14,18.35],[299.43,19.1],[295.78,19.84],[292.18,20.55],[288.65,21.24],[285.21,21.92],[281.85,22.6],[278.59,23.27],[275.43,23.94],[272.39,24.62],[269.46,25.31],[266.65,26.02],[263.96,26.75],[261.39,27.5],[258.94,28.28],[256.62,29.09],[254.41,29.93],[252.31,30.81],[250.32,31.73],[248.44,32.69],[246.65,33.69],[244.95,34.73],[243.33,35.81],[241.79,36.93],[240.3,38.09],[238.87,39.29],[237.48,40.53],[236.12,41.8],[234.79,43.1],[233.46,44.42],[232.14,45.77],[230.81,47.14],[229.46,48.52],[228.08,49.92],[226.67,51.32],[225.21,52.71],[223.7,54.11],[222.13,55.49],[220.5,56.85],[218.79,58.2],[217.02,59.51],[215.16,60.8],[213.22,62.05],[211.21,63.26],[209.11,64.42],[206.92,65.53],[204.66,66.59],[202.31,67.6],[199.89,68.55],[197.38,69.44],[194.81,70.26],[192.17,71.03],[189.47,71.73],[186.71,72.38],[183.9,72.96],[181.04,73.48],[178.13,73.94],[175.2,74.35],[172.23,74.71],[169.24,75.01],[166.23,75.28],[163.21,75.5],[160.18,75.69],[157.14,75.84],[154.11,75.97],[151.08,76.08],[148.06,76.18],[145.05,76.27],[142.05,76.36],[139.07,76.44],[136.1,76.54],[133.14,76.65],[130.2,76.79],[127.27,76.94],[124.35,77.13],[121.43,77.34],[118.53,77.6],[115.62,77.89],[112.72,78.23],[109.8,78.62],[106.88,79.05],[103.95,79.52],[100.99,80.05],[98.01,80.62],[95.0,81.24],[91.96,81.91],[88.88,82.62],[85.75,83.37],[82.59,84.15],[79.37,84.97],[76.1,85.81],[72.77,86.68],[69.39,87.57],[65.95,88.46],[62.45,89.37],[58.89,90.26],[55.28,91.15],[51.61,92.03],[47.89,92.87],[44.11,93.69],[40.29,94.47],[36.43,95.2],[32.53,95.88],[28.61,96.5],[24.66,97.05],[20.69,97.53],[16.72,97.93],[12.75,98.25],[8.79,98.47],[4.84,98.6],[0.93,98.63],[-2.95,98.56],[-6.78,98.38],[-10.56,98.1],[-14.27,97.71],[-17.91,97.2],[-21.47,96.59],[-24.94,95.87],[-28.31,95.04],[-31.57,94.11],[-34.73,93.07],[-37.77,91.94],[-40.68,90.71],[-43.47,89.38],[-46.14,87.97],[-48.67,86.48],[-51.08,84.91],[-53.35,83.27],[-55.5,81.57],[-57.51,79.82],[-59.4,78.01],[-61.18,76.16],[-62.83,74.28],[-64.37,72.36],[-65.82,70.42],[-67.16,68.47],[-68.41,66.51],[-69.59,64.55],[-70.69,62.59],[-71.73,60.64],[-72.72,58.7],[-73.67,56.79],[-74.59,54.89],[-75.48,53.03],[-76.36,51.2],[-77.23,49.4],[-78.12,47.64],[-79.02,45.92],[-79.94,44.24],[-80.89,42.59],[-81.89,41.0],[-82.92,39.44],[-84.01,37.92],[-85.15,36.44],[-86.35,35.0],[-87.62,33.6],[-88.94,32.23],[-90.33,30.88],[-91.77,29.57],[-93.28,28.28],[-94.85,27.02],[-96.47,25.77],[-98.13,24.53],[-99.84,23.31],[-101.59,22.09],[-103.36,20.88],[-105.15,19.67],[-106.96,18.45],[-108.77,17.23],[-110.57,15.99],[-112.35,14.75],[-114.1,13.49],[-115.81,12.21],[-117.47,10.92],[-119.07,9.6],[-120.6,8.27],[-122.04,6.91],[-123.4,5.53],[-124.66,4.13],[-125.81,2.7],[-126.84,1.26],[-127.75,-0.21],[-128.53,-1.69],[-129.18,-3.2],[-129.69,-4.71],[-130.06,-6.25],[-130.3,-7.79],[-130.39,-9.35],[-130.34,-10.91],[-130.15,-12.47],[-129.84,-14.04],[-129.39,-15.6],[-128.82,-17.17],[-128.13,-18.73],[-127.34,-20.28],[-126.44,-21.82],[-125.46,-23.34],[-124.4,-24.86],[-123.27,-26.36],[-122.08,-27.84],[-120.86,-29.31],[-119.6,-30.76],[-118.33,-32.19],[-117.05,-33.6],[-115.78,-35.0],[-114.54,-36.38],[-113.34,-37.74],[-112.18,-39.09],[-111.08,-40.43],[-110.06,-41.76],[-109.12,-43.08],[-108.27,-44.4],[-107.53,-45.71],[-106.89,-47.02],[-106.37,-48.34],[-105.97,-49.66],[-105.7,-50.99],[-105.56,-52.34],[-105.54,-53.7],[-105.66,-55.08],[-105.91,-56.48],[-106.28,-57.91],[-106.78,-59.37],[-107.39,-60.86],[-108.12,-62.38],[-108.95,-63.93],[-109.87,-65.53],[-110.88,-67.16],[-111.97,-68.83],[-113.11,-70.54],[-114.31,-72.28],[-115.54,-74.07],[-116.79,-75.9],[-118.05,-77.76],[-119.31,-79.65],[-120.54,-81.58],[-121.74,-83.54],[-122.89,-85.53],[-123.97,-87.54],[-124.98,-89.57],[-125.88,-91.61],[-126.69,-93.67],[-127.37,-95.73],[-127.92,-97.8],[-128.34,-99.86],[-128.6,-101.92],[-128.7,-103.96],[-128.63,-105.98],[-128.39,-107.97],[-127.96,-109.94],[-127.36,-111.87],[-126.57,-113.77],[-125.58,-115.62],[-124.41,-117.42],[-123.06,-119.17],[-121.51,-120.86],[-119.79,-122.49],[-117.89,-124.06],[-115.81,-125.57],[-113.57,-127.01],[-111.17,-128.38],[-108.62,-129.68],[-105.93,-130.92],[-103.11,-132.08],[-100.17,-133.18],[-97.12,-134.2],[-93.96,-135.17],[-90.72,-136.06],[-87.4,-136.9],[-84.01,-137.68],[-80.57,-138.41],[-77.08,-139.08],[-73.56,-139.71],[-70.01,-140.29],[-66.45,-140.84],[-62.88,-141.36],[-59.32,-141.84],[-55.77,-142.31],[-52.23,-142.76],[-48.71,-143.19],[-45.23,-143.62],[-41.77,-144.04],[-38.36,-144.47],[-34.98,-144.9],[-31.64,-145.34],[-28.35,-145.79],[-25.1,-146.26],[-21.88,-146.75],[-18.71,-147.26],[-15.58,-147.79],[-12.48,-148.35],[-9.41,-148.93],[-6.37,-149.53],[-3.36,-150.16],[-0.37,-150.82],[2.61,-151.49],[5.58,-152.18],[8.54,-152.89],[11.5,-153.61],[14.47,-154.34],[17.44,-155.08],[20.42,-155.82],[23.42,-156.55],[26.45,-157.27],[29.49,-157.98],[32.56,-158.67],[35.66,-159.34],[38.79,-159.97],[41.94,-160.56],[45.13,-161.11],[48.35,-161.61],[51.6,-162.06],[54.87,-162.44],[58.17,-162.76],[61.5,-163.01],[64.84,-163.19],[68.2,-163.28],[71.56,-163.3],[74.94,-163.23],[78.31,-163.08],[81.68,-162.83],[85.04,-162.5],[88.38,-162.08],[91.71,-161.57],[95.0,-160.97],[98.26,-160.28],[101.48,-159.51],[104.66,-158.66],[107.79,-157.73],[110.86,-156.72],[113.88,-155.65],[116.83,-154.51],[119.72,-153.31],[122.54,-152.07],[125.3,-150.77],[127.99,-149.44],[130.6,-148.07],[133.15,-146.69],[135.63,-145.28],[138.05,-143.86],[140.4,-142.45],[142.7,-141.03],[144.94,-139.63],[147.13,-138.25],[149.28,-136.9],[151.39,-135.58],[153.47,-134.3],[155.53,-133.07],[157.58,-131.88],[159.62,-130.75],[161.66,-129.69],[163.7,-128.68],[165.77,-127.74],[167.86,-126.87],[169.99,-126.07],[172.16,-125.34],[174.37,-124.68],[176.65,-124.09],[178.98,-123.57],[181.39,-123.12],[183.87,-122.74],[186.43,-122.41],[189.07,-122.15],[191.8,-121.94],[194.61,-121.79],[197.51,-121.68],[200.5,-121.61],[203.58,-121.57],[206.75,-121.56],[209.99,-121.57],[213.32,-121.6],[216.72,-121.64],[220.19,-121.68],[223.72,-121.71],[227.3,-121.73],[230.93,-121.74],[234.6,-121.72],[238.3,-121.67],[242.02,-121.59],[245.74,-121.46],[249.46,-121.29],[253.17,-121.07],[256.86,-120.8],[260.51,-120.46],[264.11,-120.07],[267.67,-119.61],[271.15,-119.09],[274.56,-118.49],[277.88,-117.83],[281.12,-117.1],[284.25,-116.31],[287.27,-115.44],[290.18,-114.51],[292.98,-113.51],[295.64,-112.45],[298.19,-111.32],[300.6,-110.14],[302.89,-108.91],[305.04,-107.62],[307.07,-106.28],[308.97,-104.9],[310.75,-103.48],[312.41,-102.02],[313.96,-100.53],[315.4,-99.01],[316.75,-97.47],[318.0,-95.91],[319.16,-94.33],[320.25,-92.73],[321.28,-91.13],[322.25,-89.52],[323.17,-87.91],[324.06,-86.3],[324.93,-84.69],[325.78,-83.09],[326.62,-81.48],[327.47,-79.89],[328.34,-78.3],[329.22,-76.72],[330.14,-75.15],[331.1,-73.59],[332.1,-72.03],[333.14,-70.48],[334.24,-68.94],[335.4,-67.4],[336.62,-65.87],[337.9,-64.33],[339.24,-62.8],[340.64,-61.26],[342.09,-59.72],[343.6,-58.18],[345.16,-56.62],[346.75,-55.06],[348.39,-53.48],[350.04,-51.89],[351.72,-50.28],[353.4,-48.66],[355.08,-47.02],[356.75,-45.36],[358.39,-43.68],[359.98,-41.99],[361.53,-40.27],[363.01,-38.53],[364.41,-36.77],[365.72,-35.0]],[[369.31,-35.0],[370.49,-33.19],[371.55,-31.36],[372.48,-29.52],[373.27,-27.66],[373.92,-25.8],[374.4,-23.94],[374.71,-22.07],[374.83,-20.2],[374.77,-18.34],[374.51,-16.49],[374.05,-14.65],[373.39,-12.82],[372.51,-11.01],[371.42,-9.23],[370.11,-7.47],[368.6,-5.75],[366.88,-4.05],[364.95,-2.4],[362.82,-0.79],[360.49,0.79],[357.98,2.31],[355.29,3.79],[352.44,5.21],[349.43,6.58],[346.27,7.91],[342.98,9.17],[339.57,10.39],[336.06,11.55],[332.46,12.65],[328.78,13.71],[325.04,14.72],[321.27,15.68],[317.46,16.59],[313.64,17.46],[309.82,18.29],[306.02,19.09],[302.25,19.85],[298.53,20.59],[294.86,21.3],[291.26,22.0],[287.74,22.68],[284.31,23.35],[280.97,24.03],[277.75,24.7],[274.63,25.38],[271.63,26.07],[268.76,26.77],[266.0,27.5],[263.37,28.25],[260.87,29.02],[258.49,29.83],[256.24,30.68],[254.1,31.56],[252.07,32.48],[250.15,33.45],[248.34,34.45],[246.61,35.5],[244.98,36.59],[243.42,37.73],[241.92,38.91],[240.49,40.13],[239.1,41.38],[237.75,42.68],[236.42,44.01],[235.11,45.37],[233.8,46.75],[232.49,48.16],[231.17,49.58],[229.81,51.02],[228.43,52.47],[227.0,53.92],[225.52,55.36],[223.98,56.8],[222.37,58.23],[220.7,59.63],[218.95,61.01],[217.12,62.36],[215.21,63.68],[213.22,64.96],[211.14,66.19],[208.97,67.37],[206.72,68.5],[204.38,69.58],[201.96,70.6],[199.46,71.56],[196.89,72.45],[194.24,73.29],[191.52,74.06],[188.75,74.76],[185.91,75.4],[183.02,75.98],[180.09,76.5],[177.11,76.96],[174.1,77.37],[171.07,77.72],[168.01,78.03],[164.93,78.29],[161.84,78.51],[158.74,78.7],[155.65,78.85],[152.55,78.99],[149.46,79.1],[146.37,79.21],[143.3,79.3],[140.24,79.4],[137.19,79.5],[134.15,79.61],[131.13,79.73],[128.11,79.88],[125.11,80.05],[122.12,80.26],[119.13,80.5],[116.15,80.77],[113.16,81.09],[110.17,81.45],[107.17,81.85],[104.16,82.3],[101.13,82.8],[98.08,83.35],[95.0,83.94],[91.89,84.58],[88.74,85.26],[85.55,85.98],[82.32,86.74],[79.04,87.53],[75.7,88.35],[72.31,89.19],[68.87,90.05],[65.37,90.93],[61.81,91.81],[58.2,92.69],[54.52,93.56],[50.79,94.42],[47.01,95.25],[43.18,96.06],[39.3,96.82],[35.38,97.55],[31.42,98.22],[27.43,98.83],[23.42,99.38],[19.39,99.85],[15.36,100.25],[11.32,100.56],[7.3,100.78],[3.29,100.91],[-0.69,100.93],[-4.64,100.86],[-8.54,100.68],[-12.38,100.39],[-16.16,99.99],[-19.86,99.48],[-23.48,98.86],[-27.01,98.13],[-30.44,97.29],[-33.76,96.34],[-36.97,95.29],[-40.07,94.14],[-43.03,92.88],[-45.87,91.54],[-48.58,90.1],[-51.16,88.58],[-53.6,86.98],[-55.91,85.31],[-58.08,83.57],[-60.12,81.78],[-62.03,79.93],[-63.81,78.04],[-65.48,76.11],[-67.02,74.15],[-68.46,72.16],[-69.8,70.16],[-71.04,68.14],[-72.2,66.13],[-73.28,64.11],[-74.29,62.11],[-75.25,60.11],[-76.16,58.14],[-77.04,56.19],[-77.89,54.27],[-78.72,52.39],[-79.55,50.53],[-80.38,48.72],[-81.23,46.95],[-82.1,45.21],[-83.0,43.52],[-83.94,41.88],[-84.92,40.27],[-85.96,38.71],[-87.05,37.19],[-88.2,35.71],[-89.42,34.27],[-90.7,32.87],[-92.05,31.5],[-93.46,30.16],[-94.95,28.84],[-96.49,27.55],[-98.09,26.29],[-99.75,25.03],[-101.46,23.79],[-103.21,22.56],[-104.99,21.34],[-106.8,20.12],[-108.63,18.89],[-110.48,17.66],[-112.32,16.43],[-114.14,15.18],[-115.95,13.92],[-117.72,12.64],[-119.45,11.35],[-121.13,10.03],[-122.74,8.7],[-124.28,7.34],[-125.72,5.96],[-127.08,4.56],[-128.33,3.13],[-129.47,1.69],[-130.48,0.22],[-131.38,-1.27],[-132.14,-2.78],[-132.76,-4.3],[-133.25,-5.84],[-133.6,-7.39],[-133.8,-8.96],[-133.87,-10.53],[-133.79,-12.11],[-133.58,-13.69],[-133.24,-15.27],[-132.77,-16.85],[-132.18,-18.43],[-131.48,-20.0],[-130.67,-21.56],[-129.77,-23.12],[-128.78,-24.66],[-127.72,-26.18],[-126.6,-27.69],[-125.43,-29.19],[-124.22,-30.67],[-122.99,-32.13],[-121.76,-33.57],[-120.52,-35.0],[-119.31,-36.41],[-118.12,-37.81],[-116.98,-39.19],[-115.89,-40.56],[-114.87,-41.92],[-113.93,-43.27],[-113.07,-44.62],[-112.32,-45.96],[-111.67,-47.3],[-111.13,-48.65],[-110.71,-50.0],[-110.42,-51.37],[-110.25,-52.74],[-110.21,-54.13],[-110.31,-55.54],[-110.53,-56.98],[-110.88,-58.43],[-111.35,-59.92],[-111.94,-61.44],[-112.65,-62.99],[-113.46,-64.57],[-114.37,-66.2],[-115.36,-67.86],[-116.43,-69.56],[-117.57,-71.3],[-118.76,-73.08],[-119.99,-74.9],[-121.24,-76.76],[-122.51,-78.65],[-123.77,-80.58],[-125.01,-82.55],[-126.22,-84.55],[-127.38,-86.57],[-128.48,-88.62],[-129.5,-90.69],[-130.42,-92.78],[-131.25,-94.88],[-131.95,-96.98],[-132.52,-99.09],[-132.95,-101.2],[-133.23,-103.3],[-133.35,-105.39],[-133.29,-107.46],[-133.06,-109.5],[-132.65,-111.52],[-132.05,-113.5],[-131.26,-115.44],[-130.28,-117.33],[-129.11,-119.18],[-127.74,-120.97],[-126.18,-122.71],[-124.44,-124.39],[-122.51,-126.0],[-120.4,-127.54],[-118.12,-129.02],[-115.68,-130.42],[-113.08,-131.76],[-110.34,-133.02],[-107.45,-134.21],[-104.44,-135.32],[-101.31,-136.37],[-98.08,-137.35],[-94.75,-138.26],[-91.34,-139.1],[-87.86,-139.89],[-84.32,-140.61],[-80.73,-141.28],[-77.1,-141.9],[-73.44,-142.48],[-69.76,-143.01],[-66.08,-143.51],[-62.4,-143.98],[-58.73,-144.42],[-55.07,-144.84],[-51.44,-145.24],[-47.83,-145.64],[-44.26,-146.02],[-40.72,-146.41],[-37.23,-146.8],[-33.78,-147.2],[-30.37,-147.61],[-27.01,-148.04],[-23.69,-148.48],[-20.42,-148.95],[-17.18,-149.43],[-13.99,-149.94],[-10.83,-150.48],[-7.71,-151.04],[-4.61,-151.63],[-1.54,-152.24],[1.51,-152.88],[4.55,-153.53],[7.57,-154.21],[10.59,-154.9],[13.61,-155.6],[16.64,-156.31],[19.67,-157.03],[22.72,-157.75],[25.78,-158.45],[28.87,-159.15],[31.98,-159.83],[35.11,-160.49],[38.27,-161.12],[41.46,-161.72],[44.67,-162.27],[47.92,-162.78],[51.2,-163.23],[54.5,-163.63],[57.83,-163.97],[61.18,-164.24],[64.55,-164.43],[67.93,-164.56],[71.33,-164.6],[74.73,-164.55],[78.14,-164.43],[81.54,-164.21],[84.93,-163.91],[88.31,-163.51],[91.67,-163.03],[95.0,-162.46],[98.3,-161.8],[101.56,-161.06],[104.78,-160.23],[107.95,-159.33],[111.07,-158.35],[114.13,-157.29],[117.13,-156.18],[120.07,-155.0],[122.94,-153.77],[125.75,-152.49],[128.48,-151.16],[131.15,-149.81],[133.75,-148.43],[136.27,-147.02],[138.74,-145.61],[141.14,-144.19],[143.48,-142.78],[145.77,-141.37],[148.01,-139.99],[150.2,-138.63],[152.35,-137.3],[154.48,-136.01],[156.58,-134.76],[158.66,-133.56],[160.74,-132.42],[162.82,-131.33],[164.9,-130.31],[167.0,-129.36],[169.13,-128.47],[171.29,-127.65],[173.5,-126.91],[175.75,-126.24],[178.06,-125.64],[180.44,-125.11],[182.88,-124.65],[185.41,-124.25],[188.01,-123.93],[190.69,-123.66],[193.47,-123.45],[196.33,-123.29],[199.29,-123.18],[202.34,-123.11],[205.48,-123.08],[208.7,-123.07],[212.02,-123.1],[215.42,-123.13],[218.89,-123.18],[222.44,-123.23],[226.06,-123.28],[229.73,-123.32],[233.45,-123.35],[237.22,-123.35],[241.02,-123.32],[244.84,-123.25],[248.68,-123.15],[252.51,-123.0],[256.34,-122.8],[260.14,-122.54],[263.91,-122.22],[267.64,-121.85],[271.32,-121.4],[274.93,-120.89],[278.47,-120.31],[281.92,-119.66],[285.28,-118.94],[288.54,-118.15],[291.68,-117.29],[294.72,-116.35],[297.63,-115.35],[300.41,-114.29],[303.06,-113.15],[305.58,-111.96],[307.97,-110.71],[310.22,-109.41],[312.34,-108.05],[314.32,-106.65],[316.17,-105.2],[317.9,-103.71],[319.51,-102.19],[321.0,-100.64],[322.39,-99.06],[323.67,-97.46],[324.86,-95.83],[325.97,-94.2],[327.0,-92.55],[327.97,-90.9],[328.89,-89.24],[329.76,-87.58],[330.6,-85.92],[331.42,-84.26],[332.22,-82.61],[333.02,-80.96],[333.83,-79.32],[334.66,-77.69],[335.51,-76.07],[336.39,-74.45],[337.32,-72.85],[338.28,-71.25],[339.3,-69.66],[340.38,-68.07],[341.51,-66.49],[342.7,-64.91],[343.95,-63.34],[345.26,-61.76],[346.63,-60.18],[348.05,-58.59],[349.52,-57.0],[351.03,-55.4],[352.58,-53.79],[354.17,-52.16],[355.77,-50.53],[357.38,-48.87],[359.0,-47.2],[360.6,-45.52],[362.19,-43.81],[363.73,-42.08],[365.23,-40.34],[366.67,-38.58],[368.04,-36.8],[369.31,-35.0]],[[372.8,-35.0],[373.94,-33.16],[374.98,-31.31],[375.89,-29.45],[376.67,-27.57],[377.3,-25.69],[377.78,-23.81],[378.08,-21.92],[378.21,-20.03],[378.15,-18.14],[377.89,-16.27],[377.44,-14.4],[376.78,-12.55],[375.91,-10.72],[374.82,-8.91],[373.53,-7.13],[372.02,-5.38],[370.3,-3.66],[368.37,-1.99],[366.24,-0.35],[363.92,1.25],[361.4,2.79],[358.71,4.29],[355.84,5.74],[352.81,7.14],[349.63,8.48],[346.32,9.77],[342.88,11.0],[339.33,12.18],[335.7,13.31],[331.98,14.38],[328.2,15.4],[324.37,16.37],[320.51,17.3],[316.64,18.18],[312.76,19.02],[308.9,19.82],[305.06,20.59],[301.27,21.34],[297.54,22.06],[293.87,22.76],[290.28,23.44],[286.78,24.12],[283.37,24.79],[280.08,25.46],[276.89,26.14],[273.83,26.83],[270.89,27.53],[268.08,28.25],[265.39,29.0],[262.83,29.78],[260.4,30.59],[258.1,31.44],[255.92,32.32],[253.85,33.25],[251.9,34.22],[250.06,35.23],[248.31,36.29],[246.65,37.39],[245.08,38.54],[243.58,39.74],[242.14,40.98],[240.75,42.26],[239.4,43.58],[238.08,44.94],[236.78,46.33],[235.5,47.75],[234.2,49.19],[232.9,50.66],[231.57,52.15],[230.21,53.64],[228.81,55.14],[227.36,56.64],[225.85,58.14],[224.28,59.62],[222.63,61.09],[220.91,62.53],[219.11,63.95],[217.23,65.33],[215.25,66.68],[213.19,67.98],[211.04,69.23],[208.81,70.44],[206.48,71.59],[204.07,72.68],[201.57,73.7],[198.99,74.67],[196.33,75.57],[193.61,76.41],[190.81,77.18],[187.95,77.88],[185.04,78.52],[182.07,79.1],[179.06,79.61],[176.01,80.07],[172.92,80.47],[169.81,80.82],[166.68,81.12],[163.53,81.38],[160.37,81.6],[157.21,81.78],[154.04,81.94],[150.87,82.07],[147.72,82.19],[144.56,82.3],[141.42,82.4],[138.29,82.5],[135.17,82.61],[132.07,82.73],[128.97,82.87],[125.89,83.03],[122.82,83.22],[119.75,83.44],[116.68,83.69],[113.62,83.98],[110.55,84.32],[107.47,84.7],[104.38,85.12],[101.28,85.59],[98.15,86.1],[95.0,86.66],[91.82,87.27],[88.6,87.92],[85.35,88.61],[82.05,89.33],[78.7,90.1],[75.3,90.89],[71.86,91.7],[68.35,92.54],[64.79,93.39],[61.17,94.24],[57.5,95.1],[53.77,95.95],[49.98,96.79],[46.14,97.61],[42.25,98.4],[38.31,99.15],[34.33,99.86],[30.32,100.52],[26.27,101.13],[22.2,101.67],[18.11,102.13],[14.02,102.52],[9.92,102.83],[5.83,103.05],[1.76,103.17],[-2.28,103.19],[-6.29,103.11],[-10.25,102.93],[-14.16,102.63],[-18.0,102.23],[-21.76,101.71],[-25.45,101.08],[-29.04,100.34],[-32.53,99.49],[-35.91,98.53],[-39.17,97.46],[-42.32,96.29],[-45.34,95.02],[-48.23,93.65],[-50.98,92.19],[-53.6,90.64],[-56.07,89.01],[-58.41,87.31],[-60.61,85.54],[-62.68,83.71],[-64.61,81.82],[-66.41,79.88],[-68.08,77.91],[-69.63,75.9],[-71.07,73.87],[-72.4,71.82],[-73.63,69.75],[-74.77,67.68],[-75.83,65.61],[-76.82,63.55],[-77.74,61.51],[-78.62,59.48],[-79.46,57.48],[-80.26,55.5],[-81.05,53.56],[-81.83,51.65],[-82.61,49.79],[-83.41,47.96],[-84.23,46.18],[-85.07,44.44],[-85.96,42.74],[-86.89,41.1],[-87.87,39.49],[-88.91,37.93],[-90.02,36.42],[-91.19,34.94],[-92.43,33.5],[-93.74,32.1],[-95.13,30.73],[-96.58,29.39],[-98.1,28.08],[-99.69,26.79],[-101.34,25.52],[-103.04,24.27],[-104.79,23.03],[-106.59,21.79],[-108.42,20.56],[-110.28,19.33],[-112.15,18.09],[-114.04,16.85],[-115.91,15.6],[-117.78,14.34],[-119.61,13.07],[-121.42,11.77],[-123.17,10.46],[-124.86,9.12],[-126.49,7.77],[-128.03,6.39],[-129.49,4.99],[-130.84,3.56],[-132.09,2.12],[-133.22,0.65],[-134.23,-0.84],[-135.11,-2.36],[-135.85,-3.88],[-136.46,-5.43],[-136.92,-6.99],[-137.25,-8.56],[-137.43,-10.15],[-137.47,-11.74],[-137.37,-13.34],[-137.14,-14.93],[-136.77,-16.53],[-136.29,-18.13],[-135.68,-19.72],[-134.96,-21.31],[-134.15,-22.88],[-133.24,-24.45],[-132.26,-26.0],[-131.21,-27.54],[-130.1,-29.07],[-128.95,-30.57],[-127.77,-32.07],[-126.57,-33.54],[-125.37,-35.0],[-124.18,-36.44],[-123.02,-37.87],[-121.89,-39.29],[-120.81,-40.69],[-119.8,-42.08],[-118.85,-43.47],[-118.0,-44.85],[-117.23,-46.22],[-116.57,-47.6],[-116.01,-48.97],[-115.57,-50.36],[-115.26,-51.75],[-115.07,-53.16],[-115.0,-54.58],[-115.07,-56.02],[-115.26,-57.48],[-115.58,-58.97],[-116.03,-60.49],[-116.59,-62.03],[-117.27,-63.61],[-118.06,-65.23],[-118.95,-66.88],[-119.92,-68.57],[-120.98,-70.3],[-122.1,-72.07],[-123.28,-73.88],[-124.5,-75.73],[-125.74,-77.62],[-127.01,-79.55],[-128.27,-81.52],[-129.51,-83.52],[-130.73,-85.55],[-131.89,-87.62],[-133.0,-89.7],[-134.03,-91.82],[-134.97,-93.94],[-135.81,-96.08],[-136.53,-98.23],[-137.11,-100.39],[-137.56,-102.54],[-137.85,-104.69],[-137.98,-106.82],[-137.94,-108.93],[-137.72,-111.02],[-137.32,-113.08],[-136.72,-115.11],[-135.93,-117.1],[-134.95,-119.04],[-133.77,-120.93],[-132.39,-122.77],[-130.82,-124.55],[-129.05,-126.27],[-127.1,-127.92],[-124.96,-129.5],[-122.64,-131.01],[-120.15,-132.45],[-117.51,-133.81],[-114.7,-135.1],[-111.76,-136.32],[-108.68,-137.46],[-105.48,-138.52],[-102.17,-139.52],[-98.76,-140.44],[-95.26,-141.29],[-91.68,-142.08],[-88.04,-142.8],[-84.34,-143.47],[-80.61,-144.09],[-76.84,-144.65],[-73.05,-145.17],[-69.25,-145.65],[-65.46,-146.09],[-61.66,-146.51],[-57.89,-146.9],[-54.13,-147.27],[-50.41,-147.63],[-46.72,-147.99],[-43.07,-148.33],[-39.45,-148.68],[-35.89,-149.04],[-32.37,-149.41],[-28.9,-149.79],[-25.47,-150.19],[-22.1,-150.6],[-18.77,-151.05],[-15.48,-151.51],[-12.23,-152.0],[-9.02,-152.52],[-5.84,-153.06],[-2.69,-153.63],[0.44,-154.23],[3.54,-154.85],[6.63,-155.49],[9.72,-156.15],[12.79,-156.82],[15.87,-157.51],[18.95,-158.2],[22.04,-158.89],[25.15,-159.59],[28.27,-160.27],[31.41,-160.94],[34.58,-161.6],[37.77,-162.22],[40.99,-162.82],[44.24,-163.38],[47.51,-163.9],[50.81,-164.36],[54.14,-164.78],[57.49,-165.13],[60.87,-165.42],[64.26,-165.64],[67.67,-165.78],[71.1,-165.85],[74.53,-165.84],[77.97,-165.74],[81.4,-165.55],[84.82,-165.28],[88.24,-164.92],[91.63,-164.47],[95.0,-163.93],[98.34,-163.3],[101.64,-162.59],[104.9,-161.79],[108.12,-160.91],[111.28,-159.96],[114.39,-158.93],[117.44,-157.84],[120.42,-156.68],[123.35,-155.47],[126.2,-154.21],[128.98,-152.9],[131.7,-151.56],[134.35,-150.18],[136.93,-148.79],[139.44,-147.38],[141.89,-145.97],[144.28,-144.55],[146.61,-143.14],[148.9,-141.75],[151.14,-140.39],[153.34,-139.05],[155.5,-137.75],[157.65,-136.49],[159.77,-135.28],[161.89,-134.13],[164.01,-133.03],[166.13,-131.99],[168.27,-131.02],[170.44,-130.12],[172.64,-129.29],[174.88,-128.53],[177.18,-127.84],[179.53,-127.23],[181.94,-126.69],[184.43,-126.22],[186.99,-125.82],[189.64,-125.48],[192.37,-125.21],[195.19,-124.99],[198.1,-124.83],[201.11,-124.72],[204.22,-124.65],[207.41,-124.62],[210.71,-124.63],[214.09,-124.65],[217.56,-124.7],[221.11,-124.76],[224.74,-124.82],[228.43,-124.89],[232.2,-124.94],[236.01,-124.98],[239.88,-125.0],[243.78,-124.98],[247.7,-124.94],[251.65,-124.85],[255.59,-124.72],[259.54,-124.54],[263.46,-124.3],[267.35,-124.0],[271.2,-123.64],[275.01,-123.21],[278.74,-122.71],[282.41,-122.14],[285.98,-121.5],[289.47,-120.79],[292.85,-120.0],[296.12,-119.14],[299.28,-118.21],[302.3,-117.21],[305.2,-116.14],[307.97,-115.0],[310.59,-113.79],[313.08,-112.53],[315.43,-111.21],[317.63,-109.83],[319.7,-108.4],[321.63,-106.93],[323.42,-105.41],[325.09,-103.86],[326.63,-102.27],[328.06,-100.65],[329.38,-99.01],[330.59,-97.35],[331.72,-95.67],[332.76,-93.98],[333.73,-92.28],[334.63,-90.57],[335.48,-88.86],[336.3,-87.15],[337.08,-85.44],[337.84,-83.74],[338.59,-82.04],[339.34,-80.34],[340.11,-78.66],[340.89,-76.99],[341.7,-75.32],[342.54,-73.66],[343.43,-72.02],[344.36,-70.38],[345.34,-68.74],[346.38,-67.11],[347.48,-65.49],[348.64,-63.87],[349.85,-62.25],[351.12,-60.63],[352.45,-59.0],[353.83,-57.37],[355.26,-55.74],[356.73,-54.09],[358.22,-52.43],[359.75,-50.76],[361.29,-49.08],[362.83,-47.38],[364.37,-45.66],[365.89,-43.93],[367.39,-42.18],[368.84,-40.41],[370.23,-38.63],[371.55,-36.82],[372.8,-35.0]],[[376.17,-35.0],[377.28,-33.14],[378.29,-31.27],[379.18,-29.38],[379.94,-27.49],[380.56,-25.58],[381.03,-23.68],[381.33,-21.77],[381.45,-19.85],[381.4,-17.95],[381.15,-16.05],[380.7,-14.16],[380.05,-12.29],[379.18,-10.44],[378.11,-8.61],[376.82,-6.8],[375.33,-5.03],[373.62,-3.29],[371.7,-1.58],[369.57,0.08],[367.25,1.7],[364.73,3.27],[362.03,4.79],[359.16,6.26],[356.12,7.68],[352.92,9.04],[349.59,10.35],[346.13,11.6],[342.56,12.8],[338.89,13.95],[335.14,15.04],[331.32,16.07],[327.45,17.06],[323.55,18.0],[319.62,18.89],[315.69,19.75],[311.77,20.56],[307.88,21.34],[304.02,22.09],[300.22,22.81],[296.49,23.52],[292.83,24.21],[289.27,24.88],[285.8,25.56],[282.43,26.23],[279.19,26.91],[276.06,27.6],[273.06,28.3],[270.18,29.02],[267.44,29.77],[264.83,30.55],[262.35,31.36],[260.0,32.21],[257.77,33.1],[255.67,34.03],[253.69,35.0],[251.81,36.02],[250.04,37.09],[248.36,38.21],[246.78,39.37],[245.26,40.59],[243.82,41.85],[242.43,43.15],[241.09,44.5],[239.78,45.88],[238.49,47.31],[237.22,48.76],[235.94,50.25],[234.66,51.76],[233.36,53.28],[232.02,54.83],[230.65,56.38],[229.23,57.93],[227.75,59.49],[226.21,61.03],[224.59,62.56],[222.9,64.07],[221.12,65.55],[219.27,67.01],[217.32,68.42],[215.28,69.79],[213.15,71.12],[210.92,72.4],[208.6,73.62],[206.2,74.78],[203.7,75.88],[201.12,76.92],[198.46,77.89],[195.72,78.79],[192.9,79.63],[190.02,80.4],[187.08,81.1],[184.08,81.73],[181.03,82.31],[177.94,82.81],[174.81,83.26],[171.64,83.66],[168.45,84.0],[165.25,84.29],[162.02,84.54],[158.79,84.76],[155.55,84.94],[152.31,85.09],[149.08,85.22],[145.85,85.34],[142.63,85.45],[139.42,85.55],[136.22,85.66],[133.03,85.77],[129.85,85.9],[126.68,86.05],[123.52,86.22],[120.37,86.42],[117.22,86.65],[114.08,86.92],[110.93,87.23],[107.77,87.58],[104.6,87.97],[101.42,88.4],[98.22,88.89],[95.0,89.41],[91.75,89.98],[88.46,90.6],[85.14,91.25],[81.77,91.95],[78.36,92.67],[74.91,93.43],[71.4,94.21],[67.83,95.02],[64.21,95.84],[60.54,96.67],[56.81,97.5],[53.02,98.33],[49.18,99.14],[45.28,99.94],[41.33,100.71],[37.34,101.45],[33.31,102.15],[29.23,102.8],[25.13,103.39],[21.0,103.92],[16.86,104.38],[12.7,104.76],[8.55,105.06],[4.4,105.27],[0.27,105.38],[-3.84,105.4],[-7.91,105.32],[-11.93,105.12],[-15.9,104.83],[-19.8,104.41],[-23.63,103.89],[-27.37,103.25],[-31.02,102.5],[-34.56,101.64],[-38.0,100.67],[-41.32,99.59],[-44.52,98.4],[-47.59,97.11],[-50.53,95.72],[-53.33,94.23],[-55.98,92.66],[-58.5,91.0],[-60.87,89.27],[-63.1,87.47],[-65.19,85.6],[-67.14,83.67],[-68.95,81.7],[-70.64,79.68],[-72.19,77.63],[-73.63,75.55],[-74.96,73.45],[-76.18,71.33],[-77.3,69.21],[-78.34,67.09],[-79.31,64.98],[-80.2,62.88],[-81.05,60.8],[-81.85,58.74],[-82.61,56.71],[-83.36,54.72],[-84.09,52.76],[-84.82,50.84],[-85.57,48.96],[-86.33,47.13],[-87.12,45.34],[-87.95,43.6],[-88.83,41.91],[-89.76,40.26],[-90.76,38.66],[-91.81,37.11],[-92.94,35.6],[-94.14,34.13],[-95.42,32.69],[-96.77,31.3],[-98.19,29.93],[-99.69,28.6],[-101.26,27.29],[-102.9,26.0],[-104.6,24.73],[-106.36,23.48],[-108.16,22.23],[-110.02,20.99],[-111.9,19.76],[-113.81,18.52],[-115.73,17.28],[-117.66,16.02],[-119.58,14.76],[-121.48,13.48],[-123.36,12.19],[-125.19,10.88],[-126.97,9.55],[-128.69,8.19],[-130.33,6.82],[-131.89,5.42],[-133.35,3.99],[-134.71,2.54],[-135.96,1.07],[-137.08,-0.42],[-138.08,-1.93],[-138.95,-3.47],[-139.68,-5.02],[-140.27,-6.59],[-140.72,-8.17],[-141.02,-9.76],[-141.18,-11.37],[-141.2,-12.98],[-141.09,-14.59],[-140.83,-16.21],[-140.45,-17.83],[-139.95,-19.44],[-139.33,-21.05],[-138.61,-22.65],[-137.79,-24.24],[-136.88,-25.82],[-135.91,-27.39],[-134.86,-28.94],[-133.77,-30.48],[-132.65,-32.0],[-131.49,-33.51],[-130.33,-35.0],[-129.18,-36.48],[-128.04,-37.94],[-126.93,-39.39],[-125.86,-40.82],[-124.85,-42.25],[-123.91,-43.67],[-123.05,-45.08],[-122.27,-46.49],[-121.59,-47.9],[-121.02,-49.31],[-120.56,-50.72],[-120.22,-52.15],[-120.0,-53.58],[-119.91,-55.04],[-119.94,-56.51],[-120.11,-58.0],[-120.4,-59.52],[-120.81,-61.06],[-121.34,-62.64],[-121.99,-64.25],[-122.75,-65.89],[-123.61,-67.57],[-124.56,-69.29],[-125.59,-71.05],[-126.7,-72.86],[-127.86,-74.7],[-129.06,-76.58],[-130.3,-78.5],[-131.55,-80.47],[-132.8,-82.47],[-134.05,-84.5],[-135.26,-86.57],[-136.43,-88.67],[-137.54,-90.79],[-138.58,-92.94],[-139.53,-95.11],[-140.37,-97.29],[-141.1,-99.48],[-141.7,-101.68],[-142.15,-103.88],[-142.46,-106.06],[-142.6,-108.24],[-142.56,-110.4],[-142.35,-112.54],[-141.95,-114.64],[-141.36,-116.72],[-140.57,-118.75],[-139.58,-120.73],[-138.4,-122.67],[-137.01,-124.55],[-135.41,-126.37],[-133.63,-128.13],[-131.65,-129.82],[-129.48,-131.44],[-127.12,-132.99],[-124.59,-134.46],[-121.89,-135.86],[-119.04,-137.17],[-116.03,-138.41],[-112.89,-139.57],[-109.61,-140.66],[-106.22,-141.66],[-102.73,-142.6],[-99.14,-143.46],[-95.47,-144.25],[-91.73,-144.98],[-87.93,-145.64],[-84.09,-146.25],[-80.21,-146.8],[-76.31,-147.31],[-72.4,-147.77],[-68.48,-148.19],[-64.57,-148.58],[-60.68,-148.94],[-56.81,-149.29],[-52.96,-149.61],[-49.15,-149.92],[-45.38,-150.23],[-41.65,-150.54],[-37.97,-150.86],[-34.34,-151.18],[-30.76,-151.51],[-27.23,-151.86],[-23.75,-152.24],[-20.32,-152.63],[-16.93,-153.05],[-13.59,-153.49],[-10.3,-153.96],[-7.03,-154.47],[-3.81,-154.99],[-0.61,-155.55],[2.57,-156.13],[5.72,-156.73],[8.86,-157.36],[12.0,-158.0],[15.13,-158.66],[18.26,-159.33],[21.39,-160.0],[24.54,-160.68],[27.7,-161.35],[30.88,-162.01],[34.07,-162.66],[37.3,-163.28],[40.54,-163.88],[43.81,-164.44],[47.11,-164.97],[50.44,-165.45],[53.79,-165.87],[57.17,-166.25],[60.57,-166.56],[63.99,-166.8],[67.43,-166.97],[70.88,-167.06],[74.34,-167.08],[77.8,-167.01],[81.26,-166.86],[84.72,-166.62],[88.17,-166.29],[91.59,-165.88],[95.0,-165.37],[98.38,-164.78],[101.72,-164.1],[105.02,-163.34],[108.28,-162.49],[111.49,-161.57],[114.65,-160.57],[117.74,-159.5],[120.78,-158.37],[123.75,-157.18],[126.65,-155.94],[129.49,-154.65],[132.25,-153.32],[134.95,-151.96],[137.58,-150.58],[140.15,-149.18],[142.65,-147.77],[145.09,-146.35],[147.47,-144.95],[149.81,-143.56],[152.1,-142.19],[154.34,-140.84],[156.56,-139.54],[158.75,-138.27],[160.92,-137.05],[163.08,-135.88],[165.24,-134.77],[167.4,-133.72],[169.58,-132.74],[171.79,-131.82],[174.03,-130.98],[176.31,-130.2],[178.64,-129.5],[181.03,-128.88],[183.49,-128.32],[186.02,-127.84],[188.62,-127.43],[191.31,-127.08],[194.09,-126.8],[196.96,-126.58],[199.92,-126.42],[202.99,-126.3],[206.15,-126.24],[209.4,-126.21],[212.76,-126.22],[216.21,-126.25],[219.74,-126.3],[223.37,-126.37],[227.08,-126.44],[230.86,-126.52],[234.71,-126.59],[238.62,-126.64],[242.57,-126.67],[246.57,-126.68],[250.6,-126.65],[254.65,-126.58],[258.71,-126.46],[262.77,-126.29],[266.81,-126.07],[270.82,-125.79],[274.79,-125.44],[278.72,-125.03],[282.58,-124.54],[286.37,-123.99],[290.07,-123.35],[293.68,-122.65],[297.19,-121.87],[300.59,-121.01],[303.86,-120.08],[307.01,-119.07],[310.02,-117.99],[312.89,-116.85],[315.63,-115.63],[318.21,-114.35],[320.65,-113.01],[322.95,-111.62],[325.1,-110.17],[327.1,-108.67],[328.96,-107.12],[330.69,-105.54],[332.29,-103.91],[333.75,-102.26],[335.11,-100.58],[336.35,-98.87],[337.49,-97.15],[338.53,-95.41],[339.5,-93.66],[340.39,-91.91],[341.23,-90.15],[342.01,-88.38],[342.76,-86.62],[343.47,-84.87],[344.17,-83.11],[344.86,-81.37],[345.56,-79.63],[346.27,-77.91],[347.0,-76.19],[347.76,-74.48],[348.56,-72.78],[349.4,-71.09],[350.29,-69.41],[351.24,-67.73],[352.24,-66.07],[353.29,-64.4],[354.41,-62.74],[355.58,-61.07],[356.81,-59.41],[358.1,-57.74],[359.43,-56.07],[360.8,-54.39],[362.22,-52.7],[363.66,-51.0],[365.12,-49.28],[366.59,-47.55],[368.05,-45.81],[369.51,-44.05],[370.94,-42.27],[372.34,-40.48],[373.68,-38.67],[374.96,-36.84],[376.17,-35.0]],[[379.42,-35.0],[380.5,-33.12],[381.48,-31.23],[382.35,-29.32],[383.09,-27.41],[383.7,-25.48],[384.15,-23.55],[384.45,-21.62],[384.57,-19.69],[384.52,-17.76],[384.27,-15.84],[383.83,-13.93],[383.19,-12.04],[382.34,-10.16],[381.28,-8.31],[380.01,-6.48],[378.52,-4.69],[376.82,-2.92],[374.91,-1.2],[372.8,0.49],[370.48,2.13],[367.97,3.73],[365.27,5.27],[362.4,6.77],[359.35,8.21],[356.15,9.59],[352.81,10.92],[349.33,12.2],[345.74,13.42],[342.05,14.58],[338.27,15.69],[334.41,16.74],[330.51,17.74],[326.56,18.7],[322.59,19.61],[318.61,20.47],[314.64,21.29],[310.69,22.08],[306.78,22.84],[302.92,23.57],[299.13,24.28],[295.41,24.98],[291.78,25.66],[288.25,26.33],[284.82,27.01],[281.51,27.69],[278.32,28.38],[275.26,29.08],[272.33,29.81],[269.53,30.56],[266.87,31.34],[264.34,32.15],[261.94,33.0],[259.67,33.89],[257.53,34.83],[255.51,35.81],[253.61,36.84],[251.81,37.92],[250.12,39.05],[248.51,40.23],[246.99,41.46],[245.54,42.74],[244.15,44.06],[242.81,45.43],[241.51,46.85],[240.23,48.3],[238.97,49.8],[237.72,51.32],[236.46,52.87],[235.18,54.45],[233.87,56.04],[232.52,57.64],[231.13,59.25],[229.68,60.86],[228.16,62.46],[226.58,64.06],[224.91,65.63],[223.17,67.18],[221.33,68.7],[219.41,70.19],[217.39,71.63],[215.27,73.03],[213.06,74.38],[210.76,75.67],[208.36,76.91],[205.86,78.08],[203.28,79.19],[200.61,80.24],[197.86,81.21],[195.02,82.11],[192.12,82.95],[189.15,83.71],[186.12,84.41],[183.03,85.03],[179.9,85.6],[176.72,86.09],[173.5,86.53],[170.26,86.92],[166.99,87.25],[163.7,87.53],[160.4,87.77],[157.09,87.98],[153.78,88.15],[150.46,88.3],[147.15,88.43],[143.85,88.54],[140.56,88.65],[137.27,88.75],[134.0,88.86],[130.74,88.98],[127.48,89.11],[124.24,89.27],[121.0,89.44],[117.77,89.65],[114.54,89.89],[111.31,90.17],[108.07,90.49],[104.83,90.85],[101.57,91.25],[98.3,91.69],[95.0,92.18],[91.68,92.72],[88.32,93.29],[84.93,93.91],[81.5,94.57],[78.03,95.26],[74.51,95.98],[70.94,96.73],[67.32,97.5],[63.64,98.29],[59.91,99.09],[56.12,99.89],[52.28,100.69],[48.38,101.48],[44.43,102.25],[40.43,103.0],[36.38,103.72],[32.29,104.4],[28.17,105.03],[24.01,105.61],[19.83,106.13],[15.63,106.57],[11.41,106.95],[7.2,107.24],[3.0,107.44],[-1.19,107.55],[-5.36,107.56],[-9.49,107.47],[-13.57,107.27],[-17.59,106.97],[-21.56,106.55],[-25.44,106.02],[-29.24,105.37],[-32.95,104.61],[-36.55,103.74],[-40.05,102.75],[-43.42,101.66],[-46.67,100.45],[-49.79,99.15],[-52.78,97.74],[-55.62,96.23],[-58.32,94.63],[-60.87,92.95],[-63.28,91.19],[-65.54,89.35],[-67.65,87.45],[-69.62,85.49],[-71.45,83.48],[-73.15,81.42],[-74.71,79.32],[-76.15,77.2],[-77.47,75.05],[-78.69,72.89],[-79.8,70.72],[-80.82,68.55],[-81.76,66.39],[-82.63,64.24],[-83.44,62.1],[-84.2,59.99],[-84.93,57.91],[-85.63,55.86],[-86.32,53.85],[-87.0,51.88],[-87.7,49.95],[-88.41,48.07],[-89.15,46.24],[-89.93,44.45],[-90.76,42.71],[-91.64,41.03],[-92.58,39.39],[-93.59,37.79],[-94.67,36.25],[-95.83,34.74],[-97.07,33.28],[-98.38,31.86],[-99.78,30.47],[-101.26,29.11],[-102.81,27.78],[-104.44,26.48],[-106.14,25.2],[-107.9,23.93],[-109.72,22.67],[-111.59,21.42],[-113.5,20.18],[-115.44,18.94],[-117.41,17.69],[-119.39,16.44],[-121.37,15.18],[-123.34,13.9],[-125.28,12.61],[-127.2,11.3],[-129.07,9.97],[-130.88,8.62],[-132.62,7.24],[-134.28,5.84],[-135.86,4.42],[-137.33,2.97],[-138.7,1.5],[-139.95,0.01],[-141.07,-1.51],[-142.07,-3.05],[-142.93,-4.6],[-143.64,-6.18],[-144.22,-7.77],[-144.65,-9.38],[-144.94,-10.99],[-145.08,-12.62],[-145.09,-14.25],[-144.95,-15.88],[-144.68,-17.52],[-144.29,-19.15],[-143.78,-20.78],[-143.15,-22.41],[-142.42,-24.03],[-141.6,-25.63],[-140.7,-27.23],[-139.73,-28.81],[-138.7,-30.38],[-137.63,-31.94],[-136.53,-33.48],[-135.41,-35.0],[-134.29,-36.51],[-133.18,-38.01],[-132.09,-39.49],[-131.04,-40.96],[-130.04,-42.42],[-129.09,-43.87],[-128.23,-45.32],[-127.44,-46.76],[-126.75,-48.2],[-126.16,-49.65],[-125.67,-51.09],[-125.3,-52.55],[-125.06,-54.02],[-124.93,-55.5],[-124.93,-57.01],[-125.06,-58.53],[-125.32,-60.08],[-125.7,-61.65],[-126.19,-63.26],[-126.81,-64.9],[-127.53,-66.57],[-128.36,-68.28],[-129.28,-70.03],[-130.28,-71.82],[-131.36,-73.65],[-132.5,-75.52],[-133.68,-77.44],[-134.9,-79.39],[-136.13,-81.39],[-137.38,-83.42],[-138.61,-85.49],[-139.82,-87.59],[-140.98,-89.72],[-142.09,-91.89],[-143.13,-94.07],[-144.08,-96.28],[-144.93,-98.5],[-145.66,-100.73],[-146.27,-102.97],[-146.73,-105.21],[-147.04,-107.44],[-147.19,-109.66],[-147.16,-111.86],[-146.96,-114.04],[-146.56,-116.19],[-145.97,-118.31],[-145.17,-120.38],[-144.18,-122.41],[-142.98,-124.39],[-141.58,-126.32],[-139.97,-128.18],[-138.16,-129.98],[-136.15,-131.71],[-133.95,-133.36],[-131.56,-134.95],[-128.99,-136.45],[-126.24,-137.88],[-123.33,-139.22],[-120.26,-140.49],[-117.05,-141.67],[-113.71,-142.77],[-110.24,-143.79],[-106.66,-144.74],[-102.98,-145.61],[-99.22,-146.4],[-95.38,-147.13],[-91.49,-147.79],[-87.54,-148.39],[-83.55,-148.93],[-79.54,-149.42],[-75.52,-149.87],[-71.48,-150.27],[-67.46,-150.63],[-63.44,-150.97],[-59.45,-151.28],[-55.49,-151.57],[-51.56,-151.84],[-47.67,-152.11],[-43.82,-152.38],[-40.03,-152.65],[-36.29,-152.92],[-32.59,-153.21],[-28.96,-153.52],[-25.37,-153.84],[-21.84,-154.19],[-18.36,-154.56],[-14.93,-154.95],[-11.55,-155.38],[-8.2,-155.83],[-4.9,-156.32],[-1.62,-156.83],[1.62,-157.37],[4.84,-157.94],[8.04,-158.53],[11.23,-159.14],[14.41,-159.77],[17.59,-160.41],[20.77,-161.06],[23.95,-161.72],[27.15,-162.38],[30.36,-163.03],[33.59,-163.67],[36.84,-164.29],[40.11,-164.89],[43.41,-165.46],[46.74,-165.99],[50.09,-166.48],[53.46,-166.93],[56.86,-167.32],[60.28,-167.65],[63.73,-167.92],[67.19,-168.11],[70.66,-168.24],[74.15,-168.29],[77.64,-168.25],[81.13,-168.13],[84.62,-167.93],[88.1,-167.64],[91.56,-167.26],[95.0,-166.79],[98.42,-166.24],[101.8,-165.59],[105.14,-164.87],[108.45,-164.06],[111.7,-163.17],[114.9,-162.2],[118.05,-161.16],[121.13,-160.06],[124.15,-158.89],[127.11,-157.68],[129.99,-156.41],[132.81,-155.1],[135.57,-153.76],[138.25,-152.39],[140.87,-151.0],[143.42,-149.6],[145.92,-148.19],[148.35,-146.79],[150.74,-145.4],[153.07,-144.03],[155.37,-142.68],[157.63,-141.37],[159.87,-140.09],[162.09,-138.86],[164.29,-137.68],[166.5,-136.56],[168.71,-135.5],[170.93,-134.5],[173.18,-133.57],[175.46,-132.72],[177.79,-131.93],[180.16,-131.21],[182.59,-130.57],[185.09,-130.01],[187.66,-129.51],[190.31,-129.09],[193.04,-128.74],[195.86,-128.45],[198.78,-128.22],[201.8,-128.05],[204.91,-127.93],[208.13,-127.86],[211.44,-127.84],[214.86,-127.84],[218.37,-127.88],[221.98,-127.94],[225.68,-128.01],[229.46,-128.1],[233.33,-128.18],[237.26,-128.26],[241.26,-128.33],[245.31,-128.37],[249.41,-128.39],[253.54,-128.38],[257.69,-128.32],[261.86,-128.22],[266.03,-128.07],[270.18,-127.86],[274.32,-127.59],[278.41,-127.26],[282.46,-126.86],[286.44,-126.39],[290.36,-125.84],[294.19,-125.22],[297.92,-124.52],[301.55,-123.74],[305.07,-122.89],[308.46,-121.95],[311.73,-120.94],[314.85,-119.86],[317.84,-118.71],[320.68,-117.48],[323.37,-116.19],[325.9,-114.83],[328.29,-113.41],[330.52,-111.94],[332.6,-110.41],[334.53,-108.84],[336.31,-107.22],[337.96,-105.56],[339.47,-103.87],[340.86,-102.15],[342.12,-100.4],[343.28,-98.63],[344.33,-96.85],[345.29,-95.05],[346.17,-93.25],[346.99,-91.44],[347.74,-89.62],[348.45,-87.81],[349.12,-86.0],[349.76,-84.19],[350.39,-82.4],[351.02,-80.61],[351.65,-78.83],[352.3,-77.05],[352.98,-75.29],[353.68,-73.55],[354.43,-71.81],[355.22,-70.07],[356.07,-68.35],[356.96,-66.64],[357.92,-64.93],[358.93,-63.22],[360.0,-61.52],[361.13,-59.81],[362.31,-58.11],[363.54,-56.4],[364.82,-54.68],[366.14,-52.96],[367.49,-51.22],[368.86,-49.48],[370.25,-47.72],[371.65,-45.95],[373.03,-44.17],[374.4,-42.37],[375.73,-40.55],[377.03,-38.71],[378.26,-36.87],[379.42,-35.0]],[[382.56,-35.0],[383.6,-33.1],[384.55,-31.19],[385.39,-29.26],[386.11,-27.33],[386.7,-25.38],[387.15,-23.43],[387.44,-21.48],[387.56,-19.53],[387.51,-17.58],[387.27,-15.64],[386.84,-13.71],[386.21,-11.8],[385.38,-9.9],[384.33,-8.03],[383.07,-6.18],[381.6,-4.36],[379.92,-2.57],[378.03,-0.82],[375.93,0.89],[373.62,2.55],[371.12,4.17],[368.43,5.74],[365.56,7.26],[362.52,8.72],[359.31,10.13],[355.96,11.49],[352.48,12.78],[348.87,14.02],[345.16,15.2],[341.36,16.33],[337.48,17.4],[333.54,18.42],[329.56,19.39],[325.55,20.32],[321.53,21.19],[317.51,22.03],[313.51,22.83],[309.55,23.6],[305.63,24.34],[301.78,25.06],[298.01,25.75],[294.32,26.44],[290.73,27.12],[287.24,27.8],[283.87,28.48],[280.62,29.17],[277.5,29.88],[274.52,30.61],[271.66,31.36],[268.95,32.14],[266.37,32.96],[263.93,33.81],[261.62,34.71],[259.44,35.65],[257.39,36.64],[255.45,37.67],[253.63,38.76],[251.92,39.91],[250.3,41.1],[248.76,42.35],[247.31,43.65],[245.91,45.0],[244.57,46.39],[243.28,47.84],[242.01,49.33],[240.77,50.85],[239.53,52.42],[238.29,54.01],[237.03,55.63],[235.75,57.27],[234.43,58.92],[233.06,60.59],[231.64,62.25],[230.15,63.92],[228.59,65.57],[226.96,67.21],[225.24,68.83],[223.43,70.42],[221.52,71.98],[219.52,73.5],[217.43,74.97],[215.23,76.39],[212.94,77.76],[210.54,79.07],[208.05,80.32],[205.46,81.5],[202.79,82.61],[200.02,83.66],[197.17,84.63],[194.25,85.53],[191.25,86.36],[188.18,87.11],[185.06,87.8],[181.88,88.41],[178.65,88.96],[175.39,89.45],[172.08,89.88],[168.75,90.25],[165.4,90.56],[162.03,90.84],[158.65,91.07],[155.26,91.26],[151.87,91.42],[148.48,91.56],[145.09,91.68],[141.71,91.79],[138.34,91.89],[134.98,91.99],[131.63,92.1],[128.29,92.22],[124.96,92.35],[121.64,92.51],[118.32,92.69],[115.01,92.9],[111.7,93.15],[108.38,93.43],[105.06,93.75],[101.72,94.12],[98.37,94.53],[95.0,94.98],[91.6,95.47],[88.18,96.01],[84.72,96.58],[81.23,97.2],[77.69,97.85],[74.11,98.53],[70.48,99.24],[66.8,99.97],[63.07,100.73],[59.28,101.49],[55.44,102.26],[51.54,103.03],[47.59,103.79],[43.59,104.54],[39.54,105.26],[35.44,105.96],[31.3,106.62],[27.12,107.23],[22.91,107.79],[18.67,108.29],[14.42,108.73],[10.15,109.09],[5.89,109.37],[1.62,109.56],[-2.62,109.66],[-6.84,109.67],[-11.03,109.57],[-15.16,109.36],[-19.25,109.05],[-23.27,108.63],[-27.21,108.09],[-31.07,107.44],[-34.83,106.67],[-38.49,105.78],[-42.04,104.79],[-45.47,103.68],[-48.77,102.46],[-51.94,101.14],[-54.97,99.71],[-57.86,98.18],[-60.6,96.56],[-63.19,94.85],[-65.63,93.06],[-67.92,91.2],[-70.06,89.27],[-72.06,87.27],[-73.91,85.22],[-75.61,83.13],[-77.18,80.99],[-78.63,78.82],[-79.95,76.63],[-81.15,74.42],[-82.25,72.21],[-83.26,69.99],[-84.18,67.78],[-85.02,65.57],[-85.8,63.39],[-86.53,61.23],[-87.22,59.09],[-87.88,56.99],[-88.52,54.93],[-89.16,52.91],[-89.81,50.93],[-90.47,49.01],[-91.16,47.12],[-91.89,45.29],[-92.66,43.51],[-93.49,41.78],[-94.39,40.1],[-95.35,38.47],[-96.39,36.89],[-97.51,35.36],[-98.71,33.86],[-99.99,32.41],[-101.36,31.0],[-102.81,29.62],[-104.35,28.27],[-105.97,26.95],[-107.66,25.65],[-109.43,24.37],[-111.26,23.11],[-113.15,21.85],[-115.09,20.6],[-117.07,19.35],[-119.08,18.11],[-121.11,16.85],[-123.15,15.59],[-125.18,14.31],[-127.2,13.02],[-129.2,11.71],[-131.16,10.39],[-133.06,9.04],[-134.91,7.67],[-136.68,6.27],[-138.37,4.85],[-139.96,3.4],[-141.45,1.93],[-142.83,0.44],[-144.08,-1.08],[-145.21,-2.62],[-146.2,-4.19],[-147.05,-5.77],[-147.76,-7.37],[-148.32,-8.98],[-148.74,-10.61],[-149.01,-12.25],[-149.14,-13.9],[-149.13,-15.55],[-148.98,-17.21],[-148.7,-18.86],[-148.29,-20.51],[-147.77,-22.16],[-147.14,-23.81],[-146.41,-25.44],[-145.59,-27.07],[-144.69,-28.68],[-143.73,-30.28],[-142.72,-31.87],[-141.68,-33.44],[-140.6,-35.0],[-139.52,-36.54],[-138.44,-38.07],[-137.37,-39.59],[-136.34,-41.1],[-135.34,-42.59],[-134.4,-44.08],[-133.53,-45.56],[-132.74,-47.04],[-132.03,-48.52],[-131.42,-49.99],[-130.91,-51.48],[-130.51,-52.97],[-130.23,-54.47],[-130.08,-55.98],[-130.04,-57.52],[-130.13,-59.07],[-130.35,-60.65],[-130.68,-62.26],[-131.14,-63.89],[-131.72,-65.56],[-132.4,-67.26],[-133.19,-69.0],[-134.07,-70.78],[-135.04,-72.6],[-136.09,-74.46],[-137.19,-76.36],[-138.35,-78.3],[-139.54,-80.29],[-140.76,-82.31],[-141.99,-84.38],[-143.2,-86.48],[-144.4,-88.62],[-145.55,-90.78],[-146.66,-92.98],[-147.69,-95.2],[-148.64,-97.45],[-149.49,-99.7],[-150.22,-101.98],[-150.83,-104.25],[-151.29,-106.53],[-151.61,-108.8],[-151.75,-111.06],[-151.73,-113.31],[-151.52,-115.53],[-151.13,-117.73],[-150.53,-119.89],[-149.74,-122.01],[-148.73,-124.08],[-147.53,-126.1],[-146.11,-128.06],[-144.48,-129.97],[-142.65,-131.81],[-140.61,-133.57],[-138.38,-135.27],[-135.95,-136.88],[-133.33,-138.42],[-130.54,-139.87],[-127.57,-141.25],[-124.45,-142.54],[-121.17,-143.74],[-117.76,-144.86],[-114.21,-145.9],[-110.55,-146.86],[-106.79,-147.73],[-102.93,-148.53],[-99.0,-149.26],[-95.0,-149.92],[-90.95,-150.51],[-86.86,-151.04],[-82.74,-151.52],[-78.6,-151.94],[-74.45,-152.32],[-70.31,-152.66],[-66.17,-152.97],[-62.06,-153.24],[-57.98,-153.5],[-53.93,-153.74],[-49.93,-153.97],[-45.97,-154.19],[-42.06,-154.42],[-38.2,-154.65],[-34.4,-154.89],[-30.66,-155.14],[-26.97,-155.42],[-23.34,-155.71],[-19.77,-156.03],[-16.24,-156.38],[-12.77,-156.76],[-9.34,-157.17],[-5.96,-157.61],[-2.61,-158.08],[0.7,-158.58],[3.98,-159.11],[7.24,-159.66],[10.49,-160.24],[13.72,-160.84],[16.94,-161.46],[20.16,-162.09],[23.39,-162.72],[26.62,-163.37],[29.87,-164.01],[33.13,-164.64],[36.41,-165.26],[39.71,-165.86],[43.03,-166.43],[46.37,-166.97],[49.75,-167.48],[53.14,-167.94],[56.56,-168.35],[60.01,-168.7],[63.47,-168.99],[66.96,-169.22],[70.45,-169.38],[73.96,-169.46],[77.48,-169.46],[81.0,-169.38],[84.52,-169.21],[88.03,-168.96],[91.52,-168.62],[95.0,-168.19],[98.45,-167.68],[101.88,-167.07],[105.26,-166.38],[108.61,-165.61],[111.91,-164.76],[115.16,-163.83],[118.35,-162.82],[121.48,-161.75],[124.56,-160.62],[127.56,-159.43],[130.51,-158.19],[133.38,-156.9],[136.19,-155.58],[138.93,-154.22],[141.6,-152.85],[144.21,-151.46],[146.76,-150.06],[149.25,-148.67],[151.69,-147.28],[154.08,-145.91],[156.43,-144.56],[158.74,-143.24],[161.03,-141.96],[163.29,-140.73],[165.55,-139.54],[167.8,-138.41],[170.05,-137.33],[172.32,-136.33],[174.61,-135.38],[176.94,-134.51],[179.31,-133.71],[181.72,-132.98],[184.2,-132.33],[186.74,-131.75],[189.35,-131.24],[192.04,-130.81],[194.82,-130.44],[197.69,-130.14],[200.66,-129.91],[203.73,-129.73],[206.89,-129.61],[210.16,-129.53],[213.54,-129.5],[217.01,-129.51],[220.59,-129.55],[224.27,-129.61],[228.04,-129.69],[231.9,-129.78],[235.84,-129.87],[239.86,-129.96],[243.94,-130.04],[248.09,-130.1],[252.28,-130.13],[256.51,-130.13],[260.77,-130.09],[265.04,-130.0],[269.32,-129.86],[273.59,-129.67],[277.84,-129.41],[282.05,-129.09],[286.22,-128.7],[290.33,-128.24],[294.37,-127.7],[298.32,-127.09],[302.18,-126.4],[305.93,-125.62],[309.57,-124.77],[313.08,-123.83],[316.46,-122.82],[319.7,-121.73],[322.8,-120.57],[325.74,-119.33],[328.53,-118.02],[331.17,-116.65],[333.64,-115.21],[335.95,-113.71],[338.1,-112.16],[340.1,-110.55],[341.95,-108.9],[343.64,-107.21],[345.2,-105.48],[346.62,-103.72],[347.91,-101.93],[349.08,-100.12],[350.14,-98.29],[351.1,-96.45],[351.96,-94.59],[352.75,-92.73],[353.48,-90.86],[354.14,-89.0],[354.76,-87.13],[355.35,-85.27],[355.92,-83.42],[356.48,-81.58],[357.03,-79.74],[357.6,-77.92],[358.18,-76.11],[358.8,-74.31],[359.44,-72.52],[360.13,-70.74],[360.87,-68.97],[361.66,-67.2],[362.51,-65.45],[363.41,-63.7],[364.37,-61.95],[365.39,-60.21],[366.47,-58.46],[367.6,-56.72],[368.77,-54.97],[369.99,-53.21],[371.25,-51.45],[372.53,-49.67],[373.83,-47.89],[375.15,-46.09],[376.46,-44.28],[377.76,-42.45],[379.03,-40.61],[380.26,-38.76],[381.45,-36.89],[382.56,-35.0]],[[385.59,-35.0],[386.59,-33.08],[387.5,-31.15],[388.31,-29.2],[389.01,-27.25],[389.58,-25.29],[390.02,-23.32],[390.3,-21.35],[390.43,-19.38],[390.38,-17.41],[390.15,-15.45],[389.73,-13.5],[389.11,-11.57],[388.29,-9.65],[387.26,-7.75],[386.02,-5.88],[384.57,-4.04],[382.91,-2.23],[381.04,-0.46],[378.96,1.28],[376.67,2.97],[374.18,4.61],[371.51,6.2],[368.65,7.74],[365.61,9.23],[362.41,10.66],[359.06,12.04],[355.57,13.36],[351.96,14.62],[348.24,15.82],[344.42,16.97],[340.52,18.06],[336.55,19.1],[332.54,20.09],[328.5,21.02],[324.44,21.92],[320.38,22.77],[316.34,23.58],[312.33,24.36],[308.37,25.11],[304.47,25.83],[300.64,26.54],[296.89,27.23],[293.24,27.92],[289.7,28.6],[286.27,29.29],[282.97,29.99],[279.8,30.7],[276.75,31.43],[273.85,32.18],[271.08,32.97],[268.46,33.79],[265.97,34.64],[263.62,35.54],[261.4,36.49],[259.32,37.49],[257.35,38.53],[255.51,39.64],[253.77,40.79],[252.13,42.0],[250.59,43.26],[249.12,44.58],[247.72,45.96],[246.39,47.38],[245.09,48.85],[243.84,50.37],[242.6,51.93],[241.38,53.54],[240.16,55.17],[238.92,56.83],[237.66,58.52],[236.36,60.23],[235.02,61.95],[233.63,63.67],[232.17,65.4],[230.64,67.11],[229.03,68.82],[227.34,70.51],[225.55,72.16],[223.67,73.79],[221.69,75.38],[219.61,76.93],[217.43,78.43],[215.14,79.87],[212.75,81.25],[210.26,82.57],[207.68,83.83],[204.99,85.02],[202.21,86.13],[199.35,87.17],[196.4,88.14],[193.37,89.03],[190.27,89.85],[187.11,90.6],[183.89,91.27],[180.61,91.87],[177.29,92.4],[173.93,92.87],[170.54,93.28],[167.12,93.64],[163.68,93.94],[160.23,94.19],[156.76,94.41],[153.29,94.58],[149.82,94.73],[146.35,94.86],[142.89,94.97],[139.43,95.07],[135.98,95.16],[132.54,95.26],[129.12,95.36],[125.7,95.47],[122.29,95.6],[118.89,95.76],[115.49,95.94],[112.09,96.16],[108.69,96.4],[105.29,96.69],[101.87,97.01],[98.45,97.38],[95.0,97.79],[91.53,98.24],[88.04,98.73],[84.51,99.26],[80.95,99.83],[77.35,100.44],[73.71,101.08],[70.02,101.75],[66.28,102.44],[62.49,103.15],[58.65,103.88],[54.76,104.61],[50.81,105.35],[46.81,106.08],[42.76,106.8],[38.65,107.5],[34.51,108.16],[30.31,108.8],[26.09,109.39],[21.83,109.93],[17.54,110.42],[13.24,110.84],[8.92,111.18],[4.6,111.45],[0.29,111.63],[-4.01,111.72],[-8.28,111.72],[-12.52,111.61],[-16.72,111.4],[-20.86,111.08],[-24.93,110.65],[-28.93,110.1],[-32.84,109.44],[-36.66,108.67],[-40.38,107.77],[-43.98,106.77],[-47.46,105.65],[-50.81,104.41],[-54.03,103.07],[-57.11,101.63],[-60.04,100.08],[-62.82,98.44],[-65.45,96.71],[-67.93,94.9],[-70.25,93.01],[-72.42,91.04],[-74.44,89.02],[-76.31,86.93],[-78.03,84.8],[-79.61,82.62],[-81.06,80.42],[-82.38,78.18],[-83.58,75.93],[-84.67,73.67],[-85.66,71.41],[-86.56,69.14],[-87.38,66.89],[-88.14,64.66],[-88.83,62.45],[-89.49,60.26],[-90.11,58.11],[-90.71,56.0],[-91.3,53.93],[-91.9,51.91],[-92.51,49.93],[-93.15,48.0],[-93.83,46.13],[-94.56,44.3],[-95.34,42.53],[-96.18,40.82],[-97.1,39.15],[-98.1,37.53],[-99.17,35.96],[-100.34,34.44],[-101.59,32.96],[-102.93,31.53],[-104.36,30.13],[-105.88,28.76],[-107.49,27.42],[-109.18,26.11],[-110.95,24.81],[-112.8,23.54],[-114.71,22.28],[-116.67,21.02],[-118.69,19.77],[-120.74,18.52],[-122.82,17.26],[-124.92,16.0],[-127.02,14.73],[-129.12,13.44],[-131.2,12.13],[-133.25,10.81],[-135.26,9.46],[-137.21,8.09],[-139.09,6.7],[-140.89,5.28],[-142.61,3.84],[-144.22,2.37],[-145.72,0.87],[-147.11,-0.65],[-148.37,-2.2],[-149.5,-3.76],[-150.49,-5.35],[-151.33,-6.96],[-152.04,-8.59],[-152.59,-10.23],[-153.0,-11.88],[-153.26,-13.54],[-153.37,-15.21],[-153.34,-16.89],[-153.18,-18.56],[-152.89,-20.24],[-152.47,-21.92],[-151.94,-23.59],[-151.3,-25.25],[-150.57,-26.9],[-149.76,-28.55],[-148.87,-30.18],[-147.93,-31.8],[-146.94,-33.41],[-145.91,-35.0],[-144.87,-36.58],[-143.82,-38.15],[-142.78,-39.7],[-141.76,-41.24],[-140.78,-42.77],[-139.84,-44.3],[-138.97,-45.81],[-138.16,-47.33],[-137.44,-48.84],[-136.81,-50.35],[-136.27,-51.87],[-135.85,-53.39],[-135.53,-54.93],[-135.34,-56.47],[-135.26,-58.04],[-135.31,-59.63],[-135.48,-61.23],[-135.78,-62.87],[-136.19,-64.54],[-136.72,-66.23],[-137.36,-67.96],[-138.11,-69.73],[-138.95,-71.54],[-139.87,-73.39],[-140.88,-75.28],[-141.95,-77.21],[-143.07,-79.18],[-144.24,-81.2],[-145.43,-83.25],[-146.63,-85.35],[-147.82,-87.48],[-149.0,-89.65],[-150.14,-91.85],[-151.23,-94.08],[-152.25,-96.33],[-153.19,-98.61],[-154.03,-100.91],[-154.76,-103.22],[-155.36,-105.53],[-155.83,-107.85],[-156.14,-110.16],[-156.29,-112.46],[-156.26,-114.75],[-156.05,-117.01],[-155.65,-119.25],[-155.05,-121.45],[-154.25,-123.61],[-153.24,-125.72],[-152.02,-127.79],[-150.58,-129.79],[-148.94,-131.74],[-147.08,-133.61],[-145.02,-135.42],[-142.75,-137.15],[-140.29,-138.8],[-137.63,-140.36],[-134.79,-141.85],[-131.77,-143.25],[-128.58,-144.56],[-125.24,-145.79],[-121.76,-146.93],[-118.14,-147.98],[-114.4,-148.95],[-110.55,-149.83],[-106.6,-150.64],[-102.58,-151.37],[-98.48,-152.02],[-94.33,-152.61],[-90.13,-153.13],[-85.9,-153.59],[-81.65,-154.0],[-77.38,-154.35],[-73.12,-154.67],[-68.88,-154.94],[-64.65,-155.19],[-60.45,-155.41],[-56.28,-155.61],[-52.16,-155.8],[-48.08,-155.98],[-44.06,-156.16],[-40.09,-156.34],[-36.18,-156.54],[-32.33,-156.74],[-28.54,-156.97],[-24.81,-157.21],[-21.14,-157.49],[-17.53,-157.79],[-13.97,-158.11],[-10.46,-158.48],[-7.0,-158.87],[-3.58,-159.29],[-0.2,-159.75],[3.15,-160.24],[6.47,-160.76],[9.77,-161.3],[13.05,-161.87],[16.32,-162.46],[19.59,-163.07],[22.85,-163.69],[26.12,-164.31],[29.4,-164.94],[32.68,-165.57],[35.99,-166.18],[39.31,-166.78],[42.66,-167.36],[46.03,-167.91],[49.42,-168.43],[52.84,-168.91],[56.28,-169.34],[59.74,-169.72],[63.23,-170.03],[66.73,-170.29],[70.25,-170.48],[73.79,-170.59],[77.33,-170.63],[80.87,-170.59],[84.42,-170.47],[87.96,-170.26],[91.49,-169.96],[95.0,-169.57],[98.49,-169.1],[101.95,-168.54],[105.38,-167.89],[108.77,-167.16],[112.11,-166.35],[115.41,-165.46],[118.65,-164.49],[121.84,-163.45],[124.96,-162.35],[128.03,-161.19],[131.02,-159.98],[133.95,-158.72],[136.82,-157.42],[139.61,-156.09],[142.34,-154.73],[145.01,-153.35],[147.62,-151.97],[150.16,-150.58],[152.66,-149.2],[155.1,-147.83],[157.51,-146.49],[159.87,-145.17],[162.21,-143.89],[164.53,-142.64],[166.83,-141.45],[169.13,-140.31],[171.44,-139.22],[173.75,-138.2],[176.09,-137.25],[178.46,-136.36],[180.88,-135.55],[183.34,-134.8],[185.85,-134.14],[188.44,-133.54],[191.1,-133.02],[193.83,-132.57],[196.66,-132.2],[199.58,-131.89],[202.59,-131.64],[205.71,-131.46],[208.93,-131.33],[212.25,-131.25],[215.68,-131.22],[219.22,-131.22],[222.86,-131.26],[226.61,-131.32],[230.45,-131.41],[234.38,-131.5],[238.4,-131.6],[242.5,-131.69],[246.67,-131.78],[250.9,-131.85],[255.19,-131.89],[259.52,-131.9],[263.88,-131.87],[268.26,-131.8],[272.65,-131.67],[277.03,-131.49],[281.39,-131.25],[285.72,-130.94],[290.01,-130.56],[294.23,-130.11],[298.39,-129.58],[302.47,-128.97],[306.45,-128.28],[310.32,-127.51],[314.08,-126.66],[317.71,-125.72],[321.21,-124.71],[324.57,-123.61],[327.77,-122.44],[330.82,-121.19],[333.71,-119.86],[336.44,-118.47],[339.0,-117.01],[341.39,-115.49],[343.62,-113.91],[345.69,-112.28],[347.59,-110.59],[349.34,-108.87],[350.93,-107.1],[352.39,-105.3],[353.7,-103.47],[354.88,-101.61],[355.95,-99.73],[356.9,-97.84],[357.76,-95.93],[358.53,-94.02],[359.22,-92.1],[359.84,-90.18],[360.41,-88.27],[360.94,-86.35],[361.44,-84.45],[361.93,-82.55],[362.4,-80.66],[362.88,-78.78],[363.37,-76.92],[363.89,-75.07],[364.43,-73.22],[365.02,-71.39],[365.65,-69.58],[366.33,-67.77],[367.06,-65.97],[367.85,-64.17],[368.7,-62.39],[369.6,-60.6],[370.57,-58.82],[371.59,-57.04],[372.66,-55.25],[373.77,-53.46],[374.93,-51.67],[376.12,-49.86],[377.33,-48.05],[378.56,-46.23],[379.79,-44.39],[381.01,-42.54],[382.22,-40.68],[383.39,-38.8],[384.52,-36.91],[385.59,-35.0]],[[388.5,-35.0],[389.45,-33.06],[390.33,-31.11],[391.11,-29.15],[391.78,-27.18],[392.34,-25.2],[392.76,-23.21],[393.04,-21.22],[393.16,-19.24],[393.12,-17.25],[392.9,-15.27],[392.49,-13.3],[391.89,-11.35],[391.08,-9.41],[390.08,-7.49],[388.86,-5.6],[387.44,-3.73],[385.8,-1.9],[383.95,-0.1],[381.89,1.65],[379.63,3.36],[377.16,5.03],[374.5,6.65],[371.66,8.21],[368.64,9.72],[365.45,11.18],[362.11,12.58],[358.62,13.92],[355.01,15.21],[351.28,16.43],[347.45,17.6],[343.53,18.71],[339.55,19.77],[335.52,20.78],[331.45,21.73],[327.36,22.64],[323.26,23.51],[319.19,24.33],[315.13,25.12],[311.13,25.89],[307.18,26.62],[303.3,27.34],[299.5,28.04],[295.8,28.73],[292.21,29.42],[288.73,30.11],[285.37,30.81],[282.14,31.53],[279.04,32.26],[276.09,33.02],[273.27,33.81],[270.6,34.64],[268.07,35.5],[265.68,36.41],[263.43,37.36],[261.3,38.36],[259.31,39.42],[257.44,40.53],[255.68,41.7],[254.02,42.93],[252.46,44.21],[250.99,45.55],[249.59,46.94],[248.25,48.39],[246.96,49.89],[245.71,51.45],[244.49,53.04],[243.28,54.68],[242.07,56.36],[240.85,58.07],[239.61,59.8],[238.34,61.56],[237.03,63.33],[235.66,65.11],[234.22,66.9],[232.72,68.68],[231.14,70.45],[229.47,72.2],[227.7,73.93],[225.85,75.63],[223.89,77.29],[221.82,78.91],[219.65,80.49],[217.38,82.0],[214.99,83.46],[212.5,84.86],[209.91,86.19],[207.22,87.45],[204.43,88.64],[201.55,89.75],[198.58,90.78],[195.52,91.74],[192.39,92.62],[189.19,93.43],[185.92,94.16],[182.6,94.81],[179.22,95.39],[175.81,95.91],[172.35,96.36],[168.86,96.74],[165.35,97.08],[161.82,97.36],[158.28,97.59],[154.73,97.79],[151.18,97.95],[147.62,98.08],[144.07,98.19],[140.53,98.28],[136.99,98.37],[133.47,98.45],[129.95,98.54],[126.44,98.63],[122.94,98.74],[119.45,98.86],[115.97,99.01],[112.48,99.19],[109.0,99.4],[105.52,99.65],[102.02,99.93],[98.52,100.25],[95.0,100.62],[91.46,101.02],[87.9,101.46],[84.3,101.95],[80.68,102.47],[77.01,103.03],[73.31,103.63],[69.56,104.25],[65.77,104.9],[61.93,105.57],[58.03,106.26],[54.08,106.95],[50.09,107.65],[46.04,108.34],[41.93,109.03],[37.78,109.69],[33.59,110.33],[29.35,110.94],[25.08,111.51],[20.77,112.03],[16.43,112.49],[12.08,112.89],[7.72,113.22],[3.35,113.48],[-1.02,113.65],[-5.36,113.73],[-9.69,113.71],[-13.98,113.6],[-18.23,113.38],[-22.42,113.05],[-26.55,112.61],[-30.6,112.06],[-34.57,111.39],[-38.44,110.61],[-42.21,109.7],[-45.86,108.69],[-49.4,107.56],[-52.8,106.31],[-56.07,104.96],[-59.19,103.5],[-62.17,101.94],[-64.99,100.28],[-67.66,98.52],[-70.18,96.69],[-72.53,94.77],[-74.73,92.78],[-76.77,90.72],[-78.66,88.61],[-80.4,86.44],[-81.99,84.23],[-83.45,81.98],[-84.77,79.71],[-85.97,77.42],[-87.05,75.11],[-88.03,72.8],[-88.91,70.49],[-89.71,68.19],[-90.44,65.91],[-91.11,63.65],[-91.73,61.42],[-92.31,59.22],[-92.87,57.06],[-93.42,54.95],[-93.98,52.87],[-94.54,50.85],[-95.14,48.88],[-95.77,46.96],[-96.44,45.09],[-97.18,43.28],[-97.98,41.53],[-98.85,39.82],[-99.8,38.17],[-100.84,36.57],[-101.96,35.02],[-103.18,33.52],[-104.5,32.05],[-105.91,30.63],[-107.41,29.24],[-109.01,27.89],[-110.7,26.56],[-112.48,25.26],[-114.33,23.97],[-116.26,22.7],[-118.25,21.44],[-120.3,20.18],[-122.4,18.93],[-124.53,17.67],[-126.69,16.41],[-128.87,15.14],[-131.04,13.85],[-133.21,12.55],[-135.35,11.23],[-137.45,9.89],[-139.51,8.52],[-141.51,7.13],[-143.43,5.71],[-145.27,4.27],[-147.01,2.8],[-148.65,1.3],[-150.17,-0.22],[-151.57,-1.77],[-152.83,-3.34],[-153.96,-4.93],[-154.95,-6.55],[-155.79,-8.18],[-156.49,-9.84],[-157.03,-11.5],[-157.43,-13.18],[-157.67,-14.87],[-157.77,-16.56],[-157.73,-18.26],[-157.56,-19.96],[-157.26,-21.66],[-156.83,-23.36],[-156.29,-25.05],[-155.65,-26.74],[-154.92,-28.41],[-154.11,-30.08],[-153.24,-31.73],[-152.31,-33.37],[-151.33,-35.0],[-150.33,-36.62],[-149.32,-38.22],[-148.31,-39.81],[-147.31,-41.39],[-146.34,-42.96],[-145.41,-44.52],[-144.53,-46.07],[-143.71,-47.62],[-142.97,-49.17],[-142.32,-50.72],[-141.76,-52.27],[-141.3,-53.83],[-140.95,-55.39],[-140.72,-56.98],[-140.6,-58.57],[-140.6,-60.19],[-140.72,-61.83],[-140.97,-63.5],[-141.33,-65.19],[-141.81,-66.92],[-142.4,-68.68],[-143.1,-70.48],[-143.89,-72.31],[-144.77,-74.19],[-145.74,-76.11],[-146.76,-78.07],[-147.85,-80.07],[-148.97,-82.11],[-150.13,-84.19],[-151.29,-86.32],[-152.46,-88.48],[-153.61,-90.68],[-154.73,-92.91],[-155.8,-95.18],[-156.8,-97.46],[-157.73,-99.78],[-158.56,-102.11],[-159.28,-104.45],[-159.88,-106.8],[-160.33,-109.16],[-160.64,-111.51],[-160.78,-113.85],[-160.75,-116.17],[-160.54,-118.48],[-160.13,-120.75],[-159.52,-122.99],[-158.71,-125.2],[-157.69,-127.35],[-156.45,-129.45],[-155.0,-131.5],[-153.34,-133.48],[-151.46,-135.39],[-149.37,-137.23],[-147.07,-139.0],[-144.56,-140.68],[-141.86,-142.28],[-138.97,-143.8],[-135.9,-145.22],[-132.66,-146.56],[-129.26,-147.81],[-125.7,-148.97],[-122.01,-150.03],[-118.19,-151.01],[-114.26,-151.91],[-110.23,-152.72],[-106.11,-153.45],[-101.91,-154.1],[-97.66,-154.68],[-93.36,-155.19],[-89.02,-155.63],[-84.65,-156.02],[-80.28,-156.36],[-75.91,-156.65],[-71.54,-156.89],[-67.2,-157.11],[-62.88,-157.29],[-58.6,-157.46],[-54.36,-157.6],[-50.17,-157.74],[-46.03,-157.88],[-41.95,-158.01],[-37.93,-158.16],[-33.98,-158.32],[-30.09,-158.49],[-26.26,-158.69],[-22.49,-158.91],[-18.79,-159.16],[-15.14,-159.44],[-11.55,-159.75],[-8.01,-160.1],[-4.52,-160.48],[-1.07,-160.89],[2.34,-161.34],[5.72,-161.82],[9.07,-162.33],[12.41,-162.87],[15.72,-163.43],[19.03,-164.01],[22.33,-164.61],[25.63,-165.22],[28.94,-165.84],[32.26,-166.46],[35.59,-167.07],[38.94,-167.67],[42.31,-168.26],[45.7,-168.82],[49.11,-169.35],[52.54,-169.84],[56.0,-170.29],[59.49,-170.69],[62.99,-171.04],[66.52,-171.33],[70.06,-171.55],[73.61,-171.7],[77.18,-171.78],[80.75,-171.78],[84.32,-171.7],[87.89,-171.53],[91.45,-171.28],[95.0,-170.94],[98.53,-170.51],[102.03,-169.99],[105.5,-169.39],[108.93,-168.71],[112.32,-167.94],[115.67,-167.09],[118.96,-166.16],[122.2,-165.16],[125.38,-164.1],[128.49,-162.97],[131.55,-161.79],[134.53,-160.56],[137.46,-159.29],[140.31,-157.98],[143.1,-156.64],[145.83,-155.28],[148.49,-153.91],[151.1,-152.54],[153.65,-151.17],[156.15,-149.81],[158.61,-148.46],[161.04,-147.15],[163.43,-145.86],[165.8,-144.61],[168.16,-143.41],[170.51,-142.26],[172.86,-141.17],[175.23,-140.14],[177.62,-139.17],[180.04,-138.27],[182.49,-137.44],[185.0,-136.69],[187.56,-136.0],[190.19,-135.39],[192.9,-134.86],[195.68,-134.4],[198.55,-134.01],[201.52,-133.69],[204.58,-133.43],[207.75,-133.24],[211.02,-133.1],[214.4,-133.01],[217.89,-132.97],[221.48,-132.97],[225.19,-133.01],[228.99,-133.07],[232.9,-133.16],[236.91,-133.25],[241.0,-133.35],[245.18,-133.46],[249.44,-133.55],[253.76,-133.62],[258.14,-133.67],[262.56,-133.69],[267.02,-133.67],[271.51,-133.61],[276.0,-133.5],[280.49,-133.32],[284.96,-133.09],[289.41,-132.79],[293.81,-132.42],[298.16,-131.98],[302.44,-131.46],[306.63,-130.85],[310.73,-130.17],[314.73,-129.4],[318.6,-128.55],[322.35,-127.61],[325.97,-126.59],[329.43,-125.49],[332.74,-124.3],[335.9,-123.04],[338.89,-121.7],[341.71,-120.29],[344.36,-118.81],[346.83,-117.27],[349.14,-115.66],[351.27,-114.0],[353.23,-112.28],[355.03,-110.52],[356.67,-108.72],[358.16,-106.87],[359.49,-105.0],[360.69,-103.1],[361.76,-101.17],[362.71,-99.23],[363.55,-97.28],[364.29,-95.31],[364.95,-93.34],[365.53,-91.37],[366.05,-89.4],[366.52,-87.43],[366.96,-85.47],[367.36,-83.52],[367.76,-81.57],[368.15,-79.64],[368.54,-77.73],[368.96,-75.82],[369.4,-73.93],[369.87,-72.05],[370.39,-70.18],[370.95,-68.33],[371.57,-66.48],[372.24,-64.64],[372.97,-62.81],[373.76,-60.99],[374.61,-59.17],[375.51,-57.35],[376.47,-55.53],[377.48,-53.71],[378.53,-51.88],[379.62,-50.05],[380.74,-48.21],[381.88,-46.36],[383.02,-44.5],[384.17,-42.62],[385.3,-40.74],[386.41,-38.84],[387.48,-36.93],[388.5,-35.0]],[[391.3,-35.0],[392.2,-33.04],[393.04,-31.07],[393.78,-29.09],[394.43,-27.11],[394.97,-25.11],[395.38,-23.11],[395.65,-21.1],[395.77,-19.1],[395.73,-17.1],[395.52,-15.1],[395.12,-13.11],[394.54,-11.13],[393.76,-9.18],[392.78,-7.24],[391.59,-5.32],[390.19,-3.44],[388.58,-1.58],[386.76,0.23],[384.73,2.01],[382.49,3.75],[380.05,5.44],[377.42,7.08],[374.6,8.67],[371.6,10.21],[368.43,11.69],[365.1,13.11],[361.62,14.48],[358.01,15.79],[354.28,17.03],[350.45,18.23],[346.53,19.36],[342.53,20.44],[338.48,21.46],[334.39,22.44],[330.28,23.37],[326.16,24.25],[322.05,25.09],[317.96,25.9],[313.91,26.67],[309.92,27.42],[306.0,28.14],[302.15,28.86],[298.4,29.56],[294.76,30.26],[291.23,30.95],[287.82,31.66],[284.54,32.38],[281.39,33.12],[278.39,33.89],[275.53,34.68],[272.81,35.51],[270.23,36.38],[267.8,37.29],[265.51,38.26],[263.36,39.27],[261.33,40.34],[259.43,41.46],[257.65,42.64],[255.97,43.88],[254.4,45.18],[252.91,46.54],[251.5,47.96],[250.16,49.44],[248.88,50.97],[247.63,52.55],[246.42,54.18],[245.22,55.86],[244.03,57.57],[242.83,59.33],[241.61,61.11],[240.36,62.92],[239.07,64.75],[237.72,66.58],[236.31,68.43],[234.83,70.27],[233.27,72.11],[231.63,73.93],[229.89,75.73],[228.05,77.5],[226.11,79.23],[224.06,80.93],[221.9,82.57],[219.64,84.17],[217.26,85.7],[214.77,87.17],[212.18,88.58],[209.48,89.91],[206.67,91.17],[203.77,92.35],[200.78,93.46],[197.69,94.48],[194.53,95.43],[191.29,96.29],[187.98,97.08],[184.6,97.78],[181.18,98.41],[177.7,98.97],[174.18,99.46],[170.63,99.89],[167.04,100.25],[163.44,100.56],[159.82,100.81],[156.19,101.03],[152.55,101.2],[148.91,101.34],[145.27,101.45],[141.64,101.54],[138.01,101.61],[134.4,101.68],[130.79,101.75],[127.19,101.82],[123.6,101.9],[120.02,102.0],[116.45,102.11],[112.88,102.26],[109.32,102.43],[105.75,102.63],[102.18,102.87],[98.6,103.14],[95.0,103.46],[91.39,103.81],[87.75,104.21],[84.09,104.64],[80.4,105.12],[76.68,105.63],[72.91,106.17],[69.11,106.75],[65.26,107.35],[61.36,107.97],[57.41,108.61],[53.42,109.26],[49.37,109.92],[45.27,110.58],[41.12,111.23],[36.93,111.86],[32.69,112.47],[28.4,113.05],[24.08,113.59],[19.73,114.08],[15.35,114.52],[10.96,114.9],[6.54,115.22],[2.13,115.45],[-2.28,115.61],[-6.68,115.68],[-11.05,115.65],[-15.39,115.53],[-19.69,115.3],[-23.94,114.96],[-28.12,114.51],[-32.22,113.95],[-36.24,113.28],[-40.17,112.49],[-43.99,111.58],[-47.69,110.55],[-51.27,109.41],[-54.73,108.16],[-58.04,106.79],[-61.21,105.32],[-64.24,103.74],[-67.1,102.06],[-69.81,100.29],[-72.36,98.43],[-74.75,96.49],[-76.98,94.47],[-79.05,92.39],[-80.96,90.24],[-82.72,88.04],[-84.32,85.8],[-85.79,83.52],[-87.11,81.21],[-88.31,78.87],[-89.39,76.53],[-90.36,74.17],[-91.23,71.82],[-92.01,69.48],[-92.72,67.15],[-93.36,64.85],[-93.95,62.57],[-94.5,60.32],[-95.02,58.12],[-95.53,55.95],[-96.04,53.83],[-96.56,51.76],[-97.11,49.75],[-97.69,47.79],[-98.32,45.88],[-99.01,44.03],[-99.76,42.23],[-100.59,40.5],[-101.5,38.81],[-102.5,37.18],[-103.59,35.6],[-104.78,34.07],[-106.07,32.58],[-107.46,31.14],[-108.95,29.73],[-110.54,28.36],[-112.23,27.02],[-114.01,25.7],[-115.87,24.4],[-117.82,23.13],[-119.84,21.86],[-121.93,20.6],[-124.07,19.34],[-126.26,18.09],[-128.48,16.82],[-130.72,15.55],[-132.97,14.27],[-135.22,12.97],[-137.46,11.65],[-139.67,10.31],[-141.83,8.95],[-143.94,7.56],[-145.98,6.15],[-147.95,4.71],[-149.82,3.24],[-151.59,1.74],[-153.25,0.22],[-154.79,-1.33],[-156.2,-2.91],[-157.48,-4.51],[-158.61,-6.13],[-159.6,-7.78],[-160.44,-9.44],[-161.12,-11.12],[-161.66,-12.82],[-162.04,-14.52],[-162.28,-16.24],[-162.36,-17.96],[-162.31,-19.68],[-162.12,-21.41],[-161.81,-23.13],[-161.38,-24.85],[-160.83,-26.57],[-160.19,-28.27],[-159.46,-29.97],[-158.66,-31.66],[-157.79,-33.34],[-156.87,-35.0],[-155.92,-36.65],[-154.94,-38.29],[-153.96,-39.92],[-152.98,-41.54],[-152.02,-43.14],[-151.1,-44.74],[-150.22,-46.33],[-149.39,-47.92],[-148.64,-49.51],[-147.96,-51.09],[-147.37,-52.68],[-146.88,-54.27],[-146.49,-55.87],[-146.21,-57.49],[-146.05,-59.12],[-146.0,-60.77],[-146.07,-62.44],[-146.26,-64.14],[-146.57,-65.86],[-147.0,-67.62],[-147.53,-69.41],[-148.17,-71.23],[-148.91,-73.1],[-149.74,-75.0],[-150.65,-76.95],[-151.63,-78.93],[-152.67,-80.96],[-153.75,-83.03],[-154.86,-85.14],[-155.99,-87.3],[-157.12,-89.49],[-158.24,-91.72],[-159.33,-93.98],[-160.37,-96.27],[-161.36,-98.59],[-162.26,-100.94],[-163.07,-103.3],[-163.78,-105.68],[-164.36,-108.06],[-164.81,-110.45],[-165.1,-112.84],[-165.24,-115.22],[-165.2,-117.58],[-164.97,-119.93],[-164.56,-122.24],[-163.94,-124.52],[-163.12,-126.76],[-162.08,-128.96],[-160.83,-131.1],[-159.36,-133.18],[-157.68,-135.2],[-155.77,-137.15],[-153.65,-139.03],[-151.32,-140.83],[-148.78,-142.54],[-146.04,-144.17],[-143.1,-145.72],[-139.98,-147.17],[-136.68,-148.53],[-133.21,-149.8],[-129.59,-150.97],[-125.83,-152.06],[-121.93,-153.05],[-117.92,-153.95],[-113.8,-154.77],[-109.59,-155.5],[-105.3,-156.15],[-100.95,-156.72],[-96.54,-157.22],[-92.09,-157.65],[-87.62,-158.02],[-83.14,-158.34],[-78.65,-158.6],[-74.17,-158.82],[-69.71,-159.0],[-65.28,-159.15],[-60.88,-159.28],[-56.53,-159.38],[-52.22,-159.48],[-47.97,-159.57],[-43.79,-159.66],[-39.66,-159.76],[-35.6,-159.87],[-31.6,-159.99],[-27.68,-160.14],[-23.82,-160.31],[-20.02,-160.5],[-16.29,-160.73],[-12.61,-161.0],[-9.0,-161.3],[-5.43,-161.63],[-1.92,-162.0],[1.56,-162.41],[5.0,-162.85],[8.4,-163.33],[11.78,-163.83],[15.14,-164.37],[18.49,-164.93],[21.83,-165.5],[25.17,-166.1],[28.51,-166.7],[31.85,-167.31],[35.21,-167.92],[38.58,-168.52],[41.97,-169.11],[45.38,-169.68],[48.81,-170.22],[52.26,-170.74],[55.74,-171.21],[59.24,-171.64],[62.76,-172.01],[66.31,-172.33],[69.87,-172.59],[73.44,-172.78],[77.03,-172.9],[80.63,-172.94],[84.23,-172.9],[87.83,-172.78],[91.42,-172.58],[95.0,-172.29],[98.56,-171.91],[102.1,-171.44],[105.61,-170.89],[109.09,-170.25],[112.53,-169.53],[115.92,-168.72],[119.27,-167.84],[122.56,-166.89],[125.79,-165.86],[128.96,-164.77],[132.08,-163.63],[135.12,-162.43],[138.1,-161.18],[141.02,-159.9],[143.87,-158.59],[146.66,-157.25],[149.38,-155.9],[152.05,-154.54],[154.67,-153.18],[157.23,-151.83],[159.75,-150.49],[162.23,-149.17],[164.68,-147.89],[167.11,-146.64],[169.52,-145.43],[171.93,-144.28],[174.34,-143.18],[176.75,-142.13],[179.19,-141.15],[181.66,-140.24],[184.16,-139.4],[186.72,-138.63],[189.33,-137.93],[192.01,-137.31],[194.76,-136.76],[197.59,-136.28],[200.51,-135.88],[203.52,-135.54],[206.63,-135.27],[209.85,-135.06],[213.17,-134.92],[216.6,-134.82],[220.15,-134.77],[223.8,-134.77],[227.57,-134.8],[231.44,-134.86],[235.41,-134.94],[239.49,-135.04],[243.66,-135.14],[247.92,-135.25],[252.25,-135.34],[256.66,-135.42],[261.13,-135.48],[265.64,-135.5],[270.2,-135.49],[274.78,-135.44],[279.38,-135.33],[283.98,-135.17],[288.56,-134.95],[293.12,-134.66],[297.63,-134.3],[302.1,-133.86],[306.49,-133.34],[310.8,-132.74],[315.02,-132.06],[319.14,-131.3],[323.13,-130.44],[327.0,-129.5],[330.72,-128.48],[334.3,-127.37],[337.72,-126.17],[340.98,-124.9],[344.06,-123.54],[346.98,-122.11],[349.71,-120.61],[352.27,-119.04],[354.65,-117.41],[356.85,-115.72],[358.87,-113.97],[360.72,-112.17],[362.4,-110.33],[363.92,-108.45],[365.28,-106.53],[366.49,-104.59],[367.57,-102.61],[368.51,-100.62],[369.34,-98.62],[370.05,-96.6],[370.68,-94.58],[371.22,-92.55],[371.68,-90.53],[372.09,-88.51],[372.46,-86.49],[372.78,-84.48],[373.09,-82.49],[373.39,-80.5],[373.69,-78.53],[374.0,-76.57],[374.33,-74.63],[374.7,-72.7],[375.1,-70.78],[375.54,-68.88],[376.04,-66.99],[376.59,-65.11],[377.2,-63.24],[377.86,-61.37],[378.59,-59.51],[379.38,-57.66],[380.22,-55.8],[381.11,-53.95],[382.06,-52.09],[383.04,-50.23],[384.06,-48.36],[385.1,-46.48],[386.16,-44.6],[387.22,-42.7],[388.28,-40.8],[389.32,-38.88],[390.33,-36.94],[391.3,-35.0]],[[393.98,-35.0],[394.83,-33.03],[395.63,-31.04],[396.34,-29.04],[396.96,-27.04],[397.48,-25.03],[397.87,-23.01],[398.14,-20.99],[398.26,-18.97],[398.22,-16.95],[398.02,-14.93],[397.64,-12.93],[397.08,-10.93],[396.32,-8.96],[395.36,-7.0],[394.2,-5.06],[392.83,-3.15],[391.26,-1.28],[389.47,0.56],[387.47,2.36],[385.27,4.12],[382.86,5.84],[380.26,7.51],[377.47,9.12],[374.49,10.68],[371.34,12.19],[368.03,13.64],[364.57,15.03],[360.98,16.36],[357.26,17.63],[353.43,18.85],[349.51,20.0],[345.51,21.1],[341.45,22.15],[337.34,23.15],[333.21,24.09],[329.07,24.99],[324.93,25.85],[320.81,26.67],[316.73,27.46],[312.7,28.23],[308.74,28.97],[304.85,29.69],[301.06,30.4],[297.37,31.11],[293.79,31.81],[290.33,32.53],[287.0,33.26],[283.81,34.0],[280.76,34.78],[277.85,35.58],[275.08,36.41],[272.47,37.29],[269.99,38.21],[267.66,39.18],[265.47,40.2],[263.42,41.28],[261.49,42.42],[259.68,43.61],[257.99,44.87],[256.4,46.19],[254.9,47.57],[253.48,49.01],[252.14,50.51],[250.85,52.07],[249.61,53.68],[248.4,55.35],[247.21,57.06],[246.03,58.82],[244.85,60.62],[243.65,62.45],[242.42,64.31],[241.15,66.19],[239.82,68.08],[238.44,69.99],[236.98,71.89],[235.45,73.79],[233.82,75.68],[232.11,77.55],[230.29,79.39],[228.36,81.19],[226.33,82.96],[224.18,84.68],[221.92,86.35],[219.55,87.96],[217.06,89.51],[214.46,90.99],[211.75,92.4],[208.94,93.73],[206.02,94.98],[203.0,96.16],[199.89,97.25],[196.69,98.26],[193.41,99.18],[190.05,100.03],[186.63,100.79],[183.15,101.47],[179.61,102.07],[176.03,102.6],[172.41,103.06],[168.75,103.46],[165.07,103.79],[161.37,104.07],[157.66,104.3],[153.94,104.48],[150.21,104.62],[146.49,104.74],[142.76,104.82],[139.05,104.89],[135.34,104.94],[131.64,104.99],[127.95,105.04],[124.27,105.09],[120.6,105.16],[116.94,105.24],[113.29,105.34],[109.63,105.47],[105.98,105.63],[102.33,105.82],[98.67,106.05],[95.0,106.31],[91.31,106.62],[87.61,106.96],[83.88,107.34],[80.13,107.76],[76.34,108.22],[72.52,108.71],[68.65,109.23],[64.75,109.78],[60.8,110.36],[56.8,110.95],[52.76,111.56],[48.66,112.17],[44.52,112.78],[40.33,113.39],[36.09,113.99],[31.8,114.56],[27.48,115.11],[23.12,115.62],[18.72,116.09],[14.3,116.5],[9.86,116.86],[5.4,117.15],[0.94,117.37],[-3.51,117.51],[-7.95,117.57],[-12.38,117.53],[-16.76,117.39],[-21.11,117.15],[-25.4,116.81],[-29.63,116.36],[-33.79,115.79],[-37.86,115.11],[-41.83,114.31],[-45.7,113.39],[-49.46,112.36],[-53.09,111.21],[-56.6,109.94],[-59.96,108.56],[-63.18,107.08],[-66.24,105.49],[-69.15,103.79],[-71.9,102.01],[-74.49,100.13],[-76.92,98.17],[-79.18,96.13],[-81.27,94.02],[-83.21,91.84],[-84.98,89.61],[-86.61,87.34],[-88.08,85.02],[-89.42,82.68],[-90.62,80.31],[-91.7,77.92],[-92.66,75.53],[-93.52,73.13],[-94.28,70.75],[-94.97,68.38],[-95.58,66.03],[-96.15,63.7],[-96.66,61.41],[-97.15,59.16],[-97.63,56.95],[-98.1,54.79],[-98.58,52.68],[-99.08,50.62],[-99.62,48.61],[-100.2,46.67],[-100.85,44.78],[-101.56,42.95],[-102.34,41.17],[-103.21,39.45],[-104.17,37.79],[-105.23,36.18],[-106.39,34.62],[-107.65,33.11],[-109.02,31.65],[-110.5,30.22],[-112.08,28.83],[-113.76,27.48],[-115.55,26.15],[-117.43,24.84],[-119.39,23.56],[-121.44,22.28],[-123.57,21.02],[-125.75,19.76],[-127.99,18.5],[-130.28,17.24],[-132.59,15.97],[-134.92,14.69],[-137.26,13.39],[-139.59,12.08],[-141.9,10.74],[-144.17,9.38],[-146.4,8.0],[-148.56,6.59],[-150.65,5.15],[-152.66,3.68],[-154.57,2.19],[-156.37,0.66],[-158.06,-0.89],[-159.61,-2.47],[-161.04,-4.08],[-162.32,-5.71],[-163.46,-7.37],[-164.44,-9.04],[-165.27,-10.73],[-165.95,-12.44],[-166.48,-14.17],[-166.85,-15.9],[-167.07,-17.64],[-167.14,-19.39],[-167.08,-21.14],[-166.88,-22.9],[-166.55,-24.65],[-166.11,-26.39],[-165.56,-28.13],[-164.91,-29.86],[-164.18,-31.59],[-163.38,-33.3],[-162.52,-35.0],[-161.62,-36.69],[-160.68,-38.37],[-159.73,-40.03],[-158.78,-41.69],[-157.83,-43.34],[-156.91,-44.97],[-156.03,-46.6],[-155.19,-48.23],[-154.42,-49.85],[-153.72,-51.47],[-153.1,-53.1],[-152.57,-54.72],[-152.14,-56.36],[-151.82,-58.01],[-151.61,-59.68],[-151.51,-61.36],[-151.52,-63.06],[-151.65,-64.79],[-151.9,-66.54],[-152.27,-68.33],[-152.74,-70.15],[-153.32,-72.0],[-154.0,-73.89],[-154.77,-75.82],[-155.62,-77.8],[-156.55,-79.81],[-157.53,-81.86],[-158.56,-83.96],[-159.62,-86.1],[-160.71,-88.28],[-161.8,-90.5],[-162.88,-92.76],[-163.93,-95.05],[-164.94,-97.37],[-165.9,-99.72],[-166.78,-102.1],[-167.57,-104.49],[-168.25,-106.9],[-168.81,-109.32],[-169.24,-111.74],[-169.52,-114.16],[-169.64,-116.58],[-169.59,-118.98],[-169.36,-121.36],[-168.93,-123.71],[-168.3,-126.03],[-167.46,-128.31],[-166.41,-130.54],[-165.14,-132.72],[-163.65,-134.84],[-161.94,-136.89],[-160.02,-138.88],[-157.87,-140.79],[-155.5,-142.62],[-152.92,-144.37],[-150.14,-146.03],[-147.16,-147.6],[-143.99,-149.08],[-140.63,-150.47],[-137.11,-151.76],[-133.42,-152.95],[-129.59,-154.05],[-125.62,-155.05],[-121.52,-155.96],[-117.32,-156.79],[-113.02,-157.52],[-108.64,-158.16],[-104.18,-158.73],[-99.68,-159.22],[-95.13,-159.64],[-90.55,-159.99],[-85.96,-160.29],[-81.36,-160.53],[-76.77,-160.72],[-72.19,-160.87],[-67.64,-160.98],[-63.13,-161.07],[-58.67,-161.14],[-54.25,-161.19],[-49.89,-161.24],[-45.59,-161.28],[-41.36,-161.33],[-37.19,-161.39],[-33.1,-161.46],[-29.07,-161.56],[-25.12,-161.68],[-21.23,-161.82],[-17.41,-162.0],[-13.66,-162.22],[-9.96,-162.47],[-6.33,-162.76],[-2.74,-163.09],[0.79,-163.45],[4.29,-163.85],[7.75,-164.29],[11.18,-164.77],[14.59,-165.27],[17.97,-165.8],[21.35,-166.36],[24.72,-166.94],[28.09,-167.53],[31.46,-168.13],[34.84,-168.74],[38.23,-169.34],[41.64,-169.93],[45.07,-170.51],[48.52,-171.07],[51.99,-171.6],[55.48,-172.1],[59.0,-172.55],[62.54,-172.96],[66.1,-173.31],[69.68,-173.6],[73.28,-173.83],[76.89,-173.99],[80.51,-174.08],[84.14,-174.09],[87.76,-174.02],[91.39,-173.86],[95.0,-173.62],[98.6,-173.3],[102.18,-172.88],[105.73,-172.38],[109.25,-171.79],[112.74,-171.12],[116.18,-170.36],[119.57,-169.53],[122.92,-168.62],[126.21,-167.64],[129.44,-166.59],[132.61,-165.48],[135.72,-164.32],[138.76,-163.11],[141.74,-161.86],[144.65,-160.57],[147.51,-159.26],[150.3,-157.93],[153.03,-156.58],[155.7,-155.24],[158.33,-153.9],[160.91,-152.57],[163.46,-151.26],[165.97,-149.97],[168.46,-148.72],[170.93,-147.51],[173.39,-146.35],[175.85,-145.24],[178.32,-144.19],[180.81,-143.2],[183.33,-142.27],[185.89,-141.42],[188.49,-140.63],[191.15,-139.92],[193.88,-139.28],[196.67,-138.71],[199.55,-138.22],[202.52,-137.8],[205.58,-137.45],[208.74,-137.17],[212.01,-136.95],[215.38,-136.78],[218.87,-136.68],[222.46,-136.62],[226.18,-136.61],[230.0,-136.63],[233.93,-136.69],[237.97,-136.76],[242.12,-136.86],[246.36,-136.96],[250.69,-137.07],[255.11,-137.16],[259.6,-137.25],[264.15,-137.31],[268.76,-137.34],[273.41,-137.33],[278.09,-137.29],[282.78,-137.19],[287.48,-137.03],[292.18,-136.82],[296.84,-136.53],[301.47,-136.18],[306.05,-135.74],[310.56,-135.23],[314.98,-134.64],[319.32,-133.96],[323.55,-133.19],[327.66,-132.34],[331.64,-131.39],[335.47,-130.36],[339.16,-129.24],[342.69,-128.04],[346.05,-126.75],[349.23,-125.38],[352.24,-123.93],[355.06,-122.41],[357.7,-120.82],[360.15,-119.16],[362.42,-117.43],[364.5,-115.65],[366.4,-113.82],[368.12,-111.94],[369.67,-110.02],[371.05,-108.06],[372.28,-106.07],[373.36,-104.05],[374.3,-102.01],[375.11,-99.96],[375.8,-97.89],[376.39,-95.81],[376.88,-93.73],[377.29,-91.65],[377.64,-89.58],[377.93,-87.51],[378.18,-85.44],[378.4,-83.39],[378.61,-81.35],[378.81,-79.33],[379.01,-77.32],[379.23,-75.32],[379.48,-73.34],[379.76,-71.38],[380.09,-69.43],[380.46,-67.49],[380.88,-65.57],[381.37,-63.65],[381.91,-61.75],[382.51,-59.85],[383.17,-57.96],[383.89,-56.07],[384.67,-54.18],[385.5,-52.3],[386.38,-50.41],[387.29,-48.51],[388.23,-46.61],[389.2,-44.7],[390.18,-42.78],[391.16,-40.85],[392.13,-38.91],[393.07,-36.96],[393.98,-35.0]],[[396.55,-35.0],[397.35,-33.01],[398.1,-31.01],[398.77,-29.0],[399.37,-26.98],[399.86,-24.95],[400.24,-22.92],[400.5,-20.88],[400.62,-18.84],[400.59,-16.81],[400.4,-14.77],[400.04,-12.75],[399.49,-10.74],[398.76,-8.74],[397.83,-6.77],[396.71,-4.81],[395.37,-2.88],[393.83,-0.99],[392.08,0.88],[390.13,2.7],[387.96,4.49],[385.59,6.23],[383.03,7.92],[380.27,9.56],[377.33,11.14],[374.21,12.68],[370.92,14.15],[367.49,15.57],[363.91,16.93],[360.21,18.22],[356.39,19.46],[352.47,20.64],[348.48,21.77],[344.41,22.84],[340.3,23.86],[336.16,24.82],[332.0,25.74],[327.84,26.62],[323.69,27.46],[319.58,28.27],[315.52,29.05],[311.52,29.8],[307.6,30.54],[303.76,31.26],[300.03,31.98],[296.41,32.7],[292.9,33.42],[289.53,34.16],[286.29,34.91],[283.19,35.69],[280.24,36.5],[277.43,37.34],[274.77,38.23],[272.26,39.16],[269.89,40.14],[267.67,41.17],[265.58,42.26],[263.62,43.41],[261.79,44.62],[260.07,45.89],[258.46,47.23],[256.95,48.63],[255.52,50.09],[254.17,51.62],[252.88,53.2],[251.64,54.85],[250.44,56.55],[249.26,58.3],[248.09,60.1],[246.92,61.94],[245.73,63.82],[244.52,65.72],[243.27,67.66],[241.97,69.61],[240.6,71.57],[239.17,73.54],[237.66,75.5],[236.05,77.45],[234.35,79.39],[232.55,81.3],[230.64,83.18],[228.62,85.02],[226.49,86.82],[224.24,88.56],[221.87,90.25],[219.38,91.87],[216.78,93.43],[214.06,94.91],[211.23,96.32],[208.29,97.64],[205.24,98.88],[202.1,100.04],[198.87,101.12],[195.55,102.1],[192.15,103.0],[188.68,103.82],[185.14,104.55],[181.54,105.2],[177.9,105.77],[174.21,106.27],[170.48,106.7],[166.72,107.06],[162.94,107.36],[159.15,107.6],[155.34,107.79],[151.52,107.94],[147.71,108.06],[143.9,108.14],[140.09,108.2],[136.29,108.24],[132.49,108.26],[128.71,108.29],[124.94,108.31],[121.18,108.34],[117.43,108.39],[113.69,108.45],[109.95,108.54],[106.22,108.65],[102.49,108.79],[98.75,108.97],[95.0,109.18],[91.24,109.43],[87.47,109.72],[83.67,110.04],[79.85,110.41],[76.0,110.81],[72.12,111.24],[68.2,111.71],[64.24,112.2],[60.24,112.73],[56.2,113.27],[52.1,113.82],[47.96,114.39],[43.78,114.96],[39.54,115.52],[35.26,116.08],[30.94,116.61],[26.57,117.13],[22.17,117.6],[17.73,118.04],[13.27,118.43],[8.79,118.77],[4.29,119.04],[-0.21,119.24],[-4.7,119.36],[-9.19,119.4],[-13.65,119.35],[-18.09,119.2],[-22.48,118.95],[-26.82,118.6],[-31.1,118.13],[-35.3,117.56],[-39.42,116.87],[-43.44,116.06],[-47.36,115.14],[-51.17,114.1],[-54.85,112.94],[-58.4,111.67],[-61.81,110.28],[-65.08,108.79],[-68.19,107.18],[-71.14,105.48],[-73.94,103.67],[-76.56,101.78],[-79.02,99.8],[-81.32,97.74],[-83.44,95.6],[-85.4,93.41],[-87.2,91.15],[-88.85,88.85],[-90.34,86.5],[-91.68,84.12],[-92.89,81.71],[-93.97,79.29],[-94.93,76.86],[-95.78,74.43],[-96.53,72.0],[-97.2,69.59],[-97.79,67.2],[-98.33,64.83],[-98.82,62.5],[-99.27,60.2],[-99.71,57.95],[-100.14,55.74],[-100.59,53.59],[-101.05,51.49],[-101.54,49.44],[-102.09,47.45],[-102.69,45.53],[-103.35,43.66],[-104.1,41.85],[-104.93,40.1],[-105.86,38.41],[-106.88,36.77],[-108.01,35.19],[-109.25,33.65],[-110.6,32.16],[-112.06,30.72],[-113.63,29.31],[-115.32,27.94],[-117.11,26.6],[-119.0,25.29],[-120.99,23.99],[-123.06,22.71],[-125.22,21.44],[-127.46,20.18],[-129.75,18.92],[-132.1,17.66],[-134.48,16.4],[-136.89,15.12],[-139.32,13.82],[-141.74,12.51],[-144.15,11.18],[-146.54,9.82],[-148.88,8.44],[-151.17,7.03],[-153.39,5.6],[-155.53,4.13],[-157.58,2.64],[-159.53,1.11],[-161.36,-0.45],[-163.07,-2.03],[-164.64,-3.64],[-166.08,-5.28],[-167.36,-6.95],[-168.5,-8.63],[-169.49,-10.34],[-170.31,-12.07],[-170.98,-13.81],[-171.49,-15.56],[-171.85,-17.33],[-172.05,-19.1],[-172.11,-20.88],[-172.03,-22.66],[-171.82,-24.44],[-171.48,-26.21],[-171.02,-27.99],[-170.47,-29.75],[-169.82,-31.51],[-169.09,-33.26],[-168.29,-35.0],[-167.44,-36.73],[-166.54,-38.45],[-165.62,-40.15],[-164.69,-41.85],[-163.76,-43.53],[-162.85,-45.21],[-161.96,-46.88],[-161.12,-48.54],[-160.33,-50.2],[-159.6,-51.86],[-158.95,-53.52],[-158.39,-55.19],[-157.91,-56.86],[-157.54,-58.54],[-157.27,-60.24],[-157.12,-61.96],[-157.07,-63.69],[-157.14,-65.45],[-157.33,-67.24],[-157.63,-69.05],[-158.03,-70.9],[-158.55,-72.78],[-159.16,-74.7],[-159.86,-76.66],[-160.65,-78.65],[-161.51,-80.69],[-162.43,-82.77],[-163.41,-84.9],[-164.42,-87.06],[-165.45,-89.27],[-166.49,-91.51],[-167.52,-93.8],[-168.54,-96.11],[-169.51,-98.46],[-170.43,-100.84],[-171.27,-103.25],[-172.03,-105.67],[-172.69,-108.11],[-173.23,-110.56],[-173.64,-113.02],[-173.9,-115.47],[-174.0,-117.92],[-173.93,-120.36],[-173.68,-122.77],[-173.23,-125.16],[-172.59,-127.51],[-171.74,-129.83],[-170.67,-132.09],[-169.38,-134.31],[-167.87,-136.47],[-166.14,-138.56],[-164.19,-140.58],[-162.01,-142.52],[-159.61,-144.39],[-157.0,-146.17],[-154.17,-147.86],[-151.15,-149.46],[-147.93,-150.96],[-144.52,-152.37],[-140.93,-153.68],[-137.18,-154.89],[-133.28,-156.01],[-129.24,-157.02],[-125.07,-157.94],[-120.78,-158.77],[-116.39,-159.5],[-111.92,-160.15],[-107.37,-160.71],[-102.77,-161.19],[-98.12,-161.6],[-93.43,-161.94],[-88.73,-162.21],[-84.02,-162.42],[-79.32,-162.59],[-74.63,-162.71],[-69.98,-162.79],[-65.35,-162.84],[-60.77,-162.87],[-56.24,-162.88],[-51.77,-162.88],[-47.37,-162.88],[-43.03,-162.88],[-38.76,-162.89],[-34.56,-162.91],[-30.44,-162.95],[-26.39,-163.02],[-22.42,-163.12],[-18.51,-163.25],[-14.68,-163.41],[-10.91,-163.62],[-7.2,-163.86],[-3.55,-164.14],[0.05,-164.46],[3.6,-164.83],[7.12,-165.23],[10.6,-165.67],[14.05,-166.15],[17.47,-166.65],[20.89,-167.19],[24.29,-167.75],[27.69,-168.33],[31.08,-168.92],[34.49,-169.52],[37.9,-170.12],[41.33,-170.72],[44.78,-171.31],[48.24,-171.89],[51.73,-172.43],[55.24,-172.95],[58.77,-173.43],[62.32,-173.87],[65.9,-174.26],[69.5,-174.59],[73.12,-174.86],[76.75,-175.07],[80.39,-175.2],[84.04,-175.26],[87.7,-175.24],[91.35,-175.14],[95.0,-174.95],[98.63,-174.68],[102.25,-174.32],[105.85,-173.87],[109.41,-173.33],[112.94,-172.71],[116.44,-172.01],[119.88,-171.23],[123.28,-170.37],[126.63,-169.43],[129.92,-168.43],[133.15,-167.36],[136.32,-166.24],[139.43,-165.07],[142.47,-163.85],[145.45,-162.59],[148.37,-161.31],[151.23,-160.0],[154.03,-158.67],[156.77,-157.34],[159.46,-156.02],[162.11,-154.7],[164.72,-153.39],[167.29,-152.11],[169.84,-150.86],[172.37,-149.65],[174.89,-148.49],[177.41,-147.37],[179.94,-146.31],[182.48,-145.31],[185.06,-144.37],[187.67,-143.5],[190.32,-142.7],[193.03,-141.97],[195.8,-141.31],[198.65,-140.73],[201.58,-140.22],[204.59,-139.78],[207.7,-139.41],[210.91,-139.11],[214.23,-138.88],[217.65,-138.7],[221.19,-138.59],[224.84,-138.52],[228.61,-138.49],[232.49,-138.51],[236.48,-138.55],[240.59,-138.62],[244.8,-138.71],[249.11,-138.81],[253.51,-138.91],[258.0,-139.01],[262.57,-139.09],[267.21,-139.16],[271.9,-139.19],[276.65,-139.19],[281.42,-139.15],[286.21,-139.05],[291.01,-138.9],[295.81,-138.69],[300.58,-138.41],[305.32,-138.06],[310.0,-137.63],[314.63,-137.13],[319.17,-136.53],[323.62,-135.85],[327.96,-135.09],[332.18,-134.23],[336.27,-133.28],[340.22,-132.24],[344.01,-131.12],[347.64,-129.9],[351.1,-128.6],[354.39,-127.21],[357.48,-125.75],[360.39,-124.2],[363.11,-122.58],[365.64,-120.9],[367.97,-119.14],[370.11,-117.33],[372.05,-115.46],[373.82,-113.55],[375.4,-111.58],[376.81,-109.58],[378.05,-107.55],[379.13,-105.48],[380.06,-103.4],[380.85,-101.29],[381.52,-99.17],[382.07,-97.04],[382.52,-94.91],[382.88,-92.77],[383.17,-90.64],[383.39,-88.52],[383.56,-86.4],[383.69,-84.3],[383.8,-82.2],[383.89,-80.12],[383.99,-78.06],[384.1,-76.01],[384.23,-73.98],[384.39,-71.97],[384.59,-69.97],[384.83,-67.99],[385.13,-66.02],[385.48,-64.06],[385.89,-62.12],[386.36,-60.18],[386.9,-58.26],[387.5,-56.33],[388.15,-54.41],[388.86,-52.5],[389.63,-50.58],[390.43,-48.66],[391.28,-46.73],[392.15,-44.8],[393.04,-42.86],[393.93,-40.91],[394.82,-38.95],[395.7,-36.98],[396.55,-35.0]],[[399.0,-35.0],[399.75,-32.99],[400.45,-30.98],[401.09,-28.95],[401.65,-26.92],[402.13,-24.87],[402.49,-22.83],[402.74,-20.78],[402.86,-18.72],[402.84,-16.67],[402.66,-14.63],[402.31,-12.59],[401.8,-10.56],[401.09,-8.54],[400.2,-6.55],[399.11,-4.57],[397.81,-2.62],[396.31,-0.7],[394.61,1.18],[392.69,3.03],[390.57,4.84],[388.25,6.6],[385.72,8.32],[383.0,9.98],[380.1,11.6],[377.02,13.16],[373.77,14.66],[370.36,16.1],[366.81,17.49],[363.13,18.81],[359.33,20.08],[355.43,21.28],[351.44,22.43],[347.38,23.53],[343.27,24.57],[339.12,25.56],[334.95,26.5],[330.77,27.4],[326.61,28.26],[322.48,29.08],[318.39,29.88],[314.36,30.65],[310.4,31.4],[306.53,32.14],[302.76,32.87],[299.09,33.6],[295.55,34.33],[292.13,35.08],[288.85,35.85],[285.71,36.64],[282.71,37.45],[279.86,38.31],[277.16,39.2],[274.6,40.14],[272.2,41.13],[269.94,42.17],[267.82,43.27],[265.83,44.44],[263.97,45.66],[262.23,46.95],[260.6,48.3],[259.07,49.72],[257.64,51.21],[256.27,52.76],[254.98,54.38],[253.74,56.05],[252.54,57.78],[251.36,59.57],[250.2,61.41],[249.04,63.29],[247.87,65.22],[246.67,67.17],[245.44,69.16],[244.15,71.16],[242.81,73.18],[241.39,75.21],[239.9,77.24],[238.31,79.26],[236.63,81.26],[234.85,83.24],[232.95,85.2],[230.95,87.11],[228.82,88.98],[226.58,90.8],[224.21,92.56],[221.72,94.26],[219.11,95.89],[216.38,97.45],[213.54,98.92],[210.58,100.32],[207.51,101.63],[204.34,102.86],[201.07,104.0],[197.71,105.05],[194.26,106.01],[190.74,106.88],[187.15,107.66],[183.49,108.36],[179.78,108.97],[176.02,109.51],[172.22,109.96],[168.38,110.35],[164.52,110.67],[160.64,110.93],[156.75,111.14],[152.85,111.29],[148.94,111.41],[145.04,111.48],[141.14,111.53],[137.24,111.55],[133.36,111.56],[129.48,111.56],[125.62,111.55],[121.77,111.55],[117.93,111.56],[114.1,111.58],[110.28,111.62],[106.46,111.68],[102.64,111.77],[98.82,111.9],[95.0,112.05],[91.17,112.24],[87.32,112.47],[83.46,112.74],[79.58,113.04],[75.67,113.39],[71.73,113.76],[67.75,114.17],[63.74,114.61],[59.69,115.07],[55.6,115.56],[51.46,116.06],[47.27,116.58],[43.04,117.1],[38.77,117.62],[34.45,118.13],[30.09,118.63],[25.68,119.1],[21.24,119.54],[16.77,119.95],[12.27,120.31],[7.75,120.62],[3.22,120.86],[-1.32,121.04],[-5.86,121.14],[-10.38,121.17],[-14.89,121.1],[-19.37,120.94],[-23.8,120.68],[-28.18,120.32],[-32.51,119.85],[-36.76,119.26],[-40.92,118.57],[-44.99,117.76],[-48.96,116.83],[-52.82,115.78],[-56.55,114.62],[-60.15,113.34],[-63.61,111.94],[-66.92,110.44],[-70.07,108.83],[-73.07,107.11],[-75.91,105.29],[-78.57,103.38],[-81.07,101.39],[-83.4,99.31],[-85.56,97.15],[-87.55,94.93],[-89.37,92.65],[-91.04,90.32],[-92.54,87.95],[-93.9,85.54],[-95.12,83.1],[-96.2,80.64],[-97.16,78.18],[-98.0,75.71],[-98.75,73.24],[-99.4,70.79],[-99.98,68.35],[-100.49,65.95],[-100.96,63.57],[-101.38,61.23],[-101.79,58.94],[-102.19,56.69],[-102.59,54.5],[-103.02,52.36],[-103.48,50.27],[-103.98,48.25],[-104.54,46.28],[-105.17,44.38],[-105.87,42.54],[-106.67,40.75],[-107.56,39.03],[-108.55,37.36],[-109.65,35.75],[-110.87,34.2],[-112.2,32.69],[-113.65,31.22],[-115.21,29.8],[-116.89,28.41],[-118.69,27.06],[-120.6,25.74],[-122.6,24.43],[-124.71,23.15],[-126.91,21.88],[-129.19,20.61],[-131.53,19.35],[-133.94,18.09],[-136.4,16.82],[-138.89,15.55],[-141.4,14.26],[-143.92,12.95],[-146.44,11.62],[-148.93,10.27],[-151.4,8.89],[-153.81,7.49],[-156.16,6.05],[-158.44,4.59],[-160.63,3.09],[-162.73,1.56],[-164.71,0.0],[-166.57,-1.58],[-168.29,-3.2],[-169.88,-4.85],[-171.33,-6.52],[-172.62,-8.22],[-173.76,-9.94],[-174.73,-11.69],[-175.55,-13.44],[-176.21,-15.22],[-176.7,-17.01],[-177.04,-18.8],[-177.23,-20.61],[-177.27,-22.41],[-177.17,-24.22],[-176.94,-26.03],[-176.59,-27.84],[-176.12,-29.64],[-175.55,-31.44],[-174.9,-33.22],[-174.16,-35.0],[-173.36,-36.77],[-172.52,-38.52],[-171.63,-40.27],[-170.73,-42.01],[-169.81,-43.73],[-168.91,-45.45],[-168.02,-47.16],[-167.16,-48.86],[-166.36,-50.56],[-165.6,-52.26],[-164.92,-53.96],[-164.31,-55.66],[-163.8,-57.37],[-163.37,-59.09],[-163.05,-60.82],[-162.83,-62.57],[-162.72,-64.33],[-162.72,-66.12],[-162.84,-67.94],[-163.07,-69.78],[-163.4,-71.66],[-163.84,-73.57],[-164.38,-75.51],[-165.01,-77.5],[-165.73,-79.52],[-166.52,-81.59],[-167.38,-83.69],[-168.29,-85.84],[-169.23,-88.03],[-170.21,-90.26],[-171.19,-92.53],[-172.17,-94.84],[-173.14,-97.18],[-174.06,-99.56],[-174.94,-101.96],[-175.75,-104.39],[-176.47,-106.85],[-177.1,-109.32],[-177.61,-111.8],[-177.99,-114.28],[-178.22,-116.77],[-178.3,-119.25],[-178.21,-121.71],[-177.94,-124.16],[-177.48,-126.58],[-176.81,-128.97],[-175.94,-131.32],[-174.85,-133.62],[-173.55,-135.87],[-172.02,-138.06],[-170.26,-140.19],[-168.28,-142.24],[-166.07,-144.22],[-163.64,-146.12],[-160.99,-147.93],[-158.13,-149.65],[-155.06,-151.28],[-151.79,-152.81],[-148.33,-154.24],[-144.69,-155.57],[-140.88,-156.8],[-136.91,-157.93],[-132.79,-158.96],[-128.54,-159.89],[-124.18,-160.72],[-119.71,-161.46],[-115.14,-162.1],[-110.5,-162.66],[-105.8,-163.13],[-101.05,-163.52],[-96.27,-163.85],[-91.46,-164.1],[-86.65,-164.29],[-81.84,-164.43],[-77.04,-164.52],[-72.27,-164.57],[-67.54,-164.58],[-62.85,-164.57],[-58.21,-164.54],[-53.63,-164.5],[-49.11,-164.45],[-44.67,-164.4],[-40.3,-164.36],[-36.0,-164.33],[-31.79,-164.33],[-27.64,-164.34],[-23.58,-164.39],[-19.59,-164.47],[-15.68,-164.58],[-11.83,-164.74],[-8.05,-164.93],[-4.33,-165.17],[-0.67,-165.45],[2.94,-165.78],[6.5,-166.14],[10.03,-166.55],[13.52,-167.0],[16.99,-167.48],[20.44,-167.99],[23.87,-168.53],[27.3,-169.1],[30.72,-169.68],[34.15,-170.28],[37.58,-170.88],[41.03,-171.49],[44.49,-172.09],[47.97,-172.67],[51.47,-173.24],[55.0,-173.78],[58.54,-174.29],[62.12,-174.76],[65.71,-175.19],[69.32,-175.56],[72.96,-175.87],[76.61,-176.12],[80.28,-176.31],[83.95,-176.42],[87.64,-176.45],[91.32,-176.4],[95.0,-176.27],[98.67,-176.05],[102.33,-175.75],[105.96,-175.36],[109.57,-174.88],[113.15,-174.32],[116.7,-173.67],[120.2,-172.94],[123.65,-172.13],[127.06,-171.25],[130.41,-170.29],[133.7,-169.27],[136.94,-168.19],[140.11,-167.06],[143.22,-165.87],[146.27,-164.65],[149.25,-163.39],[152.18,-162.11],[155.05,-160.81],[157.86,-159.5],[160.62,-158.19],[163.33,-156.88],[166.01,-155.59],[168.65,-154.31],[171.26,-153.06],[173.85,-151.85],[176.44,-150.68],[179.02,-149.56],[181.6,-148.49],[184.21,-147.48],[186.84,-146.53],[189.5,-145.64],[192.21,-144.83],[194.97,-144.08],[197.79,-143.41],[200.69,-142.81],[203.66,-142.28],[206.73,-141.82],[209.89,-141.44],[213.14,-141.12],[216.51,-140.87],[219.98,-140.68],[223.57,-140.54],[227.28,-140.46],[231.1,-140.42],[235.03,-140.42],[239.09,-140.46],[243.25,-140.52],[247.53,-140.6],[251.9,-140.7],[256.38,-140.79],[260.94,-140.89],[265.59,-140.97],[270.31,-141.03],[275.08,-141.06],[279.91,-141.06],[284.78,-141.02],[289.67,-140.93],[294.56,-140.79],[299.46,-140.58],[304.33,-140.3],[309.18,-139.95],[313.97,-139.53],[318.7,-139.02],[323.35,-138.43],[327.91,-137.75],[332.36,-136.98],[336.7,-136.12],[340.9,-135.16],[344.95,-134.12],[348.85,-132.98],[352.58,-131.76],[356.14,-130.44],[359.52,-129.04],[362.71,-127.55],[365.7,-125.99],[368.5,-124.34],[371.1,-122.63],[373.49,-120.85],[375.69,-119.0],[377.69,-117.1],[379.49,-115.14],[381.1,-113.14],[382.53,-111.1],[383.79,-109.02],[384.87,-106.91],[385.8,-104.77],[386.58,-102.62],[387.22,-100.45],[387.73,-98.27],[388.14,-96.08],[388.44,-93.89],[388.66,-91.7],[388.81,-89.52],[388.89,-87.35],[388.94,-85.19],[388.95,-83.04],[388.94,-80.91],[388.93,-78.8],[388.92,-76.7],[388.93,-74.62],[388.96,-72.56],[389.04,-70.51],[389.15,-68.48],[389.31,-66.47],[389.53,-64.47],[389.81,-62.49],[390.15,-60.51],[390.56,-58.55],[391.03,-56.59],[391.56,-54.64],[392.15,-52.69],[392.79,-50.74],[393.49,-48.8],[394.22,-46.85],[395.0,-44.89],[395.79,-42.93],[396.6,-40.96],[397.42,-38.98],[398.22,-37.0],[399.0,-35.0]],[[401.35,-35.0],[402.04,-32.98],[402.7,-30.95],[403.29,-28.91],[403.82,-26.86],[404.27,-24.8],[404.62,-22.74],[404.87,-20.68],[404.99,-18.61],[404.97,-16.55],[404.8,-14.48],[404.48,-12.43],[403.99,-10.38],[403.31,-8.35],[402.45,-6.34],[401.4,-4.34],[400.15,-2.37],[398.7,-0.43],[397.04,1.48],[395.17,3.35],[393.1,5.18],[390.82,6.97],[388.35,8.71],[385.68,10.4],[382.82,12.04],[379.78,13.63],[376.57,15.16],[373.2,16.63],[369.68,18.04],[366.03,19.39],[362.26,20.69],[358.38,21.92],[354.4,23.1],[350.36,24.22],[346.25,25.28],[342.1,26.3],[337.93,27.26],[333.74,28.19],[329.57,29.07],[325.42,29.91],[321.31,30.73],[317.25,31.51],[313.26,32.28],[309.36,33.04],[305.55,33.78],[301.85,34.53],[298.27,35.27],[294.81,36.03],[291.48,36.81],[288.3,37.61],[285.26,38.44],[282.37,39.3],[279.63,40.21],[277.03,41.16],[274.59,42.16],[272.29,43.21],[270.14,44.33],[268.12,45.5],[266.23,46.74],[264.47,48.04],[262.82,49.42],[261.27,50.86],[259.82,52.37],[258.45,53.94],[257.14,55.58],[255.9,57.29],[254.7,59.06],[253.52,60.88],[252.37,62.76],[251.22,64.68],[250.06,66.65],[248.87,68.65],[247.65,70.69],[246.38,72.75],[245.05,74.83],[243.66,76.91],[242.18,79.0],[240.61,81.09],[238.95,83.16],[237.18,85.21],[235.29,87.23],[233.3,89.22],[231.18,91.17],[228.94,93.06],[226.57,94.9],[224.08,96.67],[221.47,98.37],[218.73,100.0],[215.86,101.56],[212.89,103.02],[209.79,104.41],[206.59,105.7],[203.29,106.9],[199.89,108.01],[196.39,109.03],[192.82,109.96],[189.17,110.79],[185.45,111.53],[181.67,112.19],[177.84,112.76],[173.97,113.25],[170.06,113.67],[166.12,114.01],[162.15,114.29],[158.17,114.5],[154.18,114.67],[150.18,114.78],[146.19,114.85],[142.19,114.88],[138.2,114.89],[134.23,114.88],[130.26,114.85],[126.3,114.81],[122.36,114.78],[118.43,114.74],[114.51,114.72],[110.6,114.71],[106.69,114.73],[102.8,114.77],[98.9,114.83],[95.0,114.93],[91.09,115.06],[87.18,115.23],[83.25,115.44],[79.3,115.68],[75.33,115.96],[71.33,116.27],[67.3,116.62],[63.24,117.0],[59.14,117.4],[55.0,117.83],[50.82,118.28],[46.59,118.74],[42.32,119.21],[38.01,119.68],[33.65,120.14],[29.25,120.59],[24.81,121.03],[20.34,121.43],[15.83,121.8],[11.3,122.13],[6.75,122.41],[2.18,122.63],[-2.4,122.79],[-6.97,122.87],[-11.54,122.87],[-16.08,122.79],[-20.6,122.62],[-25.07,122.35],[-29.5,121.97],[-33.86,121.49],[-38.16,120.91],[-42.37,120.2],[-46.49,119.39],[-50.5,118.45],[-54.4,117.4],[-58.18,116.23],[-61.83,114.95],[-65.34,113.55],[-68.69,112.03],[-71.9,110.41],[-74.94,108.69],[-77.82,106.86],[-80.53,104.94],[-83.06,102.93],[-85.43,100.83],[-87.62,98.66],[-89.64,96.42],[-91.49,94.12],[-93.18,91.77],[-94.71,89.36],[-96.08,86.93],[-97.31,84.46],[-98.4,81.97],[-99.36,79.47],[-100.2,76.97],[-100.94,74.47],[-101.59,71.98],[-102.15,69.51],[-102.64,67.06],[-103.09,64.64],[-103.49,62.27],[-103.87,59.93],[-104.24,57.64],[-104.61,55.41],[-105.0,53.23],[-105.42,51.11],[-105.88,49.04],[-106.41,47.04],[-107.0,45.1],[-107.67,43.23],[-108.43,41.41],[-109.29,39.66],[-110.25,37.97],[-111.32,36.33],[-112.52,34.75],[-113.83,33.22],[-115.27,31.74],[-116.82,30.3],[-118.51,28.9],[-120.31,27.53],[-122.23,26.19],[-124.26,24.88],[-126.39,23.59],[-128.63,22.32],[-130.95,21.05],[-133.35,19.79],[-135.82,18.53],[-138.35,17.26],[-140.92,15.99],[-143.52,14.7],[-146.14,13.39],[-148.76,12.07],[-151.37,10.72],[-153.95,9.35],[-156.49,7.94],[-158.98,6.51],[-161.39,5.05],[-163.73,3.55],[-165.97,2.02],[-168.1,0.46],[-170.11,-1.13],[-172.0,-2.76],[-173.75,-4.41],[-175.35,-6.09],[-176.8,-7.8],[-178.09,-9.54],[-179.22,-11.3],[-180.19,-13.07],[-181.0,-14.87],[-181.64,-16.68],[-182.12,-18.5],[-182.44,-20.33],[-182.6,-22.17],[-182.62,-24.01],[-182.5,-25.85],[-182.25,-27.69],[-181.88,-29.53],[-181.4,-31.36],[-180.82,-33.18],[-180.15,-35.0],[-179.41,-36.81],[-178.6,-38.6],[-177.76,-40.39],[-176.88,-42.17],[-175.98,-43.93],[-175.08,-45.69],[-174.19,-47.44],[-173.33,-49.19],[-172.5,-50.93],[-171.72,-52.66],[-171.0,-54.4],[-170.35,-56.14],[-169.79,-57.89],[-169.31,-59.64],[-168.93,-61.41],[-168.64,-63.19],[-168.47,-64.99],[-168.4,-66.81],[-168.44,-68.66],[-168.59,-70.53],[-168.84,-72.43],[-169.21,-74.37],[-169.67,-76.34],[-170.22,-78.35],[-170.86,-80.4],[-171.57,-82.49],[-172.36,-84.62],[-173.19,-86.79],[-174.07,-89.0],[-174.98,-91.25],[-175.9,-93.55],[-176.82,-95.88],[-177.73,-98.25],[-178.6,-100.65],[-179.43,-103.08],[-180.19,-105.53],[-180.88,-108.01],[-181.46,-110.51],[-181.94,-113.02],[-182.29,-115.53],[-182.49,-118.05],[-182.55,-120.56],[-182.43,-123.05],[-182.13,-125.53],[-181.65,-127.99],[-180.96,-130.41],[-180.07,-132.79],[-178.96,-135.12],[-177.63,-137.41],[-176.08,-139.63],[-174.29,-141.79],[-172.29,-143.88],[-170.05,-145.89],[-167.59,-147.81],[-164.9,-149.65],[-162.0,-151.4],[-158.89,-153.06],[-155.57,-154.61],[-152.06,-156.07],[-148.36,-157.42],[-144.49,-158.67],[-140.46,-159.81],[-136.28,-160.86],[-131.96,-161.79],[-127.51,-162.63],[-122.96,-163.37],[-118.31,-164.02],[-113.58,-164.57],[-108.79,-165.03],[-103.94,-165.42],[-99.06,-165.72],[-94.15,-165.96],[-89.23,-166.13],[-84.31,-166.24],[-79.41,-166.3],[-74.53,-166.32],[-69.69,-166.3],[-64.89,-166.25],[-60.14,-166.17],[-55.46,-166.09],[-50.84,-165.99],[-46.29,-165.9],[-41.82,-165.81],[-37.42,-165.73],[-33.11,-165.68],[-28.88,-165.64],[-24.73,-165.64],[-20.65,-165.67],[-16.66,-165.73],[-12.74,-165.84],[-8.89,-165.99],[-5.1,-166.18],[-1.38,-166.42],[2.29,-166.7],[5.9,-167.03],[9.48,-167.4],[13.01,-167.82],[16.52,-168.28],[20.0,-168.77],[23.47,-169.29],[26.92,-169.84],[30.37,-170.42],[33.82,-171.01],[37.27,-171.62],[40.74,-172.23],[44.21,-172.84],[47.71,-173.44],[51.23,-174.03],[54.76,-174.59],[58.33,-175.13],[61.91,-175.63],[65.52,-176.1],[69.15,-176.51],[72.8,-176.87],[76.48,-177.16],[80.16,-177.4],[83.87,-177.56],[87.57,-177.65],[91.29,-177.65],[95.0,-177.58],[98.71,-177.42],[102.4,-177.18],[106.08,-176.85],[109.74,-176.43],[113.36,-175.93],[116.96,-175.34],[120.51,-174.67],[124.02,-173.91],[127.49,-173.08],[130.9,-172.18],[134.26,-171.21],[137.56,-170.17],[140.8,-169.08],[143.98,-167.94],[147.1,-166.75],[150.15,-165.53],[153.15,-164.27],[156.09,-163.0],[158.97,-161.71],[161.8,-160.41],[164.59,-159.12],[167.33,-157.84],[170.04,-156.57],[172.72,-155.33],[175.38,-154.12],[178.03,-152.94],[180.67,-151.82],[183.32,-150.74],[185.98,-149.71],[188.67,-148.75],[191.39,-147.85],[194.15,-147.02],[196.96,-146.26],[199.84,-145.57],[202.79,-144.95],[205.81,-144.4],[208.92,-143.92],[212.13,-143.52],[215.44,-143.18],[218.85,-142.91],[222.38,-142.7],[226.02,-142.55],[229.77,-142.45],[233.64,-142.39],[237.64,-142.38],[241.75,-142.4],[245.97,-142.46],[250.3,-142.53],[254.75,-142.61],[259.29,-142.7],[263.92,-142.79],[268.64,-142.86],[273.44,-142.92],[278.3,-142.96],[283.21,-142.95],[288.16,-142.91],[293.14,-142.82],[298.13,-142.68],[303.12,-142.47],[308.09,-142.19],[313.04,-141.85],[317.94,-141.42],[322.77,-140.91],[327.53,-140.32],[332.2,-139.64],[336.76,-138.87],[341.2,-138.0],[345.5,-137.04],[349.66,-135.99],[353.67,-134.84],[357.5,-133.6],[361.16,-132.27],[364.63,-130.85],[367.9,-129.35],[370.98,-127.76],[373.86,-126.09],[376.53,-124.35],[378.99,-122.54],[381.24,-120.66],[383.29,-118.73],[385.13,-116.73],[386.78,-114.69],[388.23,-112.6],[389.49,-110.48],[390.58,-108.32],[391.5,-106.14],[392.26,-103.94],[392.88,-101.71],[393.36,-99.48],[393.72,-97.24],[393.96,-95.0],[394.12,-92.76],[394.19,-90.52],[394.2,-88.3],[394.15,-86.08],[394.06,-83.88],[393.95,-81.69],[393.82,-79.53],[393.7,-77.38],[393.59,-75.25],[393.49,-73.13],[393.43,-71.04],[393.42,-68.97],[393.44,-66.91],[393.53,-64.87],[393.67,-62.85],[393.88,-60.83],[394.15,-58.83],[394.49,-56.84],[394.89,-54.86],[395.35,-52.88],[395.88,-50.91],[396.46,-48.93],[397.08,-46.96],[397.75,-44.98],[398.45,-43.0],[399.17,-41.01],[399.9,-39.02],[400.64,-37.01],[401.35,-35.0]],[[403.6,-35.0],[404.23,-32.96],[404.83,-30.92],[405.39,-28.87],[405.88,-26.8],[406.31,-24.74],[406.64,-22.66],[406.88,-20.58],[407.0,-18.5],[406.99,-16.43],[406.84,-14.35],[406.53,-12.28],[406.07,-10.22],[405.43,-8.17],[404.61,-6.13],[403.6,-4.12],[402.39,-2.13],[400.99,-0.17],[399.38,1.76],[397.57,3.65],[395.55,5.51],[393.33,7.32],[390.91,9.09],[388.29,10.81],[385.49,12.48],[382.5,14.09],[379.34,15.65],[376.01,17.15],[372.53,18.59],[368.92,19.97],[365.17,21.29],[361.32,22.56],[357.37,23.76],[353.34,24.91],[349.25,26.0],[345.11,27.04],[340.94,28.04],[336.75,28.98],[332.57,29.89],[328.41,30.75],[324.28,31.59],[320.2,32.4],[316.19,33.18],[312.26,33.96],[308.42,34.72],[304.68,35.48],[301.06,36.24],[297.57,37.01],[294.2,37.8],[290.98,38.62],[287.9,39.46],[284.96,40.33],[282.18,41.25],[279.55,42.21],[277.07,43.22],[274.73,44.29],[272.54,45.42],[270.49,46.6],[268.58,47.86],[266.79,49.18],[265.11,50.57],[263.55,52.03],[262.08,53.56],[260.69,55.16],[259.38,56.83],[258.12,58.57],[256.92,60.37],[255.75,62.22],[254.59,64.14],[253.45,66.1],[252.29,68.12],[251.12,70.17],[249.91,72.25],[248.66,74.37],[247.34,76.5],[245.96,78.65],[244.5,80.8],[242.94,82.95],[241.29,85.09],[239.53,87.21],[237.66,89.3],[235.67,91.36],[233.56,93.37],[231.33,95.34],[228.96,97.25],[226.46,99.1],[223.84,100.88],[221.09,102.58],[218.21,104.21],[215.21,105.75],[212.09,107.2],[208.86,108.56],[205.52,109.83],[202.08,111.0],[198.54,112.08],[194.91,113.06],[191.21,113.94],[187.43,114.73],[183.58,115.43],[179.68,116.04],[175.73,116.57],[171.75,117.01],[167.72,117.37],[163.67,117.67],[159.61,117.89],[155.52,118.06],[151.44,118.17],[147.34,118.24],[143.26,118.26],[139.17,118.25],[135.1,118.22],[131.04,118.16],[126.99,118.09],[122.95,118.02],[118.93,117.94],[114.92,117.88],[110.92,117.82],[106.93,117.78],[102.95,117.77],[98.98,117.77],[95.0,117.81],[91.02,117.88],[87.04,117.99],[83.04,118.13],[79.03,118.31],[75.0,118.52],[70.94,118.77],[66.86,119.05],[62.75,119.36],[58.6,119.71],[54.41,120.07],[50.19,120.46],[45.92,120.87],[41.62,121.28],[37.27,121.7],[32.87,122.11],[28.44,122.52],[23.97,122.91],[19.46,123.27],[14.92,123.61],[10.36,123.9],[5.77,124.15],[1.17,124.34],[-3.44,124.47],[-8.05,124.53],[-12.64,124.52],[-17.23,124.42],[-21.78,124.23],[-26.29,123.95],[-30.76,123.56],[-35.17,123.08],[-39.5,122.48],[-43.76,121.77],[-47.92,120.95],[-51.98,120.01],[-55.93,118.96],[-59.76,117.78],[-63.45,116.49],[-67.0,115.09],[-70.41,113.57],[-73.66,111.95],[-76.75,110.21],[-79.67,108.38],[-82.42,106.45],[-85.0,104.42],[-87.4,102.32],[-89.63,100.13],[-91.68,97.87],[-93.56,95.55],[-95.28,93.18],[-96.83,90.75],[-98.22,88.29],[-99.46,85.8],[-100.56,83.28],[-101.53,80.75],[-102.38,78.21],[-103.11,75.68],[-103.75,73.16],[-104.31,70.65],[-104.79,68.17],[-105.21,65.71],[-105.59,63.3],[-105.95,60.92],[-106.29,58.6],[-106.63,56.32],[-106.99,54.11],[-107.38,51.95],[-107.81,49.85],[-108.29,47.81],[-108.85,45.84],[-109.49,43.93],[-110.21,42.08],[-111.04,40.3],[-111.98,38.58],[-113.03,36.92],[-114.2,35.31],[-115.5,33.76],[-116.92,32.26],[-118.47,30.8],[-120.15,29.39],[-121.96,28.01],[-123.9,26.67],[-125.95,25.35],[-128.11,24.05],[-130.38,22.77],[-132.75,21.5],[-135.21,20.23],[-137.74,18.97],[-140.34,17.71],[-142.99,16.43],[-145.68,15.15],[-148.4,13.85],[-151.12,12.52],[-153.84,11.18],[-156.55,9.81],[-159.21,8.41],[-161.83,6.98],[-164.39,5.52],[-166.87,4.02],[-169.26,2.49],[-171.54,0.93],[-173.71,-0.67],[-175.76,-2.3],[-177.66,-3.96],[-179.43,-5.66],[-181.04,-7.38],[-182.49,-9.13],[-183.78,-10.9],[-184.9,-12.7],[-185.86,-14.52],[-186.65,-16.35],[-187.27,-18.19],[-187.72,-20.05],[-188.02,-21.92],[-188.16,-23.79],[-188.16,-25.66],[-188.01,-27.54],[-187.74,-29.41],[-187.34,-31.28],[-186.84,-33.14],[-186.24,-35.0],[-185.55,-36.85],[-184.8,-38.69],[-183.99,-40.51],[-183.14,-42.33],[-182.26,-44.14],[-181.37,-45.94],[-180.48,-47.73],[-179.61,-49.52],[-178.76,-51.3],[-177.95,-53.08],[-177.2,-54.85],[-176.5,-56.63],[-175.89,-58.41],[-175.35,-60.2],[-174.9,-62.01],[-174.55,-63.82],[-174.3,-65.65],[-174.16,-67.51],[-174.12,-69.38],[-174.19,-71.28],[-174.36,-73.21],[-174.64,-75.18],[-175.01,-77.17],[-175.48,-79.21],[-176.03,-81.28],[-176.67,-83.39],[-177.37,-85.55],[-178.12,-87.74],[-178.93,-89.97],[-179.76,-92.25],[-180.61,-94.57],[-181.47,-96.92],[-182.31,-99.31],[-183.13,-101.73],[-183.9,-104.19],[-184.61,-106.67],[-185.24,-109.17],[-185.79,-111.69],[-186.22,-114.22],[-186.53,-116.76],[-186.71,-119.31],[-186.73,-121.84],[-186.58,-124.37],[-186.26,-126.88],[-185.75,-129.36],[-185.03,-131.81],[-184.12,-134.23],[-182.98,-136.6],[-181.63,-138.91],[-180.05,-141.17],[-178.24,-143.36],[-176.21,-145.47],[-173.94,-147.52],[-171.45,-149.47],[-168.73,-151.34],[-165.79,-153.12],[-162.63,-154.8],[-159.27,-156.38],[-155.71,-157.86],[-151.96,-159.23],[-148.03,-160.5],[-143.94,-161.66],[-139.69,-162.71],[-135.3,-163.66],[-130.78,-164.51],[-126.15,-165.25],[-121.42,-165.89],[-116.6,-166.44],[-111.71,-166.9],[-106.77,-167.27],[-101.79,-167.57],[-96.78,-167.78],[-91.76,-167.93],[-86.74,-168.02],[-81.73,-168.05],[-76.75,-168.04],[-71.8,-167.98],[-66.9,-167.9],[-62.04,-167.78],[-57.25,-167.65],[-52.53,-167.52],[-47.88,-167.37],[-43.31,-167.24],[-38.82,-167.11],[-34.41,-167.01],[-30.09,-166.92],[-25.85,-166.87],[-21.7,-166.85],[-17.62,-166.86],[-13.63,-166.92],[-9.71,-167.02],[-5.86,-167.17],[-2.08,-167.36],[1.65,-167.61],[5.32,-167.9],[8.94,-168.24],[12.52,-168.62],[16.06,-169.05],[19.58,-169.52],[23.07,-170.03],[26.56,-170.57],[30.03,-171.13],[33.5,-171.72],[36.97,-172.33],[40.45,-172.94],[43.95,-173.56],[47.46,-174.18],[50.99,-174.79],[54.54,-175.38],[58.11,-175.95],[61.71,-176.49],[65.33,-176.99],[68.98,-177.44],[72.65,-177.84],[76.34,-178.19],[80.05,-178.48],[83.78,-178.69],[87.51,-178.84],[91.26,-178.9],[95.0,-178.89],[98.74,-178.8],[102.48,-178.61],[106.2,-178.35],[109.9,-177.99],[113.57,-177.55],[117.22,-177.02],[120.83,-176.41],[124.4,-175.71],[127.93,-174.94],[131.4,-174.09],[134.83,-173.17],[138.19,-172.18],[141.5,-171.14],[144.75,-170.04],[147.94,-168.89],[151.07,-167.7],[154.14,-166.48],[157.16,-165.23],[160.11,-163.97],[163.02,-162.69],[165.88,-161.42],[168.69,-160.15],[171.47,-158.89],[174.22,-157.65],[176.95,-156.44],[179.67,-155.27],[182.37,-154.14],[185.08,-153.05],[187.81,-152.02],[190.55,-151.04],[193.33,-150.13],[196.15,-149.28],[199.02,-148.5],[201.95,-147.79],[204.95,-147.15],[208.02,-146.58],[211.19,-146.09],[214.44,-145.66],[217.8,-145.3],[221.26,-145.01],[224.83,-144.78],[228.52,-144.6],[232.33,-144.48],[236.25,-144.41],[240.29,-144.38],[244.46,-144.39],[248.74,-144.43],[253.13,-144.48],[257.64,-144.56],[262.24,-144.64],[266.94,-144.72],[271.73,-144.78],[276.6,-144.84],[281.54,-144.86],[286.53,-144.86],[291.56,-144.81],[296.63,-144.72],[301.71,-144.57],[306.79,-144.36],[311.86,-144.09],[316.9,-143.74],[321.9,-143.31],[326.84,-142.8],[331.7,-142.21],[336.47,-141.52],[341.14,-140.75],[345.68,-139.88],[350.09,-138.91],[354.36,-137.85],[358.46,-136.69],[362.39,-135.44],[366.14,-134.1],[369.7,-132.66],[373.07,-131.13],[376.23,-129.52],[379.18,-127.83],[381.92,-126.06],[384.44,-124.22],[386.75,-122.31],[388.85,-120.34],[390.73,-118.31],[392.41,-116.23],[393.88,-114.1],[395.16,-111.93],[396.25,-109.73],[397.17,-107.5],[397.91,-105.25],[398.5,-102.97],[398.94,-100.69],[399.25,-98.39],[399.45,-96.1],[399.53,-93.8],[399.53,-91.51],[399.46,-89.23],[399.32,-86.96],[399.13,-84.71],[398.91,-82.47],[398.67,-80.25],[398.43,-78.05],[398.19,-75.87],[397.97,-73.71],[397.78,-71.57],[397.62,-69.45],[397.52,-67.35],[397.46,-65.26],[397.47,-63.2],[397.53,-61.15],[397.67,-59.11],[397.87,-57.09],[398.14,-55.08],[398.48,-53.07],[398.88,-51.07],[399.34,-49.07],[399.85,-47.07],[400.41,-45.07],[401.01,-43.07],[401.64,-41.06],[402.29,-39.05],[402.95,-37.03],[403.6,-35.0]],[[405.73,-35.0],[406.31,-32.95],[406.85,-30.89],[407.37,-28.83],[407.83,-26.75],[408.23,-24.67],[408.55,-22.59],[408.77,-20.5],[408.89,-18.4],[408.89,-16.31],[408.76,-14.22],[408.48,-12.14],[408.04,-10.06],[407.44,-7.99],[406.66,-5.94],[405.7,-3.91],[404.54,-1.9],[403.19,0.08],[401.64,2.03],[399.88,3.95],[397.93,5.83],[395.77,7.67],[393.41,9.46],[390.85,11.21],[388.1,12.91],[385.17,14.55],[382.06,16.14],[378.79,17.66],[375.36,19.14],[371.79,20.55],[368.08,21.9],[364.27,23.19],[360.35,24.43],[356.34,25.61],[352.27,26.73],[348.14,27.8],[343.98,28.82],[339.8,29.79],[335.61,30.72],[331.45,31.61],[327.31,32.47],[323.21,33.3],[319.18,34.11],[315.23,34.9],[311.36,35.68],[307.6,36.46],[303.94,37.24],[300.41,38.02],[297.01,38.83],[293.74,39.65],[290.62,40.51],[287.65,41.4],[284.83,42.33],[282.16,43.3],[279.64,44.33],[277.27,45.41],[275.04,46.55],[272.96,47.75],[271.01,49.02],[269.19,50.36],[267.49,51.77],[265.9,53.25],[264.41,54.8],[263.01,56.43],[261.68,58.12],[260.42,59.89],[259.21,61.72],[258.03,63.61],[256.88,65.56],[255.74,67.57],[254.59,69.62],[253.42,71.72],[252.22,73.85],[250.98,76.02],[249.67,78.21],[248.3,80.41],[246.85,82.62],[245.31,84.84],[243.67,87.04],[241.92,89.23],[240.06,91.39],[238.08,93.52],[235.97,95.6],[233.73,97.64],[231.37,99.63],[228.87,101.55],[226.24,103.4],[223.47,105.18],[220.58,106.88],[217.55,108.49],[214.41,110.01],[211.14,111.44],[207.76,112.77],[204.28,114.01],[200.7,115.14],[197.02,116.18],[193.25,117.11],[189.41,117.95],[185.5,118.69],[181.53,119.34],[177.51,119.9],[173.44,120.37],[169.34,120.75],[165.2,121.06],[161.04,121.3],[156.87,121.47],[152.69,121.58],[148.51,121.64],[144.32,121.65],[140.15,121.63],[135.98,121.57],[131.82,121.49],[127.68,121.38],[123.55,121.27],[119.43,121.16],[115.33,121.04],[111.25,120.94],[107.17,120.84],[103.11,120.77],[99.05,120.72],[95.0,120.69],[90.95,120.7],[86.89,120.74],[82.83,120.81],[78.76,120.92],[74.66,121.07],[70.55,121.25],[66.42,121.46],[62.26,121.71],[58.06,121.99],[53.83,122.29],[49.57,122.62],[45.26,122.96],[40.92,123.32],[36.54,123.68],[32.11,124.04],[27.65,124.4],[23.14,124.74],[18.61,125.06],[14.04,125.36],[9.45,125.61],[4.83,125.83],[0.2,125.99],[-4.44,126.09],[-9.08,126.13],[-13.71,126.1],[-18.32,125.98],[-22.91,125.78],[-27.46,125.48],[-31.97,125.09],[-36.41,124.59],[-40.79,123.99],[-45.09,123.27],[-49.29,122.45],[-53.4,121.51],[-57.39,120.45],[-61.27,119.27],[-65.01,117.98],[-68.61,116.58],[-72.06,115.06],[-75.35,113.42],[-78.49,111.69],[-81.45,109.85],[-84.25,107.91],[-86.87,105.88],[-89.31,103.76],[-91.58,101.56],[-93.67,99.29],[-95.58,96.95],[-97.33,94.56],[-98.9,92.12],[-100.32,89.63],[-101.58,87.11],[-102.7,84.57],[-103.67,82.01],[-104.53,79.45],[-105.27,76.88],[-105.9,74.33],[-106.45,71.79],[-106.92,69.27],[-107.33,66.78],[-107.7,64.33],[-108.03,61.92],[-108.35,59.56],[-108.66,57.25],[-108.99,54.99],[-109.35,52.8],[-109.75,50.66],[-110.21,48.59],[-110.73,46.58],[-111.34,44.64],[-112.03,42.77],[-112.83,40.96],[-113.74,39.21],[-114.77,37.52],[-115.92,35.89],[-117.2,34.32],[-118.62,32.8],[-120.17,31.33],[-121.85,29.9],[-123.66,28.51],[-125.61,27.15],[-127.68,25.82],[-129.88,24.52],[-132.19,23.23],[-134.6,21.96],[-137.11,20.69],[-139.71,19.43],[-142.38,18.16],[-145.11,16.89],[-147.89,15.61],[-150.7,14.31],[-153.53,12.99],[-156.37,11.65],[-159.19,10.28],[-161.98,8.88],[-164.74,7.45],[-167.44,5.99],[-170.06,4.5],[-172.6,2.96],[-175.04,1.4],[-177.37,-0.2],[-179.57,-1.84],[-181.64,-3.51],[-183.57,-5.22],[-185.34,-6.95],[-186.95,-8.71],[-188.4,-10.5],[-189.68,-12.32],[-190.79,-14.16],[-191.73,-16.01],[-192.5,-17.88],[-193.09,-19.77],[-193.52,-21.66],[-193.79,-23.57],[-193.9,-25.47],[-193.86,-27.38],[-193.69,-29.29],[-193.38,-31.2],[-192.96,-33.1],[-192.43,-35.0],[-191.81,-36.89],[-191.11,-38.77],[-190.34,-40.64],[-189.52,-42.5],[-188.66,-44.35],[-187.77,-46.19],[-186.88,-48.03],[-186.0,-49.86],[-185.13,-51.68],[-184.29,-53.5],[-183.5,-55.31],[-182.76,-57.13],[-182.09,-58.95],[-181.49,-60.78],[-180.98,-62.61],[-180.55,-64.46],[-180.23,-66.33],[-180.0,-68.21],[-179.88,-70.12],[-179.86,-72.05],[-179.94,-74.01],[-180.13,-76.0],[-180.41,-78.02],[-180.79,-80.08],[-181.25,-82.17],[-181.79,-84.31],[-182.41,-86.48],[-183.08,-88.7],[-183.8,-90.95],[-184.55,-93.25],[-185.32,-95.58],[-186.11,-97.96],[-186.88,-100.37],[-187.63,-102.81],[-188.34,-105.29],[-188.99,-107.79],[-189.57,-110.31],[-190.06,-112.86],[-190.45,-115.41],[-190.72,-117.98],[-190.85,-120.55],[-190.84,-123.11],[-190.66,-125.66],[-190.3,-128.2],[-189.76,-130.71],[-189.02,-133.19],[-188.08,-135.64],[-186.92,-138.03],[-185.54,-140.38],[-183.93,-142.67],[-182.1,-144.89],[-180.03,-147.03],[-177.74,-149.1],[-175.21,-151.09],[-172.46,-152.99],[-169.48,-154.79],[-166.29,-156.5],[-162.88,-158.1],[-159.28,-159.6],[-155.48,-161.0],[-151.49,-162.28],[-147.34,-163.46],[-143.03,-164.53],[-138.57,-165.49],[-133.98,-166.34],[-129.27,-167.09],[-124.46,-167.73],[-119.56,-168.28],[-114.58,-168.73],[-109.55,-169.1],[-104.48,-169.38],[-99.37,-169.58],[-94.25,-169.71],[-89.13,-169.77],[-84.02,-169.77],[-78.93,-169.73],[-73.88,-169.64],[-68.87,-169.52],[-63.92,-169.37],[-59.02,-169.2],[-54.2,-169.01],[-49.45,-168.83],[-44.78,-168.64],[-40.19,-168.47],[-35.69,-168.31],[-31.28,-168.18],[-26.96,-168.08],[-22.72,-168.0],[-18.57,-167.97],[-14.5,-167.98],[-10.51,-168.04],[-6.6,-168.14],[-2.76,-168.29],[1.02,-168.5],[4.74,-168.75],[8.41,-169.06],[12.03,-169.41],[15.61,-169.81],[19.17,-170.26],[22.69,-170.75],[26.2,-171.27],[29.7,-171.83],[33.19,-172.42],[36.68,-173.02],[40.18,-173.64],[43.68,-174.28],[47.21,-174.91],[50.75,-175.54],[54.31,-176.15],[57.9,-176.75],[61.51,-177.32],[65.15,-177.86],[68.81,-178.36],[72.5,-178.81],[76.21,-179.21],[79.94,-179.55],[83.69,-179.82],[87.45,-180.02],[91.22,-180.15],[95.0,-180.2],[98.78,-180.17],[102.55,-180.05],[106.31,-179.85],[110.06,-179.56],[113.79,-179.18],[117.49,-178.72],[121.15,-178.17],[124.78,-177.54],[128.37,-176.82],[131.91,-176.03],[135.4,-175.17],[138.84,-174.23],[142.22,-173.23],[145.54,-172.18],[148.81,-171.07],[152.01,-169.92],[155.16,-168.74],[158.25,-167.52],[161.28,-166.28],[164.26,-165.03],[167.2,-163.77],[170.09,-162.51],[172.94,-161.27],[175.76,-160.04],[178.56,-158.83],[181.35,-157.66],[184.12,-156.52],[186.9,-155.43],[189.69,-154.39],[192.5,-153.4],[195.33,-152.47],[198.21,-151.61],[201.13,-150.81],[204.12,-150.08],[207.17,-149.42],[210.3,-148.83],[213.51,-148.31],[216.81,-147.86],[220.22,-147.48],[223.73,-147.16],[227.35,-146.9],[231.09,-146.71],[234.94,-146.57],[238.91,-146.48],[243.01,-146.43],[247.23,-146.42],[251.56,-146.43],[256.01,-146.48],[260.57,-146.53],[265.24,-146.6],[270.0,-146.67],[274.86,-146.73],[279.8,-146.77],[284.8,-146.79],[289.87,-146.78],[294.99,-146.73],[300.13,-146.63],[305.3,-146.48],[310.47,-146.26],[315.63,-145.99],[320.77,-145.63],[325.86,-145.2],[330.9,-144.69],[335.86,-144.09],[340.73,-143.4],[345.5,-142.62],[350.14,-141.74],[354.66,-140.77],[359.02,-139.7],[363.22,-138.53],[367.25,-137.26],[371.09,-135.9],[374.74,-134.45],[378.19,-132.91],[381.43,-131.27],[384.46,-129.56],[387.27,-127.76],[389.86,-125.89],[392.22,-123.95],[394.36,-121.94],[396.29,-119.88],[397.99,-117.75],[399.49,-115.59],[400.78,-113.37],[401.88,-111.13],[402.78,-108.85],[403.51,-106.54],[404.07,-104.22],[404.48,-101.88],[404.75,-99.54],[404.88,-97.19],[404.91,-94.84],[404.83,-92.5],[404.67,-90.16],[404.44,-87.84],[404.15,-85.53],[403.83,-83.24],[403.47,-80.96],[403.11,-78.71],[402.75,-76.48],[402.39,-74.27],[402.07,-72.08],[401.78,-69.92],[401.53,-67.77],[401.33,-65.65],[401.2,-63.55],[401.12,-61.46],[401.12,-59.39],[401.18,-57.33],[401.32,-55.29],[401.52,-53.25],[401.8,-51.22],[402.14,-49.2],[402.53,-47.18],[402.99,-45.15],[403.48,-43.13],[404.02,-41.11],[404.58,-39.08],[405.15,-37.04],[405.73,-35.0]],[[407.77,-35.0],[408.28,-32.94],[408.78,-30.87],[409.24,-28.79],[409.67,-26.7],[410.04,-24.61],[410.35,-22.52],[410.57,-20.41],[410.69,-18.31],[410.69,-16.2],[410.58,-14.1],[410.32,-12.0],[409.92,-9.91],[409.35,-7.83],[408.62,-5.76],[407.7,-3.71],[406.6,-1.68],[405.31,0.32],[403.82,2.29],[402.13,4.24],[400.23,6.14],[398.14,8.01],[395.85,9.83],[393.36,11.6],[390.67,13.33],[387.81,15.0],[384.76,16.62],[381.54,18.18],[378.17,19.68],[374.65,21.12],[370.99,22.51],[367.21,23.83],[363.33,25.1],[359.36,26.31],[355.31,27.46],[351.21,28.56],[347.06,29.61],[342.89,30.61],[338.71,31.56],[334.54,32.48],[330.4,33.37],[326.3,34.22],[322.25,35.05],[318.27,35.86],[314.38,36.67],[310.59,37.46],[306.91,38.26],[303.34,39.07],[299.91,39.89],[296.61,40.73],[293.45,41.6],[290.43,42.5],[287.57,43.44],[284.86,44.43],[282.3,45.47],[279.89,46.57],[277.63,47.72],[275.52,48.94],[273.53,50.22],[271.68,51.58],[269.96,53.01],[268.34,54.51],[266.83,56.08],[265.41,57.73],[264.07,59.45],[262.79,61.25],[261.57,63.11],[260.39,65.03],[259.23,67.02],[258.09,69.06],[256.94,71.16],[255.77,73.3],[254.58,75.49],[253.34,77.7],[252.05,79.95],[250.69,82.21],[249.24,84.48],[247.71,86.75],[246.08,89.02],[244.34,91.27],[242.48,93.5],[240.51,95.7],[238.4,97.86],[236.17,99.97],[233.8,102.03],[231.29,104.02],[228.65,105.95],[225.87,107.8],[222.95,109.57],[219.91,111.25],[216.73,112.84],[213.44,114.33],[210.02,115.73],[206.49,117.03],[202.86,118.22],[199.13,119.31],[195.31,120.3],[191.41,121.18],[187.43,121.97],[183.39,122.65],[179.29,123.24],[175.14,123.74],[170.95,124.15],[166.73,124.47],[162.49,124.72],[158.23,124.9],[153.95,125.01],[149.68,125.06],[145.4,125.06],[141.12,125.02],[136.86,124.93],[132.6,124.82],[128.37,124.69],[124.14,124.54],[119.94,124.38],[115.75,124.21],[111.57,124.06],[107.41,123.91],[103.27,123.77],[99.13,123.66],[95.0,123.57],[90.87,123.51],[86.75,123.48],[82.62,123.49],[78.48,123.53],[74.33,123.6],[70.17,123.71],[65.98,123.86],[61.77,124.03],[57.53,124.24],[53.26,124.48],[48.96,124.74],[44.62,125.02],[40.24,125.31],[35.82,125.62],[31.37,125.93],[26.87,126.23],[22.34,126.52],[17.78,126.8],[13.18,127.05],[8.56,127.27],[3.92,127.45],[-0.74,127.58],[-5.4,127.66],[-10.07,127.67],[-14.73,127.61],[-19.38,127.48],[-24.0,127.26],[-28.58,126.95],[-33.12,126.54],[-37.61,126.04],[-42.02,125.43],[-46.36,124.71],[-50.61,123.88],[-54.76,122.94],[-58.79,121.88],[-62.71,120.7],[-66.5,119.41],[-70.14,118.0],[-73.64,116.48],[-76.99,114.85],[-80.17,113.11],[-83.18,111.26],[-86.02,109.32],[-88.69,107.28],[-91.17,105.16],[-93.48,102.95],[-95.61,100.67],[-97.56,98.32],[-99.33,95.91],[-100.94,93.45],[-102.38,90.95],[-103.66,88.41],[-104.8,85.84],[-105.79,83.26],[-106.65,80.67],[-107.4,78.08],[-108.04,75.49],[-108.58,72.92],[-109.05,70.37],[-109.45,67.85],[-109.81,65.36],[-110.12,62.92],[-110.42,60.52],[-110.71,58.17],[-111.02,55.88],[-111.35,53.65],[-111.72,51.49],[-112.15,49.38],[-112.65,47.34],[-113.22,45.37],[-113.89,43.47],[-114.67,41.63],[-115.55,39.85],[-116.56,38.14],[-117.69,36.49],[-118.96,34.9],[-120.37,33.35],[-121.91,31.86],[-123.59,30.42],[-125.42,29.01],[-127.38,27.65],[-129.48,26.31],[-131.7,25.0],[-134.05,23.71],[-136.51,22.43],[-139.07,21.16],[-141.73,19.9],[-144.47,18.63],[-147.28,17.36],[-150.15,16.08],[-153.06,14.78],[-155.99,13.47],[-158.94,12.13],[-161.88,10.76],[-164.81,9.36],[-167.7,7.94],[-170.53,6.48],[-173.31,4.98],[-176.0,3.45],[-178.59,1.88],[-181.08,0.27],[-183.44,-1.37],[-185.68,-3.05],[-187.77,-4.77],[-189.7,-6.51],[-191.48,-8.29],[-193.1,-10.1],[-194.54,-11.93],[-195.8,-13.79],[-196.89,-15.67],[-197.8,-17.57],[-198.54,-19.48],[-199.11,-21.41],[-199.5,-23.34],[-199.73,-25.28],[-199.81,-27.23],[-199.73,-29.17],[-199.52,-31.12],[-199.18,-33.06],[-198.73,-35.0],[-198.17,-36.93],[-197.52,-38.85],[-196.79,-40.77],[-196.0,-42.67],[-195.16,-44.57],[-194.28,-46.45],[-193.39,-48.33],[-192.49,-50.2],[-191.6,-52.06],[-190.73,-53.92],[-189.9,-55.78],[-189.12,-57.64],[-188.39,-59.49],[-187.73,-61.36],[-187.14,-63.23],[-186.65,-65.11],[-186.24,-67.01],[-185.92,-68.93],[-185.71,-70.86],[-185.6,-72.82],[-185.59,-74.81],[-185.68,-76.82],[-185.86,-78.87],[-186.14,-80.95],[-186.51,-83.07],[-186.95,-85.23],[-187.47,-87.42],[-188.05,-89.66],[-188.68,-91.93],[-189.34,-94.25],[-190.03,-96.6],[-190.73,-98.99],[-191.43,-101.42],[-192.1,-103.89],[-192.75,-106.38],[-193.33,-108.9],[-193.85,-111.45],[-194.29,-114.01],[-194.63,-116.59],[-194.85,-119.18],[-194.93,-121.77],[-194.88,-124.36],[-194.66,-126.93],[-194.27,-129.5],[-193.7,-132.03],[-192.93,-134.54],[-191.95,-137.01],[-190.76,-139.44],[-189.36,-141.81],[-187.72,-144.13],[-185.86,-146.38],[-183.77,-148.55],[-181.44,-150.65],[-178.88,-152.67],[-176.1,-154.59],[-173.08,-156.42],[-169.85,-158.16],[-166.4,-159.78],[-162.75,-161.31],[-158.9,-162.72],[-154.87,-164.03],[-150.66,-165.22],[-146.28,-166.3],[-141.76,-167.27],[-137.1,-168.13],[-132.32,-168.88],[-127.43,-169.53],[-122.45,-170.08],[-117.39,-170.53],[-112.27,-170.88],[-107.11,-171.15],[-101.91,-171.33],[-96.7,-171.44],[-91.48,-171.49],[-86.27,-171.47],[-81.08,-171.39],[-75.93,-171.27],[-70.82,-171.11],[-65.76,-170.92],[-60.77,-170.71],[-55.84,-170.49],[-50.99,-170.26],[-46.23,-170.03],[-41.55,-169.81],[-36.96,-169.6],[-32.46,-169.42],[-28.05,-169.27],[-23.73,-169.15],[-19.5,-169.06],[-15.36,-169.03],[-11.31,-169.04],[-7.33,-169.09],[-3.43,-169.2],[0.41,-169.37],[4.18,-169.59],[7.89,-169.86],[11.56,-170.18],[15.18,-170.56],[18.76,-170.98],[22.32,-171.45],[25.85,-171.96],[29.37,-172.51],[32.88,-173.09],[36.39,-173.7],[39.91,-174.33],[43.43,-174.97],[46.96,-175.62],[50.52,-176.27],[54.09,-176.92],[57.69,-177.54],[61.32,-178.15],[64.97,-178.73],[68.65,-179.27],[72.35,-179.77],[76.08,-180.22],[79.83,-180.61],[83.6,-180.94],[87.39,-181.21],[91.19,-181.4],[95.0,-181.51],[98.81,-181.55],[102.63,-181.5],[106.43,-181.36],[110.23,-181.14],[114.0,-180.83],[117.75,-180.44],[121.48,-179.95],[125.17,-179.38],[128.82,-178.73],[132.43,-178.0],[135.99,-177.19],[139.49,-176.31],[142.95,-175.37],[146.35,-174.36],[149.69,-173.3],[152.97,-172.19],[156.19,-171.04],[159.36,-169.86],[162.48,-168.65],[165.54,-167.42],[168.55,-166.18],[171.52,-164.94],[174.45,-163.71],[177.35,-162.49],[180.22,-161.29],[183.08,-160.11],[185.92,-158.97],[188.77,-157.88],[191.62,-156.83],[194.49,-155.83],[197.39,-154.88],[200.33,-154.0],[203.31,-153.18],[206.35,-152.43],[209.45,-151.75],[212.63,-151.13],[215.9,-150.59],[219.25,-150.12],[222.7,-149.71],[226.26,-149.37],[229.93,-149.09],[233.71,-148.87],[237.61,-148.7],[241.64,-148.58],[245.78,-148.51],[250.05,-148.48],[254.43,-148.48],[258.93,-148.5],[263.55,-148.54],[268.27,-148.59],[273.1,-148.64],[278.02,-148.69],[283.02,-148.72],[288.1,-148.73],[293.24,-148.71],[298.43,-148.65],[303.65,-148.54],[308.9,-148.39],[314.16,-148.17],[319.41,-147.88],[324.63,-147.53],[329.82,-147.09],[334.95,-146.57],[340.0,-145.97],[344.97,-145.27],[349.84,-144.48],[354.58,-143.6],[359.19,-142.62],[363.65,-141.53],[367.94,-140.35],[372.07,-139.07],[376.0,-137.7],[379.74,-136.23],[383.27,-134.66],[386.59,-133.01],[389.69,-131.27],[392.57,-129.44],[395.22,-127.54],[397.64,-125.57],[399.83,-123.53],[401.79,-121.43],[403.53,-119.27],[405.05,-117.06],[406.35,-114.8],[407.45,-112.51],[408.35,-110.18],[409.06,-107.83],[409.6,-105.46],[409.97,-103.07],[410.19,-100.67],[410.27,-98.27],[410.22,-95.87],[410.07,-93.47],[409.83,-91.08],[409.51,-88.7],[409.12,-86.34],[408.69,-84.0],[408.22,-81.67],[407.73,-79.37],[407.24,-77.09],[406.76,-74.83],[406.3,-72.59],[405.87,-70.38],[405.48,-68.2],[405.14,-66.03],[404.86,-63.89],[404.64,-61.76],[404.5,-59.66],[404.42,-57.57],[404.42,-55.49],[404.49,-53.43],[404.64,-51.37],[404.85,-49.32],[405.13,-47.28],[405.47,-45.24],[405.86,-43.2],[406.3,-41.15],[406.77,-39.11],[407.26,-37.06],[407.77,-35.0]],[[409.71,-35.0],[410.16,-32.92],[410.6,-30.84],[411.02,-28.75],[411.41,-26.66],[411.76,-24.56],[412.04,-22.45],[412.25,-20.34],[412.37,-18.22],[412.39,-16.1],[412.29,-13.99],[412.07,-11.87],[411.7,-9.77],[411.17,-7.67],[410.48,-5.59],[409.62,-3.52],[408.58,-1.47],[407.35,0.55],[405.92,2.55],[404.3,4.51],[402.48,6.44],[400.45,8.33],[398.23,10.18],[395.81,11.99],[393.2,13.74],[390.4,15.44],[387.43,17.09],[384.28,18.68],[380.96,20.22],[377.5,21.69],[373.9,23.11],[370.17,24.47],[366.33,25.77],[362.4,27.01],[358.39,28.2],[354.31,29.33],[350.19,30.41],[346.03,31.44],[341.86,32.42],[337.7,33.37],[333.56,34.28],[329.45,35.16],[325.39,36.02],[321.4,36.86],[317.49,37.68],[313.67,38.5],[309.96,39.32],[306.37,40.14],[302.9,40.98],[299.56,41.84],[296.37,42.73],[293.32,43.64],[290.42,44.6],[287.67,45.61],[285.07,46.66],[282.62,47.77],[280.32,48.94],[278.17,50.17],[276.15,51.47],[274.27,52.85],[272.51,54.29],[270.87,55.82],[269.33,57.41],[267.89,59.08],[266.53,60.83],[265.24,62.65],[264.0,64.54],[262.81,66.5],[261.65,68.52],[260.5,70.6],[259.35,72.74],[258.18,74.93],[256.99,77.16],[255.76,79.42],[254.47,81.72],[253.11,84.03],[251.67,86.36],[250.15,88.69],[248.52,91.02],[246.79,93.34],[244.94,95.64],[242.96,97.9],[240.86,100.13],[238.62,102.31],[236.24,104.44],[233.73,106.51],[231.07,108.51],[228.28,110.43],[225.35,112.27],[222.28,114.02],[219.07,115.68],[215.74,117.24],[212.29,118.7],[208.72,120.06],[205.04,121.31],[201.25,122.46],[197.37,123.49],[193.41,124.43],[189.37,125.25],[185.25,125.97],[181.08,126.6],[176.85,127.12],[172.58,127.55],[168.27,127.89],[163.94,128.15],[159.59,128.33],[155.22,128.44],[150.85,128.49],[146.47,128.48],[142.1,128.41],[137.74,128.31],[133.39,128.17],[129.06,128.0],[124.74,127.81],[120.44,127.6],[116.16,127.39],[111.9,127.18],[107.65,126.97],[103.42,126.78],[99.21,126.6],[95.0,126.45],[90.8,126.32],[86.61,126.22],[82.41,126.15],[78.21,126.12],[74.01,126.12],[69.79,126.15],[65.55,126.23],[61.29,126.33],[57.01,126.47],[52.7,126.63],[48.36,126.83],[43.98,127.04],[39.57,127.27],[35.12,127.52],[30.64,127.77],[26.12,128.02],[21.56,128.26],[16.97,128.49],[12.35,128.69],[7.71,128.87],[3.04,129.01],[-1.64,129.11],[-6.33,129.16],[-11.02,129.14],[-15.71,129.06],[-20.39,128.91],[-25.04,128.67],[-29.65,128.35],[-34.22,127.93],[-38.74,127.42],[-43.19,126.8],[-47.57,126.08],[-51.86,125.25],[-56.05,124.3],[-60.13,123.24],[-64.09,122.07],[-67.93,120.77],[-71.62,119.37],[-75.17,117.85],[-78.56,116.22],[-81.79,114.48],[-84.85,112.63],[-87.73,110.69],[-90.45,108.65],[-92.98,106.52],[-95.33,104.3],[-97.49,102.01],[-99.48,99.65],[-101.3,97.23],[-102.93,94.76],[-104.4,92.24],[-105.71,89.68],[-106.87,87.1],[-107.88,84.49],[-108.76,81.88],[-109.52,79.26],[-110.16,76.65],[-110.71,74.05],[-111.18,71.47],[-111.58,68.91],[-111.92,66.4],[-112.22,63.92],[-112.51,61.49],[-112.78,59.11],[-113.07,56.79],[-113.38,54.53],[-113.73,52.32],[-114.13,50.19],[-114.6,48.12],[-115.15,46.12],[-115.8,44.18],[-116.55,42.32],[-117.41,40.51],[-118.4,38.78],[-119.52,37.1],[-120.77,35.49],[-122.17,33.93],[-123.71,32.42],[-125.4,30.96],[-127.23,29.54],[-129.21,28.16],[-131.33,26.81],[-133.58,25.5],[-135.96,24.2],[-138.47,22.92],[-141.09,21.65],[-143.81,20.38],[-146.62,19.11],[-149.51,17.84],[-152.46,16.56],[-155.47,15.27],[-158.51,13.95],[-161.57,12.61],[-164.64,11.25],[-167.69,9.86],[-170.71,8.43],[-173.69,6.97],[-176.61,5.47],[-179.45,3.94],[-182.2,2.36],[-184.85,0.75],[-187.38,-0.9],[-189.77,-2.59],[-192.03,-4.31],[-194.13,-6.07],[-196.08,-7.86],[-197.85,-9.69],[-199.46,-11.54],[-200.88,-13.42],[-202.13,-15.32],[-203.19,-17.25],[-204.07,-19.19],[-204.77,-21.14],[-205.3,-23.11],[-205.65,-25.09],[-205.84,-27.07],[-205.87,-29.05],[-205.75,-31.04],[-205.5,-33.02],[-205.12,-35.0],[-204.62,-36.97],[-204.03,-38.94],[-203.34,-40.9],[-202.58,-42.85],[-201.76,-44.78],[-200.9,-46.71],[-200.0,-48.64],[-199.09,-50.55],[-198.18,-52.46],[-197.28,-54.36],[-196.4,-56.25],[-195.57,-58.15],[-194.78,-60.05],[-194.06,-61.95],[-193.4,-63.86],[-192.82,-65.77],[-192.33,-67.7],[-191.92,-69.65],[-191.62,-71.62],[-191.41,-73.6],[-191.3,-75.62],[-191.28,-77.66],[-191.36,-79.73],[-191.54,-81.83],[-191.8,-83.97],[-192.14,-86.15],[-192.56,-88.36],[-193.03,-90.62],[-193.56,-92.91],[-194.13,-95.24],[-194.73,-97.62],[-195.34,-100.03],[-195.96,-102.47],[-196.55,-104.95],[-197.12,-107.46],[-197.64,-110.0],[-198.09,-112.57],[-198.46,-115.15],[-198.74,-117.75],[-198.91,-120.36],[-198.94,-122.97],[-198.84,-125.58],[-198.58,-128.18],[-198.15,-130.76],[-197.54,-133.33],[-196.74,-135.86],[-195.73,-138.36],[-194.51,-140.81],[-193.07,-143.21],[-191.41,-145.55],[-189.52,-147.83],[-187.4,-150.03],[-185.04,-152.16],[-182.45,-154.2],[-179.63,-156.15],[-176.59,-158.01],[-173.32,-159.77],[-169.83,-161.42],[-166.14,-162.96],[-162.24,-164.4],[-158.15,-165.72],[-153.89,-166.93],[-149.46,-168.03],[-144.87,-169.01],[-140.15,-169.88],[-135.3,-170.64],[-130.34,-171.29],[-125.28,-171.84],[-120.14,-172.28],[-114.94,-172.63],[-109.69,-172.89],[-104.4,-173.06],[-99.09,-173.15],[-93.78,-173.17],[-88.47,-173.13],[-83.19,-173.02],[-77.94,-172.87],[-72.73,-172.68],[-67.57,-172.46],[-62.48,-172.21],[-57.46,-171.94],[-52.52,-171.67],[-47.66,-171.39],[-42.89,-171.13],[-38.21,-170.88],[-33.62,-170.64],[-29.13,-170.44],[-24.73,-170.27],[-20.43,-170.14],[-16.21,-170.06],[-12.09,-170.02],[-8.05,-170.04],[-4.09,-170.11],[-0.2,-170.23],[3.62,-170.41],[7.38,-170.65],[11.09,-170.94],[14.74,-171.29],[18.36,-171.69],[21.95,-172.15],[25.51,-172.64],[29.05,-173.18],[32.58,-173.76],[36.11,-174.37],[39.64,-175.01],[43.17,-175.66],[46.72,-176.33],[50.29,-177.0],[53.88,-177.67],[57.49,-178.33],[61.13,-178.97],[64.79,-179.59],[68.48,-180.18],[72.2,-180.73],[75.95,-181.23],[79.72,-181.68],[83.51,-182.07],[87.33,-182.39],[91.16,-182.65],[95.0,-182.83],[98.85,-182.93],[102.7,-182.95],[106.55,-182.89],[110.39,-182.74],[114.22,-182.5],[118.03,-182.17],[121.81,-181.76],[125.56,-181.25],[129.27,-180.67],[132.95,-180.0],[136.58,-179.25],[140.16,-178.43],[143.69,-177.54],[147.17,-176.58],[150.59,-175.57],[153.95,-174.51],[157.25,-173.4],[160.5,-172.25],[163.7,-171.07],[166.84,-169.87],[169.93,-168.65],[172.98,-167.43],[175.99,-166.21],[178.97,-165.0],[181.92,-163.8],[184.85,-162.63],[187.77,-161.49],[190.69,-160.39],[193.61,-159.33],[196.54,-158.32],[199.51,-157.36],[202.5,-156.46],[205.55,-155.62],[208.64,-154.85],[211.8,-154.14],[215.04,-153.51],[218.35,-152.93],[221.75,-152.43],[225.25,-152.0],[228.86,-151.63],[232.57,-151.32],[236.4,-151.07],[240.35,-150.88],[244.42,-150.74],[248.61,-150.64],[252.92,-150.58],[257.35,-150.56],[261.91,-150.56],[266.57,-150.58],[271.35,-150.61],[276.23,-150.64],[281.21,-150.67],[286.28,-150.69],[291.42,-150.69],[296.63,-150.65],[301.89,-150.58],[307.18,-150.47],[312.51,-150.3],[317.85,-150.07],[323.18,-149.78],[328.49,-149.42],[333.76,-148.97],[338.98,-148.45],[344.13,-147.84],[349.19,-147.13],[354.14,-146.34],[358.98,-145.44],[363.69,-144.45],[368.24,-143.35],[372.63,-142.16],[376.84,-140.87],[380.86,-139.48],[384.69,-137.99],[388.3,-136.4],[391.7,-134.72],[394.87,-132.96],[397.81,-131.11],[400.52,-129.18],[402.99,-127.17],[405.23,-125.1],[407.23,-122.96],[409.0,-120.76],[410.54,-118.51],[411.86,-116.21],[412.96,-113.88],[413.85,-111.5],[414.55,-109.1],[415.06,-106.68],[415.39,-104.24],[415.57,-101.79],[415.59,-99.34],[415.49,-96.88],[415.26,-94.43],[414.93,-91.99],[414.52,-89.56],[414.03,-87.14],[413.49,-84.75],[412.91,-82.37],[412.3,-80.02],[411.68,-77.68],[411.07,-75.38],[410.47,-73.1],[409.9,-70.84],[409.37,-68.61],[408.89,-66.41],[408.46,-64.22],[408.1,-62.06],[407.81,-59.92],[407.59,-57.8],[407.45,-55.69],[407.38,-53.6],[407.4,-51.52],[407.48,-49.44],[407.64,-47.38],[407.87,-45.32],[408.15,-43.26],[408.49,-41.2],[408.87,-39.13],[409.28,-37.07],[409.71,-35.0]],[[411.56,-35.0],[411.94,-32.91],[412.32,-30.82],[412.7,-28.72],[413.05,-26.62],[413.37,-24.5],[413.64,-22.39],[413.84,-20.26],[413.97,-18.14],[413.99,-16.01],[413.92,-13.88],[413.72,-11.75],[413.38,-9.63],[412.9,-7.52],[412.26,-5.42],[411.46,-3.34],[410.47,-1.27],[409.31,0.78],[407.95,2.79],[406.4,4.78],[404.66,6.74],[402.71,8.65],[400.57,10.53],[398.23,12.36],[395.7,14.15],[392.97,15.88],[390.07,17.56],[386.99,19.19],[383.75,20.76],[380.35,22.27],[376.81,23.72],[373.14,25.11],[369.35,26.44],[365.46,27.72],[361.49,28.94],[357.45,30.11],[353.35,31.22],[349.22,32.28],[345.07,33.3],[340.92,34.28],[336.78,35.22],[332.67,36.13],[328.61,37.01],[324.61,37.88],[320.69,38.73],[316.85,39.57],[313.11,40.41],[309.49,41.25],[305.99,42.11],[302.62,42.99],[299.39,43.89],[296.3,44.83],[293.36,45.8],[290.58,46.82],[287.94,47.89],[285.45,49.02],[283.11,50.2],[280.92,51.45],[278.87,52.77],[276.95,54.16],[275.16,55.63],[273.49,57.17],[271.93,58.79],[270.46,60.48],[269.07,62.25],[267.76,64.1],[266.51,66.02],[265.31,68.01],[264.13,70.06],[262.97,72.18],[261.81,74.36],[260.65,76.59],[259.45,78.86],[258.22,81.17],[256.93,83.52],[255.57,85.89],[254.14,88.27],[252.62,90.66],[251.0,93.05],[249.26,95.43],[247.41,97.79],[245.44,100.13],[243.33,102.43],[241.09,104.68],[238.71,106.88],[236.18,109.01],[233.52,111.08],[230.7,113.07],[227.75,114.98],[224.65,116.8],[221.42,118.53],[218.06,120.16],[214.56,121.68],[210.95,123.1],[207.22,124.41],[203.38,125.61],[199.44,126.7],[195.42,127.68],[191.3,128.54],[187.12,129.3],[182.87,129.96],[178.56,130.51],[174.21,130.96],[169.82,131.32],[165.39,131.59],[160.95,131.77],[156.49,131.88],[152.02,131.92],[147.55,131.9],[143.08,131.82],[138.62,131.68],[134.18,131.51],[129.75,131.31],[125.34,131.08],[120.94,130.83],[116.57,130.57],[112.22,130.3],[107.89,130.04],[103.58,129.78],[99.28,129.54],[95.0,129.32],[90.73,129.12],[86.47,128.94],[82.21,128.8],[77.95,128.69],[73.68,128.62],[69.41,128.58],[65.12,128.57],[60.82,128.6],[56.49,128.67],[52.14,128.76],[47.76,128.88],[43.35,129.03],[38.91,129.19],[34.44,129.37],[29.93,129.56],[25.38,129.75],[20.8,129.94],[16.19,130.12],[11.55,130.28],[6.89,130.42],[2.2,130.52],[-2.5,130.58],[-7.22,130.59],[-11.93,130.55],[-16.65,130.45],[-21.35,130.27],[-26.02,130.02],[-30.67,129.68],[-35.27,129.25],[-39.82,128.73],[-44.31,128.11],[-48.72,127.38],[-53.05,126.55],[-57.28,125.6],[-61.41,124.54],[-65.41,123.37],[-69.29,122.08],[-73.03,120.68],[-76.63,119.16],[-80.07,117.53],[-83.34,115.79],[-86.45,113.95],[-89.39,112.0],[-92.15,109.96],[-94.72,107.83],[-97.12,105.61],[-99.33,103.32],[-101.36,100.95],[-103.21,98.52],[-104.89,96.04],[-106.39,93.51],[-107.73,90.94],[-108.92,88.34],[-109.95,85.71],[-110.85,83.08],[-111.62,80.43],[-112.28,77.8],[-112.84,75.17],[-113.31,72.56],[-113.7,69.98],[-114.04,67.44],[-114.34,64.93],[-114.62,62.47],[-114.88,60.06],[-115.15,57.71],[-115.44,55.41],[-115.77,53.18],[-116.15,51.01],[-116.6,48.91],[-117.13,46.88],[-117.75,44.92],[-118.48,43.02],[-119.33,41.19],[-120.3,39.43],[-121.4,37.74],[-122.65,36.1],[-124.04,34.52],[-125.58,32.99],[-127.27,31.52],[-129.11,30.09],[-131.1,28.7],[-133.24,27.34],[-135.53,26.01],[-137.95,24.71],[-140.5,23.42],[-143.17,22.14],[-145.95,20.88],[-148.83,19.61],[-151.8,18.34],[-154.85,17.06],[-157.95,15.76],[-161.09,14.45],[-164.26,13.11],[-167.45,11.75],[-170.63,10.36],[-173.78,8.93],[-176.9,7.47],[-179.97,5.97],[-182.96,4.43],[-185.87,2.86],[-188.68,1.24],[-191.37,-0.42],[-193.93,-2.11],[-196.36,-3.85],[-198.63,-5.62],[-200.74,-7.43],[-202.68,-9.27],[-204.45,-11.14],[-206.03,-13.04],[-207.43,-14.97],[-208.65,-16.92],[-209.67,-18.89],[-210.51,-20.88],[-211.17,-22.88],[-211.65,-24.89],[-211.96,-26.91],[-212.09,-28.93],[-212.08,-30.96],[-211.91,-32.98],[-211.6,-35.0],[-211.17,-37.02],[-210.63,-39.03],[-209.99,-41.03],[-209.26,-43.02],[-208.46,-45.01],[-207.61,-46.98],[-206.71,-48.95],[-205.79,-50.9],[-204.85,-52.85],[-203.92,-54.8],[-203.0,-56.74],[-202.11,-58.67],[-201.27,-60.61],[-200.47,-62.55],[-199.74,-64.49],[-199.08,-66.44],[-198.49,-68.41],[-198.0,-70.38],[-197.59,-72.38],[-197.28,-74.39],[-197.06,-76.43],[-196.94,-78.5],[-196.91,-80.59],[-196.97,-82.72],[-197.12,-84.88],[-197.35,-87.08],[-197.66,-89.31],[-198.03,-91.58],[-198.45,-93.89],[-198.92,-96.24],[-199.42,-98.63],[-199.94,-101.06],[-200.46,-103.52],[-200.97,-106.01],[-201.45,-108.54],[-201.89,-111.1],[-202.27,-113.67],[-202.58,-116.27],[-202.79,-118.89],[-202.9,-121.52],[-202.88,-124.15],[-202.73,-126.78],[-202.42,-129.4],[-201.95,-132.0],[-201.29,-134.59],[-200.45,-137.15],[-199.41,-139.67],[-198.16,-142.14],[-196.69,-144.57],[-195.0,-146.94],[-193.08,-149.24],[-190.93,-151.47],[-188.54,-153.62],[-185.92,-155.69],[-183.07,-157.67],[-179.99,-159.55],[-176.68,-161.33],[-173.16,-163.01],[-169.42,-164.58],[-165.48,-166.03],[-161.35,-167.37],[-157.03,-168.6],[-152.55,-169.71],[-147.91,-170.7],[-143.12,-171.58],[-138.2,-172.35],[-133.17,-173.0],[-128.04,-173.55],[-122.83,-173.99],[-117.54,-174.34],[-112.21,-174.58],[-106.84,-174.74],[-101.44,-174.82],[-96.04,-174.82],[-90.64,-174.76],[-85.26,-174.63],[-79.91,-174.45],[-74.61,-174.23],[-69.36,-173.97],[-64.17,-173.68],[-59.05,-173.37],[-54.02,-173.06],[-49.07,-172.74],[-44.2,-172.43],[-39.44,-172.13],[-34.77,-171.85],[-30.19,-171.6],[-25.72,-171.39],[-21.34,-171.21],[-17.05,-171.08],[-12.86,-171.0],[-8.76,-170.97],[-4.74,-171.0],[-0.8,-171.08],[3.07,-171.23],[6.88,-171.43],[10.62,-171.7],[14.32,-172.02],[17.97,-172.4],[21.58,-172.83],[25.17,-173.32],[28.73,-173.85],[32.28,-174.42],[35.83,-175.03],[39.37,-175.67],[42.92,-176.34],[46.49,-177.02],[50.06,-177.72],[53.66,-178.41],[57.28,-179.11],[60.93,-179.79],[64.61,-180.45],[68.32,-181.08],[72.05,-181.68],[75.82,-182.24],[79.61,-182.74],[83.43,-183.19],[87.27,-183.58],[91.12,-183.91],[95.0,-184.16],[98.89,-184.33],[102.78,-184.42],[106.67,-184.43],[110.56,-184.35],[114.44,-184.18],[118.3,-183.93],[122.14,-183.58],[125.96,-183.15],[129.74,-182.63],[133.48,-182.03],[137.18,-181.35],[140.84,-180.59],[144.45,-179.75],[148.0,-178.85],[151.5,-177.89],[154.95,-176.87],[158.34,-175.8],[161.67,-174.69],[164.95,-173.55],[168.18,-172.37],[171.35,-171.18],[174.49,-169.98],[177.58,-168.78],[180.63,-167.58],[183.66,-166.39],[186.67,-165.22],[189.67,-164.08],[192.65,-162.97],[195.65,-161.9],[198.65,-160.88],[201.68,-159.91],[204.74,-158.99],[207.84,-158.13],[211.0,-157.33],[214.21,-156.6],[217.5,-155.94],[220.86,-155.34],[224.32,-154.81],[227.87,-154.34],[231.52,-153.94],[235.28,-153.61],[239.15,-153.33],[243.14,-153.11],[247.25,-152.94],[251.49,-152.81],[255.85,-152.73],[260.33,-152.67],[264.93,-152.65],[269.64,-152.65],[274.47,-152.65],[279.4,-152.67],[284.44,-152.68],[289.56,-152.67],[294.76,-152.65],[300.03,-152.6],[305.36,-152.52],[310.72,-152.39],[316.12,-152.21],[321.53,-151.98],[326.94,-151.67],[332.33,-151.3],[337.69,-150.85],[342.99,-150.31],[348.23,-149.69],[353.37,-148.98],[358.42,-148.17],[363.35,-147.27],[368.14,-146.26],[372.78,-145.16],[377.26,-143.95],[381.56,-142.64],[385.67,-141.23],[389.58,-139.72],[393.27,-138.12],[396.74,-136.42],[399.98,-134.63],[402.99,-132.75],[405.76,-130.79],[408.29,-128.76],[410.57,-126.65],[412.61,-124.47],[414.41,-122.24],[415.97,-119.95],[417.3,-117.61],[418.4,-115.23],[419.29,-112.81],[419.97,-110.36],[420.46,-107.89],[420.76,-105.4],[420.89,-102.9],[420.86,-100.4],[420.69,-97.89],[420.39,-95.38],[419.97,-92.89],[419.47,-90.4],[418.88,-87.94],[418.23,-85.49],[417.54,-83.06],[416.81,-80.65],[416.06,-78.27],[415.31,-75.92],[414.58,-73.59],[413.87,-71.29],[413.19,-69.02],[412.57,-66.78],[411.99,-64.55],[411.49,-62.36],[411.05,-60.18],[410.69,-58.02],[410.4,-55.89],[410.2,-53.77],[410.08,-51.66],[410.04,-49.56],[410.07,-47.47],[410.18,-45.39],[410.36,-43.31],[410.59,-41.24],[410.88,-39.16],[411.2,-37.08],[411.56,-35.0]],[[413.32,-35.0],[413.63,-32.9],[413.96,-30.8],[414.28,-28.69],[414.6,-26.57],[414.89,-24.45],[415.14,-22.33],[415.34,-20.19],[415.46,-18.06],[415.5,-15.92],[415.45,-13.78],[415.28,-11.64],[414.98,-9.51],[414.54,-7.38],[413.96,-5.26],[413.21,-3.16],[412.29,-1.07],[411.2,0.99],[409.92,3.03],[408.45,5.04],[406.78,7.02],[404.92,8.97],[402.86,10.87],[400.6,12.73],[398.15,14.55],[395.51,16.31],[392.69,18.03],[389.69,19.69],[386.52,21.29],[383.2,22.84],[379.73,24.33],[376.12,25.76],[372.39,27.13],[368.56,28.44],[364.63,29.69],[360.63,30.89],[356.57,32.04],[352.47,33.14],[348.34,34.19],[344.21,35.2],[340.08,36.18],[335.98,37.12],[331.92,38.03],[327.91,38.92],[323.97,39.8],[320.12,40.67],[316.36,41.53],[312.72,42.4],[309.19,43.28],[305.79,44.18],[302.52,45.1],[299.4,46.06],[296.42,47.05],[293.59,48.08],[290.91,49.17],[288.39,50.31],[286.01,51.51],[283.78,52.78],[281.69,54.12],[279.73,55.53],[277.91,57.01],[276.2,58.57],[274.61,60.21],[273.11,61.92],[271.7,63.72],[270.37,65.59],[269.09,67.54],[267.87,69.56],[266.68,71.65],[265.51,73.8],[264.34,76.01],[263.17,78.28],[261.97,80.6],[260.73,82.96],[259.44,85.35],[258.08,87.77],[256.65,90.21],[255.12,92.66],[253.5,95.11],[251.77,97.55],[249.92,99.98],[247.94,102.37],[245.83,104.74],[243.58,107.06],[241.19,109.32],[238.65,111.53],[235.97,113.67],[233.14,115.73],[230.16,117.71],[227.04,119.6],[223.78,121.39],[220.38,123.08],[216.84,124.67],[213.18,126.15],[209.4,127.51],[205.51,128.77],[201.52,129.91],[197.42,130.93],[193.25,131.84],[188.99,132.64],[184.66,133.32],[180.27,133.9],[175.84,134.38],[171.36,134.75],[166.85,135.03],[162.31,135.22],[157.76,135.33],[153.19,135.36],[148.63,135.32],[144.06,135.22],[139.51,135.06],[134.97,134.86],[130.44,134.62],[125.93,134.35],[121.45,134.05],[116.99,133.74],[112.55,133.42],[108.13,133.09],[103.73,132.77],[99.36,132.47],[95.0,132.17],[90.66,131.9],[86.32,131.65],[82.0,131.44],[77.68,131.25],[73.36,131.1],[69.03,130.98],[64.7,130.89],[60.35,130.85],[55.98,130.83],[51.59,130.85],[47.18,130.9],[42.74,130.97],[38.27,131.07],[33.77,131.18],[29.24,131.31],[24.67,131.44],[20.07,131.58],[15.44,131.7],[10.78,131.81],[6.1,131.9],[1.39,131.96],[-3.33,131.99],[-8.07,131.97],[-12.8,131.9],[-17.54,131.77],[-22.26,131.57],[-26.96,131.3],[-31.63,130.95],[-36.27,130.51],[-40.85,129.98],[-45.37,129.35],[-49.82,128.62],[-54.18,127.78],[-58.45,126.84],[-62.62,125.78],[-66.67,124.61],[-70.59,123.32],[-74.38,121.92],[-78.02,120.41],[-81.51,118.79],[-84.84,117.06],[-88.0,115.22],[-90.98,113.28],[-93.79,111.24],[-96.42,109.11],[-98.86,106.89],[-101.12,104.59],[-103.2,102.22],[-105.09,99.79],[-106.81,97.3],[-108.35,94.76],[-109.72,92.17],[-110.94,89.56],[-112.0,86.92],[-112.93,84.27],[-113.72,81.6],[-114.39,78.95],[-114.96,76.3],[-115.44,73.67],[-115.84,71.06],[-116.18,68.49],[-116.48,65.95],[-116.75,63.46],[-117.0,61.02],[-117.26,58.64],[-117.54,56.31],[-117.85,54.05],[-118.21,51.85],[-118.65,49.72],[-119.16,47.66],[-119.76,45.67],[-120.47,43.75],[-121.3,41.9],[-122.26,40.11],[-123.35,38.39],[-124.59,36.73],[-125.97,35.13],[-127.51,33.59],[-129.21,32.1],[-131.06,30.65],[-133.07,29.25],[-135.23,27.88],[-137.55,26.54],[-140.0,25.23],[-142.6,23.94],[-145.32,22.66],[-148.17,21.39],[-151.12,20.12],[-154.17,18.85],[-157.29,17.57],[-160.49,16.27],[-163.74,14.96],[-167.02,13.63],[-170.33,12.26],[-173.63,10.87],[-176.92,9.44],[-180.18,7.98],[-183.39,6.48],[-186.54,4.94],[-189.6,3.36],[-192.57,1.74],[-195.43,0.07],[-198.16,-1.63],[-200.75,-3.38],[-203.19,-5.16],[-205.46,-6.99],[-207.57,-8.85],[-209.5,-10.74],[-211.25,-12.66],[-212.81,-14.62],[-214.18,-16.59],[-215.35,-18.59],[-216.33,-20.61],[-217.13,-22.64],[-217.73,-24.69],[-218.15,-26.74],[-218.4,-28.81],[-218.48,-30.87],[-218.4,-32.94],[-218.18,-35.0],[-217.81,-37.06],[-217.33,-39.11],[-216.73,-41.16],[-216.03,-43.2],[-215.26,-45.23],[-214.41,-47.25],[-213.51,-49.26],[-212.58,-51.26],[-211.62,-53.26],[-210.65,-55.24],[-209.69,-57.22],[-208.75,-59.2],[-207.83,-61.18],[-206.97,-63.15],[-206.16,-65.13],[-205.41,-67.12],[-204.73,-69.12],[-204.13,-71.13],[-203.62,-73.15],[-203.2,-75.19],[-202.87,-77.26],[-202.64,-79.35],[-202.49,-81.47],[-202.44,-83.61],[-202.47,-85.79],[-202.59,-88.01],[-202.78,-90.26],[-203.03,-92.55],[-203.34,-94.87],[-203.7,-97.24],[-204.1,-99.64],[-204.51,-102.08],[-204.93,-104.55],[-205.35,-107.06],[-205.74,-109.6],[-206.1,-112.17],[-206.4,-114.77],[-206.63,-117.38],[-206.77,-120.01],[-206.81,-122.65],[-206.74,-125.3],[-206.53,-127.95],[-206.17,-130.59],[-205.65,-133.21],[-204.95,-135.82],[-204.07,-138.4],[-202.99,-140.94],[-201.71,-143.44],[-200.2,-145.89],[-198.48,-148.28],[-196.53,-150.61],[-194.35,-152.86],[-191.93,-155.04],[-189.28,-157.14],[-186.4,-159.14],[-183.29,-161.04],[-179.95,-162.85],[-176.39,-164.55],[-172.61,-166.14],[-168.63,-167.61],[-164.45,-168.97],[-160.09,-170.22],[-155.55,-171.34],[-150.85,-172.35],[-146.01,-173.24],[-141.03,-174.02],[-135.94,-174.68],[-130.74,-175.22],[-125.45,-175.67],[-120.09,-176.0],[-114.68,-176.25],[-109.22,-176.39],[-103.74,-176.46],[-98.25,-176.44],[-92.76,-176.35],[-87.29,-176.2],[-81.85,-176.0],[-76.46,-175.74],[-71.11,-175.45],[-65.83,-175.13],[-60.62,-174.79],[-55.5,-174.43],[-50.46,-174.07],[-45.51,-173.72],[-40.65,-173.37],[-35.9,-173.05],[-31.25,-172.75],[-26.69,-172.49],[-22.24,-172.27],[-17.89,-172.09],[-13.63,-171.97],[-9.47,-171.9],[-5.39,-171.88],[-1.39,-171.93],[2.52,-172.04],[6.37,-172.21],[10.16,-172.44],[13.89,-172.74],[17.57,-173.1],[21.22,-173.52],[24.83,-173.99],[28.42,-174.51],[31.99,-175.08],[35.55,-175.69],[39.11,-176.34],[42.67,-177.02],[46.25,-177.72],[49.84,-178.43],[53.45,-179.16],[57.08,-179.88],[60.74,-180.6],[64.43,-181.3],[68.15,-181.98],[71.9,-182.63],[75.68,-183.24],[79.5,-183.81],[83.34,-184.33],[87.2,-184.78],[91.09,-185.17],[95.0,-185.49],[98.92,-185.74],[102.86,-185.9],[106.79,-185.98],[110.73,-185.98],[114.66,-185.89],[118.58,-185.71],[122.48,-185.44],[126.36,-185.08],[130.21,-184.63],[134.02,-184.09],[137.8,-183.48],[141.53,-182.78],[145.22,-182.0],[148.85,-181.16],[152.44,-180.25],[155.97,-179.28],[159.44,-178.26],[162.86,-177.19],[166.23,-176.08],[169.54,-174.94],[172.8,-173.77],[176.02,-172.59],[179.2,-171.41],[182.34,-170.22],[185.45,-169.04],[188.54,-167.87],[191.61,-166.73],[194.68,-165.62],[197.74,-164.54],[200.82,-163.51],[203.91,-162.52],[207.04,-161.58],[210.2,-160.7],[213.41,-159.88],[216.69,-159.13],[220.03,-158.43],[223.44,-157.81],[226.95,-157.24],[230.54,-156.75],[234.24,-156.32],[238.04,-155.95],[241.96,-155.64],[245.99,-155.38],[250.15,-155.18],[254.42,-155.02],[258.82,-154.9],[263.35,-154.82],[267.99,-154.77],[272.75,-154.74],[277.63,-154.72],[282.61,-154.71],[287.69,-154.7],[292.87,-154.68],[298.12,-154.63],[303.45,-154.57],[308.84,-154.47],[314.27,-154.32],[319.73,-154.13],[325.21,-153.88],[330.7,-153.56],[336.16,-153.18],[341.59,-152.71],[346.98,-152.17],[352.3,-151.54],[357.53,-150.81],[362.66,-149.99],[367.67,-149.08],[372.55,-148.06],[377.28,-146.94],[381.85,-145.72],[386.23,-144.39],[390.42,-142.97],[394.41,-141.44],[398.18,-139.81],[401.72,-138.09],[405.03,-136.28],[408.1,-134.38],[410.93,-132.39],[413.51,-130.32],[415.83,-128.18],[417.91,-125.97],[419.74,-123.69],[421.32,-121.36],[422.67,-118.98],[423.78,-116.56],[424.66,-114.1],[425.33,-111.6],[425.79,-109.08],[426.05,-106.55],[426.14,-104.0],[426.05,-101.44],[425.82,-98.88],[425.45,-96.32],[424.95,-93.78],[424.35,-91.24],[423.67,-88.72],[422.91,-86.22],[422.1,-83.74],[421.25,-81.28],[420.38,-78.86],[419.5,-76.46],[418.63,-74.08],[417.77,-71.74],[416.95,-69.42],[416.18,-67.14],[415.46,-64.88],[414.81,-62.64],[414.22,-60.43],[413.71,-58.25],[413.29,-56.08],[412.94,-53.93],[412.69,-51.8],[412.52,-49.68],[412.43,-47.57],[412.42,-45.47],[412.48,-43.37],[412.61,-41.28],[412.8,-39.19],[413.04,-37.09],[413.32,-35.0]],[[415.0,-35.0],[415.24,-32.89],[415.51,-30.78],[415.78,-28.66],[416.06,-26.54],[416.32,-24.41],[416.56,-22.27],[416.75,-20.13],[416.87,-17.98],[416.93,-15.83],[416.89,-13.68],[416.75,-11.53],[416.5,-9.39],[416.11,-7.24],[415.58,-5.11],[414.89,-2.99],[414.04,-0.89],[413.02,1.2],[411.82,3.26],[410.43,5.3],[408.85,7.3],[407.08,9.27],[405.11,11.21],[402.94,13.1],[400.58,14.95],[398.03,16.74],[395.3,18.49],[392.39,20.19],[389.3,21.83],[386.05,23.41],[382.66,24.94],[379.12,26.4],[375.46,27.81],[371.69,29.16],[367.81,30.46],[363.86,31.7],[359.85,32.88],[355.78,34.02],[351.68,35.11],[347.57,36.15],[343.46,37.16],[339.36,38.13],[335.31,39.08],[331.3,40.0],[327.35,40.9],[323.49,41.8],[319.71,42.69],[316.05,43.58],[312.49,44.49],[309.06,45.41],[305.76,46.35],[302.6,47.33],[299.59,48.34],[296.72,49.39],[294.0,50.5],[291.43,51.66],[289.01,52.87],[286.74,54.16],[284.61,55.51],[282.62,56.94],[280.75,58.44],[279.01,60.02],[277.38,61.68],[275.85,63.42],[274.41,65.23],[273.05,67.13],[271.76,69.1],[270.51,71.15],[269.3,73.27],[268.11,75.46],[266.93,77.71],[265.74,80.02],[264.53,82.38],[263.29,84.78],[261.99,87.22],[260.63,89.69],[259.19,92.18],[257.66,94.68],[256.04,97.19],[254.3,99.69],[252.44,102.18],[250.46,104.64],[248.34,107.07],[246.09,109.45],[243.68,111.79],[241.13,114.06],[238.43,116.27],[235.58,118.4],[232.58,120.44],[229.43,122.4],[226.14,124.25],[222.7,126.01],[219.13,127.66],[215.42,129.2],[211.59,130.62],[207.65,131.93],[203.59,133.12],[199.43,134.19],[195.19,135.14],[190.86,135.97],[186.45,136.69],[181.99,137.29],[177.47,137.79],[172.9,138.18],[168.3,138.47],[163.67,138.66],[159.02,138.77],[154.37,138.79],[149.7,138.74],[145.04,138.62],[140.39,138.44],[135.75,138.21],[131.13,137.93],[126.53,137.61],[121.95,137.27],[117.4,136.91],[112.87,136.53],[108.37,136.14],[103.89,135.76],[99.43,135.38],[95.0,135.02],[90.58,134.67],[86.18,134.35],[81.8,134.05],[77.42,133.79],[73.04,133.55],[68.66,133.35],[64.28,133.19],[59.88,133.06],[55.48,132.97],[51.05,132.91],[46.61,132.88],[42.14,132.88],[37.64,132.91],[33.12,132.95],[28.56,133.01],[23.98,133.08],[19.36,133.16],[14.71,133.23],[10.04,133.29],[5.33,133.33],[0.61,133.35],[-4.13,133.34],[-8.88,133.28],[-13.63,133.18],[-18.38,133.02],[-23.13,132.8],[-27.85,132.51],[-32.55,132.15],[-37.21,131.69],[-41.82,131.16],[-46.37,130.52],[-50.85,129.79],[-55.25,128.95],[-59.56,128.01],[-63.77,126.95],[-67.86,125.79],[-71.83,124.51],[-75.67,123.12],[-79.36,121.61],[-82.89,119.99],[-86.27,118.27],[-89.48,116.44],[-92.52,114.5],[-95.38,112.47],[-98.06,110.34],[-100.55,108.13],[-102.86,105.83],[-104.99,103.46],[-106.93,101.03],[-108.69,98.53],[-110.27,95.98],[-111.69,93.39],[-112.94,90.77],[-114.03,88.12],[-114.99,85.45],[-115.8,82.77],[-116.5,80.09],[-117.09,77.42],[-117.58,74.77],[-117.99,72.14],[-118.34,69.54],[-118.64,66.98],[-118.91,64.47],[-119.16,62.0],[-119.41,59.58],[-119.68,57.23],[-119.98,54.94],[-120.33,52.71],[-120.75,50.56],[-121.24,48.47],[-121.83,46.45],[-122.53,44.5],[-123.35,42.62],[-124.29,40.81],[-125.38,39.07],[-126.6,37.39],[-127.99,35.77],[-129.53,34.21],[-131.23,32.7],[-133.09,31.24],[-135.12,29.83],[-137.3,28.45],[-139.64,27.1],[-142.14,25.78],[-144.78,24.48],[-147.56,23.2],[-150.46,21.92],[-153.48,20.65],[-156.6,19.38],[-159.82,18.09],[-163.11,16.8],[-166.46,15.49],[-169.85,14.15],[-173.27,12.79],[-176.71,11.4],[-180.13,9.97],[-183.53,8.5],[-186.88,7.0],[-190.18,5.46],[-193.4,3.87],[-196.53,2.24],[-199.55,0.57],[-202.44,-1.14],[-205.2,-2.9],[-207.81,-4.7],[-210.26,-6.54],[-212.53,-8.42],[-214.63,-10.33],[-216.54,-12.28],[-218.26,-14.25],[-219.78,-16.26],[-221.1,-18.29],[-222.23,-20.34],[-223.16,-22.4],[-223.89,-24.49],[-224.43,-26.58],[-224.79,-28.68],[-224.97,-30.79],[-224.98,-32.89],[-224.83,-35.0],[-224.54,-37.1],[-224.11,-39.2],[-223.56,-41.3],[-222.89,-43.38],[-222.14,-45.46],[-221.3,-47.52],[-220.4,-49.58],[-219.45,-51.63],[-218.47,-53.66],[-217.47,-55.69],[-216.46,-57.72],[-215.46,-59.74],[-214.48,-61.75],[-213.54,-63.77],[-212.65,-65.78],[-211.81,-67.8],[-211.03,-69.83],[-210.33,-71.87],[-209.71,-73.93],[-209.18,-76.0],[-208.73,-78.09],[-208.38,-80.2],[-208.11,-82.34],[-207.93,-84.51],[-207.84,-86.71],[-207.83,-88.94],[-207.9,-91.21],[-208.04,-93.51],[-208.23,-95.85],[-208.47,-98.23],[-208.75,-100.65],[-209.06,-103.1],[-209.37,-105.58],[-209.69,-108.11],[-209.99,-110.66],[-210.25,-113.24],[-210.46,-115.84],[-210.61,-118.47],[-210.68,-121.11],[-210.65,-123.77],[-210.51,-126.43],[-210.24,-129.09],[-209.83,-131.75],[-209.26,-134.39],[-208.51,-137.02],[-207.59,-139.61],[-206.47,-142.17],[-205.15,-144.7],[-203.61,-147.17],[-201.85,-149.58],[-199.87,-151.93],[-197.66,-154.21],[-195.21,-156.41],[-192.53,-158.53],[-189.62,-160.56],[-186.48,-162.49],[-183.1,-164.32],[-179.51,-166.04],[-175.7,-167.65],[-171.68,-169.15],[-167.46,-170.53],[-163.05,-171.79],[-158.47,-172.93],[-153.72,-173.95],[-148.82,-174.85],[-143.78,-175.64],[-138.62,-176.3],[-133.36,-176.86],[-128.0,-177.3],[-122.57,-177.63],[-117.08,-177.87],[-111.55,-178.01],[-105.99,-178.06],[-100.42,-178.03],[-94.84,-177.92],[-89.29,-177.75],[-83.76,-177.52],[-78.27,-177.24],[-72.84,-176.91],[-67.47,-176.56],[-62.18,-176.18],[-56.96,-175.78],[-51.83,-175.39],[-46.8,-174.99],[-41.86,-174.6],[-37.02,-174.24],[-32.29,-173.9],[-27.66,-173.59],[-23.14,-173.32],[-18.72,-173.1],[-14.4,-172.93],[-10.17,-172.82],[-6.04,-172.77],[-1.99,-172.77],[1.98,-172.85],[5.87,-172.99],[9.7,-173.19],[13.46,-173.46],[17.18,-173.8],[20.85,-174.2],[24.49,-174.66],[28.1,-175.17],[31.69,-175.74],[35.27,-176.35],[38.85,-177.01],[42.42,-177.7],[46.01,-178.41],[49.61,-179.15],[53.23,-179.9],[56.88,-180.66],[60.55,-181.42],[64.25,-182.16],[67.99,-182.89],[71.75,-183.59],[75.55,-184.26],[79.38,-184.89],[83.25,-185.46],[87.14,-185.99],[91.06,-186.45],[95.0,-186.84],[98.96,-187.16],[102.93,-187.4],[106.92,-187.56],[110.9,-187.63],[114.89,-187.61],[118.86,-187.51],[122.82,-187.32],[126.77,-187.03],[130.68,-186.66],[134.57,-186.19],[138.42,-185.64],[142.23,-185.01],[146.0,-184.3],[149.72,-183.51],[153.39,-182.66],[157.0,-181.74],[160.57,-180.76],[164.08,-179.74],[167.53,-178.66],[170.94,-177.56],[174.29,-176.42],[177.6,-175.27],[180.86,-174.1],[184.09,-172.92],[187.28,-171.75],[190.45,-170.59],[193.6,-169.45],[196.75,-168.33],[199.89,-167.25],[203.04,-166.2],[206.2,-165.2],[209.39,-164.24],[212.62,-163.34],[215.89,-162.5],[219.22,-161.71],[222.62,-160.99],[226.08,-160.33],[229.64,-159.74],[233.28,-159.21],[237.02,-158.74],[240.87,-158.34],[244.83,-157.99],[248.9,-157.7],[253.1,-157.46],[257.41,-157.27],[261.85,-157.12],[266.41,-157.01],[271.1,-156.92],[275.9,-156.86],[280.82,-156.82],[285.84,-156.78],[290.97,-156.74],[296.2,-156.69],[301.5,-156.63],[306.89,-156.54],[312.33,-156.42],[317.82,-156.25],[323.35,-156.04],[328.89,-155.77],[334.44,-155.44],[339.97,-155.04],[345.48,-154.57],[350.94,-154.01],[356.33,-153.37],[361.64,-152.63],[366.86,-151.8],[371.95,-150.87],[376.91,-149.84],[381.72,-148.7],[386.37,-147.47],[390.83,-146.12],[395.1,-144.68],[399.17,-143.13],[403.01,-141.49],[406.63,-139.74],[410.0,-137.9],[413.14,-135.97],[416.02,-133.96],[418.65,-131.86],[421.02,-129.68],[423.14,-127.44],[424.99,-125.13],[426.6,-122.76],[427.96,-120.34],[429.07,-117.87],[429.95,-115.37],[430.6,-112.83],[431.04,-110.26],[431.27,-107.67],[431.31,-105.07],[431.18,-102.47],[430.88,-99.86],[430.43,-97.25],[429.86,-94.65],[429.17,-92.06],[428.39,-89.49],[427.53,-86.94],[426.6,-84.41],[425.63,-81.91],[424.63,-79.43],[423.62,-76.98],[422.61,-74.56],[421.61,-72.18],[420.65,-69.82],[419.73,-67.49],[418.86,-65.19],[418.06,-62.92],[417.33,-60.68],[416.67,-58.46],[416.1,-56.27],[415.62,-54.09],[415.23,-51.93],[414.92,-49.79],[414.7,-47.66],[414.57,-45.54],[414.53,-43.42],[414.55,-41.32],[414.64,-39.21],[414.8,-37.11],[415.0,-35.0]],[[416.6,-35.0],[416.77,-32.88],[416.97,-30.76],[417.2,-28.63],[417.44,-26.5],[417.68,-24.36],[417.89,-22.22],[418.07,-20.07],[418.2,-17.91],[418.27,-15.75],[418.26,-13.59],[418.15,-11.43],[417.94,-9.27],[417.6,-7.12],[417.13,-4.97],[416.51,-2.83],[415.73,-0.71],[414.79,1.4],[413.67,3.48],[412.37,5.54],[410.88,7.58],[409.19,9.57],[407.32,11.54],[405.25,13.46],[402.99,15.34],[400.53,17.17],[397.89,18.96],[395.07,20.69],[392.08,22.36],[388.92,23.99],[385.6,25.55],[382.14,27.06],[378.55,28.51],[374.85,29.9],[371.04,31.23],[367.14,32.51],[363.17,33.73],[359.15,34.91],[355.09,36.04],[351.0,37.12],[346.91,38.16],[342.84,39.17],[338.79,40.15],[334.78,41.1],[330.83,42.04],[326.96,42.96],[323.17,43.88],[319.48,44.8],[315.9,45.73],[312.44,46.68],[309.11,47.65],[305.92,48.64],[302.87,49.67],[299.96,50.75],[297.2,51.87],[294.59,53.05],[292.13,54.28],[289.81,55.59],[287.64,56.96],[285.6,58.4],[283.7,59.92],[281.92,61.52],[280.25,63.2],[278.69,64.96],[277.21,66.8],[275.82,68.72],[274.5,70.72],[273.22,72.79],[271.99,74.94],[270.78,77.16],[269.58,79.45],[268.38,81.79],[267.15,84.19],[265.89,86.64],[264.59,89.12],[263.22,91.64],[261.77,94.18],[260.24,96.74],[258.6,99.3],[256.86,101.85],[255.0,104.4],[253.0,106.92],[250.88,109.41],[248.61,111.86],[246.19,114.26],[243.62,116.6],[240.9,118.87],[238.03,121.07],[235.0,123.18],[231.83,125.2],[228.5,127.12],[225.02,128.94],[221.41,130.65],[217.66,132.25],[213.78,133.73],[209.78,135.09],[205.66,136.32],[201.44,137.44],[197.13,138.43],[192.72,139.3],[188.24,140.05],[183.7,140.68],[179.09,141.2],[174.44,141.61],[169.75,141.91],[165.03,142.1],[160.29,142.21],[155.54,142.22],[150.78,142.16],[146.02,142.02],[141.27,141.81],[136.54,141.55],[131.82,141.23],[127.13,140.87],[122.45,140.48],[117.81,140.06],[113.19,139.63],[108.6,139.18],[104.04,138.73],[99.51,138.28],[95.0,137.85],[90.51,137.42],[86.05,137.02],[81.59,136.65],[77.15,136.3],[72.72,135.98],[68.29,135.7],[63.86,135.46],[59.43,135.25],[54.98,135.07],[50.53,134.93],[46.05,134.83],[41.55,134.75],[37.03,134.7],[32.48,134.68],[27.91,134.67],[23.3,134.67],[18.67,134.69],[14.01,134.7],[9.32,134.71],[4.6,134.7],[-0.13,134.68],[-4.88,134.62],[-9.65,134.53],[-14.42,134.4],[-19.19,134.21],[-23.95,133.97],[-28.69,133.66],[-33.41,133.28],[-38.1,132.82],[-42.73,132.27],[-47.32,131.63],[-51.83,130.89],[-56.27,130.05],[-60.61,129.11],[-64.86,128.06],[-68.99,126.9],[-73.01,125.63],[-76.89,124.25],[-80.63,122.75],[-84.22,121.15],[-87.65,119.43],[-90.91,117.61],[-94.0,115.68],[-96.92,113.66],[-99.65,111.54],[-102.2,109.33],[-104.56,107.04],[-106.74,104.67],[-108.73,102.24],[-110.53,99.74],[-112.17,97.19],[-113.62,94.59],[-114.91,91.96],[-116.05,89.3],[-117.04,86.62],[-117.88,83.93],[-118.61,81.24],[-119.22,78.55],[-119.73,75.88],[-120.16,73.23],[-120.52,70.61],[-120.82,68.03],[-121.1,65.48],[-121.35,62.99],[-121.6,60.55],[-121.86,58.17],[-122.16,55.85],[-122.5,53.6],[-122.91,51.41],[-123.39,49.3],[-123.97,47.25],[-124.66,45.28],[-125.46,43.38],[-126.4,41.54],[-127.48,39.78],[-128.7,38.08],[-130.08,36.44],[-131.62,34.86],[-133.33,33.33],[-135.21,31.86],[-137.25,30.43],[-139.46,29.04],[-141.83,27.68],[-144.36,26.35],[-147.04,25.04],[-149.87,23.75],[-152.84,22.47],[-155.92,21.2],[-159.12,19.92],[-162.42,18.64],[-165.8,17.34],[-169.25,16.03],[-172.76,14.69],[-176.3,13.33],[-179.85,11.93],[-183.41,10.5],[-186.94,9.04],[-190.44,7.53],[-193.89,5.98],[-197.27,4.39],[-200.55,2.76],[-203.73,1.08],[-206.79,-0.65],[-209.72,-2.42],[-212.5,-4.23],[-215.11,-6.09],[-217.56,-7.98],[-219.82,-9.92],[-221.89,-11.89],[-223.77,-13.89],[-225.45,-15.92],[-226.92,-17.98],[-228.19,-20.06],[-229.26,-22.16],[-230.12,-24.28],[-230.78,-26.41],[-231.25,-28.55],[-231.53,-30.7],[-231.64,-32.85],[-231.57,-35.0],[-231.34,-37.15],[-230.97,-39.29],[-230.46,-41.43],[-229.84,-43.56],[-229.1,-45.69],[-228.28,-47.8],[-227.37,-49.9],[-226.41,-51.99],[-225.4,-54.08],[-224.36,-56.15],[-223.31,-58.22],[-222.25,-60.28],[-221.21,-62.33],[-220.19,-64.39],[-219.2,-66.44],[-218.27,-68.5],[-217.4,-70.56],[-216.59,-72.63],[-215.86,-74.71],[-215.21,-76.81],[-214.64,-78.93],[-214.15,-81.07],[-213.76,-83.23],[-213.46,-85.42],[-213.23,-87.63],[-213.09,-89.88],[-213.03,-92.16],[-213.04,-94.48],[-213.11,-96.83],[-213.23,-99.22],[-213.39,-101.65],[-213.57,-104.11],[-213.78,-106.61],[-213.99,-109.14],[-214.18,-111.7],[-214.35,-114.29],[-214.47,-116.9],[-214.53,-119.54],[-214.52,-122.19],[-214.41,-124.86],[-214.2,-127.54],[-213.87,-130.21],[-213.39,-132.88],[-212.77,-135.54],[-211.97,-138.18],[-211.0,-140.79],[-209.84,-143.37],[-208.48,-145.91],[-206.9,-148.4],[-205.11,-150.84],[-203.1,-153.21],[-200.85,-155.51],[-198.38,-157.74],[-195.67,-159.88],[-192.73,-161.93],[-189.55,-163.88],[-186.15,-165.73],[-182.52,-167.48],[-178.68,-169.11],[-174.62,-170.63],[-170.37,-172.03],[-165.92,-173.31],[-161.29,-174.47],[-156.5,-175.5],[-151.55,-176.42],[-146.45,-177.21],[-141.24,-177.88],[-135.91,-178.44],[-130.49,-178.89],[-125.0,-179.22],[-119.44,-179.45],[-113.83,-179.59],[-108.19,-179.63],[-102.54,-179.58],[-96.89,-179.46],[-91.25,-179.27],[-85.63,-179.01],[-80.06,-178.7],[-74.54,-178.35],[-69.09,-177.97],[-63.7,-177.55],[-58.4,-177.12],[-53.19,-176.69],[-48.07,-176.25],[-43.05,-175.82],[-38.14,-175.41],[-33.33,-175.03],[-28.63,-174.68],[-24.03,-174.37],[-19.55,-174.11],[-15.16,-173.9],[-10.87,-173.74],[-6.68,-173.65],[-2.58,-173.62],[1.43,-173.66],[5.37,-173.77],[9.23,-173.94],[13.04,-174.19],[16.79,-174.5],[20.49,-174.89],[24.15,-175.33],[27.78,-175.84],[31.39,-176.4],[34.99,-177.02],[38.58,-177.68],[42.17,-178.38],[45.77,-179.11],[49.38,-179.88],[53.02,-180.66],[56.67,-181.45],[60.36,-182.24],[64.07,-183.03],[67.82,-183.81],[71.6,-184.56],[75.42,-185.29],[79.27,-185.97],[83.16,-186.62],[87.08,-187.21],[91.03,-187.74],[95.0,-188.2],[99.0,-188.59],[103.01,-188.91],[107.04,-189.15],[111.08,-189.3],[115.11,-189.36],[119.15,-189.34],[123.17,-189.22],[127.18,-189.01],[131.17,-188.71],[135.13,-188.32],[139.06,-187.85],[142.95,-187.28],[146.8,-186.64],[150.6,-185.91],[154.36,-185.11],[158.07,-184.25],[161.72,-183.32],[165.32,-182.34],[168.87,-181.31],[172.36,-180.23],[175.81,-179.13],[179.21,-178.0],[182.56,-176.85],[185.88,-175.69],[189.16,-174.53],[192.41,-173.38],[195.65,-172.23],[198.87,-171.11],[202.09,-170.02],[205.31,-168.96],[208.54,-167.94],[211.8,-166.97],[215.1,-166.04],[218.43,-165.17],[221.82,-164.36],[225.27,-163.61],[228.79,-162.92],[232.39,-162.29],[236.08,-161.72],[239.87,-161.22],[243.76,-160.78],[247.75,-160.39],[251.87,-160.06],[256.1,-159.79],[260.45,-159.56],[264.93,-159.37],[269.53,-159.22],[274.25,-159.1],[279.09,-159.01],[284.04,-158.93],[289.11,-158.86],[294.28,-158.79],[299.55,-158.72],[304.9,-158.63],[310.33,-158.51],[315.82,-158.37],[321.37,-158.18],[326.95,-157.95],[332.56,-157.67],[338.17,-157.32],[343.77,-156.9],[349.34,-156.41],[354.87,-155.84],[360.33,-155.18],[365.72,-154.43],[371.01,-153.58],[376.18,-152.64],[381.22,-151.59],[386.11,-150.44],[390.83,-149.19],[395.37,-147.83],[399.72,-146.37],[403.86,-144.8],[407.77,-143.13],[411.45,-141.36],[414.9,-139.5],[418.09,-137.55],[421.03,-135.5],[423.71,-133.37],[426.12,-131.17],[428.28,-128.89],[430.16,-126.54],[431.79,-124.13],[433.16,-121.67],[434.28,-119.16],[435.15,-116.61],[435.79,-114.03],[436.21,-111.42],[436.41,-108.78],[436.41,-106.14],[436.22,-103.48],[435.86,-100.82],[435.35,-98.16],[434.69,-95.51],[433.92,-92.87],[433.04,-90.25],[432.07,-87.65],[431.03,-85.07],[429.94,-82.52],[428.81,-79.99],[427.67,-77.5],[426.52,-75.04],[425.39,-72.61],[424.28,-70.21],[423.22,-67.84],[422.2,-65.51],[421.25,-63.2],[420.37,-60.92],[419.57,-58.67],[418.85,-56.45],[418.23,-54.24],[417.69,-52.06],[417.26,-49.9],[416.91,-47.74],[416.66,-45.61],[416.5,-43.48],[416.42,-41.35],[416.41,-39.23],[416.48,-37.12],[416.6,-35.0]],[[418.12,-35.0],[418.22,-32.87],[418.37,-30.74],[418.55,-28.61],[418.75,-26.47],[418.95,-24.32],[419.15,-22.17],[419.32,-20.01],[419.46,-17.85],[419.54,-15.68],[419.55,-13.51],[419.48,-11.33],[419.31,-9.16],[419.02,-6.99],[418.61,-4.83],[418.06,-2.67],[417.36,-0.53],[416.5,1.59],[415.46,3.7],[414.25,5.79],[412.86,7.84],[411.28,9.87],[409.5,11.86],[407.53,13.82],[405.37,15.73],[403.02,17.6],[400.48,19.42],[397.76,21.19],[394.86,22.9],[391.79,24.56],[388.57,26.17],[385.19,27.72],[381.68,29.21],[378.05,30.64],[374.31,32.02],[370.47,33.34],[366.56,34.6],[362.59,35.82],[358.56,36.99],[354.51,38.11],[350.45,39.19],[346.4,40.24],[342.36,41.25],[338.36,42.24],[334.41,43.21],[330.53,44.17],[326.73,45.12],[323.03,46.07],[319.43,47.02],[315.94,47.99],[312.58,48.98],[309.35,50.0],[306.26,51.06],[303.32,52.15],[300.51,53.29],[297.86,54.49],[295.35,55.75],[292.99,57.07],[290.78,58.46],[288.7,59.92],[286.75,61.45],[284.92,63.07],[283.21,64.77],[281.61,66.55],[280.1,68.41],[278.67,70.35],[277.32,72.38],[276.01,74.48],[274.75,76.66],[273.52,78.91],[272.3,81.23],[271.07,83.61],[269.83,86.04],[268.55,88.53],[267.23,91.06],[265.85,93.62],[264.39,96.21],[262.84,98.81],[261.2,101.43],[259.44,104.04],[257.57,106.64],[255.56,109.22],[253.42,111.77],[251.14,114.29],[248.71,116.75],[246.12,119.15],[243.38,121.49],[240.48,123.75],[237.43,125.92],[234.22,128.01],[230.86,129.99],[227.35,131.87],[223.69,133.64],[219.89,135.29],[215.96,136.83],[211.9,138.24],[207.73,139.52],[203.45,140.68],[199.06,141.72],[194.59,142.62],[190.03,143.4],[185.4,144.06],[180.72,144.6],[175.98,145.02],[171.2,145.33],[166.39,145.53],[161.55,145.64],[156.71,145.64],[151.85,145.56],[147.0,145.4],[142.15,145.17],[137.32,144.87],[132.51,144.52],[127.72,144.12],[122.96,143.68],[118.22,143.21],[113.51,142.71],[108.84,142.2],[104.2,141.69],[99.58,141.17],[95.0,140.66],[90.44,140.16],[85.91,139.68],[81.39,139.22],[76.89,138.79],[72.41,138.39],[67.93,138.03],[63.45,137.69],[58.98,137.4],[54.5,137.14],[50.01,136.92],[45.5,136.73],[40.98,136.58],[36.43,136.45],[31.87,136.36],[27.27,136.28],[22.65,136.22],[18.0,136.17],[13.33,136.12],[8.63,136.07],[3.9,136.02],[-0.84,135.95],[-5.61,135.85],[-10.38,135.72],[-15.17,135.55],[-19.95,135.34],[-24.73,135.07],[-29.49,134.74],[-34.23,134.35],[-38.93,133.87],[-43.6,133.31],[-48.21,132.67],[-52.75,131.93],[-57.22,131.1],[-61.6,130.16],[-65.89,129.11],[-70.07,127.96],[-74.12,126.7],[-78.05,125.33],[-81.84,123.84],[-85.48,122.25],[-88.96,120.55],[-92.28,118.74],[-95.43,116.82],[-98.4,114.81],[-101.19,112.7],[-103.79,110.5],[-106.21,108.22],[-108.44,105.86],[-110.49,103.42],[-112.35,100.93],[-114.03,98.38],[-115.54,95.78],[-116.87,93.15],[-118.05,90.48],[-119.08,87.79],[-119.96,85.09],[-120.72,82.39],[-121.36,79.69],[-121.89,77.0],[-122.34,74.33],[-122.72,71.69],[-123.04,69.08],[-123.32,66.52],[-123.58,64.0],[-123.83,61.54],[-124.1,59.13],[-124.39,56.79],[-124.73,54.51],[-125.13,52.3],[-125.61,50.15],[-126.18,48.08],[-126.86,46.08],[-127.66,44.16],[-128.59,42.3],[-129.66,40.51],[-130.88,38.79],[-132.26,37.13],[-133.81,35.53],[-135.52,33.99],[-137.41,32.5],[-139.47,31.05],[-141.7,29.65],[-144.1,28.28],[-146.67,26.94],[-149.4,25.63],[-152.28,24.33],[-155.3,23.04],[-158.45,21.76],[-161.73,20.48],[-165.11,19.2],[-168.58,17.9],[-172.13,16.58],[-175.74,15.24],[-179.39,13.88],[-183.07,12.48],[-186.76,11.05],[-190.43,9.58],[-194.07,8.07],[-197.67,6.52],[-201.2,4.92],[-204.64,3.28],[-207.99,1.59],[-211.21,-0.15],[-214.3,-1.93],[-217.25,-3.76],[-220.03,-5.63],[-222.64,-7.54],[-225.07,-9.5],[-227.31,-11.49],[-229.35,-13.52],[-231.18,-15.58],[-232.81,-17.67],[-234.22,-19.78],[-235.42,-21.92],[-236.42,-24.07],[-237.2,-26.24],[-237.78,-28.42],[-238.17,-30.61],[-238.36,-32.8],[-238.38,-35.0],[-238.22,-37.19],[-237.91,-39.39],[-237.45,-41.57],[-236.85,-43.75],[-236.14,-45.92],[-235.33,-48.08],[-234.42,-50.23],[-233.44,-52.37],[-232.41,-54.49],[-231.33,-56.61],[-230.23,-58.72],[-229.11,-60.82],[-227.99,-62.92],[-226.9,-65.01],[-225.83,-67.1],[-224.8,-69.19],[-223.82,-71.29],[-222.9,-73.39],[-222.05,-75.5],[-221.27,-77.63],[-220.58,-79.77],[-219.96,-81.93],[-219.44,-84.11],[-219.0,-86.32],[-218.64,-88.56],[-218.36,-90.82],[-218.16,-93.12],[-218.04,-95.45],[-217.97,-97.81],[-217.96,-100.21],[-217.99,-102.64],[-218.06,-105.11],[-218.14,-107.62],[-218.24,-110.16],[-218.32,-112.72],[-218.38,-115.32],[-218.41,-117.95],[-218.38,-120.59],[-218.28,-123.25],[-218.09,-125.93],[-217.8,-128.61],[-217.4,-131.3],[-216.86,-133.98],[-216.17,-136.65],[-215.33,-139.31],[-214.31,-141.93],[-213.1,-144.53],[-211.69,-147.09],[-210.08,-149.6],[-208.26,-152.05],[-206.21,-154.45],[-203.93,-156.77],[-201.43,-159.02],[-198.69,-161.18],[-195.72,-163.25],[-192.52,-165.23],[-189.09,-167.1],[-185.43,-168.87],[-181.56,-170.52],[-177.47,-172.06],[-173.18,-173.48],[-168.69,-174.78],[-164.02,-175.95],[-159.18,-177.0],[-154.19,-177.93],[-149.05,-178.74],[-143.78,-179.42],[-138.4,-179.98],[-132.92,-180.43],[-127.36,-180.77],[-121.73,-181.0],[-116.05,-181.13],[-110.34,-181.16],[-104.62,-181.1],[-98.89,-180.96],[-93.17,-180.75],[-87.48,-180.48],[-81.82,-180.15],[-76.22,-179.77],[-70.68,-179.35],[-65.22,-178.91],[-59.83,-178.45],[-54.54,-177.97],[-49.34,-177.5],[-44.24,-177.03],[-39.25,-176.58],[-34.37,-176.16],[-29.59,-175.77],[-24.93,-175.42],[-20.37,-175.11],[-15.92,-174.86],[-11.58,-174.67],[-7.33,-174.53],[-3.18,-174.47],[0.88,-174.48],[4.86,-174.55],[8.77,-174.7],[12.61,-174.92],[16.39,-175.22],[20.12,-175.58],[23.8,-176.02],[27.46,-176.51],[31.09,-177.07],[34.71,-177.69],[38.31,-178.36],[41.92,-179.07],[45.53,-179.83],[49.15,-180.61],[52.8,-181.42],[56.46,-182.24],[60.16,-183.08],[63.89,-183.91],[67.65,-184.73],[71.45,-185.54],[75.28,-186.32],[79.16,-187.07],[83.07,-187.78],[87.01,-188.44],[90.99,-189.04],[95.0,-189.58],[99.04,-190.05],[103.09,-190.45],[107.17,-190.76],[111.25,-191.0],[115.34,-191.14],[119.44,-191.2],[123.53,-191.16],[127.6,-191.03],[131.66,-190.81],[135.7,-190.49],[139.7,-190.09],[143.68,-189.59],[147.61,-189.02],[151.5,-188.35],[155.35,-187.62],[159.15,-186.81],[162.89,-185.93],[166.59,-184.99],[170.23,-184.0],[173.82,-182.97],[177.36,-181.9],[180.85,-180.79],[184.3,-179.66],[187.7,-178.52],[191.08,-177.37],[194.42,-176.22],[197.74,-175.08],[201.04,-173.96],[204.34,-172.86],[207.64,-171.79],[210.94,-170.75],[214.27,-169.76],[217.63,-168.81],[221.03,-167.91],[224.47,-167.07],[227.98,-166.28],[231.55,-165.56],[235.2,-164.89],[238.94,-164.29],[242.77,-163.75],[246.7,-163.26],[250.74,-162.84],[254.89,-162.47],[259.16,-162.15],[263.54,-161.89],[268.05,-161.66],[272.68,-161.47],[277.44,-161.31],[282.31,-161.18],[287.3,-161.07],[292.41,-160.96],[297.61,-160.86],[302.92,-160.75],[308.31,-160.64],[313.78,-160.49],[319.32,-160.32],[324.92,-160.11],[330.55,-159.86],[336.21,-159.55],[341.87,-159.18],[347.53,-158.75],[353.17,-158.24],[358.76,-157.65],[364.29,-156.97],[369.75,-156.2],[375.11,-155.34],[380.35,-154.38],[385.46,-153.32],[390.43,-152.15],[395.22,-150.88],[399.84,-149.51],[404.26,-148.02],[408.46,-146.44],[412.45,-144.75],[416.2,-142.96],[419.7,-141.07],[422.96,-139.09],[425.95,-137.02],[428.68,-134.86],[431.13,-132.62],[433.32,-130.31],[435.24,-127.93],[436.89,-125.48],[438.27,-122.98],[439.4,-120.43],[440.27,-117.84],[440.9,-115.21],[441.29,-112.56],[441.46,-109.88],[441.42,-107.18],[441.18,-104.47],[440.76,-101.77],[440.18,-99.06],[439.45,-96.36],[438.59,-93.67],[437.61,-91.0],[436.54,-88.35],[435.39,-85.72],[434.18,-83.12],[432.93,-80.55],[431.66,-78.01],[430.37,-75.5],[429.1,-73.03],[427.85,-70.59],[426.64,-68.18],[425.47,-65.81],[424.37,-63.47],[423.34,-61.16],[422.4,-58.88],[421.53,-56.62],[420.77,-54.4],[420.1,-52.19],[419.52,-50.0],[419.05,-47.83],[418.68,-45.67],[418.4,-43.53],[418.21,-41.39],[418.11,-39.26],[418.08,-37.13],[418.12,-35.0]],[[419.58,-35.0],[419.61,-32.86],[419.69,-30.72],[419.82,-28.58],[419.98,-26.43],[420.16,-24.28],[420.34,-22.12],[420.51,-19.95],[420.65,-17.78],[420.74,-15.61],[420.78,-13.43],[420.74,-11.24],[420.62,-9.06],[420.39,-6.87],[420.04,-4.7],[419.56,-2.53],[418.93,-0.36],[418.15,1.78],[417.21,3.91],[416.1,6.02],[414.8,8.11],[413.32,10.16],[411.66,12.18],[409.8,14.17],[407.74,16.12],[405.5,18.02],[403.07,19.88],[400.45,21.68],[397.65,23.44],[394.69,25.14],[391.56,26.79],[388.27,28.38],[384.85,29.92],[381.3,31.39],[377.63,32.81],[373.86,34.18],[370.01,35.49],[366.09,36.75],[362.12,37.96],[358.11,39.12],[354.08,40.24],[350.05,41.33],[346.03,42.38],[342.04,43.41],[338.1,44.41],[334.21,45.4],[330.41,46.39],[326.69,47.37],[323.07,48.35],[319.56,49.35],[316.17,50.37],[312.9,51.41],[309.78,52.49],[306.79,53.61],[303.95,54.77],[301.25,55.99],[298.7,57.26],[296.29,58.6],[294.02,60.01],[291.9,61.49],[289.9,63.04],[288.03,64.68],[286.28,66.39],[284.63,68.19],[283.08,70.07],[281.61,72.04],[280.22,74.09],[278.88,76.22],[277.59,78.42],[276.32,80.7],[275.07,83.05],[273.82,85.46],[272.55,87.93],[271.26,90.46],[269.92,93.02],[268.51,95.63],[267.04,98.26],[265.48,100.91],[263.82,103.58],[262.05,106.24],[260.16,108.9],[258.14,111.54],[255.98,114.15],[253.68,116.72],[251.23,119.24],[248.63,121.71],[245.86,124.1],[242.94,126.43],[239.86,128.66],[236.62,130.81],[233.22,132.86],[229.67,134.8],[225.97,136.62],[222.12,138.33],[218.14,139.92],[214.03,141.38],[209.79,142.72],[205.44,143.92],[200.99,144.99],[196.44,145.93],[191.81,146.75],[187.1,147.43],[182.33,147.99],[177.51,148.43],[172.64,148.74],[167.74,148.95],[162.81,149.05],[157.87,149.05],[152.92,148.96],[147.97,148.77],[143.03,148.52],[138.1,148.19],[133.19,147.8],[128.31,147.35],[123.45,146.86],[118.63,146.34],[113.83,145.78],[109.08,145.21],[104.35,144.62],[99.66,144.04],[95.0,143.45],[90.37,142.87],[85.77,142.31],[81.19,141.77],[76.64,141.26],[72.1,140.77],[67.57,140.32],[63.05,139.9],[58.54,139.52],[54.02,139.18],[49.49,138.87],[44.96,138.6],[40.41,138.37],[35.85,138.16],[31.26,137.99],[26.65,137.84],[22.02,137.71],[17.36,137.59],[12.68,137.49],[7.97,137.38],[3.23,137.28],[-1.52,137.16],[-6.29,137.02],[-11.08,136.85],[-15.87,136.65],[-20.67,136.41],[-25.46,136.11],[-30.24,135.76],[-34.99,135.35],[-39.72,134.86],[-44.41,134.3],[-49.04,133.65],[-53.61,132.91],[-58.12,132.07],[-62.53,131.14],[-66.86,130.1],[-71.08,128.96],[-75.18,127.71],[-79.16,126.35],[-82.99,124.88],[-86.69,123.3],[-90.22,121.61],[-93.6,119.82],[-96.8,117.92],[-99.83,115.92],[-102.68,113.82],[-105.34,111.63],[-107.82,109.36],[-110.11,107.01],[-112.21,104.59],[-114.13,102.1],[-115.87,99.55],[-117.43,96.96],[-118.82,94.32],[-120.04,91.65],[-121.11,88.96],[-122.04,86.25],[-122.83,83.54],[-123.51,80.83],[-124.07,78.12],[-124.55,75.44],[-124.95,72.78],[-125.29,70.16],[-125.59,67.57],[-125.86,65.03],[-126.12,62.55],[-126.39,60.12],[-126.69,57.75],[-127.03,55.44],[-127.43,53.21],[-127.91,51.04],[-128.47,48.94],[-129.15,46.92],[-129.94,44.97],[-130.87,43.09],[-131.94,41.28],[-133.16,39.53],[-134.54,37.85],[-136.09,36.24],[-137.81,34.67],[-139.71,33.17],[-141.79,31.71],[-144.05,30.29],[-146.48,28.91],[-149.08,27.56],[-151.85,26.24],[-154.78,24.93],[-157.86,23.64],[-161.08,22.35],[-164.42,21.07],[-167.88,19.78],[-171.45,18.47],[-175.09,17.15],[-178.81,15.81],[-182.57,14.44],[-186.37,13.05],[-190.19,11.61],[-193.99,10.14],[-197.78,8.63],[-201.52,7.07],[-205.2,5.46],[-208.8,3.81],[-212.31,2.11],[-215.69,0.36],[-218.95,-1.43],[-222.06,-3.27],[-225.01,-5.16],[-227.79,-7.1],[-230.39,-9.08],[-232.79,-11.09],[-234.99,-13.15],[-236.98,-15.23],[-238.75,-17.35],[-240.31,-19.5],[-241.65,-21.67],[-242.78,-23.86],[-243.69,-26.07],[-244.38,-28.29],[-244.87,-30.52],[-245.16,-32.76],[-245.25,-35.0],[-245.17,-37.24],[-244.91,-39.48],[-244.5,-41.71],[-243.94,-43.94],[-243.25,-46.15],[-242.45,-48.36],[-241.54,-50.56],[-240.55,-52.74],[-239.48,-54.91],[-238.37,-57.08],[-237.21,-59.23],[-236.03,-61.37],[-234.85,-63.51],[-233.66,-65.64],[-232.5,-67.77],[-231.37,-69.9],[-230.29,-72.03],[-229.25,-74.16],[-228.28,-76.3],[-227.38,-78.45],[-226.55,-80.62],[-225.8,-82.8],[-225.13,-85.0],[-224.55,-87.23],[-224.05,-89.48],[-223.63,-91.76],[-223.29,-94.07],[-223.02,-96.41],[-222.82,-98.78],[-222.67,-101.19],[-222.57,-103.63],[-222.51,-106.11],[-222.47,-108.62],[-222.44,-111.16],[-222.41,-113.74],[-222.36,-116.34],[-222.28,-118.97],[-222.15,-121.62],[-221.96,-124.29],[-221.68,-126.97],[-221.32,-129.66],[-220.84,-132.36],[-220.23,-135.05],[-219.48,-137.73],[-218.57,-140.4],[-217.5,-143.04],[-216.24,-145.65],[-214.79,-148.22],[-213.14,-150.75],[-211.28,-153.22],[-209.2,-155.63],[-206.9,-157.98],[-204.36,-160.24],[-201.6,-162.43],[-198.6,-164.52],[-195.37,-166.52],[-191.91,-168.41],[-188.23,-170.2],[-184.32,-171.88],[-180.21,-173.44],[-175.88,-174.88],[-171.36,-176.19],[-166.66,-177.39],[-161.78,-178.46],[-156.74,-179.4],[-151.56,-180.22],[-146.24,-180.91],[-140.81,-181.48],[-135.27,-181.93],[-129.65,-182.27],[-123.97,-182.5],[-118.22,-182.63],[-112.45,-182.66],[-106.65,-182.59],[-100.85,-182.44],[-95.05,-182.22],[-89.29,-181.92],[-83.56,-181.57],[-77.88,-181.17],[-72.26,-180.73],[-66.71,-180.25],[-61.25,-179.76],[-55.87,-179.25],[-50.6,-178.74],[-45.42,-178.24],[-40.35,-177.75],[-35.4,-177.28],[-30.55,-176.85],[-25.82,-176.46],[-21.2,-176.12],[-16.69,-175.83],[-12.29,-175.6],[-7.99,-175.43],[-3.79,-175.33],[0.32,-175.3],[4.35,-175.35],[8.29,-175.47],[12.17,-175.67],[15.98,-175.94],[19.74,-176.29],[23.45,-176.71],[27.13,-177.2],[30.78,-177.76],[34.41,-178.38],[38.04,-179.05],[41.66,-179.78],[45.28,-180.55],[48.92,-181.36],[52.57,-182.2],[56.25,-183.05],[59.96,-183.93],[63.7,-184.8],[67.48,-185.68],[71.29,-186.54],[75.15,-187.38],[79.04,-188.19],[82.97,-188.96],[86.95,-189.69],[90.96,-190.37],[95.0,-190.98],[99.07,-191.53],[103.17,-192.01],[107.29,-192.4],[111.43,-192.72],[115.58,-192.94],[119.73,-193.08],[123.88,-193.13],[128.03,-193.08],[132.16,-192.94],[136.27,-192.7],[140.36,-192.37],[144.42,-191.95],[148.44,-191.44],[152.42,-190.84],[156.36,-190.17],[160.25,-189.41],[164.09,-188.59],[167.88,-187.7],[171.62,-186.76],[175.31,-185.76],[178.94,-184.72],[182.53,-183.64],[186.07,-182.54],[189.57,-181.41],[193.04,-180.28],[196.47,-179.14],[199.87,-178.0],[203.26,-176.87],[206.64,-175.76],[210.02,-174.68],[213.4,-173.63],[216.8,-172.61],[220.22,-171.64],[223.68,-170.71],[227.19,-169.84],[230.75,-169.02],[234.38,-168.26],[238.08,-167.55],[241.86,-166.91],[245.73,-166.33],[249.7,-165.8],[253.78,-165.33],[257.96,-164.92],[262.26,-164.56],[266.68,-164.25],[271.22,-163.98],[275.88,-163.75],[280.67,-163.55],[285.57,-163.38],[290.59,-163.22],[295.73,-163.08],[300.97,-162.94],[306.3,-162.8],[311.73,-162.65],[317.24,-162.48],[322.82,-162.28],[328.46,-162.04],[334.14,-161.76],[339.84,-161.43],[345.56,-161.04],[351.27,-160.58],[356.96,-160.05],[362.61,-159.44],[368.21,-158.74],[373.73,-157.96],[379.15,-157.08],[384.46,-156.1],[389.64,-155.02],[394.67,-153.84],[399.54,-152.55],[404.23,-151.15],[408.71,-149.65],[412.99,-148.05],[417.04,-146.34],[420.85,-144.52],[424.42,-142.61],[427.73,-140.6],[430.77,-138.5],[433.55,-136.32],[436.05,-134.05],[438.27,-131.7],[440.22,-129.29],[441.89,-126.81],[443.29,-124.27],[444.42,-121.68],[445.29,-119.05],[445.91,-116.38],[446.28,-113.67],[446.42,-110.95],[446.34,-108.21],[446.06,-105.45],[445.58,-102.7],[444.93,-99.94],[444.13,-97.19],[443.18,-94.45],[442.11,-91.73],[440.94,-89.03],[439.68,-86.36],[438.35,-83.71],[436.98,-81.09],[435.58,-78.51],[434.16,-75.96],[432.75,-73.44],[431.35,-70.96],[430.0,-68.52],[428.69,-66.11],[427.44,-63.73],[426.26,-61.39],[425.16,-59.08],[424.16,-56.8],[423.25,-54.54],[422.44,-52.31],[421.73,-50.1],[421.13,-47.91],[420.63,-45.74],[420.24,-43.57],[419.94,-41.42],[419.74,-39.28],[419.62,-37.14],[419.58,-35.0]],[[420.98,-35.0],[420.93,-32.85],[420.95,-30.71],[421.03,-28.56],[421.15,-26.4],[421.3,-24.24],[421.46,-22.08],[421.63,-19.9],[421.77,-17.72],[421.88,-15.54],[421.95,-13.35],[421.95,-11.15],[421.87,-8.96],[421.69,-6.76],[421.41,-4.57],[421.0,-2.38],[420.46,-0.2],[419.77,1.97],[418.92,4.12],[417.91,6.25],[416.72,8.36],[415.35,10.45],[413.79,12.5],[412.04,14.52],[410.1,16.5],[407.97,18.44],[405.65,20.34],[403.15,22.19],[400.46,23.98],[397.6,25.73],[394.57,27.42],[391.39,29.05],[388.06,30.63],[384.59,32.16],[381.01,33.62],[377.31,35.03],[373.53,36.39],[369.67,37.69],[365.75,38.95],[361.78,40.16],[357.79,41.32],[353.79,42.45],[349.79,43.54],[345.82,44.61],[341.89,45.65],[338.01,46.68],[334.19,47.69],[330.46,48.71],[326.82,49.73],[323.29,50.75],[319.87,51.8],[316.58,52.87],[313.41,53.97],[310.39,55.11],[307.5,56.3],[304.76,57.53],[302.16,58.83],[299.7,60.18],[297.38,61.61],[295.21,63.11],[293.16,64.68],[291.24,66.33],[289.44,68.07],[287.75,69.89],[286.15,71.79],[284.64,73.78],[283.2,75.85],[281.82,78.0],[280.49,80.23],[279.19,82.53],[277.91,84.91],[276.63,87.35],[275.34,89.86],[274.01,92.42],[272.65,95.02],[271.22,97.67],[269.73,100.34],[268.15,103.04],[266.47,105.75],[264.68,108.47],[262.77,111.18],[260.73,113.87],[258.56,116.53],[256.24,119.16],[253.76,121.74],[251.14,124.27],[248.35,126.72],[245.4,129.11],[242.28,131.4],[239.01,133.61],[235.57,135.72],[231.98,137.71],[228.24,139.6],[224.34,141.36],[220.31,143.0],[216.14,144.51],[211.84,145.89],[207.43,147.14],[202.91,148.25],[198.29,149.23],[193.58,150.07],[188.8,150.78],[183.94,151.36],[179.03,151.81],[174.08,152.14],[169.08,152.35],[164.06,152.45],[159.03,152.44],[153.98,152.33],[148.94,152.13],[143.9,151.84],[138.88,151.48],[133.87,151.05],[128.9,150.56],[123.95,150.03],[119.03,149.45],[114.15,148.83],[109.31,148.2],[104.5,147.54],[99.73,146.88],[95.0,146.22],[90.3,145.56],[85.63,144.92],[81.0,144.29],[76.38,143.69],[71.79,143.12],[67.22,142.58],[62.65,142.08],[58.1,141.61],[53.55,141.18],[48.99,140.78],[44.43,140.43],[39.86,140.11],[35.28,139.83],[30.68,139.58],[26.06,139.35],[21.41,139.15],[16.74,138.97],[12.05,138.8],[7.33,138.64],[2.59,138.48],[-2.17,138.31],[-6.95,138.12],[-11.74,137.92],[-16.54,137.68],[-21.34,137.41],[-26.15,137.09],[-30.94,136.72],[-35.71,136.29],[-40.45,135.79],[-45.16,135.22],[-49.82,134.56],[-54.42,133.82],[-58.96,132.99],[-63.41,132.06],[-67.77,131.03],[-72.03,129.9],[-76.18,128.66],[-80.2,127.32],[-84.09,125.86],[-87.84,124.3],[-91.43,122.63],[-94.86,120.85],[-98.12,118.97],[-101.21,116.99],[-104.12,114.91],[-106.85,112.74],[-109.39,110.48],[-111.74,108.14],[-113.91,105.73],[-115.89,103.25],[-117.68,100.71],[-119.3,98.12],[-120.74,95.49],[-122.02,92.82],[-123.14,90.13],[-124.12,87.41],[-124.95,84.69],[-125.67,81.97],[-126.27,79.26],[-126.78,76.56],[-127.21,73.89],[-127.58,71.25],[-127.9,68.65],[-128.19,66.09],[-128.46,63.58],[-128.74,61.13],[-129.05,58.74],[-129.4,56.41],[-129.8,54.15],[-130.28,51.95],[-130.85,49.83],[-131.52,47.79],[-132.31,45.81],[-133.24,43.91],[-134.31,42.07],[-135.53,40.31],[-136.92,38.61],[-138.47,36.97],[-140.21,35.39],[-142.12,33.87],[-144.22,32.39],[-146.49,30.96],[-148.95,29.56],[-151.59,28.2],[-154.4,26.87],[-157.38,25.55],[-160.51,24.25],[-163.8,22.96],[-167.21,21.67],[-170.75,20.37],[-174.4,19.07],[-178.15,17.74],[-181.96,16.4],[-185.84,15.03],[-189.76,13.62],[-193.69,12.19],[-197.63,10.71],[-201.56,9.19],[-205.44,7.62],[-209.27,6.01],[-213.03,4.35],[-216.69,2.64],[-220.24,0.88],[-223.66,-0.93],[-226.94,-2.79],[-230.06,-4.69],[-233.0,-6.65],[-235.76,-8.65],[-238.33,-10.69],[-240.69,-12.77],[-242.83,-14.89],[-244.76,-17.04],[-246.46,-19.22],[-247.94,-21.42],[-249.2,-23.65],[-250.23,-25.9],[-251.04,-28.16],[-251.63,-30.43],[-252.01,-32.71],[-252.19,-35.0],[-252.18,-37.29],[-251.98,-39.57],[-251.62,-41.85],[-251.09,-44.12],[-250.42,-46.39],[-249.63,-48.64],[-248.72,-50.89],[-247.71,-53.12],[-246.62,-55.34],[-245.46,-57.55],[-244.25,-59.74],[-243.01,-61.93],[-241.75,-64.11],[-240.48,-66.28],[-239.23,-68.44],[-238.0,-70.6],[-236.8,-72.77],[-235.64,-74.93],[-234.54,-77.1],[-233.51,-79.28],[-232.55,-81.47],[-231.66,-83.67],[-230.85,-85.9],[-230.12,-88.14],[-229.47,-90.41],[-228.9,-92.7],[-228.41,-95.02],[-228.0,-97.37],[-227.64,-99.75],[-227.35,-102.17],[-227.11,-104.61],[-226.91,-107.1],[-226.74,-109.61],[-226.59,-112.16],[-226.43,-114.74],[-226.27,-117.34],[-226.08,-119.98],[-225.84,-122.63],[-225.55,-125.3],[-225.19,-127.99],[-224.73,-130.69],[-224.17,-133.39],[-223.49,-136.09],[-222.68,-138.78],[-221.71,-141.45],[-220.58,-144.1],[-219.27,-146.73],[-217.78,-149.31],[-216.09,-151.85],[-214.19,-154.34],[-212.07,-156.77],[-209.74,-159.13],[-207.17,-161.42],[-204.38,-163.62],[-201.36,-165.74],[-198.1,-167.76],[-194.62,-169.67],[-190.91,-171.48],[-186.98,-173.18],[-182.84,-174.76],[-178.49,-176.22],[-173.94,-177.56],[-169.2,-178.77],[-164.29,-179.86],[-159.21,-180.81],[-153.99,-181.65],[-148.63,-182.35],[-143.14,-182.93],[-137.56,-183.39],[-131.89,-183.74],[-126.14,-183.97],[-120.34,-184.09],[-114.5,-184.12],[-108.64,-184.05],[-102.77,-183.89],[-96.91,-183.65],[-91.07,-183.34],[-85.26,-182.97],[-79.51,-182.55],[-73.81,-182.08],[-68.19,-181.58],[-62.65,-181.06],[-57.2,-180.52],[-51.85,-179.97],[-46.6,-179.44],[-41.46,-178.91],[-36.43,-178.41],[-31.52,-177.94],[-26.72,-177.51],[-22.04,-177.13],[-17.47,-176.8],[-13.01,-176.53],[-8.65,-176.33],[-4.4,-176.2],[-0.24,-176.14],[3.82,-176.16],[7.81,-176.25],[11.72,-176.43],[15.57,-176.68],[19.35,-177.01],[23.09,-177.42],[26.8,-177.91],[30.47,-178.46],[34.12,-179.08],[37.76,-179.77],[41.39,-180.51],[45.03,-181.29],[48.68,-182.12],[52.34,-182.99],[56.03,-183.88],[59.76,-184.79],[63.51,-185.72],[67.3,-186.64],[71.13,-187.55],[75.01,-188.45],[78.92,-189.33],[82.88,-190.17],[86.88,-190.97],[90.92,-191.71],[95.0,-192.41],[99.11,-193.03],[103.26,-193.59],[107.42,-194.07],[111.61,-194.47],[115.82,-194.78],[120.03,-195.0],[124.25,-195.13],[128.46,-195.16],[132.67,-195.1],[136.86,-194.94],[141.03,-194.69],[145.17,-194.34],[149.28,-193.9],[153.35,-193.38],[157.38,-192.76],[161.37,-192.07],[165.31,-191.3],[169.2,-190.46],[173.04,-189.56],[176.82,-188.61],[180.56,-187.6],[184.24,-186.55],[187.88,-185.47],[191.48,-184.37],[195.04,-183.24],[198.56,-182.11],[202.06,-180.97],[205.53,-179.84],[208.99,-178.73],[212.45,-177.63],[215.91,-176.56],[219.38,-175.53],[222.87,-174.53],[226.4,-173.57],[229.96,-172.67],[233.58,-171.81],[237.26,-171.01],[241.01,-170.27],[244.83,-169.58],[248.75,-168.96],[252.76,-168.39],[256.87,-167.87],[261.09,-167.41],[265.42,-167.01],[269.87,-166.65],[274.43,-166.33],[279.12,-166.05],[283.93,-165.81],[288.86,-165.59],[293.91,-165.4],[299.07,-165.22],[304.34,-165.04],[309.7,-164.86],[315.16,-164.67],[320.71,-164.46],[326.32,-164.23],[331.99,-163.96],[337.71,-163.66],[343.46,-163.3],[349.22,-162.88],[354.98,-162.4],[360.72,-161.84],[366.42,-161.21],[372.07,-160.5],[377.65,-159.69],[383.14,-158.79],[388.51,-157.79],[393.75,-156.7],[398.85,-155.49],[403.78,-154.19],[408.53,-152.77],[413.08,-151.25],[417.42,-149.62],[421.54,-147.89],[425.41,-146.06],[429.04,-144.12],[432.4,-142.09],[435.5,-139.96],[438.32,-137.75],[440.86,-135.45],[443.12,-133.07],[445.1,-130.62],[446.79,-128.1],[448.2,-125.53],[449.34,-122.9],[450.21,-120.23],[450.82,-117.51],[451.17,-114.77],[451.29,-112.0],[451.17,-109.21],[450.84,-106.41],[450.31,-103.61],[449.6,-100.81],[448.72,-98.01],[447.69,-95.22],[446.53,-92.45],[445.25,-89.71],[443.89,-86.99],[442.45,-84.29],[440.96,-81.63],[439.42,-79.0],[437.88,-76.41],[436.33,-73.85],[434.79,-71.33],[433.29,-68.85],[431.84,-66.4],[430.44,-63.99],[429.12,-61.62],[427.87,-59.28],[426.72,-56.97],[425.67,-54.69],[424.72,-52.43],[423.88,-50.2],[423.15,-47.99],[422.53,-45.8],[422.02,-43.62],[421.61,-41.46],[421.31,-39.3],[421.1,-37.15],[420.98,-35.0]],[[422.32,-35.0],[422.2,-32.85],[422.16,-30.69],[422.19,-28.53],[422.27,-26.37],[422.39,-24.21],[422.53,-22.03],[422.69,-19.85],[422.84,-17.67],[422.97,-15.47],[423.06,-13.27],[423.1,-11.07],[423.07,-8.86],[422.95,-6.65],[422.74,-4.44],[422.41,-2.24],[421.95,-0.04],[421.35,2.15],[420.6,4.32],[419.69,6.48],[418.61,8.62],[417.35,10.73],[415.91,12.82],[414.28,14.87],[412.46,16.89],[410.45,18.86],[408.25,20.8],[405.86,22.69],[403.29,24.53],[400.54,26.32],[397.62,28.05],[394.54,29.74],[391.31,31.36],[387.93,32.93],[384.44,34.45],[380.82,35.9],[377.11,37.31],[373.32,38.66],[369.46,39.96],[365.54,41.22],[361.6,42.43],[357.63,43.6],[353.66,44.73],[349.71,45.84],[345.79,46.92],[341.91,47.99],[338.09,49.04],[334.35,50.09],[330.7,51.14],[327.14,52.2],[323.7,53.28],[320.37,54.37],[317.17,55.5],[314.1,56.67],[311.17,57.87],[308.38,59.13],[305.73,60.45],[303.23,61.82],[300.86,63.27],[298.63,64.78],[296.53,66.38],[294.56,68.05],[292.7,69.8],[290.96,71.64],[289.31,73.56],[287.75,75.56],[286.27,77.65],[284.85,79.82],[283.47,82.08],[282.13,84.41],[280.81,86.81],[279.5,89.28],[278.17,91.82],[276.81,94.41],[275.42,97.05],[273.97,99.73],[272.45,102.45],[270.84,105.19],[269.14,107.95],[267.33,110.71],[265.4,113.47],[263.34,116.21],[261.14,118.93],[258.8,121.61],[256.3,124.25],[253.65,126.83],[250.83,129.34],[247.85,131.78],[244.7,134.14],[241.39,136.4],[237.92,138.57],[234.29,140.62],[230.5,142.56],[226.55,144.38],[222.47,146.07],[218.24,147.63],[213.88,149.05],[209.41,150.34],[204.82,151.49],[200.13,152.5],[195.34,153.38],[190.48,154.11],[185.54,154.71],[180.55,155.18],[175.5,155.51],[170.42,155.73],[165.31,155.82],[160.18,155.81],[155.04,155.68],[149.9,155.46],[144.77,155.15],[139.65,154.76],[134.55,154.29],[129.48,153.76],[124.44,153.17],[119.44,152.53],[114.47,151.86],[109.54,151.16],[104.65,150.44],[99.81,149.7],[95.0,148.96],[90.23,148.23],[85.5,147.5],[80.8,146.79],[76.13,146.1],[71.49,145.44],[66.87,144.81],[62.26,144.22],[57.67,143.66],[53.09,143.14],[48.5,142.66],[43.92,142.22],[39.33,141.82],[34.73,141.45],[30.11,141.12],[25.47,140.82],[20.82,140.55],[16.15,140.3],[11.45,140.07],[6.73,139.84],[1.98,139.63],[-2.78,139.4],[-7.56,139.17],[-12.36,138.93],[-17.17,138.66],[-21.98,138.35],[-26.79,138.01],[-31.59,137.61],[-36.38,137.17],[-41.14,136.65],[-45.87,136.07],[-50.55,135.42],[-55.18,134.68],[-59.74,133.85],[-64.23,132.93],[-68.63,131.91],[-72.93,130.79],[-77.12,129.56],[-81.19,128.23],[-85.13,126.8],[-88.93,125.25],[-92.58,123.6],[-96.07,121.84],[-99.4,119.98],[-102.55,118.02],[-105.52,115.96],[-108.32,113.81],[-110.92,111.57],[-113.34,109.25],[-115.57,106.85],[-117.62,104.38],[-119.48,101.86],[-121.16,99.27],[-122.66,96.65],[-124.0,93.98],[-125.17,91.29],[-126.2,88.58],[-127.09,85.86],[-127.85,83.13],[-128.5,80.41],[-129.05,77.7],[-129.51,75.02],[-129.91,72.36],[-130.25,69.74],[-130.57,67.17],[-130.86,64.64],[-131.16,62.17],[-131.48,59.75],[-131.84,57.4],[-132.25,55.12],[-132.73,52.9],[-133.31,50.76],[-133.98,48.69],[-134.78,46.69],[-135.71,44.76],[-136.78,42.9],[-138.0,41.12],[-139.4,39.39],[-140.96,37.74],[-142.71,36.14],[-144.64,34.6],[-146.75,33.1],[-149.05,31.66],[-151.54,30.25],[-154.21,28.87],[-157.06,27.53],[-160.09,26.2],[-163.28,24.89],[-166.62,23.59],[-170.11,22.29],[-173.72,20.99],[-177.46,19.68],[-181.29,18.35],[-185.21,17.0],[-189.19,15.62],[-193.22,14.22],[-197.28,12.77],[-201.35,11.29],[-205.41,9.76],[-209.44,8.19],[-213.42,6.57],[-217.33,4.9],[-221.14,3.18],[-224.85,1.41],[-228.44,-0.42],[-231.88,-2.29],[-235.16,-4.22],[-238.27,-6.19],[-241.2,-8.21],[-243.92,-10.28],[-246.44,-12.39],[-248.74,-14.53],[-250.82,-16.72],[-252.67,-18.93],[-254.29,-21.17],[-255.67,-23.44],[-256.82,-25.72],[-257.75,-28.03],[-258.44,-30.34],[-258.92,-32.67],[-259.18,-35.0],[-259.24,-37.33],[-259.11,-39.66],[-258.79,-41.99],[-258.3,-44.31],[-257.65,-46.63],[-256.87,-48.93],[-255.95,-51.22],[-254.93,-53.5],[-253.81,-55.77],[-252.61,-58.02],[-251.35,-60.26],[-250.04,-62.49],[-248.7,-64.71],[-247.35,-66.92],[-246.0,-69.12],[-244.66,-71.32],[-243.34,-73.51],[-242.07,-75.71],[-240.84,-77.9],[-239.67,-80.11],[-238.56,-82.32],[-237.53,-84.55],[-236.57,-86.79],[-235.69,-89.05],[-234.89,-91.33],[-234.17,-93.63],[-233.52,-95.97],[-232.95,-98.33],[-232.45,-100.71],[-232.01,-103.14],[-231.62,-105.59],[-231.28,-108.07],[-230.97,-110.59],[-230.68,-113.14],[-230.39,-115.72],[-230.11,-118.33],[-229.8,-120.96],[-229.46,-123.62],[-229.06,-126.29],[-228.6,-128.98],[-228.06,-131.68],[-227.41,-134.39],[-226.65,-137.09],[-225.77,-139.79],[-224.74,-142.47],[-223.55,-145.13],[-222.19,-147.76],[-220.65,-150.36],[-218.91,-152.91],[-216.97,-155.42],[-214.82,-157.86],[-212.45,-160.24],[-209.86,-162.54],[-207.04,-164.77],[-204.0,-166.9],[-200.72,-168.94],[-197.21,-170.88],[-193.48,-172.71],[-189.53,-174.43],[-185.36,-176.03],[-180.99,-177.51],[-176.41,-178.87],[-171.65,-180.1],[-166.7,-181.21],[-161.59,-182.18],[-156.33,-183.03],[-150.93,-183.75],[-145.41,-184.34],[-139.78,-184.81],[-134.06,-185.16],[-128.26,-185.4],[-122.41,-185.52],[-116.51,-185.55],[-110.59,-185.47],[-104.65,-185.31],[-98.72,-185.06],[-92.82,-184.74],[-86.94,-184.35],[-81.12,-183.91],[-75.35,-183.42],[-69.65,-182.9],[-64.04,-182.35],[-58.52,-181.78],[-53.09,-181.21],[-47.77,-180.63],[-42.56,-180.08],[-37.47,-179.54],[-32.49,-179.04],[-27.62,-178.57],[-22.88,-178.15],[-18.25,-177.79],[-13.73,-177.49],[-9.32,-177.25],[-5.02,-177.08],[-0.82,-176.99],[3.29,-176.98],[7.31,-177.05],[11.26,-177.2],[15.14,-177.44],[18.96,-177.76],[22.72,-178.16],[26.45,-178.63],[30.14,-179.19],[33.81,-179.81],[37.46,-180.5],[41.11,-181.25],[44.77,-182.06],[48.43,-182.91],[52.11,-183.81],[55.81,-184.73],[59.55,-185.68],[63.31,-186.65],[67.12,-187.62],[70.97,-188.59],[74.86,-189.55],[78.8,-190.49],[82.78,-191.39],[86.81,-192.26],[90.89,-193.09],[95.0,-193.85],[99.15,-194.56],[103.34,-195.2],[107.56,-195.76],[111.8,-196.24],[116.06,-196.64],[120.34,-196.95],[124.62,-197.16],[128.91,-197.28],[133.19,-197.3],[137.46,-197.22],[141.71,-197.05],[145.94,-196.78],[150.14,-196.41],[154.3,-195.95],[158.43,-195.41],[162.51,-194.77],[166.55,-194.06],[170.54,-193.28],[174.48,-192.42],[178.37,-191.51],[182.2,-190.54],[185.99,-189.52],[189.73,-188.47],[193.43,-187.38],[197.08,-186.27],[200.7,-185.15],[204.28,-184.01],[207.85,-182.88],[211.39,-181.76],[214.93,-180.65],[218.47,-179.56],[222.01,-178.5],[225.58,-177.48],[229.17,-176.49],[232.79,-175.56],[236.47,-174.66],[240.2,-173.82],[243.99,-173.04],[247.87,-172.31],[251.82,-171.63],[255.87,-171.02],[260.01,-170.45],[264.26,-169.95],[268.62,-169.49],[273.1,-169.08],[277.69,-168.71],[282.4,-168.39],[287.23,-168.1],[292.19,-167.83],[297.25,-167.59],[302.44,-167.36],[307.73,-167.14],[313.12,-166.92],[318.6,-166.69],[324.17,-166.45],[329.81,-166.18],[335.51,-165.88],[341.26,-165.54],[347.05,-165.15],[352.85,-164.71],[358.65,-164.2],[364.44,-163.62],[370.19,-162.96],[375.89,-162.22],[381.52,-161.4],[387.05,-160.47],[392.48,-159.46],[397.79,-158.34],[402.94,-157.12],[407.94,-155.79],[412.75,-154.36],[417.36,-152.81],[421.76,-151.17],[425.94,-149.41],[429.87,-147.55],[433.55,-145.59],[436.97,-143.54],[440.11,-141.38],[442.98,-139.14],[445.56,-136.81],[447.86,-134.4],[449.86,-131.92],[451.58,-129.37],[453.01,-126.76],[454.16,-124.09],[455.02,-121.38],[455.62,-118.63],[455.96,-115.84],[456.05,-113.03],[455.9,-110.2],[455.53,-107.35],[454.95,-104.5],[454.17,-101.65],[453.22,-98.81],[452.11,-95.98],[450.86,-93.16],[449.49,-90.37],[448.02,-87.6],[446.47,-84.86],[444.86,-82.16],[443.21,-79.48],[441.53,-76.85],[439.84,-74.25],[438.17,-71.69],[436.53,-69.17],[434.93,-66.69],[433.38,-64.25],[431.91,-61.84],[430.53,-59.47],[429.23,-57.13],[428.04,-54.83],[426.95,-52.55],[425.97,-50.3],[425.11,-48.07],[424.37,-45.86],[423.74,-43.67],[423.23,-41.49],[422.82,-39.32],[422.52,-37.16],[422.32,-35.0]],[[423.61,-35.0],[423.42,-32.84],[423.32,-30.68],[423.3,-28.51],[423.34,-26.34],[423.43,-24.17],[423.56,-21.99],[423.71,-19.81],[423.86,-17.61],[424.01,-15.41],[424.13,-13.2],[424.21,-10.99],[424.23,-8.77],[424.17,-6.55],[424.03,-4.32],[423.78,-2.1],[423.4,0.11],[422.9,2.32],[422.25,4.52],[421.45,6.7],[420.48,8.87],[419.34,11.01],[418.01,13.13],[416.51,15.22],[414.81,17.27],[412.92,19.29],[410.85,21.26],[408.58,23.19],[406.13,25.08],[403.5,26.91],[400.7,28.7],[397.73,30.43],[394.6,32.1],[391.33,33.72],[387.93,35.28],[384.4,36.79],[380.77,38.24],[377.05,39.65],[373.25,41.0],[369.39,42.3],[365.49,43.56],[361.57,44.78],[357.63,45.96],[353.7,47.11],[349.8,48.23],[345.93,49.34],[342.11,50.43],[338.36,51.52],[334.7,52.6],[331.12,53.69],[327.65,54.8],[324.29,55.93],[321.05,57.08],[317.94,58.27],[314.97,59.5],[312.13,60.79],[309.43,62.12],[306.87,63.52],[304.45,64.98],[302.16,66.52],[300.01,68.12],[297.98,69.81],[296.07,71.58],[294.27,73.44],[292.56,75.37],[290.95,77.4],[289.42,79.51],[287.94,81.7],[286.52,83.97],[285.14,86.33],[283.78,88.75],[282.42,91.25],[281.05,93.82],[279.66,96.44],[278.24,99.11],[276.75,101.83],[275.2,104.58],[273.57,107.36],[271.84,110.16],[270.0,112.97],[268.05,115.77],[265.96,118.56],[263.74,121.33],[261.36,124.06],[258.84,126.75],[256.16,129.39],[253.31,131.96],[250.3,134.46],[247.12,136.87],[243.77,139.19],[240.26,141.41],[236.58,143.51],[232.74,145.51],[228.75,147.38],[224.61,149.12],[220.33,150.72],[215.91,152.19],[211.37,153.52],[206.71,154.71],[201.95,155.76],[197.09,156.66],[192.15,157.42],[187.13,158.03],[182.05,158.52],[176.92,158.86],[171.74,159.08],[166.54,159.17],[161.32,159.15],[156.09,159.01],[150.85,158.77],[145.62,158.43],[140.41,158.0],[135.22,157.5],[130.06,156.92],[124.93,156.28],[119.83,155.59],[114.78,154.86],[109.77,154.09],[104.8,153.3],[99.88,152.49],[95.0,151.68],[90.16,150.86],[85.37,150.05],[80.61,149.26],[75.88,148.48],[71.19,147.73],[66.52,147.01],[61.88,146.32],[57.25,145.68],[52.63,145.07],[48.02,144.5],[43.41,143.97],[38.8,143.48],[34.19,143.03],[29.56,142.62],[24.91,142.24],[20.25,141.9],[15.57,141.58],[10.87,141.28],[6.15,140.99],[1.4,140.72],[-3.37,140.45],[-8.15,140.17],[-12.95,139.88],[-17.76,139.57],[-22.58,139.23],[-27.39,138.86],[-32.21,138.45],[-37.0,137.98],[-41.78,137.46],[-46.52,136.87],[-51.23,136.21],[-55.88,135.47],[-60.47,134.65],[-64.99,133.73],[-69.43,132.72],[-73.77,131.62],[-78.0,130.41],[-82.12,129.1],[-86.11,127.68],[-89.97,126.16],[-93.68,124.53],[-97.23,122.8],[-100.62,120.96],[-103.84,119.02],[-106.88,116.98],[-109.74,114.85],[-112.42,112.63],[-114.91,110.33],[-117.21,107.95],[-119.32,105.5],[-121.25,102.99],[-123.0,100.42],[-124.57,97.8],[-125.97,95.15],[-127.21,92.46],[-128.29,89.75],[-129.24,87.02],[-130.05,84.3],[-130.75,81.57],[-131.34,78.86],[-131.85,76.16],[-132.28,73.49],[-132.66,70.86],[-133.0,68.27],[-133.33,65.73],[-133.65,63.23],[-133.99,60.8],[-134.36,58.43],[-134.78,56.12],[-135.28,53.88],[-135.86,51.72],[-136.54,49.62],[-137.34,47.6],[-138.28,45.65],[-139.35,43.77],[-140.59,41.96],[-141.99,40.22],[-143.56,38.54],[-145.32,36.92],[-147.26,35.36],[-149.4,33.85],[-151.72,32.39],[-154.24,30.96],[-156.94,29.58],[-159.84,28.22],[-162.9,26.88],[-166.15,25.56],[-169.55,24.25],[-173.1,22.94],[-176.79,21.63],[-180.61,20.31],[-184.53,18.98],[-188.55,17.62],[-192.63,16.24],[-196.78,14.82],[-200.96,13.37],[-205.15,11.88],[-209.35,10.35],[-213.51,8.77],[-217.64,7.14],[-221.69,5.46],[-225.66,3.73],[-229.53,1.94],[-233.27,0.1],[-236.88,-1.79],[-240.32,-3.74],[-243.6,-5.73],[-246.68,-7.78],[-249.57,-9.87],[-252.24,-12.0],[-254.7,-14.18],[-256.93,-16.39],[-258.92,-18.64],[-260.68,-20.92],[-262.19,-23.22],[-263.47,-25.55],[-264.51,-27.89],[-265.31,-30.25],[-265.88,-32.62],[-266.22,-35.0],[-266.35,-37.38],[-266.28,-39.76],[-266.01,-42.13],[-265.55,-44.51],[-264.93,-46.87],[-264.15,-49.22],[-263.23,-51.56],[-262.19,-53.88],[-261.04,-56.2],[-259.8,-58.5],[-258.48,-60.78],[-257.11,-63.05],[-255.7,-65.31],[-254.25,-67.56],[-252.8,-69.8],[-251.35,-72.03],[-249.92,-74.26],[-248.52,-76.49],[-247.16,-78.71],[-245.85,-80.94],[-244.6,-83.18],[-243.41,-85.42],[-242.3,-87.68],[-241.26,-89.96],[-240.3,-92.25],[-239.42,-94.57],[-238.61,-96.91],[-237.88,-99.28],[-237.22,-101.67],[-236.62,-104.1],[-236.08,-106.55],[-235.59,-109.04],[-235.14,-111.56],[-234.71,-114.11],[-234.29,-116.69],[-233.88,-119.29],[-233.45,-121.93],[-232.99,-124.58],[-232.48,-127.26],[-231.92,-129.95],[-231.28,-132.65],[-230.55,-135.35],[-229.71,-138.06],[-228.75,-140.76],[-227.65,-143.45],[-226.4,-146.11],[-224.98,-148.76],[-223.39,-151.36],[-221.61,-153.93],[-219.63,-156.44],[-217.45,-158.9],[-215.05,-161.3],[-212.43,-163.62],[-209.59,-165.86],[-206.51,-168.01],[-203.22,-170.07],[-199.69,-172.03],[-195.94,-173.88],[-191.97,-175.62],[-187.78,-177.25],[-183.38,-178.75],[-178.78,-180.13],[-173.99,-181.38],[-169.02,-182.5],[-163.89,-183.5],[-158.59,-184.36],[-153.16,-185.1],[-147.6,-185.7],[-141.93,-186.18],[-136.17,-186.54],[-130.32,-186.79],[-124.42,-186.92],[-118.47,-186.94],[-112.49,-186.87],[-106.5,-186.7],[-100.51,-186.44],[-94.54,-186.11],[-88.6,-185.71],[-82.71,-185.25],[-76.87,-184.75],[-71.11,-184.2],[-65.42,-183.63],[-59.83,-183.03],[-54.34,-182.43],[-48.95,-181.83],[-43.67,-181.24],[-38.51,-180.68],[-33.46,-180.14],[-28.54,-179.64],[-23.73,-179.19],[-19.04,-178.79],[-14.47,-178.45],[-10.01,-178.18],[-5.66,-177.99],[-1.41,-177.87],[2.74,-177.83],[6.81,-177.88],[10.79,-178.01],[14.7,-178.22],[18.55,-178.53],[22.34,-178.91],[26.09,-179.38],[29.8,-179.94],[33.49,-180.56],[37.16,-181.26],[40.83,-182.02],[44.5,-182.85],[48.17,-183.73],[51.87,-184.65],[55.58,-185.61],[59.33,-186.6],[63.11,-187.61],[66.94,-188.63],[70.8,-189.65],[74.72,-190.67],[78.68,-191.67],[82.69,-192.65],[86.74,-193.59],[90.85,-194.48],[95.0,-195.33],[99.19,-196.12],[103.42,-196.84],[107.69,-197.48],[111.99,-198.05],[116.31,-198.53],[120.65,-198.93],[125.0,-199.23],[129.36,-199.43],[133.71,-199.54],[138.06,-199.54],[142.4,-199.45],[146.72,-199.25],[151.01,-198.96],[155.27,-198.58],[159.49,-198.1],[163.68,-197.53],[167.82,-196.87],[171.91,-196.14],[175.95,-195.34],[179.94,-194.46],[183.88,-193.53],[187.77,-192.55],[191.62,-191.52],[195.41,-190.45],[199.16,-189.36],[202.88,-188.24],[206.56,-187.11],[210.21,-185.98],[213.84,-184.84],[217.46,-183.72],[221.08,-182.62],[224.7,-181.54],[228.33,-180.49],[231.99,-179.47],[235.68,-178.5],[239.41,-177.57],[243.19,-176.69],[247.04,-175.86],[250.95,-175.08],[254.95,-174.36],[259.03,-173.69],[263.21,-173.08],[267.49,-172.52],[271.87,-172.01],[276.37,-171.54],[280.99,-171.13],[285.72,-170.75],[290.57,-170.4],[295.54,-170.09],[300.62,-169.8],[305.82,-169.52],[311.13,-169.26],[316.54,-168.99],[322.04,-168.72],[327.63,-168.44],[333.29,-168.13],[339.02,-167.79],[344.8,-167.41],[350.61,-166.99],[356.44,-166.51],[362.28,-165.98],[368.11,-165.37],[373.9,-164.69],[379.64,-163.92],[385.32,-163.07],[390.91,-162.13],[396.39,-161.09],[401.74,-159.95],[406.95,-158.71],[412.0,-157.36],[416.87,-155.91],[421.54,-154.34],[426.0,-152.67],[430.23,-150.9],[434.22,-149.02],[437.95,-147.03],[441.42,-144.95],[444.62,-142.77],[447.53,-140.5],[450.15,-138.14],[452.48,-135.71],[454.51,-133.19],[456.25,-130.61],[457.7,-127.96],[458.86,-125.26],[459.73,-122.51],[460.32,-119.72],[460.65,-116.89],[460.71,-114.04],[460.53,-111.16],[460.12,-108.27],[459.48,-105.38],[458.65,-102.49],[457.63,-99.6],[456.45,-96.72],[455.11,-93.86],[453.65,-91.02],[452.08,-88.21],[450.42,-85.42],[448.69,-82.67],[446.92,-79.96],[445.11,-77.28],[443.29,-74.64],[441.48,-72.05],[439.7,-69.49],[437.96,-66.97],[436.27,-64.5],[434.66,-62.06],[433.13,-59.66],[431.69,-57.3],[430.35,-54.97],[429.13,-52.67],[428.02,-50.39],[427.03,-48.14],[426.16,-45.92],[425.42,-43.71],[424.8,-41.52],[424.29,-39.34],[423.9,-37.17],[423.61,-35.0]],[[424.86,-35.0],[424.6,-32.83],[424.44,-30.66],[424.36,-28.49],[424.36,-26.32],[424.43,-24.14],[424.54,-21.95],[424.68,-19.76],[424.85,-17.56],[425.01,-15.35],[425.16,-13.13],[425.28,-10.91],[425.35,-8.68],[425.36,-6.44],[425.29,-4.21],[425.11,-1.97],[424.83,0.27],[424.43,2.5],[423.88,4.72],[423.19,6.93],[422.34,9.12],[421.32,11.29],[420.12,13.44],[418.74,15.57],[417.17,17.66],[415.41,19.71],[413.47,21.73],[411.33,23.7],[409.01,25.63],[406.5,27.51],[403.82,29.35],[400.96,31.12],[397.95,32.85],[394.78,34.52],[391.48,36.14],[388.05,37.7],[384.5,39.2],[380.86,40.65],[377.13,42.06],[373.33,43.41],[369.49,44.72],[365.61,45.98],[361.71,47.21],[357.8,48.41],[353.92,49.58],[350.06,50.73],[346.25,51.86],[342.49,52.99],[338.81,54.11],[335.22,55.23],[331.72,56.37],[328.33,57.53],[325.06,58.71],[321.91,59.93],[318.89,61.19],[316.0,62.49],[313.25,63.85],[310.63,65.27],[308.15,66.75],[305.81,68.3],[303.59,69.93],[301.5,71.63],[299.53,73.42],[297.67,75.29],[295.91,77.24],[294.24,79.28],[292.65,81.41],[291.12,83.62],[289.65,85.91],[288.21,88.29],[286.8,90.74],[285.4,93.26],[283.99,95.85],[282.56,98.5],[281.09,101.2],[279.57,103.95],[277.99,106.74],[276.32,109.56],[274.56,112.39],[272.69,115.24],[270.7,118.09],[268.59,120.92],[266.33,123.74],[263.93,126.52],[261.38,129.26],[258.67,131.95],[255.79,134.57],[252.74,137.12],[249.52,139.58],[246.14,141.96],[242.58,144.23],[238.86,146.39],[234.98,148.43],[230.94,150.35],[226.74,152.14],[222.4,153.79],[217.92,155.31],[213.32,156.68],[208.59,157.9],[203.76,158.98],[198.82,159.91],[193.8,160.69],[188.7,161.33],[183.54,161.82],[178.32,162.18],[173.06,162.4],[167.76,162.49],[162.45,162.46],[157.12,162.31],[151.8,162.04],[146.47,161.68],[141.17,161.22],[135.89,160.68],[130.63,160.06],[125.41,159.37],[120.23,158.63],[115.09,157.83],[110.0,157.0],[104.95,156.14],[99.95,155.26],[95.0,154.36],[90.1,153.47],[85.24,152.57],[80.42,151.69],[75.64,150.83],[70.9,149.99],[66.18,149.17],[61.5,148.4],[56.84,147.66],[52.19,146.95],[47.55,146.29],[42.92,145.68],[38.29,145.1],[33.66,144.57],[29.02,144.08],[24.37,143.62],[19.7,143.2],[15.02,142.81],[10.31,142.44],[5.59,142.09],[0.85,141.76],[-3.92,141.43],[-8.7,141.11],[-13.5,140.78],[-18.31,140.43],[-23.13,140.06],[-27.96,139.66],[-32.78,139.22],[-37.58,138.74],[-42.37,138.21],[-47.13,137.61],[-51.86,136.94],[-56.53,136.21],[-61.15,135.39],[-65.7,134.48],[-70.18,133.49],[-74.56,132.4],[-78.84,131.21],[-83.0,129.92],[-87.05,128.52],[-90.96,127.02],[-94.73,125.42],[-98.34,123.71],[-101.8,121.9],[-105.08,119.98],[-108.2,117.97],[-111.13,115.87],[-113.88,113.67],[-116.44,111.39],[-118.82,109.04],[-121.01,106.61],[-123.01,104.11],[-124.83,101.56],[-126.47,98.95],[-127.94,96.31],[-129.25,93.63],[-130.4,90.92],[-131.4,88.2],[-132.28,85.48],[-133.03,82.75],[-133.67,80.03],[-134.23,77.33],[-134.7,74.65],[-135.12,72.01],[-135.5,69.4],[-135.86,66.84],[-136.21,64.33],[-136.57,61.88],[-136.96,59.49],[-137.41,57.16],[-137.92,54.9],[-138.51,52.71],[-139.2,50.6],[-140.02,48.55],[-140.96,46.58],[-142.04,44.67],[-143.29,42.84],[-144.7,41.08],[-146.28,39.38],[-148.05,37.74],[-150.01,36.16],[-152.16,34.63],[-154.51,33.15],[-157.06,31.71],[-159.8,30.31],[-162.72,28.93],[-165.84,27.58],[-169.13,26.25],[-172.59,24.93],[-176.21,23.61],[-179.97,22.29],[-183.86,20.96],[-187.87,19.62],[-191.98,18.26],[-196.17,16.87],[-200.42,15.45],[-204.72,13.99],[-209.04,12.49],[-213.36,10.95],[-217.66,9.36],[-221.92,7.72],[-226.13,6.03],[-230.25,4.28],[-234.27,2.48],[-238.17,0.62],[-241.93,-1.29],[-245.54,-3.25],[-248.97,-5.27],[-252.22,-7.34],[-255.26,-9.45],[-258.09,-11.62],[-260.7,-13.82],[-263.08,-16.07],[-265.22,-18.35],[-267.11,-20.66],[-268.76,-23.01],[-270.15,-25.37],[-271.3,-27.76],[-272.21,-30.16],[-272.87,-32.58],[-273.3,-35.0],[-273.5,-37.43],[-273.49,-39.85],[-273.26,-42.28],[-272.85,-44.7],[-272.24,-47.11],[-271.48,-49.51],[-270.55,-51.9],[-269.49,-54.27],[-268.31,-56.63],[-267.03,-58.98],[-265.66,-61.3],[-264.22,-63.62],[-262.72,-65.92],[-261.19,-68.21],[-259.64,-70.48],[-258.08,-72.75],[-256.52,-75.01],[-254.99,-77.27],[-253.49,-79.52],[-252.04,-81.78],[-250.64,-84.04],[-249.3,-86.3],[-248.03,-88.58],[-246.83,-90.87],[-245.7,-93.18],[-244.65,-95.5],[-243.68,-97.85],[-242.79,-100.23],[-241.96,-102.62],[-241.2,-105.05],[-240.51,-107.51],[-239.86,-110.0],[-239.25,-112.51],[-238.68,-115.06],[-238.12,-117.64],[-237.57,-120.24],[-237.01,-122.87],[-236.43,-125.52],[-235.81,-128.19],[-235.14,-130.88],[-234.4,-133.58],[-233.58,-136.29],[-232.66,-138.99],[-231.62,-141.7],[-230.45,-144.39],[-229.13,-147.06],[-227.66,-149.71],[-226.01,-152.32],[-224.19,-154.9],[-222.17,-157.42],[-219.95,-159.9],[-217.52,-162.3],[-214.87,-164.64],[-212.0,-166.9],[-208.91,-169.07],[-205.59,-171.15],[-202.05,-173.13],[-198.28,-175.0],[-194.29,-176.76],[-190.09,-178.41],[-185.67,-179.93],[-181.06,-181.33],[-176.25,-182.61],[-171.26,-183.75],[-166.09,-184.76],[-160.78,-185.64],[-155.31,-186.4],[-149.72,-187.02],[-144.02,-187.51],[-138.21,-187.89],[-132.33,-188.14],[-126.38,-188.28],[-120.38,-188.3],[-114.35,-188.23],[-108.31,-188.06],[-102.26,-187.8],[-96.23,-187.46],[-90.23,-187.05],[-84.28,-186.58],[-78.38,-186.06],[-72.55,-185.5],[-66.8,-184.9],[-61.14,-184.29],[-55.58,-183.66],[-50.13,-183.03],[-44.78,-182.42],[-39.55,-181.82],[-34.45,-181.25],[-29.46,-180.72],[-24.59,-180.24],[-19.85,-179.81],[-15.22,-179.44],[-10.71,-179.14],[-6.31,-178.91],[-2.02,-178.77],[2.18,-178.7],[6.28,-178.72],[10.3,-178.83],[14.25,-179.03],[18.12,-179.32],[21.94,-179.7],[25.72,-180.17],[29.45,-180.71],[33.16,-181.34],[36.85,-182.05],[40.53,-182.83],[44.22,-183.67],[47.91,-184.57],[51.61,-185.52],[55.35,-186.51],[59.11,-187.54],[62.91,-188.6],[66.75,-189.67],[70.63,-190.74],[74.57,-191.82],[78.55,-192.88],[82.59,-193.93],[86.67,-194.94],[90.81,-195.91],[95.0,-196.84],[99.23,-197.7],[103.51,-198.51],[107.83,-199.24],[112.18,-199.89],[116.56,-200.46],[120.96,-200.94],[125.38,-201.33],[129.81,-201.62],[134.25,-201.81],[138.68,-201.9],[143.1,-201.89],[147.51,-201.77],[151.89,-201.56],[156.25,-201.24],[160.57,-200.83],[164.86,-200.33],[169.1,-199.73],[173.3,-199.06],[177.45,-198.3],[181.54,-197.47],[185.59,-196.58],[189.59,-195.63],[193.53,-194.63],[197.43,-193.58],[201.28,-192.5],[205.1,-191.39],[208.87,-190.27],[212.62,-189.13],[216.34,-187.99],[220.04,-186.86],[223.74,-185.73],[227.44,-184.63],[231.14,-183.55],[234.86,-182.5],[238.62,-181.49],[242.4,-180.52],[246.24,-179.6],[250.13,-178.72],[254.09,-177.9],[258.12,-177.13],[262.24,-176.41],[266.45,-175.74],[270.76,-175.12],[275.17,-174.56],[279.69,-174.04],[284.32,-173.56],[289.07,-173.13],[293.93,-172.73],[298.91,-172.36],[304.01,-172.02],[309.22,-171.69],[314.54,-171.38],[319.96,-171.06],[325.48,-170.75],[331.08,-170.42],[336.77,-170.07],[342.51,-169.69],[348.31,-169.28],[354.15,-168.82],[360.01,-168.31],[365.87,-167.74],[371.73,-167.1],[377.56,-166.39],[383.34,-165.6],[389.05,-164.72],[394.68,-163.75],[400.21,-162.69],[405.62,-161.53],[410.88,-160.26],[415.98,-158.89],[420.9,-157.42],[425.62,-155.83],[430.14,-154.14],[434.42,-152.35],[438.46,-150.44],[442.25,-148.44],[445.76,-146.33],[449.0,-144.12],[451.96,-141.83],[454.62,-139.44],[456.98,-136.97],[459.05,-134.43],[460.81,-131.81],[462.28,-129.14],[463.44,-126.4],[464.32,-123.61],[464.91,-120.78],[465.22,-117.92],[465.26,-115.02],[465.05,-112.11],[464.6,-109.17],[463.92,-106.24],[463.03,-103.3],[461.95,-100.37],[460.69,-97.44],[459.28,-94.54],[457.73,-91.66],[456.06,-88.8],[454.29,-85.97],[452.45,-83.18],[450.56,-80.42],[448.63,-77.71],[446.68,-75.03],[444.74,-72.4],[442.82,-69.8],[440.94,-67.25],[439.11,-64.74],[437.35,-62.28],[435.68,-59.85],[434.1,-57.46],[432.62,-55.1],[431.26,-52.78],[430.02,-50.49],[428.9,-48.22],[427.92,-45.98],[427.06,-43.75],[426.32,-41.55],[425.72,-39.36],[425.23,-37.17],[424.86,-35.0]],[[426.08,-35.0],[425.75,-32.82],[425.52,-30.65],[425.4,-28.47],[425.36,-26.29],[425.39,-24.11],[425.49,-21.92],[425.63,-19.72],[425.8,-17.51],[425.99,-15.29],[426.17,-13.07],[426.33,-10.83],[426.45,-8.59],[426.52,-6.34],[426.52,-4.09],[426.43,-1.84],[426.24,0.42],[425.94,2.67],[425.5,4.91],[424.92,7.15],[424.19,9.37],[423.29,11.57],[422.22,13.76],[420.97,15.92],[419.54,18.04],[417.92,20.14],[416.11,22.2],[414.1,24.22],[411.91,26.19],[409.54,28.12],[406.98,30.0],[404.25,31.83],[401.35,33.61],[398.3,35.33],[395.1,37.0],[391.76,38.62],[388.31,40.18],[384.75,41.68],[381.09,43.14],[377.37,44.55],[373.58,45.91],[369.74,47.22],[365.89,48.5],[362.01,49.75],[358.15,50.96],[354.31,52.16],[350.5,53.33],[346.75,54.5],[343.06,55.66],[339.44,56.82],[335.92,57.99],[332.5,59.18],[329.19,60.4],[326.0,61.64],[322.93,62.93],[319.99,64.25],[317.19,65.63],[314.51,67.07],[311.97,68.57],[309.57,70.14],[307.29,71.79],[305.13,73.51],[303.1,75.31],[301.17,77.19],[299.35,79.16],[297.61,81.22],[295.96,83.36],[294.38,85.59],[292.85,87.9],[291.35,90.29],[289.89,92.76],[288.44,95.31],[286.98,97.92],[285.5,100.59],[283.99,103.32],[282.43,106.1],[280.8,108.92],[279.09,111.77],[277.3,114.64],[275.39,117.53],[273.37,120.41],[271.22,123.29],[268.94,126.15],[266.5,128.98],[263.92,131.76],[261.17,134.5],[258.25,137.17],[255.17,139.77],[251.92,142.29],[248.49,144.71],[244.89,147.03],[241.13,149.25],[237.2,151.34],[233.1,153.31],[228.85,155.14],[224.46,156.84],[219.92,158.39],[215.25,159.8],[210.45,161.06],[205.55,162.17],[200.54,163.13],[195.44,163.93],[190.26,164.59],[185.01,165.1],[179.71,165.46],[174.36,165.69],[168.98,165.78],[163.57,165.73],[158.15,165.57],[152.73,165.29],[147.32,164.9],[141.92,164.41],[136.54,163.83],[131.2,163.16],[125.89,162.43],[120.62,161.63],[115.4,160.77],[110.22,159.88],[105.1,158.95],[100.02,157.99],[95.0,157.02],[90.03,156.04],[85.11,155.06],[80.23,154.09],[75.4,153.14],[70.61,152.21],[65.85,151.3],[61.13,150.43],[56.43,149.6],[51.75,148.81],[47.09,148.05],[42.44,147.35],[37.79,146.68],[33.15,146.06],[28.5,145.49],[23.84,144.95],[19.17,144.45],[14.49,143.99],[9.78,143.55],[5.06,143.14],[0.32,142.75],[-4.44,142.37],[-9.22,142.0],[-14.02,141.62],[-18.83,141.23],[-23.65,140.83],[-28.48,140.4],[-33.3,139.94],[-38.12,139.44],[-42.92,138.9],[-47.69,138.29],[-52.44,137.62],[-57.14,136.89],[-61.78,136.08],[-66.37,135.18],[-70.87,134.2],[-75.29,133.12],[-79.62,131.95],[-83.83,130.68],[-87.93,129.31],[-91.9,127.84],[-95.73,126.26],[-99.41,124.58],[-102.93,122.8],[-106.29,120.92],[-109.47,118.94],[-112.48,116.86],[-115.31,114.69],[-117.95,112.44],[-120.4,110.1],[-122.67,107.7],[-124.75,105.22],[-126.65,102.69],[-128.37,100.1],[-129.92,97.47],[-131.3,94.8],[-132.52,92.11],[-133.59,89.39],[-134.53,86.67],[-135.34,83.94],[-136.04,81.22],[-136.65,78.52],[-137.18,75.83],[-137.65,73.18],[-138.07,70.56],[-138.46,67.99],[-138.84,65.47],[-139.23,63.0],[-139.65,60.59],[-140.12,58.24],[-140.65,55.96],[-141.26,53.75],[-141.97,51.61],[-142.8,49.54],[-143.75,47.54],[-144.85,45.62],[-146.1,43.76],[-147.52,41.97],[-149.12,40.25],[-150.91,38.59],[-152.88,36.99],[-155.06,35.44],[-157.43,33.94],[-160.0,32.49],[-162.77,31.07],[-165.73,29.68],[-168.89,28.32],[-172.23,26.97],[-175.74,25.64],[-179.42,24.31],[-183.25,22.98],[-187.22,21.64],[-191.32,20.29],[-195.51,18.91],[-199.8,17.51],[-204.16,16.08],[-208.57,14.62],[-213.01,13.11],[-217.45,11.56],[-221.89,9.96],[-226.29,8.31],[-230.63,6.6],[-234.9,4.84],[-239.07,3.03],[-243.13,1.15],[-247.04,-0.78],[-250.81,-2.76],[-254.4,-4.8],[-257.8,-6.89],[-261.0,-9.03],[-263.99,-11.23],[-266.75,-13.46],[-269.27,-15.74],[-271.55,-18.06],[-273.58,-20.41],[-275.36,-22.79],[-276.88,-25.2],[-278.14,-27.63],[-279.15,-30.07],[-279.91,-32.53],[-280.42,-35.0],[-280.69,-37.47],[-280.73,-39.95],[-280.56,-42.42],[-280.17,-44.89],[-279.59,-47.35],[-278.83,-49.8],[-277.91,-52.24],[-276.83,-54.66],[-275.62,-57.07],[-274.29,-59.46],[-272.86,-61.83],[-271.35,-64.19],[-269.77,-66.53],[-268.15,-68.86],[-266.49,-71.17],[-264.82,-73.47],[-263.14,-75.77],[-261.48,-78.05],[-259.84,-80.33],[-258.24,-82.61],[-256.68,-84.89],[-255.18,-87.18],[-253.75,-89.47],[-252.38,-91.78],[-251.09,-94.1],[-249.87,-96.43],[-248.73,-98.79],[-247.66,-101.17],[-246.67,-103.57],[-245.74,-106.0],[-244.88,-108.45],[-244.07,-110.94],[-243.31,-113.45],[-242.58,-116.0],[-241.88,-118.57],[-241.19,-121.17],[-240.5,-123.79],[-239.79,-126.44],[-239.05,-129.11],[-238.27,-131.79],[-237.43,-134.49],[-236.5,-137.19],[-235.49,-139.89],[-234.37,-142.6],[-233.13,-145.29],[-231.75,-147.96],[-230.21,-150.62],[-228.51,-153.24],[-226.64,-155.82],[-224.58,-158.35],[-222.32,-160.84],[-219.86,-163.26],[-217.19,-165.61],[-214.3,-167.88],[-211.18,-170.07],[-207.85,-172.17],[-204.29,-174.17],[-200.5,-176.06],[-196.5,-177.84],[-192.28,-179.51],[-187.86,-181.06],[-183.23,-182.48],[-178.4,-183.78],[-173.39,-184.94],[-168.21,-185.98],[-162.87,-186.88],[-157.39,-187.65],[-151.77,-188.29],[-146.04,-188.8],[-140.2,-189.19],[-134.28,-189.45],[-128.29,-189.6],[-122.25,-189.63],[-116.18,-189.56],[-110.08,-189.4],[-103.99,-189.14],[-97.9,-188.79],[-91.85,-188.38],[-85.83,-187.9],[-79.88,-187.37],[-73.99,-186.79],[-68.17,-186.18],[-62.45,-185.54],[-56.83,-184.89],[-51.31,-184.24],[-45.9,-183.6],[-40.61,-182.97],[-35.44,-182.38],[-30.4,-181.82],[-25.47,-181.3],[-20.67,-180.84],[-15.99,-180.45],[-11.43,-180.12],[-6.98,-179.87],[-2.64,-179.69],[1.6,-179.6],[5.74,-179.6],[9.8,-179.69],[13.77,-179.88],[17.68,-180.15],[21.53,-180.52],[25.33,-180.98],[29.09,-181.53],[32.82,-182.16],[36.53,-182.87],[40.23,-183.66],[43.92,-184.52],[47.63,-185.45],[51.35,-186.43],[55.1,-187.45],[58.88,-188.52],[62.69,-189.62],[66.55,-190.74],[70.46,-191.87],[74.41,-193.0],[78.42,-194.13],[82.48,-195.24],[86.6,-196.32],[90.77,-197.37],[95.0,-198.37],[99.28,-199.32],[103.6,-200.21],[107.97,-201.03],[112.37,-201.77],[116.81,-202.42],[121.28,-202.99],[125.77,-203.47],[130.28,-203.84],[134.79,-204.12],[139.31,-204.3],[143.82,-204.37],[148.32,-204.33],[152.8,-204.19],[157.25,-203.95],[161.67,-203.61],[166.06,-203.17],[170.41,-202.64],[174.71,-202.02],[178.97,-201.31],[183.17,-200.53],[187.33,-199.68],[191.43,-198.76],[195.48,-197.79],[199.49,-196.76],[203.44,-195.7],[207.36,-194.6],[211.23,-193.48],[215.07,-192.34],[218.88,-191.19],[222.67,-190.05],[226.45,-188.91],[230.22,-187.78],[234.0,-186.67],[237.79,-185.59],[241.6,-184.54],[245.45,-183.53],[249.34,-182.56],[253.28,-181.64],[257.28,-180.76],[261.35,-179.94],[265.5,-179.16],[269.74,-178.44],[274.07,-177.76],[278.5,-177.14],[283.04,-176.56],[287.68,-176.03],[292.45,-175.54],[297.32,-175.08],[302.31,-174.65],[307.42,-174.25],[312.64,-173.87],[317.96,-173.5],[323.39,-173.14],[328.92,-172.77],[334.53,-172.39],[340.22,-172.0],[345.98,-171.58],[351.79,-171.12],[357.65,-170.62],[363.53,-170.08],[369.41,-169.47],[375.3,-168.8],[381.15,-168.06],[386.97,-167.24],[392.72,-166.34],[398.39,-165.34],[403.95,-164.26],[409.4,-163.07],[414.71,-161.78],[419.85,-160.39],[424.82,-158.89],[429.6,-157.29],[434.16,-155.57],[438.49,-153.75],[442.58,-151.83],[446.42,-149.8],[449.98,-147.67],[453.27,-145.44],[456.26,-143.12],[458.96,-140.7],[461.36,-138.21],[463.46,-135.63],[465.25,-132.99],[466.73,-130.28],[467.91,-127.51],[468.79,-124.68],[469.37,-121.82],[469.68,-118.91],[469.7,-115.98],[469.47,-113.02],[468.98,-110.05],[468.26,-107.07],[467.32,-104.09],[466.17,-101.12],[464.85,-98.15],[463.35,-95.21],[461.72,-92.28],[459.95,-89.38],[458.09,-86.51],[456.14,-83.68],[454.13,-80.88],[452.08,-78.12],[450.01,-75.41],[447.94,-72.74],[445.88,-70.11],[443.86,-67.52],[441.9,-64.98],[440.0,-62.49],[438.19,-60.03],[436.47,-57.61],[434.85,-55.23],[433.36,-52.89],[431.98,-50.58],[430.74,-48.29],[429.63,-46.03],[428.66,-43.8],[427.82,-41.58],[427.11,-39.37],[426.53,-37.18],[426.08,-35.0]],[[427.28,-35.0],[426.87,-32.81],[426.58,-30.63],[426.41,-28.45],[426.33,-26.27],[426.34,-24.08],[426.42,-21.88],[426.55,-19.67],[426.73,-17.46],[426.94,-15.24],[427.15,-13.0],[427.35,-10.76],[427.53,-8.51],[427.66,-6.25],[427.74,-3.98],[427.74,-1.71],[427.64,0.57],[427.44,2.84],[427.11,5.11],[426.65,7.37],[426.04,9.62],[425.27,11.86],[424.33,14.07],[423.22,16.27],[421.92,18.43],[420.44,20.57],[418.77,22.67],[416.91,24.74],[414.85,26.76],[412.61,28.74],[410.19,30.67],[407.58,32.55],[404.81,34.39],[401.87,36.16],[398.78,37.89],[395.55,39.56],[392.19,41.17],[388.72,42.74],[385.15,44.25],[381.49,45.71],[377.77,47.12],[373.99,48.49],[370.17,49.82],[366.34,51.12],[362.5,52.38],[358.67,53.62],[354.87,54.84],[351.12,56.05],[347.42,57.25],[343.79,58.45],[340.25,59.66],[336.8,60.89],[333.45,62.13],[330.22,63.41],[327.1,64.72],[324.11,66.07],[321.24,67.47],[318.51,68.93],[315.91,70.45],[313.44,72.04],[311.09,73.7],[308.87,75.44],[306.76,77.25],[304.77,79.15],[302.88,81.14],[301.08,83.21],[299.36,85.36],[297.71,87.6],[296.11,89.93],[294.56,92.34],[293.04,94.83],[291.53,97.39],[290.01,100.02],[288.48,102.72],[286.92,105.47],[285.31,108.28],[283.64,111.12],[281.89,114.0],[280.05,116.91],[278.11,119.82],[276.05,122.75],[273.87,125.66],[271.54,128.56],[269.07,131.43],[266.45,134.26],[263.66,137.04],[260.71,139.76],[257.59,142.41],[254.29,144.98],[250.83,147.45],[247.19,149.82],[243.37,152.08],[239.39,154.22],[235.25,156.23],[230.94,158.11],[226.49,159.85],[221.89,161.44],[217.15,162.89],[212.29,164.19],[207.31,165.33],[202.23,166.31],[197.06,167.14],[191.8,167.82],[186.47,168.34],[181.08,168.71],[175.64,168.94],[170.17,169.02],[164.68,168.97],[159.17,168.79],[153.65,168.49],[148.15,168.08],[142.66,167.56],[137.19,166.94],[131.76,166.23],[126.36,165.45],[121.01,164.59],[115.7,163.68],[110.44,162.72],[105.24,161.72],[100.09,160.69],[95.0,159.64],[89.96,158.58],[84.98,157.52],[80.05,156.46],[75.16,155.42],[70.32,154.39],[65.52,153.4],[60.76,152.43],[56.03,151.51],[51.33,150.62],[46.64,149.78],[41.97,148.98],[37.31,148.22],[32.65,147.52],[28.0,146.86],[23.33,146.24],[18.66,145.66],[13.98,145.12],[9.27,144.62],[4.56,144.14],[-0.18,143.69],[-4.94,143.25],[-9.72,142.83],[-14.51,142.41],[-19.32,141.98],[-24.14,141.55],[-28.96,141.09],[-33.79,140.61],[-38.61,140.09],[-43.42,139.53],[-48.21,138.92],[-52.97,138.25],[-57.69,137.52],[-62.37,136.71],[-66.98,135.83],[-71.52,134.86],[-75.98,133.8],[-80.35,132.65],[-84.62,131.41],[-88.77,130.07],[-92.79,128.62],[-96.69,127.07],[-100.43,125.42],[-104.02,123.67],[-107.45,121.82],[-110.72,119.87],[-113.8,117.82],[-116.71,115.69],[-119.43,113.46],[-121.97,111.16],[-124.32,108.78],[-126.49,106.33],[-128.47,103.82],[-130.27,101.25],[-131.9,98.64],[-133.36,95.98],[-134.66,93.3],[-135.8,90.6],[-136.81,87.88],[-137.69,85.16],[-138.46,82.44],[-139.13,79.73],[-139.71,77.04],[-140.23,74.38],[-140.7,71.75],[-141.13,69.17],[-141.56,66.63],[-141.99,64.15],[-142.44,61.72],[-142.93,59.35],[-143.49,57.05],[-144.12,54.82],[-144.85,52.66],[-145.69,50.57],[-146.66,48.55],[-147.77,46.6],[-149.04,44.72],[-150.48,42.91],[-152.09,41.17],[-153.89,39.49],[-155.88,37.86],[-158.08,36.29],[-160.47,34.78],[-163.07,33.3],[-165.87,31.86],[-168.87,30.46],[-172.07,29.08],[-175.45,27.72],[-179.02,26.37],[-182.75,25.03],[-186.65,23.69],[-190.69,22.34],[-194.86,20.97],[-199.15,19.59],[-203.53,18.18],[-207.99,16.74],[-212.51,15.26],[-217.06,13.74],[-221.63,12.18],[-226.19,10.57],[-230.72,8.9],[-235.2,7.18],[-239.61,5.41],[-243.93,3.58],[-248.14,1.69],[-252.21,-0.26],[-256.12,-2.26],[-259.87,-4.33],[-263.43,-6.44],[-266.78,-8.61],[-269.92,-10.83],[-272.83,-13.1],[-275.5,-15.41],[-277.92,-17.76],[-280.08,-20.15],[-281.99,-22.57],[-283.63,-25.02],[-285.0,-27.49],[-286.11,-29.98],[-286.96,-32.48],[-287.56,-35.0],[-287.9,-37.52],[-288.0,-40.05],[-287.87,-42.57],[-287.52,-45.08],[-286.97,-47.59],[-286.21,-50.09],[-285.28,-52.58],[-284.19,-55.05],[-282.94,-57.5],[-281.57,-59.94],[-280.08,-62.36],[-278.5,-64.76],[-276.84,-67.14],[-275.13,-69.51],[-273.36,-71.86],[-271.57,-74.19],[-269.77,-76.52],[-267.97,-78.83],[-266.19,-81.14],[-264.44,-83.45],[-262.73,-85.75],[-261.06,-88.06],[-259.46,-90.37],[-257.92,-92.68],[-256.46,-95.01],[-255.06,-97.36],[-253.74,-99.72],[-252.5,-102.1],[-251.33,-104.51],[-250.23,-106.93],[-249.2,-109.39],[-248.23,-111.87],[-247.3,-114.38],[-246.42,-116.92],[-245.56,-119.48],[-244.73,-122.07],[-243.9,-124.69],[-243.06,-127.33],[-242.2,-129.99],[-241.3,-132.67],[-240.35,-135.36],[-239.32,-138.06],[-238.22,-140.76],[-237.01,-143.46],[-235.69,-146.15],[-234.24,-148.83],[-232.64,-151.48],[-230.89,-154.1],[-228.97,-156.69],[-226.87,-159.24],[-224.57,-161.73],[-222.08,-164.16],[-219.38,-166.52],[-216.46,-168.81],[-213.33,-171.02],[-209.98,-173.13],[-206.41,-175.15],[-202.61,-177.07],[-198.6,-178.87],[-194.37,-180.56],[-189.93,-182.13],[-185.29,-183.58],[-180.46,-184.9],[-175.44,-186.09],[-170.24,-187.14],[-164.89,-188.07],[-159.38,-188.86],[-153.75,-189.52],[-147.99,-190.05],[-142.13,-190.45],[-136.18,-190.73],[-130.15,-190.89],[-124.08,-190.93],[-117.96,-190.87],[-111.83,-190.71],[-105.68,-190.45],[-99.55,-190.11],[-93.44,-189.69],[-87.38,-189.2],[-81.36,-188.66],[-75.42,-188.07],[-69.55,-187.45],[-63.76,-186.79],[-58.08,-186.13],[-52.5,-185.46],[-47.03,-184.79],[-41.68,-184.14],[-36.45,-183.52],[-31.35,-182.93],[-26.37,-182.39],[-21.51,-181.91],[-16.78,-181.48],[-12.17,-181.13],[-7.67,-180.85],[-3.29,-180.65],[0.99,-180.54],[5.18,-180.52],[9.27,-180.59],[13.28,-180.76],[17.22,-181.02],[21.1,-181.38],[24.92,-181.83],[28.71,-182.38],[32.46,-183.01],[36.19,-183.74],[39.9,-184.54],[43.62,-185.42],[47.34,-186.36],[51.08,-187.37],[54.84,-188.43],[58.64,-189.53],[62.47,-190.68],[66.35,-191.84],[70.28,-193.03],[74.25,-194.22],[78.29,-195.41],[82.38,-196.59],[86.53,-197.74],[90.74,-198.86],[95.0,-199.94],[99.32,-200.97],[103.69,-201.94],[108.11,-202.85],[112.57,-203.67],[117.07,-204.42],[121.61,-205.08],[126.17,-205.64],[130.75,-206.11],[135.35,-206.47],[139.95,-206.73],[144.54,-206.88],[149.13,-206.93],[153.71,-206.87],[158.26,-206.71],[162.79,-206.44],[167.28,-206.06],[171.74,-205.59],[176.15,-205.03],[180.51,-204.38],[184.83,-203.64],[189.09,-202.83],[193.31,-201.95],[197.47,-201.0],[201.58,-200.0],[205.64,-198.95],[209.65,-197.86],[213.62,-196.75],[217.56,-195.61],[221.46,-194.45],[225.34,-193.29],[229.2,-192.13],[233.06,-190.98],[236.91,-189.84],[240.76,-188.73],[244.64,-187.64],[248.54,-186.59],[252.49,-185.57],[256.47,-184.6],[260.51,-183.67],[264.62,-182.79],[268.8,-181.95],[273.07,-181.17],[277.42,-180.44],[281.87,-179.75],[286.42,-179.11],[291.08,-178.52],[295.85,-177.96],[300.74,-177.44],[305.73,-176.96],[310.84,-176.5],[316.06,-176.06],[321.39,-175.63],[326.82,-175.21],[332.35,-174.79],[337.97,-174.36],[343.66,-173.92],[349.43,-173.45],[355.25,-172.95],[361.11,-172.41],[367.0,-171.83],[372.91,-171.18],[378.81,-170.48],[384.69,-169.7],[390.53,-168.85],[396.31,-167.92],[402.01,-166.9],[407.61,-165.78],[413.09,-164.57],[418.44,-163.26],[423.63,-161.85],[428.64,-160.33],[433.46,-158.7],[438.07,-156.96],[442.45,-155.12],[446.59,-153.17],[450.47,-151.12],[454.08,-148.97],[457.4,-146.71],[460.44,-144.37],[463.18,-141.93],[465.61,-139.41],[467.74,-136.8],[469.55,-134.13],[471.05,-131.38],[472.25,-128.58],[473.13,-125.73],[473.72,-122.83],[474.02,-119.89],[474.03,-116.92],[473.77,-113.92],[473.25,-110.91],[472.49,-107.89],[471.5,-104.87],[470.3,-101.85],[468.91,-98.85],[467.34,-95.86],[465.62,-92.89],[463.77,-89.95],[461.81,-87.04],[459.76,-84.16],[457.64,-81.33],[455.47,-78.53],[453.27,-75.78],[451.08,-73.07],[448.89,-70.41],[446.74,-67.79],[444.64,-65.22],[442.6,-62.69],[440.65,-60.21],[438.8,-57.77],[437.05,-55.36],[435.42,-53.0],[433.92,-50.67],[432.55,-48.36],[431.32,-46.09],[430.23,-43.84],[429.28,-41.61],[428.48,-39.39],[427.81,-37.19],[427.28,-35.0]],[[428.45,-35.0],[427.98,-32.81],[427.63,-30.62],[427.4,-28.43],[427.28,-26.24],[427.26,-24.05],[427.33,-21.84],[427.46,-19.63],[427.65,-17.41],[427.87,-15.18],[428.12,-12.94],[428.36,-10.69],[428.6,-8.42],[428.8,-6.15],[428.95,-3.87],[429.03,-1.58],[429.03,0.72],[428.93,3.01],[428.72,5.3],[428.38,7.59],[427.89,9.87],[427.26,12.14],[426.46,14.39],[425.48,16.62],[424.33,18.83],[422.99,21.01],[421.46,23.15],[419.74,25.26],[417.83,27.34],[415.73,29.37],[413.44,31.35],[410.97,33.29],[408.32,35.17],[405.51,37.01],[402.54,38.79],[399.42,40.52],[396.16,42.19],[392.78,43.81],[389.29,45.38],[385.71,46.9],[382.05,48.37],[378.33,49.79],[374.57,51.18],[370.77,52.53],[366.96,53.84],[363.15,55.13],[359.37,56.4],[355.61,57.65],[351.91,58.89],[348.27,60.14],[344.7,61.38],[341.22,62.64],[337.84,63.92],[334.56,65.22],[331.39,66.56],[328.35,67.94],[325.42,69.37],[322.63,70.85],[319.96,72.39],[317.42,73.99],[315.0,75.67],[312.71,77.42],[310.53,79.25],[308.47,81.16],[306.5,83.16],[304.63,85.24],[302.84,87.41],[301.11,89.66],[299.45,92.0],[297.83,94.43],[296.24,96.93],[294.67,99.51],[293.1,102.16],[291.51,104.87],[289.9,107.65],[288.23,110.47],[286.51,113.34],[284.71,116.25],[282.83,119.18],[280.84,122.13],[278.74,125.09],[276.51,128.04],[274.15,130.98],[271.64,133.88],[268.97,136.76],[266.15,139.58],[263.16,142.34],[259.99,145.03],[256.66,147.64],[253.14,150.16],[249.46,152.58],[245.6,154.88],[241.57,157.07],[237.37,159.12],[233.01,161.05],[228.5,162.83],[223.84,164.46],[219.04,165.94],[214.11,167.27],[209.06,168.44],[203.91,169.45],[198.65,170.3],[193.32,171.0],[187.9,171.53],[182.43,171.91],[176.91,172.15],[171.35,172.23],[165.77,172.17],[160.17,171.98],[154.57,171.66],[148.97,171.22],[143.39,170.66],[137.84,170.01],[132.31,169.26],[126.83,168.43],[121.39,167.52],[116.0,166.55],[110.66,165.52],[105.38,164.45],[100.16,163.35],[95.0,162.22],[89.9,161.08],[84.85,159.93],[79.86,158.79],[74.93,157.66],[70.04,156.54],[65.2,155.45],[60.4,154.4],[55.64,153.38],[50.91,152.39],[46.2,151.46],[41.51,150.57],[36.84,149.72],[32.17,148.93],[27.51,148.18],[22.84,147.48],[18.17,146.83],[13.48,146.21],[8.79,145.64],[4.07,145.1],[-0.66,144.58],[-5.41,144.09],[-10.18,143.62],[-14.97,143.15],[-19.77,142.68],[-24.59,142.21],[-29.41,141.73],[-34.24,141.22],[-39.07,140.69],[-43.89,140.12],[-48.69,139.5],[-53.46,138.83],[-58.21,138.1],[-62.9,137.3],[-67.55,136.43],[-72.12,135.47],[-76.62,134.44],[-81.04,133.31],[-85.35,132.09],[-89.56,130.78],[-93.64,129.36],[-97.6,127.85],[-101.41,126.23],[-105.08,124.51],[-108.58,122.7],[-111.92,120.78],[-115.09,118.77],[-118.08,116.67],[-120.89,114.48],[-123.52,112.2],[-125.96,109.85],[-128.21,107.43],[-130.28,104.94],[-132.17,102.4],[-133.89,99.81],[-135.43,97.17],[-136.81,94.51],[-138.04,91.81],[-139.13,89.11],[-140.08,86.39],[-140.92,83.67],[-141.66,80.97],[-142.3,78.28],[-142.88,75.61],[-143.4,72.98],[-143.89,70.38],[-144.36,67.83],[-144.83,65.34],[-145.32,62.89],[-145.85,60.51],[-146.43,58.19],[-147.09,55.94],[-147.84,53.75],[-148.71,51.64],[-149.7,49.6],[-150.83,47.63],[-152.11,45.72],[-153.56,43.89],[-155.19,42.12],[-157.01,40.42],[-159.02,38.77],[-161.23,37.18],[-163.65,35.64],[-166.27,34.15],[-169.1,32.69],[-172.13,31.27],[-175.37,29.87],[-178.8,28.49],[-182.41,27.13],[-186.21,25.77],[-190.16,24.42],[-194.27,23.05],[-198.52,21.68],[-202.89,20.28],[-207.36,18.86],[-211.91,17.41],[-216.53,15.92],[-221.2,14.39],[-225.88,12.81],[-230.56,11.19],[-235.23,9.51],[-239.84,7.78],[-244.39,5.99],[-248.85,4.14],[-253.2,2.23],[-257.42,0.26],[-261.49,-1.76],[-265.39,-3.85],[-269.1,-5.99],[-272.6,-8.19],[-275.89,-10.44],[-278.94,-12.74],[-281.76,-15.08],[-284.31,-17.47],[-286.61,-19.89],[-288.64,-22.35],[-290.4,-24.84],[-291.88,-27.35],[-293.1,-29.89],[-294.04,-32.44],[-294.71,-35.0],[-295.13,-37.57],[-295.29,-40.14],[-295.21,-42.71],[-294.89,-45.28],[-294.35,-47.84],[-293.61,-50.38],[-292.67,-52.92],[-291.56,-55.44],[-290.28,-57.94],[-288.86,-60.42],[-287.32,-62.88],[-285.67,-65.33],[-283.92,-67.75],[-282.11,-70.16],[-280.24,-72.55],[-278.33,-74.92],[-276.4,-77.27],[-274.47,-79.62],[-272.54,-81.95],[-270.63,-84.28],[-268.76,-86.61],[-266.93,-88.93],[-265.16,-91.25],[-263.44,-93.59],[-261.8,-95.93],[-260.23,-98.28],[-258.73,-100.64],[-257.3,-103.03],[-255.95,-105.43],[-254.68,-107.86],[-253.47,-110.31],[-252.32,-112.79],[-251.23,-115.29],[-250.18,-117.82],[-249.17,-120.38],[-248.19,-122.96],[-247.21,-125.57],[-246.24,-128.2],[-245.25,-130.85],[-244.23,-133.52],[-243.16,-136.2],[-242.03,-138.89],[-240.83,-141.59],[-239.54,-144.28],[-238.14,-146.97],[-236.61,-149.65],[-234.95,-152.3],[-233.14,-154.93],[-231.17,-157.52],[-229.03,-160.07],[-226.7,-162.57],[-224.17,-165.01],[-221.44,-167.39],[-218.51,-169.69],[-215.36,-171.91],[-211.99,-174.05],[-208.41,-176.08],[-204.61,-178.02],[-200.59,-179.85],[-196.35,-181.56],[-191.91,-183.15],[-187.26,-184.62],[-182.42,-185.97],[-177.39,-187.18],[-172.19,-188.26],[-166.82,-189.21],[-161.31,-190.02],[-155.65,-190.7],[-149.88,-191.25],[-143.99,-191.67],[-138.02,-191.97],[-131.97,-192.14],[-125.86,-192.2],[-119.71,-192.15],[-113.54,-191.99],[-107.35,-191.74],[-101.18,-191.4],[-95.02,-190.98],[-88.91,-190.5],[-82.84,-189.95],[-76.84,-189.35],[-70.92,-188.72],[-65.08,-188.05],[-59.34,-187.37],[-53.7,-186.68],[-48.18,-186.0],[-42.77,-185.33],[-37.48,-184.68],[-32.32,-184.07],[-27.29,-183.51],[-22.38,-183.0],[-17.59,-182.55],[-12.93,-182.17],[-8.39,-181.86],[-3.96,-181.64],[0.37,-181.51],[4.59,-181.47],[8.72,-181.52],[12.76,-181.68],[16.74,-181.93],[20.64,-182.28],[24.5,-182.73],[28.3,-183.27],[32.08,-183.91],[35.83,-184.64],[39.57,-185.45],[43.3,-186.35],[47.04,-187.32],[50.8,-188.35],[54.58,-189.45],[58.39,-190.59],[62.24,-191.77],[66.14,-192.99],[70.09,-194.23],[74.09,-195.48],[78.15,-196.73],[82.27,-197.97],[86.45,-199.2],[90.7,-200.39],[95.0,-201.55],[99.36,-202.66],[103.78,-203.72],[108.26,-204.7],[112.78,-205.62],[117.34,-206.45],[121.94,-207.2],[126.57,-207.85],[131.23,-208.41],[135.91,-208.86],[140.59,-209.2],[145.28,-209.44],[149.97,-209.57],[154.64,-209.59],[159.29,-209.5],[163.92,-209.3],[168.52,-209.0],[173.09,-208.59],[177.61,-208.08],[182.08,-207.49],[186.51,-206.8],[190.89,-206.03],[195.21,-205.18],[199.48,-204.26],[203.7,-203.29],[207.87,-202.26],[211.99,-201.18],[216.06,-200.07],[220.09,-198.92],[224.09,-197.76],[228.06,-196.59],[232.0,-195.41],[235.93,-194.23],[239.86,-193.06],[243.79,-191.91],[247.72,-190.79],[251.69,-189.69],[255.68,-188.63],[259.71,-187.6],[263.79,-186.62],[267.94,-185.68],[272.15,-184.78],[276.44,-183.94],[280.81,-183.14],[285.28,-182.39],[289.85,-181.69],[294.51,-181.03],[299.29,-180.41],[304.17,-179.82],[309.17,-179.27],[314.28,-178.75],[319.49,-178.25],[324.82,-177.76],[330.25,-177.28],[335.77,-176.81],[341.39,-176.33],[347.08,-175.83],[352.85,-175.31],[358.67,-174.77],[364.54,-174.18],[370.44,-173.55],[376.35,-172.87],[382.26,-172.13],[388.16,-171.32],[394.02,-170.43],[399.82,-169.47],[405.54,-168.42],[411.17,-167.28],[416.69,-166.04],[422.07,-164.7],[427.3,-163.26],[432.35,-161.72],[437.21,-160.07],[441.86,-158.31],[446.28,-156.45],[450.47,-154.48],[454.39,-152.4],[458.04,-150.22],[461.41,-147.95],[464.49,-145.58],[467.26,-143.11],[469.73,-140.57],[471.88,-137.94],[473.72,-135.23],[475.25,-132.46],[476.45,-129.63],[477.35,-126.74],[477.94,-123.8],[478.23,-120.83],[478.23,-117.82],[477.96,-114.79],[477.41,-111.75],[476.61,-108.69],[475.58,-105.63],[474.33,-102.57],[472.87,-99.52],[471.24,-96.49],[469.44,-93.49],[467.51,-90.51],[465.45,-87.56],[463.3,-84.64],[461.07,-81.77],[458.79,-78.93],[456.48,-76.15],[454.16,-73.4],[451.85,-70.71],[449.57,-68.06],[447.33,-65.45],[445.17,-62.9],[443.08,-60.39],[441.09,-57.92],[439.21,-55.49],[437.45,-53.11],[435.82,-50.75],[434.33,-48.43],[432.98,-46.14],[431.78,-43.88],[430.73,-41.64],[429.82,-39.41],[429.07,-37.2],[428.45,-35.0]],[[429.62,-35.0],[429.07,-32.8],[428.66,-30.6],[428.39,-28.41],[428.23,-26.22],[428.18,-24.01],[428.23,-21.81],[428.36,-19.59],[428.56,-17.36],[428.8,-15.13],[429.08,-12.88],[429.37,-10.61],[429.66,-8.34],[429.93,-6.05],[430.16,-3.75],[430.33,-1.45],[430.43,0.86],[430.44,3.18],[430.34,5.5],[430.12,7.81],[429.76,10.12],[429.26,12.42],[428.6,14.71],[427.77,16.98],[426.76,19.22],[425.57,21.45],[424.19,23.64],[422.62,25.8],[420.85,27.92],[418.9,30.0],[416.75,32.04],[414.42,34.03],[411.9,35.97],[409.22,37.87],[406.36,39.71],[403.36,41.49],[400.21,43.23],[396.93,44.91],[393.53,46.54],[390.03,48.11],[386.44,49.64],[382.78,51.13],[379.07,52.57],[375.31,53.97],[371.54,55.34],[367.75,56.68],[363.98,57.99],[360.23,59.29],[356.52,60.58],[352.87,61.86],[349.28,63.15],[345.77,64.44],[342.35,65.76],[339.02,67.09],[335.81,68.46],[332.71,69.86],[329.72,71.31],[326.86,72.82],[324.13,74.38],[321.51,76.0],[319.03,77.69],[316.66,79.46],[314.4,81.3],[312.26,83.23],[310.21,85.23],[308.26,87.33],[306.39,89.5],[304.6,91.77],[302.86,94.12],[301.17,96.55],[299.51,99.07],[297.87,101.66],[296.23,104.32],[294.58,107.06],[292.9,109.85],[291.18,112.69],[289.41,115.59],[287.56,118.52],[285.62,121.47],[283.58,124.45],[281.43,127.44],[279.16,130.42],[276.75,133.39],[274.2,136.33],[271.49,139.24],[268.62,142.1],[265.59,144.9],[262.38,147.64],[259.0,150.29],[255.44,152.85],[251.71,155.31],[247.8,157.66],[243.72,159.88],[239.47,161.98],[235.05,163.95],[230.48,165.77],[225.76,167.44],[220.9,168.95],[215.9,170.31],[210.78,171.51],[205.56,172.55],[200.23,173.42],[194.81,174.13],[189.32,174.68],[183.77,175.07],[178.16,175.31],[172.52,175.39],[166.84,175.32],[161.16,175.12],[155.47,174.78],[149.78,174.31],[144.11,173.73],[138.47,173.04],[132.86,172.25],[127.29,171.37],[121.76,170.4],[116.29,169.37],[110.88,168.29],[105.52,167.15],[100.23,165.97],[95.0,164.77],[89.83,163.55],[84.73,162.31],[79.68,161.08],[74.7,159.86],[69.77,158.66],[64.89,157.47],[60.05,156.32],[55.26,155.21],[50.5,154.13],[45.77,153.1],[41.07,152.12],[36.38,151.18],[31.7,150.3],[27.03,149.47],[22.37,148.69],[17.69,147.95],[13.01,147.26],[8.32,146.61],[3.61,146.01],[-1.11,145.43],[-5.85,144.88],[-10.61,144.35],[-15.39,143.84],[-20.19,143.34],[-25.0,142.83],[-29.83,142.32],[-34.66,141.79],[-39.49,141.24],[-44.31,140.65],[-49.12,140.03],[-53.91,139.35],[-58.68,138.63],[-63.4,137.84],[-68.07,136.98],[-72.68,136.04],[-77.22,135.03],[-81.68,133.93],[-86.05,132.73],[-90.31,131.45],[-94.45,130.07],[-98.47,128.59],[-102.36,127.01],[-106.1,125.33],[-109.68,123.55],[-113.1,121.67],[-116.36,119.7],[-119.44,117.63],[-122.34,115.47],[-125.05,113.24],[-127.59,110.92],[-129.93,108.53],[-132.1,106.07],[-134.08,103.55],[-135.89,100.99],[-137.52,98.37],[-138.99,95.73],[-140.31,93.05],[-141.48,90.35],[-142.51,87.65],[-143.43,84.94],[-144.24,82.23],[-144.96,79.55],[-145.6,76.88],[-146.18,74.24],[-146.73,71.64],[-147.25,69.08],[-147.76,66.56],[-148.3,64.11],[-148.86,61.71],[-149.48,59.37],[-150.17,57.1],[-150.96,54.89],[-151.84,52.75],[-152.86,50.69],[-154.01,48.69],[-155.31,46.77],[-156.78,44.91],[-158.43,43.12],[-160.26,41.39],[-162.29,39.72],[-164.52,38.11],[-166.96,36.55],[-169.61,35.03],[-172.47,33.55],[-175.53,32.11],[-178.8,30.69],[-182.27,29.3],[-185.93,27.92],[-189.78,26.55],[-193.79,25.17],[-197.97,23.8],[-202.29,22.4],[-206.73,20.99],[-211.29,19.56],[-215.94,18.09],[-220.65,16.59],[-225.42,15.05],[-230.22,13.46],[-235.02,11.82],[-239.8,10.13],[-244.55,8.38],[-249.23,6.57],[-253.83,4.71],[-258.32,2.78],[-262.68,0.79],[-266.9,-1.26],[-270.94,-3.37],[-274.8,-5.54],[-278.45,-7.76],[-281.89,-10.04],[-285.08,-12.37],[-288.03,-14.75],[-290.73,-17.17],[-293.16,-19.63],[-295.31,-22.13],[-297.18,-24.66],[-298.78,-27.22],[-300.09,-29.8],[-301.13,-32.39],[-301.88,-35.0],[-302.37,-37.62],[-302.59,-40.24],[-302.55,-42.86],[-302.27,-45.47],[-301.75,-48.08],[-301.01,-50.68],[-300.07,-53.26],[-298.94,-55.83],[-297.63,-58.38],[-296.16,-60.9],[-294.56,-63.41],[-292.83,-65.9],[-291.01,-68.37],[-289.09,-70.81],[-287.12,-73.23],[-285.09,-75.64],[-283.03,-78.03],[-280.95,-80.4],[-278.88,-82.76],[-276.81,-85.12],[-274.78,-87.46],[-272.78,-89.8],[-270.83,-92.14],[-268.94,-94.48],[-267.11,-96.83],[-265.35,-99.19],[-263.67,-101.56],[-262.06,-103.95],[-260.53,-106.35],[-259.07,-108.77],[-257.68,-111.22],[-256.36,-113.69],[-255.09,-116.19],[-253.88,-118.71],[-252.7,-121.25],[-251.56,-123.83],[-250.44,-126.42],[-249.32,-129.04],[-248.2,-131.68],[-247.05,-134.34],[-245.87,-137.01],[-244.64,-139.7],[-243.34,-142.38],[-241.95,-145.07],[-240.47,-147.75],[-238.87,-150.43],[-237.14,-153.08],[-235.27,-155.71],[-233.25,-158.3],[-231.06,-160.86],[-228.69,-163.36],[-226.14,-165.81],[-223.38,-168.2],[-220.43,-170.52],[-217.26,-172.75],[-213.89,-174.9],[-210.29,-176.96],[-206.48,-178.92],[-202.46,-180.76],[-198.22,-182.5],[-193.78,-184.12],[-189.13,-185.61],[-184.29,-186.98],[-179.26,-188.22],[-174.05,-189.33],[-168.68,-190.3],[-163.15,-191.14],[-157.49,-191.84],[-151.7,-192.42],[-145.8,-192.86],[-139.81,-193.17],[-133.73,-193.37],[-127.6,-193.44],[-121.42,-193.4],[-115.22,-193.26],[-109.0,-193.02],[-102.78,-192.68],[-96.59,-192.27],[-90.43,-191.78],[-84.32,-191.23],[-78.27,-190.63],[-72.29,-189.99],[-66.4,-189.31],[-60.6,-188.62],[-54.91,-187.92],[-49.33,-187.22],[-43.87,-186.53],[-38.53,-185.87],[-33.31,-185.24],[-28.23,-184.65],[-23.26,-184.11],[-18.43,-183.64],[-13.72,-183.24],[-9.13,-182.92],[-4.65,-182.67],[-0.29,-182.52],[3.98,-182.46],[8.14,-182.5],[12.22,-182.64],[16.23,-182.88],[20.17,-183.22],[24.05,-183.67],[27.88,-184.21],[31.68,-184.85],[35.45,-185.59],[39.21,-186.42],[42.97,-187.33],[46.73,-188.32],[50.5,-189.38],[54.3,-190.51],[58.13,-191.69],[62.01,-192.91],[65.92,-194.18],[69.89,-195.47],[73.92,-196.77],[78.01,-198.09],[82.16,-199.4],[86.37,-200.69],[90.65,-201.96],[95.0,-203.2],[99.41,-204.39],[103.88,-205.53],[108.4,-206.6],[112.98,-207.6],[117.61,-208.52],[122.28,-209.36],[126.98,-210.1],[131.72,-210.74],[136.48,-211.28],[141.25,-211.72],[146.03,-212.04],[150.81,-212.25],[155.58,-212.35],[160.34,-212.34],[165.07,-212.21],[169.78,-211.97],[174.45,-211.63],[179.09,-211.19],[183.68,-210.64],[188.22,-210.0],[192.71,-209.27],[197.14,-208.46],[201.53,-207.57],[205.85,-206.62],[210.13,-205.61],[214.35,-204.54],[218.53,-203.43],[222.66,-202.29],[226.75,-201.12],[230.81,-199.93],[234.84,-198.73],[238.85,-197.53],[242.85,-196.33],[246.85,-195.14],[250.85,-193.98],[254.87,-192.83],[258.91,-191.72],[262.99,-190.64],[267.12,-189.6],[271.3,-188.6],[275.54,-187.65],[279.85,-186.74],[284.24,-185.87],[288.72,-185.06],[293.3,-184.28],[297.97,-183.56],[302.75,-182.87],[307.63,-182.22],[312.62,-181.6],[317.72,-181.01],[322.93,-180.44],[328.25,-179.89],[333.67,-179.35],[339.18,-178.82],[344.79,-178.28],[350.48,-177.73],[356.23,-177.16],[362.05,-176.56],[367.92,-175.93],[373.82,-175.25],[379.74,-174.53],[385.65,-173.75],[391.56,-172.9],[397.43,-171.98],[403.25,-170.98],[408.99,-169.9],[414.64,-168.73],[420.19,-167.46],[425.6,-166.1],[430.85,-164.64],[435.94,-163.07],[440.84,-161.4],[445.53,-159.62],[449.99,-157.73],[454.21,-155.74],[458.18,-153.64],[461.87,-151.44],[465.28,-149.14],[468.4,-146.75],[471.21,-144.26],[473.71,-141.69],[475.89,-139.03],[477.76,-136.3],[479.31,-133.5],[480.53,-130.64],[481.44,-127.72],[482.04,-124.75],[482.32,-121.75],[482.32,-118.71],[482.02,-115.64],[481.45,-112.56],[480.63,-109.46],[479.55,-106.36],[478.25,-103.27],[476.74,-100.18],[475.04,-97.12],[473.18,-94.07],[471.16,-91.05],[469.02,-88.06],[466.77,-85.11],[464.44,-82.2],[462.06,-79.33],[459.63,-76.5],[457.19,-73.73],[454.76,-71.0],[452.35,-68.32],[449.99,-65.68],[447.69,-63.1],[445.48,-60.56],[443.36,-58.07],[441.35,-55.62],[439.46,-53.21],[437.7,-50.84],[436.09,-48.5],[434.62,-46.2],[433.31,-43.92],[432.16,-41.66],[431.16,-39.43],[430.31,-37.21],[429.62,-35.0]],[[430.78,-35.0],[430.16,-32.79],[429.7,-30.59],[429.37,-28.39],[429.18,-26.19],[429.1,-23.98],[429.14,-21.77],[429.26,-19.55],[429.47,-17.32],[429.74,-15.07],[430.05,-12.81],[430.38,-10.54],[430.73,-8.25],[431.07,-5.95],[431.37,-3.64],[431.64,-1.32],[431.83,1.01],[431.95,3.35],[431.97,5.69],[431.87,8.04],[431.65,10.38],[431.28,12.71],[430.76,15.03],[430.08,17.34],[429.22,19.63],[428.18,21.89],[426.95,24.13],[425.53,26.34],[423.92,28.51],[422.11,30.65],[420.11,32.74],[417.92,34.79],[415.55,36.79],[412.99,38.74],[410.27,40.64],[407.38,42.49],[404.34,44.29],[401.16,46.03],[397.86,47.72],[394.44,49.36],[390.93,50.95],[387.34,52.49],[383.68,53.99],[379.97,55.45],[376.23,56.87],[372.47,58.26],[368.71,59.63],[364.97,60.98],[361.26,62.31],[357.59,63.64],[353.98,64.96],[350.44,66.3],[346.98,67.64],[343.61,69.01],[340.35,70.41],[337.19,71.84],[334.14,73.32],[331.22,74.84],[328.41,76.42],[325.72,78.06],[323.15,79.77],[320.7,81.55],[318.37,83.4],[316.14,85.34],[314.01,87.36],[311.98,89.46],[310.03,91.65],[308.15,93.92],[306.33,96.28],[304.57,98.72],[302.83,101.25],[301.12,103.85],[299.41,106.52],[297.69,109.27],[295.94,112.07],[294.16,114.94],[292.32,117.85],[290.41,120.79],[288.42,123.77],[286.33,126.77],[284.13,129.78],[281.81,132.79],[279.35,135.79],[276.75,138.77],[273.99,141.71],[271.08,144.61],[268.0,147.45],[264.75,150.22],[261.32,152.91],[257.71,155.51],[253.93,158.01],[249.97,160.4],[245.84,162.66],[241.53,164.8],[237.06,166.8],[232.43,168.66],[227.65,170.37],[222.73,171.92],[217.66,173.31],[212.48,174.54],[207.18,175.6],[201.78,176.49],[196.29,177.22],[190.72,177.78],[185.08,178.18],[179.39,178.42],[173.66,178.5],[167.9,178.42],[162.13,178.21],[156.35,177.85],[150.58,177.36],[144.82,176.75],[139.09,176.02],[133.39,175.19],[127.74,174.26],[122.13,173.25],[116.58,172.16],[111.09,171.01],[105.66,169.8],[100.3,168.55],[95.0,167.27],[89.77,165.97],[84.61,164.66],[79.51,163.34],[74.47,162.03],[69.5,160.73],[64.58,159.46],[59.71,158.21],[54.88,157.0],[50.1,155.83],[45.35,154.71],[40.63,153.63],[35.93,152.61],[31.25,151.63],[26.57,150.71],[21.91,149.85],[17.24,149.03],[12.56,148.27],[7.88,147.55],[3.18,146.87],[-1.54,146.23],[-6.27,145.63],[-11.02,145.05],[-15.79,144.49],[-20.58,143.94],[-25.39,143.4],[-30.21,142.86],[-35.04,142.31],[-39.87,141.74],[-44.7,141.14],[-49.52,140.51],[-54.33,139.84],[-59.11,139.11],[-63.85,138.33],[-68.55,137.49],[-73.2,136.57],[-77.78,135.58],[-82.28,134.5],[-86.7,133.34],[-91.02,132.09],[-95.23,130.74],[-99.31,129.3],[-103.27,127.75],[-107.08,126.11],[-110.75,124.37],[-114.26,122.54],[-117.6,120.6],[-120.77,118.58],[-123.76,116.46],[-126.57,114.26],[-129.21,111.98],[-131.65,109.62],[-133.92,107.2],[-136.0,104.71],[-137.9,102.17],[-139.63,99.59],[-141.2,96.96],[-142.61,94.3],[-143.87,91.62],[-144.99,88.93],[-145.99,86.23],[-146.88,83.53],[-147.68,80.84],[-148.39,78.18],[-149.04,75.53],[-149.65,72.92],[-150.23,70.36],[-150.8,67.83],[-151.38,65.36],[-151.99,62.95],[-152.65,60.59],[-153.38,58.3],[-154.19,56.07],[-155.11,53.91],[-156.14,51.83],[-157.32,49.81],[-158.64,47.86],[-160.13,45.98],[-161.8,44.16],[-163.65,42.41],[-165.7,40.71],[-167.95,39.08],[-170.41,37.49],[-173.08,35.95],[-175.97,34.45],[-179.06,32.99],[-182.37,31.55],[-185.88,30.14],[-189.58,28.74],[-193.48,27.35],[-197.55,25.96],[-201.78,24.56],[-206.17,23.15],[-210.68,21.73],[-215.32,20.28],[-220.05,18.8],[-224.86,17.28],[-229.73,15.72],[-234.63,14.12],[-239.55,12.46],[-244.45,10.75],[-249.32,8.99],[-254.13,7.16],[-258.86,5.28],[-263.49,3.33],[-267.99,1.32],[-272.35,-0.75],[-276.53,-2.89],[-280.54,-5.08],[-284.33,-7.33],[-287.91,-9.64],[-291.24,-12.0],[-294.33,-14.42],[-297.16,-16.87],[-299.71,-19.37],[-301.99,-21.91],[-303.98,-24.48],[-305.68,-27.08],[-307.09,-29.7],[-308.22,-32.34],[-309.05,-35.0],[-309.61,-37.66],[-309.88,-40.33],[-309.89,-43.0],[-309.64,-45.67],[-309.14,-48.32],[-308.41,-50.97],[-307.46,-53.6],[-306.31,-56.22],[-304.97,-58.81],[-303.46,-61.39],[-301.79,-63.94],[-300.0,-66.47],[-298.08,-68.98],[-296.07,-71.46],[-293.98,-73.92],[-291.83,-76.36],[-289.64,-78.78],[-287.42,-81.18],[-285.2,-83.57],[-282.98,-85.95],[-280.77,-88.31],[-278.6,-90.67],[-276.48,-93.02],[-274.4,-95.38],[-272.39,-97.73],[-270.45,-100.1],[-268.57,-102.47],[-266.77,-104.86],[-265.05,-107.26],[-263.4,-109.68],[-261.83,-112.12],[-260.32,-114.58],[-258.88,-117.07],[-257.5,-119.58],[-256.16,-122.11],[-254.86,-124.67],[-253.58,-127.25],[-252.32,-129.86],[-251.06,-132.49],[-249.78,-135.13],[-248.48,-137.79],[-247.13,-140.46],[-245.73,-143.14],[-244.25,-145.82],[-242.68,-148.5],[-241.0,-151.16],[-239.21,-153.81],[-237.28,-156.44],[-235.2,-159.03],[-232.97,-161.59],[-230.56,-164.1],[-227.98,-166.56],[-225.2,-168.96],[-222.23,-171.29],[-219.05,-173.54],[-215.66,-175.71],[-212.06,-177.78],[-208.25,-179.76],[-204.22,-181.63],[-199.99,-183.39],[-195.54,-185.03],[-190.9,-186.55],[-186.06,-187.95],[-181.03,-189.21],[-175.83,-190.34],[-170.45,-191.35],[-164.93,-192.21],[-159.26,-192.94],[-153.46,-193.54],[-147.55,-194.01],[-141.54,-194.35],[-135.46,-194.56],[-129.3,-194.65],[-123.1,-194.63],[-116.87,-194.5],[-110.62,-194.27],[-104.37,-193.95],[-98.14,-193.54],[-91.94,-193.06],[-85.79,-192.51],[-79.69,-191.91],[-73.67,-191.27],[-67.73,-190.59],[-61.88,-189.88],[-56.14,-189.17],[-50.51,-188.46],[-44.99,-187.75],[-39.6,-187.07],[-34.33,-186.43],[-29.19,-185.82],[-24.18,-185.27],[-19.29,-184.78],[-14.53,-184.35],[-9.9,-184.01],[-5.38,-183.75],[-0.97,-183.58],[3.33,-183.5],[7.54,-183.52],[11.66,-183.65],[15.7,-183.88],[19.67,-184.21],[23.57,-184.66],[27.44,-185.2],[31.26,-185.85],[35.06,-186.59],[38.84,-187.43],[42.61,-188.36],[46.39,-189.37],[50.19,-190.46],[54.01,-191.62],[57.86,-192.83],[61.76,-194.1],[65.7,-195.41],[69.69,-196.75],[73.75,-198.12],[77.86,-199.49],[82.04,-200.86],[86.29,-202.23],[90.61,-203.57],[95.0,-204.89],[99.45,-206.16],[103.97,-207.37],[108.55,-208.53],[113.19,-209.62],[117.88,-210.63],[122.62,-211.55],[127.4,-212.39],[132.22,-213.12],[137.06,-213.75],[141.92,-214.27],[146.79,-214.68],[151.67,-214.97],[156.54,-215.15],[161.4,-215.21],[166.24,-215.16],[171.06,-214.99],[175.84,-214.71],[180.59,-214.33],[185.29,-213.84],[189.95,-213.24],[194.55,-212.56],[199.1,-211.78],[203.6,-210.93],[208.04,-210.0],[212.42,-209.01],[216.75,-207.95],[221.03,-206.85],[225.26,-205.7],[229.45,-204.52],[233.6,-203.32],[237.72,-202.1],[241.81,-200.87],[245.89,-199.64],[249.95,-198.42],[254.02,-197.21],[258.1,-196.02],[262.19,-194.85],[266.32,-193.72],[270.48,-192.62],[274.69,-191.56],[278.96,-190.54],[283.29,-189.56],[287.7,-188.63],[292.19,-187.75],[296.77,-186.9],[301.45,-186.1],[306.22,-185.34],[311.1,-184.62],[316.09,-183.93],[321.18,-183.27],[326.37,-182.64],[331.68,-182.02],[337.08,-181.42],[342.58,-180.82],[348.17,-180.22],[353.85,-179.61],[359.59,-178.98],[365.4,-178.33],[371.26,-177.65],[377.15,-176.93],[383.06,-176.16],[388.98,-175.33],[394.89,-174.45],[400.76,-173.49],[406.59,-172.46],[412.35,-171.34],[418.02,-170.14],[423.58,-168.85],[429.01,-167.46],[434.3,-165.97],[439.42,-164.37],[444.35,-162.68],[449.07,-160.87],[453.57,-158.97],[457.83,-156.95],[461.83,-154.83],[465.57,-152.61],[469.01,-150.29],[472.17,-147.88],[475.01,-145.37],[477.55,-142.77],[479.77,-140.09],[481.66,-137.33],[483.23,-134.51],[484.47,-131.62],[485.39,-128.67],[486.0,-125.67],[486.29,-122.63],[486.28,-119.56],[485.97,-116.46],[485.38,-113.35],[484.53,-110.22],[483.42,-107.08],[482.08,-103.95],[480.52,-100.83],[478.76,-97.72],[476.82,-94.64],[474.73,-91.58],[472.51,-88.56],[470.17,-85.57],[467.75,-82.62],[465.26,-79.72],[462.73,-76.86],[460.18,-74.05],[457.63,-71.28],[455.1,-68.57],[452.61,-65.91],[450.19,-63.3],[447.85,-60.74],[445.6,-58.22],[443.46,-55.75],[441.45,-53.32],[439.57,-50.93],[437.84,-48.57],[436.26,-46.25],[434.84,-43.96],[433.58,-41.69],[432.49,-39.45],[431.55,-37.22],[430.78,-35.0]],[[431.95,-35.0],[431.27,-32.79],[430.74,-30.58],[430.37,-28.37],[430.14,-26.16],[430.04,-23.95],[430.06,-21.74],[430.18,-19.51],[430.39,-17.27],[430.68,-15.01],[431.03,-12.75],[431.41,-10.46],[431.81,-8.17],[432.22,-5.85],[432.61,-3.52],[432.96,-1.18],[433.26,1.17],[433.48,3.53],[433.62,5.89],[433.65,8.26],[433.56,10.63],[433.33,13.0],[432.96,15.36],[432.42,17.7],[431.72,20.03],[430.83,22.34],[429.76,24.63],[428.5,26.89],[427.04,29.11],[425.38,31.3],[423.53,33.45],[421.49,35.56],[419.26,37.62],[416.84,39.63],[414.24,41.6],[411.48,43.51],[408.56,45.37],[405.49,47.17],[402.28,48.93],[398.96,50.63],[395.52,52.28],[392.0,53.88],[388.4,55.44],[384.74,56.96],[381.04,58.44],[377.31,59.89],[373.57,61.31],[369.83,62.7],[366.12,64.09],[362.44,65.46],[358.81,66.83],[355.24,68.2],[351.74,69.58],[348.33,70.98],[345.01,72.41],[341.79,73.87],[338.68,75.37],[335.68,76.92],[332.8,78.52],[330.04,80.17],[327.39,81.9],[324.85,83.69],[322.43,85.56],[320.12,87.5],[317.9,89.53],[315.78,91.64],[313.74,93.83],[311.78,96.11],[309.88,98.48],[308.02,100.93],[306.21,103.46],[304.41,106.07],[302.63,108.75],[300.83,111.51],[299.02,114.32],[297.16,117.2],[295.26,120.12],[293.29,123.09],[291.23,126.08],[289.09,129.1],[286.83,132.14],[284.45,135.17],[281.94,138.19],[279.29,141.2],[276.48,144.17],[273.52,147.1],[270.39,149.97],[267.09,152.78],[263.61,155.5],[259.96,158.14],[256.13,160.67],[252.12,163.1],[247.93,165.41],[243.57,167.58],[239.05,169.62],[234.36,171.51],[229.51,173.25],[224.53,174.83],[219.4,176.25],[214.14,177.51],[208.77,178.59],[203.3,179.51],[197.73,180.25],[192.09,180.83],[186.37,181.23],[180.6,181.47],[174.79,181.55],[168.95,181.47],[163.09,181.24],[157.22,180.87],[151.36,180.36],[145.52,179.71],[139.7,178.95],[133.92,178.08],[128.19,177.11],[122.5,176.04],[116.87,174.9],[111.3,173.68],[105.8,172.41],[100.36,171.09],[95.0,169.74],[89.71,168.36],[84.49,166.96],[79.34,165.56],[74.25,164.16],[69.23,162.77],[64.27,161.4],[59.37,160.06],[54.52,158.76],[49.71,157.5],[44.94,156.28],[40.2,155.11],[35.49,153.99],[30.8,152.93],[26.13,151.92],[21.46,150.97],[16.8,150.08],[12.13,149.23],[7.45,148.44],[2.76,147.7],[-1.94,147.0],[-6.67,146.33],[-11.41,145.7],[-16.17,145.09],[-20.95,144.51],[-25.75,143.93],[-30.56,143.36],[-35.39,142.78],[-40.22,142.2],[-45.05,141.59],[-49.88,140.95],[-54.7,140.28],[-59.5,139.56],[-64.27,138.79],[-69.0,137.96],[-73.68,137.06],[-78.3,136.09],[-82.85,135.04],[-87.32,133.91],[-91.69,132.69],[-95.96,131.38],[-100.12,129.98],[-104.15,128.47],[-108.04,126.88],[-111.79,125.18],[-115.38,123.39],[-118.82,121.5],[-122.08,119.51],[-125.17,117.44],[-128.09,115.28],[-130.82,113.04],[-133.37,110.72],[-135.74,108.33],[-137.93,105.88],[-139.93,103.37],[-141.77,100.81],[-143.44,98.21],[-144.94,95.57],[-146.3,92.91],[-147.52,90.23],[-148.61,87.54],[-149.59,84.86],[-150.46,82.17],[-151.26,79.51],[-151.98,76.87],[-152.66,74.25],[-153.3,71.68],[-153.93,69.14],[-154.57,66.66],[-155.23,64.23],[-155.93,61.86],[-156.7,59.55],[-157.55,57.3],[-158.5,55.12],[-159.57,53.01],[-160.77,50.97],[-162.12,48.99],[-163.63,47.09],[-165.31,45.24],[-167.19,43.47],[-169.26,41.75],[-171.53,40.08],[-174.01,38.47],[-176.7,36.91],[-179.61,35.39],[-182.74,33.9],[-186.07,32.44],[-189.62,31.0],[-193.36,29.58],[-197.3,28.17],[-201.42,26.76],[-205.71,25.35],[-210.16,23.92],[-214.74,22.48],[-219.45,21.01],[-224.27,19.52],[-229.17,17.98],[-234.13,16.41],[-239.13,14.79],[-244.15,13.12],[-249.17,11.39],[-254.15,9.61],[-259.09,7.76],[-263.94,5.86],[-268.7,3.89],[-273.34,1.86],[-277.83,-0.24],[-282.16,-2.4],[-286.3,-4.62],[-290.23,-6.9],[-293.94,-9.24],[-297.42,-11.64],[-300.64,-14.08],[-303.6,-16.58],[-306.27,-19.11],[-308.67,-21.69],[-310.77,-24.3],[-312.58,-26.94],[-314.09,-29.61],[-315.3,-32.3],[-316.22,-35.0],[-316.84,-37.71],[-317.17,-40.43],[-317.22,-43.15],[-317.01,-45.86],[-316.53,-48.57],[-315.8,-51.26],[-314.85,-53.94],[-313.67,-56.61],[-312.3,-59.25],[-310.74,-61.87],[-309.02,-64.47],[-307.14,-67.04],[-305.14,-69.59],[-303.03,-72.11],[-300.83,-74.61],[-298.56,-77.08],[-296.24,-79.53],[-293.88,-81.96],[-291.5,-84.38],[-289.11,-86.77],[-286.74,-89.16],[-284.4,-91.53],[-282.09,-93.9],[-279.83,-96.26],[-277.63,-98.63],[-275.49,-101.0],[-273.43,-103.37],[-271.44,-105.76],[-269.52,-108.16],[-267.68,-110.57],[-265.92,-113.0],[-264.23,-115.45],[-262.6,-117.93],[-261.04,-120.43],[-259.53,-122.95],[-258.06,-125.49],[-256.63,-128.06],[-255.22,-130.65],[-253.82,-133.27],[-252.41,-135.9],[-250.98,-138.54],[-249.52,-141.2],[-248.01,-143.87],[-246.43,-146.53],[-244.77,-149.2],[-243.02,-151.86],[-241.15,-154.5],[-239.16,-157.13],[-237.03,-159.72],[-234.76,-162.28],[-232.31,-164.8],[-229.69,-167.26],[-226.89,-169.67],[-223.9,-172.01],[-220.71,-174.27],[-217.31,-176.46],[-213.71,-178.55],[-209.9,-180.55],[-205.88,-182.44],[-201.65,-184.22],[-197.21,-185.89],[-192.57,-187.44],[-187.74,-188.86],[-182.72,-190.15],[-177.52,-191.32],[-172.15,-192.35],[-166.63,-193.24],[-160.96,-194.0],[-155.16,-194.63],[-149.25,-195.12],[-143.23,-195.48],[-137.14,-195.72],[-130.97,-195.84],[-124.75,-195.84],[-118.49,-195.73],[-112.22,-195.51],[-105.94,-195.2],[-99.68,-194.81],[-93.45,-194.34],[-87.25,-193.79],[-81.12,-193.2],[-75.05,-192.55],[-69.07,-191.87],[-63.18,-191.16],[-57.39,-190.44],[-51.7,-189.72],[-46.14,-189.0],[-40.69,-188.31],[-35.38,-187.65],[-30.19,-187.03],[-25.12,-186.46],[-20.19,-185.95],[-15.38,-185.51],[-10.7,-185.15],[-6.13,-184.87],[-1.68,-184.68],[2.66,-184.59],[6.91,-184.6],[11.06,-184.71],[15.14,-184.93],[19.14,-185.26],[23.08,-185.7],[26.97,-186.24],[30.82,-186.89],[34.64,-187.65],[38.44,-188.5],[42.24,-189.44],[46.05,-190.47],[49.87,-191.59],[53.71,-192.78],[57.58,-194.03],[61.5,-195.34],[65.46,-196.69],[69.48,-198.08],[73.57,-199.5],[77.71,-200.94],[81.93,-202.38],[86.21,-203.81],[90.57,-205.23],[95.0,-206.61],[99.5,-207.96],[104.07,-209.26],[108.71,-210.5],[113.41,-211.68],[118.16,-212.78],[122.97,-213.79],[127.83,-214.71],[132.72,-215.53],[137.65,-216.25],[142.59,-216.85],[147.56,-217.35],[152.53,-217.73],[157.51,-217.98],[162.47,-218.13],[167.42,-218.15],[172.35,-218.05],[177.24,-217.84],[182.11,-217.51],[186.92,-217.07],[191.7,-216.53],[196.42,-215.89],[201.08,-215.15],[205.69,-214.33],[210.25,-213.42],[214.74,-212.45],[219.18,-211.4],[223.57,-210.31],[227.9,-209.16],[232.19,-207.97],[236.43,-206.75],[240.63,-205.51],[244.81,-204.26],[248.96,-202.99],[253.1,-201.73],[257.23,-200.48],[261.36,-199.24],[265.51,-198.02],[269.68,-196.83],[273.88,-195.67],[278.12,-194.55],[282.41,-193.46],[286.77,-192.42],[291.19,-191.41],[295.69,-190.45],[300.27,-189.54],[304.95,-188.66],[309.72,-187.83],[314.59,-187.03],[319.56,-186.27],[324.63,-185.54],[329.81,-184.83],[335.1,-184.15],[340.48,-183.47],[345.96,-182.81],[351.53,-182.15],[357.18,-181.48],[362.91,-180.79],[368.7,-180.08],[374.54,-179.35],[380.42,-178.58],[386.33,-177.76],[392.24,-176.89],[398.14,-175.96],[404.02,-174.96],[409.85,-173.89],[415.61,-172.74],[421.29,-171.51],[426.87,-170.19],[432.32,-168.77],[437.63,-167.25],[442.77,-165.63],[447.73,-163.91],[452.48,-162.09],[457.02,-160.16],[461.31,-158.12],[465.35,-155.98],[469.12,-153.74],[472.6,-151.4],[475.79,-148.96],[478.68,-146.43],[481.24,-143.81],[483.49,-141.11],[485.41,-138.33],[487.01,-135.47],[488.27,-132.56],[489.21,-129.58],[489.83,-126.56],[490.12,-123.49],[490.11,-120.39],[489.8,-117.26],[489.19,-114.11],[488.32,-110.95],[487.18,-107.78],[485.8,-104.61],[484.19,-101.46],[482.38,-98.32],[480.39,-95.2],[478.23,-92.1],[475.93,-89.04],[473.51,-86.02],[470.99,-83.03],[468.41,-80.1],[465.77,-77.2],[463.11,-74.36],[460.45,-71.57],[457.81,-68.82],[455.2,-66.13],[452.66,-63.5],[450.19,-60.91],[447.82,-58.37],[445.56,-55.87],[443.43,-53.42],[441.43,-51.01],[439.59,-48.64],[437.89,-46.31],[436.37,-44.0],[435.01,-41.72],[433.82,-39.46],[432.8,-37.22],[431.95,-35.0]],[[433.14,-35.0],[432.38,-32.78],[431.8,-30.56],[431.38,-28.35],[431.11,-26.14],[430.99,-23.92],[430.99,-21.7],[431.12,-19.46],[431.34,-17.22],[431.65,-14.96],[432.03,-12.68],[432.46,-10.39],[432.92,-8.08],[433.39,-5.75],[433.86,-3.41],[434.3,-1.05],[434.7,1.32],[435.04,3.7],[435.3,6.1],[435.46,8.49],[435.5,10.89],[435.42,13.29],[435.19,15.69],[434.8,18.08],[434.25,20.45],[433.52,22.8],[432.61,25.14],[431.51,27.45],[430.21,29.73],[428.71,31.97],[427.02,34.18],[425.12,36.35],[423.04,38.47],[420.76,40.54],[418.3,42.57],[415.66,44.55],[412.86,46.47],[409.9,48.34],[406.8,50.16],[403.57,51.93],[400.22,53.64],[396.76,55.31],[393.23,56.93],[389.62,58.51],[385.96,60.05],[382.26,61.55],[378.54,63.03],[374.81,64.48],[371.1,65.91],[367.41,67.32],[363.75,68.74],[360.15,70.15],[356.62,71.57],[353.16,73.01],[349.79,74.47],[346.51,75.95],[343.34,77.48],[340.27,79.05],[337.31,80.67],[334.46,82.34],[331.73,84.08],[329.1,85.89],[326.59,87.76],[324.19,89.72],[321.88,91.75],[319.66,93.87],[317.53,96.07],[315.48,98.35],[313.48,100.72],[311.54,103.17],[309.64,105.71],[307.76,108.32],[305.89,111.01],[304.01,113.77],[302.12,116.59],[300.19,119.48],[298.22,122.41],[296.18,125.39],[294.06,128.4],[291.84,131.43],[289.52,134.48],[287.09,137.54],[284.52,140.58],[281.81,143.61],[278.96,146.61],[275.94,149.57],[272.76,152.47],[269.41,155.3],[265.88,158.06],[262.17,160.73],[258.29,163.3],[254.23,165.76],[249.99,168.1],[245.58,170.31],[240.99,172.39],[236.25,174.31],[231.34,176.08],[226.29,177.7],[221.1,179.14],[215.78,180.42],[210.34,181.53],[204.79,182.47],[199.15,183.23],[193.43,183.81],[187.64,184.23],[181.79,184.47],[175.89,184.55],[169.97,184.46],[164.02,184.22],[158.08,183.83],[152.13,183.3],[146.21,182.63],[140.31,181.83],[134.44,180.92],[128.62,179.9],[122.86,178.79],[117.15,177.59],[111.51,176.31],[105.93,174.98],[100.43,173.59],[95.0,172.16],[89.65,170.7],[84.37,169.22],[79.17,167.73],[74.03,166.24],[68.97,164.77],[63.97,163.31],[59.04,161.88],[54.16,160.48],[49.33,159.12],[44.54,157.81],[39.79,156.55],[35.07,155.34],[30.37,154.19],[25.7,153.09],[21.03,152.06],[16.37,151.08],[11.71,150.16],[7.04,149.3],[2.36,148.49],[-2.33,147.72],[-7.04,147.0],[-11.77,146.31],[-16.52,145.66],[-21.29,145.03],[-26.08,144.42],[-30.88,143.82],[-35.7,143.22],[-40.54,142.61],[-45.38,141.99],[-50.21,141.35],[-55.04,140.68],[-59.86,139.96],[-64.65,139.2],[-69.41,138.39],[-74.12,137.51],[-78.78,136.57],[-83.38,135.55],[-87.9,134.45],[-92.33,133.27],[-96.67,132.0],[-100.89,130.63],[-105.0,129.17],[-108.97,127.62],[-112.81,125.97],[-116.49,124.22],[-120.02,122.38],[-123.38,120.44],[-126.58,118.41],[-129.6,116.3],[-132.44,114.1],[-135.09,111.82],[-137.57,109.47],[-139.87,107.05],[-141.99,104.58],[-143.93,102.05],[-145.71,99.48],[-147.32,96.86],[-148.78,94.22],[-150.1,91.56],[-151.29,88.89],[-152.36,86.21],[-153.32,83.54],[-154.2,80.88],[-155.01,78.24],[-155.76,75.62],[-156.47,73.04],[-157.17,70.5],[-157.86,68.0],[-158.58,65.56],[-159.33,63.17],[-160.15,60.84],[-161.04,58.58],[-162.03,56.37],[-163.13,54.24],[-164.36,52.17],[-165.73,50.17],[-167.27,48.24],[-168.98,46.37],[-170.87,44.57],[-172.96,42.82],[-175.25,41.13],[-177.75,39.49],[-180.47,37.9],[-183.4,36.36],[-186.55,34.84],[-189.91,33.36],[-193.49,31.9],[-197.27,30.46],[-201.25,29.03],[-205.42,27.6],[-209.76,26.16],[-214.26,24.72],[-218.91,23.26],[-223.69,21.77],[-228.58,20.25],[-233.56,18.7],[-238.61,17.11],[-243.71,15.47],[-248.83,13.78],[-253.95,12.03],[-259.05,10.23],[-264.1,8.37],[-269.08,6.44],[-273.96,4.45],[-278.72,2.39],[-283.35,0.27],[-287.81,-1.91],[-292.08,-4.16],[-296.15,-6.47],[-300.0,-8.84],[-303.6,-11.27],[-306.95,-13.75],[-310.03,-16.28],[-312.84,-18.85],[-315.35,-21.47],[-317.56,-24.12],[-319.47,-26.81],[-321.08,-29.52],[-322.37,-32.25],[-323.36,-35.0],[-324.05,-37.76],[-324.44,-40.52],[-324.54,-43.29],[-324.35,-46.06],[-323.89,-48.81],[-323.18,-51.56],[-322.21,-54.28],[-321.02,-57.0],[-319.61,-59.68],[-318.0,-62.35],[-316.22,-64.99],[-314.27,-67.61],[-312.18,-70.2],[-309.97,-72.76],[-307.66,-75.29],[-305.26,-77.8],[-302.81,-80.28],[-300.3,-82.74],[-297.77,-85.18],[-295.22,-87.6],[-292.68,-90.0],[-290.16,-92.39],[-287.67,-94.77],[-285.22,-97.15],[-282.83,-99.52],[-280.5,-101.89],[-278.23,-104.26],[-276.04,-106.65],[-273.93,-109.04],[-271.9,-111.45],[-269.94,-113.87],[-268.06,-116.31],[-266.25,-118.77],[-264.51,-121.26],[-262.82,-123.76],[-261.19,-126.29],[-259.59,-128.85],[-258.03,-131.42],[-256.48,-134.02],[-254.93,-136.63],[-253.38,-139.26],[-251.8,-141.9],[-250.17,-144.55],[-248.5,-147.21],[-246.75,-149.87],[-244.91,-152.52],[-242.98,-155.15],[-240.93,-157.77],[-238.74,-160.36],[-236.42,-162.92],[-233.94,-165.44],[-231.29,-167.91],[-228.47,-170.33],[-225.46,-172.68],[-222.25,-174.96],[-218.85,-177.15],[-215.25,-179.26],[-211.44,-181.28],[-207.42,-183.2],[-203.2,-185.0],[-198.77,-186.7],[-194.15,-188.27],[-189.33,-189.72],[-184.32,-191.05],[-179.13,-192.24],[-173.77,-193.3],[-168.26,-194.23],[-162.6,-195.02],[-156.8,-195.67],[-150.89,-196.2],[-144.88,-196.59],[-138.77,-196.86],[-132.6,-197.0],[-126.37,-197.02],[-120.1,-196.93],[-113.8,-196.74],[-107.5,-196.45],[-101.21,-196.07],[-94.95,-195.61],[-88.73,-195.07],[-82.55,-194.48],[-76.45,-193.84],[-70.42,-193.16],[-64.49,-192.45],[-58.65,-191.73],[-52.92,-191.0],[-47.31,-190.28],[-41.82,-189.58],[-36.45,-188.91],[-31.21,-188.27],[-26.1,-187.69],[-21.12,-187.16],[-16.26,-186.71],[-11.53,-186.33],[-6.92,-186.04],[-2.43,-185.83],[1.96,-185.73],[6.24,-185.73],[10.44,-185.83],[14.54,-186.04],[18.58,-186.37],[22.55,-186.8],[26.47,-187.34],[30.35,-188.0],[34.2,-188.76],[38.03,-189.62],[41.85,-190.58],[45.68,-191.63],[49.52,-192.77],[53.39,-193.99],[57.29,-195.28],[61.23,-196.63],[65.22,-198.03],[69.27,-199.47],[73.38,-200.94],[77.56,-202.43],[81.81,-203.93],[86.13,-205.43],[90.53,-206.92],[95.0,-208.38],[99.55,-209.81],[104.17,-211.19],[108.87,-212.52],[113.63,-213.78],[118.45,-214.96],[123.33,-216.06],[128.26,-217.07],[133.23,-217.98],[138.24,-218.78],[143.28,-219.48],[148.34,-220.06],[153.41,-220.52],[158.49,-220.86],[163.56,-221.08],[168.62,-221.17],[173.66,-221.14],[178.67,-221.0],[183.64,-220.73],[188.58,-220.35],[193.47,-219.86],[198.31,-219.26],[203.09,-218.56],[207.82,-217.77],[212.48,-216.89],[217.09,-215.93],[221.64,-214.9],[226.13,-213.8],[230.57,-212.65],[234.95,-211.46],[239.29,-210.22],[243.58,-208.96],[247.84,-207.68],[252.07,-206.38],[256.27,-205.08],[260.47,-203.78],[264.66,-202.5],[268.86,-201.23],[273.07,-199.98],[277.31,-198.75],[281.58,-197.56],[285.9,-196.41],[290.27,-195.29],[294.71,-194.22],[299.21,-193.18],[303.8,-192.19],[308.47,-191.24],[313.23,-190.33],[318.08,-189.45],[323.04,-188.61],[328.09,-187.81],[333.25,-187.03],[338.51,-186.27],[343.87,-185.52],[349.32,-184.79],[354.87,-184.06],[360.49,-183.32],[366.19,-182.58],[371.96,-181.81],[377.78,-181.02],[383.64,-180.19],[389.53,-179.33],[395.42,-178.41],[401.31,-177.44],[407.18,-176.4],[413.01,-175.29],[418.78,-174.1],[424.46,-172.84],[430.05,-171.48],[435.51,-170.03],[440.84,-168.49],[446.0,-166.85],[450.98,-165.1],[455.76,-163.25],[460.33,-161.3],[464.65,-159.25],[468.72,-157.08],[472.53,-154.82],[476.05,-152.46],[479.27,-150.0],[482.19,-147.45],[484.79,-144.81],[487.07,-142.08],[489.02,-139.28],[490.65,-136.41],[491.93,-133.47],[492.89,-130.47],[493.52,-127.42],[493.82,-124.32],[493.81,-121.19],[493.5,-118.03],[492.89,-114.85],[491.99,-111.66],[490.83,-108.46],[489.42,-105.26],[487.77,-102.07],[485.91,-98.89],[483.86,-95.74],[481.64,-92.61],[479.27,-89.52],[476.77,-86.46],[474.18,-83.44],[471.5,-80.47],[468.77,-77.54],[466.01,-74.67],[463.24,-71.85],[460.49,-69.07],[457.77,-66.36],[455.11,-63.69],[452.52,-61.08],[450.03,-58.51],[447.66,-56.0],[445.4,-53.53],[443.29,-51.1],[441.33,-48.71],[439.53,-46.36],[437.9,-44.04],[436.44,-41.75],[435.16,-39.48],[434.06,-37.23],[433.14,-35.0]],[[434.34,-35.0],[433.53,-32.77],[432.89,-30.55],[432.42,-28.33],[432.12,-26.11],[431.97,-23.89],[431.96,-21.66],[432.08,-19.42],[432.31,-17.17],[432.65,-14.9],[433.06,-12.61],[433.53,-10.31],[434.05,-7.99],[434.6,-5.65],[435.15,-3.29],[435.68,-0.91],[436.18,1.48],[436.63,3.89],[437.01,6.3],[437.3,8.73],[437.48,11.16],[437.54,13.6],[437.46,16.03],[437.23,18.45],[436.84,20.87],[436.27,23.27],[435.52,25.66],[434.57,28.02],[433.44,30.35],[432.1,32.65],[430.56,34.92],[428.83,37.15],[426.89,39.33],[424.76,41.47],[422.43,43.56],[419.93,45.6],[417.25,47.59],[414.4,49.53],[411.41,51.42],[408.27,53.25],[405.01,55.03],[401.63,56.77],[398.16,58.45],[394.61,60.09],[390.99,61.69],[387.32,63.25],[383.63,64.78],[379.91,66.29],[376.19,67.77],[372.49,69.24],[368.82,70.69],[365.19,72.15],[361.62,73.61],[358.12,75.08],[354.69,76.57],[351.35,78.09],[348.1,79.64],[344.96,81.23],[341.92,82.87],[338.99,84.56],[336.17,86.31],[333.45,88.13],[330.85,90.02],[328.34,91.98],[325.94,94.02],[323.62,96.14],[321.4,98.34],[319.24,100.63],[317.15,103.0],[315.11,105.45],[313.12,107.99],[311.14,110.6],[309.19,113.29],[307.23,116.06],[305.25,118.89],[303.24,121.77],[301.19,124.71],[299.07,127.7],[296.88,130.72],[294.6,133.77],[292.22,136.83],[289.72,139.9],[287.09,142.96],[284.32,146.01],[281.41,149.03],[278.34,152.01],[275.1,154.94],[271.7,157.8],[268.12,160.59],[264.36,163.29],[260.42,165.89],[256.31,168.38],[252.01,170.76],[247.54,173.0],[242.9,175.1],[238.1,177.06],[233.14,178.86],[228.02,180.5],[222.77,181.98],[217.38,183.28],[211.87,184.41],[206.26,185.37],[200.54,186.14],[194.74,186.74],[188.88,187.16],[182.95,187.41],[176.97,187.49],[170.97,187.4],[164.94,187.14],[158.91,186.74],[152.89,186.18],[146.88,185.48],[140.9,184.66],[134.95,183.71],[129.05,182.64],[123.21,181.48],[117.42,180.23],[111.71,178.9],[106.06,177.49],[100.49,176.04],[95.0,174.53],[89.59,173.0],[84.25,171.44],[79.0,169.87],[73.82,168.29],[68.72,166.73],[63.68,165.18],[58.71,163.65],[53.8,162.16],[48.95,160.71],[44.15,159.31],[39.38,157.95],[34.66,156.65],[29.96,155.41],[25.28,154.23],[20.61,153.11],[15.96,152.05],[11.31,151.06],[6.65,150.12],[1.98,149.24],[-2.7,148.41],[-7.39,147.63],[-12.11,146.89],[-16.84,146.19],[-21.6,145.52],[-26.38,144.87],[-31.18,144.24],[-36.0,143.62],[-40.83,142.99],[-45.67,142.36],[-50.51,141.71],[-55.36,141.04],[-60.19,140.33],[-65.0,139.59],[-69.79,138.79],[-74.54,137.93],[-79.24,137.02],[-83.88,136.03],[-88.45,134.96],[-92.94,133.82],[-97.34,132.58],[-101.64,131.26],[-105.82,129.85],[-109.88,128.34],[-113.8,126.74],[-117.58,125.04],[-121.21,123.25],[-124.67,121.36],[-127.97,119.38],[-131.1,117.31],[-134.05,115.16],[-136.82,112.92],[-139.42,110.62],[-141.83,108.24],[-144.06,105.8],[-146.12,103.31],[-148.01,100.76],[-149.74,98.18],[-151.31,95.56],[-152.73,92.92],[-154.02,90.27],[-155.19,87.6],[-156.26,84.94],[-157.23,82.28],[-158.12,79.64],[-158.95,77.03],[-159.74,74.44],[-160.51,71.9],[-161.27,69.39],[-162.05,66.93],[-162.86,64.53],[-163.72,62.18],[-164.66,59.9],[-165.69,57.68],[-166.82,55.52],[-168.09,53.43],[-169.49,51.4],[-171.05,49.44],[-172.78,47.55],[-174.7,45.71],[-176.81,43.94],[-179.12,42.22],[-181.64,40.56],[-184.38,38.94],[-187.33,37.36],[-190.51,35.82],[-193.9,34.32],[-197.5,32.83],[-201.32,31.36],[-205.33,29.91],[-209.54,28.45],[-213.93,27.0],[-218.48,25.53],[-223.19,24.05],[-228.03,22.54],[-232.99,21.01],[-238.05,19.43],[-243.18,17.82],[-248.36,16.16],[-253.58,14.45],[-258.8,12.69],[-264.0,10.86],[-269.16,8.98],[-274.26,7.03],[-279.26,5.02],[-284.14,2.94],[-288.89,0.79],[-293.48,-1.42],[-297.88,-3.7],[-302.08,-6.04],[-306.05,-8.44],[-309.79,-10.9],[-313.26,-13.41],[-316.47,-15.98],[-319.39,-18.59],[-322.01,-21.25],[-324.33,-23.95],[-326.34,-26.67],[-328.04,-29.43],[-329.42,-32.21],[-330.49,-35.0],[-331.24,-37.81],[-331.68,-40.62],[-331.82,-43.44],[-331.67,-46.25],[-331.23,-49.05],[-330.52,-51.85],[-329.54,-54.62],[-328.33,-57.38],[-326.89,-60.12],[-325.23,-62.83],[-323.38,-65.52],[-321.36,-68.17],[-319.19,-70.8],[-316.88,-73.4],[-314.45,-75.97],[-311.94,-78.51],[-309.34,-81.02],[-306.69,-83.51],[-304.0,-85.97],[-301.29,-88.41],[-298.58,-90.84],[-295.88,-93.24],[-293.2,-95.64],[-290.56,-98.02],[-287.98,-100.4],[-285.45,-102.77],[-282.99,-105.15],[-280.6,-107.53],[-278.28,-109.91],[-276.05,-112.31],[-273.9,-114.73],[-271.82,-117.15],[-269.82,-119.6],[-267.89,-122.07],[-266.03,-124.56],[-264.22,-127.07],[-262.46,-129.61],[-260.74,-132.16],[-259.04,-134.74],[-257.36,-137.33],[-255.67,-139.95],[-253.97,-142.57],[-252.23,-145.21],[-250.45,-147.85],[-248.61,-150.49],[-246.69,-153.13],[-244.68,-155.76],[-242.57,-158.37],[-240.33,-160.96],[-237.96,-163.52],[-235.44,-166.04],[-232.76,-168.51],[-229.92,-170.93],[-226.89,-173.29],[-223.68,-175.59],[-220.28,-177.8],[-216.67,-179.93],[-212.87,-181.96],[-208.86,-183.9],[-204.65,-185.73],[-200.24,-187.46],[-195.63,-189.06],[-190.83,-190.54],[-185.84,-191.89],[-180.66,-193.12],[-175.32,-194.21],[-169.82,-195.17],[-164.17,-196.0],[-158.39,-196.69],[-152.49,-197.24],[-146.47,-197.67],[-140.37,-197.96],[-134.19,-198.13],[-127.96,-198.18],[-121.68,-198.12],[-115.37,-197.95],[-109.05,-197.68],[-102.74,-197.32],[-96.45,-196.88],[-90.2,-196.36],[-84.0,-195.78],[-77.86,-195.15],[-71.79,-194.47],[-65.82,-193.77],[-59.94,-193.05],[-54.17,-192.32],[-48.51,-191.59],[-42.97,-190.88],[-37.55,-190.2],[-32.27,-189.56],[-27.11,-188.96],[-22.08,-188.42],[-17.18,-187.96],[-12.4,-187.57],[-7.75,-187.26],[-3.21,-187.04],[1.22,-186.93],[5.54,-186.91],[9.77,-187.01],[13.92,-187.21],[17.99,-187.53],[22.0,-187.96],[25.95,-188.51],[29.86,-189.16],[33.74,-189.93],[37.59,-190.81],[41.44,-191.78],[45.3,-192.85],[49.16,-194.02],[53.06,-195.26],[56.98,-196.58],[60.95,-197.97],[64.97,-199.41],[69.04,-200.9],[73.18,-202.43],[77.4,-203.98],[81.68,-205.54],[86.04,-207.11],[90.48,-208.66],[95.0,-210.2],[99.6,-211.7],[104.27,-213.16],[109.03,-214.57],[113.85,-215.91],[118.74,-217.18],[123.69,-218.37],[128.7,-219.47],[133.75,-220.46],[138.85,-221.36],[143.98,-222.14],[149.13,-222.8],[154.3,-223.34],[159.48,-223.76],[164.66,-224.06],[169.83,-224.23],[174.98,-224.27],[180.1,-224.19],[185.2,-223.98],[190.25,-223.66],[195.26,-223.22],[200.21,-222.66],[205.12,-222.0],[209.96,-221.24],[214.75,-220.39],[219.47,-219.45],[224.13,-218.43],[228.73,-217.34],[233.26,-216.19],[237.75,-214.98],[242.18,-213.73],[246.56,-212.45],[250.9,-211.14],[255.2,-209.81],[259.48,-208.47],[263.74,-207.12],[267.99,-205.79],[272.24,-204.46],[276.49,-203.15],[280.77,-201.86],[285.07,-200.61],[289.41,-199.38],[293.8,-198.19],[298.24,-197.04],[302.75,-195.93],[307.34,-194.85],[312.0,-193.82],[316.75,-192.83],[321.58,-191.88],[326.52,-190.96],[331.55,-190.07],[336.68,-189.21],[341.91,-188.38],[347.24,-187.56],[352.66,-186.75],[358.17,-185.95],[363.76,-185.15],[369.43,-184.34],[375.17,-183.51],[380.96,-182.66],[386.79,-181.78],[392.66,-180.86],[398.53,-179.89],[404.41,-178.87],[410.26,-177.79],[416.08,-176.64],[421.84,-175.42],[427.53,-174.12],[433.12,-172.73],[438.59,-171.25],[443.93,-169.68],[449.1,-168.01],[454.1,-166.24],[458.91,-164.37],[463.5,-162.4],[467.85,-160.32],[471.95,-158.14],[475.79,-155.86],[479.34,-153.48],[482.6,-151.0],[485.56,-148.43],[488.19,-145.77],[490.5,-143.02],[492.49,-140.2],[494.14,-137.3],[495.45,-134.34],[496.43,-131.32],[497.08,-128.24],[497.39,-125.12],[497.39,-121.96],[497.07,-118.78],[496.46,-115.57],[495.55,-112.34],[494.37,-109.11],[492.93,-105.88],[491.25,-102.66],[489.35,-99.45],[487.25,-96.27],[484.97,-93.11],[482.54,-89.98],[479.97,-86.89],[477.3,-83.84],[474.54,-80.84],[471.72,-77.88],[468.86,-74.97],[465.99,-72.12],[463.13,-69.32],[460.31,-66.58],[457.54,-63.88],[454.84,-61.25],[452.24,-58.66],[449.75,-56.12],[447.38,-53.63],[445.16,-51.19],[443.09,-48.78],[441.18,-46.41],[439.45,-44.08],[437.9,-41.78],[436.53,-39.5],[435.34,-37.24],[434.34,-35.0]],[[435.59,-35.0],[434.7,-32.76],[434.01,-30.53],[433.5,-28.31],[433.16,-26.09],[432.99,-23.86],[432.96,-21.62],[433.08,-19.37],[433.33,-17.11],[433.68,-14.84],[434.13,-12.54],[434.65,-10.23],[435.23,-7.89],[435.84,-5.54],[436.47,-3.16],[437.1,-0.77],[437.71,1.64],[438.27,4.07],[438.77,6.52],[439.18,8.97],[439.5,11.43],[439.71,13.9],[439.78,16.37],[439.7,18.84],[439.47,21.3],[439.06,23.75],[438.47,26.18],[437.7,28.6],[436.73,30.99],[435.55,33.35],[434.18,35.67],[432.6,37.96],[430.81,40.21],[428.83,42.41],[426.65,44.57],[424.28,46.68],[421.72,48.74],[419.0,50.75],[416.11,52.7],[413.08,54.61],[409.9,56.46],[406.61,58.25],[403.2,60.01],[399.71,61.71],[396.14,63.37],[392.5,65.0],[388.83,66.58],[385.13,68.14],[381.41,69.68],[377.7,71.19],[374.01,72.69],[370.35,74.19],[366.74,75.69],[363.19,77.2],[359.71,78.73],[356.3,80.27],[352.99,81.85],[349.76,83.46],[346.64,85.12],[343.62,86.83],[340.7,88.6],[337.9,90.43],[335.19,92.32],[332.59,94.29],[330.08,96.33],[327.66,98.45],[325.33,100.66],[323.07,102.94],[320.88,105.31],[318.74,107.77],[316.64,110.3],[314.58,112.91],[312.52,115.6],[310.47,118.37],[308.41,121.19],[306.31,124.08],[304.17,127.03],[301.98,130.02],[299.71,133.04],[297.36,136.1],[294.9,139.17],[292.34,142.25],[289.64,145.33],[286.82,148.4],[283.84,151.43],[280.71,154.43],[277.42,157.38],[273.96,160.27],[270.32,163.08],[266.51,165.81],[262.52,168.44],[258.35,170.96],[254.0,173.36],[249.47,175.63],[244.78,177.76],[239.92,179.75],[234.89,181.58],[229.72,183.25],[224.4,184.75],[218.95,186.07],[213.37,187.23],[207.69,188.2],[201.9,188.99],[196.03,189.6],[190.09,190.03],[184.08,190.28],[178.03,190.36],[171.95,190.26],[165.84,190.0],[159.73,189.58],[153.63,189.0],[147.54,188.28],[141.47,187.42],[135.45,186.44],[129.47,185.33],[123.55,184.12],[117.69,182.82],[111.9,181.43],[106.19,179.96],[100.55,178.44],[95.0,176.86],[89.53,175.25],[84.14,173.61],[78.84,171.96],[73.61,170.3],[68.47,168.65],[63.39,167.01],[58.39,165.39],[53.46,163.81],[48.59,162.27],[43.76,160.77],[38.99,159.32],[34.25,157.93],[29.55,156.6],[24.87,155.34],[20.21,154.13],[15.56,152.99],[10.92,151.92],[6.27,150.91],[1.62,149.96],[-3.05,149.06],[-7.73,148.22],[-12.43,147.43],[-17.15,146.68],[-21.89,145.97],[-26.66,145.29],[-31.45,144.63],[-36.26,143.98],[-41.09,143.34],[-45.94,142.7],[-50.79,142.05],[-55.64,141.37],[-60.49,140.67],[-65.32,139.94],[-70.14,139.16],[-74.92,138.33],[-79.66,137.43],[-84.35,136.48],[-88.98,135.45],[-93.53,134.34],[-98.0,133.15],[-102.37,131.88],[-106.63,130.51],[-110.77,129.05],[-114.78,127.5],[-118.66,125.85],[-122.39,124.11],[-125.96,122.27],[-129.37,120.34],[-132.61,118.32],[-135.67,116.22],[-138.56,114.03],[-141.27,111.77],[-143.81,109.44],[-146.16,107.04],[-148.34,104.58],[-150.35,102.07],[-152.2,99.52],[-153.88,96.93],[-155.42,94.31],[-156.83,91.68],[-158.1,89.03],[-159.27,86.38],[-160.33,83.73],[-161.32,81.1],[-162.24,78.48],[-163.11,75.89],[-163.96,73.34],[-164.79,70.83],[-165.64,68.36],[-166.51,65.94],[-167.43,63.58],[-168.41,61.27],[-169.48,59.03],[-170.66,56.85],[-171.96,54.73],[-173.4,52.68],[-174.99,50.69],[-176.74,48.77],[-178.68,46.91],[-180.81,45.1],[-183.15,43.36],[-185.69,41.66],[-188.44,40.01],[-191.42,38.41],[-194.61,36.84],[-198.02,35.31],[-201.65,33.79],[-205.5,32.3],[-209.54,30.82],[-213.79,29.34],[-218.22,27.86],[-222.82,26.37],[-227.58,24.86],[-232.48,23.33],[-237.5,21.78],[-242.62,20.18],[-247.83,18.55],[-253.1,16.87],[-258.4,15.14],[-263.71,13.35],[-269.01,11.5],[-274.27,9.6],[-279.48,7.62],[-284.59,5.59],[-289.59,3.48],[-294.46,1.31],[-299.17,-0.93],[-303.69,-3.24],[-308.01,-5.61],[-312.11,-8.04],[-315.97,-10.53],[-319.56,-13.08],[-322.89,-15.68],[-325.92,-18.34],[-328.66,-21.03],[-331.08,-23.77],[-333.19,-26.54],[-334.98,-29.34],[-336.44,-32.16],[-337.58,-35.0],[-338.4,-37.85],[-338.89,-40.72],[-339.07,-43.58],[-338.95,-46.44],[-338.53,-49.29],[-337.82,-52.14],[-336.84,-54.96],[-335.6,-57.77],[-334.12,-60.55],[-332.42,-63.31],[-330.51,-66.04],[-328.42,-68.73],[-326.16,-71.4],[-323.75,-74.04],[-321.21,-76.65],[-318.56,-79.22],[-315.83,-81.76],[-313.04,-84.28],[-310.19,-86.76],[-307.32,-89.23],[-304.43,-91.67],[-301.55,-94.09],[-298.69,-96.49],[-295.86,-98.88],[-293.07,-101.27],[-290.34,-103.64],[-287.68,-106.02],[-285.09,-108.39],[-282.57,-110.77],[-280.14,-113.16],[-277.78,-115.57],[-275.51,-117.98],[-273.32,-120.41],[-271.2,-122.86],[-269.16,-125.34],[-267.17,-127.83],[-265.24,-130.34],[-263.36,-132.88],[-261.51,-135.43],[-259.68,-138.01],[-257.86,-140.6],[-256.03,-143.21],[-254.18,-145.83],[-252.3,-148.45],[-250.36,-151.08],[-248.36,-153.71],[-246.27,-156.33],[-244.09,-158.93],[-241.8,-161.51],[-239.38,-164.07],[-236.83,-166.59],[-234.12,-169.07],[-231.25,-171.49],[-228.21,-173.86],[-225.0,-176.16],[-221.59,-178.39],[-217.99,-180.54],[-214.2,-182.6],[-210.2,-184.56],[-206.01,-186.42],[-201.61,-188.16],[-197.02,-189.8],[-192.24,-191.31],[-187.27,-192.7],[-182.12,-193.96],[-176.8,-195.08],[-171.32,-196.08],[-165.69,-196.94],[-159.92,-197.66],[-154.03,-198.25],[-148.03,-198.71],[-141.93,-199.04],[-135.76,-199.25],[-129.52,-199.33],[-123.24,-199.3],[-116.92,-199.15],[-110.59,-198.91],[-104.27,-198.57],[-97.96,-198.15],[-91.68,-197.65],[-85.45,-197.08],[-79.28,-196.46],[-73.18,-195.8],[-67.17,-195.1],[-61.25,-194.39],[-55.44,-193.66],[-49.74,-192.93],[-44.15,-192.22],[-38.69,-191.53],[-33.36,-190.88],[-28.16,-190.28],[-23.08,-189.74],[-18.13,-189.26],[-13.31,-188.86],[-8.61,-188.54],[-4.03,-188.31],[0.44,-188.19],[4.81,-188.16],[9.08,-188.25],[13.26,-188.45],[17.37,-188.76],[21.41,-189.19],[25.4,-189.74],[29.34,-190.4],[33.25,-191.17],[37.13,-192.06],[41.01,-193.05],[44.89,-194.14],[48.79,-195.32],[52.71,-196.6],[56.66,-197.95],[60.66,-199.37],[64.7,-200.86],[68.81,-202.4],[72.98,-203.97],[77.23,-205.58],[81.55,-207.2],[85.95,-208.83],[90.43,-210.45],[95.0,-212.06],[99.65,-213.64],[104.38,-215.18],[109.19,-216.67],[114.08,-218.09],[119.03,-219.45],[124.06,-220.72],[129.14,-221.9],[134.28,-222.99],[139.46,-223.96],[144.68,-224.83],[149.93,-225.58],[155.2,-226.2],[160.49,-226.71],[165.77,-227.08],[171.05,-227.32],[176.31,-227.43],[181.55,-227.42],[186.76,-227.27],[191.94,-227.0],[197.06,-226.61],[202.14,-226.1],[207.16,-225.48],[212.13,-224.75],[217.03,-223.92],[221.86,-223.0],[226.64,-221.99],[231.34,-220.91],[235.98,-219.75],[240.57,-218.54],[245.09,-217.27],[249.56,-215.97],[253.99,-214.63],[258.37,-213.26],[262.72,-211.88],[267.04,-210.49],[271.35,-209.1],[275.65,-207.72],[279.95,-206.35],[284.26,-205.0],[288.59,-203.67],[292.95,-202.37],[297.35,-201.1],[301.8,-199.87],[306.31,-198.68],[310.89,-197.53],[315.54,-196.42],[320.27,-195.34],[325.09,-194.31],[330.0,-193.3],[335.0,-192.34],[340.1,-191.4],[345.29,-190.48],[350.59,-189.59],[355.97,-188.7],[361.44,-187.83],[367.0,-186.96],[372.63,-186.08],[378.33,-185.19],[384.08,-184.28],[389.89,-183.34],[395.72,-182.36],[401.57,-181.34],[407.42,-180.27],[413.25,-179.15],[419.06,-177.96],[424.81,-176.69],[430.48,-175.36],[436.07,-173.93],[441.55,-172.43],[446.89,-170.82],[452.08,-169.13],[457.09,-167.33],[461.92,-165.44],[466.53,-163.44],[470.91,-161.35],[475.04,-159.15],[478.9,-156.85],[482.49,-154.45],[485.78,-151.95],[488.77,-149.36],[491.44,-146.68],[493.79,-143.92],[495.8,-141.07],[497.48,-138.16],[498.82,-135.18],[499.83,-132.13],[500.49,-129.03],[500.83,-125.89],[500.83,-122.71],[500.52,-119.5],[499.91,-116.26],[498.99,-113.01],[497.8,-109.75],[496.34,-106.49],[494.64,-103.24],[492.7,-100.0],[490.56,-96.78],[488.23,-93.59],[485.74,-90.43],[483.11,-87.31],[480.37,-84.23],[477.53,-81.2],[474.63,-78.21],[471.68,-75.28],[468.72,-72.39],[465.76,-69.57],[462.83,-66.79],[459.96,-64.08],[457.15,-61.41],[454.44,-58.8],[451.84,-56.25],[449.37,-53.74],[447.04,-51.27],[444.86,-48.85],[442.86,-46.47],[441.03,-44.12],[439.38,-41.81],[437.92,-39.52],[436.66,-37.25],[435.59,-35.0]],[[436.87,-35.0],[435.92,-32.76],[435.18,-30.52],[434.62,-28.29],[434.25,-26.06],[434.05,-23.82],[434.02,-21.58],[434.14,-19.32],[434.39,-17.06],[434.77,-14.77],[435.25,-12.47],[435.82,-10.14],[436.45,-7.8],[437.14,-5.43],[437.85,-3.04],[438.57,-0.62],[439.28,1.81],[439.95,4.26],[440.57,6.73],[441.12,9.22],[441.58,11.71],[441.93,14.22],[442.15,16.73],[442.23,19.24],[442.16,21.74],[441.91,24.24],[441.49,26.72],[440.88,29.19],[440.08,31.63],[439.07,34.05],[437.86,36.44],[436.44,38.79],[434.81,41.1],[432.98,43.38],[430.94,45.6],[428.71,47.78],[426.29,49.91],[423.68,51.99],[420.91,54.01],[417.98,55.99],[414.89,57.91],[411.68,59.77],[408.35,61.59],[404.91,63.36],[401.39,65.09],[397.79,66.77],[394.14,68.42],[390.45,70.04],[386.74,71.62],[383.02,73.19],[379.31,74.74],[375.63,76.28],[371.98,77.83],[368.38,79.37],[364.83,80.93],[361.36,82.51],[357.98,84.11],[354.67,85.75],[351.46,87.43],[348.35,89.15],[345.34,90.93],[342.43,92.77],[339.62,94.67],[336.91,96.64],[334.3,98.69],[331.78,100.81],[329.33,103.02],[326.97,105.3],[324.67,107.67],[322.42,110.12],[320.22,112.64],[318.05,115.25],[315.89,117.94],[313.74,120.7],[311.58,123.52],[309.4,126.41],[307.17,129.35],[304.89,132.34],[302.54,135.37],[300.11,138.43],[297.58,141.5],[294.94,144.59],[292.18,147.68],[289.29,150.76],[286.25,153.81],[283.05,156.82],[279.7,159.79],[276.18,162.7],[272.49,165.53],[268.62,168.28],[264.57,170.94],[260.35,173.48],[255.94,175.91],[251.36,178.21],[246.61,180.37],[241.69,182.38],[236.61,184.23],[231.37,185.93],[225.99,187.45],[220.48,188.8],[214.84,189.97],[209.08,190.96],[203.23,191.77],[197.29,192.39],[191.27,192.83],[185.19,193.09],[179.07,193.16],[172.9,193.06],[166.72,192.79],[160.53,192.35],[154.35,191.76],[148.18,191.01],[142.04,190.13],[135.94,189.1],[129.88,187.96],[123.89,186.71],[117.96,185.35],[112.1,183.9],[106.32,182.38],[100.62,180.79],[95.0,179.15],[89.47,177.46],[84.03,175.75],[78.67,174.01],[73.41,172.27],[68.22,170.53],[63.11,168.8],[58.08,167.1],[53.12,165.42],[48.23,163.79],[43.39,162.2],[38.6,160.66],[33.86,159.18],[29.15,157.76],[24.48,156.41],[19.82,155.12],[15.18,153.9],[10.54,152.75],[5.91,151.67],[1.27,150.65],[-3.38,149.69],[-8.04,148.79],[-12.73,147.95],[-17.44,147.15],[-22.17,146.4],[-26.92,145.68],[-31.71,144.99],[-36.51,144.32],[-41.34,143.66],[-46.18,143.01],[-51.04,142.35],[-55.9,141.68],[-60.76,140.98],[-65.62,140.26],[-70.46,139.5],[-75.28,138.69],[-80.06,137.83],[-84.8,136.9],[-89.48,135.91],[-94.09,134.85],[-98.63,133.7],[-103.07,132.47],[-107.41,131.15],[-111.64,129.75],[-115.75,128.25],[-119.72,126.65],[-123.56,124.96],[-127.24,123.18],[-130.76,121.31],[-134.12,119.34],[-137.3,117.29],[-140.32,115.15],[-143.15,112.94],[-145.81,110.65],[-148.29,108.29],[-150.6,105.87],[-152.73,103.4],[-154.7,100.88],[-156.51,98.32],[-158.17,95.73],[-159.69,93.12],[-161.08,90.49],[-162.36,87.85],[-163.53,85.22],[-164.61,82.59],[-165.63,79.98],[-166.59,77.39],[-167.52,74.83],[-168.43,72.31],[-169.35,69.83],[-170.28,67.4],[-171.26,65.02],[-172.3,62.69],[-173.42,60.43],[-174.64,58.22],[-175.98,56.08],[-177.45,54.0],[-179.07,51.99],[-180.86,50.03],[-182.82,48.14],[-184.97,46.31],[-187.32,44.53],[-189.88,42.81],[-192.65,41.13],[-195.65,39.49],[-198.86,37.9],[-202.29,36.33],[-205.94,34.79],[-209.81,33.27],[-213.89,31.76],[-218.16,30.25],[-222.63,28.74],[-227.27,27.23],[-232.08,25.7],[-237.03,24.14],[-242.1,22.56],[-247.29,20.95],[-252.56,19.29],[-257.9,17.58],[-263.28,15.83],[-268.68,14.02],[-274.07,12.15],[-279.43,10.22],[-284.74,8.22],[-289.96,6.16],[-295.07,4.03],[-300.05,1.83],[-304.87,-0.44],[-309.51,-2.77],[-313.95,-5.17],[-318.17,-7.64],[-322.14,-10.16],[-325.85,-12.75],[-329.29,-15.39],[-332.43,-18.08],[-335.27,-20.81],[-337.8,-23.59],[-340.0,-26.4],[-341.88,-29.25],[-343.42,-32.11],[-344.63,-35.0],[-345.51,-37.9],[-346.06,-40.81],[-346.28,-43.72],[-346.18,-46.63],[-345.78,-49.53],[-345.07,-52.42],[-344.09,-55.3],[-342.83,-58.15],[-341.32,-60.98],[-339.57,-63.78],[-337.6,-66.55],[-335.43,-69.29],[-333.08,-72.0],[-330.56,-74.68],[-327.92,-77.32],[-325.15,-79.92],[-322.28,-82.5],[-319.34,-85.04],[-316.33,-87.55],[-313.29,-90.03],[-310.23,-92.49],[-307.17,-94.93],[-304.12,-97.34],[-301.1,-99.74],[-298.11,-102.13],[-295.18,-104.5],[-292.31,-106.88],[-289.52,-109.25],[-286.79,-111.62],[-284.15,-114.0],[-281.6,-116.39],[-279.13,-118.79],[-276.74,-121.21],[-274.43,-123.64],[-272.2,-126.09],[-270.04,-128.56],[-267.93,-131.05],[-265.89,-133.57],[-263.88,-136.1],[-261.9,-138.65],[-259.95,-141.23],[-257.99,-143.81],[-256.02,-146.41],[-254.03,-149.02],[-252.0,-151.63],[-249.91,-154.24],[-247.75,-156.85],[-245.5,-159.44],[-243.16,-162.02],[-240.69,-164.57],[-238.1,-167.09],[-235.36,-169.57],[-232.47,-172.0],[-229.42,-174.38],[-226.2,-176.7],[-222.79,-178.94],[-219.2,-181.1],[-215.42,-183.18],[-211.44,-185.16],[-207.26,-187.05],[-202.89,-188.82],[-198.33,-190.49],[-193.57,-192.03],[-188.63,-193.45],[-183.5,-194.75],[-178.21,-195.91],[-172.75,-196.95],[-167.15,-197.84],[-161.4,-198.61],[-155.53,-199.24],[-149.54,-199.73],[-143.46,-200.1],[-137.3,-200.34],[-131.06,-200.46],[-124.78,-200.46],[-118.46,-200.35],[-112.13,-200.13],[-105.79,-199.82],[-99.46,-199.42],[-93.17,-198.95],[-86.91,-198.4],[-80.72,-197.8],[-74.59,-197.15],[-68.55,-196.46],[-62.59,-195.75],[-56.74,-195.03],[-51.0,-194.31],[-45.37,-193.6],[-39.87,-192.91],[-34.49,-192.26],[-29.24,-191.65],[-24.12,-191.1],[-19.13,-190.61],[-14.26,-190.2],[-9.51,-189.88],[-4.89,-189.64],[-0.37,-189.51],[4.03,-189.48],[8.35,-189.56],[12.57,-189.75],[16.71,-190.06],[20.79,-190.49],[24.81,-191.03],[28.79,-191.7],[32.73,-192.48],[36.65,-193.37],[40.56,-194.38],[44.47,-195.49],[48.39,-196.7],[52.34,-198.0],[56.32,-199.38],[60.35,-200.84],[64.43,-202.36],[68.57,-203.94],[72.78,-205.57],[77.06,-207.23],[81.42,-208.91],[85.86,-210.6],[90.39,-212.29],[95.0,-213.97],[99.7,-215.62],[104.49,-217.24],[109.36,-218.8],[114.31,-220.31],[119.33,-221.75],[124.43,-223.11],[129.59,-224.37],[134.81,-225.54],[140.08,-226.61],[145.4,-227.56],[150.74,-228.39],[156.11,-229.1],[161.5,-229.68],[166.89,-230.13],[172.28,-230.44],[177.66,-230.62],[183.02,-230.67],[188.35,-230.59],[193.64,-230.37],[198.89,-230.03],[204.09,-229.57],[209.23,-228.98],[214.31,-228.29],[219.33,-227.48],[224.28,-226.58],[229.16,-225.58],[233.98,-224.5],[238.73,-223.35],[243.41,-222.13],[248.03,-220.85],[252.59,-219.52],[257.1,-218.15],[261.56,-216.75],[265.98,-215.32],[270.37,-213.89],[274.73,-212.44],[279.08,-211.0],[283.42,-209.57],[287.77,-208.15],[292.12,-206.75],[296.51,-205.38],[300.92,-204.03],[305.38,-202.72],[309.88,-201.45],[314.45,-200.21],[319.09,-199.01],[323.8,-197.85],[328.6,-196.73],[333.47,-195.65],[338.44,-194.59],[343.51,-193.57],[348.66,-192.57],[353.91,-191.6],[359.25,-190.64],[364.68,-189.69],[370.19,-188.74],[375.78,-187.79],[381.43,-186.83],[387.15,-185.86],[392.91,-184.86],[398.71,-183.83],[404.52,-182.75],[410.34,-181.63],[416.15,-180.46],[421.93,-179.23],[427.67,-177.92],[433.33,-176.55],[438.91,-175.09],[444.38,-173.55],[449.72,-171.92],[454.92,-170.2],[459.94,-168.38],[464.78,-166.46],[469.41,-164.44],[473.81,-162.32],[477.97,-160.11],[481.87,-157.79],[485.48,-155.37],[488.81,-152.86],[491.83,-150.25],[494.53,-147.55],[496.92,-144.77],[498.96,-141.91],[500.68,-138.98],[502.05,-135.98],[503.08,-132.91],[503.77,-129.79],[504.12,-126.63],[504.15,-123.42],[503.85,-120.19],[503.24,-116.93],[502.32,-113.65],[501.12,-110.37],[499.65,-107.08],[497.92,-103.8],[495.96,-100.53],[493.78,-97.29],[491.41,-94.07],[488.87,-90.88],[486.19,-87.73],[483.38,-84.62],[480.47,-81.55],[477.49,-78.54],[474.47,-75.57],[471.42,-72.66],[468.37,-69.81],[465.34,-67.01],[462.37,-64.27],[459.46,-61.58],[456.65,-58.95],[453.94,-56.37],[451.37,-53.84],[448.93,-51.36],[446.66,-48.92],[444.55,-46.52],[442.63,-44.16],[440.9,-41.84],[439.35,-39.54],[438.01,-37.26],[436.87,-35.0]],[[438.2,-35.0],[437.2,-32.75],[436.4,-30.5],[435.8,-28.26],[435.39,-26.03],[435.17,-23.78],[435.13,-21.53],[435.24,-19.27],[435.51,-17.0],[435.91,-14.7],[436.43,-12.39],[437.04,-10.05],[437.73,-7.69],[438.49,-5.31],[439.28,-2.9],[440.09,-0.47],[440.9,1.98],[441.69,4.46],[442.43,6.96],[443.11,9.47],[443.71,12.0],[444.2,14.54],[444.58,17.09],[444.81,19.64],[444.9,22.19],[444.83,24.73],[444.57,27.27],[444.13,29.79],[443.5,32.29],[442.66,34.77],[441.61,37.22],[440.35,39.64],[438.88,42.02],[437.2,44.36],[435.32,46.65],[433.22,48.9],[430.94,51.1],[428.46,53.25],[425.8,55.35],[422.97,57.39],[419.98,59.38],[416.86,61.32],[413.6,63.21],[410.22,65.05],[406.75,66.84],[403.19,68.59],[399.57,70.3],[395.9,71.97],[392.19,73.61],[388.46,75.23],[384.73,76.83],[381.01,78.42],[377.32,80.0],[373.67,81.59],[370.07,83.18],[366.54,84.79],[363.07,86.42],[359.69,88.08],[356.39,89.78],[353.18,91.52],[350.07,93.31],[347.06,95.16],[344.14,97.07],[341.32,99.04],[338.6,101.09],[335.96,103.21],[333.4,105.41],[330.92,107.69],[328.51,110.05],[326.15,112.49],[323.84,115.02],[321.56,117.62],[319.3,120.29],[317.04,123.04],[314.78,125.86],[312.5,128.74],[310.18,131.68],[307.81,134.66],[305.37,137.69],[302.86,140.75],[300.25,143.83],[297.53,146.92],[294.7,150.01],[291.73,153.1],[288.63,156.16],[285.37,159.19],[281.95,162.17],[278.37,165.09],[274.62,167.94],[270.7,170.71],[266.59,173.38],[262.31,175.95],[257.85,178.4],[253.21,180.72],[248.4,182.91],[243.42,184.95],[238.28,186.83],[232.99,188.54],[227.55,190.09],[221.97,191.46],[216.26,192.65],[210.44,193.66],[204.52,194.48],[198.51,195.11],[192.42,195.56],[186.27,195.82],[180.07,195.9],[173.84,195.79],[167.58,195.51],[161.31,195.06],[155.05,194.45],[148.81,193.68],[142.59,192.77],[136.41,191.71],[130.29,190.53],[124.22,189.23],[118.22,187.83],[112.29,186.33],[106.44,184.75],[100.68,183.09],[95.0,181.38],[89.41,179.62],[83.92,177.83],[78.52,176.02],[73.21,174.19],[67.98,172.37],[62.84,170.56],[57.78,168.76],[52.79,167.0],[47.88,165.27],[43.02,163.59],[38.23,161.97],[33.48,160.4],[28.77,158.89],[24.09,157.45],[19.44,156.08],[14.81,154.78],[10.18,153.56],[5.56,152.4],[0.94,151.31],[-3.7,150.29],[-8.35,149.33],[-13.02,148.43],[-17.71,147.59],[-22.43,146.79],[-27.17,146.04],[-31.94,145.32],[-36.74,144.63],[-41.56,143.95],[-46.4,143.29],[-51.26,142.63],[-56.14,141.96],[-61.02,141.27],[-65.9,140.56],[-70.76,139.82],[-75.62,139.04],[-80.44,138.2],[-85.22,137.31],[-89.96,136.36],[-94.63,135.33],[-99.24,134.23],[-103.76,133.05],[-108.18,131.79],[-112.5,130.43],[-116.71,128.99],[-120.78,127.45],[-124.72,125.82],[-128.52,124.09],[-132.15,122.27],[-135.63,120.36],[-138.94,118.36],[-142.08,116.28],[-145.05,114.12],[-147.84,111.88],[-150.45,109.57],[-152.89,107.19],[-155.16,104.76],[-157.26,102.27],[-159.2,99.75],[-160.99,97.18],[-162.63,94.6],[-164.14,91.99],[-165.53,89.37],[-166.81,86.74],[-168.0,84.12],[-169.12,81.51],[-170.18,78.93],[-171.19,76.37],[-172.19,73.84],[-173.18,71.35],[-174.19,68.9],[-175.23,66.51],[-176.33,64.16],[-177.5,61.88],[-178.77,59.65],[-180.15,57.48],[-181.66,55.38],[-183.31,53.33],[-185.12,51.35],[-187.11,49.43],[-189.28,47.56],[-191.65,45.75],[-194.23,44.0],[-197.02,42.28],[-200.03,40.62],[-203.25,38.99],[-206.71,37.39],[-210.38,35.82],[-214.26,34.26],[-218.36,32.72],[-222.67,31.19],[-227.16,29.65],[-231.84,28.11],[-236.68,26.55],[-241.68,24.97],[-246.8,23.36],[-252.04,21.72],[-257.38,20.04],[-262.78,18.31],[-268.24,16.53],[-273.71,14.7],[-279.19,12.8],[-284.64,10.85],[-290.03,8.83],[-295.35,6.74],[-300.56,4.58],[-305.65,2.35],[-310.58,0.06],[-315.33,-2.31],[-319.88,-4.74],[-324.21,-7.24],[-328.29,-9.8],[-332.12,-12.42],[-335.66,-15.09],[-338.91,-17.82],[-341.85,-20.6],[-344.48,-23.41],[-346.77,-26.27],[-348.73,-29.16],[-350.35,-32.07],[-351.63,-35.0],[-352.57,-37.95],[-353.16,-40.9],[-353.43,-43.86],[-353.36,-46.82],[-352.97,-49.77],[-352.27,-52.71],[-351.28,-55.63],[-350.0,-58.53],[-348.45,-61.4],[-346.65,-64.25],[-344.62,-67.06],[-342.38,-69.85],[-339.94,-72.59],[-337.33,-75.31],[-334.57,-77.98],[-331.67,-80.62],[-328.67,-83.22],[-325.58,-85.79],[-322.42,-88.33],[-319.21,-90.83],[-315.98,-93.31],[-312.73,-95.75],[-309.49,-98.18],[-306.27,-100.59],[-303.09,-102.98],[-299.96,-105.35],[-296.88,-107.72],[-293.88,-110.09],[-290.95,-112.46],[-288.1,-114.82],[-285.34,-117.2],[-282.67,-119.58],[-280.08,-121.98],[-277.58,-124.39],[-275.16,-126.82],[-272.81,-129.27],[-270.54,-131.74],[-268.32,-134.23],[-266.16,-136.74],[-264.03,-139.27],[-261.93,-141.82],[-259.85,-144.38],[-257.76,-146.96],[-255.66,-149.55],[-253.53,-152.15],[-251.35,-154.74],[-249.12,-157.34],[-246.8,-159.92],[-244.4,-162.49],[-241.89,-165.03],[-239.25,-167.55],[-236.49,-170.03],[-233.58,-172.47],[-230.52,-174.85],[-227.29,-177.18],[-223.89,-179.43],[-220.31,-181.62],[-216.54,-183.71],[-212.58,-185.72],[-208.42,-187.63],[-204.08,-189.44],[-199.54,-191.13],[-194.82,-192.71],[-189.91,-194.17],[-184.81,-195.5],[-179.55,-196.7],[-174.13,-197.78],[-168.55,-198.72],[-162.83,-199.52],[-156.98,-200.19],[-151.02,-200.73],[-144.96,-201.14],[-138.81,-201.42],[-132.58,-201.57],[-126.31,-201.61],[-119.99,-201.53],[-113.66,-201.35],[-107.31,-201.07],[-100.98,-200.7],[-94.67,-200.25],[-88.4,-199.73],[-82.18,-199.15],[-76.02,-198.52],[-69.95,-197.85],[-63.96,-197.15],[-58.08,-196.44],[-52.3,-195.72],[-46.63,-195.02],[-41.09,-194.33],[-35.66,-193.68],[-30.37,-193.07],[-25.2,-192.52],[-20.16,-192.03],[-15.25,-191.61],[-10.46,-191.28],[-5.79,-191.04],[-1.23,-190.9],[3.22,-190.86],[7.57,-190.93],[11.84,-191.12],[16.02,-191.43],[20.14,-191.85],[24.2,-192.4],[28.21,-193.07],[32.18,-193.86],[36.14,-194.76],[40.08,-195.78],[44.02,-196.91],[47.98,-198.14],[51.96,-199.46],[55.97,-200.87],[60.03,-202.37],[64.14,-203.93],[68.32,-205.55],[72.56,-207.23],[76.88,-208.94],[81.28,-210.68],[85.76,-212.43],[90.34,-214.18],[95.0,-215.93],[99.75,-217.65],[104.6,-219.34],[109.53,-220.98],[114.54,-222.57],[119.64,-224.09],[124.81,-225.53],[130.05,-226.88],[135.35,-228.13],[140.71,-229.28],[146.12,-230.32],[151.56,-231.23],[157.03,-232.02],[162.53,-232.68],[168.03,-233.2],[173.53,-233.59],[179.02,-233.84],[184.5,-233.96],[189.94,-233.93],[195.36,-233.77],[200.73,-233.48],[206.04,-233.06],[211.31,-232.51],[216.51,-231.85],[221.65,-231.07],[226.71,-230.19],[231.71,-229.2],[236.64,-228.13],[241.49,-226.97],[246.28,-225.74],[250.99,-224.44],[255.64,-223.09],[260.24,-221.69],[264.78,-220.25],[269.27,-218.79],[273.72,-217.3],[278.14,-215.8],[282.53,-214.3],[286.92,-212.8],[291.29,-211.32],[295.68,-209.85],[300.08,-208.4],[304.5,-206.97],[308.96,-205.58],[313.47,-204.22],[318.02,-202.9],[322.64,-201.62],[327.33,-200.37],[332.1,-199.16],[336.94,-197.98],[341.88,-196.84],[346.9,-195.73],[352.01,-194.65],[357.21,-193.59],[362.5,-192.55],[367.88,-191.52],[373.34,-190.5],[378.88,-189.48],[384.49,-188.45],[390.15,-187.41],[395.87,-186.35],[401.62,-185.25],[407.4,-184.12],[413.18,-182.95],[418.96,-181.73],[424.71,-180.45],[430.42,-179.1],[436.06,-177.69],[441.63,-176.2],[447.09,-174.62],[452.43,-172.96],[457.63,-171.21],[462.66,-169.37],[467.51,-167.43],[472.15,-165.39],[476.57,-163.25],[480.75,-161.01],[484.68,-158.68],[488.32,-156.24],[491.68,-153.72],[494.73,-151.09],[497.47,-148.38],[499.89,-145.58],[501.97,-142.71],[503.72,-139.76],[505.13,-136.74],[506.19,-133.66],[506.91,-130.52],[507.28,-127.34],[507.33,-124.11],[507.05,-120.85],[506.44,-117.57],[505.54,-114.27],[504.33,-110.96],[502.85,-107.65],[501.11,-104.35],[499.13,-101.05],[496.93,-97.78],[494.52,-94.53],[491.94,-91.31],[489.21,-88.13],[486.34,-85.0],[483.37,-81.9],[480.32,-78.86],[477.22,-75.87],[474.09,-72.93],[470.96,-70.05],[467.85,-67.23],[464.78,-64.46],[461.78,-61.75],[458.87,-59.1],[456.07,-56.5],[453.39,-53.95],[450.86,-51.45],[448.49,-48.99],[446.29,-46.58],[444.27,-44.21],[442.45,-41.87],[440.83,-39.56],[439.41,-37.27],[438.2,-35.0]],[[439.59,-35.0],[438.53,-32.74],[437.68,-30.49],[437.04,-28.24],[436.6,-25.99],[436.36,-23.75],[436.3,-21.49],[436.42,-19.22],[436.7,-16.93],[437.12,-14.63],[437.67,-12.31],[438.33,-9.96],[439.08,-7.59],[439.9,-5.19],[440.77,-2.76],[441.68,-0.31],[442.59,2.17],[443.49,4.67],[444.35,7.19],[445.16,9.73],[445.9,12.3],[446.54,14.87],[447.07,17.46],[447.46,20.05],[447.71,22.65],[447.8,25.24],[447.72,27.83],[447.45,30.41],[446.98,32.97],[446.31,35.5],[445.43,38.02],[444.34,40.5],[443.03,42.95],[441.51,45.36],[439.77,47.72],[437.82,50.04],[435.67,52.32],[433.32,54.54],[430.78,56.71],[428.06,58.83],[425.17,60.89],[422.13,62.9],[418.95,64.86],[415.64,66.77],[412.21,68.62],[408.7,70.44],[405.1,72.21],[401.44,73.94],[397.74,75.64],[394.01,77.32],[390.26,78.97],[386.51,80.6],[382.78,82.23],[379.08,83.85],[375.42,85.48],[371.81,87.11],[368.27,88.77],[364.8,90.46],[361.41,92.17],[358.11,93.93],[354.89,95.73],[351.77,97.59],[348.75,99.51],[345.81,101.48],[342.97,103.53],[340.21,105.65],[337.54,107.85],[334.93,110.12],[332.4,112.47],[329.92,114.9],[327.49,117.41],[325.1,120.0],[322.73,122.67],[320.37,125.41],[318.0,128.22],[315.61,131.09],[313.19,134.01],[310.73,136.99],[308.2,140.01],[305.6,143.06],[302.9,146.14],[300.11,149.23],[297.19,152.33],[294.15,155.41],[290.98,158.48],[287.65,161.51],[284.17,164.5],[280.53,167.44],[276.71,170.31],[272.73,173.09],[268.57,175.78],[264.23,178.37],[259.71,180.84],[255.01,183.18],[250.15,185.39],[245.11,187.45],[239.91,189.35],[234.56,191.09],[229.06,192.65],[223.42,194.05],[217.65,195.25],[211.77,196.28],[205.78,197.11],[199.7,197.76],[193.54,198.21],[187.32,198.48],[181.05,198.55],[174.74,198.45],[168.41,198.16],[162.07,197.7],[155.74,197.07],[149.42,196.28],[143.13,195.34],[136.88,194.26],[130.68,193.04],[124.54,191.7],[118.47,190.25],[112.47,188.7],[106.56,187.06],[100.73,185.34],[95.0,183.57],[89.36,181.74],[83.81,179.88],[78.36,177.98],[73.01,176.08],[67.75,174.17],[62.57,172.27],[57.48,170.39],[52.47,168.54],[47.54,166.73],[42.67,164.96],[37.86,163.25],[33.1,161.59],[28.39,160.0],[23.72,158.47],[19.07,157.02],[14.44,155.64],[9.83,154.34],[5.22,153.11],[0.61,151.95],[-4.01,150.87],[-8.64,149.85],[-13.29,148.9],[-17.97,148.01],[-22.67,147.17],[-27.4,146.38],[-32.16,145.63],[-36.95,144.91],[-41.77,144.22],[-46.61,143.55],[-51.47,142.88],[-56.36,142.21],[-61.25,141.54],[-66.15,140.84],[-71.05,140.12],[-75.93,139.36],[-80.8,138.56],[-85.63,137.7],[-90.42,136.79],[-95.16,135.81],[-99.84,134.76],[-104.43,133.63],[-108.95,132.41],[-113.36,131.11],[-117.66,129.72],[-121.84,128.24],[-125.89,126.67],[-129.8,125.0],[-133.56,123.24],[-137.16,121.39],[-140.6,119.45],[-143.87,117.42],[-146.97,115.31],[-149.9,113.12],[-152.65,110.86],[-155.23,108.53],[-157.63,106.14],[-159.87,103.69],[-161.94,101.2],[-163.86,98.67],[-165.63,96.11],[-167.27,93.52],[-168.78,90.92],[-170.18,88.31],[-171.49,85.7],[-172.71,83.1],[-173.87,80.51],[-174.98,77.95],[-176.06,75.42],[-177.14,72.92],[-178.22,70.46],[-179.33,68.05],[-180.5,65.69],[-181.73,63.38],[-183.04,61.13],[-184.47,58.93],[-186.01,56.8],[-187.7,54.73],[-189.54,52.71],[-191.55,50.76],[-193.75,48.86],[-196.14,47.02],[-198.73,45.22],[-201.54,43.48],[-204.56,41.78],[-207.8,40.11],[-211.26,38.48],[-214.95,36.88],[-218.85,35.29],[-222.97,33.72],[-227.29,32.15],[-231.81,30.59],[-236.52,29.01],[-241.39,27.43],[-246.43,25.82],[-251.6,24.18],[-256.89,22.51],[-262.27,20.8],[-267.74,19.05],[-273.25,17.24],[-278.8,15.38],[-284.35,13.46],[-289.88,11.48],[-295.36,9.43],[-300.77,7.32],[-306.08,5.13],[-311.26,2.88],[-316.29,0.55],[-321.14,-1.84],[-325.8,-4.31],[-330.23,-6.84],[-334.42,-9.43],[-338.35,-12.09],[-342.0,-14.8],[-345.35,-17.57],[-348.39,-20.38],[-351.11,-23.24],[-353.49,-26.14],[-355.53,-29.07],[-357.23,-32.02],[-358.57,-35.0],[-359.57,-37.99],[-360.21,-41.0],[-360.51,-44.0],[-360.47,-47.01],[-360.1,-50.0],[-359.4,-52.99],[-358.4,-55.96],[-357.1,-58.9],[-355.52,-61.82],[-353.67,-64.71],[-351.58,-67.57],[-349.26,-70.4],[-346.74,-73.18],[-344.03,-75.93],[-341.15,-78.64],[-338.14,-81.31],[-335.0,-83.94],[-331.76,-86.54],[-328.44,-89.1],[-325.07,-91.62],[-321.66,-94.11],[-318.23,-96.57],[-314.8,-99.01],[-311.39,-101.42],[-308.0,-103.82],[-304.67,-106.19],[-301.39,-108.56],[-298.17,-110.92],[-295.03,-113.28],[-291.98,-115.63],[-289.01,-117.99],[-286.13,-120.36],[-283.34,-122.74],[-280.64,-125.13],[-278.03,-127.54],[-275.5,-129.96],[-273.05,-132.41],[-270.66,-134.87],[-268.34,-137.36],[-266.06,-139.86],[-263.82,-142.38],[-261.6,-144.93],[-259.4,-147.48],[-257.18,-150.05],[-254.95,-152.62],[-252.69,-155.2],[-250.37,-157.78],[-247.99,-160.35],[-245.53,-162.91],[-242.97,-165.45],[-240.3,-167.97],[-237.51,-170.45],[-234.59,-172.89],[-231.51,-175.28],[-228.28,-177.61],[-224.88,-179.88],[-221.31,-182.08],[-217.56,-184.2],[-213.62,-186.23],[-209.5,-188.17],[-205.18,-190.01],[-200.68,-191.73],[-195.99,-193.35],[-191.11,-194.84],[-186.06,-196.21],[-180.83,-197.46],[-175.44,-198.57],[-169.9,-199.55],[-164.22,-200.4],[-158.4,-201.12],[-152.46,-201.7],[-146.42,-202.15],[-140.29,-202.47],[-134.09,-202.67],[-127.83,-202.75],[-121.52,-202.72],[-115.19,-202.57],[-108.84,-202.33],[-102.5,-201.99],[-96.18,-201.57],[-89.9,-201.08],[-83.66,-200.52],[-77.48,-199.91],[-71.38,-199.26],[-65.37,-198.58],[-59.45,-197.89],[-53.63,-197.18],[-47.93,-196.49],[-42.34,-195.81],[-36.88,-195.16],[-31.54,-194.55],[-26.33,-194.0],[-21.25,-193.5],[-16.29,-193.08],[-11.45,-192.75],[-6.73,-192.5],[-2.13,-192.36],[2.36,-192.31],[6.76,-192.38],[11.07,-192.57],[15.29,-192.87],[19.45,-193.3],[23.55,-193.84],[27.6,-194.52],[31.61,-195.31],[35.6,-196.22],[39.57,-197.26],[43.55,-198.4],[47.54,-199.65],[51.56,-201.0],[55.6,-202.44],[59.7,-203.96],[63.84,-205.56],[68.05,-207.23],[72.34,-208.94],[76.69,-210.71],[81.14,-212.5],[85.67,-214.31],[90.29,-216.12],[95.0,-217.93],[99.81,-219.73],[104.71,-221.49],[109.7,-223.21],[114.78,-224.87],[119.95,-226.47],[125.19,-227.99],[130.51,-229.42],[135.9,-230.76],[141.35,-231.99],[146.85,-233.11],[152.39,-234.1],[157.96,-234.97],[163.56,-235.71],[169.17,-236.31],[174.78,-236.77],[180.39,-237.09],[185.98,-237.27],[191.55,-237.3],[197.08,-237.2],[202.58,-236.95],[208.02,-236.58],[213.4,-236.07],[218.72,-235.43],[223.98,-234.68],[229.16,-233.81],[234.28,-232.84],[239.31,-231.77],[244.27,-230.61],[249.16,-229.37],[253.97,-228.06],[258.71,-226.68],[263.39,-225.25],[268.01,-223.78],[272.57,-222.27],[277.09,-220.74],[281.56,-219.18],[286.01,-217.62],[290.43,-216.06],[294.84,-214.5],[299.25,-212.95],[303.66,-211.43],[308.1,-209.92],[312.56,-208.45],[317.05,-207.0],[321.6,-205.59],[326.2,-204.22],[330.86,-202.88],[335.59,-201.58],[340.4,-200.31],[345.29,-199.08],[350.27,-197.88],[355.33,-196.71],[360.48,-195.57],[365.72,-194.44],[371.04,-193.34],[376.45,-192.24],[381.93,-191.14],[387.48,-190.04],[393.09,-188.93],[398.75,-187.8],[404.46,-186.64],[410.19,-185.46],[415.93,-184.23],[421.67,-182.96],[427.38,-181.63],[433.06,-180.24],[438.68,-178.79],[444.23,-177.26],[449.68,-175.65],[455.01,-173.96],[460.2,-172.18],[465.23,-170.31],[470.09,-168.35],[474.75,-166.29],[479.19,-164.13],[483.39,-161.87],[487.33,-159.52],[491.01,-157.07],[494.4,-154.53],[497.48,-151.89],[500.26,-149.17],[502.71,-146.36],[504.83,-143.46],[506.61,-140.5],[508.05,-137.47],[509.15,-134.37],[509.9,-131.22],[510.31,-128.01],[510.38,-124.77],[510.12,-121.49],[509.53,-118.19],[508.63,-114.87],[507.44,-111.54],[505.96,-108.21],[504.21,-104.88],[502.22,-101.56],[499.99,-98.26],[497.56,-94.98],[494.95,-91.74],[492.17,-88.53],[489.26,-85.37],[486.23,-82.25],[483.12,-79.18],[479.96,-76.16],[476.75,-73.2],[473.54,-70.29],[470.35,-67.44],[467.2,-64.65],[464.11,-61.92],[461.11,-59.25],[458.21,-56.62],[455.44,-54.06],[452.82,-51.54],[450.36,-49.07],[448.07,-46.64],[445.97,-44.25],[444.06,-41.9],[442.36,-39.58],[440.87,-37.28],[439.59,-35.0]],[[441.06,-35.0],[439.94,-32.73],[439.04,-30.47],[438.36,-28.21],[437.89,-25.96],[437.62,-23.7],[437.56,-21.44],[437.67,-19.16],[437.96,-16.87],[438.4,-14.55],[438.98,-12.22],[439.69,-9.86],[440.5,-7.47],[441.39,-5.06],[442.34,-2.62],[443.33,-0.15],[444.35,2.35],[445.36,4.88],[446.34,7.43],[447.28,10.01],[448.16,12.6],[448.94,15.21],[449.62,17.84],[450.18,20.48],[450.59,23.12],[450.85,25.76],[450.93,28.4],[450.83,31.03],[450.54,33.65],[450.04,36.25],[449.33,38.83],[448.4,41.38],[447.26,43.89],[445.89,46.37],[444.31,48.81],[442.51,51.2],[440.49,53.55],[438.27,55.85],[435.85,58.09],[433.24,60.29],[430.45,62.42],[427.5,64.51],[424.39,66.54],[421.15,68.52],[417.78,70.44],[414.31,72.32],[410.74,74.16],[407.1,75.95],[403.4,77.71],[399.66,79.44],[395.89,81.14],[392.11,82.82],[388.34,84.49],[384.59,86.15],[380.87,87.82],[377.19,89.49],[373.57,91.17],[370.01,92.88],[366.53,94.62],[363.12,96.39],[359.8,98.2],[356.57,100.07],[353.43,101.99],[350.37,103.97],[347.41,106.01],[344.53,108.13],[341.73,110.32],[339.0,112.58],[336.34,114.92],[333.74,117.34],[331.19,119.84],[328.68,122.41],[326.19,125.06],[323.71,127.79],[321.23,130.58],[318.73,133.44],[316.21,136.35],[313.64,139.32],[311.02,142.32],[308.32,145.37],[305.54,148.44],[302.66,151.52],[299.66,154.62],[296.55,157.7],[293.3,160.77],[289.9,163.81],[286.35,166.8],[282.64,169.75],[278.76,172.62],[274.72,175.42],[270.49,178.12],[266.1,180.73],[261.52,183.21],[256.77,185.58],[251.84,187.8],[246.75,189.88],[241.5,191.8],[236.08,193.56],[230.52,195.15],[224.82,196.55],[219.0,197.78],[213.05,198.82],[207.0,199.67],[200.85,200.32],[194.63,200.79],[188.34,201.06],[182.0,201.14],[175.63,201.03],[169.22,200.74],[162.81,200.26],[156.4,199.62],[150.01,198.81],[143.65,197.85],[137.33,196.73],[131.06,195.48],[124.85,194.1],[118.71,192.61],[112.65,191.01],[106.68,189.31],[100.79,187.54],[95.0,185.7],[89.31,183.81],[83.71,181.87],[78.21,179.91],[72.82,177.93],[67.52,175.94],[62.31,173.96],[57.19,171.99],[52.16,170.05],[47.2,168.15],[42.32,166.3],[37.5,164.5],[32.74,162.75],[28.02,161.07],[23.35,159.47],[18.71,157.93],[14.09,156.48],[9.49,155.1],[4.9,153.79],[0.3,152.57],[-4.3,151.42],[-8.92,150.35],[-13.55,149.35],[-18.21,148.41],[-22.9,147.53],[-27.62,146.7],[-32.36,145.92],[-37.15,145.18],[-41.96,144.48],[-46.8,143.79],[-51.67,143.12],[-56.56,142.46],[-61.47,141.79],[-66.4,141.11],[-71.32,140.41],[-76.24,139.67],[-81.15,138.9],[-86.03,138.08],[-90.88,137.21],[-95.68,136.27],[-100.42,135.27],[-105.1,134.19],[-109.7,133.03],[-114.2,131.79],[-118.61,130.46],[-122.89,129.04],[-127.06,127.53],[-131.08,125.92],[-134.97,124.22],[-138.7,122.43],[-142.27,120.55],[-145.68,118.58],[-148.92,116.52],[-151.99,114.39],[-154.88,112.17],[-157.6,109.89],[-160.15,107.55],[-162.53,105.14],[-164.75,102.69],[-166.81,100.19],[-168.71,97.66],[-170.48,95.09],[-172.12,92.51],[-173.65,89.92],[-175.07,87.32],[-176.41,84.73],[-177.67,82.15],[-178.88,79.58],[-180.06,77.04],[-181.22,74.54],[-182.39,72.07],[-183.57,69.64],[-184.8,67.26],[-186.09,64.93],[-187.46,62.65],[-188.93,60.43],[-190.52,58.27],[-192.24,56.17],[-194.12,54.12],[-196.16,52.13],[-198.37,50.2],[-200.78,48.32],[-203.39,46.5],[-206.21,44.72],[-209.24,42.98],[-212.49,41.28],[-215.97,39.61],[-219.66,37.97],[-223.58,36.35],[-227.71,34.74],[-232.05,33.14],[-236.59,31.55],[-241.31,29.94],[-246.21,28.32],[-251.28,26.68],[-256.48,25.02],[-261.81,23.32],[-267.24,21.58],[-272.76,19.8],[-278.33,17.96],[-283.94,16.08],[-289.56,14.13],[-295.16,12.12],[-300.72,10.04],[-306.21,7.9],[-311.6,5.68],[-316.87,3.4],[-322.0,1.04],[-326.95,-1.38],[-331.7,-3.88],[-336.23,-6.44],[-340.52,-9.07],[-344.55,-11.76],[-348.3,-14.51],[-351.74,-17.31],[-354.88,-20.17],[-357.68,-23.07],[-360.15,-26.0],[-362.27,-28.98],[-364.04,-31.98],[-365.44,-35.0],[-366.49,-38.04],[-367.19,-41.09],[-367.52,-44.14],[-367.51,-47.19],[-367.15,-50.24],[-366.46,-53.27],[-365.45,-56.28],[-364.12,-59.27],[-362.51,-62.24],[-360.62,-65.17],[-358.46,-68.07],[-356.07,-70.94],[-353.46,-73.76],[-350.65,-76.55],[-347.67,-79.29],[-344.53,-82.0],[-341.26,-84.66],[-337.87,-87.28],[-334.4,-89.86],[-330.86,-92.4],[-327.28,-94.91],[-323.66,-97.38],[-320.04,-99.83],[-316.43,-102.25],[-312.85,-104.64],[-309.31,-107.02],[-305.82,-109.38],[-302.39,-111.73],[-299.04,-114.08],[-295.78,-116.42],[-292.6,-118.77],[-289.51,-121.12],[-286.52,-123.48],[-283.63,-125.85],[-280.82,-128.23],[-278.11,-130.63],[-275.47,-133.05],[-272.92,-135.49],[-270.43,-137.95],[-268.0,-140.42],[-265.61,-142.92],[-263.26,-145.44],[-260.93,-147.97],[-258.61,-150.51],[-256.27,-153.07],[-253.92,-155.63],[-251.52,-158.19],[-249.07,-160.75],[-246.55,-163.3],[-243.95,-165.83],[-241.24,-168.34],[-238.43,-170.82],[-235.48,-173.26],[-232.4,-175.66],[-229.17,-178.01],[-225.78,-180.29],[-222.22,-182.51],[-218.49,-184.65],[-214.57,-186.7],[-210.48,-188.67],[-206.2,-190.53],[-201.73,-192.29],[-197.08,-193.94],[-192.25,-195.48],[-187.24,-196.89],[-182.05,-198.18],[-176.71,-199.34],[-171.2,-200.36],[-165.56,-201.26],[-159.78,-202.02],[-153.87,-202.65],[-147.86,-203.15],[-141.76,-203.52],[-135.58,-203.76],[-129.33,-203.89],[-123.04,-203.89],[-116.72,-203.79],[-110.38,-203.59],[-104.04,-203.29],[-97.71,-202.9],[-91.41,-202.44],[-85.16,-201.92],[-78.97,-201.33],[-72.85,-200.71],[-66.81,-200.05],[-60.86,-199.37],[-55.01,-198.68],[-49.27,-198.0],[-43.64,-197.33],[-38.14,-196.69],[-32.76,-196.09],[-27.5,-195.53],[-22.37,-195.04],[-17.37,-194.62],[-12.49,-194.29],[-7.73,-194.04],[-3.08,-193.89],[1.46,-193.84],[5.91,-193.91],[10.26,-194.09],[14.53,-194.39],[18.72,-194.82],[22.86,-195.37],[26.95,-196.04],[31.0,-196.84],[35.03,-197.76],[39.05,-198.81],[43.06,-199.96],[47.09,-201.23],[51.14,-202.6],[55.22,-204.07],[59.35,-205.63],[63.53,-207.26],[67.78,-208.96],[72.1,-210.72],[76.5,-212.53],[80.99,-214.38],[85.57,-216.24],[90.23,-218.12],[95.0,-219.99],[99.86,-221.85],[104.82,-223.68],[109.88,-225.47],[115.03,-227.21],[120.26,-228.89],[125.58,-230.49],[130.99,-232.0],[136.46,-233.42],[141.99,-234.73],[147.59,-235.93],[153.22,-237.0],[158.9,-237.95],[164.6,-238.76],[170.32,-239.43],[176.05,-239.97],[181.77,-240.35],[187.48,-240.59],[193.17,-240.69],[198.82,-240.64],[204.44,-240.45],[210.0,-240.11],[215.51,-239.64],[220.95,-239.04],[226.32,-238.31],[231.63,-237.46],[236.85,-236.5],[242.0,-235.43],[247.07,-234.27],[252.05,-233.02],[256.96,-231.69],[261.8,-230.29],[266.56,-228.83],[271.25,-227.32],[275.89,-225.77],[280.47,-224.18],[285.0,-222.58],[289.49,-220.95],[293.95,-219.32],[298.39,-217.69],[302.83,-216.07],[307.26,-214.47],[311.7,-212.88],[316.16,-211.32],[320.65,-209.78],[325.17,-208.28],[329.75,-206.82],[334.38,-205.39],[339.08,-203.99],[343.85,-202.63],[348.69,-201.31],[353.62,-200.02],[358.62,-198.76],[363.72,-197.53],[368.9,-196.32],[374.16,-195.12],[379.5,-193.94],[384.92,-192.77],[390.41,-191.59],[395.96,-190.41],[401.57,-189.21],[407.22,-188.0],[412.89,-186.75],[418.58,-185.47],[424.28,-184.14],[429.95,-182.76],[435.6,-181.33],[441.19,-179.83],[446.71,-178.27],[452.14,-176.62],[457.45,-174.9],[462.64,-173.1],[467.67,-171.2],[472.53,-169.21],[477.19,-167.13],[481.65,-164.96],[485.87,-162.68],[489.84,-160.32],[493.54,-157.85],[496.96,-155.29],[500.08,-152.64],[502.89,-149.91],[505.38,-147.08],[507.54,-144.18],[509.36,-141.2],[510.84,-138.16],[511.97,-135.04],[512.76,-131.88],[513.2,-128.66],[513.3,-125.4],[513.06,-122.11],[512.5,-118.79],[511.62,-115.45],[510.44,-112.1],[508.96,-108.74],[507.22,-105.39],[505.22,-102.05],[502.98,-98.72],[500.53,-95.43],[497.89,-92.16],[495.08,-88.93],[492.13,-85.73],[489.06,-82.59],[485.9,-79.49],[482.67,-76.45],[479.4,-73.46],[476.12,-70.53],[472.86,-67.66],[469.62,-64.85],[466.45,-62.09],[463.37,-59.4],[460.39,-56.75],[457.53,-54.17],[454.82,-51.63],[452.27,-49.14],[449.9,-46.7],[447.71,-44.3],[445.73,-41.93],[443.96,-39.6],[442.4,-37.29],[441.06,-35.0]],[[442.59,-35.0],[441.42,-32.72],[440.47,-30.45],[439.75,-28.19],[439.26,-25.92],[438.97,-23.66],[438.89,-21.39],[439.01,-19.1],[439.3,-16.8],[439.77,-14.47],[440.39,-12.13],[441.13,-9.75],[442.0,-7.35],[442.96,-4.92],[443.99,-2.46],[445.07,0.03],[446.18,2.55],[447.31,5.1],[448.41,7.68],[449.48,10.29],[450.49,12.92],[451.42,15.57],[452.26,18.23],[452.97,20.91],[453.54,23.6],[453.97,26.3],[454.22,28.99],[454.29,31.68],[454.17,34.35],[453.84,37.02],[453.3,39.66],[452.55,42.27],[451.56,44.86],[450.36,47.41],[448.93,49.92],[447.27,52.39],[445.39,54.81],[443.3,57.18],[441.01,59.5],[438.51,61.77],[435.82,63.98],[432.96,66.14],[429.93,68.25],[426.76,70.3],[423.44,72.29],[420.01,74.24],[416.48,76.14],[412.85,78.0],[409.16,79.82],[405.41,81.6],[401.63,83.35],[397.82,85.09],[394.01,86.8],[390.2,88.5],[386.42,90.2],[382.67,91.9],[378.96,93.62],[375.32,95.35],[371.73,97.1],[368.23,98.89],[364.79,100.71],[361.45,102.59],[358.18,104.51],[355.01,106.49],[351.91,108.53],[348.91,110.64],[345.98,112.82],[343.12,115.07],[340.33,117.4],[337.6,119.8],[334.92,122.28],[332.28,124.84],[329.67,127.47],[327.07,130.18],[324.47,132.95],[321.86,135.79],[319.23,138.69],[316.56,141.64],[313.83,144.63],[311.04,147.66],[308.16,150.72],[305.19,153.8],[302.11,156.88],[298.91,159.96],[295.58,163.02],[292.11,166.06],[288.49,169.06],[284.71,172.01],[280.77,174.89],[276.66,177.69],[272.38,180.41],[267.92,183.02],[263.28,185.52],[258.47,187.9],[253.49,190.14],[248.34,192.24],[243.03,194.18],[237.56,195.95],[231.94,197.56],[226.19,198.98],[220.3,200.23],[214.29,201.28],[208.18,202.14],[201.97,202.81],[195.69,203.28],[189.33,203.56],[182.93,203.64],[176.48,203.53],[170.01,203.23],[163.53,202.75],[157.05,202.1],[150.59,201.27],[144.16,200.28],[137.77,199.14],[131.43,197.86],[125.16,196.44],[118.95,194.9],[112.83,193.26],[106.79,191.51],[100.85,189.69],[95.0,187.79],[89.25,185.83],[83.61,183.83],[78.07,181.79],[72.63,179.73],[67.29,177.67],[62.05,175.6],[56.9,173.56],[51.85,171.54],[46.87,169.55],[41.97,167.61],[37.14,165.72],[32.38,163.89],[27.66,162.13],[22.99,160.44],[18.36,158.83],[13.75,157.29],[9.16,155.84],[4.58,154.46],[-0.0,153.17],[-4.59,151.96],[-9.19,150.83],[-13.81,149.78],[-18.45,148.79],[-23.12,147.87],[-27.82,147.01],[-32.56,146.2],[-37.33,145.44],[-42.14,144.72],[-46.98,144.02],[-51.86,143.35],[-56.76,142.69],[-61.68,142.03],[-66.63,141.36],[-71.58,140.68],[-76.53,139.97],[-81.48,139.23],[-86.42,138.45],[-91.32,137.62],[-96.19,136.73],[-101.01,135.78],[-105.76,134.75],[-110.45,133.65],[-115.05,132.46],[-119.56,131.19],[-123.95,129.84],[-128.23,128.39],[-132.38,126.84],[-136.39,125.21],[-140.26,123.48],[-143.97,121.66],[-147.52,119.75],[-150.9,117.75],[-154.12,115.67],[-157.16,113.51],[-160.03,111.28],[-162.72,108.98],[-165.25,106.62],[-167.61,104.21],[-169.82,101.74],[-171.87,99.24],[-173.77,96.71],[-175.55,94.15],[-177.2,91.57],[-178.75,88.99],[-180.2,86.41],[-181.58,83.83],[-182.9,81.26],[-184.18,78.72],[-185.43,76.21],[-186.68,73.73],[-187.95,71.28],[-189.25,68.89],[-190.6,66.53],[-192.03,64.23],[-193.55,61.99],[-195.18,59.79],[-196.94,57.66],[-198.85,55.58],[-200.91,53.56],[-203.15,51.59],[-205.58,49.68],[-208.2,47.81],[-211.03,45.99],[-214.07,44.22],[-217.33,42.48],[-220.81,40.77],[-224.52,39.1],[-228.44,37.44],[-232.58,35.8],[-236.93,34.16],[-241.48,32.53],[-246.22,30.89],[-251.14,29.24],[-256.23,27.56],[-261.46,25.87],[-266.82,24.14],[-272.29,22.37],[-277.85,20.56],[-283.47,18.69],[-289.13,16.78],[-294.8,14.8],[-300.47,12.76],[-306.1,10.65],[-311.66,8.48],[-317.13,6.24],[-322.48,3.92],[-327.69,1.54],[-332.73,-0.92],[-337.58,-3.45],[-342.2,-6.05],[-346.59,-8.71],[-350.71,-11.44],[-354.55,-14.22],[-358.08,-17.06],[-361.3,-19.96],[-364.19,-22.89],[-366.74,-25.87],[-368.93,-28.89],[-370.77,-31.93],[-372.24,-35.0],[-373.34,-38.08],[-374.08,-41.18],[-374.45,-44.28],[-374.46,-47.38],[-374.12,-50.47],[-373.43,-53.54],[-372.41,-56.6],[-371.06,-59.64],[-369.42,-62.65],[-367.48,-65.63],[-365.27,-68.57],[-362.8,-71.47],[-360.11,-74.34],[-357.2,-77.16],[-354.11,-79.94],[-350.84,-82.67],[-347.44,-85.36],[-343.91,-88.01],[-340.28,-90.61],[-336.58,-93.17],[-332.82,-95.69],[-329.02,-98.18],[-325.21,-100.64],[-321.41,-103.06],[-317.62,-105.46],[-313.87,-107.83],[-310.18,-110.19],[-306.54,-112.54],[-302.98,-114.87],[-299.5,-117.2],[-296.12,-119.53],[-292.82,-121.86],[-289.63,-124.2],[-286.53,-126.54],[-283.53,-128.9],[-280.63,-131.28],[-277.81,-133.67],[-275.08,-136.08],[-272.43,-138.51],[-269.84,-140.96],[-267.31,-143.43],[-264.83,-145.92],[-262.37,-148.43],[-259.93,-150.95],[-257.5,-153.48],[-255.05,-156.02],[-252.57,-158.56],[-250.05,-161.11],[-247.48,-163.64],[-244.82,-166.17],[-242.08,-168.67],[-239.24,-171.15],[-236.28,-173.6],[-233.19,-176.0],[-229.96,-178.35],[-226.58,-180.65],[-223.03,-182.88],[-219.33,-185.05],[-215.44,-187.13],[-211.38,-189.12],[-207.14,-191.02],[-202.71,-192.81],[-198.1,-194.5],[-193.32,-196.07],[-188.35,-197.53],[-183.22,-198.86],[-177.92,-200.07],[-172.46,-201.14],[-166.86,-202.09],[-161.12,-202.9],[-155.25,-203.58],[-149.28,-204.13],[-143.21,-204.55],[-137.05,-204.84],[-130.83,-205.02],[-124.56,-205.07],[-118.25,-205.01],[-111.92,-204.85],[-105.58,-204.6],[-99.26,-204.25],[-92.96,-203.83],[-86.7,-203.34],[-80.49,-202.79],[-74.35,-202.19],[-68.28,-201.55],[-62.3,-200.9],[-56.43,-200.23],[-50.65,-199.56],[-44.99,-198.91],[-39.45,-198.28],[-34.03,-197.68],[-28.73,-197.14],[-23.55,-196.65],[-18.5,-196.23],[-13.58,-195.9],[-8.77,-195.65],[-4.07,-195.5],[0.52,-195.45],[5.01,-195.51],[9.4,-195.69],[13.72,-195.99],[17.96,-196.42],[22.14,-196.97],[26.27,-197.65],[30.37,-198.45],[34.43,-199.38],[38.49,-200.44],[42.54,-201.61],[46.61,-202.89],[50.7,-204.28],[54.82,-205.77],[58.99,-207.36],[63.21,-209.03],[67.5,-210.76],[71.86,-212.57],[76.31,-214.42],[80.84,-216.31],[85.46,-218.23],[90.18,-220.16],[95.0,-222.1],[99.92,-224.02],[104.94,-225.92],[110.06,-227.78],[115.27,-229.59],[120.58,-231.34],[125.98,-233.02],[131.46,-234.61],[137.02,-236.11],[142.65,-237.5],[148.33,-238.77],[154.07,-239.92],[159.84,-240.95],[165.65,-241.84],[171.48,-242.58],[177.32,-243.18],[183.16,-243.64],[188.99,-243.94],[194.79,-244.1],[200.57,-244.1],[206.3,-243.95],[211.99,-243.66],[217.62,-243.23],[223.18,-242.66],[228.68,-241.95],[234.1,-241.12],[239.44,-240.17],[244.69,-239.11],[249.87,-237.95],[254.96,-236.69],[259.97,-235.34],[264.89,-233.91],[269.74,-232.42],[274.51,-230.87],[279.21,-229.28],[283.86,-227.64],[288.44,-225.98],[292.98,-224.29],[297.48,-222.59],[301.96,-220.89],[306.41,-219.2],[310.85,-217.51],[315.3,-215.84],[319.76,-214.19],[324.23,-212.56],[328.74,-210.97],[333.3,-209.41],[337.9,-207.89],[342.55,-206.4],[347.28,-204.94],[352.07,-203.53],[356.94,-202.14],[361.89,-200.79],[366.92,-199.47],[372.03,-198.17],[377.23,-196.89],[382.51,-195.62],[387.86,-194.37],[393.28,-193.11],[398.77,-191.86],[404.31,-190.59],[409.89,-189.31],[415.51,-188.0],[421.15,-186.66],[426.79,-185.28],[432.42,-183.85],[438.02,-182.37],[443.58,-180.83],[449.07,-179.23],[454.47,-177.55],[459.77,-175.8],[464.94,-173.96],[469.97,-172.04],[474.82,-170.03],[479.49,-167.93],[483.96,-165.73],[488.19,-163.45],[492.18,-161.06],[495.91,-158.58],[499.36,-156.01],[502.51,-153.35],[505.36,-150.6],[507.89,-147.77],[510.09,-144.86],[511.95,-141.87],[513.47,-138.81],[514.64,-135.69],[515.47,-132.51],[515.95,-129.28],[516.08,-126.0],[515.88,-122.7],[515.35,-119.36],[514.49,-116.0],[513.33,-112.63],[511.87,-109.26],[510.13,-105.89],[508.13,-102.52],[505.89,-99.18],[503.43,-95.86],[500.77,-92.57],[497.94,-89.31],[494.96,-86.1],[491.85,-82.93],[488.65,-79.81],[485.37,-76.74],[482.05,-73.73],[478.7,-70.77],[475.37,-67.88],[472.07,-65.04],[468.82,-62.27],[465.66,-59.55],[462.6,-56.89],[459.66,-54.28],[456.87,-51.73],[454.24,-49.22],[451.79,-46.76],[449.52,-44.35],[447.47,-41.97],[445.62,-39.62],[443.99,-37.3],[442.59,-35.0]],[[444.22,-35.0],[442.99,-32.71],[442.0,-30.43],[441.24,-28.16],[440.72,-25.89],[440.41,-23.61],[440.32,-21.33],[440.44,-19.03],[440.75,-16.72],[441.23,-14.39],[441.88,-12.03],[442.67,-9.64],[443.59,-7.23],[444.61,-4.78],[445.72,-2.3],[446.89,0.21],[448.11,2.75],[449.34,5.33],[450.56,7.94],[451.76,10.58],[452.91,13.24],[453.98,15.93],[454.96,18.64],[455.83,21.36],[456.57,24.1],[457.16,26.84],[457.58,29.59],[457.83,32.33],[457.88,35.07],[457.72,37.79],[457.35,40.5],[456.76,43.18],[455.95,45.84],[454.9,48.46],[453.62,51.05],[452.12,53.59],[450.38,56.09],[448.42,58.54],[446.25,60.93],[443.87,63.28],[441.28,65.57],[438.51,67.8],[435.57,69.98],[432.46,72.11],[429.2,74.17],[425.82,76.19],[422.31,78.16],[418.71,80.08],[415.02,81.96],[411.26,83.8],[407.46,85.61],[403.62,87.39],[399.76,89.14],[395.91,90.89],[392.06,92.62],[388.23,94.36],[384.45,96.1],[380.71,97.85],[377.03,99.63],[373.41,101.43],[369.87,103.27],[366.4,105.14],[363.01,107.07],[359.71,109.05],[356.48,111.08],[353.34,113.18],[350.28,115.35],[347.29,117.59],[344.36,119.9],[341.5,122.29],[338.68,124.75],[335.91,127.29],[333.17,129.9],[330.44,132.58],[327.72,135.33],[325.0,138.15],[322.25,141.03],[319.46,143.95],[316.63,146.93],[313.73,149.94],[310.76,152.98],[307.69,156.04],[304.52,159.12],[301.24,162.19],[297.83,165.24],[294.28,168.28],[290.59,171.27],[286.74,174.22],[282.73,177.1],[278.55,179.91],[274.21,182.63],[269.69,185.26],[265.0,187.77],[260.13,190.16],[255.09,192.41],[249.89,194.52],[244.52,196.48],[238.99,198.27],[233.32,199.89],[227.5,201.33],[221.56,202.59],[215.49,203.66],[209.32,204.53],[203.05,205.21],[196.7,205.69],[190.29,205.97],[183.82,206.06],[177.31,205.95],[170.77,205.65],[164.22,205.16],[157.68,204.49],[151.15,203.65],[144.65,202.65],[138.2,201.48],[131.79,200.17],[125.45,198.72],[119.19,197.14],[113.0,195.45],[106.9,193.66],[100.9,191.78],[95.0,189.82],[89.2,187.8],[83.51,185.73],[77.92,183.63],[72.44,181.5],[67.07,179.36],[61.8,177.22],[56.62,175.09],[51.54,172.99],[46.55,170.92],[41.64,168.89],[36.8,166.92],[32.02,165.01],[27.31,163.17],[22.64,161.4],[18.01,159.7],[13.41,158.09],[8.83,156.56],[4.26,155.12],[-0.3,153.76],[-4.87,152.49],[-9.45,151.3],[-14.05,150.2],[-18.68,149.16],[-23.33,148.2],[-28.02,147.31],[-32.75,146.47],[-37.51,145.69],[-42.32,144.95],[-47.16,144.24],[-52.04,143.56],[-56.95,142.91],[-61.89,142.26],[-66.85,141.61],[-71.83,140.95],[-76.82,140.27],[-81.81,139.56],[-86.8,138.82],[-91.76,138.03],[-96.69,137.18],[-101.59,136.28],[-106.43,135.31],[-111.2,134.27],[-115.9,133.14],[-120.51,131.93],[-125.02,130.64],[-129.42,129.25],[-133.69,127.78],[-137.83,126.21],[-141.84,124.54],[-145.69,122.79],[-149.38,120.94],[-152.91,119.0],[-156.28,116.98],[-159.47,114.88],[-162.5,112.7],[-165.35,110.45],[-168.03,108.13],[-170.54,105.76],[-172.9,103.33],[-175.09,100.87],[-177.15,98.36],[-179.06,95.83],[-180.85,93.27],[-182.53,90.7],[-184.11,88.13],[-185.61,85.56],[-187.04,83.0],[-188.42,80.45],[-189.77,77.93],[-191.11,75.44],[-192.46,72.98],[-193.84,70.56],[-195.26,68.19],[-196.75,65.86],[-198.32,63.59],[-200.0,61.37],[-201.8,59.2],[-203.73,57.09],[-205.83,55.03],[-208.09,53.02],[-210.53,51.07],[-213.17,49.17],[-216.01,47.31],[-219.05,45.49],[-222.32,43.72],[-225.8,41.97],[-229.51,40.25],[-233.43,38.56],[-237.58,36.88],[-241.93,35.2],[-246.49,33.53],[-251.24,31.86],[-256.17,30.17],[-261.27,28.46],[-266.52,26.73],[-271.91,24.97],[-277.4,23.17],[-283.0,21.32],[-288.66,19.43],[-294.36,17.48],[-300.09,15.47],[-305.81,13.4],[-311.49,11.27],[-317.12,9.07],[-322.66,6.79],[-328.09,4.45],[-333.38,2.03],[-338.5,-0.46],[-343.43,-3.02],[-348.14,-5.65],[-352.61,-8.35],[-356.81,-11.11],[-360.74,-13.93],[-364.36,-16.81],[-367.66,-19.75],[-370.63,-22.72],[-373.25,-25.75],[-375.52,-28.8],[-377.42,-31.89],[-378.95,-35.0],[-380.1,-38.13],[-380.88,-41.27],[-381.29,-44.41],[-381.32,-47.56],[-380.99,-50.69],[-380.31,-53.82],[-379.28,-56.92],[-377.91,-60.0],[-376.23,-63.06],[-374.25,-66.08],[-371.98,-69.06],[-369.44,-72.0],[-366.66,-74.9],[-363.66,-77.76],[-360.46,-80.57],[-357.07,-83.34],[-353.53,-86.05],[-349.86,-88.72],[-346.08,-91.35],[-342.21,-93.93],[-338.28,-96.47],[-334.3,-98.97],[-330.31,-101.43],[-326.31,-103.86],[-322.32,-106.26],[-318.37,-108.63],[-314.46,-110.99],[-310.62,-113.32],[-306.84,-115.65],[-303.15,-117.96],[-299.56,-120.27],[-296.05,-122.58],[-292.65,-124.9],[-289.35,-127.22],[-286.16,-129.55],[-283.06,-131.9],[-280.07,-134.26],[-277.16,-136.65],[-274.34,-139.05],[-271.6,-141.47],[-268.92,-143.91],[-266.3,-146.37],[-263.72,-148.85],[-261.16,-151.35],[-258.62,-153.86],[-256.08,-156.38],[-253.53,-158.9],[-250.94,-161.43],[-248.3,-163.95],[-245.6,-166.47],[-242.83,-168.97],[-239.96,-171.44],[-236.98,-173.89],[-233.88,-176.3],[-230.66,-178.66],[-227.29,-180.97],[-223.76,-183.22],[-220.08,-185.4],[-216.23,-187.51],[-212.2,-189.53],[-208.0,-191.46],[-203.62,-193.29],[-199.06,-195.02],[-194.32,-196.64],[-189.41,-198.14],[-184.33,-199.52],[-179.08,-200.77],[-173.67,-201.9],[-168.12,-202.89],[-162.43,-203.76],[-156.61,-204.49],[-150.68,-205.1],[-144.64,-205.57],[-138.52,-205.92],[-132.33,-206.14],[-126.08,-206.25],[-119.79,-206.24],[-113.47,-206.13],[-107.15,-205.92],[-100.83,-205.62],[-94.53,-205.24],[-88.26,-204.78],[-82.04,-204.27],[-75.88,-203.7],[-69.8,-203.1],[-63.8,-202.47],[-57.89,-201.82],[-52.08,-201.18],[-46.39,-200.54],[-40.8,-199.92],[-35.34,-199.34],[-30.0,-198.81],[-24.78,-198.33],[-19.69,-197.91],[-14.71,-197.58],[-9.85,-197.33],[-5.11,-197.18],[-0.47,-197.13],[4.06,-197.2],[8.51,-197.38],[12.87,-197.68],[17.16,-198.1],[21.38,-198.66],[25.56,-199.34],[29.7,-200.15],[33.81,-201.08],[37.9,-202.15],[42.0,-203.33],[46.11,-204.63],[50.24,-206.04],[54.4,-207.55],[58.61,-209.16],[62.88,-210.86],[67.21,-212.63],[71.61,-214.47],[76.1,-216.37],[80.68,-218.31],[85.36,-220.28],[90.13,-222.26],[95.0,-224.26],[99.98,-226.24],[105.06,-228.2],[110.24,-230.13],[115.53,-232.01],[120.91,-233.84],[126.38,-235.59],[131.94,-237.25],[137.59,-238.82],[143.3,-240.29],[149.08,-241.64],[154.92,-242.87],[160.8,-243.97],[166.71,-244.93],[172.65,-245.75],[178.6,-246.42],[184.56,-246.94],[190.5,-247.3],[196.43,-247.52],[202.32,-247.57],[208.18,-247.48],[213.99,-247.23],[219.74,-246.83],[225.42,-246.29],[231.04,-245.61],[236.57,-244.8],[242.03,-243.86],[247.4,-242.8],[252.68,-241.63],[257.87,-240.36],[262.98,-238.99],[267.99,-237.54],[272.92,-236.02],[277.77,-234.44],[282.55,-232.79],[287.25,-231.11],[291.9,-229.39],[296.48,-227.64],[301.02,-225.87],[305.52,-224.1],[310.0,-222.32],[314.45,-220.55],[318.9,-218.79],[323.35,-217.06],[327.82,-215.34],[332.31,-213.65],[336.83,-212.0],[341.39,-210.38],[346.01,-208.79],[350.69,-207.24],[355.43,-205.72],[360.24,-204.24],[365.12,-202.8],[370.09,-201.38],[375.13,-199.99],[380.26,-198.62],[385.46,-197.27],[390.74,-195.93],[396.09,-194.6],[401.5,-193.27],[406.97,-191.93],[412.49,-190.58],[418.04,-189.21],[423.62,-187.81],[429.2,-186.37],[434.78,-184.89],[440.33,-183.37],[445.85,-181.78],[451.3,-180.14],[456.67,-178.42],[461.95,-176.64],[467.11,-174.77],[472.12,-172.83],[476.97,-170.79],[481.65,-168.67],[486.12,-166.46],[490.37,-164.16],[494.38,-161.76],[498.13,-159.27],[501.61,-156.69],[504.8,-154.01],[507.68,-151.26],[510.25,-148.41],[512.49,-145.49],[514.39,-142.49],[515.96,-139.43],[517.17,-136.29],[518.04,-133.1],[518.57,-129.86],[518.74,-126.58],[518.58,-123.26],[518.08,-119.91],[517.26,-116.54],[516.12,-113.15],[514.68,-109.76],[512.96,-106.37],[510.97,-102.99],[508.74,-99.62],[506.27,-96.28],[503.6,-92.97],[500.76,-89.69],[497.75,-86.45],[494.62,-83.26],[491.38,-80.12],[488.06,-77.03],[484.69,-73.99],[481.29,-71.01],[477.9,-68.1],[474.53,-65.24],[471.22,-62.44],[467.99,-59.7],[464.86,-57.02],[461.84,-54.4],[458.98,-51.82],[456.27,-49.3],[453.74,-46.83],[451.41,-44.4],[449.28,-42.0],[447.36,-39.64],[445.68,-37.31],[444.22,-35.0]],[[445.94,-35.0],[444.66,-32.7],[443.63,-30.41],[442.84,-28.13],[442.28,-25.84],[441.96,-23.56],[441.86,-21.27],[441.97,-18.96],[442.29,-16.64],[442.79,-14.29],[443.47,-11.92],[444.31,-9.52],[445.28,-7.09],[446.37,-4.63],[447.55,-2.13],[448.81,0.4],[450.12,2.97],[451.46,5.57],[452.8,8.21],[454.12,10.88],[455.4,13.58],[456.62,16.3],[457.75,19.05],[458.78,21.82],[459.68,24.6],[460.43,27.4],[461.02,30.2],[461.44,33.0],[461.66,35.8],[461.68,38.59],[461.48,41.36],[461.06,44.11],[460.41,46.84],[459.52,49.53],[458.4,52.19],[457.04,54.81],[455.45,57.39],[453.63,59.91],[451.58,62.39],[449.31,64.81],[446.83,67.18],[444.15,69.49],[441.29,71.75],[438.25,73.94],[435.05,76.09],[431.71,78.17],[428.24,80.21],[424.65,82.19],[420.97,84.13],[417.21,86.03],[413.39,87.89],[409.52,89.72],[405.62,91.53],[401.7,93.31],[397.79,95.09],[393.89,96.85],[390.02,98.62],[386.18,100.4],[382.4,102.19],[378.67,104.01],[375.01,105.85],[371.42,107.74],[367.91,109.66],[364.47,111.64],[361.11,113.67],[357.83,115.76],[354.63,117.91],[351.5,120.14],[348.43,122.43],[345.43,124.8],[342.48,127.24],[339.57,129.75],[336.69,132.34],[333.83,134.99],[330.98,137.72],[328.13,140.51],[325.26,143.36],[322.36,146.26],[319.41,149.21],[316.41,152.2],[313.33,155.23],[310.17,158.27],[306.91,161.32],[303.53,164.38],[300.04,167.42],[296.41,170.45],[292.64,173.44],[288.72,176.38],[284.64,179.26],[280.4,182.07],[275.99,184.8],[271.41,187.43],[266.66,189.94],[261.73,192.34],[256.64,194.61],[251.38,196.73],[245.95,198.7],[240.37,200.51],[234.64,202.14],[228.77,203.6],[222.77,204.87],[216.65,205.95],[210.42,206.84],[204.1,207.53],[197.69,208.02],[191.21,208.31],[184.68,208.4],[178.11,208.29],[171.51,207.99],[164.9,207.49],[158.29,206.82],[151.7,205.96],[145.13,204.93],[138.61,203.75],[132.14,202.41],[125.74,200.93],[119.41,199.31],[113.17,197.58],[107.01,195.75],[100.95,193.82],[95.0,191.8],[89.15,189.73],[83.41,187.59],[77.78,185.42],[72.26,183.22],[66.85,181.01],[61.55,178.8],[56.35,176.59],[51.25,174.41],[46.23,172.26],[41.31,170.15],[36.46,168.1],[31.68,166.11],[26.96,164.18],[22.29,162.34],[17.67,160.56],[13.08,158.88],[8.51,157.28],[3.95,155.77],[-0.6,154.35],[-5.15,153.01],[-9.71,151.77],[-14.3,150.61],[-18.91,149.53],[-23.55,148.53],[-28.22,147.6],[-32.94,146.73],[-37.69,145.93],[-42.49,145.17],[-47.33,144.46],[-52.21,143.78],[-57.13,143.12],[-62.09,142.48],[-67.07,141.85],[-72.08,141.21],[-77.11,140.56],[-82.14,139.89],[-87.18,139.18],[-92.2,138.43],[-97.2,137.64],[-102.17,136.79],[-107.09,135.87],[-111.96,134.89],[-116.76,133.82],[-121.47,132.68],[-126.1,131.45],[-130.62,130.13],[-135.02,128.72],[-139.3,127.22],[-143.44,125.62],[-147.43,123.93],[-151.28,122.15],[-154.96,120.27],[-158.48,118.31],[-161.83,116.27],[-165.01,114.14],[-168.02,111.94],[-170.86,109.68],[-173.54,107.35],[-176.05,104.96],[-178.4,102.53],[-180.6,100.05],[-182.66,97.55],[-184.6,95.01],[-186.41,92.46],[-188.12,89.9],[-189.74,87.33],[-191.29,84.77],[-192.78,82.23],[-194.24,79.7],[-195.67,77.2],[-197.11,74.72],[-198.56,72.29],[-200.06,69.89],[-201.61,67.54],[-203.24,65.24],[-204.96,62.99],[-206.8,60.79],[-208.78,58.64],[-210.9,56.55],[-213.18,54.5],[-215.64,52.51],[-218.29,50.57],[-221.13,48.67],[-224.19,46.81],[-227.45,44.99],[-230.94,43.2],[-234.64,41.44],[-238.56,39.71],[-242.7,37.98],[-247.05,36.27],[-251.61,34.56],[-256.36,32.85],[-261.3,31.12],[-266.41,29.38],[-271.67,27.61],[-277.07,25.81],[-282.59,23.98],[-288.21,22.1],[-293.9,20.17],[-299.64,18.19],[-305.4,16.15],[-311.17,14.05],[-316.91,11.88],[-322.59,9.65],[-328.19,7.34],[-333.69,4.97],[-339.04,2.52],[-344.23,-0.01],[-349.24,-2.6],[-354.02,-5.26],[-358.57,-8.0],[-362.86,-10.79],[-366.86,-13.65],[-370.57,-16.57],[-373.95,-19.54],[-376.99,-22.56],[-379.68,-25.62],[-382.02,-28.72],[-383.98,-31.85],[-385.56,-35.0],[-386.77,-38.17],[-387.59,-41.36],[-388.02,-44.55],[-388.08,-47.74],[-387.76,-50.92],[-387.08,-54.09],[-386.04,-57.23],[-384.66,-60.36],[-382.94,-63.46],[-380.91,-66.52],[-378.59,-69.54],[-375.98,-72.52],[-373.12,-75.46],[-370.02,-78.35],[-366.71,-81.2],[-363.21,-83.99],[-359.54,-86.74],[-355.73,-89.43],[-351.79,-92.08],[-347.76,-94.68],[-343.66,-97.23],[-339.5,-99.74],[-335.32,-102.21],[-331.12,-104.65],[-326.94,-107.05],[-322.78,-109.42],[-318.67,-111.77],[-314.61,-114.09],[-310.63,-116.41],[-306.73,-118.7],[-302.92,-121.0],[-299.21,-123.29],[-295.6,-125.58],[-292.1,-127.88],[-288.71,-130.19],[-285.42,-132.5],[-282.24,-134.84],[-279.16,-137.19],[-276.17,-139.56],[-273.27,-141.95],[-270.44,-144.37],[-267.68,-146.8],[-264.97,-149.25],[-262.3,-151.72],[-259.66,-154.21],[-257.02,-156.7],[-254.39,-159.21],[-251.73,-161.72],[-249.03,-164.23],[-246.29,-166.73],[-243.48,-169.22],[-240.58,-171.7],[-237.59,-174.14],[-234.49,-176.56],[-231.27,-178.93],[-227.91,-181.25],[-224.41,-183.52],[-220.75,-185.73],[-216.93,-187.86],[-212.95,-189.91],[-208.79,-191.87],[-204.46,-193.74],[-199.95,-195.51],[-195.27,-197.17],[-190.41,-198.71],[-185.39,-200.14],[-180.2,-201.45],[-174.85,-202.63],[-169.35,-203.68],[-163.71,-204.6],[-157.94,-205.39],[-152.06,-206.05],[-146.07,-206.58],[-139.98,-206.99],[-133.83,-207.27],[-127.61,-207.43],[-121.34,-207.48],[-115.04,-207.42],[-108.73,-207.26],[-102.42,-207.01],[-96.12,-206.67],[-89.85,-206.26],[-83.63,-205.78],[-77.46,-205.26],[-71.35,-204.69],[-65.33,-204.09],[-59.4,-203.47],[-53.56,-202.85],[-47.83,-202.23],[-42.21,-201.63],[-36.71,-201.07],[-31.33,-200.54],[-26.06,-200.07],[-20.92,-199.67],[-15.9,-199.34],[-11.0,-199.1],[-6.2,-198.95],[-1.52,-198.9],[3.07,-198.97],[7.56,-199.15],[11.97,-199.45],[16.31,-199.88],[20.59,-200.43],[24.81,-201.11],[28.99,-201.93],[33.15,-202.87],[37.29,-203.94],[41.43,-205.14],[45.58,-206.45],[49.76,-207.88],[53.96,-209.41],[58.22,-211.04],[62.53,-212.77],[66.9,-214.57],[71.36,-216.45],[75.89,-218.38],[80.52,-220.36],[85.25,-222.38],[90.07,-224.42],[95.0,-226.47],[100.04,-228.51],[105.18,-230.53],[110.43,-232.52],[115.78,-234.47],[121.24,-236.36],[126.79,-238.19],[132.43,-239.92],[138.16,-241.57],[143.97,-243.11],[149.84,-244.54],[155.77,-245.84],[161.75,-247.01],[167.77,-248.04],[173.82,-248.93],[179.89,-249.67],[185.95,-250.25],[192.02,-250.68],[198.06,-250.95],[204.08,-251.05],[210.06,-251.0],[215.99,-250.8],[221.86,-250.44],[227.67,-249.93],[233.4,-249.27],[239.06,-248.47],[244.63,-247.54],[250.11,-246.49],[255.49,-245.32],[260.79,-244.04],[265.99,-242.65],[271.1,-241.18],[276.11,-239.63],[281.04,-238.0],[285.89,-236.31],[290.65,-234.57],[295.35,-232.79],[299.98,-230.98],[304.56,-229.15],[309.09,-227.3],[313.58,-225.44],[318.05,-223.59],[322.5,-221.75],[326.94,-219.92],[331.39,-218.11],[335.86,-216.33],[340.35,-214.58],[344.88,-212.86],[349.45,-211.17],[354.07,-209.52],[358.75,-207.91],[363.5,-206.33],[368.32,-204.78],[373.21,-203.27],[378.18,-201.79],[383.23,-200.33],[388.36,-198.89],[393.56,-197.47],[398.83,-196.05],[404.17,-194.65],[409.56,-193.23],[415.0,-191.81],[420.48,-190.37],[425.99,-188.91],[431.51,-187.42],[437.03,-185.89],[442.54,-184.31],[448.0,-182.68],[453.41,-181.0],[458.75,-179.25],[464.0,-177.43],[469.13,-175.54],[474.13,-173.56],[478.98,-171.51],[483.65,-169.37],[488.13,-167.14],[492.39,-164.82],[496.42,-162.41],[500.19,-159.9],[503.7,-157.31],[506.92,-154.63],[509.84,-151.87],[512.45,-149.02],[514.73,-146.09],[516.69,-143.08],[518.3,-140.01],[519.56,-136.87],[520.48,-133.67],[521.05,-130.42],[521.27,-127.13],[521.15,-123.79],[520.7,-120.43],[519.91,-117.05],[518.81,-113.65],[517.4,-110.24],[515.7,-106.84],[513.73,-103.44],[511.51,-100.06],[509.05,-96.7],[506.39,-93.36],[503.53,-90.06],[500.51,-86.81],[497.36,-83.59],[494.09,-80.43],[490.74,-77.31],[487.33,-74.26],[483.89,-71.26],[480.45,-68.32],[477.03,-65.44],[473.66,-62.62],[470.36,-59.86],[467.16,-57.16],[464.08,-54.51],[461.15,-51.92],[458.37,-49.39],[455.77,-46.89],[453.37,-44.45],[451.17,-42.04],[449.2,-39.67],[447.45,-37.32],[445.94,-35.0]],[[447.76,-35.0],[446.44,-32.69],[445.36,-30.38],[444.54,-28.09],[443.95,-25.8],[443.61,-23.51],[443.5,-21.2],[443.61,-18.89],[443.94,-16.55],[444.47,-14.19],[445.18,-11.81],[446.05,-9.4],[447.07,-6.95],[448.23,-4.47],[449.48,-1.95],[450.83,0.6],[452.23,3.2],[453.67,5.83],[455.13,8.49],[456.58,11.19],[457.99,13.93],[459.35,16.69],[460.63,19.48],[461.81,22.29],[462.87,25.13],[463.79,27.97],[464.55,30.83],[465.13,33.69],[465.52,36.55],[465.71,39.4],[465.68,42.24],[465.43,45.06],[464.94,47.85],[464.22,50.62],[463.26,53.36],[462.05,56.05],[460.6,58.71],[458.91,61.31],[456.98,63.87],[454.83,66.37],[452.46,68.82],[449.88,71.2],[447.1,73.54],[444.13,75.81],[440.99,78.02],[437.69,80.18],[434.25,82.29],[430.68,84.34],[427.01,86.34],[423.24,88.3],[419.4,90.21],[415.5,92.1],[411.55,93.95],[407.58,95.77],[403.6,97.59],[399.63,99.39],[395.67,101.18],[391.74,102.98],[387.85,104.79],[384.01,106.62],[380.23,108.48],[376.51,110.36],[372.86,112.29],[369.29,114.26],[365.79,116.28],[362.37,118.36],[359.02,120.5],[355.75,122.71],[352.54,124.98],[349.39,127.32],[346.29,129.74],[343.24,132.22],[340.22,134.78],[337.23,137.41],[334.24,140.11],[331.26,142.87],[328.27,145.69],[325.24,148.56],[322.18,151.49],[319.06,154.45],[315.88,157.45],[312.61,160.47],[309.25,163.5],[305.79,166.54],[302.21,169.57],[298.5,172.57],[294.65,175.55],[290.65,178.48],[286.5,181.36],[282.19,184.17],[277.72,186.89],[273.07,189.52],[268.26,192.05],[263.28,194.45],[258.13,196.73],[252.81,198.86],[247.33,200.84],[241.7,202.66],[235.92,204.31],[229.99,205.78],[223.94,207.06],[217.76,208.16],[211.48,209.05],[205.1,209.75],[198.63,210.25],[192.1,210.55],[185.51,210.64],[178.87,210.54],[172.22,210.24],[165.54,209.74],[158.87,209.06],[152.22,208.19],[145.59,207.15],[139.01,205.94],[132.48,204.58],[126.02,203.07],[119.63,201.42],[113.33,199.65],[107.12,197.78],[101.01,195.8],[95.0,193.74],[89.1,191.6],[83.32,189.41],[77.65,187.18],[72.09,184.91],[66.64,182.63],[61.31,180.34],[56.08,178.06],[50.95,175.81],[45.92,173.58],[40.98,171.4],[36.12,169.26],[31.34,167.19],[26.62,165.19],[21.95,163.26],[17.33,161.42],[12.75,159.66],[8.19,157.99],[3.65,156.41],[-0.89,154.92],[-5.42,153.53],[-9.97,152.23],[-14.54,151.02],[-19.13,149.9],[-23.76,148.85],[-28.42,147.89],[-33.12,147.0],[-37.87,146.17],[-42.66,145.4],[-47.5,144.67],[-52.39,143.99],[-57.32,143.34],[-62.29,142.71],[-67.3,142.09],[-72.34,141.48],[-77.4,140.85],[-82.48,140.21],[-87.56,139.55],[-92.64,138.85],[-97.71,138.1],[-102.76,137.3],[-107.76,136.44],[-112.72,135.51],[-117.62,134.51],[-122.45,133.44],[-127.19,132.27],[-131.83,131.02],[-136.37,129.68],[-140.78,128.24],[-145.06,126.72],[-149.21,125.09],[-153.2,123.38],[-157.04,121.57],[-160.72,119.67],[-164.24,117.68],[-167.58,115.62],[-170.76,113.47],[-173.76,111.25],[-176.6,108.97],[-179.27,106.63],[-181.78,104.23],[-184.14,101.79],[-186.36,99.31],[-188.44,96.8],[-190.39,94.26],[-192.24,91.71],[-193.99,89.16],[-195.66,86.6],[-197.27,84.05],[-198.83,81.52],[-200.37,79.01],[-201.89,76.52],[-203.43,74.07],[-205.0,71.65],[-206.62,69.28],[-208.3,66.94],[-210.08,64.66],[-211.96,62.43],[-213.97,60.24],[-216.12,58.11],[-218.42,56.03],[-220.9,53.99],[-223.56,52.01],[-226.41,50.06],[-229.46,48.16],[-232.73,46.3],[-236.21,44.47],[-239.91,42.66],[-243.82,40.88],[-247.95,39.12],[-252.3,37.36],[-256.85,35.61],[-261.59,33.86],[-266.53,32.09],[-271.64,30.31],[-276.9,28.5],[-282.31,26.67],[-287.84,24.8],[-293.47,22.88],[-299.18,20.92],[-304.95,18.91],[-310.75,16.84],[-316.55,14.7],[-322.33,12.5],[-328.06,10.23],[-333.71,7.9],[-339.26,5.49],[-344.68,3.0],[-349.93,0.45],[-355.0,-2.18],[-359.86,-4.88],[-364.48,-7.64],[-368.84,-10.48],[-372.92,-13.37],[-376.69,-16.33],[-380.15,-19.33],[-383.26,-22.39],[-386.02,-25.49],[-388.42,-28.63],[-390.44,-31.8],[-392.07,-35.0],[-393.32,-38.22],[-394.18,-41.44],[-394.65,-44.68],[-394.73,-47.91],[-394.42,-51.14],[-393.74,-54.35],[-392.7,-57.54],[-391.29,-60.71],[-389.54,-63.85],[-387.47,-66.95],[-385.09,-70.02],[-382.42,-73.04],[-379.48,-76.01],[-376.29,-78.94],[-372.87,-81.81],[-369.25,-84.64],[-365.45,-87.41],[-361.5,-90.13],[-357.42,-92.8],[-353.23,-95.41],[-348.95,-97.98],[-344.62,-100.51],[-340.25,-102.98],[-335.86,-105.42],[-331.48,-107.82],[-327.12,-110.19],[-322.8,-112.53],[-318.53,-114.85],[-314.34,-117.15],[-310.22,-119.43],[-306.2,-121.71],[-302.28,-123.98],[-298.47,-126.25],[-294.77,-128.52],[-291.18,-130.8],[-287.7,-133.09],[-284.33,-135.39],[-281.08,-137.71],[-277.92,-140.06],[-274.86,-142.42],[-271.88,-144.8],[-268.98,-147.2],[-266.14,-149.62],[-263.36,-152.06],[-260.61,-154.52],[-257.88,-157.0],[-255.16,-159.48],[-252.43,-161.98],[-249.68,-164.47],[-246.89,-166.96],[-244.04,-169.45],[-241.12,-171.92],[-238.11,-174.36],[-235.01,-176.78],[-231.79,-179.16],[-228.45,-181.5],[-224.97,-183.79],[-221.35,-186.01],[-217.57,-188.17],[-213.63,-190.25],[-209.52,-192.25],[-205.24,-194.15],[-200.79,-195.96],[-196.16,-197.67],[-191.37,-199.26],[-186.4,-200.74],[-181.27,-202.1],[-175.99,-203.33],[-170.55,-204.44],[-164.97,-205.42],[-159.25,-206.28],[-153.42,-207.0],[-147.48,-207.59],[-141.44,-208.06],[-135.32,-208.4],[-129.14,-208.62],[-122.9,-208.73],[-116.63,-208.72],[-110.34,-208.62],[-104.04,-208.42],[-97.75,-208.13],[-91.48,-207.77],[-85.25,-207.34],[-79.07,-206.85],[-72.95,-206.32],[-66.91,-205.76],[-60.95,-205.17],[-55.09,-204.58],[-49.33,-203.99],[-43.67,-203.41],[-38.13,-202.86],[-32.71,-202.35],[-27.4,-201.9],[-22.21,-201.5],[-17.14,-201.18],[-12.19,-200.95],[-7.35,-200.8],[-2.61,-200.76],[2.03,-200.82],[6.57,-201.01],[11.04,-201.31],[15.42,-201.73],[19.75,-202.29],[24.02,-202.98],[28.25,-203.79],[32.46,-204.74],[36.65,-205.82],[40.84,-207.02],[45.03,-208.35],[49.25,-209.79],[53.51,-211.34],[57.81,-213.0],[62.17,-214.75],[66.59,-216.58],[71.09,-218.49],[75.68,-220.46],[80.36,-222.48],[85.13,-224.54],[90.01,-226.63],[95.0,-228.73],[100.1,-230.82],[105.3,-232.91],[110.62,-234.96],[116.04,-236.97],[121.57,-238.93],[127.2,-240.82],[132.93,-242.63],[138.74,-244.34],[144.64,-245.95],[150.6,-247.45],[156.63,-248.83],[162.72,-250.07],[168.84,-251.17],[175.0,-252.13],[181.17,-252.93],[187.36,-253.57],[193.54,-254.06],[199.7,-254.38],[205.84,-254.54],[211.94,-254.54],[217.99,-254.37],[223.99,-254.05],[229.91,-253.56],[235.77,-252.93],[241.54,-252.15],[247.22,-251.23],[252.81,-250.18],[258.31,-249.01],[263.7,-247.71],[269.0,-246.31],[274.2,-244.81],[279.3,-243.23],[284.31,-241.56],[289.22,-239.83],[294.05,-238.04],[298.8,-236.2],[303.48,-234.33],[308.09,-232.42],[312.65,-230.5],[317.16,-228.56],[321.64,-226.62],[326.09,-224.69],[330.52,-222.77],[334.96,-220.87],[339.4,-218.99],[343.85,-217.14],[348.34,-215.32],[352.86,-213.53],[357.43,-211.78],[362.05,-210.07],[366.73,-208.39],[371.48,-206.75],[376.3,-205.14],[381.19,-203.56],[386.16,-202.01],[391.2,-200.48],[396.32,-198.97],[401.5,-197.47],[406.76,-195.98],[412.07,-194.5],[417.43,-193.0],[422.84,-191.5],[428.27,-189.97],[433.73,-188.42],[439.18,-186.83],[444.62,-185.21],[450.04,-183.54],[455.4,-181.81],[460.7,-180.02],[465.92,-178.17],[471.03,-176.25],[476.01,-174.25],[480.84,-172.17],[485.51,-170.01],[489.99,-167.76],[494.26,-165.43],[498.31,-163.0],[502.1,-160.49],[505.64,-157.89],[508.89,-155.2],[511.85,-152.43],[514.5,-149.58],[516.83,-146.64],[518.83,-143.63],[520.49,-140.55],[521.81,-137.41],[522.78,-134.2],[523.41,-130.95],[523.68,-127.65],[523.61,-124.31],[523.2,-120.93],[522.46,-117.54],[521.4,-114.13],[520.03,-110.71],[518.36,-107.29],[516.42,-103.88],[514.22,-100.48],[511.78,-97.1],[509.12,-93.75],[506.27,-90.43],[503.25,-87.15],[500.08,-83.92],[496.8,-80.73],[493.42,-77.6],[489.98,-74.52],[486.51,-71.5],[483.03,-68.54],[479.56,-65.64],[476.14,-62.8],[472.79,-60.02],[469.53,-57.3],[466.39,-54.64],[463.39,-52.03],[460.55,-49.47],[457.89,-46.96],[455.42,-44.5],[453.16,-42.08],[451.13,-39.69],[449.32,-37.33],[447.76,-35.0]],[[449.69,-35.0],[448.33,-32.67],[447.21,-30.36],[446.35,-28.06],[445.75,-25.75],[445.39,-23.45],[445.27,-21.13],[445.38,-18.8],[445.71,-16.46],[446.26,-14.09],[447.0,-11.69],[447.91,-9.26],[448.98,-6.8],[450.2,-4.3],[451.53,-1.76],[452.95,0.82],[454.45,3.43],[455.99,6.09],[457.56,8.79],[459.13,11.52],[460.67,14.29],[462.17,17.09],[463.6,19.92],[464.93,22.78],[466.14,25.66],[467.22,28.56],[468.15,31.47],[468.9,34.39],[469.46,37.31],[469.82,40.22],[469.96,43.13],[469.88,46.02],[469.56,48.89],[469.0,51.73],[468.19,54.54],[467.13,57.31],[465.82,60.04],[464.27,62.73],[462.47,65.36],[460.43,67.95],[458.17,70.47],[455.68,72.94],[452.98,75.35],[450.09,77.7],[447.0,79.99],[443.75,82.22],[440.35,84.39],[436.8,86.51],[433.13,88.58],[429.36,90.59],[425.5,92.57],[421.56,94.5],[417.57,96.4],[413.55,98.27],[409.5,100.12],[405.44,101.95],[401.39,103.78],[397.37,105.6],[393.37,107.43],[389.41,109.27],[385.51,111.13],[381.66,113.02],[377.88,114.95],[374.17,116.92],[370.53,118.93],[366.96,120.99],[363.46,123.12],[360.03,125.3],[356.67,127.55],[353.37,129.87],[350.13,132.25],[346.93,134.71],[343.76,137.23],[340.63,139.83],[337.51,142.49],[334.39,145.22],[331.26,148.01],[328.11,150.85],[324.93,153.74],[321.69,156.67],[318.4,159.64],[315.03,162.63],[311.57,165.64],[308.01,168.66],[304.33,171.66],[300.53,174.65],[296.6,177.62],[292.53,180.54],[288.31,183.4],[283.93,186.2],[279.39,188.93],[274.68,191.55],[269.81,194.08],[264.77,196.49],[259.56,198.77],[254.19,200.91],[248.66,202.89],[242.98,204.72],[237.14,206.38],[231.17,207.87],[225.06,209.16],[218.83,210.27],[212.49,211.18],[206.06,211.89],[199.54,212.4],[192.95,212.7],[186.3,212.81],[179.61,212.7],[172.9,212.4],[166.17,211.9],[159.44,211.21],[152.73,210.34],[146.04,209.28],[139.4,208.06],[132.81,206.68],[126.29,205.14],[119.84,203.47],[113.49,201.66],[107.22,199.75],[101.06,197.73],[95.0,195.62],[89.06,193.43],[83.23,191.19],[77.51,188.89],[71.92,186.56],[66.44,184.21],[61.07,181.86],[55.82,179.51],[50.67,177.18],[45.62,174.88],[40.66,172.62],[35.79,170.41],[31.0,168.26],[26.28,166.18],[21.61,164.18],[17.0,162.26],[12.42,160.43],[7.87,158.69],[3.34,157.05],[-1.18,155.5],[-5.7,154.05],[-10.23,152.69],[-14.78,151.43],[-19.36,150.26],[-23.97,149.18],[-28.62,148.18],[-33.31,147.26],[-38.05,146.41],[-42.84,145.63],[-47.68,144.9],[-52.57,144.21],[-57.51,143.56],[-62.5,142.94],[-67.53,142.34],[-72.59,141.75],[-77.69,141.15],[-82.82,140.55],[-87.95,139.92],[-93.1,139.26],[-98.23,138.57],[-103.35,137.82],[-108.45,137.02],[-113.5,136.15],[-118.5,135.22],[-123.44,134.2],[-128.3,133.11],[-133.07,131.93],[-137.74,130.66],[-142.29,129.29],[-146.72,127.83],[-151.02,126.28],[-155.17,124.63],[-159.17,122.89],[-163.01,121.05],[-166.69,119.13],[-170.21,117.12],[-173.55,115.03],[-176.73,112.87],[-179.73,110.63],[-182.57,108.33],[-185.25,105.97],[-187.77,103.56],[-190.14,101.11],[-192.37,98.63],[-194.47,96.11],[-196.46,93.58],[-198.35,91.03],[-200.15,88.48],[-201.88,85.93],[-203.55,83.39],[-205.19,80.87],[-206.81,78.37],[-208.44,75.9],[-210.08,73.46],[-211.77,71.06],[-213.52,68.7],[-215.35,66.38],[-217.27,64.11],[-219.32,61.89],[-221.5,59.72],[-223.82,57.59],[-226.31,55.52],[-228.98,53.49],[-231.84,51.5],[-234.89,49.55],[-238.15,47.64],[-241.62,45.77],[-245.31,43.92],[-249.21,42.09],[-253.33,40.28],[-257.66,38.48],[-262.19,36.68],[-266.93,34.89],[-271.85,33.08],[-276.95,31.26],[-282.21,29.41],[-287.62,27.54],[-293.15,25.63],[-298.79,23.68],[-304.51,21.68],[-310.3,19.63],[-316.11,17.52],[-321.94,15.35],[-327.76,13.12],[-333.52,10.82],[-339.22,8.45],[-344.81,6.0],[-350.28,3.49],[-355.59,0.9],[-360.72,-1.76],[-365.64,-4.49],[-370.33,-7.3],[-374.75,-10.16],[-378.9,-13.1],[-382.74,-16.09],[-386.26,-19.13],[-389.43,-22.23],[-392.26,-25.37],[-394.71,-28.55],[-396.79,-31.76],[-398.47,-35.0],[-399.77,-38.26],[-400.66,-41.53],[-401.16,-44.81],[-401.26,-48.08],[-400.97,-51.35],[-400.29,-54.61],[-399.23,-57.84],[-397.81,-61.05],[-396.03,-64.23],[-393.91,-67.38],[-391.48,-70.48],[-388.74,-73.54],[-385.72,-76.55],[-382.44,-79.51],[-378.92,-82.42],[-375.19,-85.27],[-371.26,-88.07],[-367.17,-90.82],[-362.94,-93.5],[-358.59,-96.14],[-354.15,-98.72],[-349.64,-101.25],[-345.09,-103.74],[-340.51,-106.18],[-335.93,-108.58],[-331.37,-110.95],[-326.84,-113.28],[-322.37,-115.59],[-317.96,-117.88],[-313.64,-120.15],[-309.41,-122.4],[-305.28,-124.65],[-301.26,-126.89],[-297.36,-129.14],[-293.57,-131.39],[-289.9,-133.65],[-286.35,-135.93],[-282.91,-138.22],[-279.59,-140.53],[-276.37,-142.85],[-273.24,-145.2],[-270.2,-147.58],[-267.23,-149.97],[-264.33,-152.38],[-261.47,-154.82],[-258.65,-157.27],[-255.85,-159.73],[-253.05,-162.2],[-250.24,-164.68],[-247.4,-167.16],[-244.52,-169.64],[-241.58,-172.1],[-238.56,-174.55],[-235.45,-176.97],[-232.24,-179.36],[-228.92,-181.71],[-225.46,-184.01],[-221.87,-186.26],[-218.13,-188.44],[-214.24,-190.56],[-210.18,-192.59],[-205.96,-194.53],[-201.57,-196.39],[-197.01,-198.14],[-192.28,-199.78],[-187.38,-201.31],[-182.32,-202.73],[-177.1,-204.02],[-171.72,-205.19],[-166.2,-206.24],[-160.55,-207.15],[-154.78,-207.94],[-148.89,-208.59],[-142.9,-209.12],[-136.83,-209.53],[-130.68,-209.81],[-124.48,-209.98],[-118.24,-210.04],[-111.97,-209.99],[-105.68,-209.85],[-99.4,-209.62],[-93.14,-209.31],[-86.91,-208.93],[-80.73,-208.49],[-74.6,-208.0],[-68.54,-207.47],[-62.56,-206.93],[-56.67,-206.36],[-50.88,-205.8],[-45.19,-205.25],[-39.61,-204.73],[-34.14,-204.24],[-28.79,-203.8],[-23.56,-203.42],[-18.44,-203.11],[-13.44,-202.88],[-8.54,-202.74],[-3.75,-202.7],[0.94,-202.77],[5.54,-202.95],[10.05,-203.26],[14.49,-203.69],[18.87,-204.24],[23.2,-204.93],[27.48,-205.75],[31.74,-206.7],[35.98,-207.79],[40.21,-209.0],[44.46,-210.33],[48.73,-211.79],[53.03,-213.36],[57.38,-215.03],[61.79,-216.8],[66.27,-218.66],[70.82,-220.6],[75.45,-222.6],[80.19,-224.66],[85.02,-226.76],[89.95,-228.89],[95.0,-231.04],[100.16,-233.19],[105.43,-235.32],[110.81,-237.43],[116.31,-239.51],[121.91,-241.53],[127.62,-243.48],[133.42,-245.35],[139.32,-247.14],[145.31,-248.82],[151.37,-250.39],[157.5,-251.83],[163.68,-253.14],[169.91,-254.31],[176.18,-255.33],[182.47,-256.19],[188.76,-256.9],[195.06,-257.44],[201.34,-257.82],[207.6,-258.03],[213.82,-258.07],[220.0,-257.94],[226.11,-257.65],[232.16,-257.2],[238.13,-256.59],[244.02,-255.83],[249.82,-254.92],[255.52,-253.87],[261.12,-252.69],[266.62,-251.38],[272.01,-249.97],[277.3,-248.44],[282.48,-246.82],[287.57,-245.12],[292.55,-243.34],[297.44,-241.5],[302.24,-239.6],[306.97,-237.66],[311.61,-235.69],[316.2,-233.69],[320.73,-231.67],[325.21,-229.65],[329.66,-227.63],[334.09,-225.62],[338.5,-223.62],[342.92,-221.64],[347.34,-219.69],[351.78,-217.77],[356.25,-215.88],[360.76,-214.03],[365.32,-212.21],[369.93,-210.43],[374.6,-208.68],[379.34,-206.98],[384.15,-205.3],[389.03,-203.65],[393.98,-202.03],[399.01,-200.44],[404.11,-198.85],[409.27,-197.28],[414.5,-195.72],[419.78,-194.15],[425.1,-192.58],[430.46,-190.99],[435.84,-189.38],[441.22,-187.73],[446.6,-186.06],[451.96,-184.34],[457.27,-182.57],[462.53,-180.75],[467.71,-178.86],[472.78,-176.91],[477.74,-174.88],[482.57,-172.78],[487.23,-170.6],[491.71,-168.34],[495.98,-165.99],[500.04,-163.56],[503.86,-161.03],[507.42,-158.43],[510.71,-155.73],[513.71,-152.95],[516.4,-150.1],[518.78,-147.16],[520.83,-144.14],[522.55,-141.06],[523.92,-137.91],[524.95,-134.71],[525.63,-131.45],[525.96,-128.14],[525.95,-124.79],[525.59,-121.42],[524.9,-118.01],[523.89,-114.59],[522.57,-111.16],[520.94,-107.73],[519.04,-104.31],[516.87,-100.89],[514.45,-97.5],[511.81,-94.13],[508.97,-90.8],[505.95,-87.5],[502.79,-84.25],[499.5,-81.04],[496.11,-77.89],[492.65,-74.79],[489.15,-71.75],[485.63,-68.76],[482.13,-65.84],[478.67,-62.98],[475.27,-60.18],[471.96,-57.44],[468.77,-54.76],[465.71,-52.14],[462.81,-49.56],[460.09,-47.04],[457.57,-44.56],[455.26,-42.12],[453.16,-39.72],[451.31,-37.35],[449.69,-35.0]],[[451.75,-35.0],[450.34,-32.66],[449.19,-30.33],[448.3,-28.02],[447.67,-25.7],[447.29,-23.38],[447.16,-21.06],[447.27,-18.72],[447.62,-16.36],[448.18,-13.97],[448.94,-11.56],[449.89,-9.12],[451.02,-6.64],[452.29,-4.12],[453.68,-1.56],[455.19,1.04],[456.77,3.68],[458.42,6.37],[460.1,9.09],[461.78,11.86],[463.46,14.66],[465.09,17.5],[466.66,20.38],[468.14,23.28],[469.51,26.21],[470.75,29.16],[471.84,32.13],[472.75,35.1],[473.48,38.08],[474.01,41.06],[474.32,44.04],[474.4,47.0],[474.25,49.94],[473.85,52.85],[473.19,55.74],[472.28,58.59],[471.12,61.4],[469.7,64.17],[468.03,66.88],[466.11,69.55],[463.95,72.15],[461.56,74.7],[458.94,77.19],[456.12,79.62],[453.1,81.98],[449.89,84.28],[446.52,86.53],[442.99,88.71],[439.33,90.84],[435.55,92.92],[431.67,94.95],[427.7,96.94],[423.67,98.88],[419.58,100.8],[415.47,102.68],[411.33,104.55],[407.19,106.4],[403.06,108.25],[398.95,110.09],[394.88,111.95],[390.85,113.82],[386.87,115.71],[382.95,117.64],[379.09,119.6],[375.3,121.6],[371.58,123.65],[367.93,125.75],[364.35,127.91],[360.84,130.14],[357.38,132.42],[353.98,134.78],[350.63,137.2],[347.31,139.69],[344.03,142.25],[340.77,144.88],[337.51,147.57],[334.24,150.32],[330.96,153.12],[327.65,155.98],[324.3,158.88],[320.89,161.81],[317.41,164.77],[313.84,167.75],[310.18,170.73],[306.41,173.72],[302.53,176.69],[298.51,179.63],[294.36,182.53],[290.06,185.39],[285.61,188.17],[281.0,190.89],[276.24,193.51],[271.3,196.03],[266.21,198.44],[260.94,200.72],[255.52,202.87],[249.93,204.86],[244.2,206.7],[238.31,208.37],[232.29,209.86],[226.13,211.17],[219.85,212.29],[213.46,213.21],[206.98,213.94],[200.41,214.45],[193.77,214.77],[187.07,214.88],[180.32,214.78],[173.55,214.48],[166.77,213.98],[159.98,213.29],[153.21,212.41],[146.47,211.34],[139.77,210.11],[133.13,208.7],[126.55,207.15],[120.05,205.45],[113.64,203.61],[107.32,201.66],[101.11,199.6],[95.0,197.45],[89.01,195.21],[83.14,192.91],[77.38,190.57],[71.75,188.18],[66.23,185.77],[60.84,183.35],[55.56,180.93],[50.38,178.53],[45.32,176.16],[40.35,173.82],[35.47,171.54],[30.67,169.32],[25.94,167.17],[21.28,165.09],[16.66,163.1],[12.1,161.2],[7.56,159.39],[3.04,157.68],[-1.47,156.07],[-5.98,154.57],[-10.49,153.16],[-15.03,151.85],[-19.59,150.64],[-24.18,149.52],[-28.82,148.49],[-33.5,147.54],[-38.23,146.67],[-43.02,145.87],[-47.86,145.13],[-52.76,144.44],[-57.71,143.79],[-62.71,143.19],[-67.76,142.6],[-72.86,142.03],[-78.0,141.47],[-83.16,140.89],[-88.36,140.31],[-93.56,139.69],[-98.77,139.05],[-103.97,138.35],[-109.15,137.61],[-114.3,136.81],[-119.4,135.93],[-124.45,134.99],[-129.43,133.96],[-134.33,132.85],[-139.13,131.65],[-143.83,130.36],[-148.41,128.97],[-152.86,127.49],[-157.17,125.91],[-161.34,124.23],[-165.35,122.47],[-169.2,120.61],[-172.89,118.66],[-176.4,116.63],[-179.75,114.51],[-182.93,112.33],[-185.94,110.07],[-188.79,107.75],[-191.47,105.38],[-194.01,102.96],[-196.4,100.5],[-198.66,98.01],[-200.79,95.49],[-202.82,92.95],[-204.75,90.41],[-206.6,87.86],[-208.4,85.31],[-210.14,82.78],[-211.87,80.27],[-213.58,77.78],[-215.31,75.32],[-217.07,72.89],[-218.88,70.5],[-220.76,68.15],[-222.74,65.85],[-224.82,63.59],[-227.02,61.37],[-229.37,59.21],[-231.87,57.08],[-234.55,55.01],[-237.41,52.97],[-240.46,50.98],[-243.71,49.02],[-247.17,47.1],[-250.84,45.2],[-254.72,43.33],[-258.82,41.47],[-263.13,39.62],[-267.65,37.78],[-272.36,35.94],[-277.27,34.08],[-282.35,32.22],[-287.6,30.33],[-292.99,28.42],[-298.52,26.47],[-304.16,24.48],[-309.88,22.44],[-315.67,20.35],[-321.5,18.21],[-327.35,16.01],[-333.18,13.74],[-338.98,11.4],[-344.71,9.0],[-350.34,6.52],[-355.85,3.97],[-361.21,1.35],[-366.39,-1.35],[-371.36,-4.12],[-376.1,-6.95],[-380.58,-9.86],[-384.79,-12.82],[-388.69,-15.85],[-392.27,-18.93],[-395.5,-22.07],[-398.38,-25.25],[-400.89,-28.47],[-403.02,-31.72],[-404.75,-35.0],[-406.08,-38.3],[-407.01,-41.61],[-407.54,-44.93],[-407.66,-48.25],[-407.38,-51.56],[-406.7,-54.86],[-405.63,-58.14],[-404.19,-61.39],[-402.39,-64.61],[-400.23,-67.8],[-397.74,-70.94],[-394.94,-74.03],[-391.84,-77.08],[-388.47,-80.07],[-384.85,-83.01],[-381.01,-85.9],[-376.96,-88.72],[-372.74,-91.49],[-368.36,-94.2],[-363.86,-96.85],[-359.25,-99.44],[-354.57,-101.99],[-349.84,-104.48],[-345.07,-106.93],[-340.3,-109.33],[-335.54,-111.69],[-330.81,-114.02],[-326.13,-116.32],[-321.51,-118.59],[-316.98,-120.84],[-312.54,-123.08],[-308.2,-125.3],[-303.98,-127.52],[-299.87,-129.74],[-295.89,-131.97],[-292.03,-134.2],[-288.29,-136.44],[-284.68,-138.7],[-281.18,-140.97],[-277.8,-143.27],[-274.52,-145.59],[-271.34,-147.93],[-268.25,-150.29],[-265.22,-152.67],[-262.26,-155.08],[-259.35,-157.51],[-256.46,-159.95],[-253.59,-162.4],[-250.72,-164.86],[-247.84,-167.33],[-244.92,-169.8],[-241.96,-172.26],[-238.93,-174.7],[-235.82,-177.13],[-232.62,-179.53],[-229.31,-181.89],[-225.89,-184.21],[-222.33,-186.48],[-218.63,-188.69],[-214.79,-190.83],[-210.79,-192.9],[-206.63,-194.89],[-202.3,-196.78],[-197.81,-198.58],[-193.15,-200.28],[-188.32,-201.87],[-183.33,-203.34],[-178.18,-204.69],[-172.87,-205.93],[-167.42,-207.03],[-161.84,-208.02],[-156.12,-208.87],[-150.29,-209.59],[-144.36,-210.19],[-138.34,-210.67],[-132.24,-211.02],[-126.08,-211.25],[-119.87,-211.38],[-113.62,-211.39],[-107.36,-211.31],[-101.1,-211.14],[-94.85,-210.89],[-88.62,-210.56],[-82.43,-210.17],[-76.29,-209.73],[-70.22,-209.25],[-64.22,-208.74],[-58.31,-208.21],[-52.49,-207.68],[-46.76,-207.16],[-41.15,-206.66],[-35.64,-206.19],[-30.24,-205.77],[-24.96,-205.41],[-19.79,-205.11],[-14.74,-204.89],[-9.79,-204.76],[-4.95,-204.73],[-0.2,-204.8],[4.45,-204.99],[9.02,-205.3],[13.52,-205.73],[17.95,-206.29],[22.33,-206.98],[26.67,-207.8],[30.98,-208.75],[35.28,-209.84],[39.57,-211.06],[43.87,-212.4],[48.19,-213.87],[52.54,-215.45],[56.94,-217.14],[61.4,-218.93],[65.93,-220.81],[70.53,-222.78],[75.22,-224.81],[80.01,-226.9],[84.9,-229.04],[89.89,-231.21],[95.0,-233.4],[100.22,-235.6],[105.56,-237.78],[111.01,-239.95],[116.57,-242.08],[122.25,-244.16],[128.04,-246.17],[133.93,-248.11],[139.91,-249.96],[145.99,-251.7],[152.14,-253.34],[158.37,-254.85],[164.65,-256.22],[170.99,-257.45],[177.36,-258.54],[183.76,-259.47],[190.17,-260.23],[196.58,-260.83],[202.98,-261.26],[209.36,-261.51],[215.7,-261.6],[222.0,-261.51],[228.23,-261.25],[234.4,-260.83],[240.49,-260.24],[246.49,-259.49],[252.4,-258.59],[258.22,-257.55],[263.92,-256.36],[269.52,-255.05],[275.01,-253.61],[280.39,-252.06],[285.66,-250.41],[290.82,-248.67],[295.87,-246.84],[300.82,-244.95],[305.68,-242.99],[310.44,-240.99],[315.13,-238.94],[319.74,-236.86],[324.28,-234.77],[328.77,-232.66],[333.22,-230.55],[337.64,-228.44],[342.03,-226.35],[346.41,-224.27],[350.8,-222.22],[355.19,-220.2],[359.61,-218.2],[364.06,-216.25],[368.54,-214.33],[373.08,-212.44],[377.68,-210.6],[382.33,-208.79],[387.05,-207.01],[391.84,-205.27],[396.71,-203.56],[401.64,-201.87],[406.65,-200.2],[411.72,-198.54],[416.85,-196.9],[422.04,-195.26],[427.27,-193.61],[432.55,-191.96],[437.85,-190.29],[443.16,-188.59],[448.47,-186.86],[453.76,-185.09],[459.02,-183.28],[464.23,-181.42],[469.36,-179.5],[474.41,-177.52],[479.34,-175.47],[484.15,-173.34],[488.8,-171.14],[493.27,-168.87],[497.56,-166.5],[501.63,-164.06],[505.47,-161.53],[509.06,-158.92],[512.38,-156.22],[515.42,-153.44],[518.16,-150.57],[520.59,-147.63],[522.69,-144.62],[524.46,-141.54],[525.9,-138.39],[526.99,-135.18],[527.73,-131.92],[528.12,-128.61],[528.17,-125.26],[527.88,-121.87],[527.25,-118.47],[526.29,-115.04],[525.02,-111.6],[523.45,-108.16],[521.59,-104.72],[519.45,-101.3],[517.07,-97.89],[514.46,-94.51],[511.64,-91.16],[508.64,-87.84],[505.49,-84.57],[502.2,-81.35],[498.81,-78.18],[495.34,-75.06],[491.82,-72.0],[488.28,-68.99],[484.75,-66.05],[481.25,-63.17],[477.81,-60.35],[474.46,-57.59],[471.22,-54.89],[468.12,-52.25],[465.17,-49.65],[462.4,-47.11],[459.82,-44.62],[457.46,-42.16],[455.31,-39.75],[453.41,-37.36],[451.75,-35.0]],[[453.93,-35.0],[452.49,-32.65],[451.3,-30.31],[450.38,-27.98],[449.73,-25.65],[449.33,-23.32],[449.19,-20.98],[449.3,-18.62],[449.65,-16.25],[450.23,-13.85],[451.02,-11.42],[452.01,-8.96],[453.18,-6.46],[454.5,-3.93],[455.97,-1.35],[457.55,1.28],[459.22,3.94],[460.96,6.66],[462.74,9.41],[464.55,12.21],[466.34,15.05],[468.11,17.93],[469.82,20.85],[471.44,23.8],[472.97,26.78],[474.36,29.78],[475.61,32.8],[476.69,35.83],[477.59,38.88],[478.28,41.92],[478.76,44.96],[479.01,47.99],[479.01,51.0],[478.77,54.0],[478.27,56.96],[477.51,59.89],[476.49,62.78],[475.2,65.62],[473.66,68.42],[471.86,71.16],[469.8,73.85],[467.51,76.48],[464.98,79.05],[462.22,81.55],[459.26,83.99],[456.1,86.37],[452.76,88.69],[449.26,90.94],[445.6,93.14],[441.81,95.27],[437.91,97.36],[433.91,99.4],[429.83,101.39],[425.69,103.35],[421.5,105.27],[417.28,107.17],[413.05,109.06],[408.82,110.92],[404.6,112.79],[400.4,114.66],[396.24,116.53],[392.13,118.43],[388.07,120.35],[384.06,122.3],[380.12,124.29],[376.25,126.32],[372.44,128.4],[368.7,130.54],[365.02,132.74],[361.41,134.99],[357.85,137.31],[354.34,139.7],[350.87,142.15],[347.43,144.67],[344.02,147.26],[340.62,149.91],[337.21,152.62],[333.8,155.38],[330.36,158.2],[326.88,161.05],[323.34,163.95],[319.75,166.87],[316.07,169.82],[312.31,172.77],[308.45,175.73],[304.47,178.67],[300.37,181.59],[296.13,184.47],[291.76,187.3],[287.24,190.08],[282.56,192.78],[277.73,195.4],[272.74,197.91],[267.58,200.32],[262.26,202.6],[256.79,204.75],[251.15,206.75],[245.36,208.59],[239.43,210.27],[233.35,211.77],[227.15,213.09],[220.82,214.22],[214.39,215.15],[207.86,215.89],[201.24,216.42],[194.54,216.74],[187.8,216.86],[181.0,216.77],[174.18,216.47],[167.34,215.98],[160.5,215.28],[153.68,214.4],[146.89,213.32],[140.13,212.08],[133.43,210.66],[126.8,209.08],[120.25,207.36],[113.78,205.5],[107.42,203.51],[101.15,201.42],[95.0,199.22],[88.96,196.95],[83.05,194.6],[77.25,192.2],[71.58,189.76],[66.04,187.29],[60.61,184.81],[55.3,182.33],[50.11,179.86],[45.02,177.42],[40.04,175.01],[35.14,172.66],[30.34,170.37],[25.61,168.15],[20.94,166.0],[16.33,163.94],[11.77,161.97],[7.24,160.1],[2.73,158.33],[-1.76,156.66],[-6.26,155.09],[-10.76,153.63],[-15.28,152.28],[-19.83,151.02],[-24.41,149.86],[-29.03,148.8],[-33.7,147.83],[-38.43,146.93],[-43.21,146.12],[-48.05,145.37],[-52.96,144.68],[-57.92,144.04],[-62.94,143.44],[-68.01,142.87],[-73.14,142.33],[-78.32,141.79],[-83.53,141.25],[-88.77,140.71],[-94.04,140.14],[-99.32,139.54],[-104.6,138.9],[-109.87,138.22],[-115.11,137.48],[-120.33,136.67],[-125.49,135.79],[-130.59,134.83],[-135.62,133.79],[-140.56,132.67],[-145.4,131.45],[-150.13,130.13],[-154.74,128.72],[-159.22,127.21],[-163.55,125.61],[-167.73,123.91],[-171.76,122.11],[-175.62,120.23],[-179.32,118.25],[-182.84,116.2],[-186.2,114.06],[-189.39,111.85],[-192.41,109.58],[-195.27,107.24],[-197.97,104.85],[-200.52,102.42],[-202.94,99.95],[-205.23,97.44],[-207.4,94.92],[-209.47,92.38],[-211.45,89.83],[-213.36,87.28],[-215.22,84.74],[-217.05,82.22],[-218.86,79.71],[-220.67,77.22],[-222.51,74.77],[-224.38,72.35],[-226.32,69.97],[-228.34,67.63],[-230.46,65.33],[-232.7,63.07],[-235.07,60.86],[-237.58,58.69],[-240.26,56.57],[-243.12,54.49],[-246.16,52.44],[-249.4,50.44],[-252.85,48.46],[-256.5,46.51],[-260.36,44.59],[-264.43,42.68],[-268.72,40.78],[-273.2,38.89],[-277.89,37.0],[-282.77,35.11],[-287.83,33.19],[-293.06,31.26],[-298.43,29.3],[-303.94,27.31],[-309.57,25.28],[-315.28,23.21],[-321.07,21.08],[-326.9,18.9],[-332.76,16.66],[-338.6,14.35],[-344.42,11.98],[-350.17,9.54],[-355.83,7.03],[-361.37,4.45],[-366.77,1.79],[-371.99,-0.94],[-377.0,-3.74],[-381.79,-6.61],[-386.33,-9.55],[-390.58,-12.56],[-394.54,-15.62],[-398.17,-18.74],[-401.46,-21.91],[-404.39,-25.13],[-406.95,-28.39],[-409.12,-31.68],[-410.9,-35.0],[-412.27,-38.34],[-413.23,-41.69],[-413.78,-45.06],[-413.92,-48.42],[-413.65,-51.77],[-412.97,-55.11],[-411.9,-58.43],[-410.44,-61.72],[-408.61,-64.98],[-406.41,-68.21],[-403.87,-71.39],[-401.01,-74.52],[-397.84,-77.6],[-394.39,-80.63],[-390.67,-83.6],[-386.72,-86.51],[-382.55,-89.36],[-378.19,-92.15],[-373.68,-94.87],[-369.02,-97.54],[-364.26,-100.15],[-359.4,-102.71],[-354.49,-105.21],[-349.54,-107.66],[-344.57,-110.06],[-339.62,-112.42],[-334.69,-114.74],[-329.8,-117.03],[-324.98,-119.29],[-320.24,-121.52],[-315.6,-123.74],[-311.05,-125.94],[-306.62,-128.14],[-302.32,-130.33],[-298.14,-132.52],[-294.08,-134.72],[-290.16,-136.94],[-286.37,-139.16],[-282.71,-141.4],[-279.16,-143.67],[-275.74,-145.95],[-272.41,-148.26],[-269.19,-150.59],[-266.05,-152.94],[-262.98,-155.32],[-259.97,-157.72],[-257.0,-160.14],[-254.06,-162.57],[-251.14,-165.02],[-248.21,-167.47],[-245.26,-169.93],[-242.27,-172.39],[-239.23,-174.83],[-236.12,-177.26],[-232.93,-179.67],[-229.65,-182.04],[-226.25,-184.38],[-222.73,-186.67],[-219.08,-188.91],[-215.29,-191.08],[-211.34,-193.19],[-207.25,-195.22],[-202.99,-197.16],[-198.56,-199.01],[-193.98,-200.76],[-189.22,-202.4],[-184.31,-203.93],[-179.23,-205.35],[-174.0,-206.65],[-168.63,-207.82],[-163.11,-208.87],[-157.47,-209.8],[-151.7,-210.6],[-145.83,-211.27],[-139.86,-211.81],[-133.81,-212.24],[-127.69,-212.54],[-121.52,-212.73],[-115.31,-212.82],[-109.07,-212.8],[-102.83,-212.69],[-96.59,-212.5],[-90.37,-212.23],[-84.18,-211.9],[-78.04,-211.51],[-71.95,-211.07],[-65.94,-210.61],[-60.0,-210.12],[-54.15,-209.63],[-48.39,-209.14],[-42.74,-208.67],[-37.19,-208.23],[-31.75,-207.83],[-26.42,-207.48],[-21.21,-207.2],[-16.1,-207.0],[-11.1,-206.88],[-6.2,-206.85],[-1.4,-206.93],[3.32,-207.12],[7.94,-207.43],[12.5,-207.86],[16.99,-208.42],[21.43,-209.11],[25.82,-209.94],[30.19,-210.9],[34.54,-211.99],[38.89,-213.21],[43.24,-214.56],[47.62,-216.03],[52.03,-217.63],[56.49,-219.33],[61.0,-221.14],[65.58,-223.04],[70.24,-225.02],[74.99,-227.08],[79.83,-229.2],[84.78,-231.38],[89.83,-233.58],[95.0,-235.81],[100.28,-238.05],[105.69,-240.29],[111.21,-242.5],[116.85,-244.68],[122.6,-246.82],[128.46,-248.89],[134.44,-250.89],[140.51,-252.8],[146.67,-254.6],[152.92,-256.3],[159.24,-257.87],[165.63,-259.31],[172.07,-260.61],[178.55,-261.75],[185.05,-262.74],[191.58,-263.56],[198.1,-264.21],[204.62,-264.69],[211.12,-264.99],[217.58,-265.12],[223.99,-265.07],[230.35,-264.85],[236.63,-264.45],[242.84,-263.88],[248.96,-263.15],[254.98,-262.26],[260.9,-261.21],[266.72,-260.02],[272.42,-258.7],[278.0,-257.24],[283.47,-255.67],[288.82,-253.98],[294.06,-252.2],[299.18,-250.33],[304.19,-248.38],[309.1,-246.37],[313.91,-244.3],[318.62,-242.18],[323.26,-240.03],[327.82,-237.85],[332.32,-235.66],[336.76,-233.45],[341.16,-231.25],[345.53,-229.06],[349.88,-226.89],[354.23,-224.73],[358.57,-222.6],[362.93,-220.51],[367.32,-218.44],[371.74,-216.42],[376.2,-214.43],[380.71,-212.48],[385.28,-210.57],[389.91,-208.69],[394.6,-206.85],[399.37,-205.04],[404.21,-203.26],[409.11,-201.51],[414.08,-199.77],[419.12,-198.04],[424.21,-196.32],[429.36,-194.61],[434.54,-192.89],[439.76,-191.15],[444.99,-189.4],[450.23,-187.62],[455.45,-185.8],[460.65,-183.95],[465.8,-182.04],[470.89,-180.09],[475.9,-178.08],[480.81,-176.0],[485.59,-173.86],[490.22,-171.64],[494.7,-169.34],[498.99,-166.97],[503.07,-164.52],[506.93,-161.98],[510.55,-159.36],[513.9,-156.66],[516.98,-153.88],[519.77,-151.01],[522.25,-148.07],[524.41,-145.06],[526.24,-141.98],[527.74,-138.83],[528.89,-135.62],[529.71,-132.36],[530.17,-129.05],[530.29,-125.7],[530.06,-122.31],[529.5,-118.9],[528.61,-115.47],[527.4,-112.02],[525.88,-108.58],[524.07,-105.13],[521.99,-101.69],[519.65,-98.28],[517.08,-94.88],[514.29,-91.52],[511.32,-88.19],[508.18,-84.9],[504.91,-81.66],[501.52,-78.47],[498.05,-75.33],[494.52,-72.25],[490.97,-69.23],[487.42,-66.26],[483.9,-63.36],[480.43,-60.53],[477.05,-57.75],[473.77,-55.03],[470.62,-52.36],[467.63,-49.75],[464.81,-47.19],[462.19,-44.68],[459.77,-42.21],[457.58,-39.78],[455.63,-37.37],[453.93,-35.0]],[[456.25,-35.0],[454.77,-32.63],[453.56,-30.28],[452.61,-27.93],[451.93,-25.59],[451.52,-23.25],[451.37,-20.89],[451.48,-18.52],[451.83,-16.13],[452.43,-13.72],[453.24,-11.28],[454.26,-8.8],[455.47,-6.28],[456.85,-3.72],[458.38,-1.12],[460.03,1.52],[461.79,4.22],[463.62,6.96],[465.51,9.75],[467.42,12.58],[469.34,15.46],[471.23,18.38],[473.08,21.33],[474.84,24.33],[476.52,27.36],[478.07,30.41],[479.47,33.49],[480.71,36.58],[481.77,39.68],[482.63,42.79],[483.27,45.9],[483.68,49.0],[483.85,52.09],[483.76,55.15],[483.42,58.19],[482.81,61.2],[481.92,64.17],[480.77,67.1],[479.35,69.98],[477.67,72.8],[475.72,75.57],[473.52,78.28],[471.07,80.93],[468.39,83.51],[465.49,86.03],[462.38,88.48],[459.07,90.87],[455.59,93.19],[451.94,95.45],[448.14,97.65],[444.22,99.79],[440.19,101.89],[436.06,103.93],[431.86,105.93],[427.6,107.89],[423.3,109.83],[418.97,111.74],[414.63,113.63],[410.3,115.51],[405.98,117.39],[401.69,119.27],[397.43,121.17],[393.23,123.08],[389.07,125.03],[384.98,127.0],[380.94,129.02],[376.97,131.08],[373.07,133.18],[369.23,135.35],[365.45,137.57],[361.73,139.86],[358.05,142.2],[354.42,144.62],[350.83,147.09],[347.26,149.63],[343.71,152.24],[340.16,154.9],[336.61,157.62],[333.03,160.39],[329.42,163.21],[325.77,166.06],[322.05,168.94],[318.27,171.85],[314.4,174.77],[310.43,177.69],[306.36,180.6],[302.17,183.49],[297.85,186.34],[293.4,189.16],[288.81,191.91],[284.06,194.6],[279.16,197.2],[274.11,199.71],[268.9,202.11],[263.52,204.39],[257.99,206.54],[252.31,208.54],[246.47,210.39],[240.49,212.07],[234.37,213.58],[228.12,214.91],[221.75,216.05],[215.27,217.0],[208.69,217.74],[202.03,218.28],[195.29,218.62],[188.49,218.74],[181.65,218.66],[174.78,218.37],[167.89,217.88],[161.0,217.19],[154.13,216.3],[147.28,215.23],[140.48,213.97],[133.73,212.54],[127.05,210.95],[120.44,209.21],[113.93,207.32],[107.51,205.31],[101.2,203.18],[95.0,200.95],[88.92,198.64],[82.96,196.25],[77.13,193.8],[71.42,191.3],[65.84,188.78],[60.39,186.24],[55.05,183.7],[49.83,181.17],[44.73,178.66],[39.73,176.2],[34.82,173.78],[30.01,171.42],[25.27,169.12],[20.61,166.91],[16.0,164.79],[11.44,162.75],[6.92,160.82],[2.42,158.98],[-2.06,157.26],[-6.55,155.64],[-11.03,154.12],[-15.54,152.72],[-20.07,151.42],[-24.64,150.23],[-29.26,149.13],[-33.92,148.13],[-38.64,147.22],[-43.42,146.39],[-48.26,145.63],[-53.17,144.94],[-58.14,144.31],[-63.18,143.72],[-68.28,143.17],[-73.44,142.64],[-78.65,142.13],[-83.91,141.63],[-89.21,141.13],[-94.54,140.6],[-99.89,140.06],[-105.25,139.47],[-110.61,138.85],[-115.95,138.17],[-121.27,137.42],[-126.55,136.61],[-131.78,135.73],[-136.94,134.76],[-142.02,133.7],[-147.01,132.56],[-151.9,131.32],[-156.66,129.98],[-161.3,128.55],[-165.81,127.01],[-170.17,125.38],[-174.37,123.65],[-178.41,121.83],[-182.29,119.92],[-186.0,117.91],[-189.54,115.83],[-192.91,113.67],[-196.11,111.44],[-199.15,109.14],[-202.02,106.79],[-204.74,104.38],[-207.32,101.93],[-209.77,99.45],[-212.09,96.93],[-214.3,94.4],[-216.42,91.85],[-218.46,89.3],[-220.43,86.75],[-222.36,84.21],[-224.27,81.69],[-226.17,79.18],[-228.08,76.7],[-230.03,74.25],[-232.03,71.83],[-234.09,69.45],[-236.25,67.11],[-238.52,64.81],[-240.91,62.56],[-243.44,60.34],[-246.12,58.17],[-248.98,56.04],[-252.01,53.94],[-255.23,51.88],[-258.66,49.85],[-262.28,47.85],[-266.12,45.88],[-270.16,43.92],[-274.41,41.97],[-278.86,40.03],[-283.52,38.09],[-288.36,36.14],[-293.39,34.18],[-298.58,32.21],[-303.93,30.2],[-309.41,28.17],[-315.02,26.09],[-320.72,23.98],[-326.49,21.81],[-332.31,19.59],[-338.16,17.31],[-344.01,14.97],[-349.83,12.56],[-355.6,10.09],[-361.28,7.54],[-366.84,4.92],[-372.27,2.23],[-377.52,-0.54],[-382.57,-3.37],[-387.4,-6.28],[-391.98,-9.25],[-396.28,-12.29],[-400.28,-15.39],[-403.96,-18.55],[-407.3,-21.76],[-410.28,-25.01],[-412.88,-28.31],[-415.1,-31.64],[-416.91,-35.0],[-418.32,-38.38],[-419.31,-41.77],[-419.89,-45.18],[-420.04,-48.58],[-419.78,-51.97],[-419.11,-55.35],[-418.03,-58.71],[-416.55,-62.05],[-414.69,-65.35],[-412.46,-68.61],[-409.87,-71.82],[-406.94,-74.99],[-403.7,-78.11],[-400.17,-81.17],[-396.36,-84.16],[-392.3,-87.1],[-388.02,-89.98],[-383.53,-92.79],[-378.88,-95.54],[-374.08,-98.23],[-369.15,-100.85],[-364.13,-103.41],[-359.05,-105.92],[-353.91,-108.37],[-348.76,-110.77],[-343.61,-113.13],[-338.48,-115.44],[-333.4,-117.72],[-328.37,-119.97],[-323.43,-122.18],[-318.58,-124.38],[-313.83,-126.56],[-309.2,-128.73],[-304.69,-130.9],[-300.31,-133.06],[-296.07,-135.23],[-291.97,-137.41],[-288.0,-139.61],[-284.17,-141.82],[-280.46,-144.04],[-276.88,-146.29],[-273.42,-148.57],[-270.07,-150.87],[-266.81,-153.19],[-263.63,-155.54],[-260.53,-157.91],[-257.48,-160.31],[-254.47,-162.72],[-251.49,-165.15],[-248.51,-167.59],[-245.53,-170.04],[-242.52,-172.49],[-239.47,-174.93],[-236.36,-177.36],[-233.19,-179.78],[-229.92,-182.17],[-226.55,-184.52],[-223.08,-186.84],[-219.47,-189.1],[-215.74,-191.31],[-211.85,-193.45],[-207.82,-195.52],[-203.63,-197.51],[-199.29,-199.41],[-194.78,-201.21],[-190.1,-202.92],[-185.27,-204.51],[-180.27,-206.0],[-175.12,-207.36],[-169.82,-208.61],[-164.38,-209.73],[-158.81,-210.73],[-153.11,-211.6],[-147.3,-212.35],[-141.4,-212.97],[-135.4,-213.47],[-129.33,-213.85],[-123.2,-214.11],[-117.02,-214.27],[-110.82,-214.32],[-104.6,-214.28],[-98.37,-214.15],[-92.16,-213.95],[-85.98,-213.67],[-79.83,-213.34],[-73.74,-212.96],[-67.71,-212.54],[-61.75,-212.1],[-55.87,-211.65],[-50.09,-211.19],[-44.4,-210.76],[-38.81,-210.34],[-33.32,-209.97],[-27.95,-209.65],[-22.68,-209.38],[-17.51,-209.19],[-12.46,-209.08],[-7.5,-209.07],[-2.64,-209.15],[2.13,-209.35],[6.82,-209.66],[11.43,-210.1],[15.98,-210.66],[20.48,-211.35],[24.94,-212.17],[29.37,-213.13],[33.78,-214.22],[38.18,-215.45],[42.6,-216.8],[47.03,-218.28],[51.5,-219.88],[56.01,-221.6],[60.58,-223.42],[65.22,-225.34],[69.94,-227.34],[74.74,-229.42],[79.65,-231.57],[84.65,-233.77],[89.77,-236.01],[95.0,-238.28],[100.35,-240.55],[105.82,-242.83],[111.41,-245.09],[117.12,-247.32],[122.95,-249.51],[128.89,-251.63],[134.95,-253.69],[141.1,-255.65],[147.36,-257.52],[153.7,-259.28],[160.12,-260.91],[166.6,-262.41],[173.14,-263.76],[179.73,-264.96],[186.35,-266.0],[192.98,-266.88],[199.62,-267.58],[206.26,-268.11],[212.87,-268.46],[219.45,-268.63],[225.98,-268.61],[232.45,-268.42],[238.86,-268.05],[245.18,-267.5],[251.41,-266.79],[257.55,-265.9],[263.58,-264.86],[269.5,-263.67],[275.3,-262.33],[280.98,-260.85],[286.53,-259.25],[291.97,-257.54],[297.28,-255.72],[302.47,-253.8],[307.54,-251.8],[312.5,-249.72],[317.35,-247.59],[322.1,-245.4],[326.76,-243.17],[331.33,-240.91],[335.83,-238.63],[340.27,-236.34],[344.66,-234.04],[349.01,-231.75],[353.33,-229.48],[357.63,-227.22],[361.92,-224.99],[366.22,-222.79],[370.54,-220.62],[374.89,-218.48],[379.27,-216.39],[383.69,-214.33],[388.17,-212.32],[392.71,-210.34],[397.3,-208.4],[401.97,-206.5],[406.7,-204.62],[411.51,-202.78],[416.38,-200.95],[421.31,-199.14],[426.3,-197.35],[431.35,-195.56],[436.44,-193.77],[441.57,-191.97],[446.72,-190.16],[451.87,-188.32],[457.03,-186.46],[462.16,-184.56],[467.26,-182.62],[472.3,-180.63],[477.26,-178.59],[482.14,-176.49],[486.89,-174.32],[491.51,-172.08],[495.98,-169.78],[500.27,-167.39],[504.37,-164.93],[508.25,-162.39],[511.89,-159.76],[515.28,-157.06],[518.4,-154.28],[521.23,-151.41],[523.77,-148.48],[525.99,-145.47],[527.89,-142.38],[529.45,-139.24],[530.68,-136.03],[531.56,-132.77],[532.1,-129.47],[532.29,-126.12],[532.14,-122.73],[531.65,-119.32],[530.84,-115.88],[529.69,-112.43],[528.25,-108.98],[526.5,-105.53],[524.48,-102.08],[522.19,-98.65],[519.67,-95.25],[516.92,-91.87],[513.99,-88.53],[510.88,-85.22],[507.62,-81.97],[504.25,-78.76],[500.79,-75.6],[497.27,-72.5],[493.71,-69.46],[490.15,-66.48],[486.61,-63.56],[483.12,-60.7],[479.71,-57.9],[476.4,-55.17],[473.22,-52.48],[470.19,-49.85],[467.34,-47.28],[464.67,-44.75],[462.21,-42.26],[459.98,-39.81],[457.99,-37.39],[456.25,-35.0]],[[458.72,-35.0],[457.2,-32.61],[455.96,-30.25],[454.98,-27.89],[454.28,-25.53],[453.86,-23.17],[453.7,-20.8],[453.8,-18.42],[454.17,-16.01],[454.77,-13.58],[455.61,-11.12],[456.66,-8.62],[457.91,-6.09],[459.34,-3.51],[460.93,-0.88],[462.65,1.79],[464.48,4.51],[466.41,7.28],[468.39,10.09],[470.41,12.96],[472.45,15.87],[474.46,18.83],[476.44,21.84],[478.35,24.88],[480.16,27.95],[481.86,31.06],[483.42,34.19],[484.82,37.34],[486.04,40.51],[487.06,43.68],[487.86,46.86],[488.43,50.03],[488.76,53.19],[488.83,56.33],[488.63,59.45],[488.17,62.53],[487.43,65.58],[486.41,68.59],[485.11,71.55],[483.54,74.46],[481.7,77.31],[479.59,80.1],[477.23,82.83],[474.62,85.49],[471.78,88.08],[468.71,90.61],[465.44,93.07],[461.97,95.46],[458.33,97.79],[454.53,100.05],[450.58,102.25],[446.52,104.4],[442.34,106.49],[438.08,108.53],[433.75,110.54],[429.36,112.5],[424.94,114.44],[420.49,116.35],[416.04,118.25],[411.6,120.14],[407.17,122.03],[402.78,123.93],[398.42,125.84],[394.11,127.77],[389.86,129.73],[385.66,131.72],[381.53,133.76],[377.46,135.84],[373.45,137.97],[369.5,140.16],[365.61,142.4],[361.77,144.71],[357.98,147.08],[354.22,149.51],[350.5,152.0],[346.79,154.56],[343.09,157.17],[339.39,159.84],[335.67,162.56],[331.93,165.33],[328.15,168.14],[324.31,170.97],[320.41,173.84],[316.43,176.71],[312.37,179.6],[308.2,182.47],[303.92,185.33],[299.51,188.16],[294.98,190.95],[290.31,193.68],[285.5,196.35],[280.54,198.93],[275.42,201.43],[270.15,203.82],[264.72,206.09],[259.14,208.24],[253.41,210.24],[247.53,212.09],[241.5,213.78],[235.33,215.3],[229.04,216.64],[222.63,217.79],[216.1,218.75],[209.48,219.5],[202.77,220.05],[195.99,220.4],[189.15,220.54],[182.26,220.46],[175.35,220.18],[168.41,219.7],[161.48,219.01],[154.56,218.12],[147.66,217.05],[140.81,215.79],[134.01,214.35],[127.28,212.75],[120.63,210.99],[114.06,209.08],[107.6,207.05],[101.24,204.89],[95.0,202.63],[88.88,200.28],[82.88,197.85],[77.01,195.36],[71.26,192.82],[65.65,190.24],[60.16,187.65],[54.8,185.05],[49.56,182.47],[44.44,179.9],[39.42,177.37],[34.5,174.88],[29.68,172.46],[24.94,170.1],[20.27,167.83],[15.66,165.64],[11.11,163.54],[6.59,161.54],[2.1,159.65],[-2.37,157.87],[-6.84,156.19],[-11.32,154.63],[-15.81,153.18],[-20.33,151.84],[-24.89,150.61],[-29.5,149.49],[-34.15,148.46],[-38.87,147.53],[-43.64,146.68],[-48.49,145.92],[-53.4,145.23],[-58.39,144.6],[-63.45,144.02],[-68.57,143.48],[-73.76,142.98],[-79.01,142.5],[-84.32,142.03],[-89.67,141.57],[-95.07,141.09],[-100.49,140.59],[-105.93,140.07],[-111.38,139.5],[-116.82,138.88],[-122.25,138.2],[-127.65,137.46],[-133.0,136.65],[-138.29,135.75],[-143.52,134.77],[-148.66,133.7],[-153.7,132.53],[-158.63,131.27],[-163.44,129.91],[-168.12,128.45],[-172.65,126.88],[-177.04,125.22],[-181.27,123.47],[-185.33,121.61],[-189.23,119.67],[-192.95,117.64],[-196.51,115.53],[-199.89,113.34],[-203.11,111.08],[-206.16,108.76],[-209.06,106.39],[-211.8,103.96],[-214.41,101.49],[-216.88,98.99],[-219.24,96.47],[-221.5,93.92],[-223.67,91.37],[-225.76,88.81],[-227.81,86.26],[-229.81,83.71],[-231.81,81.18],[-233.8,78.67],[-235.81,76.19],[-237.87,73.74],[-239.99,71.32],[-242.18,68.94],[-244.48,66.6],[-246.89,64.29],[-249.43,62.03],[-252.12,59.81],[-254.97,57.62],[-257.99,55.47],[-261.19,53.36],[-264.59,51.28],[-268.19,49.22],[-271.99,47.19],[-275.99,45.18],[-280.2,43.18],[-284.62,41.19],[-289.23,39.19],[-294.03,37.2],[-299.02,35.19],[-304.17,33.16],[-309.48,31.11],[-314.93,29.03],[-320.5,26.91],[-326.17,24.75],[-331.92,22.54],[-337.73,20.28],[-343.57,17.96],[-349.41,15.58],[-355.23,13.14],[-360.99,10.63],[-366.68,8.04],[-372.26,5.39],[-377.7,2.66],[-382.98,-0.14],[-388.06,-3.01],[-392.92,-5.95],[-397.53,-8.96],[-401.87,-12.03],[-405.91,-15.17],[-409.63,-18.36],[-413.01,-21.61],[-416.03,-24.9],[-418.68,-28.23],[-420.93,-31.6],[-422.78,-35.0],[-424.22,-38.42],[-425.24,-41.85],[-425.84,-45.29],[-426.01,-48.74],[-425.76,-52.17],[-425.08,-55.59],[-424.0,-58.99],[-422.5,-62.36],[-420.62,-65.7],[-418.35,-69.0],[-415.72,-72.25],[-412.74,-75.45],[-409.43,-78.6],[-405.81,-81.69],[-401.91,-84.72],[-397.75,-87.69],[-393.36,-90.59],[-388.75,-93.42],[-383.96,-96.19],[-379.02,-98.89],[-373.94,-101.53],[-368.76,-104.1],[-363.5,-106.62],[-358.19,-109.07],[-352.86,-111.47],[-347.52,-113.83],[-342.19,-116.13],[-336.91,-118.4],[-331.69,-120.63],[-326.54,-122.83],[-321.48,-125.01],[-316.53,-127.17],[-311.7,-129.31],[-307.0,-131.45],[-302.43,-133.59],[-298.0,-135.73],[-293.71,-137.87],[-289.57,-140.03],[-285.56,-142.21],[-281.7,-144.4],[-277.97,-146.62],[-274.37,-148.86],[-270.89,-151.13],[-267.51,-153.42],[-264.23,-155.74],[-261.03,-158.09],[-257.9,-160.46],[-254.82,-162.85],[-251.78,-165.26],[-248.76,-167.69],[-245.74,-170.12],[-242.71,-172.57],[-239.65,-175.01],[-236.55,-177.44],[-233.39,-179.87],[-230.14,-182.27],[-226.81,-184.64],[-223.37,-186.98],[-219.82,-189.27],[-216.14,-191.51],[-212.32,-193.69],[-208.36,-195.81],[-204.25,-197.84],[-199.98,-199.8],[-195.55,-201.66],[-190.96,-203.42],[-186.21,-205.08],[-181.3,-206.63],[-176.23,-208.07],[-171.01,-209.39],[-165.65,-210.59],[-160.16,-211.66],[-154.53,-212.61],[-148.79,-213.43],[-142.95,-214.14],[-137.01,-214.71],[-130.99,-215.17],[-124.91,-215.52],[-118.77,-215.75],[-112.6,-215.88],[-106.41,-215.91],[-100.2,-215.85],[-94.0,-215.71],[-87.83,-215.5],[-81.68,-215.22],[-75.58,-214.9],[-69.53,-214.53],[-63.56,-214.14],[-57.65,-213.73],[-51.84,-213.32],[-46.11,-212.92],[-40.48,-212.54],[-34.95,-212.19],[-29.53,-211.89],[-24.21,-211.65],[-18.99,-211.48],[-13.88,-211.38],[-8.86,-211.38],[-3.94,-211.47],[0.89,-211.67],[5.64,-211.99],[10.32,-212.42],[14.94,-212.99],[19.5,-213.68],[24.02,-214.5],[28.51,-215.46],[32.98,-216.55],[37.45,-217.78],[41.93,-219.14],[46.42,-220.62],[50.95,-222.22],[55.52,-223.95],[60.15,-225.78],[64.85,-227.71],[69.63,-229.73],[74.49,-231.83],[79.46,-234.0],[84.53,-236.22],[89.7,-238.49],[95.0,-240.79],[100.42,-243.1],[105.95,-245.42],[111.61,-247.72],[117.4,-249.99],[123.3,-252.23],[129.33,-254.4],[135.46,-256.51],[141.7,-258.53],[148.05,-260.45],[154.48,-262.26],[160.99,-263.95],[167.58,-265.5],[174.22,-266.91],[180.91,-268.17],[187.64,-269.27],[194.38,-270.19],[201.13,-270.95],[207.88,-271.52],[214.61,-271.91],[221.31,-272.12],[227.96,-272.14],[234.55,-271.98],[241.07,-271.63],[247.51,-271.1],[253.85,-270.4],[260.1,-269.53],[266.24,-268.48],[272.26,-267.29],[278.16,-265.93],[283.93,-264.44],[289.58,-262.82],[295.09,-261.07],[300.48,-259.21],[305.73,-257.24],[310.86,-255.19],[315.87,-253.06],[320.77,-250.85],[325.55,-248.6],[330.23,-246.29],[334.82,-243.95],[339.33,-241.58],[343.76,-239.2],[348.13,-236.81],[352.45,-234.42],[356.74,-232.04],[360.99,-229.68],[365.24,-227.35],[369.48,-225.04],[373.73,-222.76],[377.99,-220.52],[382.29,-218.32],[386.63,-216.16],[391.01,-214.04],[395.45,-211.96],[399.95,-209.92],[404.51,-207.91],[409.14,-205.94],[413.83,-204.01],[418.59,-202.1],[423.42,-200.21],[428.31,-198.33],[433.26,-196.47],[438.25,-194.61],[443.28,-192.75],[448.34,-190.87],[453.41,-188.99],[458.49,-187.07],[463.56,-185.13],[468.59,-183.15],[473.58,-181.13],[478.5,-179.05],[483.33,-176.93],[488.06,-174.74],[492.67,-172.48],[497.13,-170.16],[501.42,-167.77],[505.52,-165.3],[509.42,-162.75],[513.09,-160.12],[516.51,-157.42],[519.68,-154.64],[522.56,-151.78],[525.15,-148.84],[527.43,-145.84],[529.4,-142.76],[531.04,-139.62],[532.34,-136.42],[533.3,-133.16],[533.92,-129.86],[534.2,-126.51],[534.13,-123.13],[533.72,-119.71],[532.98,-116.28],[531.92,-112.83],[530.55,-109.37],[528.87,-105.91],[526.92,-102.46],[524.7,-99.03],[522.23,-95.61],[519.54,-92.22],[516.65,-88.87],[513.58,-85.55],[510.36,-82.28],[507.01,-79.05],[503.57,-75.88],[500.06,-72.76],[496.51,-69.71],[492.95,-66.71],[489.4,-63.77],[485.9,-60.89],[482.47,-58.07],[479.14,-55.31],[475.93,-52.61],[472.87,-49.96],[469.98,-47.36],[467.28,-44.81],[464.79,-42.31],[462.52,-39.84],[460.49,-37.41],[458.72,-35.0]],[[461.34,-35.0],[459.79,-32.6],[458.52,-30.21],[457.52,-27.84],[456.8,-25.46],[456.36,-23.09],[456.19,-20.7],[456.29,-18.3],[456.66,-15.88],[457.27,-13.43],[458.13,-10.95],[459.21,-8.44],[460.5,-5.88],[461.97,-3.28],[463.62,-0.63],[465.4,2.06],[467.31,4.81],[469.32,7.61],[471.4,10.46],[473.53,13.36],[475.67,16.31],[477.81,19.31],[479.91,22.35],[481.95,25.44],[483.91,28.56],[485.75,31.72],[487.46,34.91],[489.01,38.12],[490.39,41.35],[491.56,44.59],[492.52,47.83],[493.25,51.07],[493.73,54.3],[493.96,57.52],[493.91,60.71],[493.59,63.88],[492.99,67.01],[492.1,70.1],[490.93,73.14],[489.47,76.13],[487.73,79.06],[485.72,81.93],[483.44,84.74],[480.91,87.48],[478.12,90.15],[475.1,92.76],[471.86,95.29],[468.41,97.75],[464.78,100.14],[460.97,102.47],[457.0,104.73],[452.9,106.93],[448.68,109.07],[444.35,111.16],[439.95,113.2],[435.47,115.2],[430.95,117.16],[426.4,119.1],[421.83,121.02],[417.26,122.92],[412.7,124.81],[408.16,126.71],[403.65,128.61],[399.19,130.53],[394.77,132.47],[390.41,134.45],[386.11,136.45],[381.86,138.5],[377.68,140.6],[373.56,142.75],[369.5,144.95],[365.49,147.21],[361.52,149.53],[357.6,151.91],[353.71,154.35],[349.85,156.86],[345.99,159.42],[342.15,162.04],[338.29,164.71],[334.41,167.42],[330.49,170.18],[326.53,172.97],[322.51,175.78],[318.42,178.62],[314.25,181.45],[309.98,184.29],[305.61,187.11],[301.12,189.91],[296.51,192.67],[291.76,195.37],[286.88,198.02],[281.85,200.59],[276.67,203.07],[271.34,205.45],[265.86,207.71],[260.23,209.85],[254.45,211.85],[248.52,213.71],[242.45,215.4],[236.24,216.92],[229.91,218.27],[223.45,219.43],[216.89,220.4],[210.23,221.16],[203.48,221.73],[196.66,222.09],[189.78,222.23],[182.85,222.17],[175.89,221.9],[168.91,221.43],[161.93,220.74],[154.97,219.86],[148.03,218.79],[141.13,217.53],[134.28,216.08],[127.51,214.47],[120.81,212.7],[114.2,210.78],[107.69,208.73],[101.29,206.55],[95.0,204.27],[88.84,201.88],[82.8,199.42],[76.89,196.89],[71.11,194.3],[65.46,191.68],[59.95,189.04],[54.56,186.39],[49.29,183.75],[44.15,181.12],[39.11,178.53],[34.18,175.99],[29.35,173.51],[24.6,171.09],[19.93,168.75],[15.32,166.5],[10.77,164.34],[6.26,162.28],[1.77,160.33],[-2.69,158.5],[-7.15,156.77],[-11.62,155.16],[-16.1,153.67],[-20.61,152.29],[-25.16,151.03],[-29.75,149.87],[-34.4,148.82],[-39.11,147.87],[-43.89,147.01],[-48.74,146.23],[-53.66,145.54],[-58.66,144.91],[-63.74,144.34],[-68.89,143.83],[-74.11,143.35],[-79.4,142.9],[-84.76,142.46],[-90.16,142.04],[-95.62,141.6],[-101.12,141.16],[-106.64,140.68],[-112.18,140.17],[-117.73,139.62],[-123.26,139.01],[-128.78,138.34],[-134.26,137.59],[-139.69,136.77],[-145.05,135.86],[-150.34,134.87],[-155.54,133.78],[-160.64,132.59],[-165.62,131.3],[-170.48,129.91],[-175.19,128.42],[-179.76,126.83],[-184.18,125.14],[-188.43,123.35],[-192.52,121.46],[-196.44,119.49],[-200.18,117.42],[-203.75,115.28],[-207.16,113.07],[-210.39,110.78],[-213.46,108.43],[-216.38,106.03],[-219.15,103.59],[-221.78,101.1],[-224.29,98.58],[-226.69,96.04],[-228.99,93.48],[-231.22,90.92],[-233.37,88.35],[-235.49,85.78],[-237.57,83.23],[-239.65,80.69],[-241.73,78.18],[-243.85,75.69],[-246.02,73.23],[-248.25,70.81],[-250.58,68.42],[-253.01,66.07],[-255.56,63.76],[-258.25,61.48],[-261.09,59.24],[-264.1,57.04],[-267.28,54.87],[-270.65,52.73],[-274.21,50.62],[-277.97,48.53],[-281.93,46.46],[-286.1,44.41],[-290.47,42.36],[-295.03,40.31],[-299.78,38.26],[-304.72,36.2],[-309.82,34.13],[-315.08,32.03],[-320.49,29.9],[-326.02,27.73],[-331.65,25.53],[-337.37,23.28],[-343.15,20.97],[-348.96,18.62],[-354.78,16.2],[-360.59,13.71],[-366.34,11.16],[-372.03,8.54],[-377.61,5.85],[-383.06,3.09],[-388.35,0.25],[-393.45,-2.65],[-398.34,-5.63],[-402.98,-8.67],[-407.34,-11.78],[-411.42,-14.95],[-415.17,-18.18],[-418.59,-21.46],[-421.65,-24.79],[-424.33,-28.16],[-426.61,-31.57],[-428.5,-35.0],[-429.97,-38.46],[-431.01,-41.93],[-431.63,-45.41],[-431.82,-48.89],[-431.57,-52.36],[-430.9,-55.82],[-429.81,-59.26],[-428.3,-62.67],[-426.39,-66.04],[-424.09,-69.38],[-421.42,-72.67],[-418.38,-75.9],[-415.01,-79.08],[-411.32,-82.2],[-407.33,-85.26],[-403.07,-88.26],[-398.57,-91.18],[-393.85,-94.04],[-388.93,-96.82],[-383.84,-99.54],[-378.62,-102.19],[-373.28,-104.78],[-367.86,-107.3],[-362.38,-109.76],[-356.86,-112.16],[-351.33,-114.51],[-345.82,-116.81],[-340.34,-119.06],[-334.92,-121.28],[-329.57,-123.47],[-324.32,-125.62],[-319.17,-127.76],[-314.14,-129.88],[-309.24,-131.99],[-304.48,-134.1],[-299.86,-136.21],[-295.39,-138.32],[-291.07,-140.45],[-286.9,-142.59],[-282.88,-144.75],[-279.01,-146.93],[-275.26,-149.14],[-271.65,-151.37],[-268.16,-153.63],[-264.77,-155.92],[-261.48,-158.24],[-258.26,-160.59],[-255.11,-162.96],[-252.02,-165.35],[-248.95,-167.76],[-245.9,-170.19],[-242.86,-172.62],[-239.79,-175.06],[-236.69,-177.5],[-233.54,-179.93],[-230.32,-182.35],[-227.02,-184.74],[-223.63,-187.1],[-220.13,-189.42],[-216.51,-191.7],[-212.76,-193.92],[-208.87,-196.08],[-204.83,-198.16],[-200.64,-200.17],[-196.3,-202.09],[-191.8,-203.91],[-187.13,-205.64],[-182.31,-207.26],[-177.33,-208.77],[-172.2,-210.17],[-166.92,-211.44],[-161.51,-212.6],[-155.96,-213.63],[-150.29,-214.53],[-144.52,-215.32],[-138.64,-215.98],[-132.68,-216.52],[-126.65,-216.95],[-120.56,-217.26],[-114.42,-217.47],[-108.26,-217.57],[-102.08,-217.59],[-95.9,-217.52],[-89.73,-217.37],[-83.58,-217.16],[-77.48,-216.9],[-71.42,-216.59],[-65.42,-216.25],[-59.5,-215.89],[-53.65,-215.52],[-47.89,-215.16],[-42.22,-214.82],[-36.64,-214.5],[-31.17,-214.23],[-25.8,-214.01],[-20.52,-213.85],[-15.35,-213.77],[-10.28,-213.78],[-5.29,-213.88],[-0.4,-214.09],[4.42,-214.41],[9.16,-214.85],[13.85,-215.41],[18.47,-216.1],[23.06,-216.93],[27.62,-217.88],[32.16,-218.97],[36.69,-220.2],[41.23,-221.56],[45.79,-223.04],[50.38,-224.65],[55.01,-226.37],[59.71,-228.21],[64.47,-230.15],[69.31,-232.18],[74.24,-234.3],[79.26,-236.48],[84.39,-238.73],[89.64,-241.02],[95.0,-243.35],[100.48,-245.69],[106.09,-248.04],[111.82,-250.38],[117.68,-252.7],[123.66,-254.97],[129.76,-257.19],[135.98,-259.34],[142.31,-261.41],[148.74,-263.39],[155.26,-265.25],[161.87,-266.99],[168.55,-268.6],[175.29,-270.06],[182.09,-271.37],[188.92,-272.52],[195.78,-273.49],[202.64,-274.29],[209.5,-274.91],[216.34,-275.34],[223.15,-275.59],[229.92,-275.64],[236.63,-275.51],[243.26,-275.19],[249.82,-274.68],[256.27,-273.99],[262.63,-273.12],[268.87,-272.08],[275.0,-270.88],[281.0,-269.51],[286.86,-268.0],[292.59,-266.35],[298.19,-264.57],[303.65,-262.67],[308.97,-260.66],[314.16,-258.55],[319.22,-256.36],[324.15,-254.1],[328.97,-251.77],[333.67,-249.38],[338.28,-246.96],[342.78,-244.51],[347.21,-242.03],[351.57,-239.55],[355.86,-237.06],[360.11,-234.58],[364.32,-232.12],[368.51,-229.68],[372.69,-227.26],[376.86,-224.88],[381.05,-222.53],[385.27,-220.22],[389.51,-217.95],[393.8,-215.72],[398.14,-213.54],[402.53,-211.4],[406.98,-209.3],[411.5,-207.23],[416.08,-205.2],[420.74,-203.2],[425.45,-201.23],[430.23,-199.27],[435.07,-197.34],[439.96,-195.41],[444.89,-193.48],[449.86,-191.55],[454.85,-189.6],[459.85,-187.64],[464.84,-185.65],[469.81,-183.63],[474.74,-181.57],[479.61,-179.47],[484.41,-177.32],[489.11,-175.11],[493.69,-172.84],[498.14,-170.5],[502.43,-168.1],[506.54,-165.62],[510.45,-163.07],[514.15,-160.44],[517.61,-157.74],[520.82,-154.96],[523.75,-152.1],[526.4,-149.17],[528.75,-146.17],[530.79,-143.1],[532.5,-139.97],[533.88,-136.78],[534.93,-133.53],[535.64,-130.23],[536.0,-126.89],[536.02,-123.51],[535.7,-120.1],[535.05,-116.66],[534.08,-113.21],[532.79,-109.75],[531.2,-106.29],[529.32,-102.84],[527.17,-99.4],[524.77,-95.97],[522.14,-92.57],[519.31,-89.21],[516.29,-85.88],[513.11,-82.59],[509.8,-79.35],[506.39,-76.16],[502.9,-73.03],[499.37,-69.95],[495.82,-66.93],[492.27,-63.98],[488.77,-61.08],[485.33,-58.24],[481.98,-55.46],[478.76,-52.74],[475.67,-50.07],[472.75,-47.45],[470.02,-44.89],[467.5,-42.36],[465.2,-39.88],[463.14,-37.42],[461.34,-35.0]],[[464.11,-35.0],[462.54,-32.58],[461.24,-30.18],[460.22,-27.78],[459.48,-25.39],[459.02,-23.0],[458.85,-20.6],[458.94,-18.18],[459.31,-15.74],[459.94,-13.27],[460.81,-10.77],[461.92,-8.24],[463.24,-5.66],[464.76,-3.04],[466.45,-0.37],[468.3,2.35],[470.28,5.13],[472.37,7.95],[474.54,10.84],[476.76,13.77],[479.01,16.76],[481.26,19.8],[483.49,22.89],[485.66,26.02],[487.75,29.19],[489.73,32.4],[491.59,35.65],[493.29,38.91],[494.82,42.2],[496.15,45.51],[497.26,48.82],[498.14,52.13],[498.78,55.43],[499.15,58.72],[499.25,61.99],[499.07,65.24],[498.6,68.45],[497.85,71.62],[496.79,74.74],[495.45,77.81],[493.82,80.83],[491.9,83.78],[489.7,86.67],[487.24,89.49],[484.51,92.24],[481.53,94.92],[478.32,97.52],[474.9,100.06],[471.27,102.51],[467.45,104.9],[463.46,107.22],[459.32,109.47],[455.05,111.66],[450.66,113.8],[446.18,115.88],[441.62,117.91],[437.0,119.9],[432.34,121.86],[427.65,123.79],[422.95,125.71],[418.25,127.6],[413.56,129.5],[408.9,131.4],[404.28,133.3],[399.7,135.23],[395.17,137.18],[390.69,139.16],[386.28,141.17],[381.92,143.23],[377.62,145.34],[373.38,147.49],[369.19,149.71],[365.06,151.98],[360.97,154.31],[356.91,156.7],[352.88,159.14],[348.87,161.65],[344.87,164.21],[340.87,166.82],[336.84,169.48],[332.8,172.18],[328.71,174.92],[324.57,177.68],[320.36,180.47],[316.08,183.26],[311.71,186.05],[307.24,188.83],[302.66,191.59],[297.97,194.32],[293.14,197.0],[288.19,199.61],[283.1,202.16],[277.86,204.62],[272.47,206.99],[266.94,209.24],[261.26,211.37],[255.43,213.37],[249.46,215.22],[243.35,216.92],[237.1,218.45],[230.73,219.8],[224.23,220.97],[217.63,221.95],[210.93,222.73],[204.15,223.31],[197.29,223.68],[190.37,223.84],[183.4,223.79],[176.4,223.53],[169.38,223.07],[162.36,222.39],[155.36,221.52],[148.37,220.45],[141.43,219.19],[134.54,217.75],[127.72,216.13],[120.98,214.35],[114.33,212.43],[107.77,210.36],[101.33,208.16],[95.0,205.85],[88.79,203.44],[82.72,200.95],[76.77,198.38],[70.96,195.76],[65.28,193.1],[59.73,190.41],[54.32,187.71],[49.03,185.02],[43.86,182.34],[38.81,179.7],[33.86,177.1],[29.02,174.56],[24.26,172.08],[19.59,169.68],[14.98,167.37],[10.42,165.16],[5.91,163.05],[1.44,161.04],[-3.02,159.15],[-7.47,157.38],[-11.93,155.72],[-16.4,154.19],[-20.9,152.77],[-25.44,151.47],[-30.03,150.28],[-34.68,149.21],[-39.38,148.23],[-44.16,147.36],[-49.01,146.58],[-53.95,145.88],[-58.96,145.26],[-64.06,144.71],[-69.23,144.2],[-74.49,143.75],[-79.82,143.32],[-85.22,142.92],[-90.69,142.54],[-96.21,142.15],[-101.78,141.75],[-107.39,141.33],[-113.02,140.88],[-118.66,140.39],[-124.31,139.85],[-129.94,139.24],[-135.55,138.57],[-141.12,137.82],[-146.63,136.99],[-152.08,136.07],[-157.44,135.05],[-162.7,133.94],[-167.86,132.73],[-172.89,131.41],[-177.79,129.99],[-182.55,128.47],[-187.15,126.84],[-191.6,125.12],[-195.88,123.29],[-199.99,121.37],[-203.93,119.36],[-207.69,117.26],[-211.29,115.09],[-214.71,112.84],[-217.96,110.53],[-221.05,108.15],[-223.99,105.72],[-226.79,103.25],[-229.45,100.74],[-232.0,98.2],[-234.44,95.64],[-236.79,93.07],[-239.06,90.48],[-241.28,87.9],[-243.46,85.32],[-245.62,82.76],[-247.78,80.21],[-249.96,77.69],[-252.18,75.19],[-254.46,72.72],[-256.81,70.29],[-259.26,67.89],[-261.82,65.52],[-264.51,63.19],[-267.34,60.9],[-270.33,58.64],[-273.49,56.41],[-276.82,54.21],[-280.35,52.04],[-284.06,49.9],[-287.98,47.77],[-292.09,45.65],[-296.4,43.55],[-300.91,41.45],[-305.6,39.34],[-310.48,37.23],[-315.52,35.1],[-320.73,32.95],[-326.08,30.77],[-331.56,28.56],[-337.15,26.31],[-342.82,24.01],[-348.56,21.67],[-354.33,19.26],[-360.13,16.8],[-365.91,14.28],[-371.65,11.69],[-377.32,9.04],[-382.9,6.31],[-388.35,3.51],[-393.64,0.64],[-398.75,-2.3],[-403.65,-5.31],[-408.31,-8.39],[-412.7,-11.53],[-416.8,-14.74],[-420.58,-18.0],[-424.03,-21.32],[-427.11,-24.68],[-429.82,-28.09],[-432.14,-31.53],[-434.05,-35.0],[-435.55,-38.49],[-436.62,-42.0],[-437.25,-45.52],[-437.46,-49.04],[-437.22,-52.55],[-436.55,-56.04],[-435.45,-59.52],[-433.93,-62.97],[-432.0,-66.38],[-429.67,-69.75],[-426.96,-73.07],[-423.87,-76.34],[-420.44,-79.55],[-416.68,-82.7],[-412.61,-85.79],[-408.26,-88.81],[-403.65,-91.76],[-398.81,-94.64],[-393.77,-97.44],[-388.55,-100.18],[-383.18,-102.84],[-377.69,-105.43],[-372.11,-107.96],[-366.46,-110.42],[-360.77,-112.82],[-355.06,-115.17],[-349.36,-117.46],[-343.69,-119.71],[-338.08,-121.91],[-332.54,-124.08],[-327.08,-126.22],[-321.74,-128.33],[-316.52,-130.43],[-311.42,-132.51],[-306.47,-134.59],[-301.67,-136.67],[-297.02,-138.75],[-292.53,-140.84],[-288.2,-142.95],[-284.02,-145.08],[-279.99,-147.22],[-276.11,-149.4],[-272.37,-151.6],[-268.76,-153.83],[-265.26,-156.09],[-261.88,-158.38],[-258.58,-160.7],[-255.37,-163.05],[-252.21,-165.42],[-249.1,-167.82],[-246.02,-170.24],[-242.96,-172.67],[-239.88,-175.1],[-236.79,-177.55],[-233.65,-179.98],[-230.46,-182.41],[-227.2,-184.82],[-223.85,-187.21],[-220.41,-189.56],[-216.85,-191.87],[-213.17,-194.13],[-209.35,-196.33],[-205.4,-198.47],[-201.29,-200.53],[-197.03,-202.51],[-192.62,-204.4],[-188.05,-206.2],[-183.32,-207.89],[-178.43,-209.47],[-173.39,-210.95],[-168.2,-212.3],[-162.87,-213.54],[-157.41,-214.66],[-151.82,-215.65],[-146.11,-216.52],[-140.3,-217.27],[-134.4,-217.89],[-128.43,-218.4],[-122.38,-218.8],[-116.29,-219.09],[-110.16,-219.28],[-104.0,-219.37],[-97.84,-219.37],[-91.68,-219.3],[-85.54,-219.16],[-79.43,-218.96],[-73.36,-218.71],[-67.35,-218.43],[-61.4,-218.12],[-55.52,-217.8],[-49.73,-217.48],[-44.02,-217.17],[-38.4,-216.89],[-32.87,-216.65],[-27.45,-216.45],[-22.12,-216.32],[-16.89,-216.26],[-11.75,-216.28],[-6.7,-216.39],[-1.74,-216.61],[3.15,-216.93],[7.96,-217.37],[12.71,-217.94],[17.41,-218.63],[22.06,-219.45],[26.69,-220.4],[31.3,-221.49],[35.9,-222.71],[40.5,-224.06],[45.13,-225.55],[49.79,-227.15],[54.49,-228.88],[59.25,-230.72],[64.07,-232.67],[68.98,-234.71],[73.97,-236.83],[79.06,-239.03],[84.26,-241.29],[89.57,-243.61],[95.0,-245.95],[100.55,-248.33],[106.23,-250.7],[112.03,-253.08],[117.96,-255.43],[124.02,-257.74],[130.2,-260.0],[136.5,-262.2],[142.91,-264.31],[149.43,-266.33],[156.04,-268.24],[162.75,-270.03],[169.52,-271.69],[176.37,-273.2],[183.26,-274.56],[190.2,-275.75],[197.16,-276.77],[204.14,-277.62],[211.11,-278.28],[218.06,-278.75],[224.99,-279.03],[231.87,-279.12],[238.69,-279.01],[245.44,-278.71],[252.1,-278.22],[258.67,-277.55],[265.14,-276.68],[271.49,-275.64],[277.71,-274.43],[283.81,-273.06],[289.77,-271.53],[295.59,-269.85],[301.26,-268.04],[306.79,-266.1],[312.18,-264.05],[317.43,-261.89],[322.54,-259.64],[327.51,-257.31],[332.36,-254.9],[337.08,-252.45],[341.7,-249.94],[346.21,-247.4],[350.63,-244.84],[354.96,-242.26],[359.23,-239.67],[363.44,-237.09],[367.61,-234.53],[371.74,-231.98],[375.85,-229.45],[379.96,-226.96],[384.07,-224.5],[388.19,-222.08],[392.35,-219.71],[396.53,-217.38],[400.77,-215.09],[405.05,-212.84],[409.39,-210.64],[413.8,-208.48],[418.27,-206.36],[422.8,-204.27],[427.41,-202.21],[432.07,-200.18],[436.8,-198.16],[441.58,-196.16],[446.42,-194.17],[451.28,-192.17],[456.18,-190.17],[461.09,-188.16],[466.01,-186.13],[470.91,-184.07],[475.78,-181.98],[480.6,-179.84],[485.35,-177.66],[490.02,-175.43],[494.58,-173.14],[499.02,-170.8],[503.31,-168.38],[507.43,-165.9],[511.36,-163.35],[515.08,-160.72],[518.58,-158.02],[521.83,-155.24],[524.82,-152.39],[527.53,-149.47],[529.94,-146.48],[532.06,-143.42],[533.85,-140.29],[535.32,-137.11],[536.45,-133.87],[537.25,-130.58],[537.71,-127.24],[537.83,-123.87],[537.61,-120.47],[537.05,-117.03],[536.17,-113.59],[534.98,-110.13],[533.48,-106.67],[531.69,-103.21],[529.62,-99.76],[527.3,-96.33],[524.74,-92.92],[521.97,-89.55],[519.02,-86.21],[515.89,-82.91],[512.63,-79.65],[509.26,-76.45],[505.8,-73.3],[502.3,-70.21],[498.76,-67.17],[495.23,-64.19],[491.73,-61.27],[488.29,-58.42],[484.94,-55.62],[481.7,-52.87],[478.6,-50.19],[475.66,-47.55],[472.91,-44.96],[470.36,-42.42],[468.04,-39.91],[465.95,-37.44],[464.11,-35.0]],[[467.06,-35.0],[465.46,-32.56],[464.14,-30.14],[463.09,-27.72],[462.34,-25.32],[461.86,-22.9],[461.68,-20.48],[461.77,-18.05],[462.14,-15.59],[462.77,-13.1],[463.66,-10.59],[464.79,-8.03],[466.14,-5.43],[467.7,-2.79],[469.44,-0.09],[471.35,2.66],[473.39,5.46],[475.56,8.32],[477.81,11.23],[480.12,14.2],[482.48,17.23],[484.84,20.31],[487.18,23.44],[489.47,26.61],[491.69,29.84],[493.81,33.1],[495.81,36.4],[497.65,39.72],[499.33,43.07],[500.81,46.44],[502.07,49.82],[503.1,53.2],[503.88,56.57],[504.4,59.94],[504.65,63.29],[504.61,66.61],[504.27,69.9],[503.64,73.15],[502.71,76.36],[501.48,79.51],[499.95,82.61],[498.12,85.64],[496.0,88.61],[493.61,91.51],[490.94,94.34],[488.01,97.09],[484.83,99.77],[481.42,102.37],[477.79,104.9],[473.96,107.35],[469.95,109.73],[465.78,112.04],[461.46,114.28],[457.01,116.45],[452.45,118.57],[447.81,120.64],[443.09,122.66],[438.31,124.64],[433.5,126.59],[428.67,128.51],[423.83,130.41],[418.99,132.3],[414.18,134.19],[409.39,136.08],[404.64,137.99],[399.94,139.91],[395.29,141.86],[390.69,143.84],[386.16,145.86],[381.68,147.93],[377.26,150.04],[372.89,152.2],[368.58,154.42],[364.31,156.69],[360.09,159.02],[355.89,161.41],[351.72,163.86],[347.56,166.36],[343.41,168.91],[339.24,171.51],[335.05,174.15],[330.83,176.83],[326.57,179.54],[322.25,182.27],[317.85,185.01],[313.38,187.76],[308.81,190.49],[304.15,193.21],[299.37,195.9],[294.47,198.54],[289.44,201.13],[284.28,203.65],[278.98,206.1],[273.54,208.44],[267.95,210.68],[262.22,212.81],[256.35,214.8],[250.34,216.65],[244.18,218.34],[237.9,219.88],[231.49,221.24],[224.96,222.41],[218.33,223.4],[211.59,224.19],[204.77,224.78],[197.88,225.17],[190.92,225.35],[183.92,225.31],[176.89,225.07],[169.83,224.62],[162.77,223.96],[155.73,223.09],[148.7,222.03],[141.72,220.78],[134.79,219.34],[127.93,217.72],[121.14,215.94],[114.45,214.01],[107.85,211.93],[101.37,209.72],[95.0,207.39],[88.76,204.96],[82.64,202.44],[76.66,199.84],[70.81,197.19],[65.1,194.49],[59.52,191.76],[54.08,189.02],[48.76,186.28],[43.58,183.56],[38.5,180.86],[33.54,178.21],[28.69,175.61],[23.92,173.08],[19.24,170.63],[14.62,168.27],[10.07,166.0],[5.56,163.83],[1.09,161.78],[-3.37,159.83],[-7.81,158.01],[-12.26,156.31],[-16.73,154.74],[-21.22,153.28],[-25.75,151.95],[-30.34,150.73],[-34.98,149.63],[-39.68,148.64],[-44.46,147.76],[-49.32,146.97],[-54.26,146.27],[-59.29,145.65],[-64.41,145.1],[-69.61,144.62],[-74.9,144.18],[-80.27,143.79],[-85.72,143.42],[-91.25,143.07],[-96.84,142.73],[-102.48,142.38],[-108.17,142.02],[-113.89,141.62],[-119.64,141.19],[-125.4,140.71],[-131.15,140.18],[-136.89,139.58],[-142.6,138.9],[-148.26,138.14],[-153.85,137.3],[-159.38,136.36],[-164.81,135.32],[-170.14,134.18],[-175.36,132.94],[-180.44,131.59],[-185.39,130.14],[-190.19,128.58],[-194.83,126.92],[-199.31,125.16],[-203.62,123.29],[-207.75,121.33],[-211.71,119.29],[-215.5,117.15],[-219.11,114.94],[-222.55,112.66],[-225.82,110.31],[-228.93,107.9],[-231.89,105.44],[-234.72,102.94],[-237.41,100.41],[-239.99,97.84],[-242.47,95.26],[-244.87,92.66],[-247.19,90.06],[-249.47,87.46],[-251.72,84.87],[-253.96,82.29],[-256.2,79.73],[-258.47,77.19],[-260.79,74.67],[-263.17,72.19],[-265.64,69.74],[-268.21,67.32],[-270.89,64.93],[-273.71,62.58],[-276.68,60.26],[-279.81,57.98],[-283.11,55.72],[-286.59,53.49],[-290.26,51.28],[-294.12,49.1],[-298.17,46.92],[-302.42,44.76],[-306.86,42.6],[-311.49,40.43],[-316.3,38.27],[-321.28,36.08],[-326.42,33.88],[-331.71,31.65],[-337.12,29.39],[-342.65,27.09],[-348.27,24.75],[-353.96,22.36],[-359.69,19.91],[-365.44,17.41],[-371.19,14.85],[-376.9,12.22],[-382.55,9.52],[-388.11,6.76],[-393.55,3.92],[-398.84,1.02],[-403.95,-1.96],[-408.85,-5.0],[-413.52,-8.11],[-417.92,-11.29],[-422.04,-14.53],[-425.85,-17.83],[-429.31,-21.18],[-432.43,-24.58],[-435.16,-28.02],[-437.51,-31.49],[-439.44,-35.0],[-440.96,-38.53],[-442.05,-42.07],[-442.71,-45.63],[-442.92,-49.18],[-442.7,-52.73],[-442.03,-56.26],[-440.93,-59.77],[-439.4,-63.25],[-437.44,-66.7],[-435.08,-70.1],[-432.33,-73.46],[-429.2,-76.76],[-425.71,-80.01],[-421.88,-83.19],[-417.73,-86.3],[-413.3,-89.35],[-408.59,-92.32],[-403.64,-95.22],[-398.48,-98.04],[-393.14,-100.79],[-387.63,-103.47],[-381.99,-106.07],[-376.25,-108.61],[-370.44,-111.07],[-364.58,-113.48],[-358.7,-115.82],[-352.82,-118.1],[-346.96,-120.34],[-341.16,-122.53],[-335.43,-124.68],[-329.78,-126.8],[-324.25,-128.9],[-318.83,-130.97],[-313.55,-133.02],[-308.41,-135.07],[-303.43,-137.12],[-298.6,-139.17],[-293.94,-141.23],[-289.44,-143.3],[-285.11,-145.39],[-280.93,-147.51],[-276.92,-149.65],[-273.05,-151.81],[-269.32,-154.01],[-265.72,-156.24],[-262.24,-158.51],[-258.87,-160.8],[-255.58,-163.13],[-252.37,-165.48],[-249.22,-167.87],[-246.11,-170.27],[-243.02,-172.69],[-239.94,-175.13],[-236.85,-177.57],[-233.74,-180.02],[-230.57,-182.46],[-227.35,-184.89],[-224.05,-187.3],[-220.66,-189.68],[-217.16,-192.03],[-213.55,-194.33],[-209.81,-196.58],[-205.94,-198.76],[-201.92,-200.88],[-197.76,-202.92],[-193.44,-204.88],[-188.96,-206.75],[-184.32,-208.51],[-179.53,-210.18],[-174.58,-211.73],[-169.49,-213.17],[-164.25,-214.49],[-158.87,-215.7],[-153.36,-216.78],[-147.73,-217.74],[-141.99,-218.57],[-136.16,-219.29],[-130.24,-219.89],[-124.25,-220.38],[-118.2,-220.75],[-112.1,-221.02],[-105.98,-221.2],[-99.83,-221.28],[-93.69,-221.28],[-87.55,-221.21],[-81.44,-221.08],[-75.37,-220.9],[-69.34,-220.67],[-63.37,-220.42],[-57.46,-220.15],[-51.63,-219.88],[-45.88,-219.61],[-40.22,-219.37],[-34.64,-219.16],[-29.16,-218.99],[-23.77,-218.88],[-18.48,-218.84],[-13.28,-218.88],[-8.16,-219.0],[-3.13,-219.22],[1.82,-219.55],[6.71,-220.0],[11.53,-220.56],[16.3,-221.25],[21.03,-222.07],[25.73,-223.01],[30.41,-224.1],[35.08,-225.31],[39.76,-226.66],[44.45,-228.14],[49.18,-229.74],[53.95,-231.47],[58.78,-233.31],[63.67,-235.25],[68.64,-237.3],[73.7,-239.43],[78.86,-241.64],[84.12,-243.91],[89.5,-246.24],[95.0,-248.61],[100.62,-251.0],[106.37,-253.4],[112.25,-255.8],[118.25,-258.18],[124.39,-260.53],[130.64,-262.83],[137.02,-265.06],[143.52,-267.22],[150.12,-269.28],[156.83,-271.23],[163.62,-273.07],[170.49,-274.77],[177.44,-276.33],[184.43,-277.73],[191.47,-278.97],[198.54,-280.04],[205.62,-280.92],[212.7,-281.62],[219.77,-282.13],[226.81,-282.45],[233.8,-282.56],[240.73,-282.48],[247.59,-282.21],[254.37,-281.73],[261.05,-281.07],[267.62,-280.21],[274.07,-279.17],[280.4,-277.95],[286.59,-276.57],[292.64,-275.02],[298.54,-273.32],[304.3,-271.47],[309.9,-269.49],[315.36,-267.39],[320.66,-265.18],[325.82,-262.88],[330.83,-260.48],[335.71,-258.01],[340.46,-255.48],[345.08,-252.89],[349.59,-250.26],[354.0,-247.61],[358.32,-244.93],[362.56,-242.25],[366.73,-239.57],[370.85,-236.9],[374.93,-234.24],[378.97,-231.61],[383.0,-229.01],[387.03,-226.44],[391.07,-223.92],[395.12,-221.43],[399.21,-218.99],[403.34,-216.6],[407.51,-214.25],[411.74,-211.95],[416.02,-209.69],[420.38,-207.48],[424.79,-205.3],[429.28,-203.15],[433.83,-201.04],[438.45,-198.95],[443.12,-196.87],[447.84,-194.81],[452.61,-192.76],[457.41,-190.7],[462.24,-188.64],[467.07,-186.56],[471.9,-184.46],[476.7,-182.33],[481.47,-180.17],[486.18,-177.97],[490.81,-175.71],[495.35,-173.41],[499.77,-171.05],[504.05,-168.63],[508.18,-166.14],[512.13,-163.58],[515.88,-160.96],[519.41,-158.26],[522.71,-155.49],[525.76,-152.65],[528.53,-149.74],[531.02,-146.75],[533.21,-143.7],[535.08,-140.59],[536.64,-137.42],[537.87,-134.19],[538.77,-130.91],[539.33,-127.58],[539.55,-124.22],[539.43,-120.82],[538.98,-117.39],[538.21,-113.95],[537.11,-110.49],[535.71,-107.03],[534.02,-103.57],[532.05,-100.12],[529.82,-96.69],[527.34,-93.27],[524.65,-89.89],[521.76,-86.54],[518.71,-83.23],[515.5,-79.96],[512.18,-76.74],[508.77,-73.58],[505.3,-70.46],[501.79,-67.41],[498.28,-64.41],[494.8,-61.48],[491.37,-58.6],[488.02,-55.78],[484.77,-53.02],[481.66,-50.31],[478.71,-47.65],[475.94,-45.04],[473.37,-42.48],[471.03,-39.95],[468.91,-37.46],[467.06,-35.0]],[[470.17,-35.0],[468.55,-32.54],[467.21,-30.1],[466.15,-27.66],[465.37,-25.24],[464.89,-22.8],[464.69,-20.36],[464.78,-17.91],[465.14,-15.43],[465.78,-12.92],[466.68,-10.39],[467.83,-7.81],[469.21,-5.19],[470.8,-2.52],[472.59,0.2],[474.55,2.98],[476.65,5.81],[478.88,8.7],[481.22,11.64],[483.62,14.65],[486.06,17.71],[488.53,20.83],[490.98,24.0],[493.39,27.23],[495.74,30.5],[497.99,33.81],[500.12,37.16],[502.1,40.55],[503.92,43.96],[505.54,47.39],[506.95,50.83],[508.12,54.28],[509.05,57.73],[509.71,61.17],[510.1,64.6],[510.19,68.0],[509.99,71.36],[509.48,74.7],[508.67,77.98],[507.54,81.22],[506.11,84.4],[504.38,87.51],[502.34,90.57],[500.01,93.55],[497.4,96.45],[494.51,99.28],[491.36,102.03],[487.97,104.7],[484.35,107.3],[480.51,109.81],[476.48,112.25],[472.27,114.61],[467.9,116.9],[463.38,119.12],[458.75,121.28],[454.01,123.38],[449.19,125.43],[444.31,127.43],[439.37,129.39],[434.41,131.32],[429.42,133.23],[424.44,135.11],[419.47,136.99],[414.51,138.87],[409.6,140.76],[404.72,142.65],[399.89,144.57],[395.11,146.52],[390.39,148.49],[385.73,150.51],[381.13,152.57],[376.58,154.68],[372.09,156.84],[367.64,159.06],[363.24,161.33],[358.88,163.66],[354.54,166.04],[350.22,168.48],[345.91,170.97],[341.6,173.5],[337.27,176.08],[332.91,178.7],[328.52,181.35],[324.08,184.02],[319.57,186.71],[314.99,189.4],[310.33,192.09],[305.57,194.76],[300.71,197.41],[295.73,200.02],[290.63,202.57],[285.4,205.07],[280.04,207.48],[274.54,209.81],[268.91,212.04],[263.13,214.15],[257.21,216.13],[251.16,217.98],[244.97,219.67],[238.64,221.21],[232.2,222.57],[225.64,223.76],[218.97,224.76],[212.21,225.56],[205.36,226.17],[198.43,226.57],[191.44,226.76],[184.41,226.74],[177.34,226.52],[170.25,226.08],[163.16,225.43],[156.08,224.58],[149.02,223.53],[142.0,222.29],[135.03,220.86],[128.13,219.25],[121.3,217.47],[114.57,215.53],[107.93,213.44],[101.41,211.22],[95.0,208.88],[88.72,206.44],[82.56,203.89],[76.55,201.27],[70.66,198.59],[64.92,195.86],[59.31,193.1],[53.84,190.32],[48.5,187.54],[43.29,184.77],[38.2,182.03],[33.22,179.33],[28.35,176.68],[23.57,174.1],[18.88,171.6],[14.26,169.18],[9.7,166.86],[5.19,164.64],[0.72,162.54],[-3.73,160.55],[-8.17,158.68],[-12.61,156.94],[-17.07,155.32],[-21.56,153.83],[-26.09,152.46],[-30.67,151.22],[-35.3,150.1],[-40.01,149.09],[-44.79,148.19],[-49.66,147.39],[-54.61,146.69],[-59.66,146.08],[-64.8,145.54],[-70.03,145.07],[-75.35,144.66],[-80.77,144.29],[-86.27,143.96],[-91.85,143.65],[-97.5,143.35],[-103.22,143.05],[-108.99,142.73],[-114.81,142.4],[-120.66,142.03],[-126.53,141.62],[-132.41,141.15],[-138.28,140.62],[-144.12,140.02],[-149.93,139.33],[-155.68,138.56],[-161.37,137.7],[-166.97,136.74],[-172.48,135.68],[-177.88,134.51],[-183.15,133.23],[-188.29,131.85],[-193.29,130.36],[-198.13,128.76],[-202.8,127.06],[-207.31,125.25],[-211.65,123.35],[-215.81,121.35],[-219.79,119.26],[-223.59,117.08],[-227.22,114.83],[-230.67,112.51],[-233.96,110.12],[-237.1,107.68],[-240.08,105.19],[-242.93,102.65],[-245.65,100.09],[-248.27,97.5],[-250.78,94.89],[-253.22,92.27],[-255.6,89.64],[-257.94,87.02],[-260.25,84.41],[-262.56,81.81],[-264.89,79.22],[-267.24,76.66],[-269.66,74.13],[-272.14,71.63],[-274.71,69.15],[-277.4,66.71],[-280.2,64.3],[-283.15,61.92],[-286.24,59.57],[-289.5,57.25],[-292.93,54.96],[-296.55,52.69],[-300.34,50.44],[-304.33,48.21],[-308.51,45.98],[-312.88,43.76],[-317.43,41.54],[-322.17,39.31],[-327.07,37.07],[-332.14,34.81],[-337.35,32.53],[-342.7,30.22],[-348.16,27.87],[-353.71,25.48],[-359.34,23.04],[-365.02,20.55],[-370.72,18.01],[-376.42,15.41],[-382.09,12.74],[-387.71,10.0],[-393.24,7.2],[-398.66,4.33],[-403.93,1.39],[-409.04,-1.62],[-413.94,-4.7],[-418.6,-7.85],[-423.02,-11.06],[-427.14,-14.33],[-430.96,-17.66],[-434.45,-21.04],[-437.58,-24.47],[-440.34,-27.95],[-442.7,-31.46],[-444.66,-35.0],[-446.2,-38.56],[-447.31,-42.14],[-447.98,-45.73],[-448.21,-49.32],[-447.99,-52.9],[-447.33,-56.47],[-446.22,-60.02],[-444.68,-63.53],[-442.71,-67.01],[-440.32,-70.45],[-437.54,-73.84],[-434.36,-77.18],[-430.82,-80.45],[-426.93,-83.66],[-422.71,-86.8],[-418.19,-89.87],[-413.39,-92.87],[-408.34,-95.79],[-403.07,-98.63],[-397.6,-101.4],[-391.96,-104.08],[-386.18,-106.7],[-380.29,-109.24],[-374.32,-111.71],[-368.3,-114.11],[-362.24,-116.45],[-356.19,-118.73],[-350.15,-120.96],[-344.17,-123.14],[-338.25,-125.27],[-332.42,-127.37],[-326.69,-129.44],[-321.09,-131.49],[-315.62,-133.52],[-310.3,-135.54],[-305.13,-137.56],[-300.14,-139.58],[-295.3,-141.6],[-290.64,-143.64],[-286.16,-145.7],[-281.84,-147.78],[-277.69,-149.88],[-273.69,-152.02],[-269.85,-154.19],[-266.15,-156.39],[-262.58,-158.62],[-259.12,-160.89],[-255.77,-163.2],[-252.5,-165.53],[-249.31,-167.9],[-246.17,-170.29],[-243.06,-172.71],[-239.98,-175.14],[-236.89,-177.59],[-233.79,-180.05],[-230.66,-182.5],[-227.47,-184.95],[-224.22,-187.38],[-220.89,-189.8],[-217.46,-192.18],[-213.92,-194.52],[-210.26,-196.82],[-206.48,-199.06],[-202.55,-201.23],[-198.47,-203.34],[-194.25,-205.36],[-189.87,-207.3],[-185.33,-209.14],[-180.64,-210.88],[-175.79,-212.52],[-170.79,-214.05],[-165.64,-215.46],[-160.35,-216.75],[-154.93,-217.92],[-149.38,-218.98],[-143.71,-219.91],[-137.95,-220.72],[-132.09,-221.41],[-126.15,-221.99],[-120.15,-222.45],[-114.09,-222.81],[-108.0,-223.07],[-101.88,-223.24],[-95.75,-223.32],[-89.63,-223.33],[-83.52,-223.27],[-77.43,-223.15],[-71.39,-222.99],[-65.4,-222.8],[-59.46,-222.58],[-53.6,-222.36],[-47.81,-222.14],[-42.1,-221.93],[-36.47,-221.76],[-30.93,-221.62],[-25.49,-221.54],[-20.13,-221.51],[-14.86,-221.57],[-9.68,-221.7],[-4.58,-221.94],[0.45,-222.27],[5.41,-222.72],[10.31,-223.28],[15.15,-223.97],[19.96,-224.78],[24.73,-225.72],[29.48,-226.8],[34.23,-228.01],[38.98,-229.35],[43.75,-230.82],[48.55,-232.42],[53.39,-234.14],[58.29,-235.97],[63.25,-237.91],[68.29,-239.96],[73.42,-242.09],[78.65,-244.31],[83.99,-246.59],[89.43,-248.93],[95.0,-251.31],[100.69,-253.71],[106.51,-256.14],[112.46,-258.56],[118.54,-260.97],[124.75,-263.34],[131.09,-265.67],[137.55,-267.94],[144.13,-270.13],[150.82,-272.23],[157.61,-274.22],[164.49,-276.1],[171.46,-277.84],[178.5,-279.44],[185.6,-280.89],[192.74,-282.17],[199.91,-283.27],[207.1,-284.2],[214.29,-284.94],[221.46,-285.48],[228.61,-285.83],[235.71,-285.97],[242.75,-285.92],[249.73,-285.66],[256.61,-285.2],[263.4,-284.54],[270.07,-283.69],[276.63,-282.66],[283.05,-281.43],[289.34,-280.03],[295.48,-278.47],[301.47,-276.74],[307.3,-274.86],[312.98,-272.85],[318.49,-270.7],[323.85,-268.44],[329.06,-266.07],[334.11,-263.62],[339.02,-261.08],[343.79,-258.47],[348.42,-255.8],[352.94,-253.09],[357.34,-250.34],[361.64,-247.58],[365.85,-244.8],[369.98,-242.01],[374.05,-239.24],[378.06,-236.48],[382.04,-233.74],[386.0,-231.03],[389.94,-228.35],[393.89,-225.72],[397.85,-223.13],[401.83,-220.58],[405.85,-218.08],[409.91,-215.63],[414.02,-213.23],[418.18,-210.87],[422.42,-208.56],[426.71,-206.29],[431.08,-204.06],[435.51,-201.86],[440.01,-199.69],[444.57,-197.55],[449.18,-195.42],[453.84,-193.3],[458.55,-191.19],[463.28,-189.08],[468.03,-186.95],[472.78,-184.81],[477.52,-182.65],[482.23,-180.46],[486.89,-178.23],[491.49,-175.95],[496.0,-173.63],[500.4,-171.26],[504.68,-168.83],[508.81,-166.34],[512.78,-163.78],[516.56,-161.16],[520.13,-158.47],[523.47,-155.71],[526.57,-152.87],[529.41,-149.97],[531.98,-147.0],[534.25,-143.96],[536.21,-140.86],[537.87,-137.7],[539.2,-134.48],[540.2,-131.22],[540.86,-127.9],[541.19,-124.55],[541.19,-121.16],[540.85,-117.74],[540.19,-114.3],[539.21,-110.85],[537.92,-107.39],[536.33,-103.93],[534.46,-100.48],[532.33,-97.04],[529.95,-93.63],[527.35,-90.23],[524.54,-86.87],[521.56,-83.55],[518.42,-80.27],[515.16,-77.04],[511.8,-73.86],[508.38,-70.73],[504.91,-67.66],[501.43,-64.64],[497.97,-61.69],[494.56,-58.79],[491.22,-55.95],[487.98,-53.16],[484.87,-50.43],[481.91,-47.76],[479.13,-45.13],[476.55,-42.54],[474.18,-39.99],[472.05,-37.48],[470.17,-35.0]],[[473.47,-35.0],[471.83,-32.52],[470.47,-30.05],[469.39,-27.6],[468.6,-25.15],[468.09,-22.7],[467.89,-20.24],[467.97,-17.76],[468.33,-15.26],[468.97,-12.73],[469.88,-10.17],[471.05,-7.57],[472.45,-4.93],[474.07,-2.23],[475.89,0.51],[477.9,3.31],[480.06,6.17],[482.36,9.09],[484.76,12.07],[487.24,15.11],[489.78,18.21],[492.34,21.37],[494.9,24.59],[497.42,27.86],[499.88,31.18],[502.26,34.54],[504.51,37.95],[506.63,41.39],[508.58,44.86],[510.34,48.35],[511.89,51.86],[513.21,55.38],[514.28,58.9],[515.08,62.42],[515.6,65.91],[515.82,69.39],[515.75,72.84],[515.36,76.25],[514.66,79.62],[513.64,82.94],[512.31,86.2],[510.66,89.4],[508.7,92.53],[506.44,95.59],[503.88,98.57],[501.04,101.47],[497.92,104.3],[494.54,107.04],[490.93,109.7],[487.08,112.28],[483.02,114.77],[478.77,117.19],[474.35,119.53],[469.77,121.79],[465.06,123.99],[460.24,126.12],[455.32,128.2],[450.32,130.22],[445.26,132.2],[440.16,134.14],[435.03,136.05],[429.89,137.93],[424.76,139.8],[419.64,141.66],[414.55,143.52],[409.5,145.39],[404.49,147.28],[399.52,149.19],[394.62,151.12],[389.77,153.09],[384.98,155.1],[380.25,157.15],[375.57,159.26],[370.95,161.41],[366.37,163.62],[361.83,165.88],[357.32,168.2],[352.84,170.57],[348.37,172.99],[343.91,175.46],[339.44,177.97],[334.94,180.52],[330.42,183.11],[325.86,185.72],[321.23,188.35],[316.55,190.99],[311.78,193.62],[306.93,196.25],[301.98,198.85],[296.92,201.42],[291.75,203.94],[286.46,206.4],[281.04,208.79],[275.48,211.09],[269.79,213.3],[263.97,215.39],[258.01,217.37],[251.92,219.21],[245.69,220.9],[239.34,222.44],[232.86,223.81],[226.27,225.0],[219.57,226.01],[212.78,226.83],[205.9,227.45],[198.95,227.87],[191.93,228.08],[184.87,228.08],[177.77,227.87],[170.65,227.45],[163.52,226.82],[156.41,225.99],[149.32,224.96],[142.26,223.72],[135.26,222.3],[128.32,220.7],[121.46,218.93],[114.68,216.99],[108.01,214.91],[101.45,212.68],[95.0,210.33],[88.68,207.87],[82.49,205.32],[76.44,202.68],[70.52,199.97],[64.74,197.22],[59.11,194.43],[53.61,191.61],[48.24,188.8],[43.0,185.99],[37.89,183.21],[32.9,180.46],[28.01,177.77],[23.22,175.14],[18.52,172.59],[13.89,170.12],[9.33,167.75],[4.81,165.49],[0.34,163.34],[-4.11,161.3],[-8.55,159.39],[-12.99,157.61],[-17.44,155.95],[-21.93,154.43],[-26.45,153.03],[-31.03,151.76],[-35.67,150.61],[-40.37,149.59],[-45.16,148.67],[-50.04,147.87],[-55.0,147.17],[-60.06,146.56],[-65.23,146.03],[-70.49,145.57],[-75.85,145.18],[-81.3,144.84],[-86.85,144.54],[-92.49,144.26],[-98.21,144.01],[-104.01,143.75],[-109.87,143.49],[-115.78,143.22],[-121.73,142.91],[-127.71,142.56],[-133.71,142.16],[-139.71,141.7],[-145.69,141.17],[-151.65,140.56],[-157.56,139.86],[-163.41,139.08],[-169.19,138.19],[-174.87,137.2],[-180.46,136.11],[-185.92,134.91],[-191.25,133.6],[-196.45,132.17],[-201.49,130.64],[-206.37,129.0],[-211.08,127.25],[-215.62,125.4],[-219.98,123.44],[-224.16,121.4],[-228.16,119.26],[-231.97,117.04],[-235.62,114.75],[-239.09,112.38],[-242.39,109.95],[-245.54,107.47],[-248.55,104.94],[-251.42,102.37],[-254.17,99.77],[-256.81,97.15],[-259.37,94.51],[-261.85,91.86],[-264.28,89.21],[-266.67,86.56],[-269.04,83.92],[-271.42,81.3],[-273.82,78.69],[-276.26,76.11],[-278.76,73.55],[-281.34,71.02],[-284.02,68.52],[-286.81,66.05],[-289.72,63.61],[-292.78,61.2],[-296.0,58.81],[-299.38,56.46],[-302.93,54.12],[-306.66,51.81],[-310.58,49.51],[-314.68,47.22],[-318.97,44.94],[-323.44,42.65],[-328.09,40.37],[-332.91,38.07],[-337.89,35.75],[-343.02,33.42],[-348.29,31.05],[-353.67,28.65],[-359.15,26.21],[-364.7,23.73],[-370.31,21.19],[-375.95,18.61],[-381.6,15.96],[-387.22,13.25],[-392.8,10.48],[-398.29,7.64],[-403.68,4.73],[-408.93,1.75],[-414.01,-1.29],[-418.9,-4.4],[-423.56,-7.58],[-427.97,-10.83],[-432.1,-14.13],[-435.93,-17.5],[-439.42,-20.91],[-442.57,-24.38],[-445.34,-27.88],[-447.72,-31.43],[-449.7,-35.0],[-451.26,-38.6],[-452.38,-42.21],[-453.07,-45.83],[-453.31,-49.45],[-453.1,-53.07],[-452.44,-56.67],[-451.33,-60.25],[-449.78,-63.8],[-447.79,-67.32],[-445.39,-70.79],[-442.57,-74.21],[-439.35,-77.57],[-435.76,-80.88],[-431.81,-84.12],[-427.53,-87.28],[-422.93,-90.38],[-418.05,-93.4],[-412.9,-96.34],[-407.52,-99.2],[-401.93,-101.98],[-396.17,-104.68],[-390.26,-107.31],[-384.22,-109.85],[-378.1,-112.33],[-371.92,-114.73],[-365.7,-117.07],[-359.47,-119.34],[-353.27,-121.56],[-347.1,-123.72],[-341.0,-125.85],[-334.99,-127.93],[-329.08,-129.98],[-323.29,-132.0],[-317.64,-134.01],[-312.14,-136.0],[-306.8,-137.98],[-301.63,-139.97],[-296.63,-141.96],[-291.82,-143.97],[-287.18,-145.99],[-282.71,-148.04],[-278.43,-150.11],[-274.31,-152.21],[-270.35,-154.35],[-266.55,-156.52],[-262.89,-158.73],[-259.35,-160.97],[-255.93,-163.26],[-252.61,-165.57],[-249.38,-167.93],[-246.21,-170.31],[-243.08,-172.72],[-239.99,-175.15],[-236.92,-177.6],[-233.84,-180.06],[-230.73,-182.53],[-227.59,-185.0],[-224.38,-187.46],[-221.11,-189.9],[-217.75,-192.32],[-214.28,-194.71],[-210.71,-197.05],[-207.0,-199.34],[-203.17,-201.58],[-199.19,-203.75],[-195.06,-205.84],[-190.78,-207.85],[-186.35,-209.77],[-181.76,-211.6],[-177.01,-213.32],[-172.11,-214.93],[-167.05,-216.44],[-161.86,-217.82],[-156.52,-219.09],[-151.05,-220.24],[-145.47,-221.27],[-139.77,-222.17],[-133.98,-222.96],[-128.1,-223.64],[-122.15,-224.19],[-116.13,-224.65],[-110.08,-225.0],[-103.98,-225.25],[-97.87,-225.42],[-91.76,-225.5],[-85.65,-225.52],[-79.56,-225.47],[-73.51,-225.38],[-67.49,-225.25],[-61.53,-225.09],[-55.63,-224.92],[-49.8,-224.75],[-44.04,-224.59],[-38.36,-224.45],[-32.77,-224.34],[-27.26,-224.28],[-21.84,-224.28],[-16.5,-224.36],[-11.25,-224.51],[-6.07,-224.75],[-0.97,-225.09],[4.06,-225.54],[9.04,-226.1],[13.96,-226.78],[18.84,-227.59],[23.7,-228.53],[28.53,-229.59],[33.35,-230.79],[38.18,-232.12],[43.03,-233.58],[47.9,-235.17],[52.82,-236.88],[57.79,-238.71],[62.83,-240.65],[67.94,-242.68],[73.14,-244.82],[78.44,-247.03],[83.84,-249.31],[89.36,-251.66],[95.0,-254.05],[100.76,-256.47],[106.66,-258.9],[112.68,-261.34],[118.83,-263.77],[125.12,-266.17],[131.54,-268.52],[138.08,-270.82],[144.74,-273.04],[151.51,-275.17],[158.39,-277.2],[165.36,-279.11],[172.42,-280.9],[179.56,-282.53],[186.75,-284.02],[193.99,-285.34],[201.26,-286.48],[208.55,-287.44],[215.85,-288.21],[223.13,-288.79],[230.39,-289.17],[237.6,-289.34],[244.75,-289.31],[251.83,-289.07],[258.82,-288.62],[265.71,-287.98],[272.49,-287.13],[279.15,-286.09],[285.67,-284.86],[292.05,-283.45],[298.28,-281.87],[304.35,-280.11],[310.26,-278.21],[316.01,-276.15],[321.59,-273.96],[327.0,-271.65],[332.25,-269.23],[337.35,-266.71],[342.28,-264.1],[347.07,-261.42],[351.72,-258.67],[356.23,-255.88],[360.62,-253.04],[364.9,-250.18],[369.08,-247.3],[373.17,-244.42],[377.19,-241.54],[381.15,-238.67],[385.06,-235.83],[388.94,-233.01],[392.8,-230.23],[396.65,-227.48],[400.51,-224.78],[404.39,-222.13],[408.29,-219.52],[412.24,-216.97],[416.23,-214.46],[420.28,-212.01],[424.39,-209.6],[428.56,-207.24],[432.8,-204.92],[437.11,-202.64],[441.49,-200.4],[445.93,-198.18],[450.43,-195.98],[454.99,-193.81],[459.59,-191.64],[464.23,-189.47],[468.89,-187.3],[473.56,-185.12],[478.23,-182.92],[482.88,-180.7],[487.49,-178.44],[492.05,-176.15],[496.53,-173.82],[500.92,-171.43],[505.19,-169.0],[509.33,-166.5],[513.31,-163.95],[517.12,-161.33],[520.73,-158.64],[524.12,-155.89],[527.28,-153.07],[530.18,-150.17],[532.82,-147.22],[535.18,-144.19],[537.24,-141.11],[538.99,-137.96],[540.43,-134.76],[541.54,-131.51],[542.32,-128.2],[542.77,-124.86],[542.88,-121.48],[542.67,-118.08],[542.13,-114.65],[541.26,-111.2],[540.09,-107.75],[538.62,-104.29],[536.86,-100.84],[534.84,-97.4],[532.56,-93.98],[530.06,-90.58],[527.35,-87.21],[524.45,-83.88],[521.39,-80.59],[518.2,-77.35],[514.91,-74.15],[511.54,-71.0],[508.12,-67.91],[504.69,-64.88],[501.26,-61.9],[497.87,-58.99],[494.55,-56.12],[491.32,-53.32],[488.22,-50.57],[485.26,-47.87],[482.48,-45.21],[479.89,-42.61],[477.51,-40.04],[475.36,-37.5],[473.47,-35.0]],[[476.94,-35.0],[475.29,-32.5],[473.91,-30.01],[472.82,-27.53],[472.01,-25.06],[471.5,-22.59],[471.28,-20.1],[471.35,-17.6],[471.71,-15.08],[472.35,-12.53],[473.27,-9.95],[474.44,-7.33],[475.86,-4.66],[477.51,-1.94],[479.37,0.84],[481.41,3.66],[483.63,6.55],[485.98,9.5],[488.45,12.52],[491.01,15.59],[493.62,18.73],[496.27,21.93],[498.93,25.19],[501.55,28.5],[504.13,31.87],[506.62,35.29],[509.0,38.75],[511.24,42.25],[513.33,45.78],[515.22,49.33],[516.9,52.91],[518.35,56.49],[519.56,60.08],[520.49,63.67],[521.14,67.24],[521.49,70.8],[521.54,74.33],[521.27,77.82],[520.68,81.26],[519.77,84.66],[518.53,88.0],[516.97,91.28],[515.09,94.49],[512.89,97.63],[510.38,100.69],[507.58,103.67],[504.49,106.57],[501.13,109.38],[497.52,112.11],[493.66,114.75],[489.58,117.3],[485.29,119.77],[480.82,122.16],[476.18,124.47],[471.39,126.71],[466.47,128.87],[461.45,130.98],[456.33,133.02],[451.15,135.01],[445.91,136.96],[440.64,138.87],[435.35,140.75],[430.06,142.61],[424.77,144.45],[419.5,146.29],[414.27,148.13],[409.08,149.98],[403.93,151.85],[398.83,153.74],[393.8,155.66],[388.82,157.61],[383.9,159.61],[379.03,161.65],[374.22,163.74],[369.46,165.88],[364.75,168.08],[360.07,170.32],[355.42,172.62],[350.79,174.97],[346.17,177.37],[341.56,179.82],[336.92,182.3],[332.27,184.82],[327.58,187.37],[322.84,189.93],[318.04,192.51],[313.18,195.09],[308.23,197.67],[303.19,200.22],[298.05,202.74],[292.81,205.22],[287.45,207.65],[281.97,210.01],[276.36,212.29],[270.62,214.47],[264.75,216.55],[258.75,218.51],[252.62,220.35],[246.36,222.04],[239.97,223.57],[233.47,224.95],[226.85,226.15],[220.13,227.17],[213.31,228.0],[206.4,228.64],[199.42,229.07],[192.38,229.3],[185.29,229.33],[178.17,229.14],[171.02,228.74],[163.87,228.13],[156.72,227.32],[149.6,226.3],[142.51,225.09],[135.47,223.68],[128.5,222.09],[121.6,220.33],[114.79,218.4],[108.08,216.32],[101.48,214.1],[95.0,211.75],[88.64,209.28],[82.42,206.71],[76.33,204.06],[70.38,201.34],[64.57,198.56],[58.9,195.74],[53.37,192.9],[47.98,190.05],[42.72,187.21],[37.58,184.39],[32.57,181.61],[27.66,178.87],[22.86,176.2],[18.14,173.6],[13.5,171.09],[8.93,168.68],[4.42,166.37],[-0.06,164.17],[-4.51,162.1],[-8.95,160.15],[-13.39,158.32],[-17.84,156.63],[-22.32,155.07],[-26.85,153.64],[-31.42,152.34],[-36.06,151.18],[-40.78,150.13],[-45.57,149.21],[-50.45,148.4],[-55.43,147.69],[-60.52,147.08],[-65.7,146.56],[-70.99,146.12],[-76.39,145.75],[-81.89,145.43],[-87.49,145.16],[-93.19,144.93],[-98.97,144.71],[-104.85,144.51],[-110.79,144.3],[-116.79,144.08],[-122.85,143.83],[-128.95,143.54],[-135.07,143.21],[-141.2,142.82],[-147.32,142.36],[-153.42,141.82],[-159.49,141.2],[-165.51,140.49],[-171.46,139.68],[-177.32,138.77],[-183.09,137.75],[-188.75,136.62],[-194.28,135.38],[-199.67,134.02],[-204.91,132.55],[-210.0,130.97],[-214.91,129.28],[-219.66,127.48],[-224.22,125.58],[-228.6,123.58],[-232.8,121.48],[-236.81,119.29],[-240.65,117.02],[-244.3,114.68],[-247.78,112.27],[-251.1,109.8],[-254.26,107.27],[-257.28,104.7],[-260.17,102.09],[-262.94,99.45],[-265.61,96.79],[-268.2,94.12],[-270.72,91.44],[-273.19,88.75],[-275.63,86.08],[-278.07,83.41],[-280.51,80.75],[-282.98,78.12],[-285.49,75.5],[-288.08,72.92],[-290.75,70.36],[-293.52,67.82],[-296.4,65.32],[-299.42,62.84],[-302.59,60.39],[-305.91,57.97],[-309.39,55.57],[-313.05,53.19],[-316.89,50.82],[-320.91,48.47],[-325.11,46.12],[-329.49,43.78],[-334.05,41.43],[-338.78,39.07],[-343.67,36.7],[-348.7,34.3],[-353.88,31.88],[-359.17,29.43],[-364.56,26.94],[-370.04,24.41],[-375.57,21.83],[-381.14,19.2],[-386.72,16.51],[-392.28,13.76],[-397.8,10.94],[-403.25,8.07],[-408.6,5.12],[-413.81,2.11],[-418.87,-0.97],[-423.73,-4.12],[-428.38,-7.33],[-432.78,-10.61],[-436.9,-13.94],[-440.73,-17.34],[-444.23,-20.78],[-447.38,-24.28],[-450.17,-27.82],[-452.56,-31.39],[-454.56,-35.0],[-456.13,-38.63],[-457.27,-42.27],[-457.96,-45.93],[-458.21,-49.58],[-458.01,-53.23],[-457.35,-56.87],[-456.24,-60.48],[-454.69,-64.06],[-452.69,-67.61],[-450.27,-71.11],[-447.42,-74.56],[-444.17,-77.96],[-440.54,-81.29],[-436.53,-84.56],[-432.19,-87.75],[-427.52,-90.87],[-422.55,-93.91],[-417.31,-96.87],[-411.83,-99.75],[-406.14,-102.55],[-400.25,-105.26],[-394.21,-107.89],[-388.05,-110.45],[-381.78,-112.93],[-375.45,-115.33],[-369.07,-117.67],[-362.68,-119.94],[-356.3,-122.14],[-349.97,-124.3],[-343.69,-126.41],[-337.5,-128.47],[-331.41,-130.5],[-325.45,-132.5],[-319.62,-134.48],[-313.94,-136.45],[-308.43,-138.4],[-303.09,-140.36],[-297.93,-142.32],[-292.96,-144.29],[-288.17,-146.28],[-283.57,-148.29],[-279.15,-150.33],[-274.91,-152.4],[-270.84,-154.51],[-266.93,-156.65],[-263.18,-158.83],[-259.57,-161.05],[-256.08,-163.31],[-252.71,-165.61],[-249.43,-167.95],[-246.23,-170.32],[-243.09,-172.72],[-240.0,-175.15],[-236.93,-177.61],[-233.87,-180.08],[-230.79,-182.56],[-227.69,-185.05],[-224.54,-187.53],[-221.32,-190.01],[-218.03,-192.46],[-214.64,-194.89],[-211.15,-197.28],[-207.53,-199.63],[-203.79,-201.93],[-199.91,-204.16],[-195.89,-206.32],[-191.71,-208.41],[-187.38,-210.41],[-182.89,-212.32],[-178.24,-214.13],[-173.44,-215.83],[-168.49,-217.43],[-163.39,-218.91],[-158.14,-220.28],[-152.77,-221.53],[-147.26,-222.65],[-141.64,-223.66],[-135.91,-224.55],[-130.09,-225.32],[-124.19,-225.98],[-118.23,-226.53],[-112.21,-226.97],[-106.14,-227.31],[-100.05,-227.57],[-93.95,-227.74],[-87.84,-227.83],[-81.75,-227.86],[-75.68,-227.84],[-69.65,-227.78],[-63.66,-227.68],[-57.73,-227.57],[-51.85,-227.44],[-46.05,-227.32],[-40.32,-227.22],[-34.67,-227.15],[-29.1,-227.12],[-23.61,-227.15],[-18.2,-227.24],[-12.87,-227.41],[-7.62,-227.66],[-2.44,-228.0],[2.67,-228.45],[7.73,-229.02],[12.73,-229.69],[17.7,-230.49],[22.63,-231.42],[27.54,-232.48],[32.45,-233.67],[37.36,-234.98],[42.28,-236.43],[47.23,-238.01],[52.23,-239.7],[57.28,-241.52],[62.39,-243.45],[67.58,-245.48],[72.85,-247.6],[78.22,-249.81],[83.7,-252.09],[89.29,-254.44],[95.0,-256.83],[100.84,-259.25],[106.8,-261.7],[112.9,-264.15],[119.13,-266.59],[125.49,-269.01],[131.98,-271.39],[138.6,-273.71],[145.35,-275.95],[152.2,-278.12],[159.17,-280.17],[166.23,-282.12],[173.38,-283.93],[180.6,-285.6],[187.89,-287.12],[195.23,-288.48],[202.6,-289.65],[210.0,-290.65],[217.4,-291.45],[224.78,-292.06],[232.14,-292.46],[239.46,-292.66],[246.72,-292.65],[253.9,-292.43],[261.0,-292.0],[268.0,-291.36],[274.88,-290.52],[281.63,-289.48],[288.25,-288.24],[294.72,-286.82],[301.04,-285.21],[307.19,-283.44],[313.18,-281.5],[318.99,-279.41],[324.63,-277.18],[330.1,-274.82],[335.4,-272.34],[340.53,-269.75],[345.5,-267.08],[350.31,-264.32],[354.96,-261.5],[359.48,-258.62],[363.86,-255.7],[368.12,-252.74],[372.27,-249.77],[376.32,-246.79],[380.29,-243.81],[384.19,-240.83],[388.03,-237.88],[391.83,-234.96],[395.6,-232.06],[399.36,-229.21],[403.12,-226.4],[406.89,-223.64],[410.68,-220.93],[414.51,-218.27],[418.38,-215.66],[422.31,-213.11],[426.29,-210.61],[430.33,-208.16],[434.45,-205.75],[438.63,-203.39],[442.89,-201.07],[447.21,-198.78],[451.59,-196.51],[456.04,-194.27],[460.54,-192.05],[465.08,-189.83],[469.65,-187.61],[474.24,-185.39],[478.84,-183.16],[483.43,-180.9],[487.99,-178.63],[492.5,-176.31],[496.95,-173.96],[501.32,-171.57],[505.59,-169.13],[509.73,-166.63],[513.73,-164.08],[517.56,-161.46],[521.21,-158.78],[524.65,-156.04],[527.87,-153.23],[530.85,-150.35],[533.57,-147.41],[536.01,-144.4],[538.17,-141.33],[540.03,-138.2],[541.57,-135.02],[542.8,-131.78],[543.7,-128.49],[544.28,-125.16],[544.52,-121.8],[544.43,-118.4],[544.02,-114.98],[543.29,-111.55],[542.24,-108.1],[540.9,-104.65],[539.26,-101.2],[537.36,-97.76],[535.2,-94.33],[532.8,-90.93],[530.19,-87.56],[527.39,-84.22],[524.42,-80.92],[521.32,-77.66],[518.1,-74.45],[514.8,-71.29],[511.44,-68.18],[508.05,-65.13],[504.67,-62.13],[501.31,-59.19],[498.02,-56.31],[494.81,-53.48],[491.72,-50.71],[488.78,-47.98],[485.99,-45.31],[483.4,-42.68],[481.01,-40.08],[478.86,-37.53],[476.94,-35.0]],[[480.61,-35.0],[478.95,-32.47],[477.56,-29.96],[476.45,-27.46],[475.62,-24.97],[475.09,-22.47],[474.86,-19.96],[474.92,-17.44],[475.28,-14.89],[475.92,-12.32],[476.84,-9.71],[478.02,-7.06],[479.45,-4.37],[481.12,-1.62],[483.01,1.17],[485.09,4.03],[487.35,6.95],[489.75,9.93],[492.28,12.98],[494.9,16.09],[497.6,19.26],[500.33,22.5],[503.07,25.8],[505.8,29.16],[508.48,32.58],[511.08,36.05],[513.57,39.56],[515.94,43.12],[518.14,46.71],[520.16,50.33],[521.97,53.96],[523.55,57.62],[524.89,61.28],[525.95,64.94],[526.72,68.58],[527.2,72.21],[527.37,75.82],[527.21,79.39],[526.73,82.92],[525.92,86.39],[524.77,89.82],[523.29,93.18],[521.48,96.47],[519.35,99.68],[516.89,102.82],[514.13,105.88],[511.07,108.85],[507.73,111.73],[504.11,114.52],[500.24,117.22],[496.14,119.83],[491.81,122.36],[487.29,124.8],[482.58,127.15],[477.71,129.42],[472.71,131.62],[467.58,133.75],[462.35,135.82],[457.04,137.82],[451.67,139.78],[446.25,141.69],[440.8,143.56],[435.35,145.41],[429.89,147.24],[424.45,149.05],[419.03,150.86],[413.65,152.68],[408.32,154.5],[403.03,156.35],[397.8,158.22],[392.63,160.12],[387.52,162.05],[382.47,164.03],[377.47,166.05],[372.53,168.13],[367.63,170.25],[362.78,172.42],[357.96,174.65],[353.17,176.92],[348.39,179.25],[343.62,181.62],[338.85,184.03],[334.06,186.48],[329.24,188.96],[324.39,191.46],[319.48,193.98],[314.51,196.5],[309.47,199.02],[304.34,201.52],[299.12,203.99],[293.8,206.43],[288.38,208.82],[282.83,211.14],[277.17,213.39],[271.38,215.56],[265.47,217.62],[259.43,219.57],[253.26,221.39],[246.97,223.08],[240.55,224.61],[234.02,225.99],[227.38,227.2],[220.63,228.23],[213.79,229.08],[206.86,229.73],[199.86,230.19],[192.8,230.44],[185.69,230.48],[178.54,230.31],[171.37,229.94],[164.19,229.36],[157.01,228.57],[149.86,227.57],[142.75,226.38],[135.68,224.99],[128.67,223.42],[121.74,221.67],[114.9,219.75],[108.15,217.68],[101.52,215.47],[95.0,213.12],[88.61,210.65],[82.35,208.08],[76.22,205.42],[70.24,202.68],[64.39,199.89],[58.69,197.05],[53.14,194.19],[47.71,191.31],[42.43,188.44],[37.27,185.59],[32.23,182.77],[27.31,180.0],[22.48,177.29],[17.76,174.65],[13.11,172.1],[8.53,169.64],[4.0,167.29],[-0.48,165.05],[-4.93,162.94],[-9.37,160.95],[-13.82,159.09],[-18.27,157.36],[-22.75,155.77],[-27.28,154.31],[-31.86,152.99],[-36.5,151.8],[-41.22,150.74],[-46.02,149.8],[-50.92,148.98],[-55.91,148.27],[-61.01,147.67],[-66.22,147.15],[-71.54,146.73],[-76.98,146.37],[-82.52,146.08],[-88.18,145.84],[-93.93,145.64],[-99.79,145.47],[-105.74,145.31],[-111.76,145.15],[-117.86,144.98],[-124.02,144.79],[-130.23,144.57],[-136.47,144.3],[-142.74,143.98],[-149.0,143.59],[-155.25,143.12],[-161.48,142.58],[-167.66,141.94],[-173.79,141.21],[-179.83,140.37],[-185.79,139.42],[-191.63,138.36],[-197.36,137.19],[-202.95,135.91],[-208.4,134.5],[-213.69,132.98],[-218.82,131.35],[-223.77,129.6],[-228.54,127.75],[-233.12,125.79],[-237.52,123.73],[-241.73,121.58],[-245.75,119.34],[-249.59,117.02],[-253.25,114.62],[-256.74,112.16],[-260.07,109.64],[-263.24,107.06],[-266.27,104.45],[-269.17,101.79],[-271.96,99.11],[-274.66,96.41],[-277.27,93.7],[-279.82,90.98],[-282.33,88.26],[-284.82,85.55],[-287.3,82.85],[-289.8,80.16],[-292.33,77.49],[-294.92,74.84],[-297.58,72.22],[-300.32,69.63],[-303.18,67.06],[-306.15,64.51],[-309.27,62.0],[-312.52,59.5],[-315.94,57.04],[-319.52,54.59],[-323.27,52.15],[-327.2,49.73],[-331.31,47.32],[-335.59,44.91],[-340.05,42.5],[-344.68,40.08],[-349.46,37.64],[-354.4,35.19],[-359.47,32.72],[-364.66,30.21],[-369.96,27.67],[-375.34,25.09],[-380.79,22.46],[-386.27,19.78],[-391.78,17.05],[-397.27,14.26],[-402.72,11.4],[-408.11,8.49],[-413.41,5.51],[-418.58,2.46],[-423.6,-0.66],[-428.43,-3.84],[-433.05,-7.08],[-437.43,-10.39],[-441.55,-13.76],[-445.37,-17.18],[-448.87,-20.66],[-452.02,-24.19],[-454.81,-27.76],[-457.22,-31.36],[-459.22,-35.0],[-460.8,-38.66],[-461.95,-42.34],[-462.66,-46.02],[-462.92,-49.71],[-462.73,-53.39],[-462.07,-57.05],[-460.97,-60.7],[-459.41,-64.31],[-457.4,-67.89],[-454.96,-71.42],[-452.09,-74.9],[-448.81,-78.33],[-445.13,-81.69],[-441.09,-84.98],[-436.68,-88.2],[-431.95,-91.34],[-426.91,-94.41],[-421.59,-97.39],[-416.01,-100.28],[-410.21,-103.1],[-404.22,-105.82],[-398.06,-108.47],[-391.76,-111.03],[-385.36,-113.51],[-378.88,-115.92],[-372.35,-118.25],[-365.81,-120.52],[-359.27,-122.72],[-352.76,-124.86],[-346.32,-126.95],[-339.96,-129.0],[-333.7,-131.01],[-327.56,-132.99],[-321.56,-134.95],[-315.71,-136.88],[-310.03,-138.81],[-304.53,-140.74],[-299.21,-142.67],[-294.08,-144.61],[-289.15,-146.57],[-284.41,-148.55],[-279.86,-150.55],[-275.5,-152.59],[-271.32,-154.66],[-267.31,-156.78],[-263.47,-158.93],[-259.78,-161.13],[-256.23,-163.36],[-252.8,-165.64],[-249.48,-167.97],[-246.25,-170.33],[-243.1,-172.72],[-240.0,-175.15],[-236.94,-177.61],[-233.9,-180.09],[-230.85,-182.59],[-227.79,-185.1],[-224.69,-187.61],[-221.54,-190.11],[-218.31,-192.61],[-215.0,-195.08],[-211.59,-197.52],[-208.07,-199.92],[-204.42,-202.28],[-200.64,-204.58],[-196.72,-206.82],[-192.65,-208.98],[-188.42,-211.06],[-184.04,-213.05],[-179.5,-214.95],[-174.81,-216.75],[-169.95,-218.44],[-164.95,-220.03],[-159.8,-221.49],[-154.51,-222.84],[-149.09,-224.07],[-143.55,-225.18],[-137.89,-226.17],[-132.14,-227.05],[-126.29,-227.81],[-120.37,-228.45],[-114.39,-228.99],[-108.36,-229.43],[-102.29,-229.78],[-96.2,-230.03],[-90.1,-230.21],[-84.01,-230.32],[-77.92,-230.37],[-71.87,-230.38],[-65.86,-230.35],[-59.89,-230.29],[-53.97,-230.22],[-48.12,-230.15],[-42.34,-230.09],[-36.63,-230.06],[-30.99,-230.06],[-25.44,-230.11],[-19.96,-230.22],[-14.55,-230.4],[-9.22,-230.66],[-3.96,-231.02],[1.23,-231.47],[6.37,-232.03],[11.46,-232.7],[16.51,-233.5],[21.53,-234.41],[26.53,-235.46],[31.51,-236.63],[36.51,-237.93],[41.51,-239.36],[46.55,-240.92],[51.62,-242.6],[56.75,-244.4],[61.94,-246.32],[67.2,-248.33],[72.55,-250.45],[78.0,-252.65],[83.55,-254.92],[89.22,-257.26],[95.0,-259.65],[100.91,-262.08],[106.95,-264.53],[113.12,-266.98],[119.42,-269.44],[125.86,-271.87],[132.43,-274.26],[139.13,-276.6],[145.95,-278.86],[152.89,-281.05],[159.94,-283.13],[167.09,-285.1],[174.33,-286.95],[181.64,-288.65],[189.03,-290.2],[196.46,-291.58],[203.93,-292.79],[211.42,-293.82],[218.92,-294.65],[226.41,-295.28],[233.87,-295.71],[241.29,-295.93],[248.66,-295.94],[255.94,-295.73],[263.15,-295.32],[270.24,-294.69],[277.22,-293.85],[284.07,-292.81],[290.79,-291.57],[297.35,-290.13],[303.75,-288.51],[309.98,-286.71],[316.04,-284.74],[321.93,-282.61],[327.63,-280.34],[333.15,-277.93],[338.5,-275.4],[343.67,-272.75],[348.66,-270.01],[353.49,-267.18],[358.15,-264.28],[362.67,-261.32],[367.04,-258.31],[371.28,-255.26],[375.4,-252.19],[379.41,-249.11],[383.33,-246.03],[387.17,-242.96],[390.94,-239.9],[394.66,-236.86],[398.35,-233.86],[402.01,-230.9],[405.67,-227.99],[409.33,-225.12],[413.01,-222.3],[416.72,-219.54],[420.47,-216.83],[424.27,-214.18],[428.12,-211.58],[432.04,-209.04],[436.03,-206.55],[440.08,-204.1],[444.21,-201.7],[448.41,-199.33],[452.68,-197.0],[457.01,-194.7],[461.4,-192.42],[465.84,-190.15],[470.32,-187.89],[474.83,-185.62],[479.35,-183.35],[483.87,-181.07],[488.38,-178.77],[492.85,-176.44],[497.27,-174.07],[501.62,-171.67],[505.88,-169.22],[510.03,-166.72],[514.04,-164.17],[517.9,-161.56],[521.59,-158.89],[525.08,-156.16],[528.37,-153.36],[531.42,-150.5],[534.22,-147.57],[536.76,-144.59],[539.01,-141.53],[540.98,-138.42],[542.64,-135.26],[543.99,-132.04],[545.02,-128.77],[545.72,-125.45],[546.1,-122.11],[546.15,-118.72],[545.87,-115.32],[545.28,-111.89],[544.37,-108.45],[543.16,-105.0],[541.66,-101.55],[539.89,-98.12],[537.85,-94.69],[535.57,-91.28],[533.08,-87.91],[530.38,-84.56],[527.52,-81.25],[524.51,-77.98],[521.37,-74.75],[518.15,-71.58],[514.86,-68.45],[511.53,-65.38],[508.2,-62.36],[504.89,-59.4],[501.63,-56.5],[498.46,-53.65],[495.39,-50.85],[492.45,-48.1],[489.68,-45.4],[487.09,-42.75],[484.7,-40.13],[482.53,-37.55],[480.61,-35.0]],[[484.48,-35.0],[482.81,-32.45],[481.4,-29.91],[480.28,-27.39],[479.44,-24.87],[478.9,-22.34],[478.65,-19.81],[478.7,-17.26],[479.05,-14.7],[479.68,-12.1],[480.6,-9.46],[481.79,-6.79],[483.23,-4.07],[484.92,-1.3],[486.82,1.53],[488.94,4.42],[491.23,7.37],[493.68,10.38],[496.26,13.46],[498.94,16.61],[501.7,19.82],[504.51,23.1],[507.34,26.44],[510.15,29.84],[512.93,33.31],[515.63,36.83],[518.23,40.39],[520.71,44.0],[523.03,47.65],[525.17,51.33],[527.1,55.03],[528.81,58.75],[530.26,62.48],[531.44,66.21],[532.34,69.93],[532.94,73.64],[533.22,77.32],[533.17,80.97],[532.8,84.57],[532.08,88.13],[531.02,91.63],[529.62,95.07],[527.89,98.44],[525.81,101.73],[523.41,104.95],[520.69,108.08],[517.65,111.12],[514.32,114.07],[510.71,116.93],[506.83,119.69],[502.69,122.37],[498.33,124.94],[493.75,127.43],[488.98,129.83],[484.03,132.14],[478.94,134.37],[473.7,136.53],[468.36,138.61],[462.92,140.63],[457.41,142.59],[451.85,144.51],[446.25,146.38],[440.63,148.21],[435.0,150.02],[429.38,151.81],[423.78,153.59],[418.21,155.36],[412.69,157.15],[407.21,158.94],[401.79,160.76],[396.42,162.6],[391.11,164.47],[385.87,166.39],[380.68,168.34],[375.55,170.34],[370.48,172.39],[365.45,174.49],[360.46,176.64],[355.5,178.84],[350.56,181.08],[345.64,183.38],[340.72,185.72],[335.8,188.09],[330.85,190.5],[325.87,192.93],[320.85,195.38],[315.78,197.84],[310.64,200.3],[305.42,202.74],[300.13,205.17],[294.73,207.56],[289.24,209.91],[283.64,212.2],[277.92,214.42],[272.09,216.55],[266.13,218.59],[260.05,220.53],[253.85,222.34],[247.53,224.02],[241.08,225.56],[234.53,226.94],[227.86,228.15],[221.09,229.2],[214.23,230.06],[207.28,230.73],[200.26,231.2],[193.18,231.48],[186.05,231.54],[178.88,231.4],[171.69,231.06],[164.49,230.5],[157.29,229.73],[150.11,228.77],[142.97,227.6],[135.87,226.23],[128.84,224.68],[121.87,222.95],[115.0,221.06],[108.22,219.0],[101.55,216.79],[95.0,214.45],[88.57,211.99],[82.28,209.42],[76.12,206.75],[70.1,204.01],[64.22,201.21],[58.49,198.35],[52.9,195.47],[47.45,192.58],[42.14,189.68],[36.95,186.8],[31.89,183.95],[26.94,181.15],[22.1,178.4],[17.36,175.73],[12.69,173.14],[8.1,170.65],[3.57,168.26],[-0.92,165.98],[-5.38,163.83],[-9.83,161.8],[-14.27,159.9],[-18.73,158.14],[-23.22,156.52],[-27.75,155.03],[-32.33,153.69],[-36.98,152.48],[-41.7,151.4],[-46.52,150.45],[-51.43,149.62],[-56.44,148.91],[-61.56,148.31],[-66.8,147.8],[-72.15,147.39],[-77.62,147.05],[-83.21,146.79],[-88.92,146.57],[-94.74,146.41],[-100.66,146.27],[-106.68,146.16],[-112.8,146.05],[-118.99,145.93],[-125.26,145.8],[-131.58,145.64],[-137.94,145.44],[-144.33,145.18],[-150.74,144.86],[-157.14,144.47],[-163.53,143.99],[-169.87,143.43],[-176.17,142.77],[-182.4,142.0],[-188.54,141.13],[-194.58,140.15],[-200.51,139.04],[-206.3,137.83],[-211.95,136.49],[-217.45,135.03],[-222.78,133.45],[-227.94,131.76],[-232.92,129.95],[-237.71,128.04],[-242.31,126.02],[-246.72,123.9],[-250.94,121.69],[-254.97,119.39],[-258.81,117.01],[-262.47,114.55],[-265.96,112.04],[-269.29,109.46],[-272.46,106.84],[-275.49,104.17],[-278.41,101.47],[-281.21,98.74],[-283.92,96.0],[-286.55,93.24],[-289.13,90.48],[-291.67,87.72],[-294.19,84.97],[-296.72,82.23],[-299.27,79.5],[-301.85,76.8],[-304.5,74.11],[-307.23,71.45],[-310.04,68.82],[-312.97,66.2],[-316.03,63.62],[-319.22,61.06],[-322.56,58.52],[-326.06,56.0],[-329.72,53.5],[-333.55,51.01],[-337.56,48.52],[-341.73,46.05],[-346.08,43.57],[-350.6,41.09],[-355.27,38.59],[-360.09,36.08],[-365.05,33.55],[-370.14,30.99],[-375.33,28.39],[-380.61,25.76],[-385.96,23.08],[-391.35,20.36],[-396.76,17.58],[-402.17,14.75],[-407.55,11.85],[-412.88,8.9],[-418.11,5.88],[-423.23,2.8],[-428.2,-0.35],[-432.99,-3.56],[-437.58,-6.84],[-441.94,-10.18],[-446.03,-13.58],[-449.84,-17.04],[-453.33,-20.54],[-456.48,-24.1],[-459.27,-27.7],[-461.68,-31.33],[-463.69,-35.0],[-465.28,-38.69],[-466.44,-42.4],[-467.16,-46.11],[-467.43,-49.83],[-467.24,-53.54],[-466.59,-57.23],[-465.49,-60.91],[-463.93,-64.55],[-461.91,-68.16],[-459.46,-71.72],[-456.57,-75.23],[-453.26,-78.68],[-449.56,-82.07],[-445.47,-85.39],[-441.01,-88.63],[-436.22,-91.8],[-431.11,-94.88],[-425.71,-97.88],[-420.05,-100.8],[-414.16,-103.63],[-408.06,-106.37],[-401.78,-109.02],[-395.37,-111.59],[-388.83,-114.08],[-382.22,-116.49],[-375.55,-118.82],[-368.85,-121.08],[-362.16,-123.28],[-355.5,-125.41],[-348.89,-127.49],[-342.36,-129.52],[-335.93,-131.51],[-329.63,-133.47],[-323.46,-135.4],[-317.45,-137.31],[-311.6,-139.22],[-305.94,-141.11],[-300.47,-143.01],[-295.19,-144.92],[-290.11,-146.85],[-285.24,-148.79],[-280.56,-150.77],[-276.08,-152.78],[-271.79,-154.82],[-267.69,-156.9],[-263.76,-159.03],[-259.99,-161.2],[-256.38,-163.42],[-252.9,-165.68],[-249.54,-167.99],[-246.28,-170.34],[-243.11,-172.73],[-240.01,-175.16],[-236.96,-177.62],[-233.93,-180.11],[-230.92,-182.62],[-227.9,-185.15],[-224.85,-187.68],[-221.76,-190.22],[-218.61,-192.75],[-215.37,-195.27],[-212.05,-197.76],[-208.62,-200.22],[-205.07,-202.64],[-201.39,-205.01],[-197.57,-207.32],[-193.61,-209.56],[-189.49,-211.72],[-185.22,-213.8],[-180.79,-215.8],[-176.2,-217.69],[-171.45,-219.48],[-166.55,-221.16],[-161.49,-222.73],[-156.3,-224.19],[-150.96,-225.52],[-145.5,-226.74],[-139.92,-227.84],[-134.23,-228.81],[-128.44,-229.68],[-122.57,-230.43],[-116.63,-231.07],[-110.63,-231.6],[-104.59,-232.04],[-98.51,-232.39],[-92.42,-232.66],[-86.32,-232.85],[-80.23,-232.98],[-74.16,-233.06],[-68.11,-233.09],[-62.11,-233.09],[-56.16,-233.08],[-50.26,-233.06],[-44.42,-233.05],[-38.65,-233.05],[-32.95,-233.09],[-27.32,-233.16],[-21.77,-233.3],[-16.29,-233.49],[-10.88,-233.77],[-5.53,-234.13],[-0.25,-234.58],[4.97,-235.14],[10.15,-235.81],[15.29,-236.59],[20.39,-237.49],[25.48,-238.52],[30.55,-239.68],[35.63,-240.97],[40.73,-242.38],[45.84,-243.92],[51.0,-245.58],[56.21,-247.36],[61.48,-249.25],[66.82,-251.25],[72.25,-253.35],[77.77,-255.53],[83.4,-257.8],[89.14,-260.12],[95.0,-262.51],[100.98,-264.93],[107.1,-267.38],[113.34,-269.84],[119.72,-272.29],[126.24,-274.73],[132.88,-277.13],[139.66,-279.48],[146.56,-281.77],[153.58,-283.97],[160.71,-286.08],[167.94,-288.07],[175.27,-289.94],[182.67,-291.66],[190.15,-293.24],[197.67,-294.65],[205.24,-295.89],[212.83,-296.94],[220.42,-297.8],[228.01,-298.45],[235.57,-298.91],[243.1,-299.15],[250.56,-299.17],[257.95,-298.98],[265.25,-298.58],[272.45,-297.96],[279.53,-297.12],[286.47,-296.08],[293.28,-294.83],[299.92,-293.38],[306.41,-291.74],[312.72,-289.92],[318.86,-287.92],[324.81,-285.76],[330.57,-283.44],[336.15,-280.98],[341.54,-278.4],[346.74,-275.69],[351.77,-272.89],[356.61,-269.99],[361.29,-267.01],[365.8,-263.97],[370.16,-260.87],[374.38,-257.74],[378.47,-254.57],[382.44,-251.4],[386.31,-248.21],[390.09,-245.03],[393.79,-241.87],[397.44,-238.73],[401.04,-235.63],[404.61,-232.56],[408.16,-229.53],[411.71,-226.56],[415.28,-223.64],[418.87,-220.77],[422.49,-217.96],[426.16,-215.21],[429.89,-212.52],[433.68,-209.88],[437.53,-207.3],[441.46,-204.78],[445.46,-202.3],[449.54,-199.86],[453.68,-197.46],[457.9,-195.09],[462.18,-192.75],[466.52,-190.43],[470.9,-188.12],[475.33,-185.82],[479.77,-183.52],[484.23,-181.21],[488.68,-178.88],[493.11,-176.53],[497.49,-174.15],[501.82,-171.74],[506.07,-169.29],[510.22,-166.79],[514.25,-164.24],[518.14,-161.63],[521.87,-158.97],[525.42,-156.25],[528.76,-153.47],[531.89,-150.63],[534.78,-147.72],[537.41,-144.75],[539.77,-141.72],[541.85,-138.63],[543.63,-135.48],[545.11,-132.28],[546.27,-129.03],[547.12,-125.73],[547.63,-122.4],[547.83,-119.03],[547.7,-115.64],[547.25,-112.22],[546.49,-108.79],[545.43,-105.35],[544.07,-101.91],[542.43,-98.48],[540.53,-95.05],[538.38,-91.64],[536.01,-88.26],[533.44,-84.9],[530.68,-81.58],[527.77,-78.3],[524.73,-75.06],[521.6,-71.87],[518.38,-68.73],[515.13,-65.64],[511.86,-62.61],[508.6,-59.62],[505.39,-56.7],[502.25,-53.82],[499.21,-51.0],[496.3,-48.23],[493.54,-45.51],[490.95,-42.83],[488.57,-40.18],[486.41,-37.58],[484.48,-35.0]],[[488.54,-35.0],[486.86,-32.42],[485.45,-29.86],[484.31,-27.31],[483.46,-24.76],[482.9,-22.21],[482.64,-19.65],[482.68,-17.08],[483.02,-14.49],[483.64,-11.86],[484.56,-9.2],[485.74,-6.5],[487.19,-3.75],[488.89,-0.95],[490.81,1.9],[492.95,4.82],[495.27,7.8],[497.76,10.84],[500.38,13.96],[503.12,17.14],[505.94,20.39],[508.82,23.71],[511.72,27.09],[514.61,30.54],[517.48,34.05],[520.27,37.62],[522.98,41.24],[525.56,44.9],[527.99,48.61],[530.24,52.35],[532.29,56.11],[534.11,59.9],[535.68,63.7],[536.98,67.49],[537.99,71.29],[538.7,75.07],[539.09,78.82],[539.15,82.55],[538.87,86.23],[538.25,89.87],[537.28,93.45],[535.96,96.97],[534.29,100.41],[532.27,103.79],[529.92,107.08],[527.23,110.28],[524.22,113.39],[520.9,116.41],[517.29,119.34],[513.4,122.16],[509.24,124.89],[504.83,127.52],[500.2,130.06],[495.36,132.5],[490.34,134.85],[485.15,137.11],[479.81,139.29],[474.35,141.4],[468.79,143.43],[463.14,145.4],[457.43,147.31],[451.67,149.18],[445.89,151.0],[440.09,152.79],[434.29,154.55],[428.51,156.3],[422.75,158.04],[417.03,159.77],[411.36,161.52],[405.74,163.28],[400.18,165.06],[394.68,166.87],[389.24,168.72],[383.86,170.6],[378.54,172.53],[373.28,174.5],[368.07,176.52],[362.91,178.59],[357.78,180.71],[352.69,182.88],[347.61,185.09],[342.54,187.35],[337.48,189.65],[332.4,191.98],[327.3,194.34],[322.17,196.72],[316.99,199.11],[311.75,201.51],[306.45,203.9],[301.07,206.27],[295.6,208.61],[290.04,210.92],[284.38,213.17],[278.61,215.35],[272.72,217.46],[266.73,219.48],[260.61,221.39],[254.38,223.2],[248.03,224.87],[241.56,226.4],[234.98,227.79],[228.29,229.01],[221.51,230.07],[214.63,230.94],[207.67,231.63],[200.63,232.13],[193.53,232.42],[186.38,232.52],[179.2,232.41],[171.98,232.09],[164.76,231.56],[157.55,230.83],[150.35,229.89],[143.18,228.75],[136.06,227.41],[128.99,225.89],[122.0,224.18],[115.1,222.31],[108.29,220.27],[101.59,218.08],[95.0,215.75],[88.54,213.3],[82.21,210.73],[76.01,208.07],[69.96,205.33],[64.05,202.52],[58.29,199.66],[52.66,196.76],[47.18,193.85],[41.84,190.94],[36.63,188.03],[31.54,185.16],[26.57,182.33],[21.71,179.55],[16.95,176.85],[12.27,174.23],[7.66,171.7],[3.11,169.27],[-1.39,166.96],[-5.86,164.77],[-10.31,162.71],[-14.77,160.78],[-19.23,158.99],[-23.72,157.34],[-28.26,155.82],[-32.85,154.45],[-37.5,153.22],[-42.24,152.13],[-47.06,151.17],[-51.99,150.33],[-57.02,149.62],[-62.17,149.01],[-67.43,148.52],[-72.82,148.11],[-78.33,147.8],[-83.96,147.55],[-89.72,147.37],[-95.6,147.23],[-101.59,147.13],[-107.69,147.06],[-113.89,147.0],[-120.18,146.94],[-126.55,146.86],[-132.98,146.76],[-139.47,146.62],[-145.99,146.43],[-152.54,146.18],[-159.09,145.85],[-165.63,145.45],[-172.15,144.96],[-178.62,144.37],[-185.02,143.68],[-191.35,142.88],[-197.59,141.96],[-203.71,140.93],[-209.71,139.78],[-215.57,138.51],[-221.27,137.11],[-226.82,135.59],[-232.19,133.95],[-237.37,132.19],[-242.37,130.32],[-247.18,128.34],[-251.79,126.26],[-256.2,124.07],[-260.42,121.79],[-264.44,119.43],[-268.28,116.98],[-271.93,114.47],[-275.42,111.89],[-278.74,109.26],[-281.9,106.58],[-284.94,103.86],[-287.85,101.1],[-290.65,98.33],[-293.37,95.54],[-296.02,92.73],[-298.61,89.93],[-301.18,87.13],[-303.73,84.33],[-306.29,81.55],[-308.88,78.78],[-311.51,76.03],[-314.21,73.3],[-316.99,70.6],[-319.87,67.92],[-322.86,65.26],[-325.98,62.63],[-329.24,60.01],[-332.65,57.42],[-336.22,54.85],[-339.95,52.29],[-343.84,49.74],[-347.9,47.19],[-352.14,44.65],[-356.53,42.1],[-361.08,39.54],[-365.78,36.97],[-370.63,34.38],[-375.59,31.76],[-380.67,29.11],[-385.83,26.43],[-391.07,23.7],[-396.36,20.93],[-401.68,18.11],[-407.0,15.23],[-412.29,12.3],[-417.53,9.3],[-422.7,6.25],[-427.75,3.13],[-432.66,-0.06],[-437.41,-3.3],[-441.96,-6.61],[-446.28,-9.98],[-450.35,-13.41],[-454.13,-16.89],[-457.61,-20.43],[-460.75,-24.02],[-463.54,-27.64],[-465.95,-31.31],[-467.96,-35.0],[-469.56,-38.72],[-470.72,-42.45],[-471.45,-46.2],[-471.73,-49.94],[-471.55,-53.68],[-470.91,-57.4],[-469.81,-61.11],[-468.24,-64.78],[-466.23,-68.41],[-463.76,-72.0],[-460.86,-75.54],[-457.53,-79.02],[-453.8,-82.44],[-449.67,-85.78],[-445.17,-89.05],[-440.33,-92.24],[-435.16,-95.34],[-429.69,-98.37],[-423.95,-101.3],[-417.97,-104.14],[-411.77,-106.9],[-405.39,-109.56],[-398.86,-112.14],[-392.21,-114.63],[-385.46,-117.04],[-378.66,-119.37],[-371.82,-121.63],[-364.98,-123.82],[-358.17,-125.95],[-351.4,-128.01],[-344.72,-130.03],[-338.13,-132.0],[-331.66,-133.94],[-325.33,-135.85],[-319.16,-137.74],[-313.16,-139.61],[-307.34,-141.48],[-301.72,-143.35],[-296.29,-145.23],[-291.07,-147.13],[-286.06,-149.04],[-281.26,-150.99],[-276.67,-152.96],[-272.27,-154.98],[-268.07,-157.03],[-264.05,-159.13],[-260.21,-161.28],[-256.53,-163.48],[-253.0,-165.72],[-249.6,-168.01],[-246.32,-170.35],[-243.14,-172.74],[-240.03,-175.17],[-236.99,-177.63],[-233.98,-180.13],[-231.0,-182.66],[-228.02,-185.21],[-225.03,-187.77],[-222.0,-190.34],[-218.92,-192.91],[-215.76,-195.47],[-212.52,-198.01],[-209.19,-200.53],[-205.73,-203.01],[-202.16,-205.45],[-198.45,-207.83],[-194.59,-210.15],[-190.58,-212.4],[-186.42,-214.57],[-182.1,-216.66],[-177.62,-218.65],[-172.98,-220.54],[-168.18,-222.32],[-163.23,-224.0],[-158.12,-225.56],[-152.88,-227.0],[-147.49,-228.33],[-141.99,-229.54],[-136.37,-230.62],[-130.64,-231.59],[-124.82,-232.45],[-118.92,-233.19],[-112.96,-233.83],[-106.94,-234.37],[-100.88,-234.81],[-94.8,-235.17],[-88.7,-235.44],[-82.6,-235.65],[-76.51,-235.81],[-70.44,-235.91],[-64.4,-235.98],[-58.4,-236.02],[-52.45,-236.06],[-46.56,-236.09],[-40.73,-236.13],[-34.96,-236.2],[-29.26,-236.31],[-23.63,-236.47],[-18.07,-236.68],[-12.58,-236.97],[-7.15,-237.33],[-1.78,-237.79],[3.53,-238.34],[8.8,-239.0],[14.03,-239.78],[19.22,-240.67],[24.4,-241.68],[29.57,-242.82],[34.73,-244.08],[39.92,-245.47],[45.12,-246.99],[50.36,-248.63],[55.66,-250.38],[61.01,-252.25],[66.43,-254.23],[71.94,-256.31],[77.55,-258.47],[83.25,-260.72],[89.07,-263.03],[95.0,-265.4],[101.06,-267.81],[107.25,-270.25],[113.57,-272.71],[120.02,-275.16],[126.61,-277.6],[133.33,-280.01],[140.19,-282.37],[147.16,-284.66],[154.26,-286.88],[161.48,-289.0],[168.79,-291.01],[176.2,-292.9],[183.69,-294.65],[191.25,-296.24],[198.87,-297.68],[206.53,-298.94],[214.21,-300.01],[221.9,-300.89],[229.59,-301.57],[237.25,-302.05],[244.87,-302.3],[252.43,-302.35],[259.92,-302.17],[267.32,-301.78],[274.61,-301.16],[281.78,-300.33],[288.82,-299.28],[295.71,-298.02],[302.45,-296.56],[309.02,-294.91],[315.41,-293.06],[321.61,-291.03],[327.63,-288.84],[333.46,-286.48],[339.09,-283.98],[344.52,-281.34],[349.76,-278.58],[354.81,-275.71],[359.68,-272.74],[364.36,-269.69],[368.87,-266.57],[373.22,-263.39],[377.42,-260.16],[381.48,-256.91],[385.41,-253.63],[389.23,-250.35],[392.95,-247.07],[396.59,-243.81],[400.15,-240.56],[403.66,-237.35],[407.14,-234.17],[410.59,-231.04],[414.04,-227.96],[417.49,-224.94],[420.96,-221.97],[424.46,-219.06],[428.0,-216.21],[431.59,-213.42],[435.25,-210.7],[438.97,-208.03],[442.77,-205.42],[446.64,-202.86],[450.59,-200.35],[454.62,-197.88],[458.72,-195.45],[462.88,-193.05],[467.12,-190.68],[471.41,-188.33],[475.74,-185.99],[480.11,-183.65],[484.49,-181.31],[488.89,-178.96],[493.27,-176.59],[497.62,-174.2],[501.93,-171.78],[506.17,-169.32],[510.32,-166.82],[514.37,-164.27],[518.29,-161.68],[522.06,-159.03],[525.66,-156.32],[529.07,-153.56],[532.28,-150.73],[535.25,-147.84],[537.99,-144.89],[540.46,-141.88],[542.65,-138.81],[544.56,-135.69],[546.17,-132.51],[547.47,-129.28],[548.46,-126.0],[549.13,-122.69],[549.48,-119.34],[549.5,-115.96],[549.21,-112.56],[548.6,-109.14],[547.69,-105.71],[546.49,-102.27],[545.0,-98.84],[543.24,-95.42],[541.24,-92.01],[539.0,-88.62],[536.55,-85.26],[533.92,-81.93],[531.12,-78.64],[528.19,-75.39],[525.15,-72.18],[522.03,-69.02],[518.85,-65.91],[515.65,-62.86],[512.46,-59.85],[509.3,-56.9],[506.21,-54.01],[503.2,-51.16],[500.32,-48.36],[497.58,-45.61],[495.01,-42.91],[492.63,-40.24],[490.47,-37.6],[488.54,-35.0]],[[492.81,-35.0],[491.13,-32.39],[489.71,-29.8],[488.56,-27.22],[487.69,-24.65],[487.12,-22.07],[486.85,-19.49],[486.87,-16.89],[487.19,-14.26],[487.81,-11.61],[488.71,-8.93],[489.89,-6.2],[491.34,-3.42],[493.04,-0.59],[494.98,2.29],[497.13,5.24],[499.48,8.25],[501.99,11.33],[504.66,14.47],[507.44,17.69],[510.31,20.98],[513.25,24.34],[516.21,27.76],[519.18,31.26],[522.13,34.81],[525.01,38.43],[527.8,42.1],[530.48,45.82],[533.01,49.58],[535.37,53.38],[537.52,57.2],[539.45,61.05],[541.13,64.92],[542.54,68.79],[543.67,72.65],[544.48,76.5],[544.97,80.33],[545.14,84.13],[544.95,87.89],[544.42,91.61],[543.53,95.26],[542.28,98.86],[540.68,102.38],[538.72,105.83],[536.41,109.2],[533.76,112.47],[530.78,115.66],[527.47,118.75],[523.85,121.73],[519.95,124.62],[515.76,127.41],[511.32,130.09],[506.63,132.68],[501.73,135.16],[496.62,137.55],[491.34,139.84],[485.9,142.05],[480.33,144.18],[474.64,146.22],[468.85,148.2],[462.99,150.11],[457.08,151.97],[451.12,153.77],[445.15,155.54],[439.17,157.28],[433.21,158.99],[427.26,160.69],[421.35,162.39],[415.48,164.08],[409.66,165.78],[403.9,167.51],[398.21,169.25],[392.57,171.03],[387.0,172.84],[381.49,174.69],[376.04,176.58],[370.65,178.52],[365.31,180.51],[360.02,182.54],[354.76,184.63],[349.52,186.76],[344.31,188.94],[339.1,191.15],[333.89,193.41],[328.67,195.69],[323.42,198.0],[318.13,200.32],[312.8,202.65],[307.4,204.98],[301.94,207.3],[296.4,209.59],[290.77,211.84],[285.05,214.05],[279.23,216.2],[273.3,218.28],[267.27,220.28],[261.11,222.17],[254.85,223.96],[248.47,225.63],[241.98,227.16],[235.38,228.55],[228.68,229.78],[221.88,230.84],[214.98,231.73],[208.01,232.44],[200.96,232.96],[193.85,233.28],[186.69,233.41],[179.48,233.32],[172.26,233.04],[165.02,232.54],[157.78,231.84],[150.57,230.94],[143.38,229.83],[136.23,228.53],[129.14,227.03],[122.13,225.36],[115.19,223.51],[108.35,221.49],[101.62,219.32],[95.0,217.02],[88.51,214.58],[82.14,212.02],[75.91,209.37],[69.83,206.63],[63.88,203.82],[58.08,200.96],[52.43,198.06],[46.91,195.14],[41.54,192.21],[36.3,189.29],[31.19,186.39],[26.19,183.54],[21.31,180.74],[16.52,178.01],[11.82,175.36],[7.2,172.8],[2.63,170.34],[-1.88,168.0],[-6.37,165.77],[-10.83,163.68],[-15.29,161.72],[-19.77,159.9],[-24.27,158.22],[-28.81,156.68],[-33.41,155.29],[-38.08,154.04],[-42.82,152.93],[-47.66,151.95],[-52.61,151.11],[-57.66,150.39],[-62.83,149.79],[-68.12,149.3],[-73.54,148.91],[-79.09,148.6],[-84.77,148.38],[-90.59,148.22],[-96.52,148.12],[-102.58,148.06],[-108.76,148.02],[-115.05,148.01],[-121.43,147.99],[-127.9,147.97],[-134.45,147.93],[-141.05,147.85],[-147.71,147.72],[-154.4,147.54],[-161.1,147.28],[-167.8,146.95],[-174.48,146.53],[-181.12,146.01],[-187.71,145.39],[-194.23,144.66],[-200.65,143.82],[-206.98,142.86],[-213.18,141.77],[-219.24,140.56],[-225.16,139.22],[-230.91,137.76],[-236.49,136.17],[-241.89,134.46],[-247.1,132.64],[-252.11,130.7],[-256.92,128.64],[-261.53,126.48],[-265.94,124.23],[-270.15,121.88],[-274.16,119.44],[-277.98,116.93],[-281.62,114.35],[-285.09,111.71],[-288.39,109.01],[-291.55,106.27],[-294.57,103.5],[-297.47,100.69],[-300.28,97.86],[-302.99,95.01],[-305.64,92.16],[-308.25,89.3],[-310.83,86.45],[-313.4,83.61],[-315.99,80.78],[-318.61,77.97],[-321.28,75.17],[-324.02,72.4],[-326.84,69.65],[-329.77,66.92],[-332.81,64.21],[-335.99,61.53],[-339.3,58.86],[-342.76,56.21],[-346.38,53.58],[-350.16,50.96],[-354.1,48.34],[-358.21,45.73],[-362.48,43.12],[-366.9,40.49],[-371.47,37.86],[-376.18,35.21],[-381.02,32.53],[-385.97,29.83],[-391.01,27.09],[-396.13,24.31],[-401.3,21.49],[-406.51,18.62],[-411.73,15.7],[-416.93,12.73],[-422.08,9.69],[-427.16,6.6],[-432.14,3.45],[-436.99,0.23],[-441.68,-3.05],[-446.18,-6.39],[-450.46,-9.79],[-454.49,-13.25],[-458.25,-16.76],[-461.7,-20.32],[-464.83,-23.94],[-467.61,-27.59],[-470.01,-31.28],[-472.02,-35.0],[-473.62,-38.74],[-474.8,-42.51],[-475.53,-46.28],[-475.82,-50.05],[-475.65,-53.81],[-475.01,-57.57],[-473.92,-61.3],[-472.36,-65.0],[-470.34,-68.66],[-467.87,-72.28],[-464.96,-75.84],[-461.61,-79.35],[-457.85,-82.79],[-453.7,-86.16],[-449.16,-89.45],[-444.27,-92.66],[-439.05,-95.79],[-433.52,-98.83],[-427.71,-101.78],[-421.65,-104.64],[-415.36,-107.4],[-408.89,-110.08],[-402.25,-112.67],[-395.49,-115.17],[-388.62,-117.58],[-381.69,-119.91],[-374.72,-122.17],[-367.74,-124.35],[-360.78,-126.47],[-353.87,-128.53],[-347.03,-130.53],[-340.29,-132.49],[-333.66,-134.41],[-327.18,-136.29],[-320.85,-138.16],[-314.7,-140.01],[-308.73,-141.85],[-302.96,-143.69],[-297.39,-145.54],[-292.04,-147.41],[-286.9,-149.29],[-281.98,-151.21],[-277.27,-153.15],[-272.77,-155.14],[-268.47,-157.17],[-264.37,-159.24],[-260.45,-161.37],[-256.71,-163.54],[-253.13,-165.77],[-249.69,-168.05],[-246.38,-170.38],[-243.18,-172.76],[-240.08,-175.18],[-237.04,-177.65],[-234.06,-180.16],[-231.11,-182.7],[-228.17,-185.27],[-225.23,-187.86],[-222.26,-190.47],[-219.25,-193.08],[-216.18,-195.68],[-213.02,-198.28],[-209.78,-200.85],[-206.43,-203.4],[-202.95,-205.9],[-199.35,-208.36],[-195.6,-210.76],[-191.71,-213.1],[-187.66,-215.36],[-183.45,-217.54],[-179.08,-219.63],[-174.54,-221.62],[-169.85,-223.51],[-165.0,-225.3],[-159.99,-226.97],[-154.83,-228.52],[-149.54,-229.96],[-144.11,-231.28],[-138.56,-232.48],[-132.89,-233.56],[-127.13,-234.52],[-121.28,-235.37],[-115.35,-236.11],[-109.36,-236.75],[-103.31,-237.29],[-97.24,-237.74],[-91.14,-238.11],[-85.03,-238.4],[-78.92,-238.63],[-72.82,-238.81],[-66.75,-238.95],[-60.71,-239.05],[-54.71,-239.14],[-48.76,-239.22],[-42.87,-239.31],[-37.04,-239.41],[-31.26,-239.55],[-25.56,-239.73],[-19.91,-239.96],[-14.33,-240.26],[-8.82,-240.63],[-3.36,-241.09],[2.05,-241.64],[7.41,-242.29],[12.73,-243.05],[18.02,-243.93],[23.29,-244.92],[28.55,-246.04],[33.81,-247.28],[39.08,-248.65],[44.38,-250.14],[49.71,-251.75],[55.09,-253.48],[60.53,-255.32],[66.04,-257.27],[71.63,-259.32],[77.31,-261.46],[83.1,-263.68],[88.99,-265.97],[95.0,-268.33],[101.13,-270.72],[107.4,-273.15],[113.79,-275.6],[120.32,-278.04],[126.99,-280.48],[133.78,-282.88],[140.71,-285.24],[147.77,-287.54],[154.94,-289.77],[162.24,-291.9],[169.63,-293.92],[177.12,-295.83],[184.7,-297.59],[192.35,-299.21],[200.05,-300.66],[207.8,-301.94],[215.57,-303.03],[223.35,-303.93],[231.13,-304.63],[238.89,-305.12],[246.6,-305.4],[254.26,-305.46],[261.84,-305.29],[269.34,-304.91],[276.73,-304.3],[283.99,-303.46],[291.12,-302.42],[298.1,-301.15],[304.92,-299.68],[311.57,-298.01],[318.04,-296.14],[324.31,-294.08],[330.4,-291.85],[336.28,-289.46],[341.96,-286.91],[347.44,-284.22],[352.72,-281.4],[357.79,-278.47],[362.68,-275.43],[367.37,-272.31],[371.88,-269.11],[376.22,-265.85],[380.4,-262.54],[384.43,-259.19],[388.32,-255.83],[392.09,-252.45],[395.75,-249.07],[399.32,-245.7],[402.81,-242.35],[406.23,-239.03],[409.61,-235.75],[412.96,-232.52],[416.3,-229.33],[419.63,-226.2],[422.98,-223.13],[426.36,-220.12],[429.77,-217.18],[433.24,-214.29],[436.76,-211.48],[440.35,-208.72],[444.02,-206.03],[447.76,-203.39],[451.58,-200.81],[455.48,-198.27],[459.46,-195.78],[463.52,-193.32],[467.64,-190.9],[471.83,-188.5],[476.08,-186.12],[480.36,-183.75],[484.68,-181.38],[489.02,-179.0],[493.35,-176.62],[497.67,-174.21],[501.95,-171.78],[506.18,-169.32],[510.34,-166.82],[514.41,-164.28],[518.35,-161.7],[522.17,-159.06],[525.82,-156.37],[529.3,-153.62],[532.59,-150.81],[535.66,-147.94],[538.49,-145.02],[541.07,-142.03],[543.39,-138.98],[545.43,-135.88],[547.18,-132.72],[548.63,-129.52],[549.77,-126.27],[550.59,-122.97],[551.1,-119.64],[551.28,-116.28],[551.15,-112.89],[550.71,-109.48],[549.97,-106.06],[548.92,-102.64],[547.59,-99.21],[545.99,-95.79],[544.14,-92.38],[542.05,-88.99],[539.74,-85.62],[537.24,-82.29],[534.57,-78.98],[531.75,-75.72],[528.82,-72.5],[525.79,-69.32],[522.71,-66.2],[519.59,-63.12],[516.47,-60.09],[513.37,-57.12],[510.33,-54.2],[507.37,-51.33],[504.52,-48.5],[501.81,-45.72],[499.26,-42.99],[496.9,-40.29],[494.74,-37.63],[492.81,-35.0]],[[497.29,-35.0],[495.6,-32.36],[494.17,-29.74],[493.02,-27.13],[492.14,-24.53],[491.55,-21.93],[491.26,-19.31],[491.27,-16.68],[491.57,-14.03],[492.18,-11.35],[493.07,-8.64],[494.24,-5.88],[495.68,-3.08],[497.38,-0.22],[499.32,2.7],[501.49,5.67],[503.85,8.72],[506.39,11.83],[509.08,15.01],[511.9,18.26],[514.81,21.59],[517.8,24.98],[520.82,28.45],[523.86,31.99],[526.87,35.59],[529.83,39.25],[532.71,42.97],[535.47,46.74],[538.1,50.56],[540.55,54.42],[542.8,58.31],[544.84,62.22],[546.62,66.15],[548.13,70.08],[549.36,74.02],[550.27,77.94],[550.87,81.84],[551.12,85.72],[551.03,89.55],[550.58,93.34],[549.77,97.08],[548.6,100.75],[547.06,104.35],[545.15,107.87],[542.88,111.31],[540.27,114.66],[537.3,117.91],[534.01,121.07],[530.39,124.12],[526.46,127.07],[522.25,129.91],[517.77,132.65],[513.03,135.28],[508.06,137.81],[502.88,140.24],[497.5,142.56],[491.96,144.79],[486.27,146.94],[480.45,149.0],[474.53,150.98],[468.52,152.89],[462.45,154.74],[456.33,156.53],[450.18,158.28],[444.03,159.99],[437.87,161.67],[431.74,163.33],[425.63,164.98],[419.57,166.62],[413.55,168.27],[407.59,169.92],[401.7,171.6],[395.86,173.31],[390.1,175.04],[384.39,176.81],[378.76,178.62],[373.18,180.48],[367.67,182.38],[362.2,184.34],[356.77,186.33],[351.38,188.38],[346.02,190.47],[340.67,192.61],[335.33,194.78],[329.98,196.98],[324.61,199.22],[319.22,201.47],[313.78,203.73],[308.3,205.99],[302.76,208.25],[297.14,210.49],[291.45,212.69],[285.67,214.86],[279.79,216.97],[273.82,219.02],[267.74,220.99],[261.56,222.86],[255.27,224.64],[248.86,226.29],[242.35,227.82],[235.74,229.21],[229.02,230.45],[222.2,231.53],[215.3,232.43],[208.31,233.16],[201.25,233.71],[194.13,234.06],[186.96,234.21],[179.75,234.16],[172.51,233.91],[165.26,233.45],[158.01,232.78],[150.77,231.91],[143.56,230.85],[136.39,229.58],[129.28,228.12],[122.24,226.48],[115.28,224.66],[108.41,222.68],[101.65,220.54],[95.0,218.25],[88.47,215.83],[82.07,213.3],[75.81,210.66],[69.69,207.93],[63.71,205.13],[57.88,202.27],[52.19,199.37],[46.64,196.44],[41.24,193.5],[35.96,190.57],[30.82,187.66],[25.8,184.79],[20.89,181.97],[16.08,179.21],[11.35,176.53],[6.71,173.95],[2.13,171.46],[-2.4,169.09],[-6.9,166.84],[-11.38,164.71],[-15.86,162.73],[-20.34,160.88],[-24.86,159.17],[-29.41,157.61],[-34.02,156.19],[-38.7,154.92],[-43.46,153.8],[-48.32,152.81],[-53.28,151.96],[-58.35,151.24],[-63.55,150.64],[-68.87,150.15],[-74.33,149.77],[-79.92,149.48],[-85.65,149.27],[-91.52,149.14],[-97.52,149.07],[-103.65,149.04],[-109.9,149.05],[-116.27,149.07],[-122.75,149.11],[-129.32,149.14],[-135.98,149.15],[-142.71,149.13],[-149.49,149.06],[-156.32,148.94],[-163.17,148.76],[-170.02,148.49],[-176.87,148.14],[-183.69,147.7],[-190.45,147.15],[-197.16,146.49],[-203.78,145.71],[-210.3,144.81],[-216.7,143.79],[-222.97,142.64],[-229.1,141.37],[-235.06,139.96],[-240.86,138.43],[-246.46,136.77],[-251.88,134.98],[-257.1,133.08],[-262.12,131.06],[-266.93,128.93],[-271.53,126.69],[-275.92,124.36],[-280.11,121.93],[-284.1,119.43],[-287.9,116.84],[-291.52,114.19],[-294.96,111.48],[-298.24,108.72],[-301.37,105.91],[-304.37,103.07],[-307.26,100.2],[-310.05,97.32],[-312.75,94.42],[-315.4,91.51],[-318.01,88.6],[-320.59,85.7],[-323.17,82.8],[-325.78,79.92],[-328.41,77.06],[-331.11,74.21],[-333.88,71.39],[-336.74,68.59],[-339.7,65.81],[-342.78,63.05],[-346.0,60.31],[-349.35,57.59],[-352.85,54.88],[-356.51,52.18],[-360.32,49.5],[-364.29,46.82],[-368.42,44.13],[-372.71,41.44],[-377.14,38.75],[-381.71,36.03],[-386.41,33.3],[-391.22,30.54],[-396.13,27.74],[-401.12,24.92],[-406.18,22.05],[-411.26,19.13],[-416.37,16.17],[-421.46,13.15],[-426.51,10.08],[-431.5,6.95],[-436.4,3.76],[-441.17,0.51],[-445.8,-2.8],[-450.24,-6.17],[-454.47,-9.6],[-458.46,-13.09],[-462.18,-16.63],[-465.61,-20.22],[-468.72,-23.86],[-471.48,-27.54],[-473.87,-31.25],[-475.88,-35.0],[-477.48,-38.77],[-478.66,-42.56],[-479.4,-46.35],[-479.69,-50.15],[-479.53,-53.94],[-478.91,-57.72],[-477.82,-61.48],[-476.26,-65.2],[-474.25,-68.89],[-471.77,-72.53],[-468.86,-76.13],[-465.5,-79.66],[-461.73,-83.12],[-457.55,-86.51],[-452.98,-89.83],[-448.05,-93.06],[-442.78,-96.21],[-437.2,-99.27],[-431.33,-102.24],[-425.19,-105.12],[-418.83,-107.9],[-412.27,-110.59],[-405.54,-113.18],[-398.67,-115.69],[-391.69,-118.11],[-384.64,-120.44],[-377.54,-122.69],[-370.43,-124.87],[-363.34,-126.98],[-356.28,-129.03],[-349.3,-131.02],[-342.41,-132.96],[-335.64,-134.87],[-329.01,-136.73],[-322.53,-138.58],[-316.23,-140.4],[-310.12,-142.22],[-304.2,-144.03],[-298.5,-145.85],[-293.01,-147.69],[-287.75,-149.55],[-282.71,-151.43],[-277.88,-153.35],[-273.28,-155.31],[-268.89,-157.31],[-264.71,-159.36],[-260.72,-161.46],[-256.92,-163.62],[-253.29,-165.83],[-249.81,-168.09],[-246.48,-170.42],[-243.26,-172.79],[-240.15,-175.22],[-237.13,-177.69],[-234.16,-180.21],[-231.24,-182.77],[-228.35,-185.36],[-225.46,-187.97],[-222.55,-190.61],[-219.61,-193.26],[-216.62,-195.91],[-213.56,-198.56],[-210.4,-201.19],[-207.15,-203.8],[-203.78,-206.38],[-200.28,-208.91],[-196.65,-211.4],[-192.87,-213.82],[-188.93,-216.17],[-184.83,-218.45],[-180.57,-220.64],[-176.15,-222.73],[-171.56,-224.73],[-166.81,-226.62],[-161.9,-228.41],[-156.84,-230.08],[-151.63,-231.63],[-146.28,-233.06],[-140.8,-234.37],[-135.2,-235.57],[-129.49,-236.64],[-123.68,-237.6],[-117.79,-238.45],[-111.83,-239.19],[-105.81,-239.83],[-99.74,-240.38],[-93.64,-240.84],[-87.52,-241.22],[-81.4,-241.53],[-75.27,-241.78],[-69.17,-241.99],[-63.08,-242.16],[-57.03,-242.3],[-51.03,-242.44],[-45.07,-242.57],[-39.17,-242.71],[-33.32,-242.88],[-27.53,-243.08],[-21.8,-243.33],[-16.14,-243.64],[-10.53,-244.02],[-4.98,-244.48],[0.52,-245.03],[5.98,-245.67],[11.4,-246.42],[16.79,-247.28],[22.15,-248.25],[27.51,-249.35],[32.87,-250.56],[38.23,-251.9],[43.62,-253.36],[49.05,-254.94],[54.51,-256.63],[60.04,-258.44],[65.64,-260.36],[71.31,-262.38],[77.07,-264.49],[82.94,-266.69],[88.91,-268.95],[95.0,-271.28],[101.21,-273.66],[107.55,-276.07],[114.02,-278.5],[120.62,-280.93],[127.36,-283.36],[134.23,-285.75],[141.24,-288.11],[148.37,-290.41],[155.62,-292.64],[162.99,-294.77],[170.46,-296.81],[178.03,-298.72],[185.69,-300.5],[193.42,-302.12],[201.21,-303.59],[209.04,-304.89],[216.9,-306.0],[224.78,-306.92],[232.65,-307.63],[240.49,-308.14],[248.3,-308.43],[256.05,-308.5],[263.73,-308.34],[271.31,-307.96],[278.79,-307.36],[286.15,-306.53],[293.37,-305.48],[300.43,-304.21],[307.33,-302.72],[314.06,-301.03],[320.6,-299.14],[326.95,-297.06],[333.1,-294.8],[339.04,-292.37],[344.77,-289.78],[350.29,-287.04],[355.6,-284.16],[360.71,-281.17],[365.61,-278.07],[370.31,-274.87],[374.83,-271.6],[379.16,-268.26],[383.32,-264.86],[387.32,-261.43],[391.17,-257.97],[394.89,-254.49],[398.49,-251.02],[401.99,-247.55],[405.4,-244.1],[408.74,-240.68],[412.03,-237.29],[415.28,-233.95],[418.5,-230.66],[421.72,-227.43],[424.95,-224.26],[428.2,-221.15],[431.49,-218.11],[434.82,-215.13],[438.21,-212.23],[441.67,-209.38],[445.2,-206.61],[448.81,-203.89],[452.5,-201.24],[456.28,-198.63],[460.14,-196.08],[464.08,-193.57],[468.1,-191.09],[472.19,-188.65],[476.34,-186.22],[480.55,-183.82],[484.79,-181.42],[489.07,-179.02],[493.36,-176.62],[497.64,-174.2],[501.9,-171.76],[506.12,-169.3],[510.28,-166.81],[514.36,-164.27],[518.34,-161.69],[522.2,-159.07],[525.91,-156.39],[529.46,-153.66],[532.83,-150.87],[535.99,-148.03],[538.93,-145.12],[541.63,-142.16],[544.07,-139.14],[546.25,-136.06],[548.14,-132.93],[549.74,-129.75],[551.04,-126.52],[552.02,-123.25],[552.7,-119.94],[553.05,-116.59],[553.1,-113.22],[552.83,-109.83],[552.25,-106.42],[551.38,-103.0],[550.22,-99.58],[548.78,-96.16],[547.09,-92.76],[545.15,-89.36],[543.0,-85.99],[540.64,-82.65],[538.1,-79.34],[535.41,-76.06],[532.6,-72.82],[529.68,-69.63],[526.69,-66.49],[523.67,-63.39],[520.62,-60.34],[517.6,-57.34],[514.62,-54.4],[511.71,-51.5],[508.9,-48.65],[506.23,-45.84],[503.7,-43.08],[501.35,-40.35],[499.21,-37.66],[497.29,-35.0]],[[501.97,-35.0],[500.29,-32.33],[498.86,-29.68],[497.69,-27.04],[496.8,-24.41],[496.2,-21.77],[495.89,-19.13],[495.88,-16.47],[496.17,-13.79],[496.75,-11.08],[497.63,-8.34],[498.79,-5.55],[500.22,-2.72],[501.91,0.17],[503.85,3.12],[506.01,6.13],[508.38,9.2],[510.94,12.34],[513.65,15.56],[516.5,18.85],[519.45,22.21],[522.47,25.65],[525.55,29.15],[528.64,32.73],[531.71,36.38],[534.74,40.09],[537.69,43.86],[540.54,47.68],[543.24,51.55],[545.78,55.47],[548.13,59.41],[550.25,63.39],[552.13,67.38],[553.74,71.38],[555.06,75.38],[556.08,79.38],[556.76,83.35],[557.11,87.3],[557.1,91.21],[556.73,95.07],[556.0,98.88],[554.89,102.63],[553.4,106.31],[551.55,109.9],[549.32,113.42],[546.74,116.84],[543.79,120.16],[540.51,123.38],[536.89,126.5],[532.95,129.51],[528.71,132.41],[524.18,135.19],[519.39,137.87],[514.35,140.44],[509.09,142.91],[503.62,145.26],[497.98,147.52],[492.17,149.68],[486.23,151.75],[480.17,153.74],[474.01,155.65],[467.78,157.49],[461.5,159.27],[455.18,161.0],[448.84,162.68],[442.5,164.33],[436.18,165.94],[429.88,167.54],[423.61,169.13],[417.4,170.72],[411.24,172.32],[405.14,173.92],[399.11,175.55],[393.15,177.21],[387.25,178.9],[381.43,180.63],[375.67,182.41],[369.97,184.22],[364.33,186.09],[358.74,188.0],[353.19,189.95],[347.67,191.96],[342.18,194.01],[336.71,196.1],[331.23,198.22],[325.75,200.37],[320.24,202.55],[314.71,204.74],[309.14,206.94],[303.51,209.13],[297.82,211.31],[292.06,213.47],[286.22,215.59],[280.3,217.66],[274.28,219.67],[268.17,221.61],[261.95,223.47],[255.63,225.22],[249.2,226.87],[242.67,228.39],[236.04,229.78],[229.31,231.03],[222.49,232.12],[215.57,233.04],[208.58,233.79],[201.51,234.36],[194.39,234.74],[187.21,234.93],[179.99,234.91],[172.74,234.7],[165.48,234.28],[158.21,233.65],[150.96,232.83],[143.74,231.8],[136.55,230.57],[129.42,229.16],[122.35,227.55],[115.37,225.77],[108.47,223.82],[101.68,221.71],[95.0,219.46],[88.44,217.07],[82.01,214.56],[75.71,211.94],[69.56,209.23],[63.54,206.44],[57.67,203.58],[51.95,200.69],[46.37,197.76],[40.93,194.82],[35.62,191.88],[30.45,188.96],[25.39,186.08],[20.45,183.24],[15.61,180.46],[10.87,177.76],[6.2,175.15],[1.6,172.65],[-2.96,170.25],[-7.47,167.97],[-11.97,165.82],[-16.46,163.8],[-20.96,161.93],[-25.49,160.2],[-30.06,158.61],[-34.69,157.18],[-39.38,155.89],[-44.16,154.75],[-49.03,153.75],[-54.02,152.89],[-59.11,152.16],[-64.34,151.56],[-69.69,151.08],[-75.19,150.7],[-80.82,150.43],[-86.6,150.24],[-92.52,150.13],[-98.58,150.08],[-104.78,150.09],[-111.11,150.13],[-117.56,150.2],[-124.13,150.28],[-130.81,150.36],[-137.58,150.42],[-144.43,150.46],[-151.34,150.45],[-158.3,150.4],[-165.3,150.28],[-172.31,150.08],[-179.32,149.79],[-186.31,149.42],[-193.26,148.94],[-200.15,148.34],[-206.96,147.64],[-213.68,146.81],[-220.29,145.85],[-226.77,144.76],[-233.1,143.54],[-239.27,142.19],[-245.28,140.71],[-251.1,139.1],[-256.73,137.36],[-262.15,135.49],[-267.37,133.5],[-272.38,131.4],[-277.18,129.18],[-281.76,126.87],[-286.13,124.45],[-290.29,121.95],[-294.25,119.36],[-298.01,116.7],[-301.59,113.97],[-305.0,111.19],[-308.24,108.35],[-311.34,105.48],[-314.31,102.58],[-317.17,99.64],[-319.93,96.69],[-322.62,93.73],[-325.25,90.77],[-327.85,87.8],[-330.42,84.85],[-333.01,81.9],[-335.61,78.96],[-338.26,76.05],[-340.97,73.15],[-343.76,70.27],[-346.64,67.42],[-349.62,64.58],[-352.73,61.76],[-355.97,58.96],[-359.35,56.18],[-362.87,53.41],[-366.55,50.65],[-370.39,47.9],[-374.37,45.15],[-378.51,42.39],[-382.79,39.63],[-387.22,36.85],[-391.77,34.06],[-396.43,31.24],[-401.2,28.39],[-406.05,25.51],[-410.97,22.59],[-415.93,19.63],[-420.91,16.62],[-425.88,13.56],[-430.83,10.45],[-435.72,7.28],[-440.52,4.06],[-445.21,0.78],[-449.76,-2.57],[-454.13,-5.97],[-458.3,-9.43],[-462.25,-12.94],[-465.93,-16.51],[-469.32,-20.12],[-472.4,-23.79],[-475.15,-27.49],[-477.53,-31.23],[-479.53,-35.0],[-481.13,-38.79],[-482.31,-42.6],[-483.05,-46.42],[-483.35,-50.25],[-483.2,-54.06],[-482.58,-57.87],[-481.5,-61.65],[-479.96,-65.4],[-477.95,-69.11],[-475.48,-72.78],[-472.56,-76.4],[-469.2,-79.95],[-465.41,-83.44],[-461.22,-86.86],[-456.63,-90.2],[-451.67,-93.45],[-446.36,-96.62],[-440.73,-99.7],[-434.8,-102.68],[-428.61,-105.58],[-422.18,-108.37],[-415.53,-111.07],[-408.71,-113.68],[-401.75,-116.19],[-394.67,-118.61],[-387.51,-120.95],[-380.3,-123.2],[-373.07,-125.38],[-365.84,-127.49],[-358.66,-129.53],[-351.54,-131.51],[-344.51,-133.43],[-337.6,-135.32],[-330.82,-137.17],[-324.2,-138.99],[-317.76,-140.79],[-311.51,-142.59],[-305.46,-144.37],[-299.62,-146.17],[-294.01,-147.98],[-288.62,-149.81],[-283.46,-151.66],[-278.53,-153.55],[-273.83,-155.49],[-269.35,-157.46],[-265.09,-159.49],[-261.03,-161.57],[-257.17,-163.71],[-253.48,-165.9],[-249.97,-168.15],[-246.61,-170.47],[-243.38,-172.84],[-240.27,-175.26],[-237.25,-177.74],[-234.31,-180.27],[-231.42,-182.85],[-228.57,-185.46],[-225.73,-188.1],[-222.89,-190.77],[-220.02,-193.46],[-217.1,-196.16],[-214.12,-198.86],[-211.06,-201.55],[-207.91,-204.23],[-204.65,-206.88],[-201.26,-209.49],[-197.73,-212.05],[-194.06,-214.56],[-190.24,-217.01],[-186.26,-219.38],[-182.11,-221.67],[-177.8,-223.88],[-173.32,-225.98],[-168.67,-227.99],[-163.86,-229.88],[-158.89,-231.67],[-153.77,-233.33],[-148.5,-234.88],[-143.1,-236.31],[-137.56,-237.62],[-131.91,-238.81],[-126.15,-239.89],[-120.3,-240.84],[-114.36,-241.69],[-108.36,-242.44],[-102.3,-243.08],[-96.2,-243.63],[-90.08,-244.1],[-83.93,-244.5],[-77.78,-244.83],[-71.64,-245.11],[-65.52,-245.35],[-59.42,-245.55],[-53.35,-245.73],[-47.33,-245.91],[-41.35,-246.09],[-35.43,-246.29],[-29.56,-246.52],[-23.74,-246.79],[-17.99,-247.12],[-12.29,-247.5],[-6.64,-247.96],[-1.04,-248.51],[4.51,-249.14],[10.03,-249.87],[15.52,-250.71],[20.99,-251.67],[26.44,-252.73],[31.9,-253.92],[37.36,-255.22],[42.85,-256.65],[48.37,-258.19],[53.93,-259.85],[59.54,-261.63],[65.23,-263.51],[70.99,-265.49],[76.83,-267.57],[82.78,-269.73],[88.83,-271.97],[95.0,-274.27],[101.29,-276.61],[107.7,-279.0],[114.25,-281.41],[120.92,-283.82],[127.73,-286.23],[134.68,-288.62],[141.76,-290.97],[148.96,-293.26],[156.29,-295.48],[163.73,-297.62],[171.28,-299.65],[178.93,-301.57],[186.67,-303.36],[194.48,-304.99],[202.35,-306.47],[210.26,-307.78],[218.21,-308.9],[226.17,-309.84],[234.13,-310.56],[242.06,-311.08],[249.96,-311.38],[257.8,-311.46],[265.56,-311.32],[273.24,-310.95],[280.81,-310.34],[288.25,-309.52],[295.55,-308.46],[302.7,-307.18],[309.69,-305.69],[316.49,-303.98],[323.1,-302.07],[329.52,-299.96],[335.73,-297.67],[341.73,-295.2],[347.51,-292.57],[353.07,-289.78],[358.42,-286.86],[363.55,-283.81],[368.48,-280.64],[373.19,-277.38],[377.7,-274.03],[382.02,-270.61],[386.17,-267.13],[390.14,-263.61],[393.95,-260.06],[397.62,-256.49],[401.17,-252.92],[404.6,-249.35],[407.93,-245.8],[411.19,-242.28],[414.38,-238.79],[417.53,-235.35],[420.65,-231.96],[423.75,-228.63],[426.86,-225.35],[429.99,-222.15],[433.14,-219.01],[436.35,-215.94],[439.6,-212.95],[442.93,-210.02],[446.32,-207.16],[449.8,-204.37],[453.37,-201.64],[457.02,-198.97],[460.75,-196.35],[464.58,-193.78],[468.49,-191.26],[472.48,-188.77],[476.54,-186.3],[480.67,-183.86],[484.84,-181.44],[489.05,-179.02],[493.29,-176.6],[497.54,-174.17],[501.78,-171.72],[505.99,-169.26],[510.15,-166.76],[514.25,-164.24],[518.26,-161.67],[522.16,-159.06],[525.93,-156.4],[529.55,-153.69],[533.0,-150.92],[536.26,-148.1],[539.31,-145.22],[542.13,-142.28],[544.71,-139.29],[547.02,-136.24],[549.06,-133.13],[550.82,-129.98],[552.28,-126.77],[553.43,-123.52],[554.28,-120.23],[554.82,-116.91],[555.04,-113.55],[554.95,-110.18],[554.56,-106.78],[553.87,-103.37],[552.88,-99.96],[551.62,-96.55],[550.1,-93.14],[548.33,-89.75],[546.33,-86.37],[544.12,-83.02],[541.73,-79.7],[539.18,-76.41],[536.49,-73.16],[533.7,-69.95],[530.82,-66.79],[527.89,-63.67],[524.94,-60.6],[521.99,-57.58],[519.08,-54.6],[516.23,-51.68],[513.47,-48.8],[510.83,-45.96],[508.34,-43.17],[506.02,-40.41],[503.89,-37.69],[501.97,-35.0]],[[506.87,-35.0],[505.19,-32.3],[503.76,-29.62],[502.58,-26.94],[501.68,-24.28],[501.07,-21.61],[500.74,-18.94],[500.71,-16.25],[500.97,-13.54],[501.53,-10.8],[502.39,-8.02],[503.53,-5.2],[504.95,-2.34],[506.63,0.58],[508.56,3.56],[510.72,6.6],[513.09,9.7],[515.65,12.88],[518.37,16.13],[521.24,19.45],[524.21,22.85],[527.27,26.33],[530.38,29.87],[533.52,33.49],[536.65,37.18],[539.73,40.94],[542.75,44.76],[545.66,48.63],[548.45,52.56],[551.07,56.53],[553.49,60.53],[555.7,64.57],[557.67,68.62],[559.37,72.69],[560.78,76.76],[561.88,80.82],[562.65,84.86],[563.08,88.88],[563.15,92.86],[562.86,96.8],[562.19,100.68],[561.15,104.5],[559.72,108.25],[557.91,111.92],[555.73,115.51],[553.17,119.0],[550.24,122.39],[546.96,125.68],[543.34,128.85],[539.38,131.92],[535.11,134.88],[530.55,137.72],[525.7,140.44],[520.6,143.06],[515.26,145.55],[509.7,147.94],[503.95,150.23],[498.03,152.41],[491.96,154.49],[485.76,156.48],[479.46,158.39],[473.07,160.23],[466.62,161.99],[460.13,163.69],[453.61,165.35],[447.09,166.96],[440.57,168.53],[434.08,170.08],[427.62,171.62],[421.2,173.15],[414.84,174.68],[408.55,176.22],[402.31,177.77],[396.15,179.35],[390.06,180.96],[384.05,182.61],[378.1,184.29],[372.22,186.02],[366.41,187.79],[360.65,189.61],[354.94,191.48],[349.27,193.39],[343.64,195.35],[338.02,197.36],[332.42,199.39],[326.82,201.47],[321.21,203.56],[315.57,205.68],[309.91,207.81],[304.2,209.94],[298.44,212.06],[292.61,214.16],[286.72,216.23],[280.74,218.26],[274.68,220.24],[268.53,222.15],[262.28,223.98],[255.94,225.72],[249.49,227.36],[242.95,228.88],[236.3,230.27],[229.56,231.52],[222.73,232.63],[215.81,233.57],[208.81,234.34],[201.74,234.94],[194.61,235.35],[187.42,235.57],[180.2,235.59],[172.94,235.41],[165.67,235.04],[158.4,234.46],[151.14,233.67],[143.9,232.69],[136.7,231.51],[129.55,230.14],[122.46,228.58],[115.45,226.84],[108.53,224.93],[101.71,222.86],[95.0,220.64],[88.41,218.28],[81.94,215.8],[75.61,213.21],[69.42,210.52],[63.37,207.75],[57.46,204.91],[51.7,202.02],[46.09,199.1],[40.61,196.16],[35.27,193.22],[30.06,190.3],[24.97,187.41],[20.0,184.56],[15.13,181.77],[10.36,179.05],[5.66,176.42],[1.03,173.89],[-3.54,171.47],[-8.08,169.17],[-12.6,167.0],[-17.11,164.96],[-21.63,163.06],[-26.17,161.3],[-30.76,159.7],[-35.4,158.24],[-40.12,156.94],[-44.92,155.78],[-49.81,154.77],[-54.82,153.9],[-59.94,153.16],[-65.19,152.56],[-70.58,152.08],[-76.11,151.71],[-81.79,151.45],[-87.62,151.28],[-93.59,151.19],[-99.71,151.17],[-105.98,151.2],[-112.39,151.28],[-118.93,151.39],[-125.59,151.51],[-132.37,151.64],[-139.25,151.75],[-146.21,151.84],[-153.26,151.9],[-160.36,151.9],[-167.5,151.84],[-174.67,151.71],[-181.84,151.49],[-189.0,151.18],[-196.13,150.76],[-203.2,150.24],[-210.21,149.6],[-217.12,148.83],[-223.93,147.94],[-230.61,146.91],[-237.15,145.75],[-243.54,144.45],[-249.75,143.02],[-255.78,141.46],[-261.62,139.76],[-267.26,137.93],[-272.68,135.97],[-277.89,133.89],[-282.88,131.7],[-287.65,129.4],[-292.2,126.99],[-296.53,124.49],[-300.65,121.9],[-304.56,119.23],[-308.28,116.48],[-311.81,113.68],[-315.17,110.82],[-318.37,107.91],[-321.43,104.97],[-324.35,101.99],[-327.17,98.99],[-329.9,95.98],[-332.56,92.96],[-335.16,89.93],[-337.73,86.91],[-340.3,83.89],[-342.87,80.88],[-345.47,77.89],[-348.11,74.92],[-350.82,71.97],[-353.61,69.03],[-356.5,66.12],[-359.5,63.23],[-362.62,60.35],[-365.87,57.49],[-369.26,54.65],[-372.79,51.81],[-376.48,48.99],[-380.31,46.16],[-384.29,43.34],[-388.42,40.51],[-392.68,37.67],[-397.08,34.81],[-401.59,31.93],[-406.2,29.03],[-410.91,26.1],[-415.68,23.13],[-420.5,20.12],[-425.35,17.07],[-430.2,13.96],[-435.02,10.81],[-439.8,7.61],[-444.5,4.35],[-449.1,1.03],[-453.56,-2.34],[-457.86,-5.77],[-461.97,-9.26],[-465.85,-12.8],[-469.48,-16.39],[-472.84,-20.03],[-475.89,-23.72],[-478.61,-27.44],[-480.97,-31.21],[-482.96,-35.0],[-484.56,-38.82],[-485.74,-42.65],[-486.49,-46.49],[-486.79,-50.34],[-486.65,-54.18],[-486.04,-58.0],[-484.97,-61.81],[-483.44,-65.58],[-481.44,-69.32],[-478.98,-73.01],[-476.06,-76.65],[-472.7,-80.23],[-468.91,-83.74],[-464.7,-87.18],[-460.1,-90.54],[-455.12,-93.82],[-449.78,-97.01],[-444.11,-100.11],[-438.14,-103.11],[-431.89,-106.02],[-425.4,-108.83],[-418.69,-111.54],[-411.79,-114.16],[-404.74,-116.68],[-397.57,-119.11],[-390.31,-121.45],[-382.99,-123.7],[-375.64,-125.88],[-368.3,-127.98],[-360.99,-130.01],[-353.75,-131.98],[-346.59,-133.9],[-339.54,-135.77],[-332.63,-137.6],[-325.88,-139.41],[-319.3,-141.19],[-312.91,-142.96],[-306.73,-144.72],[-300.77,-146.49],[-295.03,-148.27],[-289.52,-150.08],[-284.25,-151.91],[-279.22,-153.77],[-274.42,-155.68],[-269.85,-157.63],[-265.51,-159.64],[-261.38,-161.69],[-257.46,-163.81],[-253.73,-165.99],[-250.18,-168.23],[-246.79,-170.54],[-243.54,-172.9],[-240.43,-175.33],[-237.42,-177.82],[-234.5,-180.36],[-231.64,-182.95],[-228.83,-185.58],[-226.04,-188.25],[-223.26,-190.96],[-220.46,-193.69],[-217.63,-196.43],[-214.73,-199.19],[-211.77,-201.94],[-208.71,-204.68],[-205.55,-207.4],[-202.27,-210.09],[-198.86,-212.73],[-195.3,-215.33],[-191.6,-217.87],[-187.73,-220.35],[-183.7,-222.74],[-179.5,-225.05],[-175.12,-227.27],[-170.58,-229.38],[-165.87,-231.4],[-161.0,-233.3],[-155.96,-235.08],[-150.78,-236.75],[-145.44,-238.3],[-139.98,-239.73],[-134.38,-241.03],[-128.67,-242.22],[-122.86,-243.29],[-116.95,-244.25],[-110.97,-245.1],[-104.93,-245.85],[-98.83,-246.5],[-92.69,-247.06],[-86.53,-247.54],[-80.35,-247.95],[-74.18,-248.31],[-68.01,-248.61],[-61.86,-248.88],[-55.73,-249.12],[-49.64,-249.34],[-43.59,-249.56],[-37.59,-249.8],[-31.64,-250.05],[-25.73,-250.34],[-19.89,-250.68],[-14.09,-251.07],[-8.34,-251.53],[-2.64,-252.07],[3.01,-252.69],[8.63,-253.41],[14.23,-254.23],[19.8,-255.16],[25.35,-256.2],[30.91,-257.35],[36.47,-258.62],[42.06,-260.01],[47.67,-261.51],[53.33,-263.14],[59.04,-264.87],[64.81,-266.71],[70.66,-268.65],[76.59,-270.69],[82.62,-272.81],[88.75,-275.01],[95.0,-277.27],[101.37,-279.59],[107.85,-281.94],[114.47,-284.32],[121.22,-286.72],[128.11,-289.1],[135.13,-291.47],[142.28,-293.8],[149.55,-296.09],[156.95,-298.3],[164.47,-300.43],[172.09,-302.46],[179.82,-304.38],[187.63,-306.17],[195.52,-307.81],[203.46,-309.3],[211.46,-310.61],[219.49,-311.75],[227.53,-312.69],[235.57,-313.43],[243.59,-313.95],[251.57,-314.27],[259.5,-314.35],[267.35,-314.22],[275.12,-313.85],[282.77,-313.25],[290.3,-312.42],[297.68,-311.36],[304.91,-310.08],[311.97,-308.57],[318.85,-306.85],[325.54,-304.92],[332.02,-302.79],[338.29,-300.47],[344.34,-297.96],[350.18,-295.29],[355.78,-292.46],[361.17,-289.48],[366.33,-286.38],[371.27,-283.15],[375.99,-279.82],[380.51,-276.4],[384.82,-272.9],[388.94,-269.35],[392.89,-265.74],[396.66,-262.1],[400.29,-258.45],[403.78,-254.78],[407.14,-251.11],[410.4,-247.47],[413.57,-243.84],[416.67,-240.26],[419.72,-236.71],[422.73,-233.22],[425.72,-229.79],[428.71,-226.42],[431.72,-223.11],[434.75,-219.88],[437.82,-216.72],[440.94,-213.64],[444.13,-210.62],[447.4,-207.69],[450.74,-204.82],[454.18,-202.02],[457.7,-199.28],[461.32,-196.6],[465.03,-193.97],[468.83,-191.4],[472.72,-188.86],[476.68,-186.36],[480.72,-183.89],[484.83,-181.43],[488.98,-178.99],[493.17,-176.55],[497.38,-174.11],[501.59,-171.66],[505.79,-169.19],[509.96,-166.7],[514.07,-164.18],[518.11,-161.63],[522.06,-159.03],[525.89,-156.39],[529.59,-153.7],[533.12,-150.95],[536.48,-148.15],[539.64,-145.3],[542.59,-142.39],[545.3,-139.42],[547.76,-136.4],[549.95,-133.32],[551.87,-130.19],[553.5,-127.02],[554.83,-123.79],[555.86,-120.53],[556.58,-117.22],[556.99,-113.89],[557.09,-110.53],[556.89,-107.15],[556.39,-103.75],[555.59,-100.34],[554.52,-96.94],[553.17,-93.53],[551.58,-90.14],[549.75,-86.76],[547.7,-83.4],[545.47,-80.07],[543.06,-76.77],[540.51,-73.51],[537.84,-70.28],[535.09,-67.1],[532.26,-63.96],[529.41,-60.86],[526.55,-57.82],[523.71,-54.82],[520.93,-51.86],[518.23,-48.95],[515.64,-46.09],[513.18,-43.26],[510.89,-40.48],[508.77,-37.72],[506.87,-35.0]],[[511.98,-35.0],[510.31,-32.27],[508.88,-29.55],[507.7,-26.84],[506.79,-24.14],[506.15,-21.44],[505.8,-18.74],[505.75,-16.01],[505.99,-13.27],[506.53,-10.5],[507.36,-7.69],[508.47,-4.84],[509.87,-1.95],[511.53,1.0],[513.44,4.01],[515.59,7.08],[517.95,10.22],[520.51,13.43],[523.24,16.72],[526.12,20.08],[529.11,23.51],[532.19,27.02],[535.33,30.61],[538.5,34.27],[541.67,38.01],[544.81,41.81],[547.88,45.67],[550.85,49.6],[553.7,53.57],[556.39,57.6],[558.89,61.66],[561.18,65.75],[563.22,69.87],[565.0,73.99],[566.49,78.13],[567.67,82.25],[568.53,86.37],[569.03,90.46],[569.18,94.51],[568.96,98.52],[568.36,102.47],[567.37,106.37],[565.99,110.19],[564.23,113.93],[562.08,117.58],[559.55,121.14],[556.64,124.6],[553.36,127.95],[549.73,131.19],[545.76,134.32],[541.46,137.33],[536.85,140.22],[531.96,142.99],[526.79,145.64],[521.37,148.18],[515.72,150.6],[509.87,152.91],[503.83,155.1],[497.63,157.2],[491.3,159.2],[484.85,161.11],[478.31,162.93],[471.7,164.68],[465.03,166.36],[458.34,167.99],[451.63,169.56],[444.92,171.09],[438.23,172.6],[431.57,174.08],[424.96,175.54],[418.4,177.01],[411.9,178.48],[405.47,179.96],[399.11,181.46],[392.83,182.98],[386.62,184.54],[380.49,186.14],[374.43,187.77],[368.44,189.46],[362.51,191.18],[356.64,192.96],[350.82,194.78],[345.04,196.65],[339.28,198.56],[333.55,200.51],[327.83,202.5],[322.11,204.52],[316.38,206.56],[310.62,208.62],[304.83,210.68],[299.0,212.74],[293.11,214.78],[287.15,216.81],[281.13,218.79],[275.03,220.73],[268.84,222.61],[262.56,224.42],[256.19,226.14],[249.73,227.76],[243.17,229.28],[236.52,230.67],[229.77,231.93],[222.93,233.05],[216.01,234.01],[209.01,234.8],[201.93,235.43],[194.8,235.87],[187.61,236.13],[180.39,236.19],[173.13,236.06],[165.85,235.73],[158.57,235.19],[151.3,234.46],[144.05,233.53],[136.84,232.4],[129.67,231.07],[122.56,229.56],[115.53,227.87],[108.59,226.01],[101.74,223.98],[95.0,221.8],[88.38,219.48],[81.88,217.04],[75.51,214.47],[69.29,211.81],[63.2,209.07],[57.26,206.25],[51.46,203.38],[45.8,200.47],[40.29,197.54],[34.91,194.6],[29.66,191.68],[24.54,188.78],[19.53,185.93],[14.63,183.13],[9.83,180.4],[5.1,177.76],[0.44,175.21],[-4.16,172.77],[-8.72,170.44],[-13.26,168.25],[-17.8,166.19],[-22.34,164.27],[-26.91,162.49],[-31.51,160.87],[-36.18,159.39],[-40.91,158.07],[-45.73,156.89],[-50.65,155.87],[-55.68,154.99],[-60.84,154.25],[-66.12,153.65],[-71.55,153.17],[-77.12,152.8],[-82.84,152.55],[-88.71,152.39],[-94.74,152.32],[-100.92,152.32],[-107.26,152.39],[-113.74,152.5],[-120.37,152.64],[-127.12,152.81],[-134.0,152.98],[-140.99,153.14],[-148.07,153.29],[-155.24,153.39],[-162.48,153.45],[-169.77,153.45],[-177.09,153.38],[-184.42,153.23],[-191.75,152.98],[-199.05,152.63],[-206.31,152.17],[-213.5,151.59],[-220.62,150.89],[-227.62,150.06],[-234.51,149.09],[-241.26,147.98],[-247.85,146.74],[-254.28,145.36],[-260.52,143.84],[-266.57,142.18],[-272.41,140.39],[-278.04,138.46],[-283.45,136.41],[-288.63,134.24],[-293.59,131.95],[-298.32,129.55],[-302.82,127.05],[-307.1,124.46],[-311.17,121.78],[-315.02,119.02],[-318.68,116.19],[-322.15,113.3],[-325.45,110.36],[-328.59,107.38],[-331.59,104.36],[-334.47,101.31],[-337.23,98.24],[-339.91,95.16],[-342.53,92.07],[-345.09,88.98],[-347.63,85.89],[-350.17,82.82],[-352.71,79.75],[-355.29,76.7],[-357.92,73.67],[-360.62,70.66],[-363.41,67.67],[-366.29,64.69],[-369.28,61.74],[-372.4,58.8],[-375.64,55.88],[-379.03,52.97],[-382.56,50.07],[-386.23,47.17],[-390.05,44.28],[-394.02,41.38],[-398.11,38.48],[-402.34,35.56],[-406.69,32.62],[-411.14,29.66],[-415.68,26.67],[-420.3,23.65],[-424.97,20.6],[-429.68,17.5],[-434.39,14.36],[-439.09,11.16],[-443.75,7.92],[-448.34,4.63],[-452.84,1.28],[-457.21,-2.12],[-461.42,-5.58],[-465.45,-9.09],[-469.27,-12.66],[-472.85,-16.28],[-476.16,-19.94],[-479.17,-23.65],[-481.86,-27.4],[-484.21,-31.19],[-486.18,-35.0],[-487.77,-38.84],[-488.95,-42.69],[-489.7,-46.56],[-490.01,-50.42],[-489.88,-54.28],[-489.29,-58.13],[-488.23,-61.96],[-486.71,-65.76],[-484.72,-69.52],[-482.27,-73.23],[-479.36,-76.89],[-476.01,-80.49],[-472.22,-84.03],[-468.01,-87.49],[-463.4,-90.87],[-458.4,-94.17],[-453.04,-97.38],[-447.35,-100.5],[-441.34,-103.52],[-435.05,-106.44],[-428.5,-109.27],[-421.73,-111.99],[-414.77,-114.62],[-407.64,-117.15],[-400.39,-119.59],[-393.03,-121.93],[-385.62,-124.19],[-378.17,-126.37],[-370.72,-128.46],[-363.29,-130.49],[-355.93,-132.45],[-348.65,-134.36],[-341.47,-136.22],[-334.44,-138.04],[-327.55,-139.82],[-320.85,-141.58],[-314.33,-143.33],[-308.03,-145.08],[-301.94,-146.82],[-296.08,-148.58],[-290.46,-150.36],[-285.08,-152.16],[-279.95,-154.0],[-275.05,-155.89],[-270.4,-157.82],[-265.98,-159.8],[-261.78,-161.84],[-257.8,-163.94],[-254.02,-166.1],[-250.44,-168.33],[-247.02,-170.63],[-243.77,-172.99],[-240.65,-175.42],[-237.64,-177.91],[-234.74,-180.46],[-231.92,-183.07],[-229.15,-185.73],[-226.41,-188.43],[-223.69,-191.17],[-220.96,-193.94],[-218.2,-196.73],[-215.4,-199.54],[-212.52,-202.35],[-209.57,-205.15],[-206.51,-207.94],[-203.34,-210.71],[-200.04,-213.45],[-196.59,-216.13],[-193.0,-218.77],[-189.25,-221.34],[-185.33,-223.84],[-181.24,-226.26],[-176.98,-228.59],[-172.54,-230.82],[-167.93,-232.95],[-163.15,-234.97],[-158.21,-236.87],[-153.11,-238.66],[-147.85,-240.33],[-142.45,-241.88],[-136.91,-243.31],[-131.25,-244.61],[-125.48,-245.8],[-119.6,-246.87],[-113.64,-247.83],[-107.61,-248.68],[-101.51,-249.43],[-95.37,-250.08],[-89.19,-250.65],[-82.99,-251.15],[-76.77,-251.58],[-70.56,-251.95],[-64.35,-252.28],[-58.17,-252.58],[-52.01,-252.85],[-45.89,-253.12],[-39.8,-253.38],[-33.76,-253.67],[-27.77,-253.98],[-21.83,-254.33],[-15.94,-254.73],[-10.09,-255.19],[-4.29,-255.72],[1.48,-256.33],[7.2,-257.03],[12.9,-257.83],[18.58,-258.73],[24.24,-259.74],[29.9,-260.85],[35.57,-262.09],[41.25,-263.43],[46.96,-264.9],[52.72,-266.48],[58.52,-268.16],[64.39,-269.96],[70.32,-271.86],[76.34,-273.85],[82.46,-275.93],[88.67,-278.08],[95.0,-280.31],[101.44,-282.58],[108.01,-284.9],[114.7,-287.25],[121.53,-289.61],[128.48,-291.97],[135.57,-294.31],[142.79,-296.62],[150.14,-298.89],[157.61,-301.09],[165.2,-303.21],[172.89,-305.23],[180.69,-307.14],[188.57,-308.93],[196.53,-310.57],[204.56,-312.06],[212.63,-313.38],[220.74,-314.52],[228.86,-315.47],[236.98,-316.21],[245.08,-316.75],[253.14,-317.07],[261.15,-317.16],[269.09,-317.03],[276.94,-316.67],[284.67,-316.07],[292.28,-315.24],[299.75,-314.18],[307.06,-312.89],[314.19,-311.37],[321.14,-309.64],[327.9,-307.69],[334.45,-305.53],[340.78,-303.18],[346.89,-300.64],[352.77,-297.93],[358.42,-295.06],[363.84,-292.04],[369.02,-288.87],[373.98,-285.59],[378.72,-282.2],[383.23,-278.71],[387.54,-275.14],[391.65,-271.5],[395.57,-267.82],[399.31,-264.09],[402.89,-260.35],[406.32,-256.59],[409.62,-252.83],[412.81,-249.09],[415.9,-245.37],[418.91,-241.68],[421.86,-238.04],[424.76,-234.45],[427.64,-230.92],[430.51,-227.45],[433.39,-224.05],[436.3,-220.73],[439.24,-217.48],[442.23,-214.3],[445.29,-211.21],[448.42,-208.19],[451.63,-205.24],[454.94,-202.37],[458.33,-199.56],[461.83,-196.83],[465.42,-194.14],[469.11,-191.52],[472.9,-188.94],[476.78,-186.4],[480.73,-183.89],[484.76,-181.41],[488.85,-178.94],[492.99,-176.49],[497.16,-174.04],[501.35,-171.58],[505.54,-169.11],[509.71,-166.62],[513.84,-164.11],[517.92,-161.57],[521.91,-158.99],[525.8,-156.36],[529.57,-153.69],[533.2,-150.97],[536.66,-148.2],[539.93,-145.37],[543.01,-142.49],[545.86,-139.55],[548.46,-136.56],[550.82,-133.51],[552.9,-130.41],[554.71,-127.26],[556.22,-124.06],[557.44,-120.82],[558.35,-117.54],[558.96,-114.22],[559.26,-110.88],[559.25,-107.51],[558.95,-104.13],[558.35,-100.73],[557.47,-97.33],[556.31,-93.93],[554.9,-90.54],[553.25,-87.16],[551.38,-83.8],[549.31,-80.46],[547.06,-77.15],[544.66,-73.87],[542.13,-70.62],[539.5,-67.42],[536.79,-64.26],[534.04,-61.14],[531.28,-58.07],[528.53,-55.04],[525.82,-52.06],[523.18,-49.12],[520.64,-46.22],[518.22,-43.36],[515.96,-40.55],[513.87,-37.76],[511.98,-35.0]],[[517.31,-35.0],[515.65,-32.23],[514.22,-29.48],[513.03,-26.74],[512.11,-24.0],[511.46,-21.27],[511.09,-18.53],[511.01,-15.77],[511.22,-12.99],[511.73,-10.19],[512.53,-7.35],[513.62,-4.47],[514.99,-1.54],[516.62,1.44],[518.51,4.48],[520.64,7.59],[522.99,10.76],[525.53,14.01],[528.26,17.32],[531.13,20.72],[534.13,24.19],[537.23,27.74],[540.39,31.36],[543.58,35.07],[546.79,38.84],[549.96,42.69],[553.08,46.6],[556.1,50.57],[559.0,54.6],[561.75,58.67],[564.32,62.79],[566.67,66.94],[568.79,71.11],[570.64,75.3],[572.2,79.5],[573.46,83.69],[574.38,87.87],[574.96,92.02],[575.18,96.15],[575.02,100.23],[574.48,104.25],[573.54,108.21],[572.22,112.11],[570.5,115.92],[568.38,119.64],[565.87,123.27],[562.97,126.79],[559.7,130.2],[556.07,133.51],[552.08,136.69],[547.75,139.76],[543.1,142.7],[538.15,145.51],[532.91,148.21],[527.41,150.78],[521.68,153.23],[515.72,155.56],[509.57,157.77],[503.25,159.88],[496.78,161.89],[490.19,163.79],[483.49,165.61],[476.72,167.34],[469.88,169.0],[463.01,170.59],[456.11,172.13],[449.22,173.62],[442.33,175.08],[435.48,176.5],[428.66,177.91],[421.9,179.31],[415.2,180.7],[408.57,182.11],[402.02,183.52],[395.54,184.97],[389.14,186.44],[382.82,187.94],[376.57,189.49],[370.41,191.07],[364.31,192.71],[358.28,194.39],[352.3,196.12],[346.38,197.89],[340.49,199.71],[334.63,201.58],[328.79,203.48],[322.96,205.41],[317.13,207.38],[311.28,209.36],[305.41,211.35],[299.5,213.35],[293.54,215.33],[287.53,217.3],[281.46,219.24],[275.32,221.14],[269.1,222.99],[262.79,224.77],[256.4,226.47],[249.92,228.09],[243.35,229.6],[236.68,230.99],[229.93,232.26],[223.09,233.38],[216.17,234.36],[209.17,235.19],[202.1,235.84],[194.97,236.32],[187.78,236.61],[180.55,236.72],[173.29,236.63],[166.02,236.35],[158.73,235.87],[151.45,235.18],[144.19,234.3],[136.97,233.23],[129.78,231.96],[122.66,230.5],[115.61,228.86],[108.64,227.05],[101.77,225.08],[95.0,222.94],[88.35,220.67],[81.82,218.26],[75.42,215.74],[69.15,213.11],[63.03,210.39],[57.04,207.6],[51.2,204.75],[45.51,201.86],[39.95,198.95],[34.54,196.02],[29.25,193.1],[24.09,190.21],[19.05,187.35],[14.11,184.55],[9.27,181.81],[4.51,179.15],[-0.18,176.59],[-4.81,174.14],[-9.41,171.8],[-13.97,169.58],[-18.53,167.5],[-23.1,165.56],[-27.69,163.77],[-32.32,162.12],[-37.01,160.63],[-41.77,159.29],[-46.62,158.1],[-51.56,157.06],[-56.62,156.17],[-61.8,155.43],[-67.12,154.82],[-72.58,154.34],[-78.19,153.98],[-83.96,153.73],[-89.88,153.59],[-95.97,153.53],[-102.21,153.56],[-108.62,153.65],[-115.18,153.79],[-121.88,153.96],[-128.73,154.17],[-135.71,154.38],[-142.8,154.59],[-150.01,154.78],[-157.3,154.94],[-164.67,155.06],[-172.1,155.11],[-179.57,155.1],[-187.06,155.01],[-194.56,154.82],[-202.04,154.54],[-209.48,154.14],[-216.86,153.62],[-224.16,152.98],[-231.37,152.2],[-238.46,151.29],[-245.42,150.25],[-252.22,149.05],[-258.85,147.72],[-265.31,146.24],[-271.56,144.63],[-277.61,142.87],[-283.44,140.97],[-289.05,138.95],[-294.43,136.79],[-299.57,134.52],[-304.48,132.13],[-309.16,129.63],[-313.6,127.03],[-317.82,124.34],[-321.81,121.57],[-325.6,118.72],[-329.18,115.8],[-332.58,112.82],[-335.81,109.8],[-338.88,106.74],[-341.81,103.64],[-344.61,100.51],[-347.32,97.37],[-349.94,94.22],[-352.5,91.06],[-355.01,87.91],[-357.51,84.76],[-360.0,81.62],[-362.51,78.49],[-365.06,75.38],[-367.66,72.29],[-370.33,69.22],[-373.1,66.16],[-375.96,63.13],[-378.93,60.11],[-382.03,57.11],[-385.26,54.13],[-388.63,51.15],[-392.14,48.18],[-395.79,45.22],[-399.58,42.25],[-403.5,39.28],[-407.55,36.3],[-411.72,33.3],[-416.01,30.28],[-420.38,27.24],[-424.83,24.17],[-429.35,21.06],[-433.9,17.92],[-438.47,14.74],[-443.03,11.51],[-447.56,8.23],[-452.03,4.9],[-456.42,1.52],[-460.68,-1.92],[-464.81,-5.4],[-468.76,-8.94],[-472.51,-12.53],[-476.02,-16.17],[-479.28,-19.86],[-482.25,-23.59],[-484.91,-27.36],[-487.23,-31.17],[-489.19,-35.0],[-490.76,-38.86],[-491.93,-42.73],[-492.69,-46.62],[-493.01,-50.5],[-492.89,-54.38],[-492.31,-58.25],[-491.27,-62.1],[-489.76,-65.92],[-487.79,-69.7],[-485.36,-73.43],[-482.46,-77.12],[-479.12,-80.74],[-475.34,-84.3],[-471.14,-87.78],[-466.52,-91.19],[-461.52,-94.5],[-456.15,-97.73],[-450.43,-100.87],[-444.4,-103.91],[-438.07,-106.85],[-431.48,-109.69],[-424.66,-112.43],[-417.64,-115.07],[-410.45,-117.61],[-403.12,-120.06],[-395.69,-122.41],[-388.19,-124.67],[-380.65,-126.84],[-373.09,-128.94],[-365.57,-130.96],[-358.09,-132.92],[-350.69,-134.82],[-343.4,-136.67],[-336.25,-138.47],[-329.24,-140.24],[-322.42,-141.99],[-315.78,-143.72],[-309.35,-145.44],[-303.15,-147.16],[-297.18,-148.9],[-291.45,-150.65],[-285.96,-152.43],[-280.73,-154.25],[-275.74,-156.11],[-271.01,-158.02],[-266.51,-159.98],[-262.25,-162.0],[-258.21,-164.09],[-254.39,-166.24],[-250.76,-168.46],[-247.32,-170.75],[-244.05,-173.11],[-240.93,-175.54],[-237.93,-178.04],[-235.05,-180.6],[-232.25,-183.22],[-229.52,-185.9],[-226.84,-188.63],[-224.18,-191.41],[-221.51,-194.22],[-218.83,-197.06],[-216.11,-199.92],[-213.33,-202.79],[-210.47,-205.66],[-207.52,-208.52],[-204.45,-211.37],[-201.26,-214.19],[-197.93,-216.97],[-194.45,-219.7],[-190.81,-222.37],[-187.01,-224.97],[-183.03,-227.5],[-178.88,-229.94],[-174.55,-232.29],[-170.05,-234.54],[-165.36,-236.68],[-160.51,-238.71],[-155.49,-240.62],[-150.31,-242.41],[-144.97,-244.08],[-139.49,-245.63],[-133.88,-247.05],[-128.15,-248.36],[-122.31,-249.54],[-116.37,-250.61],[-110.35,-251.57],[-104.25,-252.42],[-98.1,-253.17],[-91.9,-253.83],[-85.67,-254.41],[-79.42,-254.92],[-73.16,-255.37],[-66.91,-255.76],[-60.66,-256.12],[-54.43,-256.44],[-48.23,-256.75],[-42.07,-257.05],[-35.94,-257.36],[-29.86,-257.7],[-23.82,-258.06],[-17.82,-258.47],[-11.87,-258.93],[-5.96,-259.45],[-0.1,-260.05],[5.74,-260.73],[11.55,-261.5],[17.33,-262.37],[23.1,-263.35],[28.87,-264.43],[34.64,-265.62],[40.43,-266.92],[46.25,-268.34],[52.1,-269.87],[58.0,-271.51],[63.96,-273.26],[69.99,-275.1],[76.09,-277.05],[82.29,-279.07],[88.59,-281.18],[95.0,-283.36],[101.52,-285.59],[108.16,-287.86],[114.93,-290.17],[121.83,-292.5],[128.85,-294.82],[136.01,-297.14],[143.3,-299.42],[150.72,-301.66],[158.26,-303.84],[165.91,-305.95],[173.68,-307.96],[181.54,-309.86],[189.5,-311.64],[197.53,-313.28],[205.63,-314.76],[213.77,-316.08],[221.95,-317.22],[230.15,-318.17],[238.35,-318.92],[246.53,-319.47],[254.67,-319.79],[262.76,-319.89],[270.78,-319.76],[278.7,-319.4],[286.52,-318.8],[294.2,-317.97],[301.75,-316.91],[309.13,-315.61],[316.34,-314.08],[323.37,-312.33],[330.19,-310.37],[336.8,-308.19],[343.19,-305.81],[349.35,-303.25],[355.28,-300.5],[360.97,-297.58],[366.43,-294.51],[371.64,-291.3],[376.62,-287.96],[381.37,-284.5],[385.89,-280.95],[390.19,-277.31],[394.28,-273.6],[398.17,-269.84],[401.88,-266.03],[405.42,-262.2],[408.8,-258.35],[412.03,-254.5],[415.15,-250.67],[418.16,-246.85],[421.08,-243.07],[423.93,-239.33],[426.74,-235.64],[429.51,-232.01],[432.26,-228.45],[435.02,-224.96],[437.8,-221.54],[440.61,-218.2],[443.47,-214.94],[446.4,-211.76],[449.4,-208.67],[452.48,-205.65],[455.65,-202.7],[458.92,-199.83],[462.3,-197.03],[465.78,-194.3],[469.36,-191.62],[473.04,-188.99],[476.82,-186.41],[480.7,-183.87],[484.65,-181.36],[488.68,-178.88],[492.77,-176.41],[496.9,-173.95],[501.07,-171.48],[505.25,-169.02],[509.42,-166.53],[513.57,-164.03],[517.68,-161.5],[521.72,-158.93],[525.67,-156.32],[529.52,-153.68],[533.23,-150.98],[536.8,-148.24],[540.19,-145.44],[543.4,-142.59],[546.39,-139.68],[549.15,-136.71],[551.67,-133.69],[553.93,-130.62],[555.91,-127.5],[557.62,-124.33],[559.03,-121.11],[560.14,-117.86],[560.95,-114.56],[561.45,-111.24],[561.65,-107.89],[561.55,-104.52],[561.16,-101.13],[560.48,-97.74],[559.53,-94.34],[558.31,-90.95],[556.85,-87.57],[555.16,-84.2],[553.26,-80.85],[551.18,-77.53],[548.93,-74.24],[546.55,-70.98],[544.05,-67.75],[541.47,-64.57],[538.84,-61.43],[536.18,-58.33],[533.52,-55.27],[530.89,-52.26],[528.32,-49.29],[525.84,-46.36],[523.47,-43.47],[521.25,-40.61],[519.19,-37.79],[517.31,-35.0]]],"level":[0.0,0.0101,0.0202,0.0303,0.0404,0.0505,0.0606,0.0707,0.0808,0.0909,0.101,0.1111,0.1212,0.1313,0.1414,0.1515,0.1616,0.1717,0.1818,0.1919,0.202,0.2121,0.2222,0.2323,0.2424,0.2525,0.2626,0.2727,0.2828,0.2929,0.303,0.3131,0.3232,0.3333,0.3434,0.3535,0.3636,0.3737,0.3838,0.3939,0.404,0.4141,0.4242,0.4343,0.4444,0.4545,0.4646,0.4747,0.4848,0.4949,0.5051,0.5152,0.5253,0.5354,0.5455,0.5556,0.5657,0.5758,0.5859,0.596,0.6061,0.6162,0.6263,0.6364,0.6465,0.6566,0.6667,0.6768,0.6869,0.697,0.7071,0.7172,0.7273,0.7374,0.7475,0.7576,0.7677,0.7778,0.7879,0.798,0.8081,0.8182,0.8283,0.8384,0.8485,0.8586,0.8687,0.8788,0.8889,0.899,0.9091,0.9192,0.9293,0.9394,0.9495,0.9596,0.9697,0.9798,0.9899,1.0]}}}]} diff --git a/crates/latkit-cli/examples/cli-gallery/tides.json b/crates/latkit-cli/examples/cli-gallery/tides.json new file mode 100644 index 00000000..67f2f0d0 --- /dev/null +++ b/crates/latkit-cli/examples/cli-gallery/tides.json @@ -0,0 +1,38 @@ +{ + "space": { + "plane": { + "grid": "off" + } + }, + "ease": 0, + "theme": { + "background": "#080f1c", + "text": "#c7d5e4", + "font": "sans-serif", + "fontSize": 13, + "halo": 0, + "flow": "#d9fff0a0", + "flowSpacing": 100 + }, + "title": "03 / TIDAL FORMS", + "subtitle": "100 closed contours / 48,100 coordinates / harmonic geometry", + "marks": [ + { + "lines": { + "of": [ + "art", + "Contour" + ], + "width": 1.15, + "color": { + "colormap": "turbo", + "value": "level", + "domain": [ + 0, + 1 + ] + } + } + } + ] +} diff --git a/crates/latkit-cli/examples/cli-gallery/tides.png b/crates/latkit-cli/examples/cli-gallery/tides.png new file mode 100644 index 00000000..7dce140d Binary files /dev/null and b/crates/latkit-cli/examples/cli-gallery/tides.png differ diff --git a/crates/latkit-cli/examples/wecc240-fault/README.md b/crates/latkit-cli/examples/wecc240-fault/README.md new file mode 100644 index 00000000..bc4cbecd --- /dev/null +++ b/crates/latkit-cli/examples/wecc240-fault/README.md @@ -0,0 +1,75 @@ +# WECC240 fault — GridKit + Latkit CLI + +[Preview](preview.png) · The video is not in Git: [reproduce it](#reproduce) to write +`animation.mp4` here. + +The reference WECC240 fault is applied at **John Day, bus 4005**, at 1.00 s and +cleared at 1.15 s, with fault impedance R = 0, X = 0.01 p.u. The model contains +243 buses, 447 branches, 103 synchronous machines, and 37 inverter groups. +GridKit simulates 0–10 s; Latkit renders **1920 × 1080, 60 fps, 1,561 frames** +into a 26.017-second H.264 MP4. Playback slows to 0.1× around the fault and runs +at 0.5× elsewhere. + +The preview, case, compact recordings, and reproduction scripts are included in +Git. Intermediate CSV and generated CLI inputs stay in `target/`. + +## Reproduce + +From the repository root, with Python 3.10+, Docker, and the image available locally: + +```powershell +python crates/latkit-cli/examples/wecc240-fault/simulate.py +cargo build --locked -p latkit-cli --profile cli +python crates/latkit-cli/examples/wecc240-fault/render.py --preview +python crates/latkit-cli/examples/wecc240-fault/render.py +``` + +Skip the first command to render the included recording without Docker. +`render.py` finds `target/cli/latkit.exe` (or `target/cli/latkit`), then falls back +to an installed `latkit`. Use `--cli PATH` to select another executable, +`--preview --at 1.12` for a still, or `--limit 120 --output target/wecc-preview` +for a short movie. `--prepare-only` writes scene/data/camera/frame inputs under +`target/wecc240-fault/render/` and prints the CLI command. +Native MP4 encoding currently requires Windows; the Python recipes use only +the standard library. State boundaries reuse [`../branch-opening/states.geojson`](../branch-opening/states.geojson). + +## Simulation and display + +The run used `ghcr.io/lukelowry/gridkit:develop-perf`, pinned for execution to: + +```text +sha256:befba9e16edce341888e73c05b9d2c35aedf1357fa18b54c56114dbe25ccd565 +``` + +`simulate.py` resolves the requested tag to its local image ID before running, +with two CPUs and networking disabled. To reproduce with this exact image, pass +that ID through `--image`. The saved [metadata](recording/metadata.json) includes +the image labels, case hashes, solver settings, sample times, and recording hashes. + +Monitors sample at 240 Hz, retaining both sides of fault application and clearing: +2,403 samples total. The map shows bus frequency deviation, estimated with a +20 ms causal filtered derivative of unwrapped voltage angle; switching angle +jumps contribute impulses. Colors saturate at ±0.1 Hz. Height exaggerates this +same quantity with an `asinh` scale; it is a visual displacement. + +The upper plot shows actual GENROU rotor-speed deviation (`omega × 60 Hz`) for +4039_G, the machine with the largest absolute excursion. The lower plot shows +faulted-bus voltage. A white playhead follows simulation time. These are distinct +measurements: estimated bus frequency, rotor speed, and voltage. + +Only monitor selection and monitor names change in the runtime case. +GridKit reports initialization adjustments to small Hygov time constants and +Repca reactive limits; the complete messages are retained in [solver.txt](solver.txt). +`animation.json` and `preview.json` record render settings, timing, and hashes. + +## Source + +`source.case.json` comes from GridKit's +`cases/PhasorDynamics/WECC240/WECC240.case.json`; only line endings are normalized +to LF. Fault parameters match its +`examples/PhasorDynamics/Validation/WECC240/WECC240.solver.json`. +The upstream case README credits the National Laboratory of the Rockies test +case repository. The GridKit notice is retained in [SOURCE-LICENSE.txt](SOURCE-LICENSE.txt). + +This product includes software produced by UT-Battelle, LLC under Contract +No. DE-AC05-00OR22725 with the Department of Energy. diff --git a/crates/latkit-cli/examples/wecc240-fault/SOURCE-LICENSE.txt b/crates/latkit-cli/examples/wecc240-fault/SOURCE-LICENSE.txt new file mode 100644 index 00000000..c58bcc5e --- /dev/null +++ b/crates/latkit-cli/examples/wecc240-fault/SOURCE-LICENSE.txt @@ -0,0 +1,46 @@ +Copyright (c) 2025, UT-Battelle. +All rights reserved. + +GridKit™ version 0.1 + + +Open Source License: + +Subject to the conditions of this License, UT-Battelle, LLC, hereby grants +free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable copyright license to use, copy, modify, +merge, publish, distribute, and/or sublicense copies of the Software. + +1. Redistributions of Software must retain the above open source license grant, +copyright and license notices, this list of conditions, and the disclaimer +listed below. Changes or modifications to, or derivative works of the +Software must be noted with comments and the contributor and organization's +name. If the Software is protected by a proprietary trademark owned by +UT-Battelle, LLC or the Department of Energy, then derivative works of the +Software may not be distributed using the trademark without the prior written +approval of the trademark owner. + +2. Neither the names of Licensor nor the Department of Energy may be used to +endorse or promote products derived from this Software without their specific +prior written permission. + +3. The Software, with or without modification, must include the following +acknowledgment: "This product includes software produced by UT-Battelle, LLC +under Contract No. DE-AC05-00OR22725 with the Department of Energy.” + + + +------------------------------------------------------------------------------- + +DISCLAIMER: + +UT-BATTELLE, LLC, AND THE GOVERNMENT MAKE NO REPRESENTATIONS AND DISCLAIM ALL +WARRANTIES, BOTH EXPRESSED AND IMPLIED. THERE ARE NO EXPRESS OR IMPLIED +WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, OR THAT THE +USE OF THE SOFTWARE WILL NOT INFRINGE ANY PATENT, COPYRIGHT, TRADEMARK, OR +OTHER PROPRIETARY RIGHTS, OR THAT THE SOFTWARE WILL ACCOMPLISH THE INTENDED +RESULTS OR THAT THE SOFTWARE OR ITS USE WILL NOT RESULT IN INJURY OR DAMAGE. +THE USER ASSUMES RESPONSIBILITY FOR ALL LIABILITIES, PENALTIES, FINES, CLAIMS, +CAUSES OF ACTION, AND COSTS AND EXPENSES, CAUSED BY, RESULTING FROM OR ARISING +OUT OF, IN WHOLE OR IN PART THE USE, STORAGE OR DISPOSAL OF THE SOFTWARE. diff --git a/crates/latkit-cli/examples/wecc240-fault/animation.json b/crates/latkit-cli/examples/wecc240-fault/animation.json new file mode 100644 index 00000000..c7e9dce5 --- /dev/null +++ b/crates/latkit-cli/examples/wecc240-fault/animation.json @@ -0,0 +1,97 @@ +{ + "bus_count": 243, + "branch_count": 447, + "machine_count": 103, + "traced_machines": [ + "4039_G" + ], + "traced_bus_ids": [ + 4005 + ], + "events": [ + { + "time": 1.0, + "type": "fault_on", + "bus": 4005, + "R": 0.0, + "X": 0.01 + }, + { + "time": 1.15, + "type": "fault_off", + "bus": 4005 + } + ], + "gridkit_image_id": "sha256:befba9e16edce341888e73c05b9d2c35aedf1357fa18b54c56114dbe25ccd565", + "recording_hashes": { + "frequency.f32": { + "bytes": 2335716, + "sha256": "b7246f9a31c11fbaf71cf2096b56f17eff38d3a95b548e361ebdd7f8dbc5d4f3" + }, + "voltage.f32": { + "bytes": 2335716, + "sha256": "dd22306b958667941a4c81885ba43304105f00cad92db2140132278aac664bf8" + }, + "rotor.f32": { + "bytes": 990036, + "sha256": "53a6ec1b32450176ec3362feb64ca76544f88f3c6ec6bb6811395cd4ec348a39" + } + }, + "frames": 1561, + "fps": 60, + "resolution": [ + 1920, + 1080 + ], + "seconds": 26.016666666666666, + "simulation_start_s": 0.0, + "simulation_end_s": 10.0, + "playback": "0.5x before 0.75 s; 0.1x from 0.75 to 1.5 s; 0.5x thereafter", + "color_domain_hz": [ + -0.1, + 0.1 + ], + "height": "1.4 * asinh(df / 0.01) / asinh(0.1 / 0.01); exaggerated visual displacement", + "render_seconds": 7.429454600031022, + "output_bytes": 45918877, + "command": [ + "/target/cli/latkit.exe", + "render", + "/target/wecc240-fault/render/map.json", + "/target/wecc240-fault/render/rotor.json", + "/target/wecc240-fault/render/voltage.json", + "--data", + "/target/wecc240-fault/render/grid.json", + "--data", + "states=/crates/latkit-cli/examples/branch-opening/states.geojson", + "--panel", + "0,0,0.68,1", + "--panel", + "0.68,0,0.32,0.5", + "--panel", + "0.68,0.5,0.32,0.5", + "--camera", + "/target/wecc240-fault/render/map-camera.json", + "--camera", + "/target/wecc240-fault/render/rotor-camera.json", + "--camera", + "/target/wecc240-fault/render/voltage-camera.json", + "--frames", + "/target/wecc240-fault/render/frames.jsonl", + "--deadline", + "120", + "--insets", + "20,12,12,8", + "--font", + "C:/Windows/Fonts/segoeui.ttf", + "--size", + "1920x1080", + "--fps", + "60", + "--bitrate", + "14000000", + "--output", + "/crates/latkit-cli/examples/wecc240-fault/animation.mp4" + ], + "sha256": "cafe2f8bfbeb7187b22cdd7a35af136cad7d53a2f43aa5f877b86cabde7d987c" +} diff --git a/crates/latkit-cli/examples/wecc240-fault/preview.json b/crates/latkit-cli/examples/wecc240-fault/preview.json new file mode 100644 index 00000000..b7fcbe8d --- /dev/null +++ b/crates/latkit-cli/examples/wecc240-fault/preview.json @@ -0,0 +1,97 @@ +{ + "bus_count": 243, + "branch_count": 447, + "machine_count": 103, + "traced_machines": [ + "4039_G" + ], + "traced_bus_ids": [ + 4005 + ], + "events": [ + { + "time": 1.0, + "type": "fault_on", + "bus": 4005, + "R": 0.0, + "X": 0.01 + }, + { + "time": 1.15, + "type": "fault_off", + "bus": 4005 + } + ], + "gridkit_image_id": "sha256:befba9e16edce341888e73c05b9d2c35aedf1357fa18b54c56114dbe25ccd565", + "recording_hashes": { + "frequency.f32": { + "bytes": 2335716, + "sha256": "b7246f9a31c11fbaf71cf2096b56f17eff38d3a95b548e361ebdd7f8dbc5d4f3" + }, + "voltage.f32": { + "bytes": 2335716, + "sha256": "dd22306b958667941a4c81885ba43304105f00cad92db2140132278aac664bf8" + }, + "rotor.f32": { + "bytes": 990036, + "sha256": "53a6ec1b32450176ec3362feb64ca76544f88f3c6ec6bb6811395cd4ec348a39" + } + }, + "frames": 1, + "fps": 60, + "resolution": [ + 1920, + 1080 + ], + "seconds": 0.016666666666666666, + "simulation_start_s": 1.12, + "simulation_end_s": 1.12, + "playback": "0.5x before 0.75 s; 0.1x from 0.75 to 1.5 s; 0.5x thereafter", + "color_domain_hz": [ + -0.1, + 0.1 + ], + "height": "1.4 * asinh(df / 0.01) / asinh(0.1 / 0.01); exaggerated visual displacement", + "render_seconds": 2.3411011999705806, + "output_bytes": 448738, + "command": [ + "/target/cli/latkit.exe", + "render", + "/target/wecc240-fault/render/map.json", + "/target/wecc240-fault/render/rotor.json", + "/target/wecc240-fault/render/voltage.json", + "--data", + "/target/wecc240-fault/render/grid.json", + "--data", + "states=/crates/latkit-cli/examples/branch-opening/states.geojson", + "--panel", + "0,0,0.68,1", + "--panel", + "0.68,0,0.32,0.5", + "--panel", + "0.68,0.5,0.32,0.5", + "--camera", + "/target/wecc240-fault/render/map-camera.json", + "--camera", + "/target/wecc240-fault/render/rotor-camera.json", + "--camera", + "/target/wecc240-fault/render/voltage-camera.json", + "--at", + "1.12", + "--deadline", + "120", + "--insets", + "20,12,12,8", + "--font", + "C:/Windows/Fonts/segoeui.ttf", + "--size", + "1920x1080", + "--fps", + "60", + "--bitrate", + "14000000", + "--output", + "/crates/latkit-cli/examples/wecc240-fault/preview.png" + ], + "sha256": "e642c2ad8707f50eedf91ccb988ee1e78812f72b557d38fe02c972cab1bdeb33" +} diff --git a/crates/latkit-cli/examples/wecc240-fault/preview.png b/crates/latkit-cli/examples/wecc240-fault/preview.png new file mode 100644 index 00000000..38204ba4 Binary files /dev/null and b/crates/latkit-cli/examples/wecc240-fault/preview.png differ diff --git a/crates/latkit-cli/examples/wecc240-fault/recording/frequency.f32 b/crates/latkit-cli/examples/wecc240-fault/recording/frequency.f32 new file mode 100644 index 00000000..f3eec40a Binary files /dev/null and b/crates/latkit-cli/examples/wecc240-fault/recording/frequency.f32 differ diff --git a/crates/latkit-cli/examples/wecc240-fault/recording/metadata.json b/crates/latkit-cli/examples/wecc240-fault/recording/metadata.json new file mode 100644 index 00000000..b2e3db01 --- /dev/null +++ b/crates/latkit-cli/examples/wecc240-fault/recording/metadata.json @@ -0,0 +1,3526 @@ +{ + "image": "ghcr.io/lukelowry/gridkit:develop-perf", + "image_id": "sha256:befba9e16edce341888e73c05b9d2c35aedf1357fa18b54c56114dbe25ccd565", + "image_labels": { + "io.gridkit.images.revision": "2ca0766", + "io.gridkit.patches": "develop/perf/0001-ida-fused-vector-ops.patch@0941dd8582bb,develop/perf/0002-monitor-output-gating.patch@6774620acc20,develop/perf/0003-monitor-formatting.patch@a585d85c74bf,develop/perf/0004-klu-pivot-recovery.patch@c23d457fe0c2,develop/perf/0005-vector-slice-aliases.patch@b67c89b29482,develop/perf/0006-bus-terminal-cache.patch@b5cf9f18e47e,develop/perf/0007-shared-admittance-context.patch@c1204e559c45,develop/perf/0008-load-algebraic-elimination.patch@7bef3cd7a78c,develop/perf/0009-network-admittance.patch@3332aaa51e31,develop/perf/0010-constant-jacobian-cache.patch@b92378dc69ca,develop/perf/0011-genrou-algebraic-elimination.patch@b1d7f2743d15,develop/perf/0012-gensal-algebraic-elimination.patch@167b1fa6ea35,develop/perf/0013-ieeet1-algebraic-elimination.patch@ea4d7035cbab,develop/perf/0014-ieeest-algebraic-elimination.patch@60c41d1014a8,develop/perf/0015-simulation-tolerances.patch@45d484157c63", + "io.gridkit.ref": "develop", + "org.opencontainers.image.base.name": "ghcr.io/lukelowry/gridkit-sdk:1", + "org.opencontainers.image.revision": "a6f047a4408591b33d18b893644aa4f59b9d87ae", + "org.opencontainers.image.source": "https://github.com/ORNL/GridKit", + "org.opencontainers.image.version": "0.2.0" + }, + "source": "ORNL/GridKit/cases/PhasorDynamics/WECC240/WECC240.case.json", + "source_sha256": "454bb47ae581b2c322e715bbc566a83b5235786b30f4b513c9cbf2f86b1b6344", + "prepared_case_sha256": "2aa8a7e88e65887537b22c0f17bb2d1a89d5733eae52f055a3a6b384380aa169", + "study": { + "system_model_file": "case.json", + "output_file": "monitor.csv", + "dt_monitor": 0.004166666666666667, + "tmax": 10.0, + "max_steps": 1000000, + "rel_tol": 1e-07, + "abs_tol": 1e-09, + "events": [ + { + "time": 1.0, + "type": "fault_on", + "bus": 4005, + "R": 0.0, + "X": 0.01 + }, + { + "time": 1.15, + "type": "fault_off", + "bus": 4005 + } + ] + }, + "exit_code": 0, + "simulation_wall_seconds": 2.034018800011836, + "bus_ids": [ + 1001, + 1002, + 1003, + 1004, + 1032, + 1034, + 1101, + 1102, + 1131, + 1201, + 1202, + 1232, + 1301, + 1302, + 1303, + 1331, + 1333, + 1401, + 1402, + 1403, + 1431, + 2000, + 2030, + 2100, + 2130, + 2201, + 2202, + 2203, + 2233, + 2301, + 2302, + 2332, + 2400, + 2401, + 2402, + 2403, + 2404, + 2405, + 2406, + 2407, + 2408, + 2409, + 2410, + 2411, + 2431, + 2434, + 2438, + 2439, + 2501, + 2502, + 2503, + 2533, + 2600, + 2601, + 2602, + 2603, + 2604, + 2605, + 2606, + 2607, + 2608, + 2609, + 2610, + 2611, + 2612, + 2613, + 2614, + 2615, + 2616, + 2617, + 2618, + 2619, + 2620, + 2621, + 2630, + 2631, + 2634, + 2637, + 2638, + 2901, + 2902, + 3101, + 3102, + 3103, + 3104, + 3105, + 3133, + 3135, + 3201, + 3202, + 3203, + 3204, + 3205, + 3234, + 3301, + 3302, + 3303, + 3304, + 3305, + 3333, + 3401, + 3402, + 3403, + 3404, + 3405, + 3432, + 3433, + 3501, + 3531, + 3601, + 3631, + 3701, + 3731, + 3801, + 3802, + 3803, + 3804, + 3805, + 3806, + 3831, + 3835, + 3836, + 3891, + 3892, + 3893, + 3894, + 3895, + 3896, + 3897, + 3901, + 3902, + 3903, + 3904, + 3905, + 3906, + 3907, + 3908, + 3909, + 3910, + 3911, + 3912, + 3913, + 3914, + 3915, + 3916, + 3917, + 3918, + 3919, + 3920, + 3921, + 3922, + 3923, + 3924, + 3925, + 3926, + 3931, + 3932, + 3933, + 4001, + 4002, + 4003, + 4004, + 4005, + 4006, + 4007, + 4008, + 4009, + 4010, + 4031, + 4035, + 4039, + 4090, + 4091, + 4092, + 4093, + 4094, + 4095, + 4096, + 4097, + 4101, + 4102, + 4103, + 4104, + 4131, + 4132, + 4201, + 4202, + 4203, + 4204, + 4231, + 4232, + 5001, + 5002, + 5003, + 5004, + 5031, + 5032, + 6101, + 6102, + 6103, + 6104, + 6132, + 6201, + 6202, + 6203, + 6204, + 6205, + 6231, + 6235, + 6301, + 6302, + 6303, + 6304, + 6305, + 6333, + 6335, + 6401, + 6402, + 6403, + 6404, + 6433, + 6501, + 6502, + 6503, + 6504, + 6505, + 6506, + 6507, + 6508, + 6509, + 6510, + 6533, + 7001, + 7002, + 7031, + 7032, + 8001, + 8002, + 8003, + 8004, + 8005, + 8033, + 8034 + ], + "machine_ids": [ + "1032_C_genrou", + "1032_G_genrou", + "1034_C_genrou", + "1034_G_genrou", + "1131_C_genrou", + "1131_G_genrou", + "1232_C_genrou", + "1232_H_genrou", + "1331_G_genrou", + "1331_H_genrou", + "1333_C_genrou", + "1333_G_genrou", + "1431_G_genrou", + "1431_N_genrou", + "2030_E_genrou", + "2030_G_genrou", + "2130_E_genrou", + "2130_G_genrou", + "2130_H_genrou", + "2233_DG_genrou", + "2233_EG_genrou", + "2233_TG_genrou", + "2438_EG_genrou", + "2438_RG_genrou", + "2438_SG_genrou", + "2438_SH_genrou", + "2438_WG_genrou", + "2630_G_genrou", + "2634_C_genrou", + "2637_H_genrou", + "2638_H_genrou", + "3133_NG_genrou", + "3135_MG_genrou", + "3135_NG_genrou", + "3234_DG_genrou", + "3234_MG_genrou", + "3234_NG_genrou", + "3333_CG_genrou", + "3333_NG_genrou", + "3433_NG_genrou", + "3531_CE_genrou", + "3531_NE_genrou", + "3531_NH_genrou", + "3631_NB_genrou", + "3631_NG_genrou", + "3731_NH_genrou", + "3831_NN_genrou", + "3835_NG_genrou", + "3836_DG_genrou", + "3931_NB_genrou", + "3931_NH_genrou", + "3933_CG_genrou", + "3933_NB_genrou", + "3933_NG_genrou", + "3933_NH_genrou", + "4031_G_genrou", + "4031_H_genrou", + "4035_C_genrou", + "4035_G_genrou", + "4035_H_genrou", + "4039_G_genrou", + "4039_H_genrou", + "4131_B_genrou", + "4131_H_genrou", + "4132_G_genrou", + "4132_H_genrou", + "4132_N_genrou", + "4231_C_genrou", + "4231_G_genrou", + "4231_H_genrou", + "4232_G_genrou", + "4232_H_genrou", + "5031_G_genrou", + "5031_H_genrou", + "5032_C_genrou", + "5032_G_genrou", + "5032_R_genrou", + "6132_B_genrou", + "6132_G_genrou", + "6132_H_genrou", + "6231_C_genrou", + "6231_G_genrou", + "6235_G_genrou", + "6235_H_genrou", + "6333_C_genrou", + "6335_C_genrou", + "6335_G_genrou", + "6335_H_genrou", + "6433_C_genrou", + "6433_E_genrou", + "6433_G_genrou", + "6533_C_genrou", + "6533_G_genrou", + "6533_H_genrou", + "7031_C_genrou", + "7031_G_genrou", + "7031_P_genrou", + "7032_C_genrou", + "7032_G_genrou", + "7032_H_genrou", + "8033_H_genrou", + "8034_G_genrou", + "8034_H_genrou" + ], + "machine_bus_ids": [ + 1032, + 1032, + 1034, + 1034, + 1131, + 1131, + 1232, + 1232, + 1331, + 1331, + 1333, + 1333, + 1431, + 1431, + 2030, + 2030, + 2130, + 2130, + 2130, + 2233, + 2233, + 2233, + 2438, + 2438, + 2438, + 2438, + 2438, + 2630, + 2634, + 2637, + 2638, + 3133, + 3135, + 3135, + 3234, + 3234, + 3234, + 3333, + 3333, + 3433, + 3531, + 3531, + 3531, + 3631, + 3631, + 3731, + 3831, + 3835, + 3836, + 3931, + 3931, + 3933, + 3933, + 3933, + 3933, + 4031, + 4031, + 4035, + 4035, + 4035, + 4039, + 4039, + 4131, + 4131, + 4132, + 4132, + 4132, + 4231, + 4231, + 4231, + 4232, + 4232, + 5031, + 5031, + 5032, + 5032, + 5032, + 6132, + 6132, + 6132, + 6231, + 6231, + 6235, + 6235, + 6333, + 6335, + 6335, + 6335, + 6433, + 6433, + 6433, + 6533, + 6533, + 6533, + 7031, + 7031, + 7031, + 7032, + 7032, + 7032, + 8033, + 8034, + 8034 + ], + "times": [ + 0.0, + 0.004166666666666667, + 0.008333333333333333, + 0.0125, + 0.016666666666666666, + 0.020833333333333332, + 0.025, + 0.029166666666666667, + 0.03333333333333333, + 0.0375, + 0.041666666666666664, + 0.04583333333333333, + 0.05, + 0.05416666666666667, + 0.058333333333333334, + 0.0625, + 0.06666666666666667, + 0.07083333333333333, + 0.075, + 0.07916666666666666, + 0.08333333333333333, + 0.0875, + 0.09166666666666666, + 0.09583333333333333, + 0.1, + 0.10416666666666667, + 0.10833333333333334, + 0.1125, + 0.11666666666666667, + 0.12083333333333333, + 0.125, + 0.12916666666666665, + 0.13333333333333333, + 0.1375, + 0.14166666666666666, + 0.14583333333333334, + 0.15, + 0.15416666666666667, + 0.15833333333333333, + 0.1625, + 0.16666666666666666, + 0.17083333333333334, + 0.175, + 0.17916666666666667, + 0.18333333333333332, + 0.1875, + 0.19166666666666665, + 0.19583333333333333, + 0.2, + 0.20416666666666666, + 0.20833333333333334, + 0.2125, + 0.21666666666666667, + 0.22083333333333333, + 0.225, + 0.22916666666666666, + 0.23333333333333334, + 0.2375, + 0.24166666666666667, + 0.24583333333333332, + 0.25, + 0.25416666666666665, + 0.2583333333333333, + 0.2625, + 0.26666666666666666, + 0.2708333333333333, + 0.275, + 0.2791666666666667, + 0.2833333333333333, + 0.2875, + 0.2916666666666667, + 0.29583333333333334, + 0.3, + 0.30416666666666664, + 0.30833333333333335, + 0.3125, + 0.31666666666666665, + 0.3208333333333333, + 0.325, + 0.32916666666666666, + 0.3333333333333333, + 0.3375, + 0.3416666666666667, + 0.3458333333333333, + 0.35, + 0.3541666666666667, + 0.35833333333333334, + 0.3625, + 0.36666666666666664, + 0.37083333333333335, + 0.375, + 0.37916666666666665, + 0.3833333333333333, + 0.3875, + 0.39166666666666666, + 0.3958333333333333, + 0.4, + 0.4041666666666667, + 0.4083333333333333, + 0.4125, + 0.4166666666666667, + 0.42083333333333334, + 0.425, + 0.42916666666666664, + 0.43333333333333335, + 0.4375, + 0.44166666666666665, + 0.4458333333333333, + 0.45, + 0.45416666666666666, + 0.4583333333333333, + 0.46249999999999997, + 0.4666666666666667, + 0.4708333333333333, + 0.475, + 0.4791666666666667, + 0.48333333333333334, + 0.4875, + 0.49166666666666664, + 0.49583333333333335, + 0.5, + 0.5041666666666667, + 0.5083333333333333, + 0.5125, + 0.5166666666666666, + 0.5208333333333334, + 0.525, + 0.5291666666666667, + 0.5333333333333333, + 0.5375, + 0.5416666666666666, + 0.5458333333333333, + 0.55, + 0.5541666666666667, + 0.5583333333333333, + 0.5625, + 0.5666666666666667, + 0.5708333333333333, + 0.575, + 0.5791666666666666, + 0.5833333333333334, + 0.5875, + 0.5916666666666667, + 0.5958333333333333, + 0.6, + 0.6041666666666666, + 0.6083333333333333, + 0.6125, + 0.6166666666666667, + 0.6208333333333333, + 0.625, + 0.6291666666666667, + 0.6333333333333333, + 0.6375, + 0.6416666666666666, + 0.6458333333333334, + 0.65, + 0.6541666666666667, + 0.6583333333333333, + 0.6625, + 0.6666666666666666, + 0.6708333333333333, + 0.675, + 0.6791666666666667, + 0.6833333333333333, + 0.6875, + 0.6916666666666667, + 0.6958333333333333, + 0.7, + 0.7041666666666666, + 0.7083333333333334, + 0.7125, + 0.7166666666666667, + 0.7208333333333333, + 0.725, + 0.7291666666666666, + 0.7333333333333333, + 0.7375, + 0.7416666666666667, + 0.7458333333333333, + 0.75, + 0.7541666666666667, + 0.7583333333333333, + 0.7625, + 0.7666666666666666, + 0.7708333333333334, + 0.775, + 0.7791666666666667, + 0.7833333333333333, + 0.7875, + 0.7916666666666666, + 0.7958333333333333, + 0.8, + 0.8041666666666667, + 0.8083333333333333, + 0.8125, + 0.8166666666666667, + 0.8208333333333333, + 0.825, + 0.8291666666666666, + 0.8333333333333334, + 0.8375, + 0.8416666666666667, + 0.8458333333333333, + 0.85, + 0.8541666666666666, + 0.8583333333333333, + 0.8624999999999999, + 0.8666666666666667, + 0.8708333333333333, + 0.875, + 0.8791666666666667, + 0.8833333333333333, + 0.8875, + 0.8916666666666666, + 0.8958333333333334, + 0.9, + 0.9041666666666667, + 0.9083333333333333, + 0.9125, + 0.9166666666666666, + 0.9208333333333333, + 0.9249999999999999, + 0.9291666666666667, + 0.9333333333333333, + 0.9375, + 0.9416666666666667, + 0.9458333333333333, + 0.95, + 0.9541666666666666, + 0.9583333333333334, + 0.9625, + 0.9666666666666667, + 0.9708333333333333, + 0.975, + 0.9791666666666666, + 0.9833333333333333, + 0.9874999999999999, + 0.9916666666666667, + 0.9958333333333333, + 1.0, + 1.0, + 1.0041666666666667, + 1.0083333333333333, + 1.0125, + 1.0166666666666666, + 1.0208333333333333, + 1.025, + 1.0291666666666666, + 1.0333333333333334, + 1.0375, + 1.0416666666666667, + 1.0458333333333334, + 1.05, + 1.0541666666666667, + 1.0583333333333333, + 1.0625, + 1.0666666666666667, + 1.0708333333333333, + 1.075, + 1.0791666666666666, + 1.0833333333333333, + 1.0875, + 1.0916666666666666, + 1.0958333333333334, + 1.1, + 1.1041666666666667, + 1.1083333333333334, + 1.1125, + 1.1166666666666667, + 1.1208333333333333, + 1.125, + 1.1291666666666667, + 1.1333333333333333, + 1.1375, + 1.1416666666666666, + 1.1458333333333333, + 1.15, + 1.15, + 1.1541666666666666, + 1.1583333333333332, + 1.1624999999999999, + 1.1666666666666665, + 1.1708333333333332, + 1.1749999999999998, + 1.1791666666666665, + 1.1833333333333333, + 1.1875, + 1.1916666666666667, + 1.1958333333333333, + 1.2, + 1.2041666666666666, + 1.2083333333333333, + 1.2125, + 1.2166666666666666, + 1.2208333333333332, + 1.2249999999999999, + 1.2291666666666665, + 1.2333333333333332, + 1.2374999999999998, + 1.2416666666666665, + 1.2458333333333333, + 1.25, + 1.2541666666666667, + 1.2583333333333333, + 1.2625, + 1.2666666666666666, + 1.2708333333333333, + 1.275, + 1.2791666666666666, + 1.2833333333333332, + 1.2874999999999999, + 1.2916666666666665, + 1.2958333333333332, + 1.2999999999999998, + 1.3041666666666665, + 1.3083333333333333, + 1.3125, + 1.3166666666666667, + 1.3208333333333333, + 1.325, + 1.3291666666666666, + 1.3333333333333333, + 1.3375, + 1.3416666666666666, + 1.3458333333333332, + 1.3499999999999999, + 1.3541666666666665, + 1.3583333333333332, + 1.3624999999999998, + 1.3666666666666665, + 1.3708333333333333, + 1.375, + 1.3791666666666667, + 1.3833333333333333, + 1.3875, + 1.3916666666666666, + 1.3958333333333333, + 1.4, + 1.4041666666666666, + 1.4083333333333332, + 1.4124999999999999, + 1.4166666666666665, + 1.4208333333333332, + 1.4249999999999998, + 1.4291666666666665, + 1.4333333333333333, + 1.4375, + 1.4416666666666667, + 1.4458333333333333, + 1.45, + 1.4541666666666666, + 1.4583333333333333, + 1.4625, + 1.4666666666666666, + 1.4708333333333332, + 1.4749999999999999, + 1.4791666666666665, + 1.4833333333333332, + 1.4874999999999998, + 1.4916666666666665, + 1.4958333333333333, + 1.5, + 1.5041666666666667, + 1.5083333333333333, + 1.5125, + 1.5166666666666666, + 1.5208333333333333, + 1.525, + 1.5291666666666666, + 1.5333333333333332, + 1.5374999999999999, + 1.5416666666666665, + 1.5458333333333332, + 1.5499999999999998, + 1.5541666666666665, + 1.5583333333333333, + 1.5625, + 1.5666666666666667, + 1.5708333333333333, + 1.575, + 1.5791666666666666, + 1.5833333333333333, + 1.5875, + 1.5916666666666666, + 1.5958333333333332, + 1.5999999999999999, + 1.6041666666666665, + 1.6083333333333332, + 1.6124999999999998, + 1.6166666666666665, + 1.6208333333333333, + 1.625, + 1.6291666666666667, + 1.6333333333333333, + 1.6375, + 1.6416666666666666, + 1.6458333333333333, + 1.65, + 1.6541666666666666, + 1.6583333333333332, + 1.6624999999999999, + 1.6666666666666665, + 1.6708333333333332, + 1.6749999999999998, + 1.6791666666666665, + 1.6833333333333331, + 1.6875, + 1.6916666666666667, + 1.6958333333333333, + 1.7, + 1.7041666666666666, + 1.7083333333333333, + 1.7125, + 1.7166666666666666, + 1.7208333333333332, + 1.7249999999999999, + 1.7291666666666665, + 1.7333333333333332, + 1.7374999999999998, + 1.7416666666666665, + 1.7458333333333331, + 1.75, + 1.7541666666666667, + 1.7583333333333333, + 1.7625, + 1.7666666666666666, + 1.7708333333333333, + 1.775, + 1.7791666666666666, + 1.7833333333333332, + 1.7874999999999999, + 1.7916666666666665, + 1.7958333333333332, + 1.7999999999999998, + 1.8041666666666665, + 1.8083333333333331, + 1.8125, + 1.8166666666666667, + 1.8208333333333333, + 1.825, + 1.8291666666666666, + 1.8333333333333333, + 1.8375, + 1.8416666666666666, + 1.8458333333333332, + 1.8499999999999999, + 1.8541666666666665, + 1.8583333333333332, + 1.8624999999999998, + 1.8666666666666665, + 1.8708333333333331, + 1.875, + 1.8791666666666667, + 1.8833333333333333, + 1.8875, + 1.8916666666666666, + 1.8958333333333333, + 1.9, + 1.9041666666666666, + 1.9083333333333332, + 1.9124999999999999, + 1.9166666666666665, + 1.9208333333333332, + 1.9249999999999998, + 1.9291666666666665, + 1.9333333333333331, + 1.9375, + 1.9416666666666667, + 1.9458333333333333, + 1.95, + 1.9541666666666666, + 1.9583333333333333, + 1.9625, + 1.9666666666666666, + 1.9708333333333332, + 1.9749999999999999, + 1.9791666666666665, + 1.9833333333333332, + 1.9874999999999998, + 1.9916666666666665, + 1.9958333333333331, + 2.0, + 2.0041666666666664, + 2.0083333333333333, + 2.0124999999999997, + 2.0166666666666666, + 2.020833333333333, + 2.025, + 2.029166666666667, + 2.033333333333333, + 2.0375, + 2.0416666666666665, + 2.0458333333333334, + 2.05, + 2.0541666666666667, + 2.058333333333333, + 2.0625, + 2.0666666666666664, + 2.0708333333333333, + 2.0749999999999997, + 2.0791666666666666, + 2.083333333333333, + 2.0875, + 2.091666666666667, + 2.095833333333333, + 2.1, + 2.1041666666666665, + 2.1083333333333334, + 2.1125, + 2.1166666666666667, + 2.120833333333333, + 2.125, + 2.1291666666666664, + 2.1333333333333333, + 2.1374999999999997, + 2.1416666666666666, + 2.145833333333333, + 2.15, + 2.154166666666667, + 2.158333333333333, + 2.1625, + 2.1666666666666665, + 2.1708333333333334, + 2.175, + 2.1791666666666667, + 2.183333333333333, + 2.1875, + 2.1916666666666664, + 2.1958333333333333, + 2.1999999999999997, + 2.2041666666666666, + 2.208333333333333, + 2.2125, + 2.216666666666667, + 2.220833333333333, + 2.225, + 2.2291666666666665, + 2.2333333333333334, + 2.2375, + 2.2416666666666667, + 2.245833333333333, + 2.25, + 2.2541666666666664, + 2.2583333333333333, + 2.2624999999999997, + 2.2666666666666666, + 2.270833333333333, + 2.275, + 2.2791666666666663, + 2.283333333333333, + 2.2875, + 2.2916666666666665, + 2.2958333333333334, + 2.3, + 2.3041666666666667, + 2.308333333333333, + 2.3125, + 2.3166666666666664, + 2.3208333333333333, + 2.3249999999999997, + 2.3291666666666666, + 2.333333333333333, + 2.3375, + 2.3416666666666663, + 2.345833333333333, + 2.35, + 2.3541666666666665, + 2.3583333333333334, + 2.3625, + 2.3666666666666667, + 2.370833333333333, + 2.375, + 2.3791666666666664, + 2.3833333333333333, + 2.3874999999999997, + 2.3916666666666666, + 2.395833333333333, + 2.4, + 2.4041666666666663, + 2.408333333333333, + 2.4125, + 2.4166666666666665, + 2.4208333333333334, + 2.425, + 2.4291666666666667, + 2.433333333333333, + 2.4375, + 2.4416666666666664, + 2.4458333333333333, + 2.4499999999999997, + 2.4541666666666666, + 2.458333333333333, + 2.4625, + 2.4666666666666663, + 2.470833333333333, + 2.475, + 2.4791666666666665, + 2.4833333333333334, + 2.4875, + 2.4916666666666667, + 2.495833333333333, + 2.5, + 2.5041666666666664, + 2.5083333333333333, + 2.5124999999999997, + 2.5166666666666666, + 2.520833333333333, + 2.525, + 2.5291666666666663, + 2.533333333333333, + 2.5375, + 2.5416666666666665, + 2.5458333333333334, + 2.55, + 2.5541666666666667, + 2.558333333333333, + 2.5625, + 2.5666666666666664, + 2.5708333333333333, + 2.5749999999999997, + 2.5791666666666666, + 2.583333333333333, + 2.5875, + 2.5916666666666663, + 2.595833333333333, + 2.6, + 2.6041666666666665, + 2.6083333333333334, + 2.6125, + 2.6166666666666667, + 2.620833333333333, + 2.625, + 2.6291666666666664, + 2.6333333333333333, + 2.6374999999999997, + 2.6416666666666666, + 2.645833333333333, + 2.65, + 2.6541666666666663, + 2.658333333333333, + 2.6625, + 2.6666666666666665, + 2.6708333333333334, + 2.675, + 2.6791666666666667, + 2.683333333333333, + 2.6875, + 2.6916666666666664, + 2.6958333333333333, + 2.6999999999999997, + 2.7041666666666666, + 2.708333333333333, + 2.7125, + 2.7166666666666663, + 2.720833333333333, + 2.725, + 2.7291666666666665, + 2.7333333333333334, + 2.7375, + 2.7416666666666667, + 2.745833333333333, + 2.75, + 2.7541666666666664, + 2.7583333333333333, + 2.7624999999999997, + 2.7666666666666666, + 2.770833333333333, + 2.775, + 2.7791666666666663, + 2.783333333333333, + 2.7875, + 2.7916666666666665, + 2.7958333333333334, + 2.8, + 2.8041666666666667, + 2.808333333333333, + 2.8125, + 2.8166666666666664, + 2.8208333333333333, + 2.8249999999999997, + 2.8291666666666666, + 2.833333333333333, + 2.8375, + 2.8416666666666663, + 2.845833333333333, + 2.85, + 2.8541666666666665, + 2.8583333333333334, + 2.8625, + 2.8666666666666667, + 2.870833333333333, + 2.875, + 2.8791666666666664, + 2.8833333333333333, + 2.8874999999999997, + 2.8916666666666666, + 2.895833333333333, + 2.9, + 2.9041666666666663, + 2.908333333333333, + 2.9125, + 2.9166666666666665, + 2.9208333333333334, + 2.925, + 2.9291666666666667, + 2.933333333333333, + 2.9375, + 2.9416666666666664, + 2.9458333333333333, + 2.9499999999999997, + 2.9541666666666666, + 2.958333333333333, + 2.9625, + 2.9666666666666663, + 2.970833333333333, + 2.975, + 2.9791666666666665, + 2.9833333333333334, + 2.9875, + 2.9916666666666667, + 2.995833333333333, + 3.0, + 3.0041666666666664, + 3.0083333333333333, + 3.0124999999999997, + 3.0166666666666666, + 3.020833333333333, + 3.025, + 3.0291666666666663, + 3.033333333333333, + 3.0375, + 3.0416666666666665, + 3.0458333333333334, + 3.05, + 3.0541666666666667, + 3.058333333333333, + 3.0625, + 3.0666666666666664, + 3.0708333333333333, + 3.0749999999999997, + 3.0791666666666666, + 3.083333333333333, + 3.0875, + 3.0916666666666663, + 3.095833333333333, + 3.1, + 3.1041666666666665, + 3.1083333333333334, + 3.1125, + 3.1166666666666667, + 3.120833333333333, + 3.125, + 3.1291666666666664, + 3.1333333333333333, + 3.1374999999999997, + 3.1416666666666666, + 3.145833333333333, + 3.15, + 3.1541666666666663, + 3.158333333333333, + 3.1625, + 3.1666666666666665, + 3.1708333333333334, + 3.175, + 3.1791666666666667, + 3.183333333333333, + 3.1875, + 3.1916666666666664, + 3.1958333333333333, + 3.1999999999999997, + 3.2041666666666666, + 3.208333333333333, + 3.2125, + 3.2166666666666663, + 3.220833333333333, + 3.225, + 3.2291666666666665, + 3.2333333333333334, + 3.2375, + 3.2416666666666667, + 3.245833333333333, + 3.25, + 3.2541666666666664, + 3.2583333333333333, + 3.2624999999999997, + 3.2666666666666666, + 3.270833333333333, + 3.275, + 3.2791666666666663, + 3.283333333333333, + 3.2875, + 3.2916666666666665, + 3.2958333333333334, + 3.3, + 3.3041666666666667, + 3.308333333333333, + 3.3125, + 3.3166666666666664, + 3.3208333333333333, + 3.3249999999999997, + 3.3291666666666666, + 3.333333333333333, + 3.3375, + 3.3416666666666663, + 3.345833333333333, + 3.35, + 3.3541666666666665, + 3.3583333333333334, + 3.3625, + 3.3666666666666667, + 3.370833333333333, + 3.375, + 3.3791666666666664, + 3.3833333333333333, + 3.3874999999999997, + 3.3916666666666666, + 3.395833333333333, + 3.4, + 3.4041666666666663, + 3.408333333333333, + 3.4125, + 3.4166666666666665, + 3.4208333333333334, + 3.425, + 3.4291666666666667, + 3.433333333333333, + 3.4375, + 3.4416666666666664, + 3.4458333333333333, + 3.4499999999999997, + 3.4541666666666666, + 3.458333333333333, + 3.4625, + 3.4666666666666663, + 3.470833333333333, + 3.475, + 3.4791666666666665, + 3.4833333333333334, + 3.4875, + 3.4916666666666667, + 3.495833333333333, + 3.5, + 3.5041666666666664, + 3.5083333333333333, + 3.5124999999999997, + 3.5166666666666666, + 3.520833333333333, + 3.525, + 3.5291666666666663, + 3.533333333333333, + 3.5375, + 3.5416666666666665, + 3.5458333333333334, + 3.55, + 3.5541666666666667, + 3.558333333333333, + 3.5625, + 3.5666666666666664, + 3.5708333333333333, + 3.5749999999999997, + 3.5791666666666666, + 3.583333333333333, + 3.5875, + 3.5916666666666663, + 3.595833333333333, + 3.6, + 3.6041666666666665, + 3.6083333333333334, + 3.6125, + 3.6166666666666667, + 3.620833333333333, + 3.625, + 3.6291666666666664, + 3.6333333333333333, + 3.6374999999999997, + 3.6416666666666666, + 3.645833333333333, + 3.65, + 3.6541666666666663, + 3.658333333333333, + 3.6625, + 3.6666666666666665, + 3.6708333333333334, + 3.675, + 3.6791666666666667, + 3.683333333333333, + 3.6875, + 3.6916666666666664, + 3.6958333333333333, + 3.6999999999999997, + 3.7041666666666666, + 3.708333333333333, + 3.7125, + 3.7166666666666663, + 3.720833333333333, + 3.725, + 3.7291666666666665, + 3.7333333333333334, + 3.7375, + 3.7416666666666667, + 3.745833333333333, + 3.75, + 3.7541666666666664, + 3.7583333333333333, + 3.7624999999999997, + 3.7666666666666666, + 3.770833333333333, + 3.775, + 3.7791666666666663, + 3.783333333333333, + 3.7875, + 3.7916666666666665, + 3.7958333333333334, + 3.8, + 3.8041666666666667, + 3.808333333333333, + 3.8125, + 3.8166666666666664, + 3.8208333333333333, + 3.8249999999999997, + 3.8291666666666666, + 3.833333333333333, + 3.8375, + 3.8416666666666663, + 3.845833333333333, + 3.85, + 3.8541666666666665, + 3.8583333333333334, + 3.8625, + 3.8666666666666667, + 3.870833333333333, + 3.875, + 3.8791666666666664, + 3.8833333333333333, + 3.8874999999999997, + 3.8916666666666666, + 3.895833333333333, + 3.9, + 3.9041666666666663, + 3.908333333333333, + 3.9125, + 3.9166666666666665, + 3.9208333333333334, + 3.925, + 3.9291666666666667, + 3.933333333333333, + 3.9375, + 3.9416666666666664, + 3.9458333333333333, + 3.9499999999999997, + 3.9541666666666666, + 3.958333333333333, + 3.9625, + 3.9666666666666663, + 3.970833333333333, + 3.975, + 3.9791666666666665, + 3.9833333333333334, + 3.9875, + 3.9916666666666667, + 3.995833333333333, + 4.0, + 4.004166666666666, + 4.008333333333333, + 4.0125, + 4.016666666666667, + 4.020833333333333, + 4.0249999999999995, + 4.029166666666667, + 4.033333333333333, + 4.0375, + 4.041666666666667, + 4.045833333333333, + 4.05, + 4.054166666666666, + 4.058333333333334, + 4.0625, + 4.066666666666666, + 4.070833333333333, + 4.075, + 4.079166666666667, + 4.083333333333333, + 4.0874999999999995, + 4.091666666666667, + 4.095833333333333, + 4.1, + 4.104166666666667, + 4.108333333333333, + 4.1125, + 4.116666666666666, + 4.120833333333334, + 4.125, + 4.129166666666666, + 4.133333333333333, + 4.1375, + 4.141666666666667, + 4.145833333333333, + 4.1499999999999995, + 4.154166666666667, + 4.158333333333333, + 4.1625, + 4.166666666666667, + 4.170833333333333, + 4.175, + 4.179166666666666, + 4.183333333333334, + 4.1875, + 4.191666666666666, + 4.195833333333333, + 4.2, + 4.204166666666667, + 4.208333333333333, + 4.2124999999999995, + 4.216666666666667, + 4.220833333333333, + 4.225, + 4.229166666666667, + 4.233333333333333, + 4.2375, + 4.241666666666666, + 4.245833333333334, + 4.25, + 4.254166666666666, + 4.258333333333333, + 4.2625, + 4.266666666666667, + 4.270833333333333, + 4.2749999999999995, + 4.279166666666667, + 4.283333333333333, + 4.2875, + 4.291666666666667, + 4.295833333333333, + 4.3, + 4.304166666666666, + 4.308333333333334, + 4.3125, + 4.316666666666666, + 4.320833333333333, + 4.325, + 4.329166666666667, + 4.333333333333333, + 4.3374999999999995, + 4.341666666666667, + 4.345833333333333, + 4.35, + 4.354166666666667, + 4.358333333333333, + 4.3625, + 4.366666666666666, + 4.370833333333334, + 4.375, + 4.379166666666666, + 4.383333333333333, + 4.3875, + 4.391666666666667, + 4.395833333333333, + 4.3999999999999995, + 4.404166666666667, + 4.408333333333333, + 4.4125, + 4.416666666666667, + 4.420833333333333, + 4.425, + 4.429166666666666, + 4.433333333333334, + 4.4375, + 4.441666666666666, + 4.445833333333333, + 4.45, + 4.454166666666667, + 4.458333333333333, + 4.4624999999999995, + 4.466666666666667, + 4.470833333333333, + 4.475, + 4.479166666666667, + 4.483333333333333, + 4.4875, + 4.491666666666666, + 4.495833333333334, + 4.5, + 4.504166666666666, + 4.508333333333333, + 4.5125, + 4.516666666666667, + 4.520833333333333, + 4.5249999999999995, + 4.529166666666667, + 4.533333333333333, + 4.5375, + 4.541666666666667, + 4.545833333333333, + 4.55, + 4.554166666666666, + 4.558333333333334, + 4.5625, + 4.566666666666666, + 4.570833333333333, + 4.575, + 4.579166666666667, + 4.583333333333333, + 4.5874999999999995, + 4.591666666666667, + 4.595833333333333, + 4.6, + 4.604166666666667, + 4.608333333333333, + 4.6125, + 4.616666666666666, + 4.620833333333334, + 4.625, + 4.629166666666666, + 4.633333333333333, + 4.6375, + 4.641666666666667, + 4.645833333333333, + 4.6499999999999995, + 4.654166666666667, + 4.658333333333333, + 4.6625, + 4.666666666666667, + 4.670833333333333, + 4.675, + 4.679166666666666, + 4.683333333333334, + 4.6875, + 4.691666666666666, + 4.695833333333333, + 4.7, + 4.704166666666667, + 4.708333333333333, + 4.7124999999999995, + 4.716666666666667, + 4.720833333333333, + 4.725, + 4.729166666666667, + 4.733333333333333, + 4.7375, + 4.741666666666666, + 4.745833333333334, + 4.75, + 4.754166666666666, + 4.758333333333333, + 4.7625, + 4.766666666666667, + 4.770833333333333, + 4.7749999999999995, + 4.779166666666667, + 4.783333333333333, + 4.7875, + 4.791666666666667, + 4.795833333333333, + 4.8, + 4.804166666666666, + 4.808333333333334, + 4.8125, + 4.816666666666666, + 4.820833333333333, + 4.825, + 4.829166666666667, + 4.833333333333333, + 4.8374999999999995, + 4.841666666666667, + 4.845833333333333, + 4.85, + 4.854166666666667, + 4.858333333333333, + 4.8625, + 4.866666666666666, + 4.870833333333334, + 4.875, + 4.879166666666666, + 4.883333333333333, + 4.8875, + 4.891666666666667, + 4.895833333333333, + 4.8999999999999995, + 4.904166666666667, + 4.908333333333333, + 4.9125, + 4.916666666666667, + 4.920833333333333, + 4.925, + 4.929166666666666, + 4.933333333333334, + 4.9375, + 4.941666666666666, + 4.945833333333333, + 4.95, + 4.954166666666667, + 4.958333333333333, + 4.9624999999999995, + 4.966666666666667, + 4.970833333333333, + 4.975, + 4.979166666666667, + 4.983333333333333, + 4.9875, + 4.991666666666666, + 4.995833333333334, + 5.0, + 5.004166666666666, + 5.008333333333333, + 5.0125, + 5.016666666666667, + 5.020833333333333, + 5.0249999999999995, + 5.029166666666667, + 5.033333333333333, + 5.0375, + 5.041666666666667, + 5.045833333333333, + 5.05, + 5.054166666666666, + 5.058333333333334, + 5.0625, + 5.066666666666666, + 5.070833333333333, + 5.075, + 5.079166666666667, + 5.083333333333333, + 5.0874999999999995, + 5.091666666666667, + 5.095833333333333, + 5.1, + 5.104166666666667, + 5.108333333333333, + 5.1125, + 5.116666666666666, + 5.120833333333334, + 5.125, + 5.129166666666666, + 5.133333333333333, + 5.1375, + 5.141666666666667, + 5.145833333333333, + 5.1499999999999995, + 5.154166666666667, + 5.158333333333333, + 5.1625, + 5.166666666666667, + 5.170833333333333, + 5.175, + 5.179166666666666, + 5.183333333333334, + 5.1875, + 5.191666666666666, + 5.195833333333333, + 5.2, + 5.204166666666667, + 5.208333333333333, + 5.2124999999999995, + 5.216666666666667, + 5.220833333333333, + 5.225, + 5.229166666666667, + 5.233333333333333, + 5.2375, + 5.241666666666666, + 5.245833333333334, + 5.25, + 5.254166666666666, + 5.258333333333333, + 5.2625, + 5.266666666666667, + 5.270833333333333, + 5.2749999999999995, + 5.279166666666667, + 5.283333333333333, + 5.2875, + 5.291666666666667, + 5.295833333333333, + 5.3, + 5.304166666666666, + 5.308333333333334, + 5.3125, + 5.316666666666666, + 5.320833333333333, + 5.325, + 5.329166666666667, + 5.333333333333333, + 5.3374999999999995, + 5.341666666666667, + 5.345833333333333, + 5.35, + 5.354166666666667, + 5.358333333333333, + 5.3625, + 5.366666666666666, + 5.370833333333334, + 5.375, + 5.379166666666666, + 5.383333333333333, + 5.3875, + 5.391666666666667, + 5.395833333333333, + 5.3999999999999995, + 5.404166666666667, + 5.408333333333333, + 5.4125, + 5.416666666666666, + 5.420833333333333, + 5.425, + 5.429166666666666, + 5.433333333333334, + 5.4375, + 5.441666666666666, + 5.445833333333333, + 5.45, + 5.454166666666667, + 5.458333333333333, + 5.4624999999999995, + 5.466666666666667, + 5.470833333333333, + 5.475, + 5.479166666666666, + 5.483333333333333, + 5.4875, + 5.491666666666666, + 5.495833333333334, + 5.5, + 5.504166666666666, + 5.508333333333333, + 5.5125, + 5.516666666666667, + 5.520833333333333, + 5.5249999999999995, + 5.529166666666667, + 5.533333333333333, + 5.5375, + 5.541666666666666, + 5.545833333333333, + 5.55, + 5.554166666666666, + 5.558333333333334, + 5.5625, + 5.566666666666666, + 5.570833333333333, + 5.575, + 5.579166666666667, + 5.583333333333333, + 5.5874999999999995, + 5.591666666666667, + 5.595833333333333, + 5.6, + 5.604166666666666, + 5.608333333333333, + 5.6125, + 5.616666666666666, + 5.620833333333334, + 5.625, + 5.629166666666666, + 5.633333333333333, + 5.6375, + 5.641666666666667, + 5.645833333333333, + 5.6499999999999995, + 5.654166666666667, + 5.658333333333333, + 5.6625, + 5.666666666666666, + 5.670833333333333, + 5.675, + 5.679166666666666, + 5.683333333333334, + 5.6875, + 5.691666666666666, + 5.695833333333333, + 5.7, + 5.704166666666667, + 5.708333333333333, + 5.7124999999999995, + 5.716666666666667, + 5.720833333333333, + 5.725, + 5.729166666666666, + 5.733333333333333, + 5.7375, + 5.741666666666666, + 5.745833333333334, + 5.75, + 5.754166666666666, + 5.758333333333333, + 5.7625, + 5.766666666666667, + 5.770833333333333, + 5.7749999999999995, + 5.779166666666667, + 5.783333333333333, + 5.7875, + 5.791666666666666, + 5.795833333333333, + 5.8, + 5.804166666666666, + 5.808333333333334, + 5.8125, + 5.816666666666666, + 5.820833333333333, + 5.825, + 5.829166666666667, + 5.833333333333333, + 5.8374999999999995, + 5.841666666666667, + 5.845833333333333, + 5.85, + 5.854166666666666, + 5.858333333333333, + 5.8625, + 5.866666666666666, + 5.870833333333334, + 5.875, + 5.879166666666666, + 5.883333333333333, + 5.8875, + 5.891666666666667, + 5.895833333333333, + 5.8999999999999995, + 5.904166666666667, + 5.908333333333333, + 5.9125, + 5.916666666666666, + 5.920833333333333, + 5.925, + 5.929166666666666, + 5.933333333333334, + 5.9375, + 5.941666666666666, + 5.945833333333333, + 5.95, + 5.954166666666667, + 5.958333333333333, + 5.9624999999999995, + 5.966666666666667, + 5.970833333333333, + 5.975, + 5.979166666666666, + 5.983333333333333, + 5.9875, + 5.991666666666666, + 5.995833333333334, + 6.0, + 6.004166666666666, + 6.008333333333333, + 6.0125, + 6.016666666666667, + 6.020833333333333, + 6.0249999999999995, + 6.029166666666667, + 6.033333333333333, + 6.0375, + 6.041666666666666, + 6.045833333333333, + 6.05, + 6.054166666666666, + 6.058333333333334, + 6.0625, + 6.066666666666666, + 6.070833333333333, + 6.075, + 6.079166666666667, + 6.083333333333333, + 6.0874999999999995, + 6.091666666666667, + 6.095833333333333, + 6.1, + 6.104166666666666, + 6.108333333333333, + 6.1125, + 6.116666666666666, + 6.120833333333334, + 6.125, + 6.129166666666666, + 6.133333333333333, + 6.1375, + 6.141666666666667, + 6.145833333333333, + 6.1499999999999995, + 6.154166666666667, + 6.158333333333333, + 6.1625, + 6.166666666666666, + 6.170833333333333, + 6.175, + 6.179166666666666, + 6.183333333333334, + 6.1875, + 6.191666666666666, + 6.195833333333333, + 6.2, + 6.204166666666667, + 6.208333333333333, + 6.2124999999999995, + 6.216666666666667, + 6.220833333333333, + 6.225, + 6.229166666666666, + 6.233333333333333, + 6.2375, + 6.241666666666666, + 6.245833333333334, + 6.25, + 6.254166666666666, + 6.258333333333333, + 6.2625, + 6.266666666666667, + 6.270833333333333, + 6.2749999999999995, + 6.279166666666667, + 6.283333333333333, + 6.2875, + 6.291666666666666, + 6.295833333333333, + 6.3, + 6.304166666666666, + 6.308333333333334, + 6.3125, + 6.316666666666666, + 6.320833333333333, + 6.325, + 6.329166666666667, + 6.333333333333333, + 6.3374999999999995, + 6.341666666666667, + 6.345833333333333, + 6.35, + 6.354166666666666, + 6.358333333333333, + 6.3625, + 6.366666666666666, + 6.370833333333334, + 6.375, + 6.379166666666666, + 6.383333333333333, + 6.3875, + 6.391666666666667, + 6.395833333333333, + 6.3999999999999995, + 6.404166666666667, + 6.408333333333333, + 6.4125, + 6.416666666666666, + 6.420833333333333, + 6.425, + 6.429166666666666, + 6.433333333333334, + 6.4375, + 6.441666666666666, + 6.445833333333333, + 6.45, + 6.454166666666667, + 6.458333333333333, + 6.4624999999999995, + 6.466666666666667, + 6.470833333333333, + 6.475, + 6.479166666666666, + 6.483333333333333, + 6.4875, + 6.491666666666666, + 6.495833333333334, + 6.5, + 6.504166666666666, + 6.508333333333333, + 6.5125, + 6.516666666666667, + 6.520833333333333, + 6.5249999999999995, + 6.529166666666667, + 6.533333333333333, + 6.5375, + 6.541666666666666, + 6.545833333333333, + 6.55, + 6.554166666666666, + 6.558333333333334, + 6.5625, + 6.566666666666666, + 6.570833333333333, + 6.575, + 6.579166666666667, + 6.583333333333333, + 6.5874999999999995, + 6.591666666666667, + 6.595833333333333, + 6.6, + 6.604166666666666, + 6.608333333333333, + 6.6125, + 6.616666666666666, + 6.620833333333334, + 6.625, + 6.629166666666666, + 6.633333333333333, + 6.6375, + 6.641666666666667, + 6.645833333333333, + 6.6499999999999995, + 6.654166666666667, + 6.658333333333333, + 6.6625, + 6.666666666666666, + 6.670833333333333, + 6.675, + 6.679166666666666, + 6.683333333333334, + 6.6875, + 6.691666666666666, + 6.695833333333333, + 6.7, + 6.704166666666667, + 6.708333333333333, + 6.7124999999999995, + 6.716666666666667, + 6.720833333333333, + 6.725, + 6.729166666666666, + 6.733333333333333, + 6.7375, + 6.741666666666666, + 6.745833333333334, + 6.75, + 6.754166666666666, + 6.758333333333333, + 6.7625, + 6.766666666666667, + 6.770833333333333, + 6.7749999999999995, + 6.779166666666667, + 6.783333333333333, + 6.7875, + 6.791666666666666, + 6.795833333333333, + 6.8, + 6.804166666666666, + 6.808333333333334, + 6.8125, + 6.816666666666666, + 6.820833333333333, + 6.825, + 6.829166666666667, + 6.833333333333333, + 6.8374999999999995, + 6.841666666666667, + 6.845833333333333, + 6.85, + 6.854166666666666, + 6.858333333333333, + 6.8625, + 6.866666666666666, + 6.870833333333334, + 6.875, + 6.879166666666666, + 6.883333333333333, + 6.8875, + 6.891666666666667, + 6.895833333333333, + 6.8999999999999995, + 6.904166666666667, + 6.908333333333333, + 6.9125, + 6.916666666666666, + 6.920833333333333, + 6.925, + 6.929166666666666, + 6.933333333333334, + 6.9375, + 6.941666666666666, + 6.945833333333333, + 6.95, + 6.954166666666667, + 6.958333333333333, + 6.9624999999999995, + 6.966666666666667, + 6.970833333333333, + 6.975, + 6.979166666666666, + 6.983333333333333, + 6.9875, + 6.991666666666666, + 6.995833333333334, + 7.0, + 7.004166666666666, + 7.008333333333333, + 7.0125, + 7.016666666666667, + 7.020833333333333, + 7.0249999999999995, + 7.029166666666667, + 7.033333333333333, + 7.0375, + 7.041666666666666, + 7.045833333333333, + 7.05, + 7.054166666666666, + 7.058333333333334, + 7.0625, + 7.066666666666666, + 7.070833333333333, + 7.075, + 7.079166666666667, + 7.083333333333333, + 7.0874999999999995, + 7.091666666666667, + 7.095833333333333, + 7.1, + 7.104166666666666, + 7.108333333333333, + 7.1125, + 7.116666666666666, + 7.120833333333334, + 7.125, + 7.129166666666666, + 7.133333333333333, + 7.1375, + 7.141666666666667, + 7.145833333333333, + 7.1499999999999995, + 7.154166666666667, + 7.158333333333333, + 7.1625, + 7.166666666666666, + 7.170833333333333, + 7.175, + 7.179166666666666, + 7.183333333333334, + 7.1875, + 7.191666666666666, + 7.195833333333333, + 7.2, + 7.204166666666667, + 7.208333333333333, + 7.2124999999999995, + 7.216666666666667, + 7.220833333333333, + 7.225, + 7.229166666666666, + 7.233333333333333, + 7.2375, + 7.241666666666666, + 7.245833333333334, + 7.25, + 7.254166666666666, + 7.258333333333333, + 7.2625, + 7.266666666666667, + 7.270833333333333, + 7.2749999999999995, + 7.279166666666667, + 7.283333333333333, + 7.2875, + 7.291666666666666, + 7.295833333333333, + 7.3, + 7.304166666666666, + 7.308333333333334, + 7.3125, + 7.316666666666666, + 7.320833333333333, + 7.325, + 7.329166666666667, + 7.333333333333333, + 7.3374999999999995, + 7.341666666666667, + 7.345833333333333, + 7.35, + 7.354166666666666, + 7.358333333333333, + 7.3625, + 7.366666666666666, + 7.370833333333334, + 7.375, + 7.379166666666666, + 7.383333333333333, + 7.3875, + 7.391666666666667, + 7.395833333333333, + 7.3999999999999995, + 7.404166666666667, + 7.408333333333333, + 7.4125, + 7.416666666666666, + 7.420833333333333, + 7.425, + 7.429166666666666, + 7.433333333333334, + 7.4375, + 7.441666666666666, + 7.445833333333333, + 7.45, + 7.454166666666667, + 7.458333333333333, + 7.4624999999999995, + 7.466666666666667, + 7.470833333333333, + 7.475, + 7.479166666666666, + 7.483333333333333, + 7.4875, + 7.491666666666666, + 7.495833333333334, + 7.5, + 7.504166666666666, + 7.508333333333333, + 7.5125, + 7.516666666666667, + 7.520833333333333, + 7.5249999999999995, + 7.529166666666667, + 7.533333333333333, + 7.5375, + 7.541666666666666, + 7.545833333333333, + 7.55, + 7.554166666666666, + 7.558333333333334, + 7.5625, + 7.566666666666666, + 7.570833333333333, + 7.575, + 7.579166666666667, + 7.583333333333333, + 7.5874999999999995, + 7.591666666666667, + 7.595833333333333, + 7.6, + 7.604166666666666, + 7.608333333333333, + 7.6125, + 7.616666666666666, + 7.620833333333334, + 7.625, + 7.629166666666666, + 7.633333333333333, + 7.6375, + 7.641666666666667, + 7.645833333333333, + 7.6499999999999995, + 7.654166666666667, + 7.658333333333333, + 7.6625, + 7.666666666666666, + 7.670833333333333, + 7.675, + 7.679166666666666, + 7.683333333333334, + 7.6875, + 7.691666666666666, + 7.695833333333333, + 7.7, + 7.704166666666667, + 7.708333333333333, + 7.7124999999999995, + 7.716666666666667, + 7.720833333333333, + 7.725, + 7.729166666666666, + 7.733333333333333, + 7.7375, + 7.741666666666666, + 7.745833333333334, + 7.75, + 7.754166666666666, + 7.758333333333333, + 7.7625, + 7.766666666666667, + 7.770833333333333, + 7.7749999999999995, + 7.779166666666667, + 7.783333333333333, + 7.7875, + 7.791666666666666, + 7.795833333333333, + 7.8, + 7.804166666666666, + 7.808333333333334, + 7.8125, + 7.816666666666666, + 7.820833333333333, + 7.825, + 7.829166666666667, + 7.833333333333333, + 7.8374999999999995, + 7.841666666666667, + 7.845833333333333, + 7.85, + 7.854166666666666, + 7.858333333333333, + 7.8625, + 7.866666666666666, + 7.870833333333334, + 7.875, + 7.879166666666666, + 7.883333333333333, + 7.8875, + 7.891666666666667, + 7.895833333333333, + 7.8999999999999995, + 7.904166666666667, + 7.908333333333333, + 7.9125, + 7.916666666666666, + 7.920833333333333, + 7.925, + 7.929166666666666, + 7.933333333333334, + 7.9375, + 7.941666666666666, + 7.945833333333333, + 7.95, + 7.954166666666667, + 7.958333333333333, + 7.9624999999999995, + 7.966666666666667, + 7.970833333333333, + 7.975, + 7.979166666666666, + 7.983333333333333, + 7.9875, + 7.991666666666666, + 7.995833333333334, + 8.0, + 8.004166666666666, + 8.008333333333333, + 8.0125, + 8.016666666666666, + 8.020833333333334, + 8.025, + 8.029166666666667, + 8.033333333333333, + 8.0375, + 8.041666666666666, + 8.045833333333333, + 8.049999999999999, + 8.054166666666667, + 8.058333333333334, + 8.0625, + 8.066666666666666, + 8.070833333333333, + 8.075, + 8.079166666666666, + 8.083333333333334, + 8.0875, + 8.091666666666667, + 8.095833333333333, + 8.1, + 8.104166666666666, + 8.108333333333333, + 8.112499999999999, + 8.116666666666667, + 8.120833333333334, + 8.125, + 8.129166666666666, + 8.133333333333333, + 8.1375, + 8.141666666666666, + 8.145833333333334, + 8.15, + 8.154166666666667, + 8.158333333333333, + 8.1625, + 8.166666666666666, + 8.170833333333333, + 8.174999999999999, + 8.179166666666667, + 8.183333333333334, + 8.1875, + 8.191666666666666, + 8.195833333333333, + 8.2, + 8.204166666666666, + 8.208333333333334, + 8.2125, + 8.216666666666667, + 8.220833333333333, + 8.225, + 8.229166666666666, + 8.233333333333333, + 8.237499999999999, + 8.241666666666667, + 8.245833333333334, + 8.25, + 8.254166666666666, + 8.258333333333333, + 8.2625, + 8.266666666666666, + 8.270833333333334, + 8.275, + 8.279166666666667, + 8.283333333333333, + 8.2875, + 8.291666666666666, + 8.295833333333333, + 8.299999999999999, + 8.304166666666667, + 8.308333333333334, + 8.3125, + 8.316666666666666, + 8.320833333333333, + 8.325, + 8.329166666666666, + 8.333333333333334, + 8.3375, + 8.341666666666667, + 8.345833333333333, + 8.35, + 8.354166666666666, + 8.358333333333333, + 8.362499999999999, + 8.366666666666667, + 8.370833333333334, + 8.375, + 8.379166666666666, + 8.383333333333333, + 8.3875, + 8.391666666666666, + 8.395833333333334, + 8.4, + 8.404166666666667, + 8.408333333333333, + 8.4125, + 8.416666666666666, + 8.420833333333333, + 8.424999999999999, + 8.429166666666667, + 8.433333333333334, + 8.4375, + 8.441666666666666, + 8.445833333333333, + 8.45, + 8.454166666666666, + 8.458333333333334, + 8.4625, + 8.466666666666667, + 8.470833333333333, + 8.475, + 8.479166666666666, + 8.483333333333333, + 8.487499999999999, + 8.491666666666667, + 8.495833333333334, + 8.5, + 8.504166666666666, + 8.508333333333333, + 8.5125, + 8.516666666666666, + 8.520833333333334, + 8.525, + 8.529166666666667, + 8.533333333333333, + 8.5375, + 8.541666666666666, + 8.545833333333333, + 8.549999999999999, + 8.554166666666667, + 8.558333333333334, + 8.5625, + 8.566666666666666, + 8.570833333333333, + 8.575, + 8.579166666666666, + 8.583333333333334, + 8.5875, + 8.591666666666667, + 8.595833333333333, + 8.6, + 8.604166666666666, + 8.608333333333333, + 8.612499999999999, + 8.616666666666667, + 8.620833333333334, + 8.625, + 8.629166666666666, + 8.633333333333333, + 8.6375, + 8.641666666666666, + 8.645833333333334, + 8.65, + 8.654166666666667, + 8.658333333333333, + 8.6625, + 8.666666666666666, + 8.670833333333333, + 8.674999999999999, + 8.679166666666667, + 8.683333333333334, + 8.6875, + 8.691666666666666, + 8.695833333333333, + 8.7, + 8.704166666666666, + 8.708333333333334, + 8.7125, + 8.716666666666667, + 8.720833333333333, + 8.725, + 8.729166666666666, + 8.733333333333333, + 8.737499999999999, + 8.741666666666667, + 8.745833333333334, + 8.75, + 8.754166666666666, + 8.758333333333333, + 8.7625, + 8.766666666666666, + 8.770833333333334, + 8.775, + 8.779166666666667, + 8.783333333333333, + 8.7875, + 8.791666666666666, + 8.795833333333333, + 8.799999999999999, + 8.804166666666667, + 8.808333333333334, + 8.8125, + 8.816666666666666, + 8.820833333333333, + 8.825, + 8.829166666666666, + 8.833333333333334, + 8.8375, + 8.841666666666667, + 8.845833333333333, + 8.85, + 8.854166666666666, + 8.858333333333333, + 8.862499999999999, + 8.866666666666667, + 8.870833333333334, + 8.875, + 8.879166666666666, + 8.883333333333333, + 8.8875, + 8.891666666666666, + 8.895833333333334, + 8.9, + 8.904166666666667, + 8.908333333333333, + 8.9125, + 8.916666666666666, + 8.920833333333333, + 8.924999999999999, + 8.929166666666667, + 8.933333333333334, + 8.9375, + 8.941666666666666, + 8.945833333333333, + 8.95, + 8.954166666666666, + 8.958333333333334, + 8.9625, + 8.966666666666667, + 8.970833333333333, + 8.975, + 8.979166666666666, + 8.983333333333333, + 8.987499999999999, + 8.991666666666667, + 8.995833333333334, + 9.0, + 9.004166666666666, + 9.008333333333333, + 9.0125, + 9.016666666666666, + 9.020833333333334, + 9.025, + 9.029166666666667, + 9.033333333333333, + 9.0375, + 9.041666666666666, + 9.045833333333333, + 9.049999999999999, + 9.054166666666667, + 9.058333333333334, + 9.0625, + 9.066666666666666, + 9.070833333333333, + 9.075, + 9.079166666666666, + 9.083333333333334, + 9.0875, + 9.091666666666667, + 9.095833333333333, + 9.1, + 9.104166666666666, + 9.108333333333333, + 9.112499999999999, + 9.116666666666667, + 9.120833333333334, + 9.125, + 9.129166666666666, + 9.133333333333333, + 9.1375, + 9.141666666666666, + 9.145833333333334, + 9.15, + 9.154166666666667, + 9.158333333333333, + 9.1625, + 9.166666666666666, + 9.170833333333333, + 9.174999999999999, + 9.179166666666667, + 9.183333333333334, + 9.1875, + 9.191666666666666, + 9.195833333333333, + 9.2, + 9.204166666666666, + 9.208333333333334, + 9.2125, + 9.216666666666667, + 9.220833333333333, + 9.225, + 9.229166666666666, + 9.233333333333333, + 9.237499999999999, + 9.241666666666667, + 9.245833333333334, + 9.25, + 9.254166666666666, + 9.258333333333333, + 9.2625, + 9.266666666666666, + 9.270833333333334, + 9.275, + 9.279166666666667, + 9.283333333333333, + 9.2875, + 9.291666666666666, + 9.295833333333333, + 9.299999999999999, + 9.304166666666667, + 9.308333333333334, + 9.3125, + 9.316666666666666, + 9.320833333333333, + 9.325, + 9.329166666666666, + 9.333333333333334, + 9.3375, + 9.341666666666667, + 9.345833333333333, + 9.35, + 9.354166666666666, + 9.358333333333333, + 9.362499999999999, + 9.366666666666667, + 9.370833333333334, + 9.375, + 9.379166666666666, + 9.383333333333333, + 9.3875, + 9.391666666666666, + 9.395833333333334, + 9.4, + 9.404166666666667, + 9.408333333333333, + 9.4125, + 9.416666666666666, + 9.420833333333333, + 9.424999999999999, + 9.429166666666667, + 9.433333333333334, + 9.4375, + 9.441666666666666, + 9.445833333333333, + 9.45, + 9.454166666666666, + 9.458333333333334, + 9.4625, + 9.466666666666667, + 9.470833333333333, + 9.475, + 9.479166666666666, + 9.483333333333333, + 9.487499999999999, + 9.491666666666667, + 9.495833333333334, + 9.5, + 9.504166666666666, + 9.508333333333333, + 9.5125, + 9.516666666666666, + 9.520833333333334, + 9.525, + 9.529166666666667, + 9.533333333333333, + 9.5375, + 9.541666666666666, + 9.545833333333333, + 9.549999999999999, + 9.554166666666667, + 9.558333333333334, + 9.5625, + 9.566666666666666, + 9.570833333333333, + 9.575, + 9.579166666666666, + 9.583333333333334, + 9.5875, + 9.591666666666667, + 9.595833333333333, + 9.6, + 9.604166666666666, + 9.608333333333333, + 9.612499999999999, + 9.616666666666667, + 9.620833333333334, + 9.625, + 9.629166666666666, + 9.633333333333333, + 9.6375, + 9.641666666666666, + 9.645833333333334, + 9.65, + 9.654166666666667, + 9.658333333333333, + 9.6625, + 9.666666666666666, + 9.670833333333333, + 9.674999999999999, + 9.679166666666667, + 9.683333333333334, + 9.6875, + 9.691666666666666, + 9.695833333333333, + 9.7, + 9.704166666666666, + 9.708333333333334, + 9.7125, + 9.716666666666667, + 9.720833333333333, + 9.725, + 9.729166666666666, + 9.733333333333333, + 9.737499999999999, + 9.741666666666667, + 9.745833333333334, + 9.75, + 9.754166666666666, + 9.758333333333333, + 9.7625, + 9.766666666666666, + 9.770833333333334, + 9.775, + 9.779166666666667, + 9.783333333333333, + 9.7875, + 9.791666666666666, + 9.795833333333333, + 9.799999999999999, + 9.804166666666667, + 9.808333333333334, + 9.8125, + 9.816666666666666, + 9.820833333333333, + 9.825, + 9.829166666666666, + 9.833333333333334, + 9.8375, + 9.841666666666667, + 9.845833333333333, + 9.85, + 9.854166666666666, + 9.858333333333333, + 9.862499999999999, + 9.866666666666667, + 9.870833333333334, + 9.875, + 9.879166666666666, + 9.883333333333333, + 9.8875, + 9.891666666666666, + 9.895833333333334, + 9.9, + 9.904166666666667, + 9.908333333333333, + 9.9125, + 9.916666666666666, + 9.920833333333333, + 9.924999999999999, + 9.929166666666667, + 9.933333333333334, + 9.9375, + 9.941666666666666, + 9.945833333333333, + 9.95, + 9.954166666666666, + 9.958333333333334, + 9.9625, + 9.966666666666667, + 9.970833333333333, + 9.975, + 9.979166666666666, + 9.983333333333333, + 9.987499999999999, + 9.991666666666667, + 9.995833333333334, + 10.0 + ], + "samples": 2403, + "sample_hz": 240, + "dtype": "f32le", + "layout": "frame-major", + "duplicate_times": [ + 1.0, + 1.15 + ], + "frequency_estimator": "20 ms causal filtered derivative of unwrapped bus voltage angle; event angle jumps retained", + "frequency_filter_tau_s": 0.02, + "frequency_units": "Hz deviation from 60 Hz", + "rotor_units": "GENROU omega * 60, Hz deviation from synchronous speed", + "voltage_units": "per unit", + "statistics": { + "pre_fault_max_abs_frequency_hz": 1.8751307040264686e-08, + "bus_peak_abs_frequency_hz": [ + 0.021316164244405248, + 0.02149580844510364, + 0.021495808445081706, + 0.02171327792363338, + 0.021509108219738685, + 0.021758947689290077, + 0.024181887820591996, + 0.022835708595066798, + 0.024303061630924078, + 0.020513071130498616, + 0.021312579251454508, + 0.021401627261861296, + 0.02016858163027441, + 0.020180903394155347, + 0.019823474513176703, + 0.02021454256254394, + 0.0198570369896552, + 0.023679994869649692, + 0.022386471567381234, + 0.023227509515018778, + 0.023917859989411754, + 0.022311994355503725, + 0.02235187165558617, + 0.02094319460594931, + 0.020965594375709502, + 0.01955584898122265, + 0.019368484303724346, + 0.018660533916521005, + 0.018679509711668634, + 0.021503863877937172, + 0.02150604927975598, + 0.021505545438360904, + 0.019792237409984183, + 0.015379913330584739, + 0.01597787245581739, + 0.01800512574327942, + 0.01491837946441077, + 0.015928788145395247, + 0.016778207340570082, + 0.01834254887437707, + 0.018342548874376127, + 0.016414978024755472, + 0.015468591135270764, + 0.01478881572206063, + 0.015379452926619634, + 0.014788737750712096, + 0.018517401304502027, + 0.016413986101875933, + 0.016487493322322813, + 0.016636580306517573, + 0.017477932831486367, + 0.017469283041669524, + 0.016072527567839452, + 0.016062068014173606, + 0.0162755973691484, + 0.016064493877595634, + 0.027218320842744045, + 0.01667337040784582, + 0.01667337040784582, + 0.01627566132031736, + 0.016121712160158886, + 0.016538249447256348, + 0.017626646576301547, + 0.016071182136500696, + 0.01607066910256804, + 0.016887581692682903, + 0.01681782579919412, + 0.016364922534424405, + 0.016873156950707447, + 0.01667021294668655, + 0.01607324196512541, + 0.015995673162916738, + 0.016174868885306646, + 0.016748849764163957, + 0.017670349676239323, + 0.016070482010188573, + 0.02723120763409325, + 0.01607260727984104, + 0.01612545142059191, + 0.01758289913371539, + 0.016804422292361565, + 0.028509080894642276, + 0.028509080894639702, + 0.028705774446675915, + 0.030329898597001827, + 0.03224844150331463, + 0.028709418948368877, + 0.03228209742843505, + 0.028089101988594014, + 0.028434803907349596, + 0.02796618408617343, + 0.029214645282609468, + 0.029307947759451676, + 0.029358974993090484, + 0.025528663340033605, + 0.02723960233075358, + 0.026243937199165342, + 0.02663197637035722, + 0.02844491007123054, + 0.02624532557068748, + 0.02233165236830513, + 0.022331652368297875, + 0.0207838410222257, + 0.02153155085742274, + 0.0240487674970425, + 0.022331652368300783, + 0.02078786245012033, + 0.033989182263935665, + 0.03410915513163394, + 0.031634994348093706, + 0.03166179354433448, + 0.02660697168897742, + 0.02662332623191002, + 0.01661834237749391, + 0.017308539343885147, + 0.016096466260522878, + 0.01988069875239893, + 0.01722602491485962, + 0.019666159155185693, + 0.016630721225584944, + 0.01726790647942319, + 0.019707320450988074, + 0.014864329239524193, + 0.018092848796804648, + 0.014984117664821398, + 0.018130162685756717, + 0.014991586659151594, + 0.018242847837750483, + 0.014940350302528832, + 0.02055456797933879, + 0.023189172389856884, + 0.026310299614542877, + 0.027003633166593977, + 0.037936750844287506, + 0.048996910433674476, + 0.02576576271382525, + 0.02582954076605154, + 0.026738077645768778, + 0.027801137182067656, + 0.0322854121747664, + 0.02940507884575551, + 0.02681694998520511, + 0.03146692928724933, + 0.030012204555866322, + 0.028446041759307178, + 0.020871835469057225, + 0.024133567765571396, + 0.028347787244336235, + 0.02621998471021413, + 0.03550134642691999, + 0.030491647262746436, + 0.028403461472151458, + 0.027784228805141906, + 0.03098995147762805, + 0.025884459116524886, + 0.03547200135125016, + 0.02317706922057635, + 0.02859982658646963, + 0.05801875724908303, + 0.07650483883381158, + 0.08559045276478701, + 0.09258737037703409, + 0.12396400786760395, + 0.10785476810270837, + 0.10776306958626303, + 0.05392915889958936, + 0.11039367159142528, + 0.10991418104280569, + 0.057885953211550184, + 0.12892917934058085, + 0.11214850016368569, + 0.07295700801150032, + 0.08677695780321719, + 0.07053870115816244, + 0.06888552401278704, + 0.08290523488817851, + 0.06973137078045655, + 0.06804777993722547, + 0.08245340349121168, + 0.061231731269390265, + 0.08723300217173323, + 0.10296943366248598, + 0.09382404189407176, + 0.06089676975122378, + 0.0829192775128436, + 0.06128523880953136, + 0.10405195967885557, + 0.09625015387005, + 0.06736324359959893, + 0.06159331800206591, + 0.10416343529269331, + 0.03449665861844962, + 0.04577301987065524, + 0.04269310995934195, + 0.054382097522967604, + 0.0349901370626646, + 0.04683293317283485, + 0.0399794039970365, + 0.030816848037157327, + 0.02951779232654231, + 0.03005350153071965, + 0.03115242532492514, + 0.05145209554580264, + 0.09043157568700616, + 0.041866399556939424, + 0.07081625225544777, + 0.04607842164460085, + 0.05152976829622335, + 0.046012524833927454, + 0.029423886269798645, + 0.019838409595209928, + 0.029514597626381714, + 0.01653174497518832, + 0.03229090830123001, + 0.02982786576202284, + 0.03246511144517994, + 0.027079511981868046, + 0.02685214514043684, + 0.026465263599349566, + 0.023696911718290588, + 0.026551062843583863, + 0.027769309166282338, + 0.027676332919613536, + 0.028519340991736756, + 0.027602283227274396, + 0.020788914706141838, + 0.019885582698768216, + 0.026742361320193662, + 0.027945206322279502, + 0.027681254903183086, + 0.02857395728574614, + 0.028650589500498785, + 0.02057610890937121, + 0.02073439181272406, + 0.02064463188013633, + 0.020761379621248584, + 0.03735448380746239, + 0.0266451750848469, + 0.032422535598521464, + 0.029790536437874365, + 0.025116148231336257, + 0.032480209598585705, + 0.0299642925327153 + ], + "machine_peak_abs_frequency_hz": [ + 0.02213200304985474, + 0.02187202968664686, + 0.022540390946031073, + 0.022275198139436, + 0.026532706367365336, + 0.02611358346127625, + 0.02281408698975305, + 0.022873903878776528, + 0.020950038424579136, + 0.02122927969758004, + 0.020854486875301698, + 0.020075032467546376, + 0.025392410677161942, + 0.025774423727462994, + 0.02398281084460047, + 0.022815270224427434, + 0.02203443904502489, + 0.021759956502761472, + 0.02209835127715738, + 0.019247243533210192, + 0.019251605419797244, + 0.019242064533763058, + 0.019797172705951403, + 0.019803032928880412, + 0.019801633026997896, + 0.02028063245525565, + 0.018455962118680266, + 0.018356202870909343, + 0.027613983924556804, + 0.017223848872471064, + 0.017195003067858216, + 0.032452353793113994, + 0.037748640217022185, + 0.03588295062144816, + 0.03162519535023016, + 0.03176362336938686, + 0.03194252024959937, + 0.02658363305176602, + 0.026641536153773532, + 0.02143676787825577, + 0.03910194263907521, + 0.03917463836442706, + 0.03937454319212905, + 0.04069653061743137, + 0.04031196451935567, + 0.031318331238899225, + 0.016948447370513126, + 0.019439174077008934, + 0.02201003570715986, + 0.04098397870503424, + 0.03189388170325446, + 0.03131153049996939, + 0.031698859376122865, + 0.031323388683423416, + 0.03202166405668444, + 0.0393385513571453, + 0.03898632289891931, + 0.04943702589481643, + 0.05160898016529638, + 0.055939370162555124, + 0.1003985352263202, + 0.07375695669051795, + 0.07058565578460758, + 0.06086310615542949, + 0.08482061584844011, + 0.07904082326316159, + 0.08089827639136268, + 0.0693515000721947, + 0.07100921665442674, + 0.06845507105858394, + 0.06112654720591666, + 0.061145943102825256, + 0.0389003342319932, + 0.03849817734288513, + 0.0523513182380202, + 0.0514844039664714, + 0.05113352340493949, + 0.03919626693837062, + 0.03834573090711116, + 0.03836136317451905, + 0.053567009401127054, + 0.06886727647827641, + 0.053746666682853016, + 0.04432444125311196, + 0.03463229567069797, + 0.03531574032210183, + 0.03537063041167749, + 0.03596911261025265, + 0.03058745138292486, + 0.03084973396200301, + 0.03064934035040044, + 0.029123854631777527, + 0.030824754710405737, + 0.03133399276359503, + 0.02221382573024473, + 0.02068876078264379, + 0.022070180914477825, + 0.02191305972634689, + 0.021595754144428395, + 0.021970147875376204, + 0.03790044954912073, + 0.03202127077186054, + 0.03468491633603268 + ], + "bus_min_voltage_pu": [ + 1.0332570501940463, + 1.01322663695312, + 0.9724387899879015, + 1.0291931658796452, + 1.0131427473217198, + 1.032612306378081, + 1.009082439598357, + 0.9932450626802783, + 1.0085662282918193, + 1.0904556900468036, + 1.079149459475384, + 1.0790620768096357, + 1.044056915478689, + 1.0233108354141927, + 1.0034699819287016, + 1.044134712089141, + 1.0063464188431945, + 1.0342492111039367, + 1.0579573523404284, + 1.0344655055522831, + 1.0392940800281012, + 0.9974941073658077, + 0.9988106264706555, + 1.0343306263928163, + 1.0348657212824985, + 0.9928349289240158, + 0.989702235888624, + 1.0042955967020457, + 1.006181764287026, + 1.0346791915937996, + 1.0340256906850904, + 1.0342208906487997, + 1.0288436132395589, + 1.048204699242809, + 1.0302779171760665, + 1.026090393897003, + 1.0358431865270838, + 1.0097170170032308, + 1.0056764083165939, + 0.9723603030658337, + 1.0063767312142333, + 1.0184857327733325, + 1.0055498459467538, + 1.0175637285968322, + 1.0481619356996623, + 1.0172324228487841, + 1.0070915580993667, + 1.0182479243094014, + 1.025612965327542, + 1.021774338807826, + 1.0078376979071628, + 1.0084277968551147, + 1.0544479381969916, + 1.046458210541716, + 1.0206661782756374, + 1.055209262135142, + 1.0284779169020166, + 1.0185744299297987, + 1.0185744299297987, + 1.0455554477085063, + 1.013351457654591, + 0.9973722155167164, + 1.0007296963520718, + 1.0132177480690256, + 1.0117660898434249, + 0.992044788185747, + 0.9995204755576748, + 1.0032788955664103, + 0.9939875654617475, + 0.9951935531667501, + 1.0093254857763296, + 1.0107597824232917, + 1.0073740803666744, + 1.0102567635125985, + 1.0015638910485027, + 1.0133755240116729, + 1.0283932783924372, + 1.011969590438212, + 1.013396298227609, + 1.1064359722753012, + 1.1161624861760187, + 0.9761529769941333, + 0.9808375854672315, + 0.9877706739849106, + 0.9818529006860902, + 0.9972113271253563, + 0.98771177114359, + 0.9976620842844627, + 0.9968216201636402, + 0.9961363438785844, + 0.9944346984588445, + 1.0056562056192784, + 0.996025242430592, + 1.0079957964284068, + 1.0005685373065742, + 0.9778825149381132, + 0.9924568250936806, + 0.9827892109344182, + 0.9895938505859004, + 0.9934094876798784, + 0.9615739789241043, + 0.9636949127195166, + 0.9963072496542729, + 0.9826427032033721, + 0.9565929520140888, + 0.9636949127195166, + 0.9965890636143346, + 0.9972672489699794, + 0.9976879702799104, + 1.0082957758539606, + 1.0080893741377126, + 0.9957455159405377, + 0.995188912165437, + 1.0460255192984187, + 1.0324903254632802, + 1.0422203446976546, + 0.9981072655839293, + 1.0325578620789084, + 1.0167925306384755, + 1.0458703731070897, + 1.0329370135245297, + 1.016795793752309, + 1.0499116171780873, + 1.0340012100547509, + 1.0314922981112828, + 1.0337824475347386, + 1.0316992769364774, + 1.034148109350924, + 1.0335234626570637, + 1.0204627366170596, + 0.9903496782163166, + 1.018461922202982, + 1.0170148285586236, + 1.021611086479793, + 1.035065289424222, + 0.9635886620093955, + 0.9661998823958667, + 0.9725242081371314, + 0.970880508858868, + 1.0333599865526057, + 1.0152289798339311, + 0.9791688580378567, + 0.9877113649753114, + 0.9917976732689077, + 1.0129608270331076, + 1.002129512836508, + 0.9859400373800826, + 0.9788708796818586, + 0.9780872682873949, + 1.0603555787462116, + 0.9953975848485224, + 1.012113586646165, + 1.000706262855367, + 1.0218285500031656, + 0.9863933816186656, + 1.061668789697309, + 0.989101072294185, + 1.0149441775355417, + 1.0366301212133888, + 1.049144029029927, + 1.0881332423441317, + 0.9960303410588407, + 0.9132694309757363, + 0.9536294029386471, + 0.9549041775419832, + 1.0393801859544824, + 0.9823241057052159, + 0.9759724763266282, + 1.0362217677151584, + 0.9290446964357543, + 0.9917761088552193, + 1.0487750559382718, + 1.0218624095367288, + 1.035274269643179, + 1.03967678051857, + 1.0060300510988427, + 1.0363527314929333, + 1.0409007539797466, + 1.006143826949062, + 1.1146359812901871, + 1.0533133397017374, + 1.044452462317098, + 0.9985806366764565, + 1.1200231103312965, + 1.0590447620281442, + 1.0982567174113693, + 0.9855934525520341, + 0.9595592508558963, + 1.0158065667886849, + 1.1066629754435053, + 0.987486451732778, + 1.0472954005671775, + 1.0535521373535575, + 1.0495648798700814, + 1.057914775753125, + 1.0523137151245558, + 1.0600855170404748, + 1.0527460178556391, + 1.0233736618867029, + 1.0091167384617024, + 1.0023636128230873, + 1.0194109970549134, + 1.0414930743635262, + 1.0471783169019546, + 0.9944887903545141, + 1.0250931437591713, + 1.0369557344694853, + 1.0415343300109419, + 1.037461799625829, + 1.0117052590292954, + 1.0035378463439006, + 1.027754905479058, + 0.9811346948251742, + 1.059156745179536, + 1.030907023586987, + 1.0628471344863522, + 1.0600324362076168, + 1.0243080520382442, + 1.1065467810333738, + 1.0780318195494953, + 1.107827842041906, + 1.0204631308008068, + 1.018426228577071, + 1.0620262762479395, + 1.0209039789044916, + 1.0701734785128167, + 1.0580024615782364, + 1.0492963822969488, + 1.0263880703756945, + 1.0191923523789432, + 0.9862652600414168, + 1.0633479133183859, + 1.0181314049967087, + 1.0134567988895944, + 1.0242058387079487, + 1.0138506060142545, + 1.039578421152772, + 1.0245026275617828, + 1.0622109594856297, + 0.9959618939624236, + 0.9904757292594611, + 1.0636796702911788, + 0.9981445718480827 + ] + }, + "files": { + "frequency.f32": { + "bytes": 2335716, + "sha256": "b7246f9a31c11fbaf71cf2096b56f17eff38d3a95b548e361ebdd7f8dbc5d4f3" + }, + "voltage.f32": { + "bytes": 2335716, + "sha256": "dd22306b958667941a4c81885ba43304105f00cad92db2140132278aac664bf8" + }, + "rotor.f32": { + "bytes": 990036, + "sha256": "53a6ec1b32450176ec3362feb64ca76544f88f3c6ec6bb6811395cd4ec348a39" + } + } +} diff --git a/crates/latkit-cli/examples/wecc240-fault/recording/rotor.f32 b/crates/latkit-cli/examples/wecc240-fault/recording/rotor.f32 new file mode 100644 index 00000000..e1220fad Binary files /dev/null and b/crates/latkit-cli/examples/wecc240-fault/recording/rotor.f32 differ diff --git a/crates/latkit-cli/examples/wecc240-fault/recording/voltage.f32 b/crates/latkit-cli/examples/wecc240-fault/recording/voltage.f32 new file mode 100644 index 00000000..62696820 Binary files /dev/null and b/crates/latkit-cli/examples/wecc240-fault/recording/voltage.f32 differ diff --git a/crates/latkit-cli/examples/wecc240-fault/render.py b/crates/latkit-cli/examples/wecc240-fault/render.py new file mode 100644 index 00000000..d2714685 --- /dev/null +++ b/crates/latkit-cli/examples/wecc240-fault/render.py @@ -0,0 +1,224 @@ +"""Render the saved WECC240 fault with the Latkit CLI, including native H.264 encoding.""" + +import argparse +import hashlib +import json +import math +import os +import subprocess +import time +from pathlib import Path + +EXAMPLE = Path(__file__).resolve().parent +REPO = EXAMPLE.parents[3] +W, H, FPS = 1920, 1080, 60 +PANELS = ["0,0,0.68,1", "0.68,0,0.32,0.5", "0.68,0.5,0.32,0.5"] +PALETTE = ["#3972fa", "#52c6ea", "#829aa6", "#ffbd68", "#fc624e"] + + +def read(path): + return json.loads(path.read_text(encoding="utf-8-sig")) + + +def write(path, value): + path.write_text(json.dumps(value, indent=2, allow_nan=False) + "\n", encoding="utf-8") + + +def op(name, *args): + return {"op": name, "args": list(args)} + + +def playback(): + frames = [] + for start, end, speed in [(0, 0.75, 0.5), (0.75, 1.5, 0.1), (1.5, 10, 0.5)]: + count = round((end - start) * FPS / speed) + frames.extend(round(start + k * speed / FPS, 12) for k in range(count)) + return frames + [10.0] + + +def camera(at): + u = max(0, min(1, at / 10)) + return { + "center": [-115.6, 40.7], "zoom": math.log2(60), "pitch": 35, + "bearing": -8 + 16 * u * u * (3 - 2 * u), + } + + +def status(at): + return "PRE-FAULT" if at < 1 else "FAULT ON" if at < 1.15 else "FAULT CLEARED" + + +def prepare(work, frames): + work.mkdir(parents=True, exist_ok=True) + case = read(EXAMPLE / "source.case.json") + meta = read(EXAMPLE / "recording/metadata.json") + times, ids = meta["times"], meta["bus_ids"] + for name, expected in meta["files"].items(): + data = (EXAMPLE / "recording" / name).read_bytes() + if len(data) != expected["bytes"] or hashlib.sha256(data).hexdigest() != expected["sha256"]: + raise ValueError(f"The saved recording changed: {name}") + if not times[0] <= frames[0] <= frames[-1] <= times[-1]: + raise ValueError("Render times lie outside the simulation") + by_id = {b["number"]: b for b in case["buses"]} + buses = [by_id[i] for i in ids] + branches = [d for d in case["devices"] if d["class"] == "Branch"] + machines = {d["id"]: d for d in case["devices"] if d["class"] == "Genrou"} + ordered_machines = [machines[i] for i in meta["machine_ids"]] + selected = [max(range(len(ordered_machines)), key=lambda i: meta["statistics"]["machine_peak_abs_frequency_hz"][i])] + rotor_names = [meta["machine_ids"][i].removesuffix("_genrou") for i in selected] + voltage_ids = [4005] + + def column(name, rows): + return { + "file": os.path.relpath(EXAMPLE / "recording" / name, work).replace(os.sep, "/"), + "dtype": "f32le", "count": len(times) * rows, + } + + named = {i: by_id[i]["name"].strip() for i in [1001, 2201]} + named[4005] = f"4005 / {status(frames[0])}" + patch = [ + {"axis": {"name": "time", "unit": "s"}}, + {"replace": {"table": "Bus", "ids": ids, "fields": { + "lon": [b["extension"]["longitude"] for b in buses], + "lat": [b["extension"]["latitude"] for b in buses], + "label": [named.get(i, "") for i in ids], + "priority": [1000 if i == 4005 else 1 for i in ids], + "is_fault": [i == 4005 for i in ids], + "faulted": [i == 4005 and 1 <= frames[0] < 1.15 for i in ids], + "voltage_trace": [i in voltage_ids for i in ids], + }}}, + {"replace": {"table": "Branch", "ids": [b["id"] for b in branches], "fields": { + "from": {"reference": "Bus", "ids": [b["ports"]["bus1"] for b in branches]}, + "to": {"reference": "Bus", "ids": [b["ports"]["bus2"] for b in branches]}, + "width": [0.8 + min(by_id[b["ports"]["bus1"]]["params"]["kv"], by_id[b["ports"]["bus2"]]["params"]["kv"]) / 500 + for b in branches], + }}}, + {"replace": {"table": "Machine", "ids": meta["machine_ids"], "fields": { + "traced": [i in selected for i in range(len(ordered_machines))], + }}}, + {"append": {"at": times, "table": "Bus", "fields": { + "df": column("frequency.f32", len(ids)), "vm": column("voltage.f32", len(ids)), + }}}, + {"append": {"at": times, "table": "Machine", "fields": { + "df": column("rotor.f32", len(ordered_machines)), + }}}, + ] + write(work / "grid.json", {"name": "grid", "patch": patch}) + # The original samples fit in memory for 243 buses. No interpolated cache is needed: + # Latkit reads at each frame's time and preserves the duplicate event timestamps. + x = op("div", op("abs", "df"), 0.01) + magnitude = op("ln", op("add", x, op("sqrt", op("add", op("mul", x, x), 1)))) + signed = {"when": [[op("lt", "df", 0), op("neg", magnitude)]], "otherwise": magnitude} + elevation = op("mul", signed, 1.4 / math.asinh(0.1 / 0.01)) + theme = {"background": "#0a111b", "text": "#d5e1ed", "font": "Segoe UI, sans-serif", "fontSize": 17} + map_scene = { + "space": {"plane": {"grid": "off"}}, "ease": 0, + "theme": {**theme, "edge": None, "laneBow": 0}, + "title": "WECC 240 / FAULT RESPONSE", + "subtitle": "JOHN DAY / Bus 4005 / Applied 1.00 s / Cleared 1.15 s", + "marks": [ + {"lines": {"of": ["states", "polygons"], "color": "#58718b70", "width": 0.9}}, + {"edges": {"of": ["grid", "Branch"], "ends": ["from", "to"], "width": "width"}}, + {"vertices": { + "of": ["grid", "Bus"], "position": ["lon", "lat"], "elevation": elevation, + "radius": {"when": [["faulted", 8], ["is_fault", 5]], "otherwise": 2.8}, + "color": {"colormap": {"kind": "diverging", "colors": PALETTE}, "value": "df", "domain": [-0.1, 0.1]}, + "label": {"text": "label", "size": 15, "priority": "priority"}, + "legend": "Bus frequency deviation / Hz", + }}, + ], + } + + def plot(title, table, field, visible, color): + return { + "space": {"plot": {"x": {"label": "Simulation time / s"}, + "y": {"label": title, "precision": 3 if field == "df" else 2}}}, + "ease": 0, "theme": {**theme, "background": "#101b28", "fontSize": 14, "playhead": "#f3f7fc"}, + "marks": [{"lines": { + "of": ["grid", table], "trace": field, "width": 2.0, "visible": visible, + "color": color, + }}], + } + + write(work / "map.json", map_scene) + write(work / "rotor.json", plot(f"{rotor_names[0]} / Rotor speed deviation / Hz", + "Machine", "df", "traced", "#ffcb72")) + write(work / "voltage.json", plot("4005 / JOHN DAY / Voltage / p.u.", + "Bus", "vm", "voltage_trace", "#66d6ef")) + write(work / "map-camera.json", camera(frames[0])) + write(work / "rotor-camera.json", {"x": [0, 10], "y": [-0.05, 0.12]}) + write(work / "voltage-camera.json", {"x": [0, 10], "y": [0.88, 1.12]}) + previous_status = status(frames[0]) + with (work / "frames.jsonl").open("w", encoding="utf-8", newline="\n") as stream: + for at in frames: + frame = {"at": at, "camera": [camera(at), None, None]} + phase = status(at) + if phase != previous_status: + frame["patch"] = {"grid": [{"set": {"table": "Bus", "ids": [4005], "fields": { + "label": [f"4005 / {phase}"], "faulted": [phase == "FAULT ON"], + }}}]} + previous_status = phase + stream.write(json.dumps(frame, allow_nan=False) + "\n") + return { + "bus_count": len(ids), "branch_count": len(branches), "machine_count": len(ordered_machines), + "traced_machines": rotor_names, "traced_bus_ids": voltage_ids, + "events": meta["study"]["events"], "gridkit_image_id": meta["image_id"], + "recording_hashes": meta["files"], "frames": len(frames), "fps": FPS, + "resolution": [W, H], "seconds": len(frames) / FPS, + "simulation_start_s": frames[0], "simulation_end_s": frames[-1], + "playback": "0.5x before 0.75 s; 0.1x from 0.75 to 1.5 s; 0.5x thereafter", + "color_domain_hz": [-0.1, 0.1], + "height": "1.4 * asinh(df / 0.01) / asinh(0.1 / 0.01); exaggerated visual displacement", + } + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + default_cli = REPO / "target/cli" / ("latkit.exe" if os.name == "nt" else "latkit") + parser.add_argument("--cli", default=str(default_cli) if default_cli.exists() else "latkit") + parser.add_argument("--work", type=Path, default=REPO / "target/wecc240-fault/render") + parser.add_argument("--output", type=Path, default=EXAMPLE) + parser.add_argument("--preview", action="store_true") + parser.add_argument("--at", type=float, default=1.12) + parser.add_argument("--limit", type=int) + parser.add_argument("--prepare-only", action="store_true") + args = parser.parse_args() + if args.limit is not None and args.limit < 1: + parser.error("--limit must be positive") + frames = [args.at] if args.preview else playback() + if args.limit is not None: + frames = frames[:args.limit] + work, output = args.work.resolve(), args.output.resolve() + metadata = prepare(work, frames) + output.mkdir(parents=True, exist_ok=True) + result = output / ("preview.png" if args.preview else "animation.mp4") + inputs = [str(work / f"{name}.json") for name in ("map", "rotor", "voltage")] + inputs += ["--data", str(work / "grid.json"), "--data", + f"states={EXAMPLE.parent / 'branch-opening/states.geojson'}"] + for panel in PANELS: + inputs += ["--panel", panel] + for name in ("map", "rotor", "voltage"): + inputs += ["--camera", str(work / f"{name}-camera.json")] + inputs += ["--at", str(args.at)] if args.preview else ["--frames", str(work / "frames.jsonl")] + inputs += ["--deadline", "120", "--insets", "20,12,12,8"] + if os.name == "nt": + inputs += ["--font", "C:/Windows/Fonts/segoeui.ttf"] + command = [args.cli, "render", *inputs, "--size", f"{W}x{H}", "--fps", str(FPS), + "--bitrate", "14000000", "--output", str(result)] + print(subprocess.list2cmdline(command), flush=True) + if args.prepare_only: + return + subprocess.run([args.cli, "validate", *inputs], check=True) + started = time.perf_counter() + subprocess.run(command, check=True) + metadata.update({ + "render_seconds": time.perf_counter() - started, "output_bytes": result.stat().st_size, + "command": [part.replace(str(REPO), "").replace(os.sep, "/") for part in command], + "sha256": hashlib.sha256(result.read_bytes()).hexdigest(), + }) + write(result.with_suffix(".json"), metadata) + print(f"Saved {result}: {metadata['output_bytes'] / 1e6:.2f} MB in {metadata['render_seconds']:.2f} s", flush=True) + + +if __name__ == "__main__": + main() diff --git a/crates/latkit-cli/examples/wecc240-fault/simulate.py b/crates/latkit-cli/examples/wecc240-fault/simulate.py new file mode 100644 index 00000000..e478e442 --- /dev/null +++ b/crates/latkit-cli/examples/wecc240-fault/simulate.py @@ -0,0 +1,172 @@ +"""Simulate the reference WECC240 fault with GridKit; compact the monitors for Latkit.""" + +import argparse +import csv +import hashlib +import json +import math +import re +import struct +import subprocess +import time +from pathlib import Path + +EXAMPLE = Path(__file__).resolve().parent +REPO = EXAMPLE.parents[3] +IMAGE = "ghcr.io/lukelowry/gridkit:develop-perf" +TAU = 0.02 +EVENTS = [ + {"time": 1.0, "type": "fault_on", "bus": 4005, "R": 0.0, "X": 0.01}, + {"time": 1.15, "type": "fault_off", "bus": 4005}, +] + + +def read(path): + return json.loads(path.read_text(encoding="utf-8-sig")) + + +def write(path, value): + path.write_text(json.dumps(value, indent=2, allow_nan=False) + "\n", encoding="utf-8") + + +def sha(path): + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def simulate(work, image): + work.mkdir(parents=True, exist_ok=True) + source = EXAMPLE / "source.case.json" + case = read(source) + # Only monitor selection and monitor names change; physical inputs remain untouched. + for bus in case["buses"]: + bus["name"] = str(bus["number"]) + bus["mon"] = ["Vm", "Va"] + for device in case["devices"]: + device.pop("mon", None) + if device["class"] == "Genrou": + device["mon"] = ["omega"] + for signal in case["signals"]: + signal.pop("mon", None) + (work / "case.json").write_text(json.dumps(case, separators=(",", ":")), encoding="utf-8") + study = { + "system_model_file": "case.json", "output_file": "monitor.csv", + "dt_monitor": 1 / 240, "tmax": 10.0, "max_steps": 1_000_000, + "rel_tol": 1e-7, "abs_tol": 1e-9, "events": EVENTS, + } + write(work / "study.json", study) + info = json.loads(subprocess.check_output(["docker", "image", "inspect", image]))[0] + command = [ + "docker", "run", "--rm", "--pull=never", "--network=none", "--cpus", "2", + "--env", "OMP_NUM_THREADS=2", "--env", "OPENBLAS_NUM_THREADS=1", + "--mount", f"type=bind,source={work},target=/workspace", + "--workdir", "/workspace", info["Id"], "DynamicSimulation", "study.json", + ] + started = time.perf_counter() + with (work / "solver.log").open("wb") as log: + result = subprocess.run(command, stdout=log, stderr=subprocess.STDOUT) + metadata = { + "image": image, "image_id": info["Id"], "image_labels": info["Config"]["Labels"], + "source": "ORNL/GridKit/cases/PhasorDynamics/WECC240/WECC240.case.json", + "source_sha256": sha(source), "prepared_case_sha256": sha(work / "case.json"), + "study": study, "exit_code": result.returncode, + "simulation_wall_seconds": time.perf_counter() - started, + } + write(work / "simulation.json", metadata) + if result.returncode: + raise RuntimeError((work / "solver.log").read_text(errors="replace")) + return metadata + + +def compact(work): + metadata = read(work / "simulation.json") + if metadata["exit_code"] != 0 or metadata["source_sha256"] != sha(EXAMPLE / "source.case.json"): + raise ValueError("The saved simulation must match the included case and have completed successfully") + case = read(EXAMPLE / "source.case.json") + buses = case["buses"] + machines = [d for d in case["devices"] if d["class"] == "Genrou"] + ids = [b["number"] for b in buses] + destination = EXAMPLE / "recording" + destination.mkdir(exist_ok=True) + times, duplicate_times = [], [] + frequency = [0.0] * len(ids) + previous = None + peaks = [0.0] * len(ids) + machine_peaks = [0.0] * len(machines) + voltage_min = [math.inf] * len(ids) + pre_event_peak = 0.0 + with (work / "monitor.csv").open(newline="") as stream, \ + (destination / "frequency.f32").open("wb") as frequencies, \ + (destination / "voltage.f32").open("wb") as voltages, \ + (destination / "rotor.f32").open("wb") as rotors: + rows = csv.reader(stream) + header = next(rows) + vm = [header.index(f"Bus_{i}_Vm") for i in ids] + va = [header.index(f"Bus_{i}_Va") for i in ids] + omega = [header.index(f"Genrou_{d['id']}_omega") for d in machines] + for line in rows: + row = [float(value) for value in line] + if len(row) != len(header) or not all(math.isfinite(v) for v in row): + raise ValueError("Malformed or nonfinite monitor row") + at, theta = row[0], [row[i] for i in va] + if previous is not None: + dt = at - times[-1] + if dt < 0: + raise ValueError("Monitor time reversed") + delta = [(a - b + math.pi) % (2 * math.pi) - math.pi + for a, b in zip(theta, previous)] + if dt == 0: + duplicate_times.append(at) + frequency = [f + d / (2 * math.pi * TAU) for f, d in zip(frequency, delta)] + else: + decay = math.exp(-dt / TAU) + frequency = [decay * f + (1 - decay) * d / (2 * math.pi * dt) + for f, d in zip(frequency, delta)] + volts = [row[i] for i in vm] + # GENROU omega is per-unit speed deviation, not absolute speed. + rotor = [case["params"]["freq_base"] * row[i] for i in omega] + for values, output in ((frequency, frequencies), (volts, voltages), (rotor, rotors)): + output.write(struct.pack(f"<{len(values)}f", *values)) + peaks = [max(p, abs(f)) for p, f in zip(peaks, frequency)] + machine_peaks = [max(p, abs(f)) for p, f in zip(machine_peaks, rotor)] + voltage_min = [min(a, b) for a, b in zip(voltage_min, volts)] + if at < 1: + pre_event_peak = max(pre_event_peak, max(map(abs, frequency))) + previous = theta + times.append(at) + if len(times) != 2403 or times[-1] != 10 or duplicate_times != [1.0, 1.15]: + raise ValueError("Expected 240 Hz over 0–10 s, retaining both sides of both events") + if pre_event_peak > 1e-5: + raise ValueError("The pre-fault state did not remain at equilibrium") + metadata.update({ + "bus_ids": ids, "machine_ids": [d["id"] for d in machines], + "machine_bus_ids": [d["ports"]["bus"] for d in machines], + "times": times, "samples": len(times), "sample_hz": 240, + "dtype": "f32le", "layout": "frame-major", "duplicate_times": duplicate_times, + "frequency_estimator": "20 ms causal filtered derivative of unwrapped bus voltage angle; event angle jumps retained", + "frequency_filter_tau_s": TAU, "frequency_units": "Hz deviation from 60 Hz", + "rotor_units": "GENROU omega * 60, Hz deviation from synchronous speed", + "voltage_units": "per unit", + "statistics": { + "pre_fault_max_abs_frequency_hz": pre_event_peak, + "bus_peak_abs_frequency_hz": peaks, "machine_peak_abs_frequency_hz": machine_peaks, + "bus_min_voltage_pu": voltage_min, + }, + "files": {name: {"bytes": (destination / name).stat().st_size, "sha256": sha(destination / name)} + for name in ("frequency.f32", "voltage.f32", "rotor.f32")}, + }) + write(destination / "metadata.json", metadata) + log = re.sub(r"\x1b\[[0-9;]*m", "", (work / "solver.log").read_text()) + (EXAMPLE / "solver.txt").write_text(log, encoding="utf-8") + print(f"Saved {len(times)} samples: {len(ids)} buses, {len(machines)} synchronous machines.", flush=True) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--work", type=Path, default=REPO / "target/wecc240-fault") + parser.add_argument("--image", default=IMAGE) + parser.add_argument("--reuse", action="store_true", help="compact an existing successful run") + args = parser.parse_args() + work = args.work.resolve() + if not args.reuse: + simulate(work, args.image) + compact(work) diff --git a/crates/latkit-cli/examples/wecc240-fault/solver.txt b/crates/latkit-cli/examples/wecc240-fault/solver.txt new file mode 100644 index 00000000..1c4b35d0 --- /dev/null +++ b/crates/latkit-cli/examples/wecc240-fault/solver.txt @@ -0,0 +1,3 @@ +[WARNING] Hygov: Tr, Tf, Tg, Tw, and Tnp below 0.001 s are raised to preserve Hessenberg form +[WARNING] Repca: initial reactive PI output is outside [Qmin, Qmax]; the limits are adjusted to include the initialized value +[SUMMARY] Complete in 0.507613 seconds diff --git a/crates/latkit-cli/examples/wecc240-fault/source.case.json b/crates/latkit-cli/examples/wecc240-fault/source.case.json new file mode 100644 index 00000000..4ca0379a --- /dev/null +++ b/crates/latkit-cli/examples/wecc240-fault/source.case.json @@ -0,0 +1,27581 @@ +{ + "header": { + "format_version": 0.2, + "format_revision": 0, + "case_name": "WECC240", + "case_description": "", + "case_comments": "" + }, + "params": { + "freq_base": 60.0, + "va_base": 100000000.0 + }, + "buses": [ + { + "number": 1001, + "class": "Bus", + "name": "FOURCORN", + "init": { + "Vr": 1.0291178854372438, + "Vi": 0.10050546385827296 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 37.79104, + "longitude": -113.740793 + } + }, + { + "number": 1002, + "class": "Bus", + "name": "FOURCORN", + "init": { + "Vr": 1.0032050288440562, + "Vi": 0.1475662615574077 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 37.321766, + "longitude": -112.086864 + } + }, + { + "number": 1003, + "class": "Bus", + "name": "FOURCORN", + "init": { + "Vr": 0.9731683917939695, + "Vi": -0.004970202771357422 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 36.652361, + "longitude": -111.331526 + } + }, + { + "number": 1004, + "class": "Bus", + "name": "SAN JUAN", + "init": { + "Vr": 0.9750083889067531, + "Vi": 0.33205210625568937 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 37.948556, + "longitude": -109.788292 + } + }, + { + "number": 1032, + "class": "Bus", + "name": "FCNGN4CC", + "init": { + "Vr": 1.0015564684871028, + "Vi": 0.15773042379182503 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 36.598981, + "longitude": -112.054306 + } + }, + { + "number": 1034, + "class": "Bus", + "name": "SJUAN G4", + "init": { + "Vr": 0.9684387912559518, + "Vi": 0.3606341824247621 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 37.09398, + "longitude": -109.788292 + } + }, + { + "number": 1101, + "class": "Bus", + "name": "CORONADO", + "init": { + "Vr": 0.9817288403261187, + "Vi": -0.2372941158573136 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 35.998612, + "longitude": -114.346366 + } + }, + { + "number": 1102, + "class": "Bus", + "name": "CHOLLA", + "init": { + "Vr": 0.9911787882031262, + "Vi": -0.08302254767036511 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 36.668367, + "longitude": -113.350101 + } + }, + { + "number": 1131, + "class": "Bus", + "name": "CORONADO", + "init": { + "Vr": 0.9841390269038477, + "Vi": -0.22466520004927026 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 35.247111, + "longitude": -113.350101 + } + }, + { + "number": 1201, + "class": "Bus", + "name": "MOENKOPI", + "init": { + "Vr": 1.0840856880765497, + "Vi": -0.12579664590720174 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 37.168218, + "longitude": -114.613339 + } + }, + { + "number": 1202, + "class": "Bus", + "name": "NAVAJO", + "init": { + "Vr": 1.077540070445575, + "Vi": -0.07285279279270523 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 37.943311, + "longitude": -114.782639 + } + }, + { + "number": 1232, + "class": "Bus", + "name": "NAVAJO 2", + "init": { + "Vr": 1.0783785013749112, + "Vi": -0.057202406790463976 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 37.675315, + "longitude": -116.156573 + } + }, + { + "number": 1301, + "class": "Bus", + "name": "MEAD", + "init": { + "Vr": 1.0295416878422843, + "Vi": -0.1790777485711603 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 37.938065, + "longitude": -117.908175 + } + }, + { + "number": 1302, + "class": "Bus", + "name": "H ALLEN", + "init": { + "Vr": 1.0031906476403882, + "Vi": -0.20748574427235075 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 38.361733, + "longitude": -116.924934 + } + }, + { + "number": 1303, + "class": "Bus", + "name": "H ALLEN", + "init": { + "Vr": 0.9697210881035389, + "Vi": -0.26394325445288835 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 38.523226, + "longitude": -116.091457 + } + }, + { + "number": 1331, + "class": "Bus", + "name": "HOOVER", + "init": { + "Vr": 1.0327887989266924, + "Vi": -0.15963854865450935 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 38.507614, + "longitude": -118.077475 + } + }, + { + "number": 1333, + "class": "Bus", + "name": "H ALLEN", + "init": { + "Vr": 0.9789437262325904, + "Vi": -0.23992078469011754 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 39.010702, + "longitude": -116.924934 + } + }, + { + "number": 1401, + "class": "Bus", + "name": "PALOVRDE", + "init": { + "Vr": 1.0007416182190785, + "Vi": -0.2640855482760244 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 34.976431, + "longitude": -115.32312 + } + }, + { + "number": 1402, + "class": "Bus", + "name": "WESTWING", + "init": { + "Vr": 0.992803796506842, + "Vi": -0.3683836828133849 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 36.561594, + "longitude": -115.961227 + } + }, + { + "number": 1403, + "class": "Bus", + "name": "PARKER", + "init": { + "Vr": 1.002713928087405, + "Vi": -0.2575738183209373 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.113847, + "longitude": -115.829421 + } + }, + { + "number": 1431, + "class": "Bus", + "name": "PALOVRD2", + "init": { + "Vr": 1.0156571770372371, + "Vi": -0.2238705814068629 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 34.729446, + "longitude": -115.238446 + } + }, + { + "number": 2000, + "class": "Bus", + "name": "MEXICO", + "init": { + "Vr": 0.9574411831779276, + "Vi": -0.28862849322034656 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 34.297952, + "longitude": -118.241794 + } + }, + { + "number": 2030, + "class": "Bus", + "name": "MEXICO", + "init": { + "Vr": 0.9622086686257666, + "Vi": -0.2772296896864369 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 34.150117, + "longitude": -118.177975 + } + }, + { + "number": 2100, + "class": "Bus", + "name": "IMPERIAL", + "init": { + "Vr": 1.0106471695431412, + "Vi": -0.2231978164697469 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.212286, + "longitude": -116.144263 + } + }, + { + "number": 2130, + "class": "Bus", + "name": "IMPERIAL", + "init": { + "Vr": 1.0125355376272693, + "Vi": -0.2170399742555953 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 35.444485, + "longitude": -115.867712 + } + }, + { + "number": 2201, + "class": "Bus", + "name": "MIGUEL", + "init": { + "Vr": 0.8892165103680651, + "Vi": -0.4436522372250774 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 34.718903, + "longitude": -118.331141 + } + }, + { + "number": 2202, + "class": "Bus", + "name": "MIGUEL", + "init": { + "Vr": 0.8770950011639516, + "Vi": -0.4605788667938676 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 34.496665, + "longitude": -118.684275 + } + }, + { + "number": 2203, + "class": "Bus", + "name": "MISSION", + "init": { + "Vr": 0.8879448550434562, + "Vi": -0.47072173767196135 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 34.934562, + "longitude": -119.041664 + } + }, + { + "number": 2233, + "class": "Bus", + "name": "MISSION", + "init": { + "Vr": 0.8918895552561795, + "Vi": -0.46722178204038184 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 35.098921, + "longitude": -118.914025 + } + }, + { + "number": 2301, + "class": "Bus", + "name": "IMPRLVLY", + "init": { + "Vr": 1.000405604495706, + "Vi": -0.26766941321129933 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 34.850762, + "longitude": -117.880151 + } + }, + { + "number": 2302, + "class": "Bus", + "name": "IMPRLVLY", + "init": { + "Vr": 1.0047474357675403, + "Vi": -0.24841006440961605 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 34.538755, + "longitude": -117.812077 + } + }, + { + "number": 2332, + "class": "Bus", + "name": "IMPRLVLY", + "init": { + "Vr": 1.0059463388354748, + "Vi": -0.2443372613350076 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 34.376289, + "longitude": -117.756767 + } + }, + { + "number": 2400, + "class": "Bus", + "name": "DEVERS", + "init": { + "Vr": 0.9687697509488613, + "Vi": -0.3485044292044673 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 35.218248, + "longitude": -117.433415 + } + }, + { + "number": 2401, + "class": "Bus", + "name": "LUGO", + "init": { + "Vr": 1.020185317104043, + "Vi": -0.24861917121833166 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 36.298976, + "longitude": -118.960826 + } + }, + { + "number": 2402, + "class": "Bus", + "name": "MIRALOMA", + "init": { + "Vr": 0.9812428318038446, + "Vi": -0.3189001946872327 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 35.761927, + "longitude": -120.296779 + } + }, + { + "number": 2403, + "class": "Bus", + "name": "VALLEY", + "init": { + "Vr": 0.9496430311917626, + "Vi": -0.39128519368666664 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 35.176503, + "longitude": -118.182229 + } + }, + { + "number": 2404, + "class": "Bus", + "name": "VINCENT", + "init": { + "Vr": 1.023581697567488, + "Vi": -0.17919105886843667 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 36.525085, + "longitude": -119.411817 + } + }, + { + "number": 2405, + "class": "Bus", + "name": "SYLMAR S", + "init": { + "Vr": 0.9927278917027919, + "Vi": -0.19378213071990696 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.767849, + "longitude": -119.305451 + } + }, + { + "number": 2406, + "class": "Bus", + "name": "EAGLROCK", + "init": { + "Vr": 0.9735893514354769, + "Vi": -0.2602517408174836 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.631543, + "longitude": -119.60753 + } + }, + { + "number": 2407, + "class": "Bus", + "name": "LITEHIPE", + "init": { + "Vr": 0.9107761107658282, + "Vi": -0.34771665985036765 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.340375, + "longitude": -119.960664 + } + }, + { + "number": 2408, + "class": "Bus", + "name": "MESA CAL", + "init": { + "Vr": 0.9960829983667543, + "Vi": -0.16093347539392014 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.489062, + "longitude": -120.011719 + } + }, + { + "number": 2409, + "class": "Bus", + "name": "MIRALOMA", + "init": { + "Vr": 0.9657092502933803, + "Vi": -0.3283376653103315 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.295716, + "longitude": -120.322307 + } + }, + { + "number": 2410, + "class": "Bus", + "name": "PARDEE", + "init": { + "Vr": 0.9741576354525452, + "Vi": -0.2554786962820719 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.912788, + "longitude": -119.428835 + } + }, + { + "number": 2411, + "class": "Bus", + "name": "VINCENT", + "init": { + "Vr": 1.0001435873014726, + "Vi": -0.20195836646429502 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 36.293094, + "longitude": -119.582002 + } + }, + { + "number": 2431, + "class": "Bus", + "name": "LUGO", + "init": { + "Vr": 1.0202564793923456, + "Vi": -0.24814636216204305 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 36.87031, + "longitude": -118.731076 + } + }, + { + "number": 2434, + "class": "Bus", + "name": "VINCENT", + "init": { + "Vr": 0.9999165296632286, + "Vi": -0.20141225118379424 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 36.348723, + "longitude": -119.73175 + } + }, + { + "number": 2438, + "class": "Bus", + "name": "MESA CAL", + "init": { + "Vr": 1.000573076456902, + "Vi": -0.13623958120764726 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 35.486091, + "longitude": -120.798825 + } + }, + { + "number": 2439, + "class": "Bus", + "name": "MIRALOMA", + "init": { + "Vr": 0.965799645483867, + "Vi": -0.3273326397192824 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 35.018277, + "longitude": -120.420163 + } + }, + { + "number": 2501, + "class": "Bus", + "name": "SERRANO", + "init": { + "Vr": 0.9633415436055629, + "Vi": -0.35580217762303923 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 35.322514, + "longitude": -119.37778 + } + }, + { + "number": 2502, + "class": "Bus", + "name": "SERRANO", + "init": { + "Vr": 0.9513187283801735, + "Vi": -0.3767703855060677 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.018277, + "longitude": -119.586256 + } + }, + { + "number": 2503, + "class": "Bus", + "name": "S.ONOFRE", + "init": { + "Vr": 0.9248147380467772, + "Vi": -0.40348310205813004 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 34.757883, + "longitude": -119.509673 + } + }, + { + "number": 2533, + "class": "Bus", + "name": "S.ONOFRE", + "init": { + "Vr": 0.9290778821775172, + "Vi": -0.3950762656465426 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 34.607858, + "longitude": -119.77346 + } + }, + { + "number": 2600, + "class": "Bus", + "name": "ADELANTO", + "init": { + "Vr": 1.0417157975318705, + "Vi": -0.1718999503042707 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 36.522153, + "longitude": -116.91435 + } + }, + { + "number": 2601, + "class": "Bus", + "name": "RINALDI", + "init": { + "Vr": 1.0326042911106608, + "Vi": -0.1787074418783699 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 36.390086, + "longitude": -117.654656 + } + }, + { + "number": 2602, + "class": "Bus", + "name": "STA E", + "init": { + "Vr": 1.0086893651068751, + "Vi": -0.1676346330837567 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 36.248967, + "longitude": -116.880313 + } + }, + { + "number": 2603, + "class": "Bus", + "name": "VICTORVL", + "init": { + "Vr": 1.040439629599286, + "Vi": -0.1840136012542966 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 36.727142, + "longitude": -117.484471 + } + }, + { + "number": 2604, + "class": "Bus", + "name": "INTERMT", + "init": { + "Vr": 1.0282510831640337, + "Vi": -0.05999710691454806 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 40.483424, + "longitude": -114.886823 + } + }, + { + "number": 2605, + "class": "Bus", + "name": "STA B1", + "init": { + "Vr": 1.012818757596012, + "Vi": -0.12872909805887428 + }, + "params": { + "kv": 287.0 + }, + "mon": [], + "extension": { + "latitude": 35.782651, + "longitude": -118.288595 + } + }, + { + "number": 2606, + "class": "Bus", + "name": "STA B2", + "init": { + "Vr": 1.012818757596012, + "Vi": -0.12872909805887428 + }, + "params": { + "kv": 287.0 + }, + "mon": [], + "extension": { + "latitude": 35.729351, + "longitude": -118.497072 + } + }, + { + "number": 2607, + "class": "Bus", + "name": "VICTORVL", + "init": { + "Vr": 1.034163217506761, + "Vi": -0.1656247680371199 + }, + "params": { + "kv": 287.0 + }, + "mon": [], + "extension": { + "latitude": 36.530949, + "longitude": -117.756767 + } + }, + { + "number": 2608, + "class": "Bus", + "name": "CASTAIC", + "init": { + "Vr": 1.0012616559172747, + "Vi": -0.1664334836786176 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 36.213648, + "longitude": -118.51409 + } + }, + { + "number": 2609, + "class": "Bus", + "name": "GLENDAL", + "init": { + "Vr": 0.9906538349030883, + "Vi": -0.13431046642691002 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.889143, + "longitude": -117.250466 + } + }, + { + "number": 2610, + "class": "Bus", + "name": "HAYNES", + "init": { + "Vr": 0.9976290136127944, + "Vi": 0.11292599284040156 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.408805, + "longitude": -116.633545 + } + }, + { + "number": 2611, + "class": "Bus", + "name": "OLIVE", + "init": { + "Vr": 1.0006947498616412, + "Vi": -0.16980879614779287 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 36.381274, + "longitude": -118.207757 + } + }, + { + "number": 2612, + "class": "Bus", + "name": "RINALDI", + "init": { + "Vr": 0.9981814359215982, + "Vi": -0.1759485753724291 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 36.23131, + "longitude": -117.54829 + } + }, + { + "number": 2613, + "class": "Bus", + "name": "RIVER", + "init": { + "Vr": 0.9920714739096348, + "Vi": -0.07327006970795101 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.414753, + "longitude": -117.986517 + } + }, + { + "number": 2614, + "class": "Bus", + "name": "STA BLD", + "init": { + "Vr": 0.9970240906342276, + "Vi": -0.1012968961463488 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.732313, + "longitude": -118.00779 + } + }, + { + "number": 2615, + "class": "Bus", + "name": "STA E", + "init": { + "Vr": 0.9926101753760911, + "Vi": -0.1598443473006861 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 36.010251, + "longitude": -117.314285 + } + }, + { + "number": 2616, + "class": "Bus", + "name": "STA F", + "init": { + "Vr": 0.9935468290693091, + "Vi": -0.07920529831602903 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.536584, + "longitude": -117.37385 + } + }, + { + "number": 2617, + "class": "Bus", + "name": "STA G", + "init": { + "Vr": 0.9916964406539152, + "Vi": -0.10926410263002753 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.829998, + "longitude": -117.633383 + } + }, + { + "number": 2618, + "class": "Bus", + "name": "STA J", + "init": { + "Vr": 0.992558705681965, + "Vi": -0.19283153771568565 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.927563, + "longitude": -117.867387 + } + }, + { + "number": 2619, + "class": "Bus", + "name": "SYLMARLA", + "init": { + "Vr": 0.9980796625833909, + "Vi": -0.17047058525181263 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.880274, + "longitude": -118.663002 + } + }, + { + "number": 2620, + "class": "Bus", + "name": "VALLEY", + "init": { + "Vr": 0.9937915165908, + "Vi": -0.17620498344481186 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 35.821123, + "longitude": -116.365504 + } + }, + { + "number": 2621, + "class": "Bus", + "name": "STA B", + "init": { + "Vr": 1.005434675493241, + "Vi": -0.12177584337612585 + }, + "params": { + "kv": 138.0 + }, + "mon": [], + "extension": { + "latitude": 35.521736, + "longitude": -118.428998 + } + }, + { + "number": 2630, + "class": "Bus", + "name": "HAYNES3G", + "init": { + "Vr": 0.9971389605845953, + "Vi": 0.12430745398752142 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 35.471234, + "longitude": -116.40805 + } + }, + { + "number": 2631, + "class": "Bus", + "name": "OLIVE", + "init": { + "Vr": 1.0010405941541551, + "Vi": -0.16870832017950163 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 36.478155, + "longitude": -118.126919 + } + }, + { + "number": 2634, + "class": "Bus", + "name": "INTERM1G", + "init": { + "Vr": 1.0285417184438843, + "Vi": -0.05254019095669047 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 40.871886, + "longitude": -115.20813 + } + }, + { + "number": 2637, + "class": "Bus", + "name": "OWENS G", + "init": { + "Vr": 0.9984488847326837, + "Vi": -0.1755800027868625 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 36.328378, + "longitude": -117.38236 + } + }, + { + "number": 2638, + "class": "Bus", + "name": "CASTAI4G", + "init": { + "Vr": 1.0014600657990034, + "Vi": -0.1654677318950609 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 36.098749, + "longitude": -118.543873 + } + }, + { + "number": 2901, + "class": "Bus", + "name": "ELDORADO", + "init": { + "Vr": 1.0905891370529095, + "Vi": -0.19230903479861583 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 37.454784, + "longitude": -117.007952 + } + }, + { + "number": 2902, + "class": "Bus", + "name": "MOHAVE", + "init": { + "Vr": 1.096153053959966, + "Vi": -0.2170147670364765 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 37.106388, + "longitude": -118.199248 + } + }, + { + "number": 3101, + "class": "Bus", + "name": "EMBRCDRD", + "init": { + "Vr": 0.9722931284547578, + "Vi": -0.1327856272299986 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 40.046666, + "longitude": -123.385639 + } + }, + { + "number": 3102, + "class": "Bus", + "name": "MARTIN", + "init": { + "Vr": 0.9794265121238133, + "Vi": -0.11390642826319415 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 39.867662, + "longitude": -123.453713 + } + }, + { + "number": 3103, + "class": "Bus", + "name": "SANMATEO", + "init": { + "Vr": 0.9896580875926599, + "Vi": -0.07790952575830737 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 39.542025, + "longitude": -122.994213 + } + }, + { + "number": 3104, + "class": "Bus", + "name": "MARTIN", + "init": { + "Vr": 0.9660330473147188, + "Vi": -0.19645501561854037 + }, + "params": { + "kv": 115.0 + }, + "mon": [], + "extension": { + "latitude": 40.149938, + "longitude": -123.751537 + } + }, + { + "number": 3105, + "class": "Bus", + "name": "POTRERO", + "init": { + "Vr": 0.9799048238020691, + "Vi": -0.19946565935283173 + }, + "params": { + "kv": 115.0 + }, + "mon": [], + "extension": { + "latitude": 40.367134, + "longitude": -123.730263 + } + }, + { + "number": 3133, + "class": "Bus", + "name": "SANMATEO", + "init": { + "Vr": 0.9896073417355664, + "Vi": -0.07774889842772482 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 39.347599, + "longitude": -122.870829 + } + }, + { + "number": 3135, + "class": "Bus", + "name": "POTRERO", + "init": { + "Vr": 0.9805420521360869, + "Vi": -0.19847290035110018 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 40.580861, + "longitude": -123.82812 + } + }, + { + "number": 3201, + "class": "Bus", + "name": "C.COSTA", + "init": { + "Vr": 1.0004147159397625, + "Vi": -0.08004229102575253 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 40.001959, + "longitude": -121.968848 + } + }, + { + "number": 3202, + "class": "Bus", + "name": "MORAGA", + "init": { + "Vr": 0.9997040603567278, + "Vi": -0.07217977124062025 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 39.623578, + "longitude": -122.258162 + } + }, + { + "number": 3203, + "class": "Bus", + "name": "NEWARK", + "init": { + "Vr": 0.9978320796012269, + "Vi": -0.07366535831230554 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 39.192233, + "longitude": -122.06245 + } + }, + { + "number": 3204, + "class": "Bus", + "name": "PITSBURG", + "init": { + "Vr": 1.0099967188161656, + "Vi": 0.0025696894778991807 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 39.954425, + "longitude": -122.930394 + } + }, + { + "number": 3205, + "class": "Bus", + "name": "SOBRANTE", + "init": { + "Vr": 0.9998452023240696, + "Vi": -0.04401002055119826 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 40.278112, + "longitude": -122.828282 + } + }, + { + "number": 3234, + "class": "Bus", + "name": "PITSBURG", + "init": { + "Vr": 1.0118253240235424, + "Vi": 0.022346231478620488 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 40.381033, + "longitude": -123.245236 + } + }, + { + "number": 3301, + "class": "Bus", + "name": "METCALF", + "init": { + "Vr": 1.007866937546572, + "Vi": -0.08340156198974104 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 38.761069, + "longitude": -121.360436 + } + }, + { + "number": 3302, + "class": "Bus", + "name": "JEFFERSN", + "init": { + "Vr": 0.9754937580171337, + "Vi": -0.1313626301481899 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 39.262896, + "longitude": -123.249491 + } + }, + { + "number": 3303, + "class": "Bus", + "name": "METCALF", + "init": { + "Vr": 0.9954325113973748, + "Vi": -0.09546791965348518 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 38.4274, + "longitude": -122.258162 + } + }, + { + "number": 3304, + "class": "Bus", + "name": "MONTAVIS", + "init": { + "Vr": 0.9823906419731837, + "Vi": -0.12141073436103614 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 39.050692, + "longitude": -122.785736 + } + }, + { + "number": 3305, + "class": "Bus", + "name": "RAVENSWD", + "init": { + "Vr": 0.9914754213389761, + "Vi": -0.08296385035941362 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 39.325022, + "longitude": -122.411329 + } + }, + { + "number": 3333, + "class": "Bus", + "name": "METCALF", + "init": { + "Vr": 0.9966163504641669, + "Vi": -0.09150801474746428 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 38.284334, + "longitude": -122.63257 + } + }, + { + "number": 3401, + "class": "Bus", + "name": "GREGG", + "init": { + "Vr": 0.9385628433185484, + "Vi": -0.23141879696687814 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 38.704141, + "longitude": -119.501164 + } + }, + { + "number": 3402, + "class": "Bus", + "name": "HELMS PP", + "init": { + "Vr": 0.9405776900269747, + "Vi": -0.23215352799590322 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 38.880469, + "longitude": -119.407562 + } + }, + { + "number": 3403, + "class": "Bus", + "name": "MC CALL", + "init": { + "Vr": 0.9996379495082729, + "Vi": -0.02690702982598862 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 38.678509, + "longitude": -120.092557 + } + }, + { + "number": 3404, + "class": "Bus", + "name": "PANOCHE", + "init": { + "Vr": 0.9770923660147381, + "Vi": -0.14887042972563508 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 38.521669, + "longitude": -120.403145 + } + }, + { + "number": 3405, + "class": "Bus", + "name": "WILSON", + "init": { + "Vr": 0.9267614523616793, + "Vi": -0.25834289053386744 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 39.237466, + "longitude": -120.700969 + } + }, + { + "number": 3432, + "class": "Bus", + "name": "HELMS PP", + "init": { + "Vr": 0.9405776900269747, + "Vi": -0.23215352799590322 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 38.991161, + "longitude": -119.43309 + } + }, + { + "number": 3433, + "class": "Bus", + "name": "MC CALL", + "init": { + "Vr": 1.000022781865973, + "Vi": -0.020785219240381233 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 38.803734, + "longitude": -120.203177 + } + }, + { + "number": 3501, + "class": "Bus", + "name": "FULTON", + "init": { + "Vr": 0.9996023627645195, + "Vi": 0.028197887326842485 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 40.658411, + "longitude": -123.47924 + } + }, + { + "number": 3531, + "class": "Bus", + "name": "FULTON", + "init": { + "Vr": 0.9997935418988533, + "Vi": 0.03365037183766125 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 40.94291, + "longitude": -123.551569 + } + }, + { + "number": 3601, + "class": "Bus", + "name": "HUMBOLDT", + "init": { + "Vr": 1.012594829955947, + "Vi": -0.06983332616798761 + }, + "params": { + "kv": 115.0 + }, + "mon": [], + "extension": { + "latitude": 41.475448, + "longitude": -122.828282 + } + }, + { + "number": 3631, + "class": "Bus", + "name": "HUMBOLDT", + "init": { + "Vr": 1.012396079859527, + "Vi": -0.06934060539135728 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 41.701961, + "longitude": -123.198435 + } + }, + { + "number": 3701, + "class": "Bus", + "name": "SUMMIT", + "init": { + "Vr": 0.9416557558603073, + "Vi": -0.3556129593048615 + }, + "params": { + "kv": 115.0 + }, + "mon": [], + "extension": { + "latitude": 39.974002, + "longitude": -120.096812 + } + }, + { + "number": 3731, + "class": "Bus", + "name": "SUMMIT", + "init": { + "Vr": 0.9414818409693088, + "Vi": -0.3543683776528598 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 39.772376, + "longitude": -120.024483 + } + }, + { + "number": 3801, + "class": "Bus", + "name": "DIABLO", + "init": { + "Vr": 1.0489913945645062, + "Vi": 0.0042578862107550295 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 38.034726, + "longitude": -121.556149 + } + }, + { + "number": 3802, + "class": "Bus", + "name": "GATES", + "init": { + "Vr": 1.0318774425716297, + "Vi": -0.10387071565097808 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 38.244225, + "longitude": -119.956409 + } + }, + { + "number": 3803, + "class": "Bus", + "name": "MIDWAY", + "init": { + "Vr": 1.0381071545683649, + "Vi": -0.12961703817420264 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 37.775612, + "longitude": -120.535038 + } + }, + { + "number": 3804, + "class": "Bus", + "name": "GATES", + "init": { + "Vr": 0.9945929770856804, + "Vi": -0.12431144741711979 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 38.321558, + "longitude": -120.377617 + } + }, + { + "number": 3805, + "class": "Bus", + "name": "MIDWAY", + "init": { + "Vr": 1.0280211033651232, + "Vi": -0.1199898918403978 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 37.582124, + "longitude": -119.930881 + } + }, + { + "number": 3806, + "class": "Bus", + "name": "MORROBAY", + "init": { + "Vr": 1.0170704073699968, + "Vi": -0.06268100801336776 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 37.648602, + "longitude": -121.224288 + } + }, + { + "number": 3831, + "class": "Bus", + "name": "DIABLO1", + "init": { + "Vr": 1.0486618750743935, + "Vi": 0.014304334865360438 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 37.985852, + "longitude": -121.862482 + } + }, + { + "number": 3835, + "class": "Bus", + "name": "MIDWAY", + "init": { + "Vr": 1.028507010937164, + "Vi": -0.11820331528869157 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 37.668823, + "longitude": -119.420326 + } + }, + { + "number": 3836, + "class": "Bus", + "name": "MORROBAY", + "init": { + "Vr": 1.0172317024618558, + "Vi": -0.05935292294210547 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 37.483744, + "longitude": -121.147705 + } + }, + { + "number": 3891, + "class": "Bus", + "name": "GATES1", + "init": { + "Vr": 1.0384992251021798, + "Vi": -0.16914564786810307 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 38.118023, + "longitude": -120.173395 + } + }, + { + "number": 3892, + "class": "Bus", + "name": "MIDWAY1", + "init": { + "Vr": 1.0362966886561964, + "Vi": -0.07080251210623617 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 37.315619, + "longitude": -119.918117 + } + }, + { + "number": 3893, + "class": "Bus", + "name": "MIDWAY2", + "init": { + "Vr": 1.006416717622578, + "Vi": -0.23516357143142072 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 36.902413, + "longitude": -119.522437 + } + }, + { + "number": 3894, + "class": "Bus", + "name": "MIDWAY3", + "init": { + "Vr": 1.0361566693266289, + "Vi": -0.06982286263393161 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 37.312717, + "longitude": -120.330816 + } + }, + { + "number": 3895, + "class": "Bus", + "name": "MIDWAY4", + "init": { + "Vr": 1.0065214763974337, + "Vi": -0.23557587673313815 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 36.884904, + "longitude": -119.89259 + } + }, + { + "number": 3896, + "class": "Bus", + "name": "MIDWAY5", + "init": { + "Vr": 1.036734140432592, + "Vi": -0.0669784292058116 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 37.286594, + "longitude": -120.726497 + } + }, + { + "number": 3897, + "class": "Bus", + "name": "MIDWAY6", + "init": { + "Vr": 1.0090410697014338, + "Vi": -0.233151317831234 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 36.832353, + "longitude": -120.309543 + } + }, + { + "number": 3901, + "class": "Bus", + "name": "LOSBANOS", + "init": { + "Vr": 1.024235363911919, + "Vi": -0.10791164810628685 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 38.911707, + "longitude": -120.705223 + } + }, + { + "number": 3902, + "class": "Bus", + "name": "MOSSLAND", + "init": { + "Vr": 0.9992197525213846, + "Vi": -0.03949539156705649 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 38.56733, + "longitude": -121.109413 + } + }, + { + "number": 3903, + "class": "Bus", + "name": "TESLA", + "init": { + "Vr": 1.0302497343114967, + "Vi": -0.09537211903974258 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 39.028019, + "longitude": -121.126432 + } + }, + { + "number": 3904, + "class": "Bus", + "name": "VACA-DIX", + "init": { + "Vr": 1.029444168877676, + "Vi": -0.0984415143079731 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 40.486572, + "longitude": -121.973102 + } + }, + { + "number": 3905, + "class": "Bus", + "name": "TABLE MT", + "init": { + "Vr": 1.0431184070605861, + "Vi": -0.11237193427097877 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 40.669483, + "longitude": -121.879501 + } + }, + { + "number": 3906, + "class": "Bus", + "name": "ROUND MT", + "init": { + "Vr": 1.0649774101089475, + "Vi": -0.10257592982310373 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 41.614724, + "longitude": -121.339163 + } + }, + { + "number": 3907, + "class": "Bus", + "name": "BELLOTA", + "init": { + "Vr": 0.9419070958335489, + "Vi": -0.22991313501305208 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 39.387092, + "longitude": -121.015811 + } + }, + { + "number": 3908, + "class": "Bus", + "name": "BRIGHTON", + "init": { + "Vr": 0.9345738765963039, + "Vi": -0.2783865547472467 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 40.029904, + "longitude": -121.488075 + } + }, + { + "number": 3909, + "class": "Bus", + "name": "COLGATE", + "init": { + "Vr": 0.9404009334990066, + "Vi": -0.30122816256084395 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 40.669483, + "longitude": -121.007302 + } + }, + { + "number": 3910, + "class": "Bus", + "name": "CORTINA", + "init": { + "Vr": 0.9545072532199945, + "Vi": -0.22023624942858822 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 40.683319, + "longitude": -122.364528 + } + }, + { + "number": 3911, + "class": "Bus", + "name": "COTWDPGE", + "init": { + "Vr": 1.0403165540407433, + "Vi": -0.07528126503320838 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 40.989749, + "longitude": -122.177324 + } + }, + { + "number": 3912, + "class": "Bus", + "name": "GLENN", + "init": { + "Vr": 1.0083289707968137, + "Vi": -0.181486005345536 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 41.091578, + "longitude": -122.91763 + } + }, + { + "number": 3913, + "class": "Bus", + "name": "GOLDHILL", + "init": { + "Vr": 0.9638389469915553, + "Vi": -0.2169752947485779 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 39.990777, + "longitude": -120.951992 + } + }, + { + "number": 3914, + "class": "Bus", + "name": "IGNACIO", + "init": { + "Vr": 0.9906657476318554, + "Vi": -0.03698206466516002 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 40.816003, + "longitude": -123.168653 + } + }, + { + "number": 3915, + "class": "Bus", + "name": "LAKEVILE", + "init": { + "Vr": 0.9952778869991848, + "Vi": -0.05887878208945546 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 40.489347, + "longitude": -122.764463 + } + }, + { + "number": 3916, + "class": "Bus", + "name": "LOGAN CR", + "init": { + "Vr": 1.006797145740073, + "Vi": -0.1767096480581869 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 41.206976, + "longitude": -122.692134 + } + }, + { + "number": 3917, + "class": "Bus", + "name": "LOSBANOS", + "init": { + "Vr": 0.9994489088245955, + "Vi": -0.1464411568037393 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 38.687054, + "longitude": -120.492492 + } + }, + { + "number": 3918, + "class": "Bus", + "name": "MOSSLAND", + "init": { + "Vr": 0.9883467710975091, + "Vi": -0.10435004632524449 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 38.086439, + "longitude": -122.296454 + } + }, + { + "number": 3919, + "class": "Bus", + "name": "PALERMO", + "init": { + "Vr": 0.9551573079151378, + "Vi": -0.2850749833122782 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 40.937398, + "longitude": -121.215779 + } + }, + { + "number": 3920, + "class": "Bus", + "name": "RIO OSO", + "init": { + "Vr": 0.9504839580759618, + "Vi": -0.27778590974446277 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 40.52264, + "longitude": -120.675441 + } + }, + { + "number": 3921, + "class": "Bus", + "name": "ROUND MT", + "init": { + "Vr": 1.0696329641683537, + "Vi": 0.028025873450743668 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 41.272826, + "longitude": -121.113668 + } + }, + { + "number": 3922, + "class": "Bus", + "name": "TABLE MT", + "init": { + "Vr": 0.9913288500399144, + "Vi": -0.2238669662880582 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 40.411601, + "longitude": -121.585931 + } + }, + { + "number": 3923, + "class": "Bus", + "name": "TESLA", + "init": { + "Vr": 1.0174459838144574, + "Vi": -0.018204050668783302 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 39.530769, + "longitude": -121.577422 + } + }, + { + "number": 3924, + "class": "Bus", + "name": "VACA-DIX", + "init": { + "Vr": 1.0049188471121937, + "Vi": -0.09598996043849413 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 40.353232, + "longitude": -122.339 + } + }, + { + "number": 3925, + "class": "Bus", + "name": "COTWDPGE", + "init": { + "Vr": 1.0272875871698077, + "Vi": -0.07321869957591998 + }, + "params": { + "kv": 115.0 + }, + "mon": [], + "extension": { + "latitude": 41.300244, + "longitude": -122.551732 + } + }, + { + "number": 3926, + "class": "Bus", + "name": "RIO OSO", + "init": { + "Vr": 0.9403213475282999, + "Vi": -0.333957210894513 + }, + "params": { + "kv": 115.0 + }, + "mon": [], + "extension": { + "latitude": 40.161093, + "longitude": -120.330816 + } + }, + { + "number": 3931, + "class": "Bus", + "name": "ROUND MT", + "init": { + "Vr": 1.070091197006786, + "Vi": 0.03480174694473029 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 41.352307, + "longitude": -120.837117 + } + }, + { + "number": 3932, + "class": "Bus", + "name": "MOSSLAND", + "init": { + "Vr": 0.9982283130082861, + "Vi": -0.032675670009689115 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 38.4274, + "longitude": -121.122177 + } + }, + { + "number": 3933, + "class": "Bus", + "name": "TESLA", + "init": { + "Vr": 1.0199999809265137, + "Vi": 0.0 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 38.999668, + "longitude": -121.598695 + } + }, + { + "number": 4001, + "class": "Bus", + "name": "MALIN", + "init": { + "Vr": 1.0742150954886451, + "Vi": -0.1116334975647323 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 42.295809, + "longitude": -122.313473 + } + }, + { + "number": 4002, + "class": "Bus", + "name": "SUMMER L", + "init": { + "Vr": 1.1117588653391925, + "Vi": -0.07213652237198542 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 41.66171, + "longitude": -118.057941 + } + }, + { + "number": 4003, + "class": "Bus", + "name": "BURNS", + "init": { + "Vr": 1.1254580462787114, + "Vi": 0.08074687523525724 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 41.641831, + "longitude": -117.452368 + } + }, + { + "number": 4004, + "class": "Bus", + "name": "GRIZZLY", + "init": { + "Vr": 1.0958334028460324, + "Vi": -0.10978355460893538 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 42.5891, + "longitude": -118.832813 + } + }, + { + "number": 4005, + "class": "Bus", + "name": "JOHN DAY", + "init": { + "Vr": 1.0753080995429867, + "Vi": -0.10056131570277813 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 43.945107, + "longitude": -119.282109 + } + }, + { + "number": 4006, + "class": "Bus", + "name": "BIG EDDY", + "init": { + "Vr": 1.0628128498876628, + "Vi": -0.16758686526287284 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 43.217585, + "longitude": -120.493254 + } + }, + { + "number": 4007, + "class": "Bus", + "name": "CELILOCA", + "init": { + "Vr": 1.0623064836131175, + "Vi": -0.17079729309735756 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 42.087627, + "longitude": -120.851389 + } + }, + { + "number": 4008, + "class": "Bus", + "name": "MALIN", + "init": { + "Vr": 1.0693154704164687, + "Vi": -0.15247801518194742 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 40.796341, + "longitude": -119.438386 + } + }, + { + "number": 4009, + "class": "Bus", + "name": "BIG EDDY", + "init": { + "Vr": 1.0585649232896344, + "Vi": -0.2141037233349766 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 43.97862, + "longitude": -121.509054 + } + }, + { + "number": 4010, + "class": "Bus", + "name": "CELILO", + "init": { + "Vr": 1.0563885991972057, + "Vi": -0.2182870495419395 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 42.84809, + "longitude": -121.430915 + } + }, + { + "number": 4031, + "class": "Bus", + "name": "MALIN", + "init": { + "Vr": 1.0717996284183116, + "Vi": -0.10414307826474267 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 40.665296, + "longitude": -123.176007 + } + }, + { + "number": 4035, + "class": "Bus", + "name": "JOHN DAY", + "init": { + "Vr": 1.073926468979413, + "Vi": -0.08980213940015647 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 42.770018, + "longitude": -119.907216 + } + }, + { + "number": 4039, + "class": "Bus", + "name": "DALLES21", + "init": { + "Vr": 1.0644295672627466, + "Vi": -0.20468437089984598 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 43.295089, + "longitude": -122.459738 + } + }, + { + "number": 4090, + "class": "Bus", + "name": "MALIN1", + "init": { + "Vr": 1.1079273209852338, + "Vi": -0.0781504103577864 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 41.651772, + "longitude": -119.190948 + } + }, + { + "number": 4091, + "class": "Bus", + "name": "GRIZZLY1", + "init": { + "Vr": 1.106561302953537, + "Vi": -0.09471677727580895 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 42.053065, + "longitude": -118.630956 + } + }, + { + "number": 4092, + "class": "Bus", + "name": "GRIZZLY2", + "init": { + "Vr": 1.0882278845876256, + "Vi": -0.11299995543237296 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 42.122169, + "longitude": -118.884905 + } + }, + { + "number": 4093, + "class": "Bus", + "name": "GRIZZLY3", + "init": { + "Vr": 1.0863994414257208, + "Vi": -0.11337996995770021 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 41.944321, + "longitude": -119.295132 + } + }, + { + "number": 4094, + "class": "Bus", + "name": "GRIZZLY4", + "init": { + "Vr": 1.1003951431675545, + "Vi": -0.11047017243942504 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 41.726275, + "longitude": -120.278374 + } + }, + { + "number": 4095, + "class": "Bus", + "name": "GRIZZLY5", + "init": { + "Vr": 1.0865438776549408, + "Vi": -0.11305572669568284 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 42.18627, + "longitude": -119.151878 + } + }, + { + "number": 4096, + "class": "Bus", + "name": "GRIZZLY6", + "init": { + "Vr": 1.0844982600176971, + "Vi": -0.11345434404839705 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 41.978941, + "longitude": -119.718382 + } + }, + { + "number": 4097, + "class": "Bus", + "name": "GRIZZLY7", + "init": { + "Vr": 1.100156324094967, + "Vi": -0.11040203663047926 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 41.820522, + "longitude": -120.64302 + } + }, + { + "number": 4101, + "class": "Bus", + "name": "COULEE", + "init": { + "Vr": 1.106259130542874, + "Vi": 0.2203968985312899 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 45.644104, + "longitude": -119.197459 + } + }, + { + "number": 4102, + "class": "Bus", + "name": "HANFORD", + "init": { + "Vr": 1.0933308488862448, + "Vi": 0.0764431476694636 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 44.810297, + "longitude": -120.297908 + } + }, + { + "number": 4103, + "class": "Bus", + "name": "BELL", + "init": { + "Vr": 1.0785286137608066, + "Vi": -0.0704903631402604 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 44.417318, + "longitude": -116.833772 + } + }, + { + "number": 4104, + "class": "Bus", + "name": "BELL", + "init": { + "Vr": 1.0173271028054875, + "Vi": -0.26701826375529075 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 45.476456, + "longitude": -117.458879 + } + }, + { + "number": 4131, + "class": "Bus", + "name": "COULEE", + "init": { + "Vr": 1.101289655917031, + "Vi": 0.2574803744594305 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 46.318885, + "longitude": -118.377006 + } + }, + { + "number": 4132, + "class": "Bus", + "name": "HANFORD", + "init": { + "Vr": 1.0912138201935935, + "Vi": 0.10767016380894881 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 44.222214, + "longitude": -118.943509 + } + }, + { + "number": 4201, + "class": "Bus", + "name": "NORTH", + "init": { + "Vr": 1.1171502138256575, + "Vi": 0.07984619348110389 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 46.337256, + "longitude": -121.183477 + } + }, + { + "number": 4202, + "class": "Bus", + "name": "WCASCADE", + "init": { + "Vr": 1.0490325011586195, + "Vi": -0.15208777987868904 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 45.252146, + "longitude": -122.51183 + } + }, + { + "number": 4203, + "class": "Bus", + "name": "WILLAMET", + "init": { + "Vr": 1.008659388938506, + "Vi": -0.20519613920439653 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 44.231747, + "longitude": -123.228099 + } + }, + { + "number": 4204, + "class": "Bus", + "name": "MERIDIAN", + "init": { + "Vr": 1.0522103173835093, + "Vi": -0.1428316386092655 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 42.984478, + "longitude": -123.195541 + } + }, + { + "number": 4231, + "class": "Bus", + "name": "NORTH G3", + "init": { + "Vr": 1.122012845901798, + "Vi": 0.09840754125580804 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 46.77632, + "longitude": -119.900705 + } + }, + { + "number": 4232, + "class": "Bus", + "name": "WCASCADE", + "init": { + "Vr": 1.0495669903600091, + "Vi": -0.14793564763330605 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 46.037956, + "longitude": -123.130426 + } + }, + { + "number": 5001, + "class": "Bus", + "name": "CANADA", + "init": { + "Vr": 1.044697957467842, + "Vi": -0.10538541844550599 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 47.207314, + "longitude": -121.137896 + } + }, + { + "number": 5002, + "class": "Bus", + "name": "CANALB", + "init": { + "Vr": 1.0471976935789618, + "Vi": -0.12806984041606298 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 47.184716, + "longitude": -117.497949 + } + }, + { + "number": 5003, + "class": "Bus", + "name": "CA230TO", + "init": { + "Vr": 1.0362072539978977, + "Vi": -0.19109784448597206 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 46.465683, + "longitude": -117.361206 + } + }, + { + "number": 5004, + "class": "Bus", + "name": "CA230", + "init": { + "Vr": 1.0605136082258966, + "Vi": -0.23750667870276446 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 45.871489, + "longitude": -117.471902 + } + }, + { + "number": 5031, + "class": "Bus", + "name": "CANAD G1", + "init": { + "Vr": 1.0520077225700353, + "Vi": -0.07358953981120041 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 47.89414, + "longitude": -122.205788 + } + }, + { + "number": 5032, + "class": "Bus", + "name": "CMAIN GM", + "init": { + "Vr": 1.0580457806182115, + "Vi": -0.08431627327644076 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 47.965446, + "longitude": -118.676536 + } + }, + { + "number": 6101, + "class": "Bus", + "name": "MIDPOINT", + "init": { + "Vr": 1.034845555465481, + "Vi": 0.25667915598909957 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 41.656741, + "longitude": -116.794703 + } + }, + { + "number": 6102, + "class": "Bus", + "name": "MIDPOINT", + "init": { + "Vr": 0.9865247716604576, + "Vi": 0.29608922033956325 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 42.156693, + "longitude": -115.362165 + } + }, + { + "number": 6103, + "class": "Bus", + "name": "BORAH", + "init": { + "Vr": 0.9814350507322236, + "Vi": 0.260871446160652 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 41.537365, + "longitude": -114.417993 + } + }, + { + "number": 6104, + "class": "Bus", + "name": "BORAH", + "init": { + "Vr": 1.0086610396824167, + "Vi": 0.0471410495450563 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 42.628262, + "longitude": -114.203112 + } + }, + { + "number": 6132, + "class": "Bus", + "name": "MIDPOINT", + "init": { + "Vr": 0.9770442655079542, + "Vi": 0.31232070242024784 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 42.818825, + "longitude": -115.648673 + } + }, + { + "number": 6201, + "class": "Bus", + "name": "COLSTRP", + "init": { + "Vr": 1.0512607632089848, + "Vi": 0.13583332169594756 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 45.373758, + "longitude": -109.65155 + } + }, + { + "number": 6202, + "class": "Bus", + "name": "GARRISON", + "init": { + "Vr": 1.0935227185534016, + "Vi": 0.05218150379495341 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 43.411162, + "longitude": -115.244958 + } + }, + { + "number": 6203, + "class": "Bus", + "name": "COLSTRP", + "init": { + "Vr": 0.9993297313330015, + "Vi": 0.11320335548013538 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 44.654371, + "longitude": -109.664573 + } + }, + { + "number": 6204, + "class": "Bus", + "name": "GARRISON", + "init": { + "Vr": 1.050156048950021, + "Vi": 0.05732658547417582 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 44.112482, + "longitude": -114.639385 + } + }, + { + "number": 6205, + "class": "Bus", + "name": "MONTANA", + "init": { + "Vr": 1.0230816995897476, + "Vi": 0.2362281508376658 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 45.91778, + "longitude": -113.17429 + } + }, + { + "number": 6231, + "class": "Bus", + "name": "COLSTRP", + "init": { + "Vr": 1.0498663181019732, + "Vi": 0.14007728523184154 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 46.056422, + "longitude": -110.022707 + } + }, + { + "number": 6235, + "class": "Bus", + "name": "MONTA G1", + "init": { + "Vr": 1.0222216198529543, + "Vi": 0.24292622395523433 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 46.548084, + "longitude": -113.219871 + } + }, + { + "number": 6301, + "class": "Bus", + "name": "BRIDGER", + "init": { + "Vr": 0.9773593118339055, + "Vi": 0.2837587127891073 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 42.862718, + "longitude": -112.438486 + } + }, + { + "number": 6302, + "class": "Bus", + "name": "LARAMIE", + "init": { + "Vr": 0.8513436846801328, + "Vi": -0.5377241134892583 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 41.467628, + "longitude": -108.219012 + } + }, + { + "number": 6303, + "class": "Bus", + "name": "BRIDGER2", + "init": { + "Vr": 0.8961468778007547, + "Vi": 0.507760479283254 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 43.449803, + "longitude": -110.79758 + } + }, + { + "number": 6304, + "class": "Bus", + "name": "LARAMIE", + "init": { + "Vr": 0.9368187909677602, + "Vi": -0.3360948471764651 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 42.862718, + "longitude": -108.316685 + } + }, + { + "number": 6305, + "class": "Bus", + "name": "NAUGHTON", + "init": { + "Vr": 0.9180104614155901, + "Vi": 0.5299591093737004 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 41.875023, + "longitude": -111.722218 + } + }, + { + "number": 6333, + "class": "Bus", + "name": "BRIDGER", + "init": { + "Vr": 0.8896627869972821, + "Vi": 0.5250505848593485 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 42.686959, + "longitude": -110.426422 + } + }, + { + "number": 6335, + "class": "Bus", + "name": "NAUGHT", + "init": { + "Vr": 0.9143801386054924, + "Vi": 0.5432691934430212 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 41.132843, + "longitude": -110.660838 + } + }, + { + "number": 6401, + "class": "Bus", + "name": "TRACYSPP", + "init": { + "Vr": 1.0130307044587665, + "Vi": -0.3517413188519168 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 39.955241, + "longitude": -118.194683 + } + }, + { + "number": 6402, + "class": "Bus", + "name": "SUMITSPP", + "init": { + "Vr": 0.9670124115274004, + "Vi": -0.3713112601222232 + }, + "params": { + "kv": 115.0 + }, + "mon": [], + "extension": { + "latitude": 39.237737, + "longitude": -119.002113 + } + }, + { + "number": 6403, + "class": "Bus", + "name": "VALMY", + "init": { + "Vr": 1.1072754144375725, + "Vi": 0.07772519617874256 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 40.624923, + "longitude": -116.319361 + } + }, + { + "number": 6404, + "class": "Bus", + "name": "GONDER", + "init": { + "Vr": 1.0792041930637892, + "Vi": -0.07692081573967828 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 39.325258, + "longitude": -116.052388 + } + }, + { + "number": 6433, + "class": "Bus", + "name": "VALMY", + "init": { + "Vr": 1.1079871163876425, + "Vi": 0.08373549796191469 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 40.942202, + "longitude": -116.78168 + } + }, + { + "number": 6501, + "class": "Bus", + "name": "BENLOMND", + "init": { + "Vr": 1.0222378440185365, + "Vi": -0.007572623790669165 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 40.78627, + "longitude": -113.55847 + } + }, + { + "number": 6502, + "class": "Bus", + "name": "CAMP WIL", + "init": { + "Vr": 1.0199890330318777, + "Vi": -0.021025209189236563 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 39.119151, + "longitude": -112.080352 + } + }, + { + "number": 6503, + "class": "Bus", + "name": "EMERY", + "init": { + "Vr": 1.0480922840187312, + "Vi": 0.18901770216968847 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 38.554441, + "longitude": -113.610563 + } + }, + { + "number": 6504, + "class": "Bus", + "name": "MONA", + "init": { + "Vr": 1.0225335445238373, + "Vi": -0.02107489960942126 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 39.837876, + "longitude": -113.623586 + } + }, + { + "number": 6505, + "class": "Bus", + "name": "PINTO", + "init": { + "Vr": 1.0586390446964378, + "Vi": 0.1648467805072507 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 38.220784, + "longitude": -113.317544 + } + }, + { + "number": 6506, + "class": "Bus", + "name": "PINTO PS", + "init": { + "Vr": 1.0470416985338609, + "Vi": 0.15883207957364662 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 37.770013, + "longitude": -112.607786 + } + }, + { + "number": 6507, + "class": "Bus", + "name": "SIGURD", + "init": { + "Vr": 1.0513104657332852, + "Vi": 0.005304431058699239 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 39.052036, + "longitude": -115.095192 + } + }, + { + "number": 6508, + "class": "Bus", + "name": "SPAN FRK", + "init": { + "Vr": 1.0278217002112773, + "Vi": 0.027586293009952273 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 39.273788, + "longitude": -114.092416 + } + }, + { + "number": 6509, + "class": "Bus", + "name": "TERMINAL", + "init": { + "Vr": 1.020743685275763, + "Vi": -0.020705281744462806 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 40.584525, + "longitude": -112.106398 + } + }, + { + "number": 6510, + "class": "Bus", + "name": "BENLOMND", + "init": { + "Vr": 0.9884696859234469, + "Vi": 0.005820398069765441 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 41.322932, + "longitude": -112.646856 + } + }, + { + "number": 6533, + "class": "Bus", + "name": "EMERY", + "init": { + "Vr": 1.0466086833922248, + "Vi": 0.2047088327764947 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 38.074326, + "longitude": -111.852448 + } + }, + { + "number": 7001, + "class": "Bus", + "name": "COLOEAST", + "init": { + "Vr": 0.8473568427622199, + "Vi": -0.5677907759663925 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 40.412562, + "longitude": -107.795762 + } + }, + { + "number": 7002, + "class": "Bus", + "name": "CRAIG", + "init": { + "Vr": 0.8730095288262582, + "Vi": -0.5177638049496448 + }, + "params": { + "kv": 345.0 + }, + "mon": [], + "extension": { + "latitude": 39.211974, + "longitude": -109.632015 + } + }, + { + "number": 7031, + "class": "Bus", + "name": "COLOEAST", + "init": { + "Vr": 0.8647534008283276, + "Vi": -0.5524872070474078 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 39.103668, + "longitude": -107.567859 + } + }, + { + "number": 7032, + "class": "Bus", + "name": "CRAIG", + "init": { + "Vr": 0.8801103910765938, + "Vi": -0.5062950378008639 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 39.980729, + "longitude": -110.231076 + } + }, + { + "number": 8001, + "class": "Bus", + "name": "OLINDA", + "init": { + "Vr": 1.058881132588958, + "Vi": -0.11206694277966919 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 41.715581, + "longitude": -122.134778 + } + }, + { + "number": 8002, + "class": "Bus", + "name": "TRACY", + "init": { + "Vr": 1.032499551862721, + "Vi": -0.14027832116440273 + }, + "params": { + "kv": 500.0 + }, + "mon": [], + "extension": { + "latitude": 39.231813, + "longitude": -120.228705 + } + }, + { + "number": 8003, + "class": "Bus", + "name": "COTWDWAP", + "init": { + "Vr": 1.073016887407295, + "Vi": -0.06526760091869742 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 41.401591, + "longitude": -122.181579 + } + }, + { + "number": 8004, + "class": "Bus", + "name": "RNCHSECO", + "init": { + "Vr": 0.9791255000728262, + "Vi": -0.2032566364151699 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 39.806022, + "longitude": -121.007302 + } + }, + { + "number": 8005, + "class": "Bus", + "name": "TRACYPMP", + "init": { + "Vr": 0.975632495789703, + "Vi": -0.23274557610966565 + }, + "params": { + "kv": 230.0 + }, + "mon": [], + "extension": { + "latitude": 39.519511, + "longitude": -119.956409 + } + }, + { + "number": 8033, + "class": "Bus", + "name": "COTWDWAP", + "init": { + "Vr": 1.074528218161104, + "Vi": -0.05985193640100093 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 41.58198, + "longitude": -121.790153 + } + }, + { + "number": 8034, + "class": "Bus", + "name": "RNCHSECO", + "init": { + "Vr": 0.9846175031479656, + "Vi": -0.18717265584303155 + }, + "params": { + "kv": 20.0 + }, + "mon": [], + "extension": { + "latitude": 39.654487, + "longitude": -120.794571 + } + } + ], + "signals": [ + { + "signal_id": 0, + "name": "1032_C_pmech" + }, + { + "signal_id": 1, + "name": "1032_C_efd" + }, + { + "signal_id": 2, + "name": "1032_C_speed" + }, + { + "signal_id": 3, + "name": "1032_G_pmech" + }, + { + "signal_id": 4, + "name": "1032_G_efd" + }, + { + "signal_id": 5, + "name": "1032_G_speed" + }, + { + "signal_id": 6, + "name": "1032_S_ipcmd" + }, + { + "signal_id": 7, + "name": "1032_S_iqcmd" + }, + { + "signal_id": 8, + "name": "1032_S_ibranchr" + }, + { + "signal_id": 9, + "name": "1032_S_ibranchi" + }, + { + "signal_id": 10, + "name": "1032_S_pbranch" + }, + { + "signal_id": 11, + "name": "1032_S_qbranch" + }, + { + "signal_id": 12, + "name": "1032_S_qext" + }, + { + "signal_id": 13, + "name": "1032_S_pext" + }, + { + "signal_id": 14, + "name": "1034_C_pmech" + }, + { + "signal_id": 15, + "name": "1034_C_efd" + }, + { + "signal_id": 16, + "name": "1034_C_speed" + }, + { + "signal_id": 17, + "name": "1034_G_pmech" + }, + { + "signal_id": 18, + "name": "1034_G_efd" + }, + { + "signal_id": 19, + "name": "1034_G_speed" + }, + { + "signal_id": 20, + "name": "1034_W_ipcmd" + }, + { + "signal_id": 21, + "name": "1034_W_iqcmd" + }, + { + "signal_id": 22, + "name": "1034_W_ibranchr" + }, + { + "signal_id": 23, + "name": "1034_W_ibranchi" + }, + { + "signal_id": 24, + "name": "1034_W_pbranch" + }, + { + "signal_id": 25, + "name": "1034_W_qbranch" + }, + { + "signal_id": 26, + "name": "1034_W_qext" + }, + { + "signal_id": 27, + "name": "1034_W_pext" + }, + { + "signal_id": 28, + "name": "1131_C_pmech" + }, + { + "signal_id": 29, + "name": "1131_C_efd" + }, + { + "signal_id": 30, + "name": "1131_C_speed" + }, + { + "signal_id": 31, + "name": "1131_G_pmech" + }, + { + "signal_id": 32, + "name": "1131_G_efd" + }, + { + "signal_id": 33, + "name": "1131_G_speed" + }, + { + "signal_id": 34, + "name": "1232_C_pmech" + }, + { + "signal_id": 35, + "name": "1232_C_efd" + }, + { + "signal_id": 36, + "name": "1232_C_speed" + }, + { + "signal_id": 37, + "name": "1232_H_pmech" + }, + { + "signal_id": 38, + "name": "1232_H_efd" + }, + { + "signal_id": 39, + "name": "1232_H_speed" + }, + { + "signal_id": 40, + "name": "1331_G_pmech" + }, + { + "signal_id": 41, + "name": "1331_G_efd" + }, + { + "signal_id": 42, + "name": "1331_G_speed" + }, + { + "signal_id": 43, + "name": "1331_H_pmech" + }, + { + "signal_id": 44, + "name": "1331_H_efd" + }, + { + "signal_id": 45, + "name": "1331_H_speed" + }, + { + "signal_id": 46, + "name": "1333_C_pmech" + }, + { + "signal_id": 47, + "name": "1333_C_efd" + }, + { + "signal_id": 48, + "name": "1333_C_speed" + }, + { + "signal_id": 49, + "name": "1333_G_pmech" + }, + { + "signal_id": 50, + "name": "1333_G_efd" + }, + { + "signal_id": 51, + "name": "1333_G_speed" + }, + { + "signal_id": 52, + "name": "1333_G_vs" + }, + { + "signal_id": 53, + "name": "1333_S_ipcmd" + }, + { + "signal_id": 54, + "name": "1333_S_iqcmd" + }, + { + "signal_id": 55, + "name": "1333_S_ibranchr" + }, + { + "signal_id": 56, + "name": "1333_S_ibranchi" + }, + { + "signal_id": 57, + "name": "1333_S_pbranch" + }, + { + "signal_id": 58, + "name": "1333_S_qbranch" + }, + { + "signal_id": 59, + "name": "1333_S_qext" + }, + { + "signal_id": 60, + "name": "1333_S_pext" + }, + { + "signal_id": 61, + "name": "1431_G_pmech" + }, + { + "signal_id": 62, + "name": "1431_G_efd" + }, + { + "signal_id": 63, + "name": "1431_G_speed" + }, + { + "signal_id": 64, + "name": "1431_N_pmech" + }, + { + "signal_id": 65, + "name": "1431_N_efd" + }, + { + "signal_id": 66, + "name": "1431_N_speed" + }, + { + "signal_id": 67, + "name": "1431_S_ipcmd" + }, + { + "signal_id": 68, + "name": "1431_S_iqcmd" + }, + { + "signal_id": 69, + "name": "1431_S_ibranchr" + }, + { + "signal_id": 70, + "name": "1431_S_ibranchi" + }, + { + "signal_id": 71, + "name": "1431_S_pbranch" + }, + { + "signal_id": 72, + "name": "1431_S_qbranch" + }, + { + "signal_id": 73, + "name": "1431_S_qext" + }, + { + "signal_id": 74, + "name": "1431_S_pext" + }, + { + "signal_id": 75, + "name": "2030_E_pmech" + }, + { + "signal_id": 76, + "name": "2030_E_efd" + }, + { + "signal_id": 77, + "name": "2030_E_speed" + }, + { + "signal_id": 78, + "name": "2030_G_pmech" + }, + { + "signal_id": 79, + "name": "2030_G_efd" + }, + { + "signal_id": 80, + "name": "2030_G_speed" + }, + { + "signal_id": 81, + "name": "2030_G_vs" + }, + { + "signal_id": 82, + "name": "2130_E_pmech" + }, + { + "signal_id": 83, + "name": "2130_E_efd" + }, + { + "signal_id": 84, + "name": "2130_E_speed" + }, + { + "signal_id": 85, + "name": "2130_G_pmech" + }, + { + "signal_id": 86, + "name": "2130_G_efd" + }, + { + "signal_id": 87, + "name": "2130_G_speed" + }, + { + "signal_id": 88, + "name": "2130_H_pmech" + }, + { + "signal_id": 89, + "name": "2130_H_efd" + }, + { + "signal_id": 90, + "name": "2130_H_speed" + }, + { + "signal_id": 91, + "name": "2130_S_ipcmd" + }, + { + "signal_id": 92, + "name": "2130_S_iqcmd" + }, + { + "signal_id": 93, + "name": "2130_S_ibranchr" + }, + { + "signal_id": 94, + "name": "2130_S_ibranchi" + }, + { + "signal_id": 95, + "name": "2130_S_pbranch" + }, + { + "signal_id": 96, + "name": "2130_S_qbranch" + }, + { + "signal_id": 97, + "name": "2130_S_qext" + }, + { + "signal_id": 98, + "name": "2130_S_pext" + }, + { + "signal_id": 99, + "name": "2233_DG_pmech" + }, + { + "signal_id": 100, + "name": "2233_DG_efd" + }, + { + "signal_id": 101, + "name": "2233_DG_speed" + }, + { + "signal_id": 102, + "name": "2233_EG_pmech" + }, + { + "signal_id": 103, + "name": "2233_EG_efd" + }, + { + "signal_id": 104, + "name": "2233_EG_speed" + }, + { + "signal_id": 105, + "name": "2233_TG_pmech" + }, + { + "signal_id": 106, + "name": "2233_TG_efd" + }, + { + "signal_id": 107, + "name": "2233_TG_speed" + }, + { + "signal_id": 108, + "name": "2332_S_ipcmd" + }, + { + "signal_id": 109, + "name": "2332_S_iqcmd" + }, + { + "signal_id": 110, + "name": "2332_S_ibranchr" + }, + { + "signal_id": 111, + "name": "2332_S_ibranchi" + }, + { + "signal_id": 112, + "name": "2332_S_pbranch" + }, + { + "signal_id": 113, + "name": "2332_S_qbranch" + }, + { + "signal_id": 114, + "name": "2332_S_qext" + }, + { + "signal_id": 115, + "name": "2332_S_pext" + }, + { + "signal_id": 116, + "name": "2431_S_ipcmd" + }, + { + "signal_id": 117, + "name": "2431_S_iqcmd" + }, + { + "signal_id": 118, + "name": "2431_S_ibranchr" + }, + { + "signal_id": 119, + "name": "2431_S_ibranchi" + }, + { + "signal_id": 120, + "name": "2431_S_pbranch" + }, + { + "signal_id": 121, + "name": "2431_S_qbranch" + }, + { + "signal_id": 122, + "name": "2431_S_qext" + }, + { + "signal_id": 123, + "name": "2431_S_pext" + }, + { + "signal_id": 124, + "name": "2434_S_ipcmd" + }, + { + "signal_id": 125, + "name": "2434_S_iqcmd" + }, + { + "signal_id": 126, + "name": "2434_S_ibranchr" + }, + { + "signal_id": 127, + "name": "2434_S_ibranchi" + }, + { + "signal_id": 128, + "name": "2434_S_pbranch" + }, + { + "signal_id": 129, + "name": "2434_S_qbranch" + }, + { + "signal_id": 130, + "name": "2434_S_qext" + }, + { + "signal_id": 131, + "name": "2434_S_pext" + }, + { + "signal_id": 132, + "name": "2438_EG_pmech" + }, + { + "signal_id": 133, + "name": "2438_EG_efd" + }, + { + "signal_id": 134, + "name": "2438_EG_speed" + }, + { + "signal_id": 135, + "name": "2438_RG_pmech" + }, + { + "signal_id": 136, + "name": "2438_RG_efd" + }, + { + "signal_id": 137, + "name": "2438_RG_speed" + }, + { + "signal_id": 138, + "name": "2438_S_ipcmd" + }, + { + "signal_id": 139, + "name": "2438_S_iqcmd" + }, + { + "signal_id": 140, + "name": "2438_S_ibranchr" + }, + { + "signal_id": 141, + "name": "2438_S_ibranchi" + }, + { + "signal_id": 142, + "name": "2438_S_pbranch" + }, + { + "signal_id": 143, + "name": "2438_S_qbranch" + }, + { + "signal_id": 144, + "name": "2438_S_qext" + }, + { + "signal_id": 145, + "name": "2438_S_pext" + }, + { + "signal_id": 146, + "name": "2438_SG_pmech" + }, + { + "signal_id": 147, + "name": "2438_SG_efd" + }, + { + "signal_id": 148, + "name": "2438_SG_speed" + }, + { + "signal_id": 149, + "name": "2438_SH_pmech" + }, + { + "signal_id": 150, + "name": "2438_SH_efd" + }, + { + "signal_id": 151, + "name": "2438_SH_speed" + }, + { + "signal_id": 152, + "name": "2438_SW_ipcmd" + }, + { + "signal_id": 153, + "name": "2438_SW_iqcmd" + }, + { + "signal_id": 154, + "name": "2438_SW_ibranchr" + }, + { + "signal_id": 155, + "name": "2438_SW_ibranchi" + }, + { + "signal_id": 156, + "name": "2438_SW_pbranch" + }, + { + "signal_id": 157, + "name": "2438_SW_qbranch" + }, + { + "signal_id": 158, + "name": "2438_SW_qext" + }, + { + "signal_id": 159, + "name": "2438_SW_pext" + }, + { + "signal_id": 160, + "name": "2438_WG_pmech" + }, + { + "signal_id": 161, + "name": "2438_WG_efd" + }, + { + "signal_id": 162, + "name": "2438_WG_speed" + }, + { + "signal_id": 163, + "name": "2438_WG_vs" + }, + { + "signal_id": 164, + "name": "2439_S_ipcmd" + }, + { + "signal_id": 165, + "name": "2439_S_iqcmd" + }, + { + "signal_id": 166, + "name": "2439_S_ibranchr" + }, + { + "signal_id": 167, + "name": "2439_S_ibranchi" + }, + { + "signal_id": 168, + "name": "2439_S_pbranch" + }, + { + "signal_id": 169, + "name": "2439_S_qbranch" + }, + { + "signal_id": 170, + "name": "2439_S_qext" + }, + { + "signal_id": 171, + "name": "2439_S_pext" + }, + { + "signal_id": 172, + "name": "2533_S_ipcmd" + }, + { + "signal_id": 173, + "name": "2533_S_iqcmd" + }, + { + "signal_id": 174, + "name": "2533_S_ibranchr" + }, + { + "signal_id": 175, + "name": "2533_S_ibranchi" + }, + { + "signal_id": 176, + "name": "2533_S_pbranch" + }, + { + "signal_id": 177, + "name": "2533_S_qbranch" + }, + { + "signal_id": 178, + "name": "2533_S_qext" + }, + { + "signal_id": 179, + "name": "2533_S_pext" + }, + { + "signal_id": 180, + "name": "2630_G_pmech" + }, + { + "signal_id": 181, + "name": "2630_G_efd" + }, + { + "signal_id": 182, + "name": "2630_G_speed" + }, + { + "signal_id": 183, + "name": "2630_G_vs" + }, + { + "signal_id": 184, + "name": "2631_S_ipcmd" + }, + { + "signal_id": 185, + "name": "2631_S_iqcmd" + }, + { + "signal_id": 186, + "name": "2631_S_ibranchr" + }, + { + "signal_id": 187, + "name": "2631_S_ibranchi" + }, + { + "signal_id": 188, + "name": "2631_S_pbranch" + }, + { + "signal_id": 189, + "name": "2631_S_qbranch" + }, + { + "signal_id": 190, + "name": "2631_S_qext" + }, + { + "signal_id": 191, + "name": "2631_S_pext" + }, + { + "signal_id": 192, + "name": "2634_C_pmech" + }, + { + "signal_id": 193, + "name": "2634_C_efd" + }, + { + "signal_id": 194, + "name": "2634_C_speed" + }, + { + "signal_id": 195, + "name": "2637_H_pmech" + }, + { + "signal_id": 196, + "name": "2637_H_efd" + }, + { + "signal_id": 197, + "name": "2637_H_speed" + }, + { + "signal_id": 198, + "name": "2638_H_pmech" + }, + { + "signal_id": 199, + "name": "2638_H_efd" + }, + { + "signal_id": 200, + "name": "2638_H_speed" + }, + { + "signal_id": 201, + "name": "3133_NG_pmech" + }, + { + "signal_id": 202, + "name": "3133_NG_efd" + }, + { + "signal_id": 203, + "name": "3133_NG_speed" + }, + { + "signal_id": 204, + "name": "3135_MG_pmech" + }, + { + "signal_id": 205, + "name": "3135_MG_efd" + }, + { + "signal_id": 206, + "name": "3135_MG_speed" + }, + { + "signal_id": 207, + "name": "3135_NG_pmech" + }, + { + "signal_id": 208, + "name": "3135_NG_efd" + }, + { + "signal_id": 209, + "name": "3135_NG_speed" + }, + { + "signal_id": 210, + "name": "3234_DG_pmech" + }, + { + "signal_id": 211, + "name": "3234_DG_efd" + }, + { + "signal_id": 212, + "name": "3234_DG_speed" + }, + { + "signal_id": 213, + "name": "3234_MG_pmech" + }, + { + "signal_id": 214, + "name": "3234_MG_efd" + }, + { + "signal_id": 215, + "name": "3234_MG_speed" + }, + { + "signal_id": 216, + "name": "3234_NG_pmech" + }, + { + "signal_id": 217, + "name": "3234_NG_efd" + }, + { + "signal_id": 218, + "name": "3234_NG_speed" + }, + { + "signal_id": 219, + "name": "3234_NW_ipcmd" + }, + { + "signal_id": 220, + "name": "3234_NW_iqcmd" + }, + { + "signal_id": 221, + "name": "3234_NW_ibranchr" + }, + { + "signal_id": 222, + "name": "3234_NW_ibranchi" + }, + { + "signal_id": 223, + "name": "3234_NW_pbranch" + }, + { + "signal_id": 224, + "name": "3234_NW_qbranch" + }, + { + "signal_id": 225, + "name": "3234_NW_qext" + }, + { + "signal_id": 226, + "name": "3234_NW_pext" + }, + { + "signal_id": 227, + "name": "3333_CG_pmech" + }, + { + "signal_id": 228, + "name": "3333_CG_efd" + }, + { + "signal_id": 229, + "name": "3333_CG_speed" + }, + { + "signal_id": 230, + "name": "3333_NG_pmech" + }, + { + "signal_id": 231, + "name": "3333_NG_efd" + }, + { + "signal_id": 232, + "name": "3333_NG_speed" + }, + { + "signal_id": 233, + "name": "3433_NG_pmech" + }, + { + "signal_id": 234, + "name": "3433_NG_efd" + }, + { + "signal_id": 235, + "name": "3433_NG_speed" + }, + { + "signal_id": 236, + "name": "3433_S_ipcmd" + }, + { + "signal_id": 237, + "name": "3433_S_iqcmd" + }, + { + "signal_id": 238, + "name": "3433_S_ibranchr" + }, + { + "signal_id": 239, + "name": "3433_S_ibranchi" + }, + { + "signal_id": 240, + "name": "3433_S_pbranch" + }, + { + "signal_id": 241, + "name": "3433_S_qbranch" + }, + { + "signal_id": 242, + "name": "3433_S_qext" + }, + { + "signal_id": 243, + "name": "3433_S_pext" + }, + { + "signal_id": 244, + "name": "3531_CE_pmech" + }, + { + "signal_id": 245, + "name": "3531_CE_efd" + }, + { + "signal_id": 246, + "name": "3531_CE_speed" + }, + { + "signal_id": 247, + "name": "3531_NE_pmech" + }, + { + "signal_id": 248, + "name": "3531_NE_efd" + }, + { + "signal_id": 249, + "name": "3531_NE_speed" + }, + { + "signal_id": 250, + "name": "3531_NH_pmech" + }, + { + "signal_id": 251, + "name": "3531_NH_efd" + }, + { + "signal_id": 252, + "name": "3531_NH_speed" + }, + { + "signal_id": 253, + "name": "3631_NB_pmech" + }, + { + "signal_id": 254, + "name": "3631_NB_efd" + }, + { + "signal_id": 255, + "name": "3631_NB_speed" + }, + { + "signal_id": 256, + "name": "3631_NG_pmech" + }, + { + "signal_id": 257, + "name": "3631_NG_efd" + }, + { + "signal_id": 258, + "name": "3631_NG_speed" + }, + { + "signal_id": 259, + "name": "3731_NH_pmech" + }, + { + "signal_id": 260, + "name": "3731_NH_efd" + }, + { + "signal_id": 261, + "name": "3731_NH_speed" + }, + { + "signal_id": 262, + "name": "3831_NN_pmech" + }, + { + "signal_id": 263, + "name": "3831_NN_efd" + }, + { + "signal_id": 264, + "name": "3831_NN_speed" + }, + { + "signal_id": 265, + "name": "3835_NG_pmech" + }, + { + "signal_id": 266, + "name": "3835_NG_efd" + }, + { + "signal_id": 267, + "name": "3835_NG_speed" + }, + { + "signal_id": 268, + "name": "3835_S_ipcmd" + }, + { + "signal_id": 269, + "name": "3835_S_iqcmd" + }, + { + "signal_id": 270, + "name": "3835_S_ibranchr" + }, + { + "signal_id": 271, + "name": "3835_S_ibranchi" + }, + { + "signal_id": 272, + "name": "3835_S_pbranch" + }, + { + "signal_id": 273, + "name": "3835_S_qbranch" + }, + { + "signal_id": 274, + "name": "3835_S_qext" + }, + { + "signal_id": 275, + "name": "3835_S_pext" + }, + { + "signal_id": 276, + "name": "3836_DG_pmech" + }, + { + "signal_id": 277, + "name": "3836_DG_efd" + }, + { + "signal_id": 278, + "name": "3836_DG_speed" + }, + { + "signal_id": 279, + "name": "3931_NB_pmech" + }, + { + "signal_id": 280, + "name": "3931_NB_efd" + }, + { + "signal_id": 281, + "name": "3931_NB_speed" + }, + { + "signal_id": 282, + "name": "3931_NH_pmech" + }, + { + "signal_id": 283, + "name": "3931_NH_efd" + }, + { + "signal_id": 284, + "name": "3931_NH_speed" + }, + { + "signal_id": 285, + "name": "3931_NH_vs" + }, + { + "signal_id": 286, + "name": "3932_S_ipcmd" + }, + { + "signal_id": 287, + "name": "3932_S_iqcmd" + }, + { + "signal_id": 288, + "name": "3932_S_ibranchr" + }, + { + "signal_id": 289, + "name": "3932_S_ibranchi" + }, + { + "signal_id": 290, + "name": "3932_S_pbranch" + }, + { + "signal_id": 291, + "name": "3932_S_qbranch" + }, + { + "signal_id": 292, + "name": "3932_S_qext" + }, + { + "signal_id": 293, + "name": "3932_S_pext" + }, + { + "signal_id": 294, + "name": "3933_CG_pmech" + }, + { + "signal_id": 295, + "name": "3933_CG_efd" + }, + { + "signal_id": 296, + "name": "3933_CG_speed" + }, + { + "signal_id": 297, + "name": "3933_NB_pmech" + }, + { + "signal_id": 298, + "name": "3933_NB_efd" + }, + { + "signal_id": 299, + "name": "3933_NB_speed" + }, + { + "signal_id": 300, + "name": "3933_NG_pmech" + }, + { + "signal_id": 301, + "name": "3933_NG_efd" + }, + { + "signal_id": 302, + "name": "3933_NG_speed" + }, + { + "signal_id": 303, + "name": "3933_NH_pmech" + }, + { + "signal_id": 304, + "name": "3933_NH_efd" + }, + { + "signal_id": 305, + "name": "3933_NH_speed" + }, + { + "signal_id": 306, + "name": "3933_NW_ipcmd" + }, + { + "signal_id": 307, + "name": "3933_NW_iqcmd" + }, + { + "signal_id": 308, + "name": "3933_NW_ibranchr" + }, + { + "signal_id": 309, + "name": "3933_NW_ibranchi" + }, + { + "signal_id": 310, + "name": "3933_NW_pbranch" + }, + { + "signal_id": 311, + "name": "3933_NW_qbranch" + }, + { + "signal_id": 312, + "name": "3933_NW_qext" + }, + { + "signal_id": 313, + "name": "3933_NW_pext" + }, + { + "signal_id": 314, + "name": "3933_S_ipcmd" + }, + { + "signal_id": 315, + "name": "3933_S_iqcmd" + }, + { + "signal_id": 316, + "name": "3933_S_ibranchr" + }, + { + "signal_id": 317, + "name": "3933_S_ibranchi" + }, + { + "signal_id": 318, + "name": "3933_S_pbranch" + }, + { + "signal_id": 319, + "name": "3933_S_qbranch" + }, + { + "signal_id": 320, + "name": "3933_S_qext" + }, + { + "signal_id": 321, + "name": "3933_S_pext" + }, + { + "signal_id": 322, + "name": "4031_G_pmech" + }, + { + "signal_id": 323, + "name": "4031_G_efd" + }, + { + "signal_id": 324, + "name": "4031_G_speed" + }, + { + "signal_id": 325, + "name": "4031_H_pmech" + }, + { + "signal_id": 326, + "name": "4031_H_efd" + }, + { + "signal_id": 327, + "name": "4031_H_speed" + }, + { + "signal_id": 328, + "name": "4031_S_ipcmd" + }, + { + "signal_id": 329, + "name": "4031_S_iqcmd" + }, + { + "signal_id": 330, + "name": "4031_S_ibranchr" + }, + { + "signal_id": 331, + "name": "4031_S_ibranchi" + }, + { + "signal_id": 332, + "name": "4031_S_pbranch" + }, + { + "signal_id": 333, + "name": "4031_S_qbranch" + }, + { + "signal_id": 334, + "name": "4031_S_qext" + }, + { + "signal_id": 335, + "name": "4031_S_pext" + }, + { + "signal_id": 336, + "name": "4031_W_ipcmd" + }, + { + "signal_id": 337, + "name": "4031_W_iqcmd" + }, + { + "signal_id": 338, + "name": "4031_W_ibranchr" + }, + { + "signal_id": 339, + "name": "4031_W_ibranchi" + }, + { + "signal_id": 340, + "name": "4031_W_pbranch" + }, + { + "signal_id": 341, + "name": "4031_W_qbranch" + }, + { + "signal_id": 342, + "name": "4031_W_qext" + }, + { + "signal_id": 343, + "name": "4031_W_pext" + }, + { + "signal_id": 344, + "name": "4035_C_pmech" + }, + { + "signal_id": 345, + "name": "4035_C_efd" + }, + { + "signal_id": 346, + "name": "4035_C_speed" + }, + { + "signal_id": 347, + "name": "4035_G_pmech" + }, + { + "signal_id": 348, + "name": "4035_G_efd" + }, + { + "signal_id": 349, + "name": "4035_G_speed" + }, + { + "signal_id": 350, + "name": "4035_H_pmech" + }, + { + "signal_id": 351, + "name": "4035_H_efd" + }, + { + "signal_id": 352, + "name": "4035_H_speed" + }, + { + "signal_id": 353, + "name": "4035_W_ipcmd" + }, + { + "signal_id": 354, + "name": "4035_W_iqcmd" + }, + { + "signal_id": 355, + "name": "4035_W_ibranchr" + }, + { + "signal_id": 356, + "name": "4035_W_ibranchi" + }, + { + "signal_id": 357, + "name": "4035_W_pbranch" + }, + { + "signal_id": 358, + "name": "4035_W_qbranch" + }, + { + "signal_id": 359, + "name": "4035_W_qext" + }, + { + "signal_id": 360, + "name": "4035_W_pext" + }, + { + "signal_id": 361, + "name": "4039_G_pmech" + }, + { + "signal_id": 362, + "name": "4039_G_efd" + }, + { + "signal_id": 363, + "name": "4039_G_speed" + }, + { + "signal_id": 364, + "name": "4039_H_pmech" + }, + { + "signal_id": 365, + "name": "4039_H_efd" + }, + { + "signal_id": 366, + "name": "4039_H_speed" + }, + { + "signal_id": 367, + "name": "4039_W_ipcmd" + }, + { + "signal_id": 368, + "name": "4039_W_iqcmd" + }, + { + "signal_id": 369, + "name": "4039_W_ibranchr" + }, + { + "signal_id": 370, + "name": "4039_W_ibranchi" + }, + { + "signal_id": 371, + "name": "4039_W_pbranch" + }, + { + "signal_id": 372, + "name": "4039_W_qbranch" + }, + { + "signal_id": 373, + "name": "4039_W_qext" + }, + { + "signal_id": 374, + "name": "4039_W_pext" + }, + { + "signal_id": 375, + "name": "4131_B_pmech" + }, + { + "signal_id": 376, + "name": "4131_B_efd" + }, + { + "signal_id": 377, + "name": "4131_B_speed" + }, + { + "signal_id": 378, + "name": "4131_H_pmech" + }, + { + "signal_id": 379, + "name": "4131_H_efd" + }, + { + "signal_id": 380, + "name": "4131_H_speed" + }, + { + "signal_id": 381, + "name": "4131_H_vs" + }, + { + "signal_id": 382, + "name": "4131_W_ipcmd" + }, + { + "signal_id": 383, + "name": "4131_W_iqcmd" + }, + { + "signal_id": 384, + "name": "4131_W_ibranchr" + }, + { + "signal_id": 385, + "name": "4131_W_ibranchi" + }, + { + "signal_id": 386, + "name": "4131_W_pbranch" + }, + { + "signal_id": 387, + "name": "4131_W_qbranch" + }, + { + "signal_id": 388, + "name": "4131_W_qext" + }, + { + "signal_id": 389, + "name": "4131_W_pext" + }, + { + "signal_id": 390, + "name": "4132_G_pmech" + }, + { + "signal_id": 391, + "name": "4132_G_efd" + }, + { + "signal_id": 392, + "name": "4132_G_speed" + }, + { + "signal_id": 393, + "name": "4132_H_pmech" + }, + { + "signal_id": 394, + "name": "4132_H_efd" + }, + { + "signal_id": 395, + "name": "4132_H_speed" + }, + { + "signal_id": 396, + "name": "4132_N_pmech" + }, + { + "signal_id": 397, + "name": "4132_N_efd" + }, + { + "signal_id": 398, + "name": "4132_N_speed" + }, + { + "signal_id": 399, + "name": "4132_W_ipcmd" + }, + { + "signal_id": 400, + "name": "4132_W_iqcmd" + }, + { + "signal_id": 401, + "name": "4132_W_ibranchr" + }, + { + "signal_id": 402, + "name": "4132_W_ibranchi" + }, + { + "signal_id": 403, + "name": "4132_W_pbranch" + }, + { + "signal_id": 404, + "name": "4132_W_qbranch" + }, + { + "signal_id": 405, + "name": "4132_W_qext" + }, + { + "signal_id": 406, + "name": "4132_W_pext" + }, + { + "signal_id": 407, + "name": "4231_C_pmech" + }, + { + "signal_id": 408, + "name": "4231_C_efd" + }, + { + "signal_id": 409, + "name": "4231_C_speed" + }, + { + "signal_id": 410, + "name": "4231_G_pmech" + }, + { + "signal_id": 411, + "name": "4231_G_efd" + }, + { + "signal_id": 412, + "name": "4231_G_speed" + }, + { + "signal_id": 413, + "name": "4231_H_pmech" + }, + { + "signal_id": 414, + "name": "4231_H_efd" + }, + { + "signal_id": 415, + "name": "4231_H_speed" + }, + { + "signal_id": 416, + "name": "4232_G_pmech" + }, + { + "signal_id": 417, + "name": "4232_G_efd" + }, + { + "signal_id": 418, + "name": "4232_G_speed" + }, + { + "signal_id": 419, + "name": "4232_H_pmech" + }, + { + "signal_id": 420, + "name": "4232_H_efd" + }, + { + "signal_id": 421, + "name": "4232_H_speed" + }, + { + "signal_id": 422, + "name": "4232_W_ipcmd" + }, + { + "signal_id": 423, + "name": "4232_W_iqcmd" + }, + { + "signal_id": 424, + "name": "4232_W_ibranchr" + }, + { + "signal_id": 425, + "name": "4232_W_ibranchi" + }, + { + "signal_id": 426, + "name": "4232_W_pbranch" + }, + { + "signal_id": 427, + "name": "4232_W_qbranch" + }, + { + "signal_id": 428, + "name": "4232_W_qext" + }, + { + "signal_id": 429, + "name": "4232_W_pext" + }, + { + "signal_id": 430, + "name": "5031_G_pmech" + }, + { + "signal_id": 431, + "name": "5031_G_efd" + }, + { + "signal_id": 432, + "name": "5031_G_speed" + }, + { + "signal_id": 433, + "name": "5031_H_pmech" + }, + { + "signal_id": 434, + "name": "5031_H_efd" + }, + { + "signal_id": 435, + "name": "5031_H_speed" + }, + { + "signal_id": 436, + "name": "5032_C_pmech" + }, + { + "signal_id": 437, + "name": "5032_C_efd" + }, + { + "signal_id": 438, + "name": "5032_C_speed" + }, + { + "signal_id": 439, + "name": "5032_G_pmech" + }, + { + "signal_id": 440, + "name": "5032_G_efd" + }, + { + "signal_id": 441, + "name": "5032_G_speed" + }, + { + "signal_id": 442, + "name": "5032_R_pmech" + }, + { + "signal_id": 443, + "name": "5032_R_efd" + }, + { + "signal_id": 444, + "name": "5032_R_speed" + }, + { + "signal_id": 445, + "name": "5032_S_ipcmd" + }, + { + "signal_id": 446, + "name": "5032_S_iqcmd" + }, + { + "signal_id": 447, + "name": "5032_S_ibranchr" + }, + { + "signal_id": 448, + "name": "5032_S_ibranchi" + }, + { + "signal_id": 449, + "name": "5032_S_pbranch" + }, + { + "signal_id": 450, + "name": "5032_S_qbranch" + }, + { + "signal_id": 451, + "name": "5032_S_qext" + }, + { + "signal_id": 452, + "name": "5032_S_pext" + }, + { + "signal_id": 453, + "name": "5032_W_ipcmd" + }, + { + "signal_id": 454, + "name": "5032_W_iqcmd" + }, + { + "signal_id": 455, + "name": "5032_W_ibranchr" + }, + { + "signal_id": 456, + "name": "5032_W_ibranchi" + }, + { + "signal_id": 457, + "name": "5032_W_pbranch" + }, + { + "signal_id": 458, + "name": "5032_W_qbranch" + }, + { + "signal_id": 459, + "name": "5032_W_qext" + }, + { + "signal_id": 460, + "name": "5032_W_pext" + }, + { + "signal_id": 461, + "name": "6132_B_pmech" + }, + { + "signal_id": 462, + "name": "6132_B_efd" + }, + { + "signal_id": 463, + "name": "6132_B_speed" + }, + { + "signal_id": 464, + "name": "6132_G_pmech" + }, + { + "signal_id": 465, + "name": "6132_G_efd" + }, + { + "signal_id": 466, + "name": "6132_G_speed" + }, + { + "signal_id": 467, + "name": "6132_H_pmech" + }, + { + "signal_id": 468, + "name": "6132_H_efd" + }, + { + "signal_id": 469, + "name": "6132_H_speed" + }, + { + "signal_id": 470, + "name": "6132_S_ipcmd" + }, + { + "signal_id": 471, + "name": "6132_S_iqcmd" + }, + { + "signal_id": 472, + "name": "6132_S_ibranchr" + }, + { + "signal_id": 473, + "name": "6132_S_ibranchi" + }, + { + "signal_id": 474, + "name": "6132_S_pbranch" + }, + { + "signal_id": 475, + "name": "6132_S_qbranch" + }, + { + "signal_id": 476, + "name": "6132_S_qext" + }, + { + "signal_id": 477, + "name": "6132_S_pext" + }, + { + "signal_id": 478, + "name": "6132_W_ipcmd" + }, + { + "signal_id": 479, + "name": "6132_W_iqcmd" + }, + { + "signal_id": 480, + "name": "6132_W_ibranchr" + }, + { + "signal_id": 481, + "name": "6132_W_ibranchi" + }, + { + "signal_id": 482, + "name": "6132_W_pbranch" + }, + { + "signal_id": 483, + "name": "6132_W_qbranch" + }, + { + "signal_id": 484, + "name": "6132_W_qext" + }, + { + "signal_id": 485, + "name": "6132_W_pext" + }, + { + "signal_id": 486, + "name": "6231_C_pmech" + }, + { + "signal_id": 487, + "name": "6231_C_efd" + }, + { + "signal_id": 488, + "name": "6231_C_speed" + }, + { + "signal_id": 489, + "name": "6231_G_pmech" + }, + { + "signal_id": 490, + "name": "6231_G_efd" + }, + { + "signal_id": 491, + "name": "6231_G_speed" + }, + { + "signal_id": 492, + "name": "6235_G_pmech" + }, + { + "signal_id": 493, + "name": "6235_G_efd" + }, + { + "signal_id": 494, + "name": "6235_G_speed" + }, + { + "signal_id": 495, + "name": "6235_H_pmech" + }, + { + "signal_id": 496, + "name": "6235_H_efd" + }, + { + "signal_id": 497, + "name": "6235_H_speed" + }, + { + "signal_id": 498, + "name": "6235_H_vs" + }, + { + "signal_id": 499, + "name": "6235_W_ipcmd" + }, + { + "signal_id": 500, + "name": "6235_W_iqcmd" + }, + { + "signal_id": 501, + "name": "6235_W_ibranchr" + }, + { + "signal_id": 502, + "name": "6235_W_ibranchi" + }, + { + "signal_id": 503, + "name": "6235_W_pbranch" + }, + { + "signal_id": 504, + "name": "6235_W_qbranch" + }, + { + "signal_id": 505, + "name": "6235_W_qext" + }, + { + "signal_id": 506, + "name": "6235_W_pext" + }, + { + "signal_id": 507, + "name": "6333_C_pmech" + }, + { + "signal_id": 508, + "name": "6333_C_efd" + }, + { + "signal_id": 509, + "name": "6333_C_speed" + }, + { + "signal_id": 510, + "name": "6333_W_ipcmd" + }, + { + "signal_id": 511, + "name": "6333_W_iqcmd" + }, + { + "signal_id": 512, + "name": "6333_W_ibranchr" + }, + { + "signal_id": 513, + "name": "6333_W_ibranchi" + }, + { + "signal_id": 514, + "name": "6333_W_pbranch" + }, + { + "signal_id": 515, + "name": "6333_W_qbranch" + }, + { + "signal_id": 516, + "name": "6333_W_qext" + }, + { + "signal_id": 517, + "name": "6333_W_pext" + }, + { + "signal_id": 518, + "name": "6335_C_pmech" + }, + { + "signal_id": 519, + "name": "6335_C_efd" + }, + { + "signal_id": 520, + "name": "6335_C_speed" + }, + { + "signal_id": 521, + "name": "6335_G_pmech" + }, + { + "signal_id": 522, + "name": "6335_G_efd" + }, + { + "signal_id": 523, + "name": "6335_G_speed" + }, + { + "signal_id": 524, + "name": "6335_H_pmech" + }, + { + "signal_id": 525, + "name": "6335_H_efd" + }, + { + "signal_id": 526, + "name": "6335_H_speed" + }, + { + "signal_id": 527, + "name": "6433_C_pmech" + }, + { + "signal_id": 528, + "name": "6433_C_efd" + }, + { + "signal_id": 529, + "name": "6433_C_speed" + }, + { + "signal_id": 530, + "name": "6433_E_pmech" + }, + { + "signal_id": 531, + "name": "6433_E_efd" + }, + { + "signal_id": 532, + "name": "6433_E_speed" + }, + { + "signal_id": 533, + "name": "6433_G_pmech" + }, + { + "signal_id": 534, + "name": "6433_G_efd" + }, + { + "signal_id": 535, + "name": "6433_G_speed" + }, + { + "signal_id": 536, + "name": "6433_W_ipcmd" + }, + { + "signal_id": 537, + "name": "6433_W_iqcmd" + }, + { + "signal_id": 538, + "name": "6433_W_ibranchr" + }, + { + "signal_id": 539, + "name": "6433_W_ibranchi" + }, + { + "signal_id": 540, + "name": "6433_W_pbranch" + }, + { + "signal_id": 541, + "name": "6433_W_qbranch" + }, + { + "signal_id": 542, + "name": "6433_W_qext" + }, + { + "signal_id": 543, + "name": "6433_W_pext" + }, + { + "signal_id": 544, + "name": "6533_C_pmech" + }, + { + "signal_id": 545, + "name": "6533_C_efd" + }, + { + "signal_id": 546, + "name": "6533_C_speed" + }, + { + "signal_id": 547, + "name": "6533_C_vs" + }, + { + "signal_id": 548, + "name": "6533_G_pmech" + }, + { + "signal_id": 549, + "name": "6533_G_efd" + }, + { + "signal_id": 550, + "name": "6533_G_speed" + }, + { + "signal_id": 551, + "name": "6533_H_pmech" + }, + { + "signal_id": 552, + "name": "6533_H_efd" + }, + { + "signal_id": 553, + "name": "6533_H_speed" + }, + { + "signal_id": 554, + "name": "6533_S_ipcmd" + }, + { + "signal_id": 555, + "name": "6533_S_iqcmd" + }, + { + "signal_id": 556, + "name": "6533_S_ibranchr" + }, + { + "signal_id": 557, + "name": "6533_S_ibranchi" + }, + { + "signal_id": 558, + "name": "6533_S_pbranch" + }, + { + "signal_id": 559, + "name": "6533_S_qbranch" + }, + { + "signal_id": 560, + "name": "6533_S_qext" + }, + { + "signal_id": 561, + "name": "6533_S_pext" + }, + { + "signal_id": 562, + "name": "6533_W_ipcmd" + }, + { + "signal_id": 563, + "name": "6533_W_iqcmd" + }, + { + "signal_id": 564, + "name": "6533_W_ibranchr" + }, + { + "signal_id": 565, + "name": "6533_W_ibranchi" + }, + { + "signal_id": 566, + "name": "6533_W_pbranch" + }, + { + "signal_id": 567, + "name": "6533_W_qbranch" + }, + { + "signal_id": 568, + "name": "6533_W_qext" + }, + { + "signal_id": 569, + "name": "6533_W_pext" + }, + { + "signal_id": 570, + "name": "7031_C_pmech" + }, + { + "signal_id": 571, + "name": "7031_C_efd" + }, + { + "signal_id": 572, + "name": "7031_C_speed" + }, + { + "signal_id": 573, + "name": "7031_G_pmech" + }, + { + "signal_id": 574, + "name": "7031_G_efd" + }, + { + "signal_id": 575, + "name": "7031_G_speed" + }, + { + "signal_id": 576, + "name": "7031_G_vs" + }, + { + "signal_id": 577, + "name": "7031_P_pmech" + }, + { + "signal_id": 578, + "name": "7031_P_efd" + }, + { + "signal_id": 579, + "name": "7031_P_speed" + }, + { + "signal_id": 580, + "name": "7031_W_ipcmd" + }, + { + "signal_id": 581, + "name": "7031_W_iqcmd" + }, + { + "signal_id": 582, + "name": "7031_W_ibranchr" + }, + { + "signal_id": 583, + "name": "7031_W_ibranchi" + }, + { + "signal_id": 584, + "name": "7031_W_pbranch" + }, + { + "signal_id": 585, + "name": "7031_W_qbranch" + }, + { + "signal_id": 586, + "name": "7031_W_qext" + }, + { + "signal_id": 587, + "name": "7031_W_pext" + }, + { + "signal_id": 588, + "name": "7032_C_pmech" + }, + { + "signal_id": 589, + "name": "7032_C_efd" + }, + { + "signal_id": 590, + "name": "7032_C_speed" + }, + { + "signal_id": 591, + "name": "7032_G_pmech" + }, + { + "signal_id": 592, + "name": "7032_G_efd" + }, + { + "signal_id": 593, + "name": "7032_G_speed" + }, + { + "signal_id": 594, + "name": "7032_H_pmech" + }, + { + "signal_id": 595, + "name": "7032_H_efd" + }, + { + "signal_id": 596, + "name": "7032_H_speed" + }, + { + "signal_id": 597, + "name": "7032_S_ipcmd" + }, + { + "signal_id": 598, + "name": "7032_S_iqcmd" + }, + { + "signal_id": 599, + "name": "7032_S_ibranchr" + }, + { + "signal_id": 600, + "name": "7032_S_ibranchi" + }, + { + "signal_id": 601, + "name": "7032_S_pbranch" + }, + { + "signal_id": 602, + "name": "7032_S_qbranch" + }, + { + "signal_id": 603, + "name": "7032_S_qext" + }, + { + "signal_id": 604, + "name": "7032_S_pext" + }, + { + "signal_id": 605, + "name": "8033_H_pmech" + }, + { + "signal_id": 606, + "name": "8033_H_efd" + }, + { + "signal_id": 607, + "name": "8033_H_speed" + }, + { + "signal_id": 608, + "name": "8034_G_pmech" + }, + { + "signal_id": 609, + "name": "8034_G_efd" + }, + { + "signal_id": 610, + "name": "8034_G_speed" + }, + { + "signal_id": 611, + "name": "8034_G_vs" + }, + { + "signal_id": 612, + "name": "8034_H_pmech" + }, + { + "signal_id": 613, + "name": "8034_H_efd" + }, + { + "signal_id": 614, + "name": "8034_H_speed" + } + ], + "devices": [ + { + "class": "Branch", + "id": "branch_1001_1002_1", + "ports": { + "bus1": 1001, + "bus2": 1002 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.010999999940395355, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1001_1002_2", + "ports": { + "bus1": 1001, + "bus2": 1002 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.010999999940395355, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1001_1201_1", + "ports": { + "bus1": 1001, + "bus2": 1201 + }, + "params": { + "R": 0.001769999973475933, + "X": 0.031690001487731934, + "B": 3.344599962234497, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1001_1202_9", + "ports": { + "bus1": 1001, + "bus2": 1202 + }, + "params": { + "R": 0.01080000028014183, + "X": 0.09650000184774399, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1002_1003_1", + "ports": { + "bus1": 1002, + "bus2": 1003 + }, + "params": { + "R": 0.0002800000074785203, + "X": 0.013799999840557575, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1002_1003_2", + "ports": { + "bus1": 1002, + "bus2": 1003 + }, + "params": { + "R": 0.0002899999963119626, + "X": 0.013899999670684338, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1002_1004_1", + "ports": { + "bus1": 1002, + "bus2": 1004 + }, + "params": { + "R": 0.0005000000237487257, + "X": 0.0052999998442828655, + "B": 0.08820000290870667, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1002_1032_1", + "ports": { + "bus1": 1002, + "bus2": 1032 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1002_1102_1", + "ports": { + "bus1": 1002, + "bus2": 1102 + }, + "params": { + "R": 0.0017900000093504786, + "X": 0.01988000050187111, + "B": 2.5759999752044678, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1002_1102_2", + "ports": { + "bus1": 1002, + "bus2": 1102 + }, + "params": { + "R": 0.0017900000093504786, + "X": 0.01988000050187111, + "B": 2.5759999752044678, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1002_6506_1", + "ports": { + "bus1": 1002, + "bus2": 6506 + }, + "params": { + "R": 0.004800000227987766, + "X": 0.04360000044107437, + "B": 0.7077999711036682, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1004_1034_1", + "ports": { + "bus1": 1004, + "bus2": 1034 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1004_7001_1", + "ports": { + "bus1": 1004, + "bus2": 7001 + }, + "params": { + "R": 0.00810999982059002, + "X": 0.13689999282360077, + "B": 2.434799909591675, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1004_7002_1", + "ports": { + "bus1": 1004, + "bus2": 7002 + }, + "params": { + "R": 0.009770000353455544, + "X": 0.10999999940395355, + "B": 2.0, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1101_1102_1", + "ports": { + "bus1": 1101, + "bus2": 1102 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.014600000344216824, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1101_1102_2", + "ports": { + "bus1": 1101, + "bus2": 1102 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.014600000344216824, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1101_1131_1", + "ports": { + "bus1": 1101, + "bus2": 1131 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1101_1401_1", + "ports": { + "bus1": 1101, + "bus2": 1401 + }, + "params": { + "R": 0.00279999990016222, + "X": 0.0210999995470047, + "B": 1.0194000005722046, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1101_1401_2", + "ports": { + "bus1": 1101, + "bus2": 1401 + }, + "params": { + "R": 0.00279999990016222, + "X": 0.0210999995470047, + "B": 1.0194000005722046, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1201_1202_1", + "ports": { + "bus1": 1201, + "bus2": 1202 + }, + "params": { + "R": 0.0007699999841861427, + "X": 0.00535999983549118, + "B": 1.398419976234436, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1201_1402_1", + "ports": { + "bus1": 1201, + "bus2": 1402 + }, + "params": { + "R": 0.0017900000093504786, + "X": 0.025919999927282333, + "B": 3.392199993133545, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1201_2901_1", + "ports": { + "bus1": 1201, + "bus2": 2901 + }, + "params": { + "R": 0.0020699999295175076, + "X": 0.013690000399947166, + "B": 3.9516000747680664, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1202_1232_1", + "ports": { + "bus1": 1202, + "bus2": 1232 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1202_1302_1", + "ports": { + "bus1": 1202, + "bus2": 1302 + }, + "params": { + "R": 0.00279999990016222, + "X": 0.0210999995470047, + "B": 1.0194000005722046, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1202_1402_1", + "ports": { + "bus1": 1202, + "bus2": 1402 + }, + "params": { + "R": 0.002409999957308173, + "X": 0.03488999977707863, + "B": 4.865600109100342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1301_1302_1", + "ports": { + "bus1": 1301, + "bus2": 1302 + }, + "params": { + "R": 0.00279999990016222, + "X": 0.0210999995470047, + "B": 1.0194000005722046, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1301_1331_1", + "ports": { + "bus1": 1301, + "bus2": 1331 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1301_1402_1", + "ports": { + "bus1": 1301, + "bus2": 1402 + }, + "params": { + "R": 0.00279999990016222, + "X": 0.0210999995470047, + "B": 1.0194000005722046, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1301_1402_2", + "ports": { + "bus1": 1301, + "bus2": 1402 + }, + "params": { + "R": 0.006200000178068876, + "X": 0.06729999929666519, + "B": 1.1155999898910522, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1301_2603_1", + "ports": { + "bus1": 1301, + "bus2": 2603 + }, + "params": { + "R": 0.0017900000093504786, + "X": 0.02524000033736229, + "B": 0.5354599952697754, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1301_2901_1", + "ports": { + "bus1": 1301, + "bus2": 2901 + }, + "params": { + "R": 0.01080000028014183, + "X": 0.09650000184774399, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1302_1303_1", + "ports": { + "bus1": 1302, + "bus2": 1303 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.007199999876320362, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1303_1333_1", + "ports": { + "bus1": 1303, + "bus2": 1333 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1303_6507_1", + "ports": { + "bus1": 1303, + "bus2": 6507 + }, + "params": { + "R": 0.00810999982059002, + "X": 0.13689999282360077, + "B": 1.1155999898910522, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1401_1402_1", + "ports": { + "bus1": 1401, + "bus2": 1402 + }, + "params": { + "R": 0.00039999998989515007, + "X": 0.009600000455975533, + "B": 0.9038000106811523, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1401_1402_2", + "ports": { + "bus1": 1401, + "bus2": 1402 + }, + "params": { + "R": 0.00039999998989515007, + "X": 0.009600000455975533, + "B": 0.9038000106811523, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1401_1403_1", + "ports": { + "bus1": 1401, + "bus2": 1403 + }, + "params": { + "R": 0.0002800000074785203, + "X": 0.013799999840557575, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1401_1431_1", + "ports": { + "bus1": 1401, + "bus2": 1431 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_1401_2301_1", + "ports": { + "bus1": 1401, + "bus2": 2301 + }, + "params": { + "R": 0.002589999930933118, + "X": 0.029670000076293945, + "B": 2.1530001163482666, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1401_2400_1", + "ports": { + "bus1": 1401, + "bus2": 2400 + }, + "params": { + "R": 0.002589999930933118, + "X": 0.029670000076293945, + "B": 2.1530001163482666, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_1403_2100_1", + "ports": { + "bus1": 1403, + "bus2": 2100 + }, + "params": { + "R": 0.008449999615550041, + "X": 0.07034000009298325, + "B": 0.15953999757766724, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2000_2030_1", + "ports": { + "bus1": 2000, + "bus2": 2030 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2000_2202_1", + "ports": { + "bus1": 2000, + "bus2": 2202 + }, + "params": { + "R": 0.0013800000306218863, + "X": 0.05398999899625778, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2000_2302_1", + "ports": { + "bus1": 2000, + "bus2": 2302 + }, + "params": { + "R": 0.0013800000306218863, + "X": 0.05398999899625778, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2100_2130_1", + "ports": { + "bus1": 2100, + "bus2": 2130 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2100_2302_1", + "ports": { + "bus1": 2100, + "bus2": 2302 + }, + "params": { + "R": 0.008449999615550041, + "X": 0.07034000009298325, + "B": 0.15953999757766724, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2100_2400_1", + "ports": { + "bus1": 2100, + "bus2": 2400 + }, + "params": { + "R": 0.0002800000074785203, + "X": 0.013799999840557575, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2201_2202_1", + "ports": { + "bus1": 2201, + "bus2": 2202 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.004999999888241291, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2201_2202_2", + "ports": { + "bus1": 2201, + "bus2": 2202 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.004999999888241291, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2201_2301_1", + "ports": { + "bus1": 2201, + "bus2": 2301 + }, + "params": { + "R": 0.0017900000093504786, + "X": 0.02524000033736229, + "B": 2.1530001163482666, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2202_2203_1", + "ports": { + "bus1": 2202, + "bus2": 2203 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2202_2203_2", + "ports": { + "bus1": 2202, + "bus2": 2203 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2202_2503_1", + "ports": { + "bus1": 2202, + "bus2": 2503 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2203_2233_1", + "ports": { + "bus1": 2203, + "bus2": 2233 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2203_2503_1", + "ports": { + "bus1": 2203, + "bus2": 2503 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2203_2503_2", + "ports": { + "bus1": 2203, + "bus2": 2503 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2301_2302_1", + "ports": { + "bus1": 2301, + "bus2": 2302 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.004999999888241291, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2301_2302_2", + "ports": { + "bus1": 2301, + "bus2": 2302 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.004999999888241291, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2302_2332_1", + "ports": { + "bus1": 2302, + "bus2": 2332 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2400_2403_1", + "ports": { + "bus1": 2400, + "bus2": 2403 + }, + "params": { + "R": 0.0004199999966658652, + "X": 0.009050000458955765, + "B": 0.6679400205612183, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2401_2402_1", + "ports": { + "bus1": 2401, + "bus2": 2402 + }, + "params": { + "R": 0.0002800000074785203, + "X": 0.007530000060796738, + "B": 0.5173599720001221, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2401_2402_2", + "ports": { + "bus1": 2401, + "bus2": 2402 + }, + "params": { + "R": 0.0003499999875202775, + "X": 0.007499999832361937, + "B": 0.553600013256073, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2401_2404_1", + "ports": { + "bus1": 2401, + "bus2": 2404 + }, + "params": { + "R": 0.0004400000034365803, + "X": 0.011250000447034836, + "B": 0.829200029373169, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2401_2404_2", + "ports": { + "bus1": 2401, + "bus2": 2404 + }, + "params": { + "R": 0.0004400000034365803, + "X": 0.011250000447034836, + "B": 0.829200029373169, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2401_2431_1", + "ports": { + "bus1": 2401, + "bus2": 2431 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 9.999999747378752e-05, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2401_2501_1", + "ports": { + "bus1": 2401, + "bus2": 2501 + }, + "params": { + "R": 0.0006000000284984708, + "X": 0.012799999676644802, + "B": 0.9462000131607056, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2401_2603_1", + "ports": { + "bus1": 2401, + "bus2": 2603 + }, + "params": { + "R": 0.00019999999494757503, + "X": 0.004100000020116568, + "B": 0.2962000072002411, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2401_2901_1", + "ports": { + "bus1": 2401, + "bus2": 2901 + }, + "params": { + "R": 0.001930000027641654, + "X": 0.027790000662207603, + "B": 4.671199798583984, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2401_2902_1", + "ports": { + "bus1": 2401, + "bus2": 2902 + }, + "params": { + "R": 0.0019000000320374966, + "X": 0.03099999949336052, + "B": 4.140200138092041, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2402_2409_1", + "ports": { + "bus1": 2402, + "bus2": 2409 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.004999999888241291, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2402_2501_1", + "ports": { + "bus1": 2402, + "bus2": 2501 + }, + "params": { + "R": 0.0002099999983329326, + "X": 0.004569999873638153, + "B": 0.32335999608039856, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2403_2501_1", + "ports": { + "bus1": 2403, + "bus2": 2501 + }, + "params": { + "R": 0.00039999998989515007, + "X": 0.00930000003427267, + "B": 0.6855999827384949, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2404_2411_1", + "ports": { + "bus1": 2404, + "bus2": 2411 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.011490000411868095, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2404_2411_2", + "ports": { + "bus1": 2404, + "bus2": 2411 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.011490000411868095, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2404_2411_3", + "ports": { + "bus1": 2404, + "bus2": 2411 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.011490000411868095, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2404_3893_1", + "ports": { + "bus1": 2404, + "bus2": 3893 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": -0.009349999949336052, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "capacitor": true + } + }, + { + "class": "Branch", + "id": "branch_2404_3895_1", + "ports": { + "bus1": 2404, + "bus2": 3895 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": -0.009349999949336052, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "capacitor": true + } + }, + { + "class": "Branch", + "id": "branch_2404_3897_1", + "ports": { + "bus1": 2404, + "bus2": 3897 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": -0.00839999970048666, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "capacitor": true + } + }, + { + "class": "Branch", + "id": "branch_2405_2406_1", + "ports": { + "bus1": 2405, + "bus2": 2406 + }, + "params": { + "R": 0.00139999995008111, + "X": 0.026399999856948853, + "B": 0.10199999809265137, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2405_2410_1", + "ports": { + "bus1": 2405, + "bus2": 2410 + }, + "params": { + "R": 0.0006500000017695129, + "X": 0.011869999580085278, + "B": 0.046720001846551895, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2405_2410_2", + "ports": { + "bus1": 2405, + "bus2": 2410 + }, + "params": { + "R": 0.0006500000017695129, + "X": 0.011869999580085278, + "B": 0.046720001846551895, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2405_2619_1", + "ports": { + "bus1": 2405, + "bus2": 2619 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0011500000255182385, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2406_2408_1", + "ports": { + "bus1": 2406, + "bus2": 2408 + }, + "params": { + "R": 0.0019000000320374966, + "X": 0.025800000876188278, + "B": 0.09839999675750732, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2406_2410_1", + "ports": { + "bus1": 2406, + "bus2": 2410 + }, + "params": { + "R": 0.008449999615550041, + "X": 0.07034000009298325, + "B": 0.15953999757766724, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2407_2408_1", + "ports": { + "bus1": 2407, + "bus2": 2408 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2408_2409_1", + "ports": { + "bus1": 2408, + "bus2": 2409 + }, + "params": { + "R": 0.0013800000306218863, + "X": 0.05398999899625778, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2408_2409_2", + "ports": { + "bus1": 2408, + "bus2": 2409 + }, + "params": { + "R": 0.0013800000306218863, + "X": 0.05398999899625778, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2408_2411_1", + "ports": { + "bus1": 2408, + "bus2": 2411 + }, + "params": { + "R": 0.0031999999191612005, + "X": 0.039500001817941666, + "B": 0.14399999380111694, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2408_2438_1", + "ports": { + "bus1": 2408, + "bus2": 2438 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2408_2502_1", + "ports": { + "bus1": 2408, + "bus2": 2502 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2409_2439_1", + "ports": { + "bus1": 2409, + "bus2": 2439 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 9.999999747378752e-05, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2409_2502_1", + "ports": { + "bus1": 2409, + "bus2": 2502 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2409_2503_1", + "ports": { + "bus1": 2409, + "bus2": 2503 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2410_2411_1", + "ports": { + "bus1": 2410, + "bus2": 2411 + }, + "params": { + "R": 0.002850000048056245, + "X": 0.036490000784397125, + "B": 0.1265600025653839, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2410_2411_2", + "ports": { + "bus1": 2410, + "bus2": 2411 + }, + "params": { + "R": 0.0013800000306218863, + "X": 0.03398999944329262, + "B": 0.1125200018286705, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2411_2434_1", + "ports": { + "bus1": 2411, + "bus2": 2434 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 9.999999747378752e-05, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2501_2502_1", + "ports": { + "bus1": 2501, + "bus2": 2502 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.004999999888241291, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2501_2502_2", + "ports": { + "bus1": 2501, + "bus2": 2502 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.004999999888241291, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2501_2502_3", + "ports": { + "bus1": 2501, + "bus2": 2502 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.004999999888241291, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2502_2503_1", + "ports": { + "bus1": 2502, + "bus2": 2503 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2502_2503_2", + "ports": { + "bus1": 2502, + "bus2": 2503 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2503_2533_1", + "ports": { + "bus1": 2503, + "bus2": 2533 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2600_2601_1", + "ports": { + "bus1": 2600, + "bus2": 2601 + }, + "params": { + "R": 0.0007399999885819852, + "X": 0.018610000610351562, + "B": 1.4026399850845337, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2600_2602_1", + "ports": { + "bus1": 2600, + "bus2": 2602 + }, + "params": { + "R": 0.0008200000156648457, + "X": 0.016680000349879265, + "B": 1.1880199909210205, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2600_2603_1", + "ports": { + "bus1": 2600, + "bus2": 2603 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0015899999998509884, + "B": 0.12002000212669373, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2600_2603_2", + "ports": { + "bus1": 2600, + "bus2": 2603 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0015899999998509884, + "B": 0.12002000212669373, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2601_2603_1", + "ports": { + "bus1": 2601, + "bus2": 2603 + }, + "params": { + "R": 0.0008299999753944576, + "X": 0.0188400000333786, + "B": 1.6666799783706665, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2601_2612_1", + "ports": { + "bus1": 2601, + "bus2": 2612 + }, + "params": { + "R": 0.00026000000070780516, + "X": 0.013860000297427177, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2602_2615_1", + "ports": { + "bus1": 2602, + "bus2": 2615 + }, + "params": { + "R": 0.00013000000035390258, + "X": 0.013860000297427177, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2602_2615_2", + "ports": { + "bus1": 2602, + "bus2": 2615 + }, + "params": { + "R": 0.00013000000035390258, + "X": 0.013860000297427177, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2603_2607_1", + "ports": { + "bus1": 2603, + "bus2": 2607 + }, + "params": { + "R": 0.00019999999494757503, + "X": 0.02338000014424324, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2603_2901_1", + "ports": { + "bus1": 2603, + "bus2": 2901 + }, + "params": { + "R": 0.0017900000093504786, + "X": 0.02524000033736229, + "B": 0.5354599952697754, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2604_2634_1", + "ports": { + "bus1": 2604, + "bus2": 2634 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2604_6404_1", + "ports": { + "bus1": 2604, + "bus2": 6404 + }, + "params": { + "R": 0.01080000028014183, + "X": 0.09650000184774399, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2604_6504_1", + "ports": { + "bus1": 2604, + "bus2": 6504 + }, + "params": { + "R": 0.0017999999690800905, + "X": 0.02449999935925007, + "B": 0.4392000138759613, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2604_6504_2", + "ports": { + "bus1": 2604, + "bus2": 6504 + }, + "params": { + "R": 0.0017999999690800905, + "X": 0.02449999935925007, + "B": 0.4392000138759613, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2605_2607_1", + "ports": { + "bus1": 2605, + "bus2": 2607 + }, + "params": { + "R": 0.010700000450015068, + "X": 0.07904999703168869, + "B": 0.3666999936103821, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2605_2621_1", + "ports": { + "bus1": 2605, + "bus2": 2621 + }, + "params": { + "R": 0.000590000010561198, + "X": 0.014910000376403332, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2606_2607_1", + "ports": { + "bus1": 2606, + "bus2": 2607 + }, + "params": { + "R": 0.010700000450015068, + "X": 0.07904999703168869, + "B": 0.3666999936103821, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2606_2621_1", + "ports": { + "bus1": 2606, + "bus2": 2621 + }, + "params": { + "R": 0.000590000010561198, + "X": 0.014910000376403332, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2608_2611_1", + "ports": { + "bus1": 2608, + "bus2": 2611 + }, + "params": { + "R": 0.0022100000642240047, + "X": 0.03345999866724014, + "B": 0.0733800008893013, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2608_2612_1", + "ports": { + "bus1": 2608, + "bus2": 2612 + }, + "params": { + "R": 0.002899999963119626, + "X": 0.03799999877810478, + "B": 0.08240000158548355, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2608_2618_1", + "ports": { + "bus1": 2608, + "bus2": 2618 + }, + "params": { + "R": 0.0030900000128895044, + "X": 0.04676999896764755, + "B": 0.10080000013113022, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2608_2619_1", + "ports": { + "bus1": 2608, + "bus2": 2619 + }, + "params": { + "R": 0.002259999979287386, + "X": 0.034219998866319656, + "B": 0.07506000250577927, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2608_2638_1", + "ports": { + "bus1": 2608, + "bus2": 2638 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2609_2615_1", + "ports": { + "bus1": 2609, + "bus2": 2615 + }, + "params": { + "R": 0.00046999999904073775, + "X": 0.007230000104755163, + "B": 0.01624000072479248, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2609_2617_1", + "ports": { + "bus1": 2609, + "bus2": 2617 + }, + "params": { + "R": 0.0003499999875202775, + "X": 0.00535999983549118, + "B": 0.012040000408887863, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2610_2613_1", + "ports": { + "bus1": 2610, + "bus2": 2613 + }, + "params": { + "R": 0.002199999988079071, + "X": 0.034219998866319656, + "B": 0.07716000080108643, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2610_2613_2", + "ports": { + "bus1": 2610, + "bus2": 2613 + }, + "params": { + "R": 0.0023799999617040157, + "X": 0.03669000044465065, + "B": 0.08284000307321548, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2610_2616_1", + "ports": { + "bus1": 2610, + "bus2": 2616 + }, + "params": { + "R": 0.0020099999383091927, + "X": 0.030740000307559967, + "B": 0.0688600018620491, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2610_2617_1", + "ports": { + "bus1": 2610, + "bus2": 2617 + }, + "params": { + "R": 0.0028099999763071537, + "X": 0.04295999929308891, + "B": 0.09647999703884125, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2610_2630_1", + "ports": { + "bus1": 2610, + "bus2": 2630 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2611_2612_1", + "ports": { + "bus1": 2611, + "bus2": 2612 + }, + "params": { + "R": 0.0002899999963119626, + "X": 0.004339999984949827, + "B": 0.009499999694526196, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2611_2631_1", + "ports": { + "bus1": 2611, + "bus2": 2631 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2612_2615_1", + "ports": { + "bus1": 2612, + "bus2": 2615 + }, + "params": { + "R": 0.0022899999748915434, + "X": 0.01583000086247921, + "B": 0.03060000017285347, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2612_2615_2", + "ports": { + "bus1": 2612, + "bus2": 2615 + }, + "params": { + "R": 0.0022899999748915434, + "X": 0.01583000086247921, + "B": 0.03060000017285347, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2612_2618_1", + "ports": { + "bus1": 2612, + "bus2": 2618 + }, + "params": { + "R": 0.0014100000262260437, + "X": 0.009669999592006207, + "B": 0.01940000057220459, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2612_2618_2", + "ports": { + "bus1": 2612, + "bus2": 2618 + }, + "params": { + "R": 0.0014100000262260437, + "X": 0.009669999592006207, + "B": 0.01940000057220459, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2612_2618_3", + "ports": { + "bus1": 2612, + "bus2": 2618 + }, + "params": { + "R": 0.001610000035725534, + "X": 0.009709999896585941, + "B": 0.019279999658465385, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2612_2618_4", + "ports": { + "bus1": 2612, + "bus2": 2618 + }, + "params": { + "R": 0.001610000035725534, + "X": 0.009709999896585941, + "B": 0.019279999658465385, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2612_2619_1", + "ports": { + "bus1": 2612, + "bus2": 2619 + }, + "params": { + "R": 0.0002699999895412475, + "X": 0.003930000122636557, + "B": 0.009180000051856041, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2612_2619_2", + "ports": { + "bus1": 2612, + "bus2": 2619 + }, + "params": { + "R": 0.0002699999895412475, + "X": 0.003930000122636557, + "B": 0.009180000051856041, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2612_2619_3", + "ports": { + "bus1": 2612, + "bus2": 2619 + }, + "params": { + "R": 0.0002699999895412475, + "X": 0.003930000122636557, + "B": 0.009180000051856041, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2612_2620_1", + "ports": { + "bus1": 2612, + "bus2": 2620 + }, + "params": { + "R": 0.0013800000306218863, + "X": 0.01116000022739172, + "B": 0.024700000882148743, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2612_2620_2", + "ports": { + "bus1": 2612, + "bus2": 2620 + }, + "params": { + "R": 0.0013800000306218863, + "X": 0.01116000022739172, + "B": 0.024700000882148743, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2612_2637_1", + "ports": { + "bus1": 2612, + "bus2": 2637 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2613_2616_1", + "ports": { + "bus1": 2613, + "bus2": 2616 + }, + "params": { + "R": 0.0003699999942909926, + "X": 0.003659999929368496, + "B": 0.008299999870359898, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2613_2617_1", + "ports": { + "bus1": 2613, + "bus2": 2617 + }, + "params": { + "R": 0.0005499999970197678, + "X": 0.005859999917447567, + "B": 0.01245999988168478, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2614_2616_1", + "ports": { + "bus1": 2614, + "bus2": 2616 + }, + "params": { + "R": 0.0007300000288523734, + "X": 0.010250000283122063, + "B": 0.02558000013232231, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2614_2616_2", + "ports": { + "bus1": 2614, + "bus2": 2616 + }, + "params": { + "R": 0.0007300000288523734, + "X": 0.010250000283122063, + "B": 0.02558000013232231, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2614_2621_1", + "ports": { + "bus1": 2614, + "bus2": 2621 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.013299999758601189, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2614_2621_2", + "ports": { + "bus1": 2614, + "bus2": 2621 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.013399999588727951, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_2615_2617_1", + "ports": { + "bus1": 2615, + "bus2": 2617 + }, + "params": { + "R": 0.0011899999808520079, + "X": 0.012439999729394913, + "B": 0.027979999780654907, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2615_2617_2", + "ports": { + "bus1": 2615, + "bus2": 2617 + }, + "params": { + "R": 0.0011899999808520079, + "X": 0.012439999729394913, + "B": 0.027979999780654907, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2615_2620_1", + "ports": { + "bus1": 2615, + "bus2": 2620 + }, + "params": { + "R": 0.0012799999676644802, + "X": 0.009789999574422836, + "B": 0.021199999377131462, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2616_2617_1", + "ports": { + "bus1": 2616, + "bus2": 2617 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.011889999732375145, + "B": 0.025140000507235527, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_2901_2902_1", + "ports": { + "bus1": 2901, + "bus2": 2902 + }, + "params": { + "R": 0.0005600000149570405, + "X": 0.014150000177323818, + "B": 1.0428999662399292, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3101_3102_1", + "ports": { + "bus1": 3101, + "bus2": 3102 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3101_3102_2", + "ports": { + "bus1": 3101, + "bus2": 3102 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3102_3103_1", + "ports": { + "bus1": 3102, + "bus2": 3103 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3102_3103_2", + "ports": { + "bus1": 3102, + "bus2": 3103 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3102_3103_3", + "ports": { + "bus1": 3102, + "bus2": 3103 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3102_3104_1", + "ports": { + "bus1": 3102, + "bus2": 3104 + }, + "params": { + "R": 0.0008900000248104334, + "X": 0.029899999499320984, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3102_3302_1", + "ports": { + "bus1": 3102, + "bus2": 3302 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3103_3133_1", + "ports": { + "bus1": 3103, + "bus2": 3133 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3103_3204_1", + "ports": { + "bus1": 3103, + "bus2": 3204 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3103_3204_2", + "ports": { + "bus1": 3103, + "bus2": 3204 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3103_3305_1", + "ports": { + "bus1": 3103, + "bus2": 3305 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3103_3305_2", + "ports": { + "bus1": 3103, + "bus2": 3305 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3104_3105_1", + "ports": { + "bus1": 3104, + "bus2": 3105 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3105_3135_1", + "ports": { + "bus1": 3105, + "bus2": 3135 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3201_3202_1", + "ports": { + "bus1": 3201, + "bus2": 3202 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3201_3202_2", + "ports": { + "bus1": 3201, + "bus2": 3202 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3201_3203_1", + "ports": { + "bus1": 3201, + "bus2": 3203 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3201_3203_2", + "ports": { + "bus1": 3201, + "bus2": 3203 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3201_3923_1", + "ports": { + "bus1": 3201, + "bus2": 3923 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3201_3923_2", + "ports": { + "bus1": 3201, + "bus2": 3923 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3201_3924_1", + "ports": { + "bus1": 3201, + "bus2": 3924 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3201_3924_2", + "ports": { + "bus1": 3201, + "bus2": 3924 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3202_3203_9", + "ports": { + "bus1": 3202, + "bus2": 3203 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3202_3204_1", + "ports": { + "bus1": 3202, + "bus2": 3204 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3202_3205_1", + "ports": { + "bus1": 3202, + "bus2": 3205 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3202_3924_1", + "ports": { + "bus1": 3202, + "bus2": 3924 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3202_3924_2", + "ports": { + "bus1": 3202, + "bus2": 3924 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3203_3204_1", + "ports": { + "bus1": 3203, + "bus2": 3204 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3203_3303_1", + "ports": { + "bus1": 3203, + "bus2": 3303 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3203_3303_9", + "ports": { + "bus1": 3203, + "bus2": 3303 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3203_3305_1", + "ports": { + "bus1": 3203, + "bus2": 3305 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3203_3923_1", + "ports": { + "bus1": 3203, + "bus2": 3923 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3203_3923_2", + "ports": { + "bus1": 3203, + "bus2": 3923 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3204_3205_1", + "ports": { + "bus1": 3204, + "bus2": 3205 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3204_3205_2", + "ports": { + "bus1": 3204, + "bus2": 3205 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3204_3234_1", + "ports": { + "bus1": 3204, + "bus2": 3234 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3204_3923_1", + "ports": { + "bus1": 3204, + "bus2": 3923 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3204_3923_2", + "ports": { + "bus1": 3204, + "bus2": 3923 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3205_3914_1", + "ports": { + "bus1": 3205, + "bus2": 3914 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3205_3915_1", + "ports": { + "bus1": 3205, + "bus2": 3915 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3301_3303_1", + "ports": { + "bus1": 3301, + "bus2": 3303 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.017400000244379044, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3301_3303_2", + "ports": { + "bus1": 3301, + "bus2": 3303 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.017400000244379044, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3301_3303_3", + "ports": { + "bus1": 3301, + "bus2": 3303 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.017400000244379044, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3301_3902_1", + "ports": { + "bus1": 3301, + "bus2": 3902 + }, + "params": { + "R": 0.0005300000193528831, + "X": 0.012969999574124813, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3301_3903_1", + "ports": { + "bus1": 3301, + "bus2": 3903 + }, + "params": { + "R": 0.0005000000237487257, + "X": 0.00880999956279993, + "B": 0.5987799763679504, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3302_3304_1", + "ports": { + "bus1": 3302, + "bus2": 3304 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3302_3304_2", + "ports": { + "bus1": 3302, + "bus2": 3304 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3303_3304_1", + "ports": { + "bus1": 3303, + "bus2": 3304 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3303_3304_2", + "ports": { + "bus1": 3303, + "bus2": 3304 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3303_3304_3", + "ports": { + "bus1": 3303, + "bus2": 3304 + }, + "params": { + "R": 0.0010999999940395355, + "X": 0.01269999984651804, + "B": 0.04800000041723251, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3303_3333_1", + "ports": { + "bus1": 3303, + "bus2": 3333 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3303_3918_1", + "ports": { + "bus1": 3303, + "bus2": 3918 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3303_3918_2", + "ports": { + "bus1": 3303, + "bus2": 3918 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3305_3923_1", + "ports": { + "bus1": 3305, + "bus2": 3923 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3401_3402_1", + "ports": { + "bus1": 3401, + "bus2": 3402 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3401_3402_2", + "ports": { + "bus1": 3401, + "bus2": 3402 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3401_3404_1", + "ports": { + "bus1": 3401, + "bus2": 3404 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3401_3405_1", + "ports": { + "bus1": 3401, + "bus2": 3405 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3401_3405_2", + "ports": { + "bus1": 3401, + "bus2": 3405 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3401_3804_1", + "ports": { + "bus1": 3401, + "bus2": 3804 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3402_3432_1", + "ports": { + "bus1": 3402, + "bus2": 3432 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3403_3404_1", + "ports": { + "bus1": 3403, + "bus2": 3404 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3403_3433_1", + "ports": { + "bus1": 3403, + "bus2": 3433 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3403_3804_1", + "ports": { + "bus1": 3403, + "bus2": 3804 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3404_3804_2", + "ports": { + "bus1": 3404, + "bus2": 3804 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3404_3917_1", + "ports": { + "bus1": 3404, + "bus2": 3917 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3404_3918_1", + "ports": { + "bus1": 3404, + "bus2": 3918 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3405_3907_1", + "ports": { + "bus1": 3405, + "bus2": 3907 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3405_3907_2", + "ports": { + "bus1": 3405, + "bus2": 3907 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3501_3531_1", + "ports": { + "bus1": 3501, + "bus2": 3531 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3501_3914_1", + "ports": { + "bus1": 3501, + "bus2": 3914 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3501_3915_1", + "ports": { + "bus1": 3501, + "bus2": 3915 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3601_3631_1", + "ports": { + "bus1": 3601, + "bus2": 3631 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3601_3925_1", + "ports": { + "bus1": 3601, + "bus2": 3925 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3701_3731_1", + "ports": { + "bus1": 3701, + "bus2": 3731 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3701_3926_1", + "ports": { + "bus1": 3701, + "bus2": 3926 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3701_3926_2", + "ports": { + "bus1": 3701, + "bus2": 3926 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3701_6402_1", + "ports": { + "bus1": 3701, + "bus2": 6402 + }, + "params": { + "R": 0.0008900000248104334, + "X": 0.029899999499320984, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3701_6402_2", + "ports": { + "bus1": 3701, + "bus2": 6402 + }, + "params": { + "R": 0.0008900000248104334, + "X": 0.029899999499320984, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3801_3802_1", + "ports": { + "bus1": 3801, + "bus2": 3802 + }, + "params": { + "R": 0.0007900000200606883, + "X": 0.019370000809431076, + "B": 1.3285000324249268, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3801_3803_1", + "ports": { + "bus1": 3801, + "bus2": 3803 + }, + "params": { + "R": 0.0008699999889358878, + "X": 0.02087000012397766, + "B": 1.4571000337600708, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3801_3803_2", + "ports": { + "bus1": 3801, + "bus2": 3803 + }, + "params": { + "R": 0.0008699999889358878, + "X": 0.02087000012397766, + "B": 1.4571000337600708, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3801_3831_1", + "ports": { + "bus1": 3801, + "bus2": 3831 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3802_3804_1", + "ports": { + "bus1": 3802, + "bus2": 3804 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.017400000244379044, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3802_3891_1", + "ports": { + "bus1": 3802, + "bus2": 3891 + }, + "params": { + "R": 0.0007200000109151006, + "X": 0.01600000075995922, + "B": 1.0879000425338745, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3802_3901_1", + "ports": { + "bus1": 3802, + "bus2": 3901 + }, + "params": { + "R": 0.0008299999753944576, + "X": 0.019850000739097595, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3803_3805_1", + "ports": { + "bus1": 3803, + "bus2": 3805 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.017400000244379044, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3803_3805_2", + "ports": { + "bus1": 3803, + "bus2": 3805 + }, + "params": { + "R": 0.00019999999494757503, + "X": 0.011900000274181366, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3803_3891_1", + "ports": { + "bus1": 3803, + "bus2": 3891 + }, + "params": { + "R": 1.9999999494757503e-05, + "X": -0.009979999624192715, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3803_3892_1", + "ports": { + "bus1": 3803, + "bus2": 3892 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": -0.009349999949336052, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "capacitor": true + } + }, + { + "class": "Branch", + "id": "branch_3803_3894_1", + "ports": { + "bus1": 3803, + "bus2": 3894 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": -0.009440000168979168, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "capacitor": true + } + }, + { + "class": "Branch", + "id": "branch_3803_3896_1", + "ports": { + "bus1": 3803, + "bus2": 3896 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": -0.009349999949336052, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "capacitor": true + } + }, + { + "class": "Branch", + "id": "branch_3803_3901_1", + "ports": { + "bus1": 3803, + "bus2": 3901 + }, + "params": { + "R": 0.0015300000086426735, + "X": 0.014700000174343586, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3804_3806_1", + "ports": { + "bus1": 3804, + "bus2": 3806 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3805_3806_1", + "ports": { + "bus1": 3805, + "bus2": 3806 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3805_3835_1", + "ports": { + "bus1": 3805, + "bus2": 3835 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3806_3836_1", + "ports": { + "bus1": 3806, + "bus2": 3836 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3892_3893_1", + "ports": { + "bus1": 3892, + "bus2": 3893 + }, + "params": { + "R": 0.001230000052601099, + "X": 0.026590000838041306, + "B": 1.9870200157165527, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3894_3895_1", + "ports": { + "bus1": 3894, + "bus2": 3895 + }, + "params": { + "R": 0.001230000052601099, + "X": 0.02662000060081482, + "B": 1.988800048828125, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3896_3897_1", + "ports": { + "bus1": 3896, + "bus2": 3897 + }, + "params": { + "R": 0.001120000029914081, + "X": 0.02517000027000904, + "B": 1.835860013961792, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3901_3902_1", + "ports": { + "bus1": 3901, + "bus2": 3902 + }, + "params": { + "R": 0.0005300000193528831, + "X": 0.012969999574124813, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3901_3903_1", + "ports": { + "bus1": 3901, + "bus2": 3903 + }, + "params": { + "R": 0.0009299999801442027, + "X": 0.03643999993801117, + "B": 1.3895000219345093, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3901_3917_1", + "ports": { + "bus1": 3901, + "bus2": 3917 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.017400000244379044, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3901_8002_1", + "ports": { + "bus1": 3901, + "bus2": 8002 + }, + "params": { + "R": 0.0006799999973736703, + "X": 0.015850000083446503, + "B": 1.1512600183486938, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3902_3918_1", + "ports": { + "bus1": 3902, + "bus2": 3918 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.017400000244379044, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3902_3932_1", + "ports": { + "bus1": 3902, + "bus2": 3932 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3903_3904_1", + "ports": { + "bus1": 3903, + "bus2": 3904 + }, + "params": { + "R": 9.999999747378752e-06, + "X": 0.003590000094845891, + "B": 0.9781200289726257, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3903_3905_9", + "ports": { + "bus1": 3903, + "bus2": 3905 + }, + "params": { + "R": 0.0009800000116229057, + "X": 0.010350000113248825, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3903_3923_1", + "ports": { + "bus1": 3903, + "bus2": 3923 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.017400000244379044, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3903_8002_1", + "ports": { + "bus1": 3903, + "bus2": 8002 + }, + "params": { + "R": 0.0016499999910593033, + "X": 0.057190001010894775, + "B": 2.477400064468384, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3904_3905_9", + "ports": { + "bus1": 3904, + "bus2": 3905 + }, + "params": { + "R": 0.0015999999595806003, + "X": 0.01228999998420477, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3904_3924_1", + "ports": { + "bus1": 3904, + "bus2": 3924 + }, + "params": { + "R": 0.00019999999494757503, + "X": 0.012500000186264515, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3905_3906_9", + "ports": { + "bus1": 3905, + "bus2": 3906 + }, + "params": { + "R": 0.0007200000109151006, + "X": 0.0034600000362843275, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3905_3922_1", + "ports": { + "bus1": 3905, + "bus2": 3922 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.017400000244379044, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3906_3921_1", + "ports": { + "bus1": 3906, + "bus2": 3921 + }, + "params": { + "R": 9.999999747378752e-05, + "X": 0.017400000244379044, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3906_4001_1", + "ports": { + "bus1": 3906, + "bus2": 4001 + }, + "params": { + "R": 0.0005300000193528831, + "X": 0.004559999797493219, + "B": 0.7634999752044678, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3906_4001_2", + "ports": { + "bus1": 3906, + "bus2": 4001 + }, + "params": { + "R": 0.0005300000193528831, + "X": 0.004559999797493219, + "B": 0.7634999752044678, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3907_3908_1", + "ports": { + "bus1": 3907, + "bus2": 3908 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3907_3923_1", + "ports": { + "bus1": 3907, + "bus2": 3923 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3907_8004_1", + "ports": { + "bus1": 3907, + "bus2": 8004 + }, + "params": { + "R": 0.013819999992847443, + "X": 0.09267999976873398, + "B": 0.11060000211000443, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3908_3920_1", + "ports": { + "bus1": 3908, + "bus2": 3920 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3909_3919_1", + "ports": { + "bus1": 3909, + "bus2": 3919 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3909_3920_1", + "ports": { + "bus1": 3909, + "bus2": 3920 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3910_3911_1", + "ports": { + "bus1": 3910, + "bus2": 3911 + }, + "params": { + "R": 0.024819999933242798, + "X": 0.16937999427318573, + "B": 0.20231999456882477, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3910_3924_1", + "ports": { + "bus1": 3910, + "bus2": 3924 + }, + "params": { + "R": 0.014800000004470348, + "X": 0.10101000219583511, + "B": 0.12065999954938889, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3911_3912_1", + "ports": { + "bus1": 3911, + "bus2": 3912 + }, + "params": { + "R": 0.013819999992847443, + "X": 0.09267999976873398, + "B": 0.11060000211000443, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3911_3916_1", + "ports": { + "bus1": 3911, + "bus2": 3916 + }, + "params": { + "R": 0.016680000349879265, + "X": 0.11381000280380249, + "B": 0.13607999682426453, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3911_3921_1", + "ports": { + "bus1": 3911, + "bus2": 3921 + }, + "params": { + "R": 0.011130000464618206, + "X": 0.06678000092506409, + "B": 0.0728600025177002, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3911_3921_2", + "ports": { + "bus1": 3911, + "bus2": 3921 + }, + "params": { + "R": 0.010499999858438969, + "X": 0.06539999693632126, + "B": 0.06859999895095825, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3911_3921_3", + "ports": { + "bus1": 3911, + "bus2": 3921 + }, + "params": { + "R": 0.011049999855458736, + "X": 0.06641999632120132, + "B": 0.07159999758005142, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3911_3924_1", + "ports": { + "bus1": 3911, + "bus2": 3924 + }, + "params": { + "R": 0.03903000056743622, + "X": 0.27402999997138977, + "B": 0.3107199966907501, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3911_3925_1", + "ports": { + "bus1": 3911, + "bus2": 3925 + }, + "params": { + "R": 0.0008900000248104334, + "X": 0.029899999499320984, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3911_8003_1", + "ports": { + "bus1": 3911, + "bus2": 8003 + }, + "params": { + "R": 0.013819999992847443, + "X": 0.09267999976873398, + "B": 0.11060000211000443, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3911_8003_2", + "ports": { + "bus1": 3911, + "bus2": 8003 + }, + "params": { + "R": 0.013819999992847443, + "X": 0.09267999976873398, + "B": 0.11060000211000443, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3912_3924_1", + "ports": { + "bus1": 3912, + "bus2": 3924 + }, + "params": { + "R": 0.030579999089241028, + "X": 0.2046000063419342, + "B": 0.244719997048378, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3913_3920_1", + "ports": { + "bus1": 3913, + "bus2": 3920 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3913_3920_2", + "ports": { + "bus1": 3913, + "bus2": 3920 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3913_3923_1", + "ports": { + "bus1": 3913, + "bus2": 3923 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3913_8004_1", + "ports": { + "bus1": 3913, + "bus2": 8004 + }, + "params": { + "R": 0.013819999992847443, + "X": 0.09267999976873398, + "B": 0.11060000211000443, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3915_3924_1", + "ports": { + "bus1": 3915, + "bus2": 3924 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3916_3924_1", + "ports": { + "bus1": 3916, + "bus2": 3924 + }, + "params": { + "R": 0.022350000217556953, + "X": 0.16106000542640686, + "B": 0.18342000246047974, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3919_3922_1", + "ports": { + "bus1": 3919, + "bus2": 3922 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3920_3922_1", + "ports": { + "bus1": 3920, + "bus2": 3922 + }, + "params": { + "R": 0.003120000008493662, + "X": 0.028860000893473625, + "B": 0.15252000093460083, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3920_3926_1", + "ports": { + "bus1": 3920, + "bus2": 3926 + }, + "params": { + "R": 0.0008900000248104334, + "X": 0.029899999499320984, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3920_3926_2", + "ports": { + "bus1": 3920, + "bus2": 3926 + }, + "params": { + "R": 0.0008900000248104334, + "X": 0.029899999499320984, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3921_3931_1", + "ports": { + "bus1": 3921, + "bus2": 3931 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3923_3933_1", + "ports": { + "bus1": 3923, + "bus2": 3933 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_3923_8005_1", + "ports": { + "bus1": 3923, + "bus2": 8005 + }, + "params": { + "R": 0.013819999992847443, + "X": 0.09267999976873398, + "B": 0.11060000211000443, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_3923_8005_2", + "ports": { + "bus1": 3923, + "bus2": 8005 + }, + "params": { + "R": 0.013819999992847443, + "X": 0.09267999976873398, + "B": 0.11060000211000443, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4001_4008_1", + "ports": { + "bus1": 4001, + "bus2": 4008 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.007199999876320362, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_4001_4031_1", + "ports": { + "bus1": 4001, + "bus2": 4031 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_4001_4090_1", + "ports": { + "bus1": 4001, + "bus2": 4090 + }, + "params": { + "R": 0.0007200000109151006, + "X": 0.013819999992847443, + "B": 1.2757200002670288, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4001_4094_1", + "ports": { + "bus1": 4001, + "bus2": 4094 + }, + "params": { + "R": 0.0007800000021234155, + "X": 0.01501999981701374, + "B": 1.138100028038025, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4001_4097_1", + "ports": { + "bus1": 4001, + "bus2": 4097 + }, + "params": { + "R": 0.0007399999885819852, + "X": 0.01413000002503395, + "B": 1.0663399696350098, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4001_4204_1", + "ports": { + "bus1": 4001, + "bus2": 4204 + }, + "params": { + "R": 0.0007800000021234155, + "X": 0.0023900000378489494, + "B": 1.138100028038025, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4001_8001_1", + "ports": { + "bus1": 4001, + "bus2": 8001 + }, + "params": { + "R": 0.0010600000387057662, + "X": 0.012930000200867653, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4002_4003_1", + "ports": { + "bus1": 4002, + "bus2": 4003 + }, + "params": { + "R": 0.0012199999764561653, + "X": 0.023730000481009483, + "B": 2.2070999145507812, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4002_4090_1", + "ports": { + "bus1": 4002, + "bus2": 4090 + }, + "params": { + "R": 0.00011999999696854502, + "X": 0.0023799999617040157, + "B": 0.21926000714302063, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4002_4091_1", + "ports": { + "bus1": 4002, + "bus2": 4091 + }, + "params": { + "R": 0.0006000000284984708, + "X": 0.010359999723732471, + "B": 1.0145599842071533, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4003_6101_1", + "ports": { + "bus1": 4003, + "bus2": 6101 + }, + "params": { + "R": 0.0026400000788271427, + "X": 0.026890000328421593, + "B": 5.2906599044799805, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4004_4005_1", + "ports": { + "bus1": 4004, + "bus2": 4005 + }, + "params": { + "R": 0.0006300000241026282, + "X": 0.014120000414550304, + "B": 1.0975600481033325, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4004_4005_2", + "ports": { + "bus1": 4004, + "bus2": 4005 + }, + "params": { + "R": 0.0010900000343099236, + "X": 0.024080000817775726, + "B": 1.5554200410842896, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4004_4005_3", + "ports": { + "bus1": 4004, + "bus2": 4005 + }, + "params": { + "R": 0.00107999995816499, + "X": 0.024089999496936798, + "B": 1.5534800291061401, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4004_4091_1", + "ports": { + "bus1": 4004, + "bus2": 4091 + }, + "params": { + "R": 0.00041000000783242285, + "X": 0.007369999773800373, + "B": 0.7269399762153625, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4004_4092_1", + "ports": { + "bus1": 4004, + "bus2": 4092 + }, + "params": { + "R": 0.0006600000197067857, + "X": 0.012659999541938305, + "B": 0.9597600102424622, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4004_4095_1", + "ports": { + "bus1": 4004, + "bus2": 4095 + }, + "params": { + "R": 0.0006600000197067857, + "X": 0.012659999541938305, + "B": 0.9597600102424622, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4005_4006_1", + "ports": { + "bus1": 4005, + "bus2": 4006 + }, + "params": { + "R": 0.0002300000051036477, + "X": 0.004509999882429838, + "B": 0.33320000767707825, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4005_4006_2", + "ports": { + "bus1": 4005, + "bus2": 4006 + }, + "params": { + "R": 0.00019999999494757503, + "X": 0.004459999967366457, + "B": 0.3050000071525574, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4005_4035_1", + "ports": { + "bus1": 4005, + "bus2": 4035 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_4005_4102_1", + "ports": { + "bus1": 4005, + "bus2": 4102 + }, + "params": { + "R": 0.0012000000569969416, + "X": 0.023159999400377274, + "B": 1.7151999473571777, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4005_4102_2", + "ports": { + "bus1": 4005, + "bus2": 4102 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.019999999552965164, + "B": 3.5999999046325684, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4005_4202_1", + "ports": { + "bus1": 4005, + "bus2": 4202 + }, + "params": { + "R": 0.00019999999494757503, + "X": 0.008200000040233135, + "B": 1.2999999523162842, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4005_6202_1", + "ports": { + "bus1": 4005, + "bus2": 6202 + }, + "params": { + "R": 0.0019600000232458115, + "X": 0.03303999826312065, + "B": 1.8799999952316284, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4006_4007_1", + "ports": { + "bus1": 4006, + "bus2": 4007 + }, + "params": { + "R": 9.999999747378752e-06, + "X": 0.0003000000142492354, + "B": 0.014340000227093697, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4006_4007_2", + "ports": { + "bus1": 4006, + "bus2": 4007 + }, + "params": { + "R": 9.999999747378752e-06, + "X": 0.0003000000142492354, + "B": 0.01844000071287155, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4006_4009_1", + "ports": { + "bus1": 4006, + "bus2": 4009 + }, + "params": { + "R": 0.00019999999494757503, + "X": 0.01181000005453825, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_4006_4009_2", + "ports": { + "bus1": 4006, + "bus2": 4009 + }, + "params": { + "R": 9.000000136438757e-05, + "X": 0.007350000087171793, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_4006_4202_1", + "ports": { + "bus1": 4006, + "bus2": 4202 + }, + "params": { + "R": 0.00019999999494757503, + "X": 0.008200000040233135, + "B": 1.2999999523162842, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4007_4010_1", + "ports": { + "bus1": 4007, + "bus2": 4010 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0022100000642240047, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_4008_6401_1", + "ports": { + "bus1": 4008, + "bus2": 6401 + }, + "params": { + "R": 0.006200000178068876, + "X": 0.06729999929666519, + "B": 1.1155999898910522, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4009_4010_1", + "ports": { + "bus1": 4009, + "bus2": 4010 + }, + "params": { + "R": 5.999999848427251e-05, + "X": 0.0013099999632686377, + "B": 0.0037799999117851257, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4009_4010_2", + "ports": { + "bus1": 4009, + "bus2": 4010 + }, + "params": { + "R": 5.999999848427251e-05, + "X": 0.0011599999852478504, + "B": 0.0033199999015778303, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4009_4039_1", + "ports": { + "bus1": 4009, + "bus2": 4039 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_4009_4104_1", + "ports": { + "bus1": 4009, + "bus2": 4104 + }, + "params": { + "R": 0.0020000000949949026, + "X": 0.019999999552965164, + "B": 0.800000011920929, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4092_4093_1", + "ports": { + "bus1": 4092, + "bus2": 4093 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0016499999910593033, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4093_4094_1", + "ports": { + "bus1": 4093, + "bus2": 4094 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": -0.012629999779164791, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "capacitor": true + } + }, + { + "class": "Branch", + "id": "branch_4095_4096_1", + "ports": { + "bus1": 4095, + "bus2": 4096 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0016499999910593033, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4096_4097_1", + "ports": { + "bus1": 4096, + "bus2": 4097 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": -0.012629999779164791, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "capacitor": true + } + }, + { + "class": "Branch", + "id": "branch_4101_4102_1", + "ports": { + "bus1": 4101, + "bus2": 4102 + }, + "params": { + "R": 0.001129999989643693, + "X": 0.02068999968469143, + "B": 1.8552600145339966, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4101_4102_2", + "ports": { + "bus1": 4101, + "bus2": 4102 + }, + "params": { + "R": 0.001129999989643693, + "X": 0.02068999968469143, + "B": 1.8552600145339966, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4101_4103_1", + "ports": { + "bus1": 4101, + "bus2": 4103 + }, + "params": { + "R": 0.000699999975040555, + "X": 0.07400000095367432, + "B": 4.869999885559082, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4101_4103_2", + "ports": { + "bus1": 4101, + "bus2": 4103 + }, + "params": { + "R": 0.0020000000949949026, + "X": 0.019999999552965164, + "B": 0.800000011920929, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4101_4131_1", + "ports": { + "bus1": 4101, + "bus2": 4131 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_4101_4201_1", + "ports": { + "bus1": 4101, + "bus2": 4201 + }, + "params": { + "R": 0.00019999999494757503, + "X": 0.008200000040233135, + "B": 1.2999999523162842, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4101_4201_2", + "ports": { + "bus1": 4101, + "bus2": 4201 + }, + "params": { + "R": 0.00019999999494757503, + "X": 0.008200000040233135, + "B": 1.2999999523162842, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4102_4132_1", + "ports": { + "bus1": 4102, + "bus2": 4132 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_4102_4201_1", + "ports": { + "bus1": 4102, + "bus2": 4201 + }, + "params": { + "R": 0.00019999999494757503, + "X": 0.008200000040233135, + "B": 1.2999999523162842, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4102_4201_2", + "ports": { + "bus1": 4102, + "bus2": 4201 + }, + "params": { + "R": 0.00019999999494757503, + "X": 0.008200000040233135, + "B": 1.2999999523162842, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4102_4202_1", + "ports": { + "bus1": 4102, + "bus2": 4202 + }, + "params": { + "R": 0.00019999999494757503, + "X": 0.008200000040233135, + "B": 1.2999999523162842, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4102_4202_2", + "ports": { + "bus1": 4102, + "bus2": 4202 + }, + "params": { + "R": 0.00019999999494757503, + "X": 0.008200000040233135, + "B": 1.2999999523162842, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4102_6202_1", + "ports": { + "bus1": 4102, + "bus2": 6202 + }, + "params": { + "R": 0.0014199999859556556, + "X": 0.022579999640583992, + "B": 1.8799999952316284, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4103_4104_1", + "ports": { + "bus1": 4103, + "bus2": 4104 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.009999999776482582, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_4103_6202_1", + "ports": { + "bus1": 4103, + "bus2": 6202 + }, + "params": { + "R": 0.000699999975040555, + "X": 0.07400000095367432, + "B": 4.869999885559082, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4104_5004_1", + "ports": { + "bus1": 4104, + "bus2": 5004 + }, + "params": { + "R": 0.0020000000949949026, + "X": 0.07999999821186066, + "B": 0.800000011920929, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4201_4202_1", + "ports": { + "bus1": 4201, + "bus2": 4202 + }, + "params": { + "R": 0.0010900000343099236, + "X": 0.024080000817775726, + "B": 1.5554200410842896, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4201_4231_1", + "ports": { + "bus1": 4201, + "bus2": 4231 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_4201_5001_1", + "ports": { + "bus1": 4201, + "bus2": 5001 + }, + "params": { + "R": 0.0008299999753944576, + "X": 0.019999999552965164, + "B": 3.299999952316284, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4202_4203_1", + "ports": { + "bus1": 4202, + "bus2": 4203 + }, + "params": { + "R": 0.0006600000197067857, + "X": 0.0016499999910593033, + "B": 0.9597600102424622, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_4202_4232_1", + "ports": { + "bus1": 4202, + "bus2": 4232 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_4203_4204_1", + "ports": { + "bus1": 4203, + "bus2": 4204 + }, + "params": { + "R": 0.0007399999885819852, + "X": 0.012659999541938305, + "B": 1.082200050354004, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_5001_5002_1", + "ports": { + "bus1": 5001, + "bus2": 5002 + }, + "params": { + "R": 0.0035000001080334187, + "X": 0.007000000216066837, + "B": 4.605999946594238, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_5001_5031_1", + "ports": { + "bus1": 5001, + "bus2": 5031 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_5002_5003_1", + "ports": { + "bus1": 5002, + "bus2": 5003 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.009999999776482582, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_5002_5032_1", + "ports": { + "bus1": 5002, + "bus2": 5032 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_5003_5004_1", + "ports": { + "bus1": 5003, + "bus2": 5004 + }, + "params": { + "R": 0.0020000000949949026, + "X": 0.07999999821186066, + "B": 0.800000011920929, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6101_6102_1", + "ports": { + "bus1": 6101, + "bus2": 6102 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.007199999876320362, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6102_6103_1", + "ports": { + "bus1": 6102, + "bus2": 6103 + }, + "params": { + "R": 0.0012000000569969416, + "X": 0.0023159999400377274, + "B": 1.7151999473571777, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6102_6132_1", + "ports": { + "bus1": 6102, + "bus2": 6132 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6102_6301_1", + "ports": { + "bus1": 6102, + "bus2": 6301 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.004600000102072954, + "B": 0.30000001192092896, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6102_6403_1", + "ports": { + "bus1": 6102, + "bus2": 6403 + }, + "params": { + "R": 0.006200000178068876, + "X": 0.06729999929666519, + "B": 1.1155999898910522, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6103_6104_1", + "ports": { + "bus1": 6103, + "bus2": 6104 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.01810000091791153, + "tap": 1.0034500360488892, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6103_6301_1", + "ports": { + "bus1": 6103, + "bus2": 6301 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.004600000102072954, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6103_6301_2", + "ports": { + "bus1": 6103, + "bus2": 6301 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.004600000102072954, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6103_6501_1", + "ports": { + "bus1": 6103, + "bus2": 6501 + }, + "params": { + "R": 0.006200000178068876, + "X": 0.06729999929666519, + "B": 1.1155999898910522, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6103_6501_2", + "ports": { + "bus1": 6103, + "bus2": 6501 + }, + "params": { + "R": 0.006200000178068876, + "X": 0.06729999929666519, + "B": 1.1155999898910522, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6104_6204_1", + "ports": { + "bus1": 6104, + "bus2": 6204 + }, + "params": { + "R": 0.01080000028014183, + "X": 0.09650000184774399, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6104_6305_1", + "ports": { + "bus1": 6104, + "bus2": 6305 + }, + "params": { + "R": 0.01080000028014183, + "X": 0.09650000184774399, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6201_6202_1", + "ports": { + "bus1": 6201, + "bus2": 6202 + }, + "params": { + "R": 0.0017900000093504786, + "X": 0.014050000347197056, + "B": 3.680000066757202, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6201_6203_1", + "ports": { + "bus1": 6201, + "bus2": 6203 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.01810000091791153, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6201_6231_1", + "ports": { + "bus1": 6201, + "bus2": 6231 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6202_6204_1", + "ports": { + "bus1": 6202, + "bus2": 6204 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.01810000091791153, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6203_6205_1", + "ports": { + "bus1": 6203, + "bus2": 6205 + }, + "params": { + "R": 0.000699999975040555, + "X": 0.07400000095367432, + "B": 0.4876999855041504, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6203_6303_1", + "ports": { + "bus1": 6203, + "bus2": 6303 + }, + "params": { + "R": 0.01080000028014183, + "X": 0.09650000184774399, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6203_6303_2", + "ports": { + "bus1": 6203, + "bus2": 6303 + }, + "params": { + "R": 0.01080000028014183, + "X": 0.09650000184774399, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6203_6304_1", + "ports": { + "bus1": 6203, + "bus2": 6304 + }, + "params": { + "R": 0.01080000028014183, + "X": 0.09650000184774399, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6204_6205_1", + "ports": { + "bus1": 6204, + "bus2": 6205 + }, + "params": { + "R": 0.000699999975040555, + "X": 0.02500000037252903, + "B": 0.4869999885559082, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6205_6235_1", + "ports": { + "bus1": 6205, + "bus2": 6235 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6301_6303_1", + "ports": { + "bus1": 6301, + "bus2": 6303 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.01810000091791153, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6302_6304_1", + "ports": { + "bus1": 6302, + "bus2": 6304 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.01810000091791153, + "tap": 1.0028599500656128, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6302_7001_1", + "ports": { + "bus1": 6302, + "bus2": 7001 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.004600000102072954, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6303_6304_1", + "ports": { + "bus1": 6303, + "bus2": 6304 + }, + "params": { + "R": 0.01080000028014183, + "X": 0.09650000184774399, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6303_6305_1", + "ports": { + "bus1": 6303, + "bus2": 6305 + }, + "params": { + "R": 0.01080000028014183, + "X": 0.09650000184774399, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6303_6305_2", + "ports": { + "bus1": 6303, + "bus2": 6305 + }, + "params": { + "R": 0.01080000028014183, + "X": 0.09650000184774399, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6303_6333_1", + "ports": { + "bus1": 6303, + "bus2": 6333 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6305_6335_1", + "ports": { + "bus1": 6305, + "bus2": 6335 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6305_6510_1", + "ports": { + "bus1": 6305, + "bus2": 6510 + }, + "params": { + "R": 0.00547999981790781, + "X": 0.048250000923871994, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6305_6510_2", + "ports": { + "bus1": 6305, + "bus2": 6510 + }, + "params": { + "R": 0.005400000140070915, + "X": 0.048250000923871994, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6401_6402_1", + "ports": { + "bus1": 6401, + "bus2": 6402 + }, + "params": { + "R": 0.0008900000248104334, + "X": 0.029899999499320984, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6401_6402_2", + "ports": { + "bus1": 6401, + "bus2": 6402 + }, + "params": { + "R": 0.0008900000248104334, + "X": 0.029899999499320984, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6401_6403_1", + "ports": { + "bus1": 6401, + "bus2": 6403 + }, + "params": { + "R": 0.006200000178068876, + "X": 0.06729999929666519, + "B": 1.1155999898910522, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6401_6403_2", + "ports": { + "bus1": 6401, + "bus2": 6403 + }, + "params": { + "R": 0.006200000178068876, + "X": 0.06729999929666519, + "B": 1.1155999898910522, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6401_6404_1", + "ports": { + "bus1": 6401, + "bus2": 6404 + }, + "params": { + "R": 0.01080000028014183, + "X": 0.09650000184774399, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6403_6404_1", + "ports": { + "bus1": 6403, + "bus2": 6404 + }, + "params": { + "R": 0.006200000178068876, + "X": 0.06729999929666519, + "B": 1.1155999898910522, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6403_6433_1", + "ports": { + "bus1": 6403, + "bus2": 6433 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6404_6507_1", + "ports": { + "bus1": 6404, + "bus2": 6507 + }, + "params": { + "R": 0.01080000028014183, + "X": 0.09650000184774399, + "B": 0.3296000063419342, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6501_6502_1", + "ports": { + "bus1": 6501, + "bus2": 6502 + }, + "params": { + "R": 0.002400000113993883, + "X": 0.0033199999015778303, + "B": 0.5849000215530396, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6501_6504_1", + "ports": { + "bus1": 6501, + "bus2": 6504 + }, + "params": { + "R": 0.002099999925121665, + "X": 0.0023799999617040157, + "B": 0.38449999690055847, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6501_6509_1", + "ports": { + "bus1": 6501, + "bus2": 6509 + }, + "params": { + "R": 0.0015999999595806003, + "X": 0.022600000724196434, + "B": 0.38100001215934753, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6501_6509_2", + "ports": { + "bus1": 6501, + "bus2": 6509 + }, + "params": { + "R": 0.0015999999595806003, + "X": 0.022600000724196434, + "B": 0.38100001215934753, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6501_6510_1", + "ports": { + "bus1": 6501, + "bus2": 6510 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.01810000091791153, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6501_6510_2", + "ports": { + "bus1": 6501, + "bus2": 6510 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.01810000091791153, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6502_6503_1", + "ports": { + "bus1": 6502, + "bus2": 6503 + }, + "params": { + "R": 0.005200000014156103, + "X": 0.06019999831914902, + "B": 1.0099999904632568, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6502_6503_2", + "ports": { + "bus1": 6502, + "bus2": 6503 + }, + "params": { + "R": 0.004900000058114529, + "X": 0.053700000047683716, + "B": 0.8842999935150146, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6502_6504_2", + "ports": { + "bus1": 6502, + "bus2": 6504 + }, + "params": { + "R": 0.002099999925121665, + "X": 0.0023799999617040157, + "B": 0.38449999690055847, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6502_6504_3", + "ports": { + "bus1": 6502, + "bus2": 6504 + }, + "params": { + "R": 0.0017000000225380063, + "X": 0.0022499999031424522, + "B": 0.3991999924182892, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6502_6508_1", + "ports": { + "bus1": 6502, + "bus2": 6508 + }, + "params": { + "R": 0.0012000000569969416, + "X": 0.01720000058412552, + "B": 0.2987000048160553, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6502_6509_1", + "ports": { + "bus1": 6502, + "bus2": 6509 + }, + "params": { + "R": 0.0007999999797903001, + "X": 0.0010600000387057662, + "B": 0.20389999449253082, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6502_6509_2", + "ports": { + "bus1": 6502, + "bus2": 6509 + }, + "params": { + "R": 0.0007999999797903001, + "X": 0.0010600000387057662, + "B": 0.20389999449253082, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6503_6504_1", + "ports": { + "bus1": 6503, + "bus2": 6504 + }, + "params": { + "R": 0.0031999999191612005, + "X": 0.0348999984562397, + "B": 0.5722000002861023, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6503_6505_1", + "ports": { + "bus1": 6503, + "bus2": 6505 + }, + "params": { + "R": 0.009600000455975533, + "X": 0.08780000358819962, + "B": 1.4264999628067017, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6503_6507_1", + "ports": { + "bus1": 6503, + "bus2": 6507 + }, + "params": { + "R": 0.0034000000450760126, + "X": 0.03739999979734421, + "B": 0.6208000183105469, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6503_6507_2", + "ports": { + "bus1": 6503, + "bus2": 6507 + }, + "params": { + "R": 0.0034000000450760126, + "X": 0.03720000013709068, + "B": 0.6182000041007996, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6503_6508_1", + "ports": { + "bus1": 6503, + "bus2": 6508 + }, + "params": { + "R": 0.0034000000450760126, + "X": 0.03920000046491623, + "B": 0.652400016784668, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6503_6533_1", + "ports": { + "bus1": 6503, + "bus2": 6533 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_6504_6507_1", + "ports": { + "bus1": 6504, + "bus2": 6507 + }, + "params": { + "R": 0.003800000064074993, + "X": 0.03400000184774399, + "B": 0.5824000239372253, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6504_6507_2", + "ports": { + "bus1": 6504, + "bus2": 6507 + }, + "params": { + "R": 0.0031999999191612005, + "X": 0.0348999984562397, + "B": 0.5722000002861023, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6504_7002_1", + "ports": { + "bus1": 6504, + "bus2": 7002 + }, + "params": { + "R": 0.00810999982059002, + "X": 0.13689999282360077, + "B": 2.434799909591675, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_6505_6506_1", + "ports": { + "bus1": 6505, + "bus2": 6506 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.019500000402331352, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_7001_7002_1", + "ports": { + "bus1": 7001, + "bus2": 7002 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.004600000102072954, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_7001_7031_1", + "ports": { + "bus1": 7001, + "bus2": 7031 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_7002_7032_1", + "ports": { + "bus1": 7002, + "bus2": 7032 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_8001_8002_9", + "ports": { + "bus1": 8001, + "bus2": 8002 + }, + "params": { + "R": 0.0015899999998509884, + "X": 0.011099999770522118, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_8001_8003_1", + "ports": { + "bus1": 8001, + "bus2": 8003 + }, + "params": { + "R": 9.999999747378752e-05, + "X": 0.017400000244379044, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_8002_8005_1", + "ports": { + "bus1": 8002, + "bus2": 8005 + }, + "params": { + "R": 0.0003000000142492354, + "X": 0.017400000244379044, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_8003_8004_1", + "ports": { + "bus1": 8003, + "bus2": 8004 + }, + "params": { + "R": 0.019519999623298645, + "X": 0.13702000677585602, + "B": 0.15535999834537506, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_8003_8005_1", + "ports": { + "bus1": 8003, + "bus2": 8005 + }, + "params": { + "R": 0.03903000056743622, + "X": 0.27402999997138977, + "B": 0.3107199966907501, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_8003_8005_2", + "ports": { + "bus1": 8003, + "bus2": 8005 + }, + "params": { + "R": 0.03903000056743622, + "X": 0.27402999997138977, + "B": 0.3107199966907501, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_8003_8033_1", + "ports": { + "bus1": 8003, + "bus2": 8033 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "Branch", + "id": "branch_8004_8005_1", + "ports": { + "bus1": 8004, + "bus2": 8005 + }, + "params": { + "R": 0.019519999623298645, + "X": 0.13702000677585602, + "B": 0.15535999834537506, + "tap": 1.0, + "phase": 0.0 + } + }, + { + "class": "Branch", + "id": "branch_8004_8034_1", + "ports": { + "bus1": 8004, + "bus2": 8034 + }, + "params": { + "R": 1.0000000116860974e-07, + "X": 0.0005000000237487257, + "tap": 1.0, + "phase": 0.0 + }, + "extension": { + "xfmr": true + } + }, + { + "class": "LoadZIP", + "id": "load_1002", + "ports": { + "bus": 1002 + }, + "params": { + "Pnom": 2.2684197425842285, + "Qnom": -5.999997615814209, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_1003", + "ports": { + "bus": 1003 + }, + "params": { + "Pnom": 21.533227920532227, + "Qnom": 3.668557643890381, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_1004", + "ports": { + "bus": 1004 + }, + "params": { + "Pnom": 10.379494667053223, + "Qnom": 0.05520923435688019, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_1101", + "ports": { + "bus": 1101 + }, + "params": { + "Pnom": 45.27366256713867, + "Qnom": -1.3704431056976318, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_1102", + "ports": { + "bus": 1102 + }, + "params": { + "Pnom": 1.7891063690185547, + "Qnom": 0.23651868104934692, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_1201", + "ports": { + "bus": 1201 + }, + "params": { + "Pnom": 1.680519700050354, + "Qnom": -0.020379148423671722, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_1202", + "ports": { + "bus": 1202 + }, + "params": { + "Pnom": 8.75610065460205, + "Qnom": 2.8713154792785645, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_1301", + "ports": { + "bus": 1301 + }, + "params": { + "Pnom": 27.04778480529785, + "Qnom": 3.5282559394836426, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_1302", + "ports": { + "bus": 1302 + }, + "params": { + "Pnom": 0.17505332827568054, + "Qnom": 0.022909315302968025, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_1303", + "ports": { + "bus": 1303 + }, + "params": { + "Pnom": 62.35136795043945, + "Qnom": 8.133489608764648, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_1401", + "ports": { + "bus": 1401 + }, + "params": { + "Pnom": 65.3553695678711, + "Qnom": 15.245942115783691, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_1402", + "ports": { + "bus": 1402 + }, + "params": { + "Pnom": 53.73303985595703, + "Qnom": -6.016554355621338, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2000", + "ports": { + "bus": 2000 + }, + "params": { + "Pnom": 22.071880340576172, + "Qnom": 2.879159927368164, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2100", + "ports": { + "bus": 2100 + }, + "params": { + "Pnom": 2.530357837677002, + "Qnom": 0.4934704899787903, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2202", + "ports": { + "bus": 2202 + }, + "params": { + "Pnom": 14.007658958435059, + "Qnom": 2.4498908519744873, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2203", + "ports": { + "bus": 2203 + }, + "params": { + "Pnom": 15.376973152160645, + "Qnom": 2.504457950592041, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2400", + "ports": { + "bus": 2400 + }, + "params": { + "Pnom": 7.635193824768066, + "Qnom": 0.6982765197753906, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2401", + "ports": { + "bus": 2401 + }, + "params": { + "Pnom": 7.944181442260742, + "Qnom": 0.9476205706596375, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2402", + "ports": { + "bus": 2402 + }, + "params": { + "Pnom": 9.741750717163086, + "Qnom": 0.7410865426063538, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2403", + "ports": { + "bus": 2403 + }, + "params": { + "Pnom": 9.499732971191406, + "Qnom": 0.350541353225708, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2405", + "ports": { + "bus": 2405 + }, + "params": { + "Pnom": 7.427496433258057, + "Qnom": 0.20640239119529724, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2406", + "ports": { + "bus": 2406 + }, + "params": { + "Pnom": 6.643393516540527, + "Qnom": -0.3674974739551544, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2407", + "ports": { + "bus": 2407 + }, + "params": { + "Pnom": 15.699891090393066, + "Qnom": -0.33325526118278503, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2408", + "ports": { + "bus": 2408 + }, + "params": { + "Pnom": 15.689494132995605, + "Qnom": -0.6536079049110413, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2409", + "ports": { + "bus": 2409 + }, + "params": { + "Pnom": 14.416006088256836, + "Qnom": -0.7802792191505432, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2410", + "ports": { + "bus": 2410 + }, + "params": { + "Pnom": 14.214787483215332, + "Qnom": 0.5254030227661133, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2411", + "ports": { + "bus": 2411 + }, + "params": { + "Pnom": 9.789714813232422, + "Qnom": 0.6837463974952698, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2502", + "ports": { + "bus": 2502 + }, + "params": { + "Pnom": 21.36306381225586, + "Qnom": -0.8303046822547913, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2503", + "ports": { + "bus": 2503 + }, + "params": { + "Pnom": 16.61333656311035, + "Qnom": 1.817926049232483, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2600", + "ports": { + "bus": 2600 + }, + "params": { + "Pnom": -16.808162689208984, + "Qnom": 0.0, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2602", + "ports": { + "bus": 2602 + }, + "params": { + "Pnom": 0.8950256109237671, + "Qnom": 0.11699766665697098, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2604", + "ports": { + "bus": 2604 + }, + "params": { + "Pnom": 18.45703125, + "Qnom": 0.0, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2608", + "ports": { + "bus": 2608 + }, + "params": { + "Pnom": 0.8935045003890991, + "Qnom": 0.11660086363554001, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2609", + "ports": { + "bus": 2609 + }, + "params": { + "Pnom": 1.2075583934783936, + "Qnom": 0.24177315831184387, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2610", + "ports": { + "bus": 2610 + }, + "params": { + "Pnom": 0.8934997320175171, + "Qnom": 0.11659720540046692, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2611", + "ports": { + "bus": 2611 + }, + "params": { + "Pnom": 0.8935045003890991, + "Qnom": 0.11660086363554001, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2612", + "ports": { + "bus": 2612 + }, + "params": { + "Pnom": 1.0811445713043213, + "Qnom": 0.22337107360363007, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2613", + "ports": { + "bus": 2613 + }, + "params": { + "Pnom": 2.8622119426727295, + "Qnom": 0.5819884538650513, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2614", + "ports": { + "bus": 2614 + }, + "params": { + "Pnom": 1.2341761589050293, + "Qnom": 0.25063762068748474, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2615", + "ports": { + "bus": 2615 + }, + "params": { + "Pnom": 7.225333213806152, + "Qnom": 1.1828069686889648, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2616", + "ports": { + "bus": 2616 + }, + "params": { + "Pnom": 1.0464341640472412, + "Qnom": 0.21486438810825348, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2617", + "ports": { + "bus": 2617 + }, + "params": { + "Pnom": 1.0822324752807617, + "Qnom": 0.22381579875946045, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2618", + "ports": { + "bus": 2618 + }, + "params": { + "Pnom": 7.9342827796936035, + "Qnom": -0.05543218180537224, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2619", + "ports": { + "bus": 2619 + }, + "params": { + "Pnom": -24.97441291809082, + "Qnom": 0.0, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2620", + "ports": { + "bus": 2620 + }, + "params": { + "Pnom": 1.834448218345642, + "Qnom": 0.15742522478103638, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_2621", + "ports": { + "bus": 2621 + }, + "params": { + "Pnom": 2.120918035507202, + "Qnom": -0.5655044913291931, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3101", + "ports": { + "bus": 3101 + }, + "params": { + "Pnom": 3.0772182941436768, + "Qnom": 0.4771499037742615, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3102", + "ports": { + "bus": 3102 + }, + "params": { + "Pnom": 1.436879277229309, + "Qnom": 0.22489137947559357, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3103", + "ports": { + "bus": 3103 + }, + "params": { + "Pnom": 3.7764956951141357, + "Qnom": 0.5379905104637146, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3104", + "ports": { + "bus": 3104 + }, + "params": { + "Pnom": 2.794879674911499, + "Qnom": 0.36252567172050476, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3105", + "ports": { + "bus": 3105 + }, + "params": { + "Pnom": 2.153719902038574, + "Qnom": 0.4418199956417084, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3201", + "ports": { + "bus": 3201 + }, + "params": { + "Pnom": 4.186827182769775, + "Qnom": 0.8910516500473022, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3202", + "ports": { + "bus": 3202 + }, + "params": { + "Pnom": 5.301629543304443, + "Qnom": 0.7586875557899475, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3203", + "ports": { + "bus": 3203 + }, + "params": { + "Pnom": 5.928674697875977, + "Qnom": 1.4333983659744263, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3204", + "ports": { + "bus": 3204 + }, + "params": { + "Pnom": 6.019084453582764, + "Qnom": 0.8578122854232788, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3205", + "ports": { + "bus": 3205 + }, + "params": { + "Pnom": 4.926012992858887, + "Qnom": 0.7033026814460754, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3302", + "ports": { + "bus": 3302 + }, + "params": { + "Pnom": 3.114095449447632, + "Qnom": 0.7751820087432861, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3303", + "ports": { + "bus": 3303 + }, + "params": { + "Pnom": 5.628699779510498, + "Qnom": 1.3564300537109375, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3304", + "ports": { + "bus": 3304 + }, + "params": { + "Pnom": 4.808534622192383, + "Qnom": 1.1068475246429443, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3305", + "ports": { + "bus": 3305 + }, + "params": { + "Pnom": 3.87717342376709, + "Qnom": 0.5522391200065613, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3401", + "ports": { + "bus": 3401 + }, + "params": { + "Pnom": 5.05819845199585, + "Qnom": 1.2421801090240479, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3403", + "ports": { + "bus": 3403 + }, + "params": { + "Pnom": 4.6437201499938965, + "Qnom": 0.6622499823570251, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3404", + "ports": { + "bus": 3404 + }, + "params": { + "Pnom": 3.957129955291748, + "Qnom": 0.5617892742156982, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3405", + "ports": { + "bus": 3405 + }, + "params": { + "Pnom": 4.0699143409729, + "Qnom": 0.5820162892341614, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3501", + "ports": { + "bus": 3501 + }, + "params": { + "Pnom": 5.6251397132873535, + "Qnom": 0.8011400103569031, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3601", + "ports": { + "bus": 3601 + }, + "params": { + "Pnom": 0.9436962008476257, + "Qnom": 0.13359957933425903, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3701", + "ports": { + "bus": 3701 + }, + "params": { + "Pnom": 3.19132924079895, + "Qnom": 0.16055803000926971, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3801", + "ports": { + "bus": 3801 + }, + "params": { + "Pnom": 1.721010446548462, + "Qnom": 0.42669153213500977, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3804", + "ports": { + "bus": 3804 + }, + "params": { + "Pnom": 2.0229456424713135, + "Qnom": 0.5029169917106628, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3805", + "ports": { + "bus": 3805 + }, + "params": { + "Pnom": 4.494497776031494, + "Qnom": 1.467953085899353, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3806", + "ports": { + "bus": 3806 + }, + "params": { + "Pnom": 2.6062657833099365, + "Qnom": 0.37229400873184204, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3902", + "ports": { + "bus": 3902 + }, + "params": { + "Pnom": 1.3769199848175049, + "Qnom": 0.3442299962043762, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3903", + "ports": { + "bus": 3903 + }, + "params": { + "Pnom": 1.9735521078109741, + "Qnom": 0.2880636155605316, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3907", + "ports": { + "bus": 3907 + }, + "params": { + "Pnom": 4.172797679901123, + "Qnom": 0.5732795596122742, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3908", + "ports": { + "bus": 3908 + }, + "params": { + "Pnom": 1.8222721815109253, + "Qnom": 0.227347731590271, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3909", + "ports": { + "bus": 3909 + }, + "params": { + "Pnom": 1.5739049911499023, + "Qnom": 0.37467920780181885, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3910", + "ports": { + "bus": 3910 + }, + "params": { + "Pnom": 2.2377359867095947, + "Qnom": 0.3276321589946747, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3911", + "ports": { + "bus": 3911 + }, + "params": { + "Pnom": 2.1316230297088623, + "Qnom": 0.43763992190361023, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3912", + "ports": { + "bus": 3912 + }, + "params": { + "Pnom": 1.6076843738555908, + "Qnom": -0.005983087699860334, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3913", + "ports": { + "bus": 3913 + }, + "params": { + "Pnom": 2.973787307739258, + "Qnom": 0.3929828107357025, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3914", + "ports": { + "bus": 3914 + }, + "params": { + "Pnom": 2.054535150527954, + "Qnom": 0.47512805461883545, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3915", + "ports": { + "bus": 3915 + }, + "params": { + "Pnom": 2.3016059398651123, + "Qnom": 0.48545169830322266, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3916", + "ports": { + "bus": 3916 + }, + "params": { + "Pnom": 1.4286702871322632, + "Qnom": 0.0, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3917", + "ports": { + "bus": 3917 + }, + "params": { + "Pnom": 2.1632535457611084, + "Qnom": 0.40320897102355957, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3918", + "ports": { + "bus": 3918 + }, + "params": { + "Pnom": 2.8776047229766846, + "Qnom": 0.6811009049415588, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3919", + "ports": { + "bus": 3919 + }, + "params": { + "Pnom": 1.7111918926239014, + "Qnom": 0.23026522994041443, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3920", + "ports": { + "bus": 3920 + }, + "params": { + "Pnom": 1.5727760791778564, + "Qnom": 0.21869002282619476, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3921", + "ports": { + "bus": 3921 + }, + "params": { + "Pnom": 1.358012080192566, + "Qnom": 0.3133935034275055, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3922", + "ports": { + "bus": 3922 + }, + "params": { + "Pnom": 2.3559069633483887, + "Qnom": 0.3064464032649994, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3923", + "ports": { + "bus": 3923 + }, + "params": { + "Pnom": 3.5967586040496826, + "Qnom": 0.604934573173523, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3924", + "ports": { + "bus": 3924 + }, + "params": { + "Pnom": 3.0299627780914307, + "Qnom": 0.4352167844772339, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_3926", + "ports": { + "bus": 3926 + }, + "params": { + "Pnom": 2.436922550201416, + "Qnom": 0.15387041866779327, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4001", + "ports": { + "bus": 4001 + }, + "params": { + "Pnom": 0.0, + "Qnom": -6.998400688171387, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4002", + "ports": { + "bus": 4002 + }, + "params": { + "Pnom": 1.7213351726531982, + "Qnom": 0.22906558215618134, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4004", + "ports": { + "bus": 4004 + }, + "params": { + "Pnom": 2.733253002166748, + "Qnom": 0.36051124334335327, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4005", + "ports": { + "bus": 4005 + }, + "params": { + "Pnom": 4.801139831542969, + "Qnom": 1.5741851329803467, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4008", + "ports": { + "bus": 4008 + }, + "params": { + "Pnom": 2.8635165691375732, + "Qnom": 0.3751359283924103, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4009", + "ports": { + "bus": 4009 + }, + "params": { + "Pnom": 22.087425231933594, + "Qnom": 4.313953876495361, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4010", + "ports": { + "bus": 4010 + }, + "params": { + "Pnom": 31.3309326171875, + "Qnom": 0.0, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4101", + "ports": { + "bus": 4101 + }, + "params": { + "Pnom": 9.95028018951416, + "Qnom": 1.297844409942627, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4102", + "ports": { + "bus": 4102 + }, + "params": { + "Pnom": 4.806485652923584, + "Qnom": 0.6866390109062195, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4103", + "ports": { + "bus": 4103 + }, + "params": { + "Pnom": 0.11678365617990494, + "Qnom": 0.015221552923321724, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4104", + "ports": { + "bus": 4104 + }, + "params": { + "Pnom": 25.505657196044922, + "Qnom": 3.35713529586792, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4201", + "ports": { + "bus": 4201 + }, + "params": { + "Pnom": 57.6265869140625, + "Qnom": 4.610133171081543, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4202", + "ports": { + "bus": 4202 + }, + "params": { + "Pnom": 45.582393646240234, + "Qnom": 5.946259498596191, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4203", + "ports": { + "bus": 4203 + }, + "params": { + "Pnom": 44.34751510620117, + "Qnom": 5.858034610748291, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_4204", + "ports": { + "bus": 4204 + }, + "params": { + "Pnom": 10.083734512329102, + "Qnom": 1.3074138164520264, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_5001", + "ports": { + "bus": 5001 + }, + "params": { + "Pnom": 75.74051666259766, + "Qnom": 17.2137508392334, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_5002", + "ports": { + "bus": 5002 + }, + "params": { + "Pnom": 90.03983306884766, + "Qnom": 11.743592262268066, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_5003", + "ports": { + "bus": 5003 + }, + "params": { + "Pnom": 6.208952903747559, + "Qnom": 0.8174059987068176, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6102", + "ports": { + "bus": 6102 + }, + "params": { + "Pnom": 10.531440734863281, + "Qnom": -3.452773094177246, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6103", + "ports": { + "bus": 6103 + }, + "params": { + "Pnom": 3.924494504928589, + "Qnom": 0.5125714540481567, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6104", + "ports": { + "bus": 6104 + }, + "params": { + "Pnom": 17.000837326049805, + "Qnom": -1.8542389869689941, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6201", + "ports": { + "bus": 6201 + }, + "params": { + "Pnom": 2.058201789855957, + "Qnom": 0.2685740888118744, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6202", + "ports": { + "bus": 6202 + }, + "params": { + "Pnom": 0.8902536034584045, + "Qnom": 0.13621120154857635, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6203", + "ports": { + "bus": 6203 + }, + "params": { + "Pnom": 6.127285003662109, + "Qnom": 1.452741026878357, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6204", + "ports": { + "bus": 6204 + }, + "params": { + "Pnom": 7.020753860473633, + "Qnom": 1.5770753622055054, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6205", + "ports": { + "bus": 6205 + }, + "params": { + "Pnom": 4.892831802368164, + "Qnom": 0.8634448051452637, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6301", + "ports": { + "bus": 6301 + }, + "params": { + "Pnom": 5.176612854003906, + "Qnom": 0.6769766807556152, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6302", + "ports": { + "bus": 6302 + }, + "params": { + "Pnom": 5.9250311851501465, + "Qnom": 0.7739758491516113, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6303", + "ports": { + "bus": 6303 + }, + "params": { + "Pnom": 7.4660162925720215, + "Qnom": 0.9740440845489502, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6304", + "ports": { + "bus": 6304 + }, + "params": { + "Pnom": 0.0, + "Qnom": -5.943535327911377, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6305", + "ports": { + "bus": 6305 + }, + "params": { + "Pnom": 0.6023237705230713, + "Qnom": 0.19751763343811035, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6401", + "ports": { + "bus": 6401 + }, + "params": { + "Pnom": 17.462181091308594, + "Qnom": -4.521339416503906, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6402", + "ports": { + "bus": 6402 + }, + "params": { + "Pnom": 2.8056514263153076, + "Qnom": 0.3769932687282562, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6403", + "ports": { + "bus": 6403 + }, + "params": { + "Pnom": 0.021978000178933144, + "Qnom": 0.002722941106185317, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6404", + "ports": { + "bus": 6404 + }, + "params": { + "Pnom": 0.29751238226890564, + "Qnom": 0.03978864103555679, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6501", + "ports": { + "bus": 6501 + }, + "params": { + "Pnom": 1.9733105897903442, + "Qnom": 0.6530481576919556, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6502", + "ports": { + "bus": 6502 + }, + "params": { + "Pnom": 15.704302787780762, + "Qnom": 2.8299992084503174, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6503", + "ports": { + "bus": 6503 + }, + "params": { + "Pnom": 4.411528587341309, + "Qnom": 1.4460349082946777, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6504", + "ports": { + "bus": 6504 + }, + "params": { + "Pnom": 3.0040745735168457, + "Qnom": 0.3963261544704437, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6505", + "ports": { + "bus": 6505 + }, + "params": { + "Pnom": 0.07023005932569504, + "Qnom": 0.023830218240618706, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6507", + "ports": { + "bus": 6507 + }, + "params": { + "Pnom": 5.549244403839111, + "Qnom": -0.6460703611373901, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6508", + "ports": { + "bus": 6508 + }, + "params": { + "Pnom": 1.3262748718261719, + "Qnom": 0.4373018741607666, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6509", + "ports": { + "bus": 6509 + }, + "params": { + "Pnom": 0.08673001080751419, + "Qnom": 0.02869579568505287, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_6510", + "ports": { + "bus": 6510 + }, + "params": { + "Pnom": 19.492170333862305, + "Qnom": -1.093284010887146, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_7001", + "ports": { + "bus": 7001 + }, + "params": { + "Pnom": 70.0091781616211, + "Qnom": 5.642703056335449, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_7002", + "ports": { + "bus": 7002 + }, + "params": { + "Pnom": 25.54833984375, + "Qnom": -1.3806869983673096, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_8003", + "ports": { + "bus": 8003 + }, + "params": { + "Pnom": 5.87404727935791, + "Qnom": 0.7662602663040161, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_8004", + "ports": { + "bus": 8004 + }, + "params": { + "Pnom": 34.09103012084961, + "Qnom": 4.446990013122559, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "LoadZIP", + "id": "load_8005", + "ports": { + "bus": 8005 + }, + "params": { + "Pnom": 12.168739318847656, + "Qnom": 1.6246064901351929, + "alphaI": 0.0, + "alphaP": 0.0 + } + }, + { + "class": "Genrou", + "id": "1032_C_genrou", + "ports": { + "bus": 1032, + "pmech": 0, + "efd": 1, + "speed": 2 + }, + "params": { + "p0": 7.119999885559082, + "q0": -0.03334444761276245, + "H": 2.4100000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 873.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "1032_C_tgov1", + "ports": { + "speed": 2, + "pmech": 0 + }, + "params": { + "Trate": 873.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "1032_C_sexs_pti", + "ports": { + "bus": 1032, + "efd": 1 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "1032_G_genrou", + "ports": { + "bus": 1032, + "pmech": 3, + "efd": 4, + "speed": 5 + }, + "params": { + "p0": 8.5600004196167, + "q0": -0.03334444761276245, + "H": 2.4100000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1050.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "1032_G_gast_pti", + "ports": { + "pmech": 3, + "speed": 5 + }, + "params": { + "Trate": 1050.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "1032_G_sexs_pti", + "ports": { + "bus": 1032, + "efd": 4 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "1032_S_regca", + "ports": { + "bus": 1032, + "ipcmd": 6, + "iqcmd": 7, + "ibranchr": 8, + "ibranchi": 9, + "pbranch": 10, + "qbranch": 11 + }, + "params": { + "p0": 5.199999809265137, + "q0": -0.03334444761276245, + "mva": 638.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "1032_S_reecb", + "ports": { + "bus": 1032, + "iqcmd": 7, + "ipcmd": 6, + "pe": 10, + "qgen": 11, + "qext": 12, + "pref": 13 + }, + "params": { + "mva": 638.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "1032_S_repca", + "ports": { + "bus": 1032, + "ir": 8, + "ii": 9, + "p": 10, + "q": 11, + "qext": 12, + "pext": 13 + }, + "params": { + "mva": 638.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "1034_C_genrou", + "ports": { + "bus": 1034, + "pmech": 14, + "efd": 15, + "speed": 16 + }, + "params": { + "p0": 18.469999313354492, + "q0": 2.6262736320495605, + "H": 2.4100000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2100.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "1034_C_tgov1", + "ports": { + "speed": 16, + "pmech": 14 + }, + "params": { + "Trate": 2100.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "1034_C_sexs_pti", + "ports": { + "bus": 1034, + "efd": 15 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "1034_G_genrou", + "ports": { + "bus": 1034, + "pmech": 17, + "efd": 18, + "speed": 19 + }, + "params": { + "p0": 25.649999618530273, + "q0": 2.6262736320495605, + "H": 2.4100000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2900.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "1034_G_gast_pti", + "ports": { + "pmech": 17, + "speed": 19 + }, + "params": { + "Trate": 2900.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "1034_G_sexs_pti", + "ports": { + "bus": 1034, + "efd": 18 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "1034_W_regca", + "ports": { + "bus": 1034, + "ipcmd": 20, + "iqcmd": 21, + "ibranchr": 22, + "ibranchi": 23, + "pbranch": 24, + "qbranch": 25 + }, + "params": { + "p0": 15.979999542236328, + "q0": 2.6262736320495605, + "mva": 1682.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "1034_W_reecb", + "ports": { + "bus": 1034, + "iqcmd": 21, + "ipcmd": 20, + "pe": 24, + "qgen": 25, + "qext": 26, + "pref": 27 + }, + "params": { + "mva": 1682.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "1034_W_repca", + "ports": { + "bus": 1034, + "ir": 22, + "ii": 23, + "p": 24, + "q": 25, + "qext": 26, + "pext": 27 + }, + "params": { + "mva": 1682.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "1131_C_genrou", + "ports": { + "bus": 1131, + "pmech": 28, + "efd": 29, + "speed": 30 + }, + "params": { + "p0": 5.300000190734863, + "q0": -0.4679132103919983, + "H": 4.260000228881836, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1268.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "1131_C_tgov1", + "ports": { + "speed": 30, + "pmech": 28 + }, + "params": { + "Trate": 1268.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "1131_C_sexs_pti", + "ports": { + "bus": 1131, + "efd": 29 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "1131_G_genrou", + "ports": { + "bus": 1131, + "pmech": 31, + "efd": 32, + "speed": 33 + }, + "params": { + "p0": 20.639999389648438, + "q0": -0.4679132103919983, + "H": 4.260000228881836, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 4934.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "1131_G_gast_pti", + "ports": { + "pmech": 31, + "speed": 33 + }, + "params": { + "Trate": 4934.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "1131_G_sexs_pti", + "ports": { + "bus": 1131, + "efd": 32 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "1232_C_genrou", + "ports": { + "bus": 1232, + "pmech": 34, + "efd": 35, + "speed": 36 + }, + "params": { + "p0": 27.280000686645508, + "q0": 0.005521142389625311, + "H": 4.260000228881836, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 4977.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "1232_C_tgov1", + "ports": { + "speed": 36, + "pmech": 34 + }, + "params": { + "Trate": 4977.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "1232_C_sexs_pti", + "ports": { + "bus": 1232, + "efd": 35 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "1232_H_genrou", + "ports": { + "bus": 1232, + "pmech": 37, + "efd": 38, + "speed": 39 + }, + "params": { + "p0": 6.570000171661377, + "q0": 0.005521142389625311, + "H": 4.260000228881836, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1199.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "1232_H_hygov", + "ports": { + "speed": 39, + "pmech": 37 + }, + "params": { + "Trate": 1199.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "1232_H_sexs_pti", + "ports": { + "bus": 1232, + "efd": 38 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "1331_G_genrou", + "ports": { + "bus": 1331, + "pmech": 40, + "efd": 41, + "speed": 42 + }, + "params": { + "p0": 19.860000610351562, + "q0": 0.24621528387069702, + "H": 4.260000228881836, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2167.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "1331_G_gast_pti", + "ports": { + "pmech": 40, + "speed": 42 + }, + "params": { + "Trate": 2167.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "1331_G_sexs_pti", + "ports": { + "bus": 1331, + "efd": 41 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "1331_H_genrou", + "ports": { + "bus": 1331, + "pmech": 43, + "efd": 44, + "speed": 45 + }, + "params": { + "p0": 21.329999923706055, + "q0": 0.24621528387069702, + "H": 4.260000228881836, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2328.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "1331_H_hygov", + "ports": { + "speed": 45, + "pmech": 43 + }, + "params": { + "Trate": 2328.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "1331_H_sexs_pti", + "ports": { + "bus": 1331, + "efd": 44 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "1333_C_genrou", + "ports": { + "bus": 1333, + "pmech": 46, + "efd": 47, + "speed": 48 + }, + "params": { + "p0": 2.180000066757202, + "q0": 2.1732051372528076, + "H": 2.7899999618530273, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 418.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "1333_C_tgov1", + "ports": { + "speed": 48, + "pmech": 46 + }, + "params": { + "Trate": 418.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "1333_C_sexs_pti", + "ports": { + "bus": 1333, + "efd": 47 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "1333_G_genrou", + "ports": { + "bus": 1333, + "pmech": 49, + "efd": 50, + "speed": 51 + }, + "params": { + "p0": 36.619998931884766, + "q0": 2.1732051372528076, + "H": 2.7899999618530273, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 7011.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "1333_G_gast_pti", + "ports": { + "pmech": 49, + "speed": 51 + }, + "params": { + "Trate": 7011.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "1333_G_sexs_pti", + "ports": { + "bus": 1333, + "vs": 52, + "efd": 50 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Ieeest", + "id": "1333_G_ieeest", + "ports": { + "input": 51, + "output": 52 + }, + "params": { + "A1": 1.0130000114440918, + "A2": 0.013000000268220901, + "A3": 0.0, + "A4": 0.0, + "A5": 1.0130000114440918, + "A6": 0.11299999803304672, + "T1": 3.0, + "T2": 0.019999999552965164, + "T3": 0.0, + "T4": 0.0, + "T5": 1.649999976158142, + "T6": 1.649999976158142, + "Ks": 3.0, + "Lsmin": -0.10000000149011612, + "Lsmax": 0.10000000149011612, + "Vcl": 0.0, + "Vcu": 0.0, + "Tdelay": 0.0 + } + }, + { + "class": "Regca", + "id": "1333_S_regca", + "ports": { + "bus": 1333, + "ipcmd": 53, + "iqcmd": 54, + "ibranchr": 55, + "ibranchi": 56, + "pbranch": 57, + "qbranch": 58 + }, + "params": { + "p0": 12.65999984741211, + "q0": 2.1732051372528076, + "mva": 2423.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "1333_S_reecb", + "ports": { + "bus": 1333, + "iqcmd": 54, + "ipcmd": 53, + "pe": 57, + "qgen": 58, + "qext": 59, + "pref": 60 + }, + "params": { + "mva": 2423.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "1333_S_repca", + "ports": { + "bus": 1333, + "ir": 55, + "ii": 56, + "p": 57, + "q": 58, + "qext": 59, + "pext": 60 + }, + "params": { + "mva": 2423.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "1431_G_genrou", + "ports": { + "bus": 1431, + "pmech": 61, + "efd": 62, + "speed": 63 + }, + "params": { + "p0": 51.290000915527344, + "q0": 4.09153938293457, + "H": 4.260000228881836, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 9170.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "1431_G_gast_pti", + "ports": { + "pmech": 61, + "speed": 63 + }, + "params": { + "Trate": 9170.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "1431_G_sexs_pti", + "ports": { + "bus": 1431, + "efd": 62 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "1431_N_genrou", + "ports": { + "bus": 1431, + "pmech": 64, + "efd": 65, + "speed": 66 + }, + "params": { + "p0": 23.549999237060547, + "q0": 4.09153938293457, + "H": 4.260000228881836, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 4210.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "1431_N_tgov1", + "ports": { + "speed": 66, + "pmech": 64 + }, + "params": { + "Trate": 4210.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "1431_N_sexs_pti", + "ports": { + "bus": 1431, + "efd": 65 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "1431_S_regca", + "ports": { + "bus": 1431, + "ipcmd": 67, + "iqcmd": 68, + "ibranchr": 69, + "ibranchi": 70, + "pbranch": 71, + "qbranch": 72 + }, + "params": { + "p0": 13.529999732971191, + "q0": 4.09153938293457, + "mva": 2419.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "1431_S_reecb", + "ports": { + "bus": 1431, + "iqcmd": 68, + "ipcmd": 67, + "pe": 71, + "qgen": 72, + "qext": 73, + "pref": 74 + }, + "params": { + "mva": 2419.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "1431_S_repca", + "ports": { + "bus": 1431, + "ir": 69, + "ii": 70, + "p": 71, + "q": 72, + "qext": 73, + "pext": 74 + }, + "params": { + "mva": 2419.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "2030_E_genrou", + "ports": { + "bus": 2030, + "pmech": 75, + "efd": 76, + "speed": 77 + }, + "params": { + "p0": 6.050000190734863, + "q0": 1.4247709512710571, + "H": 4.53000020980835, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 699.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "2030_E_tgov1", + "ports": { + "speed": 77, + "pmech": 75 + }, + "params": { + "Trate": 699.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "2030_E_sexs_pti", + "ports": { + "bus": 2030, + "efd": 76 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "2030_G_genrou", + "ports": { + "bus": 2030, + "pmech": 78, + "efd": 79, + "speed": 80 + }, + "params": { + "p0": 18.530000686645508, + "q0": 1.4247709512710571, + "H": 4.53000020980835, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2140.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "2030_G_gast_pti", + "ports": { + "pmech": 78, + "speed": 80 + }, + "params": { + "Trate": 2140.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "2030_G_sexs_pti", + "ports": { + "bus": 2030, + "vs": 81, + "efd": 79 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Ieeest", + "id": "2030_G_ieeest", + "ports": { + "input": 80, + "output": 81 + }, + "params": { + "A1": 1.0130000114440918, + "A2": 0.013000000268220901, + "A3": 0.0, + "A4": 0.0, + "A5": 1.0130000114440918, + "A6": 0.11299999803304672, + "T1": 4.0, + "T2": 0.019999999552965164, + "T3": 0.0, + "T4": 0.0, + "T5": 1.649999976158142, + "T6": 1.649999976158142, + "Ks": 3.0, + "Lsmin": -0.10000000149011612, + "Lsmax": 0.10000000149011612, + "Vcl": 0.0, + "Vcu": 0.0, + "Tdelay": 0.0 + } + }, + { + "class": "Genrou", + "id": "2130_E_genrou", + "ports": { + "bus": 2130, + "pmech": 82, + "efd": 83, + "speed": 84 + }, + "params": { + "p0": 5.730000019073486, + "q0": 0.2871064245700836, + "H": 3.740000009536743, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 831.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "2130_E_tgov1", + "ports": { + "speed": 84, + "pmech": 82 + }, + "params": { + "Trate": 831.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "2130_E_sexs_pti", + "ports": { + "bus": 2130, + "efd": 83 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "2130_G_genrou", + "ports": { + "bus": 2130, + "pmech": 85, + "efd": 86, + "speed": 87 + }, + "params": { + "p0": 4.039999961853027, + "q0": 0.2871064245700836, + "H": 3.740000009536743, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 586.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "2130_G_gast_pti", + "ports": { + "pmech": 85, + "speed": 87 + }, + "params": { + "Trate": 586.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "2130_G_sexs_pti", + "ports": { + "bus": 2130, + "efd": 86 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "2130_H_genrou", + "ports": { + "bus": 2130, + "pmech": 88, + "efd": 89, + "speed": 90 + }, + "params": { + "p0": 2.7300000190734863, + "q0": 0.2871064245700836, + "H": 3.740000009536743, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 396.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "2130_H_hygov", + "ports": { + "speed": 90, + "pmech": 88 + }, + "params": { + "Trate": 396.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "2130_H_sexs_pti", + "ports": { + "bus": 2130, + "efd": 89 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "2130_S_regca", + "ports": { + "bus": 2130, + "ipcmd": 91, + "iqcmd": 92, + "ibranchr": 93, + "ibranchi": 94, + "pbranch": 95, + "qbranch": 96 + }, + "params": { + "p0": 0.7900000214576721, + "q0": 0.2871064245700836, + "mva": 115.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "2130_S_reecb", + "ports": { + "bus": 2130, + "iqcmd": 92, + "ipcmd": 91, + "pe": 95, + "qgen": 96, + "qext": 97, + "pref": 98 + }, + "params": { + "mva": 115.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "2130_S_repca", + "ports": { + "bus": 2130, + "ir": 93, + "ii": 94, + "p": 95, + "q": 96, + "qext": 97, + "pext": 98 + }, + "params": { + "mva": 115.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "2233_DG_genrou", + "ports": { + "bus": 2233, + "pmech": 99, + "efd": 100, + "speed": 101 + }, + "params": { + "p0": 2.8499999046325684, + "q0": 1.2546589374542236, + "H": 3.299999952316284, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1035.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "2233_DG_gast_pti", + "ports": { + "pmech": 99, + "speed": 101 + }, + "params": { + "Trate": 1035.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "2233_DG_sexs_pti", + "ports": { + "bus": 2233, + "efd": 100 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "2233_EG_genrou", + "ports": { + "bus": 2233, + "pmech": 102, + "efd": 103, + "speed": 104 + }, + "params": { + "p0": 5.059999942779541, + "q0": 1.2546589374542236, + "H": 3.299999952316284, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1837.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "2233_EG_gast_pti", + "ports": { + "pmech": 102, + "speed": 104 + }, + "params": { + "Trate": 1837.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "2233_EG_sexs_pti", + "ports": { + "bus": 2233, + "efd": 103 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "2233_TG_genrou", + "ports": { + "bus": 2233, + "pmech": 105, + "efd": 106, + "speed": 107 + }, + "params": { + "p0": 2.0199999809265137, + "q0": 1.2546589374542236, + "H": 3.299999952316284, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 733.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "2233_TG_gast_pti", + "ports": { + "pmech": 105, + "speed": 107 + }, + "params": { + "Trate": 733.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "2233_TG_sexs_pti", + "ports": { + "bus": 2233, + "efd": 106 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "2332_S_regca", + "ports": { + "bus": 2332, + "ipcmd": 108, + "iqcmd": 109, + "ibranchr": 110, + "ibranchi": 111, + "pbranch": 112, + "qbranch": 113 + }, + "params": { + "p0": 8.779999732971191, + "q0": 0.42003318667411804, + "mva": 1333.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "2332_S_reecb", + "ports": { + "bus": 2332, + "iqcmd": 109, + "ipcmd": 108, + "pe": 112, + "qgen": 113, + "qext": 114, + "pref": 115 + }, + "params": { + "mva": 1333.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "2332_S_repca", + "ports": { + "bus": 2332, + "ir": 110, + "ii": 111, + "p": 112, + "q": 113, + "qext": 114, + "pext": 115 + }, + "params": { + "mva": 1333.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Regca", + "id": "2431_S_regca", + "ports": { + "bus": 2431, + "ipcmd": 116, + "iqcmd": 117, + "ibranchr": 118, + "ibranchi": 119, + "pbranch": 120, + "qbranch": 121 + }, + "params": { + "p0": 5.0, + "q0": -0.452220618724823, + "mva": 1666.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "2431_S_reecb", + "ports": { + "bus": 2431, + "iqcmd": 117, + "ipcmd": 116, + "pe": 120, + "qgen": 121, + "qext": 122, + "pref": 123 + }, + "params": { + "mva": 1666.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "2431_S_repca", + "ports": { + "bus": 2431, + "ir": 118, + "ii": 119, + "p": 120, + "q": 121, + "qext": 122, + "pext": 123 + }, + "params": { + "mva": 1666.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Regca", + "id": "2434_S_regca", + "ports": { + "bus": 2434, + "ipcmd": 124, + "iqcmd": 125, + "ibranchr": 126, + "ibranchi": 127, + "pbranch": 128, + "qbranch": 129 + }, + "params": { + "p0": 5.0, + "q0": -3.3753299713134766, + "mva": 1489.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "2434_S_reecb", + "ports": { + "bus": 2434, + "iqcmd": 125, + "ipcmd": 124, + "pe": 128, + "qgen": 129, + "qext": 130, + "pref": 131 + }, + "params": { + "mva": 1489.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "2434_S_repca", + "ports": { + "bus": 2434, + "ir": 126, + "ii": 127, + "p": 128, + "q": 129, + "qext": 130, + "pext": 131 + }, + "params": { + "mva": 1489.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "2438_EG_genrou", + "ports": { + "bus": 2438, + "pmech": 132, + "efd": 133, + "speed": 134 + }, + "params": { + "p0": 5.03000020980835, + "q0": 0.32094326615333557, + "H": 3.5399999618530273, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2292.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "2438_EG_gast_pti", + "ports": { + "pmech": 132, + "speed": 134 + }, + "params": { + "Trate": 2292.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "2438_EG_sexs_pti", + "ports": { + "bus": 2438, + "efd": 133 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "2438_RG_genrou", + "ports": { + "bus": 2438, + "pmech": 135, + "efd": 136, + "speed": 137 + }, + "params": { + "p0": 11.959990501403809, + "q0": 0.32094326615333557, + "H": 3.5399999618530273, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 5451.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "2438_RG_gast_pti", + "ports": { + "pmech": 135, + "speed": 137 + }, + "params": { + "Trate": 5451.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "2438_RG_sexs_pti", + "ports": { + "bus": 2438, + "efd": 136 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "2438_S_regca", + "ports": { + "bus": 2438, + "ipcmd": 138, + "iqcmd": 139, + "ibranchr": 140, + "ibranchi": 141, + "pbranch": 142, + "qbranch": 143 + }, + "params": { + "p0": 2.509999990463257, + "q0": 0.32094326615333557, + "mva": 1146.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "2438_S_reecb", + "ports": { + "bus": 2438, + "iqcmd": 139, + "ipcmd": 138, + "pe": 142, + "qgen": 143, + "qext": 144, + "pref": 145 + }, + "params": { + "mva": 1146.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "2438_S_repca", + "ports": { + "bus": 2438, + "ir": 140, + "ii": 141, + "p": 142, + "q": 143, + "qext": 144, + "pext": 145 + }, + "params": { + "mva": 1146.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "2438_SG_genrou", + "ports": { + "bus": 2438, + "pmech": 146, + "efd": 147, + "speed": 148 + }, + "params": { + "p0": 9.010000228881836, + "q0": 0.32094326615333557, + "H": 3.5399999618530273, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 4110.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "2438_SG_gast_pti", + "ports": { + "pmech": 146, + "speed": 148 + }, + "params": { + "Trate": 4110.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "2438_SG_sexs_pti", + "ports": { + "bus": 2438, + "efd": 147 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "2438_SH_genrou", + "ports": { + "bus": 2438, + "pmech": 149, + "efd": 150, + "speed": 151 + }, + "params": { + "p0": 2.3299999237060547, + "q0": 0.32094326615333557, + "H": 3.5399999618530273, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1460.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "2438_SH_hygov", + "ports": { + "speed": 151, + "pmech": 149 + }, + "params": { + "Trate": 1460.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "2438_SH_sexs_pti", + "ports": { + "bus": 2438, + "efd": 150 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "2438_SW_regca", + "ports": { + "bus": 2438, + "ipcmd": 152, + "iqcmd": 153, + "ibranchr": 154, + "ibranchi": 155, + "pbranch": 156, + "qbranch": 157 + }, + "params": { + "p0": 7.039999961853027, + "q0": 0.32094326615333557, + "mva": 3210.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "2438_SW_reecb", + "ports": { + "bus": 2438, + "iqcmd": 153, + "ipcmd": 152, + "pe": 156, + "qgen": 157, + "qext": 158, + "pref": 159 + }, + "params": { + "mva": 3210.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "2438_SW_repca", + "ports": { + "bus": 2438, + "ir": 154, + "ii": 155, + "p": 156, + "q": 157, + "qext": 158, + "pext": 159 + }, + "params": { + "mva": 3210.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "2438_WG_genrou", + "ports": { + "bus": 2438, + "pmech": 160, + "efd": 161, + "speed": 162 + }, + "params": { + "p0": 12.760000228881836, + "q0": 0.32094326615333557, + "H": 3.5399999618530273, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 5817.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "2438_WG_gast_pti", + "ports": { + "pmech": 160, + "speed": 162 + }, + "params": { + "Trate": 5817.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "2438_WG_sexs_pti", + "ports": { + "bus": 2438, + "vs": 163, + "efd": 161 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Ieeest", + "id": "2438_WG_ieeest", + "ports": { + "input": 162, + "output": 163 + }, + "params": { + "A1": 1.0130000114440918, + "A2": 0.013000000268220901, + "A3": 0.0, + "A4": 0.0, + "A5": 1.0130000114440918, + "A6": 0.11299999803304672, + "T1": 11.0, + "T2": 0.019999999552965164, + "T3": 0.0, + "T4": 0.0, + "T5": 1.649999976158142, + "T6": 1.649999976158142, + "Ks": 3.0, + "Lsmin": -0.10000000149011612, + "Lsmax": 0.10000000149011612, + "Vcl": 0.0, + "Vcu": 0.0, + "Tdelay": 0.0 + } + }, + { + "class": "Regca", + "id": "2439_S_regca", + "ports": { + "bus": 2439, + "ipcmd": 164, + "iqcmd": 165, + "ibranchr": 166, + "ibranchi": 167, + "pbranch": 168, + "qbranch": 169 + }, + "params": { + "p0": 10.0, + "q0": -2.4267404079437256, + "mva": 1666.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "2439_S_reecb", + "ports": { + "bus": 2439, + "iqcmd": 165, + "ipcmd": 164, + "pe": 168, + "qgen": 169, + "qext": 170, + "pref": 171 + }, + "params": { + "mva": 1666.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "2439_S_repca", + "ports": { + "bus": 2439, + "ir": 166, + "ii": 167, + "p": 168, + "q": 169, + "qext": 170, + "pext": 171 + }, + "params": { + "mva": 1666.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Regca", + "id": "2533_S_regca", + "ports": { + "bus": 2533, + "ipcmd": 172, + "iqcmd": 173, + "ibranchr": 174, + "ibranchi": 175, + "pbranch": 176, + "qbranch": 177 + }, + "params": { + "p0": 18.989999771118164, + "q0": 1.2751047611236572, + "mva": 1999.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "2533_S_reecb", + "ports": { + "bus": 2533, + "iqcmd": 173, + "ipcmd": 172, + "pe": 176, + "qgen": 177, + "qext": 178, + "pref": 179 + }, + "params": { + "mva": 1999.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "2533_S_repca", + "ports": { + "bus": 2533, + "ir": 174, + "ii": 175, + "p": 176, + "q": 177, + "qext": 178, + "pext": 179 + }, + "params": { + "mva": 1999.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "2630_G_genrou", + "ports": { + "bus": 2630, + "pmech": 180, + "efd": 181, + "speed": 182 + }, + "params": { + "p0": 22.81999969482422, + "q0": 1.8477349281311035, + "H": 4.75, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 3947.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "2630_G_gast_pti", + "ports": { + "pmech": 180, + "speed": 182 + }, + "params": { + "Trate": 3947.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "2630_G_sexs_pti", + "ports": { + "bus": 2630, + "vs": 183, + "efd": 181 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Ieeest", + "id": "2630_G_ieeest", + "ports": { + "input": 182, + "output": 183 + }, + "params": { + "A1": 1.0130000114440918, + "A2": 0.013000000268220901, + "A3": 0.0, + "A4": 0.0, + "A5": 1.0130000114440918, + "A6": 0.11299999803304672, + "T1": 4.0, + "T2": 0.019999999552965164, + "T3": 0.0, + "T4": 0.0, + "T5": 1.649999976158142, + "T6": 1.649999976158142, + "Ks": 3.0, + "Lsmin": -0.10000000149011612, + "Lsmax": 0.10000000149011612, + "Vcl": 0.0, + "Vcu": 0.0, + "Tdelay": 0.0 + } + }, + { + "class": "Regca", + "id": "2631_S_regca", + "ports": { + "bus": 2631, + "ipcmd": 184, + "iqcmd": 185, + "ibranchr": 186, + "ibranchi": 187, + "pbranch": 188, + "qbranch": 189 + }, + "params": { + "p0": 2.319999933242798, + "q0": 0.3206254243850708, + "mva": 520.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "2631_S_reecb", + "ports": { + "bus": 2631, + "iqcmd": 185, + "ipcmd": 184, + "pe": 188, + "qgen": 189, + "qext": 190, + "pref": 191 + }, + "params": { + "mva": 520.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "2631_S_repca", + "ports": { + "bus": 2631, + "ir": 186, + "ii": 187, + "p": 188, + "q": 189, + "qext": 190, + "pext": 191 + }, + "params": { + "mva": 520.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "2634_C_genrou", + "ports": { + "bus": 2634, + "pmech": 192, + "efd": 193, + "speed": 194 + }, + "params": { + "p0": 15.369999885559082, + "q0": -0.1887885481119156, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1900.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "2634_C_tgov1", + "ports": { + "speed": 194, + "pmech": 192 + }, + "params": { + "Trate": 1900.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "2634_C_sexs_pti", + "ports": { + "bus": 2634, + "efd": 193 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "2637_H_genrou", + "ports": { + "bus": 2637, + "pmech": 195, + "efd": 196, + "speed": 197 + }, + "params": { + "p0": 0.8299999833106995, + "q0": 0.4044739603996277, + "H": 4.75, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 200.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "2637_H_hygov", + "ports": { + "speed": 197, + "pmech": 195 + }, + "params": { + "Trate": 200.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "2637_H_sexs_pti", + "ports": { + "bus": 2637, + "efd": 196 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "2638_H_genrou", + "ports": { + "bus": 2638, + "pmech": 198, + "efd": 199, + "speed": 200 + }, + "params": { + "p0": 2.0, + "q0": 0.07739762961864471, + "H": 4.75, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 407.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "2638_H_hygov", + "ports": { + "speed": 200, + "pmech": 198 + }, + "params": { + "Trate": 407.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "2638_H_sexs_pti", + "ports": { + "bus": 2638, + "efd": 199 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3133_NG_genrou", + "ports": { + "bus": 3133, + "pmech": 201, + "efd": 202, + "speed": 203 + }, + "params": { + "p0": 0.3100000023841858, + "q0": -0.12547613680362701, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 80.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "3133_NG_gast_pti", + "ports": { + "pmech": 201, + "speed": 203 + }, + "params": { + "Trate": 80.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "3133_NG_sexs_pti", + "ports": { + "bus": 3133, + "efd": 202 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3135_MG_genrou", + "ports": { + "bus": 3135, + "pmech": 204, + "efd": 205, + "speed": 206 + }, + "params": { + "p0": 2.059999942779541, + "q0": 0.42757341265678406, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 541.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "3135_MG_gast_pti", + "ports": { + "pmech": 204, + "speed": 206 + }, + "params": { + "Trate": 541.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "3135_MG_sexs_pti", + "ports": { + "bus": 3135, + "efd": 205 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3135_NG_genrou", + "ports": { + "bus": 3135, + "pmech": 207, + "efd": 208, + "speed": 209 + }, + "params": { + "p0": 0.14000000059604645, + "q0": 0.42757341265678406, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 38.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "3135_NG_gast_pti", + "ports": { + "pmech": 207, + "speed": 209 + }, + "params": { + "Trate": 38.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "3135_NG_sexs_pti", + "ports": { + "bus": 3135, + "efd": 208 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3234_DG_genrou", + "ports": { + "bus": 3234, + "pmech": 210, + "efd": 211, + "speed": 212 + }, + "params": { + "p0": 1.0399999618530273, + "q0": 1.0099999904632568, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 177.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "3234_DG_gast_pti", + "ports": { + "pmech": 210, + "speed": 212 + }, + "params": { + "Trate": 177.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "3234_DG_sexs_pti", + "ports": { + "bus": 3234, + "efd": 211 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3234_MG_genrou", + "ports": { + "bus": 3234, + "pmech": 213, + "efd": 214, + "speed": 215 + }, + "params": { + "p0": 22.610000610351562, + "q0": 1.1887773275375366, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 3853.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "3234_MG_gast_pti", + "ports": { + "pmech": 213, + "speed": 215 + }, + "params": { + "Trate": 3853.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "3234_MG_sexs_pti", + "ports": { + "bus": 3234, + "efd": 214 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3234_NG_genrou", + "ports": { + "bus": 3234, + "pmech": 216, + "efd": 217, + "speed": 218 + }, + "params": { + "p0": 6.079999923706055, + "q0": 1.1887773275375366, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1037.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "3234_NG_gast_pti", + "ports": { + "pmech": 216, + "speed": 218 + }, + "params": { + "Trate": 1037.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "3234_NG_sexs_pti", + "ports": { + "bus": 3234, + "efd": 217 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "3234_NW_regca", + "ports": { + "bus": 3234, + "ipcmd": 219, + "iqcmd": 220, + "ibranchr": 221, + "ibranchi": 222, + "pbranch": 223, + "qbranch": 224 + }, + "params": { + "p0": 10.210000038146973, + "q0": 1.1887773275375366, + "mva": 1740.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "3234_NW_reecb", + "ports": { + "bus": 3234, + "iqcmd": 220, + "ipcmd": 219, + "pe": 223, + "qgen": 224, + "qext": 225, + "pref": 226 + }, + "params": { + "mva": 1740.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "3234_NW_repca", + "ports": { + "bus": 3234, + "ir": 221, + "ii": 222, + "p": 223, + "q": 224, + "qext": 225, + "pext": 226 + }, + "params": { + "mva": 1740.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "3333_CG_genrou", + "ports": { + "bus": 3333, + "pmech": 227, + "efd": 228, + "speed": 229 + }, + "params": { + "p0": 6.199999809265137, + "q0": 0.8166592717170715, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1012.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "3333_CG_gast_pti", + "ports": { + "pmech": 227, + "speed": 229 + }, + "params": { + "Trate": 1012.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "3333_CG_sexs_pti", + "ports": { + "bus": 3333, + "efd": 228 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3333_NG_genrou", + "ports": { + "bus": 3333, + "pmech": 230, + "efd": 231, + "speed": 232 + }, + "params": { + "p0": 1.909999966621399, + "q0": 0.8166592717170715, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 312.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "3333_NG_gast_pti", + "ports": { + "pmech": 230, + "speed": 232 + }, + "params": { + "Trate": 312.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "3333_NG_sexs_pti", + "ports": { + "bus": 3333, + "efd": 231 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3433_NG_genrou", + "ports": { + "bus": 3433, + "pmech": 233, + "efd": 234, + "speed": 235 + }, + "params": { + "p0": 4.809999942779541, + "q0": 0.25637194514274597, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 921.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "3433_NG_gast_pti", + "ports": { + "pmech": 233, + "speed": 235 + }, + "params": { + "Trate": 921.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "3433_NG_sexs_pti", + "ports": { + "bus": 3433, + "efd": 234 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "3433_S_regca", + "ports": { + "bus": 3433, + "ipcmd": 236, + "iqcmd": 237, + "ibranchr": 238, + "ibranchi": 239, + "pbranch": 240, + "qbranch": 241 + }, + "params": { + "p0": 7.449999809265137, + "q0": 0.25637194514274597, + "mva": 1426.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "3433_S_reecb", + "ports": { + "bus": 3433, + "iqcmd": 237, + "ipcmd": 236, + "pe": 240, + "qgen": 241, + "qext": 242, + "pref": 243 + }, + "params": { + "mva": 1426.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "3433_S_repca", + "ports": { + "bus": 3433, + "ir": 238, + "ii": 239, + "p": 240, + "q": 241, + "qext": 242, + "pext": 243 + }, + "params": { + "mva": 1426.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "3531_CE_genrou", + "ports": { + "bus": 3531, + "pmech": 244, + "efd": 245, + "speed": 246 + }, + "params": { + "p0": 7.829999923706055, + "q0": 0.3085287809371948, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1424.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "3531_CE_tgov1", + "ports": { + "speed": 246, + "pmech": 244 + }, + "params": { + "Trate": 1424.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "3531_CE_sexs_pti", + "ports": { + "bus": 3531, + "efd": 245 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3531_NE_genrou", + "ports": { + "bus": 3531, + "pmech": 247, + "efd": 248, + "speed": 249 + }, + "params": { + "p0": 2.930000066757202, + "q0": 0.3085287809371948, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 533.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "3531_NE_tgov1", + "ports": { + "speed": 249, + "pmech": 247 + }, + "params": { + "Trate": 533.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "3531_NE_sexs_pti", + "ports": { + "bus": 3531, + "efd": 248 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3531_NH_genrou", + "ports": { + "bus": 3531, + "pmech": 250, + "efd": 251, + "speed": 252 + }, + "params": { + "p0": 0.12999999523162842, + "q0": 0.12999999523162842, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 24.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "3531_NH_hygov", + "ports": { + "speed": 252, + "pmech": 250 + }, + "params": { + "Trate": 24.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "3531_NH_sexs_pti", + "ports": { + "bus": 3531, + "efd": 251 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3631_NB_genrou", + "ports": { + "bus": 3631, + "pmech": 253, + "efd": 254, + "speed": 255 + }, + "params": { + "p0": 0.30000001192092896, + "q0": -0.14000000059604645, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 96.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "3631_NB_tgov1", + "ports": { + "speed": 255, + "pmech": 253 + }, + "params": { + "Trate": 96.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "3631_NB_sexs_pti", + "ports": { + "bus": 3631, + "efd": 254 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3631_NG_genrou", + "ports": { + "bus": 3631, + "pmech": 256, + "efd": 257, + "speed": 258 + }, + "params": { + "p0": 0.6700000166893005, + "q0": -0.3309527039527893, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 210.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "3631_NG_gast_pti", + "ports": { + "pmech": 256, + "speed": 258 + }, + "params": { + "Trate": 210.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "3631_NG_sexs_pti", + "ports": { + "bus": 3631, + "efd": 257 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3731_NH_genrou", + "ports": { + "bus": 3731, + "pmech": 259, + "efd": 260, + "speed": 261 + }, + "params": { + "p0": 2.2200000286102295, + "q0": -1.2100000381469727, + "H": 2.7899999618530273, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 400.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "3731_NH_hygov", + "ports": { + "speed": 261, + "pmech": 259 + }, + "params": { + "Trate": 400.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "3731_NH_sexs_pti", + "ports": { + "bus": 3731, + "efd": 260 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3831_NN_genrou", + "ports": { + "bus": 3831, + "pmech": 262, + "efd": 263, + "speed": 264 + }, + "params": { + "p0": 21.079999923706055, + "q0": -0.4079095125198364, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2323.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "3831_NN_tgov1", + "ports": { + "speed": 264, + "pmech": 262 + }, + "params": { + "Trate": 2323.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "3831_NN_sexs_pti", + "ports": { + "bus": 3831, + "efd": 263 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3835_NG_genrou", + "ports": { + "bus": 3835, + "pmech": 265, + "efd": 266, + "speed": 267 + }, + "params": { + "p0": 2.2899999618530273, + "q0": 0.28820106387138367, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2025.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "3835_NG_gast_pti", + "ports": { + "pmech": 265, + "speed": 267 + }, + "params": { + "Trate": 2025.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "3835_NG_sexs_pti", + "ports": { + "bus": 3835, + "efd": 266 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "3835_S_regca", + "ports": { + "bus": 3835, + "ipcmd": 268, + "iqcmd": 269, + "ibranchr": 270, + "ibranchi": 271, + "pbranch": 272, + "qbranch": 273 + }, + "params": { + "p0": 1.5, + "q0": 0.28820106387138367, + "mva": 1333.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "3835_S_reecb", + "ports": { + "bus": 3835, + "iqcmd": 269, + "ipcmd": 268, + "pe": 272, + "qgen": 273, + "qext": 274, + "pref": 275 + }, + "params": { + "mva": 1333.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "3835_S_repca", + "ports": { + "bus": 3835, + "ir": 270, + "ii": 271, + "p": 272, + "q": 273, + "qext": 274, + "pext": 275 + }, + "params": { + "mva": 1333.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "3836_DG_genrou", + "ports": { + "bus": 3836, + "pmech": 276, + "efd": 277, + "speed": 278 + }, + "params": { + "p0": 6.789999961853027, + "q0": -0.0682721883058548, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1497.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "3836_DG_gast_pti", + "ports": { + "pmech": 276, + "speed": 278 + }, + "params": { + "Trate": 1497.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "3836_DG_sexs_pti", + "ports": { + "bus": 3836, + "efd": 277 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3931_NB_genrou", + "ports": { + "bus": 3931, + "pmech": 279, + "efd": 280, + "speed": 281 + }, + "params": { + "p0": 2.3499999046325684, + "q0": 0.7247161269187927, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 567.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "3931_NB_tgov1", + "ports": { + "speed": 281, + "pmech": 279 + }, + "params": { + "Trate": 567.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "3931_NB_sexs_pti", + "ports": { + "bus": 3931, + "efd": 280 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3931_NH_genrou", + "ports": { + "bus": 3931, + "pmech": 282, + "efd": 283, + "speed": 284 + }, + "params": { + "p0": 12.119999885559082, + "q0": 0.7247161269187927, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2875.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "3931_NH_hygov", + "ports": { + "speed": 284, + "pmech": 282 + }, + "params": { + "Trate": 2875.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "3931_NH_sexs_pti", + "ports": { + "bus": 3931, + "vs": 285, + "efd": 283 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Ieeest", + "id": "3931_NH_ieeest", + "ports": { + "input": 284, + "output": 285 + }, + "params": { + "A1": 1.0130000114440918, + "A2": 0.013000000268220901, + "A3": 0.0, + "A4": 0.0, + "A5": 1.0130000114440918, + "A6": 0.11299999803304672, + "T1": 10.0, + "T2": 0.019999999552965164, + "T3": 0.0, + "T4": 0.0, + "T5": 1.649999976158142, + "T6": 1.649999976158142, + "Ks": 3.0, + "Lsmin": -0.10000000149011612, + "Lsmax": 0.10000000149011612, + "Vcl": 0.0, + "Vcu": 0.0, + "Tdelay": 0.0 + } + }, + { + "class": "Regca", + "id": "3932_S_regca", + "ports": { + "bus": 3932, + "ipcmd": 286, + "iqcmd": 287, + "ibranchr": 288, + "ibranchi": 289, + "pbranch": 290, + "qbranch": 291 + }, + "params": { + "p0": 13.550000190734863, + "q0": -2.4277539253234863, + "mva": 1426.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "3932_S_reecb", + "ports": { + "bus": 3932, + "iqcmd": 287, + "ipcmd": 286, + "pe": 290, + "qgen": 291, + "qext": 292, + "pref": 293 + }, + "params": { + "mva": 1426.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "3932_S_repca", + "ports": { + "bus": 3932, + "ir": 288, + "ii": 289, + "p": 290, + "q": 291, + "qext": 292, + "pext": 293 + }, + "params": { + "mva": 1426.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "3933_CG_genrou", + "ports": { + "bus": 3933, + "pmech": 294, + "efd": 295, + "speed": 296 + }, + "params": { + "p0": 4.048871040344238, + "q0": 0.8865452408790588, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 865.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "3933_CG_gast_pti", + "ports": { + "pmech": 294, + "speed": 296 + }, + "params": { + "Trate": 865.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "3933_CG_sexs_pti", + "ports": { + "bus": 3933, + "efd": 295 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3933_NB_genrou", + "ports": { + "bus": 3933, + "pmech": 297, + "efd": 298, + "speed": 299 + }, + "params": { + "p0": 1.6148682832717896, + "q0": 0.7699999809265137, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 345.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "3933_NB_tgov1", + "ports": { + "speed": 299, + "pmech": 297 + }, + "params": { + "Trate": 345.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "3933_NB_sexs_pti", + "ports": { + "bus": 3933, + "efd": 298 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3933_NG_genrou", + "ports": { + "bus": 3933, + "pmech": 300, + "efd": 301, + "speed": 302 + }, + "params": { + "p0": 9.019858360290527, + "q0": 0.8865452408790588, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1927.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "3933_NG_gast_pti", + "ports": { + "pmech": 300, + "speed": 302 + }, + "params": { + "Trate": 1927.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "3933_NG_sexs_pti", + "ports": { + "bus": 3933, + "efd": 301 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "3933_NH_genrou", + "ports": { + "bus": 3933, + "pmech": 303, + "efd": 304, + "speed": 305 + }, + "params": { + "p0": 12.750443458557129, + "q0": 0.8865452408790588, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2774.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "3933_NH_hygov", + "ports": { + "speed": 305, + "pmech": 303 + }, + "params": { + "Trate": 2774.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "3933_NH_sexs_pti", + "ports": { + "bus": 3933, + "efd": 304 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "3933_NW_regca", + "ports": { + "bus": 3933, + "ipcmd": 306, + "iqcmd": 307, + "ibranchr": 308, + "ibranchi": 309, + "pbranch": 310, + "qbranch": 311 + }, + "params": { + "p0": 3.4637808799743652, + "q0": 0.8865452408790588, + "mva": 740.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "3933_NW_reecb", + "ports": { + "bus": 3933, + "iqcmd": 307, + "ipcmd": 306, + "pe": 310, + "qgen": 311, + "qext": 312, + "pref": 313 + }, + "params": { + "mva": 740.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "3933_NW_repca", + "ports": { + "bus": 3933, + "ir": 308, + "ii": 309, + "p": 310, + "q": 311, + "qext": 312, + "pext": 313 + }, + "params": { + "mva": 740.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Regca", + "id": "3933_S_regca", + "ports": { + "bus": 3933, + "ipcmd": 314, + "iqcmd": 315, + "ibranchr": 316, + "ibranchi": 317, + "pbranch": 318, + "qbranch": 319 + }, + "params": { + "p0": 6.239480018615723, + "q0": 0.8865452408790588, + "mva": 1333.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "3933_S_reecb", + "ports": { + "bus": 3933, + "iqcmd": 315, + "ipcmd": 314, + "pe": 318, + "qgen": 319, + "qext": 320, + "pref": 321 + }, + "params": { + "mva": 1333.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "3933_S_repca", + "ports": { + "bus": 3933, + "ir": 316, + "ii": 317, + "p": 318, + "q": 319, + "qext": 320, + "pext": 321 + }, + "params": { + "mva": 1333.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "4031_G_genrou", + "ports": { + "bus": 4031, + "pmech": 322, + "efd": 323, + "speed": 324 + }, + "params": { + "p0": 8.928009986877441, + "q0": -1.6852635145187378, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2710.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "4031_G_gast_pti", + "ports": { + "pmech": 322, + "speed": 324 + }, + "params": { + "Trate": 2710.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "4031_G_sexs_pti", + "ports": { + "bus": 4031, + "efd": 323 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "4031_H_genrou", + "ports": { + "bus": 4031, + "pmech": 325, + "efd": 326, + "speed": 327 + }, + "params": { + "p0": 3.1319899559020996, + "q0": -1.6852635145187378, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 952.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "4031_H_hygov", + "ports": { + "speed": 327, + "pmech": 325 + }, + "params": { + "Trate": 952.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "4031_H_sexs_pti", + "ports": { + "bus": 4031, + "efd": 326 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "4031_S_regca", + "ports": { + "bus": 4031, + "ipcmd": 328, + "iqcmd": 329, + "ibranchr": 330, + "ibranchi": 331, + "pbranch": 332, + "qbranch": 333 + }, + "params": { + "p0": 1.403999924659729, + "q0": -1.6852635145187378, + "mva": 427.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "4031_S_reecb", + "ports": { + "bus": 4031, + "iqcmd": 329, + "ipcmd": 328, + "pe": 332, + "qgen": 333, + "qext": 334, + "pref": 335 + }, + "params": { + "mva": 427.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "4031_S_repca", + "ports": { + "bus": 4031, + "ir": 330, + "ii": 331, + "p": 332, + "q": 333, + "qext": 334, + "pext": 335 + }, + "params": { + "mva": 427.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Regca", + "id": "4031_W_regca", + "ports": { + "bus": 4031, + "ipcmd": 336, + "iqcmd": 337, + "ibranchr": 338, + "ibranchi": 339, + "pbranch": 340, + "qbranch": 341 + }, + "params": { + "p0": 2.0880000591278076, + "q0": -1.6852635145187378, + "mva": 635.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "4031_W_reecb", + "ports": { + "bus": 4031, + "iqcmd": 337, + "ipcmd": 336, + "pe": 340, + "qgen": 341, + "qext": 342, + "pref": 343 + }, + "params": { + "mva": 635.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "4031_W_repca", + "ports": { + "bus": 4031, + "ir": 338, + "ii": 339, + "p": 340, + "q": 341, + "qext": 342, + "pext": 343 + }, + "params": { + "mva": 635.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "4035_C_genrou", + "ports": { + "bus": 4035, + "pmech": 344, + "efd": 345, + "speed": 346 + }, + "params": { + "p0": 1.7369999885559082, + "q0": -1.2261263132095337, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 642.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "4035_C_tgov1", + "ports": { + "speed": 346, + "pmech": 344 + }, + "params": { + "Trate": 642.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "4035_C_sexs_pti", + "ports": { + "bus": 4035, + "efd": 345 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "4035_G_genrou", + "ports": { + "bus": 4035, + "pmech": 347, + "efd": 348, + "speed": 349 + }, + "params": { + "p0": 4.482000350952148, + "q0": -1.2261263132095337, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1656.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "4035_G_gast_pti", + "ports": { + "pmech": 347, + "speed": 349 + }, + "params": { + "Trate": 1656.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "4035_G_sexs_pti", + "ports": { + "bus": 4035, + "efd": 348 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "4035_H_genrou", + "ports": { + "bus": 4035, + "pmech": 350, + "efd": 351, + "speed": 352 + }, + "params": { + "p0": 9.665999412536621, + "q0": -1.2261263132095337, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 3572.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "4035_H_hygov", + "ports": { + "speed": 352, + "pmech": 350 + }, + "params": { + "Trate": 3572.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "4035_H_sexs_pti", + "ports": { + "bus": 4035, + "efd": 351 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "4035_W_regca", + "ports": { + "bus": 4035, + "ipcmd": 353, + "iqcmd": 354, + "ibranchr": 355, + "ibranchi": 356, + "pbranch": 357, + "qbranch": 358 + }, + "params": { + "p0": 6.974999904632568, + "q0": -1.2261263132095337, + "mva": 2578.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "4035_W_reecb", + "ports": { + "bus": 4035, + "iqcmd": 354, + "ipcmd": 353, + "pe": 357, + "qgen": 358, + "qext": 359, + "pref": 360 + }, + "params": { + "mva": 2578.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "4035_W_repca", + "ports": { + "bus": 4035, + "ir": 355, + "ii": 356, + "p": 357, + "q": 358, + "qext": 359, + "pext": 360 + }, + "params": { + "mva": 2578.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "4039_G_genrou", + "ports": { + "bus": 4039, + "pmech": 361, + "efd": 362, + "speed": 363 + }, + "params": { + "p0": 0.7739999890327454, + "q0": 1.0199999809265137, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 150.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "4039_G_gast_pti", + "ports": { + "pmech": 361, + "speed": 363 + }, + "params": { + "Trate": 150.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "4039_G_sexs_pti", + "ports": { + "bus": 4039, + "efd": 362 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "4039_H_genrou", + "ports": { + "bus": 4039, + "pmech": 364, + "efd": 365, + "speed": 366 + }, + "params": { + "p0": 14.553000450134277, + "q0": 3.802260398864746, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2839.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "4039_H_hygov", + "ports": { + "speed": 366, + "pmech": 364 + }, + "params": { + "Trate": 2839.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "4039_H_sexs_pti", + "ports": { + "bus": 4039, + "efd": 365 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "4039_W_regca", + "ports": { + "bus": 4039, + "ipcmd": 367, + "iqcmd": 368, + "ibranchr": 369, + "ibranchi": 370, + "pbranch": 371, + "qbranch": 372 + }, + "params": { + "p0": 7.127999782562256, + "q0": 3.802260398864746, + "mva": 1290.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "4039_W_reecb", + "ports": { + "bus": 4039, + "iqcmd": 368, + "ipcmd": 367, + "pe": 371, + "qgen": 372, + "qext": 373, + "pref": 374 + }, + "params": { + "mva": 1290.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "4039_W_repca", + "ports": { + "bus": 4039, + "ir": 369, + "ii": 370, + "p": 371, + "q": 372, + "qext": 373, + "pext": 374 + }, + "params": { + "mva": 1290.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "4131_B_genrou", + "ports": { + "bus": 4131, + "pmech": 375, + "efd": 376, + "speed": 377 + }, + "params": { + "p0": 4.5, + "q0": 1.5, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 711.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "4131_B_tgov1", + "ports": { + "speed": 377, + "pmech": 375 + }, + "params": { + "Trate": 711.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "4131_B_sexs_pti", + "ports": { + "bus": 4131, + "efd": 376 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "4131_H_genrou", + "ports": { + "bus": 4131, + "pmech": 378, + "efd": 379, + "speed": 380 + }, + "params": { + "p0": 74.18700408935547, + "q0": 5.434023857116699, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 12613.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "4131_H_hygov", + "ports": { + "speed": 380, + "pmech": 378 + }, + "params": { + "Trate": 12613.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "4131_H_sexs_pti", + "ports": { + "bus": 4131, + "vs": 381, + "efd": 379 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Ieeest", + "id": "4131_H_ieeest", + "ports": { + "input": 380, + "output": 381 + }, + "params": { + "A1": 1.0130000114440918, + "A2": 0.013000000268220901, + "A3": 0.0, + "A4": 0.0, + "A5": 1.0130000114440918, + "A6": 0.11299999803304672, + "T1": 7.0, + "T2": 0.019999999552965164, + "T3": 0.0, + "T4": 0.0, + "T5": 1.649999976158142, + "T6": 1.649999976158142, + "Ks": 3.0, + "Lsmin": -0.10000000149011612, + "Lsmax": 0.10000000149011612, + "Vcl": 0.0, + "Vcu": 0.0, + "Tdelay": 0.0 + } + }, + { + "class": "Regca", + "id": "4131_W_regca", + "ports": { + "bus": 4131, + "ipcmd": 382, + "iqcmd": 383, + "ibranchr": 384, + "ibranchi": 385, + "pbranch": 386, + "qbranch": 387 + }, + "params": { + "p0": 5.552999973297119, + "q0": 1.2000000476837158, + "mva": 790.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "4131_W_reecb", + "ports": { + "bus": 4131, + "iqcmd": 383, + "ipcmd": 382, + "pe": 386, + "qgen": 387, + "qext": 388, + "pref": 389 + }, + "params": { + "mva": 790.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "4131_W_repca", + "ports": { + "bus": 4131, + "ir": 384, + "ii": 385, + "p": 386, + "q": 387, + "qext": 388, + "pext": 389 + }, + "params": { + "mva": 790.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "4132_G_genrou", + "ports": { + "bus": 4132, + "pmech": 390, + "efd": 391, + "speed": 392 + }, + "params": { + "p0": 18.54899024963379, + "q0": 0.5226131081581116, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2170.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "4132_G_gast_pti", + "ports": { + "pmech": 390, + "speed": 392 + }, + "params": { + "Trate": 2170.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "4132_G_sexs_pti", + "ports": { + "bus": 4132, + "efd": 391 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "4132_H_genrou", + "ports": { + "bus": 4132, + "pmech": 393, + "efd": 394, + "speed": 395 + }, + "params": { + "p0": 38.358009338378906, + "q0": 0.5226131081581116, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 5539.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "4132_H_hygov", + "ports": { + "speed": 395, + "pmech": 393 + }, + "params": { + "Trate": 5539.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "4132_H_sexs_pti", + "ports": { + "bus": 4132, + "efd": 394 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "4132_N_genrou", + "ports": { + "bus": 4132, + "pmech": 396, + "efd": 397, + "speed": 398 + }, + "params": { + "p0": 9.0, + "q0": 0.5226131081581116, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1200.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "4132_N_tgov1", + "ports": { + "speed": 398, + "pmech": 396 + }, + "params": { + "Trate": 1200.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "4132_N_sexs_pti", + "ports": { + "bus": 4132, + "efd": 397 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "4132_W_regca", + "ports": { + "bus": 4132, + "ipcmd": 399, + "iqcmd": 400, + "ibranchr": 401, + "ibranchi": 402, + "pbranch": 403, + "qbranch": 404 + }, + "params": { + "p0": 2.700000047683716, + "q0": 0.5226131081581116, + "mva": 400.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "4132_W_reecb", + "ports": { + "bus": 4132, + "iqcmd": 400, + "ipcmd": 399, + "pe": 403, + "qgen": 404, + "qext": 405, + "pref": 406 + }, + "params": { + "mva": 400.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "4132_W_repca", + "ports": { + "bus": 4132, + "ir": 401, + "ii": 402, + "p": 403, + "q": 404, + "qext": 405, + "pext": 406 + }, + "params": { + "mva": 400.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "4231_C_genrou", + "ports": { + "bus": 4231, + "pmech": 407, + "efd": 408, + "speed": 409 + }, + "params": { + "p0": 9.989999771118164, + "q0": 4.852294921875, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1460.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "4231_C_tgov1", + "ports": { + "speed": 409, + "pmech": 407 + }, + "params": { + "Trate": 1460.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "4231_C_sexs_pti", + "ports": { + "bus": 4231, + "efd": 408 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "4231_G_genrou", + "ports": { + "bus": 4231, + "pmech": 410, + "efd": 411, + "speed": 412 + }, + "params": { + "p0": 6.642000198364258, + "q0": 4.852294921875, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 970.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "4231_G_gast_pti", + "ports": { + "pmech": 410, + "speed": 412 + }, + "params": { + "Trate": 970.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "4231_G_sexs_pti", + "ports": { + "bus": 4231, + "efd": 411 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "4231_H_genrou", + "ports": { + "bus": 4231, + "pmech": 413, + "efd": 414, + "speed": 415 + }, + "params": { + "p0": 24.066011428833008, + "q0": 4.852294921875, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 3517.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "4231_H_hygov", + "ports": { + "speed": 415, + "pmech": 413 + }, + "params": { + "Trate": 3517.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "4231_H_sexs_pti", + "ports": { + "bus": 4231, + "efd": 414 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "4232_G_genrou", + "ports": { + "bus": 4232, + "pmech": 416, + "efd": 417, + "speed": 418 + }, + "params": { + "p0": 3.482999801635742, + "q0": -0.03610236570239067, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 872.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "4232_G_gast_pti", + "ports": { + "pmech": 416, + "speed": 418 + }, + "params": { + "Trate": 872.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "4232_G_sexs_pti", + "ports": { + "bus": 4232, + "efd": 417 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "4232_H_genrou", + "ports": { + "bus": 4232, + "pmech": 419, + "efd": 420, + "speed": 421 + }, + "params": { + "p0": 2.2230000495910645, + "q0": -0.03610236570239067, + "H": 3.8399999141693115, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 558.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "4232_H_hygov", + "ports": { + "speed": 421, + "pmech": 419 + }, + "params": { + "Trate": 558.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "4232_H_sexs_pti", + "ports": { + "bus": 4232, + "efd": 420 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "4232_W_regca", + "ports": { + "bus": 4232, + "ipcmd": 422, + "iqcmd": 423, + "ibranchr": 424, + "ibranchi": 425, + "pbranch": 426, + "qbranch": 427 + }, + "params": { + "p0": 3.1679999828338623, + "q0": -0.03610236570239067, + "mva": 695.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "4232_W_reecb", + "ports": { + "bus": 4232, + "iqcmd": 423, + "ipcmd": 422, + "pe": 426, + "qgen": 427, + "qext": 428, + "pref": 429 + }, + "params": { + "mva": 695.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "4232_W_repca", + "ports": { + "bus": 4232, + "ir": 424, + "ii": 425, + "p": 426, + "q": 427, + "qext": 428, + "pext": 429 + }, + "params": { + "mva": 695.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "5031_G_genrou", + "ports": { + "bus": 5031, + "pmech": 430, + "efd": 431, + "speed": 432 + }, + "params": { + "p0": 8.217000007629395, + "q0": 5.343287467956543, + "H": 3.0799999237060547, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2650.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "5031_G_gast_pti", + "ports": { + "pmech": 430, + "speed": 432 + }, + "params": { + "Trate": 2650.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "5031_G_sexs_pti", + "ports": { + "bus": 5031, + "efd": 431 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "5031_H_genrou", + "ports": { + "bus": 5031, + "pmech": 433, + "efd": 434, + "speed": 435 + }, + "params": { + "p0": 59.7599983215332, + "q0": 5.343287467956543, + "H": 3.0799999237060547, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 10747.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "5031_H_hygov", + "ports": { + "speed": 435, + "pmech": 433 + }, + "params": { + "Trate": 10747.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "5031_H_sexs_pti", + "ports": { + "bus": 5031, + "efd": 434 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "5032_C_genrou", + "ports": { + "bus": 5032, + "pmech": 436, + "efd": 437, + "speed": 438 + }, + "params": { + "p0": 36.46800231933594, + "q0": 4.102795124053955, + "H": 3.0799999237060547, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 13039.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "5032_C_tgov1", + "ports": { + "speed": 438, + "pmech": 436 + }, + "params": { + "Trate": 13039.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "5032_C_sexs_pti", + "ports": { + "bus": 5032, + "efd": 437 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "5032_G_genrou", + "ports": { + "bus": 5032, + "pmech": 439, + "efd": 440, + "speed": 441 + }, + "params": { + "p0": 26.954999923706055, + "q0": 4.102795124053955, + "H": 3.0799999237060547, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 9636.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "5032_G_gast_pti", + "ports": { + "pmech": 439, + "speed": 441 + }, + "params": { + "Trate": 9636.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "5032_G_sexs_pti", + "ports": { + "bus": 5032, + "efd": 440 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "5032_R_genrou", + "ports": { + "bus": 5032, + "pmech": 442, + "efd": 443, + "speed": 444 + }, + "params": { + "p0": 0.6660000085830688, + "q0": 0.5400000214576721, + "H": 3.0799999237060547, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 108.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "5032_R_tgov1", + "ports": { + "speed": 444, + "pmech": 442 + }, + "params": { + "Trate": 108.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "5032_R_sexs_pti", + "ports": { + "bus": 5032, + "efd": 443 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "5032_S_regca", + "ports": { + "bus": 5032, + "ipcmd": 445, + "iqcmd": 446, + "ibranchr": 447, + "ibranchi": 448, + "pbranch": 449, + "qbranch": 450 + }, + "params": { + "p0": 27.01799964904785, + "q0": 4.102795124053955, + "mva": 4410.2001953125, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "5032_S_reecb", + "ports": { + "bus": 5032, + "iqcmd": 446, + "ipcmd": 445, + "pe": 449, + "qgen": 450, + "qext": 451, + "pref": 452 + }, + "params": { + "mva": 4410.2001953125, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "5032_S_repca", + "ports": { + "bus": 5032, + "ir": 447, + "ii": 448, + "p": 449, + "q": 450, + "qext": 451, + "pext": 452 + }, + "params": { + "mva": 4410.2001953125, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Regca", + "id": "5032_W_regca", + "ports": { + "bus": 5032, + "ipcmd": 453, + "iqcmd": 454, + "ibranchr": 455, + "ibranchi": 456, + "pbranch": 457, + "qbranch": 458 + }, + "params": { + "p0": 3.312000036239624, + "q0": 2.7100000381469727, + "mva": 541.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "5032_W_reecb", + "ports": { + "bus": 5032, + "iqcmd": 454, + "ipcmd": 453, + "pe": 457, + "qgen": 458, + "qext": 459, + "pref": 460 + }, + "params": { + "mva": 541.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "5032_W_repca", + "ports": { + "bus": 5032, + "ir": 455, + "ii": 456, + "p": 457, + "q": 458, + "qext": 459, + "pext": 460 + }, + "params": { + "mva": 541.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "6132_B_genrou", + "ports": { + "bus": 6132, + "pmech": 461, + "efd": 462, + "speed": 463 + }, + "params": { + "p0": 0.44999998807907104, + "q0": -0.20000000298023224, + "H": 2.1500000953674316, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 122.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "6132_B_tgov1", + "ports": { + "speed": 463, + "pmech": 461 + }, + "params": { + "Trate": 122.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "6132_B_sexs_pti", + "ports": { + "bus": 6132, + "efd": 462 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "6132_G_genrou", + "ports": { + "bus": 6132, + "pmech": 464, + "efd": 465, + "speed": 466 + }, + "params": { + "p0": 10.430999755859375, + "q0": -1.4700000286102295, + "H": 2.1500000953674316, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1272.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "6132_G_gast_pti", + "ports": { + "pmech": 464, + "speed": 466 + }, + "params": { + "Trate": 1272.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "6132_G_sexs_pti", + "ports": { + "bus": 6132, + "efd": 465 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "6132_H_genrou", + "ports": { + "bus": 6132, + "pmech": 467, + "efd": 468, + "speed": 469 + }, + "params": { + "p0": 19.925989151000977, + "q0": -3.874419689178467, + "H": 2.1500000953674316, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2541.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "6132_H_hygov", + "ports": { + "speed": 469, + "pmech": 467 + }, + "params": { + "Trate": 2541.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "6132_H_sexs_pti", + "ports": { + "bus": 6132, + "efd": 468 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "6132_S_regca", + "ports": { + "bus": 6132, + "ipcmd": 470, + "iqcmd": 471, + "ibranchr": 472, + "ibranchi": 473, + "pbranch": 474, + "qbranch": 475 + }, + "params": { + "p0": 1.7999999523162842, + "q0": -0.75, + "mva": 395.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "6132_S_reecb", + "ports": { + "bus": 6132, + "iqcmd": 471, + "ipcmd": 470, + "pe": 474, + "qgen": 475, + "qext": 476, + "pref": 477 + }, + "params": { + "mva": 395.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "6132_S_repca", + "ports": { + "bus": 6132, + "ir": 472, + "ii": 473, + "p": 474, + "q": 475, + "qext": 476, + "pext": 477 + }, + "params": { + "mva": 395.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Regca", + "id": "6132_W_regca", + "ports": { + "bus": 6132, + "ipcmd": 478, + "iqcmd": 479, + "ibranchr": 480, + "ibranchi": 481, + "pbranch": 482, + "qbranch": 483 + }, + "params": { + "p0": 5.031000137329102, + "q0": -2.0999999046325684, + "mva": 973.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "6132_W_reecb", + "ports": { + "bus": 6132, + "iqcmd": 479, + "ipcmd": 478, + "pe": 482, + "qgen": 483, + "qext": 484, + "pref": 485 + }, + "params": { + "mva": 973.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "6132_W_repca", + "ports": { + "bus": 6132, + "ir": 480, + "ii": 481, + "p": 482, + "q": 483, + "qext": 484, + "pext": 485 + }, + "params": { + "mva": 973.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "6231_C_genrou", + "ports": { + "bus": 6231, + "pmech": 486, + "efd": 487, + "speed": 488 + }, + "params": { + "p0": 7.05150032043457, + "q0": -1.0408563613891602, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2488.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "6231_C_tgov1", + "ports": { + "speed": 488, + "pmech": 486 + }, + "params": { + "Trate": 2488.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "6231_C_sexs_pti", + "ports": { + "bus": 6231, + "efd": 487 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "6231_G_genrou", + "ports": { + "bus": 6231, + "pmech": 489, + "efd": 490, + "speed": 491 + }, + "params": { + "p0": 2.25, + "q0": -0.699999988079071, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 250.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "6231_G_gast_pti", + "ports": { + "pmech": 489, + "speed": 491 + }, + "params": { + "Trate": 250.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "6231_G_sexs_pti", + "ports": { + "bus": 6231, + "efd": 490 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "6235_G_genrou", + "ports": { + "bus": 6235, + "pmech": 492, + "efd": 493, + "speed": 494 + }, + "params": { + "p0": 0.8999999761581421, + "q0": 0.49768951535224915, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 226.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "6235_G_gast_pti", + "ports": { + "pmech": 492, + "speed": 494 + }, + "params": { + "Trate": 226.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "6235_G_sexs_pti", + "ports": { + "bus": 6235, + "efd": 493 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "6235_H_genrou", + "ports": { + "bus": 6235, + "pmech": 495, + "efd": 496, + "speed": 497 + }, + "params": { + "p0": 10.404000282287598, + "q0": 0.49768951535224915, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 2671.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "6235_H_hygov", + "ports": { + "speed": 497, + "pmech": 495 + }, + "params": { + "Trate": 2671.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "6235_H_sexs_pti", + "ports": { + "bus": 6235, + "vs": 498, + "efd": 496 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Ieeest", + "id": "6235_H_ieeest", + "ports": { + "input": 497, + "output": 498 + }, + "params": { + "A1": 1.0130000114440918, + "A2": 0.013000000268220901, + "A3": 0.0, + "A4": 0.0, + "A5": 1.0130000114440918, + "A6": 0.11299999803304672, + "T1": 10.0, + "T2": 0.019999999552965164, + "T3": 0.0, + "T4": 0.0, + "T5": 1.649999976158142, + "T6": 1.649999976158142, + "Ks": 3.0, + "Lsmin": -0.10000000149011612, + "Lsmax": 0.10000000149011612, + "Vcl": 0.0, + "Vcu": 0.0, + "Tdelay": 0.0 + } + }, + { + "class": "Regca", + "id": "6235_W_regca", + "ports": { + "bus": 6235, + "ipcmd": 499, + "iqcmd": 500, + "ibranchr": 501, + "ibranchi": 502, + "pbranch": 503, + "qbranch": 504 + }, + "params": { + "p0": 2.807999849319458, + "q0": 0.49768951535224915, + "mva": 720.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "6235_W_reecb", + "ports": { + "bus": 6235, + "iqcmd": 500, + "ipcmd": 499, + "pe": 503, + "qgen": 504, + "qext": 505, + "pref": 506 + }, + "params": { + "mva": 720.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "6235_W_repca", + "ports": { + "bus": 6235, + "ir": 501, + "ii": 502, + "p": 503, + "q": 504, + "qext": 505, + "pext": 506 + }, + "params": { + "mva": 720.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "6333_C_genrou", + "ports": { + "bus": 6333, + "pmech": 507, + "efd": 508, + "speed": 509 + }, + "params": { + "p0": 28.376998901367188, + "q0": 3.3057680130004883, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 4594.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "6333_C_tgov1", + "ports": { + "speed": 509, + "pmech": 507 + }, + "params": { + "Trate": 4594.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "6333_C_sexs_pti", + "ports": { + "bus": 6333, + "efd": 508 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "6333_W_regca", + "ports": { + "bus": 6333, + "ipcmd": 510, + "iqcmd": 511, + "ibranchr": 512, + "ibranchi": 513, + "pbranch": 514, + "qbranch": 515 + }, + "params": { + "p0": 9.197999954223633, + "q0": 3.3057680130004883, + "mva": 1489.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "6333_W_reecb", + "ports": { + "bus": 6333, + "iqcmd": 511, + "ipcmd": 510, + "pe": 514, + "qgen": 515, + "qext": 516, + "pref": 517 + }, + "params": { + "mva": 1489.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "6333_W_repca", + "ports": { + "bus": 6333, + "ir": 512, + "ii": 513, + "p": 514, + "q": 515, + "qext": 516, + "pext": 517 + }, + "params": { + "mva": 1489.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "6335_C_genrou", + "ports": { + "bus": 6335, + "pmech": 518, + "efd": 519, + "speed": 520 + }, + "params": { + "p0": 22.743000030517578, + "q0": 2.6057565212249756, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 3000.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "6335_C_tgov1", + "ports": { + "speed": 520, + "pmech": 518 + }, + "params": { + "Trate": 3000.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "6335_C_sexs_pti", + "ports": { + "bus": 6335, + "efd": 519 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "6335_G_genrou", + "ports": { + "bus": 6335, + "pmech": 521, + "efd": 522, + "speed": 523 + }, + "params": { + "p0": 2.952000141143799, + "q0": 2.6057565212249756, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 418.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "6335_G_gast_pti", + "ports": { + "pmech": 521, + "speed": 523 + }, + "params": { + "Trate": 418.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "6335_G_sexs_pti", + "ports": { + "bus": 6335, + "efd": 522 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "6335_H_genrou", + "ports": { + "bus": 6335, + "pmech": 524, + "efd": 525, + "speed": 526 + }, + "params": { + "p0": 2.5920000076293945, + "q0": 2.6057565212249756, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 400.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "6335_H_hygov", + "ports": { + "speed": 526, + "pmech": 524 + }, + "params": { + "Trate": 400.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "6335_H_sexs_pti", + "ports": { + "bus": 6335, + "efd": 525 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "6433_C_genrou", + "ports": { + "bus": 6433, + "pmech": 527, + "efd": 528, + "speed": 529 + }, + "params": { + "p0": 1.940000057220459, + "q0": 0.7455121278762817, + "H": 2.7899999618530273, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 391.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "6433_C_tgov1", + "ports": { + "speed": 529, + "pmech": 527 + }, + "params": { + "Trate": 391.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "6433_C_sexs_pti", + "ports": { + "bus": 6433, + "efd": 528 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "6433_E_genrou", + "ports": { + "bus": 6433, + "pmech": 530, + "efd": 531, + "speed": 532 + }, + "params": { + "p0": 3.7200000286102295, + "q0": 0.5899999737739563, + "H": 2.7899999618530273, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 751.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "6433_E_tgov1", + "ports": { + "speed": 532, + "pmech": 530 + }, + "params": { + "Trate": 751.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "6433_E_sexs_pti", + "ports": { + "bus": 6433, + "efd": 531 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "6433_G_genrou", + "ports": { + "bus": 6433, + "pmech": 533, + "efd": 534, + "speed": 535 + }, + "params": { + "p0": 6.789999961853027, + "q0": 0.7455121278762817, + "H": 2.7899999618530273, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1369.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "6433_G_gast_pti", + "ports": { + "pmech": 533, + "speed": 535 + }, + "params": { + "Trate": 1369.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "6433_G_sexs_pti", + "ports": { + "bus": 6433, + "efd": 534 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "6433_W_regca", + "ports": { + "bus": 6433, + "ipcmd": 536, + "iqcmd": 537, + "ibranchr": 538, + "ibranchi": 539, + "pbranch": 540, + "qbranch": 541 + }, + "params": { + "p0": 0.75, + "q0": 0.5, + "mva": 152.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "6433_W_reecb", + "ports": { + "bus": 6433, + "iqcmd": 537, + "ipcmd": 536, + "pe": 540, + "qgen": 541, + "qext": 542, + "pref": 543 + }, + "params": { + "mva": 152.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "6433_W_repca", + "ports": { + "bus": 6433, + "ir": 538, + "ii": 539, + "p": 540, + "q": 541, + "qext": 542, + "pext": 543 + }, + "params": { + "mva": 152.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "6533_C_genrou", + "ports": { + "bus": 6533, + "pmech": 544, + "efd": 545, + "speed": 546 + }, + "params": { + "p0": 13.185009956359863, + "q0": 0.7873455882072449, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 3276.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "6533_C_tgov1", + "ports": { + "speed": 546, + "pmech": 544 + }, + "params": { + "Trate": 3276.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "6533_C_sexs_pti", + "ports": { + "bus": 6533, + "vs": 547, + "efd": 545 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Ieeest", + "id": "6533_C_ieeest", + "ports": { + "input": 546, + "output": 547 + }, + "params": { + "A1": 1.0130000114440918, + "A2": 0.013000000268220901, + "A3": 0.0, + "A4": 0.0, + "A5": 1.0130000114440918, + "A6": 0.11299999803304672, + "T1": 7.0, + "T2": 0.019999999552965164, + "T3": 0.0, + "T4": 0.0, + "T5": 1.649999976158142, + "T6": 1.649999976158142, + "Ks": 3.0, + "Lsmin": -0.10000000149011612, + "Lsmax": 0.10000000149011612, + "Vcl": 0.0, + "Vcu": 0.0, + "Tdelay": 0.0 + } + }, + { + "class": "Genrou", + "id": "6533_G_genrou", + "ports": { + "bus": 6533, + "pmech": 548, + "efd": 549, + "speed": 550 + }, + "params": { + "p0": 12.132010459899902, + "q0": 0.7873455882072449, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 3239.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "6533_G_gast_pti", + "ports": { + "pmech": 548, + "speed": 550 + }, + "params": { + "Trate": 3239.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "6533_G_sexs_pti", + "ports": { + "bus": 6533, + "efd": 549 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "6533_H_genrou", + "ports": { + "bus": 6533, + "pmech": 551, + "efd": 552, + "speed": 553 + }, + "params": { + "p0": 0.8999999761581421, + "q0": 0.75, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 275.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "6533_H_hygov", + "ports": { + "speed": 553, + "pmech": 551 + }, + "params": { + "Trate": 275.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "6533_H_sexs_pti", + "ports": { + "bus": 6533, + "efd": 552 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "6533_S_regca", + "ports": { + "bus": 6533, + "ipcmd": 554, + "iqcmd": 555, + "ibranchr": 556, + "ibranchi": 557, + "pbranch": 558, + "qbranch": 559 + }, + "params": { + "p0": 5.660999774932861, + "q0": 0.7873455882072449, + "mva": 1407.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "6533_S_reecb", + "ports": { + "bus": 6533, + "iqcmd": 555, + "ipcmd": 554, + "pe": 558, + "qgen": 559, + "qext": 560, + "pref": 561 + }, + "params": { + "mva": 1407.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "6533_S_repca", + "ports": { + "bus": 6533, + "ir": 556, + "ii": 557, + "p": 558, + "q": 559, + "qext": 560, + "pext": 561 + }, + "params": { + "mva": 1407.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Regca", + "id": "6533_W_regca", + "ports": { + "bus": 6533, + "ipcmd": 562, + "iqcmd": 563, + "ibranchr": 564, + "ibranchi": 565, + "pbranch": 566, + "qbranch": 567 + }, + "params": { + "p0": 1.5750000476837158, + "q0": 0.20000000298023224, + "mva": 391.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "6533_W_reecb", + "ports": { + "bus": 6533, + "iqcmd": 563, + "ipcmd": 562, + "pe": 566, + "qgen": 567, + "qext": 568, + "pref": 569 + }, + "params": { + "mva": 391.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "6533_W_repca", + "ports": { + "bus": 6533, + "ir": 564, + "ii": 565, + "p": 566, + "q": 567, + "qext": 568, + "pext": 569 + }, + "params": { + "mva": 391.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "7031_C_genrou", + "ports": { + "bus": 7031, + "pmech": 570, + "efd": 571, + "speed": 572 + }, + "params": { + "p0": 11.051989555358887, + "q0": 3.80609130859375, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 3127.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "7031_C_tgov1", + "ports": { + "speed": 572, + "pmech": 570 + }, + "params": { + "Trate": 3127.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "7031_C_sexs_pti", + "ports": { + "bus": 7031, + "efd": 571 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "7031_G_genrou", + "ports": { + "bus": 7031, + "pmech": 573, + "efd": 574, + "speed": 575 + }, + "params": { + "p0": 22.428020477294922, + "q0": 3.80609130859375, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 6346.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "7031_G_gast_pti", + "ports": { + "pmech": 573, + "speed": 575 + }, + "params": { + "Trate": 6346.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "7031_G_sexs_pti", + "ports": { + "bus": 7031, + "vs": 576, + "efd": 574 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Ieeest", + "id": "7031_G_ieeest", + "ports": { + "input": 575, + "output": 576 + }, + "params": { + "A1": 1.0130000114440918, + "A2": 0.013000000268220901, + "A3": 0.0, + "A4": 0.0, + "A5": 1.0130000114440918, + "A6": 0.11299999803304672, + "T1": 7.0, + "T2": 0.019999999552965164, + "T3": 0.0, + "T4": 0.0, + "T5": 1.649999976158142, + "T6": 1.649999976158142, + "Ks": 3.0, + "Lsmin": -0.10000000149011612, + "Lsmax": 0.10000000149011612, + "Vcl": 0.0, + "Vcu": 0.0, + "Tdelay": 0.0 + } + }, + { + "class": "Genrou", + "id": "7031_P_genrou", + "ports": { + "bus": 7031, + "pmech": 577, + "efd": 578, + "speed": 579 + }, + "params": { + "p0": 1.2330000400543213, + "q0": 1.75, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 509.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "7031_P_tgov1", + "ports": { + "speed": 579, + "pmech": 577 + }, + "params": { + "Trate": 509.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "7031_P_sexs_pti", + "ports": { + "bus": 7031, + "efd": 578 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "7031_W_regca", + "ports": { + "bus": 7031, + "ipcmd": 580, + "iqcmd": 581, + "ibranchr": 582, + "ibranchi": 583, + "pbranch": 584, + "qbranch": 585 + }, + "params": { + "p0": 10.979999542236328, + "q0": 3.80609130859375, + "mva": 3106.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "7031_W_reecb", + "ports": { + "bus": 7031, + "iqcmd": 581, + "ipcmd": 580, + "pe": 584, + "qgen": 585, + "qext": 586, + "pref": 587 + }, + "params": { + "mva": 3106.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "7031_W_repca", + "ports": { + "bus": 7031, + "ir": 582, + "ii": 583, + "p": 584, + "q": 585, + "qext": 586, + "pext": 587 + }, + "params": { + "mva": 3106.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "7032_C_genrou", + "ports": { + "bus": 7032, + "pmech": 588, + "efd": 589, + "speed": 590 + }, + "params": { + "p0": 10.574999809265137, + "q0": 0.22011247277259827, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1821.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Tgov1", + "id": "7032_C_tgov1", + "ports": { + "speed": 590, + "pmech": 588 + }, + "params": { + "Trate": 1821.0, + "R": 0.07999999821186066, + "T1": 2.0, + "T2": 3.0, + "T3": 15.0, + "Pvmax": 1.0, + "Pvmin": 0.0, + "Dt": 0.4000000059604645 + } + }, + { + "class": "SexsPti", + "id": "7032_C_sexs_pti", + "ports": { + "bus": 7032, + "efd": 589 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "7032_G_genrou", + "ports": { + "bus": 7032, + "pmech": 591, + "efd": 592, + "speed": 593 + }, + "params": { + "p0": 8.61299991607666, + "q0": 0.22011247277259827, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1483.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "7032_G_gast_pti", + "ports": { + "pmech": 591, + "speed": 593 + }, + "params": { + "Trate": 1483.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "7032_G_sexs_pti", + "ports": { + "bus": 7032, + "efd": 592 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "7032_H_genrou", + "ports": { + "bus": 7032, + "pmech": 594, + "efd": 595, + "speed": 596 + }, + "params": { + "p0": 3.9060001373291016, + "q0": 0.22011247277259827, + "H": 2.869999885559082, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 672.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "7032_H_hygov", + "ports": { + "speed": 596, + "pmech": 594 + }, + "params": { + "Trate": 672.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "7032_H_sexs_pti", + "ports": { + "bus": 7032, + "efd": 595 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Regca", + "id": "7032_S_regca", + "ports": { + "bus": 7032, + "ipcmd": 597, + "iqcmd": 598, + "ibranchr": 599, + "ibranchi": 600, + "pbranch": 601, + "qbranch": 602 + }, + "params": { + "p0": 4.283999919891357, + "q0": 0.22011247277259827, + "mva": 738.0, + "Tg": 0.019999999552965164, + "TM": 0.019999999552965164, + "Rqmax": 100.0, + "Rqmin": -100.0, + "Rpmax": 10.0, + "sL": true, + "IL1": 1.2200000286102295, + "VL0": 0.4000000059604645, + "VL1": 0.8999999761581421, + "VA0": 0.5, + "VA1": 0.8999999761581421, + "Vhvmax": 1.2000000476837158, + "Qmin": -1.2999999523162842, + "Khv": 0.0, + "Xe": 0.0 + } + }, + { + "class": "Reecb", + "id": "7032_S_reecb", + "ports": { + "bus": 7032, + "iqcmd": 598, + "ipcmd": 597, + "pe": 601, + "qgen": 602, + "qext": 603, + "pref": 604 + }, + "params": { + "mva": 738.0, + "PfFlag": false, + "VFlag": true, + "QFlag": false, + "Pqflag": false, + "Trv": 0.019999999552965164, + "Tp": 0.05000000074505806, + "Vdip": -99.0, + "Vup": 99.0, + "dbd1": 0.0, + "dbd2": 0.0, + "kqv": 0.0, + "Iql1": -1.100000023841858, + "Iqh1": 1.100000023841858, + "Qmax": 0.4399999976158142, + "Qmin": -0.4399999976158142, + "Kqp": 0.0, + "Kqi": 0.009999999776482582, + "Vmax": 1.0499999523162842, + "Vmin": 0.8999999761581421, + "Kvp": 10.0, + "Kvi": 60.0, + "Tiq": 0.019999999552965164, + "Tpord": 0.019999999552965164, + "dPmax": 99.0, + "dPmin": -99.0, + "Pmax": 1.0, + "Pmin": 0.0, + "Imax": 1.1100000143051147 + } + }, + { + "class": "Repca", + "id": "7032_S_repca", + "ports": { + "bus": 7032, + "ir": 599, + "ii": 600, + "p": 601, + "q": 602, + "qext": 603, + "pext": 604 + }, + "params": { + "mva": 738.0, + "VcompFlag": false, + "RefFlag": false, + "Freqflag": true, + "Tfltr": 0.019999999552965164, + "Vfrz": 0.0, + "Rc": 0.0, + "Xc": 0.0, + "Kc": 0.019999999552965164, + "dbdlow": -1.0, + "dbdupper": 1.0, + "emax": 0.10000000149011612, + "emin": -0.10000000149011612, + "Kp": 18.0, + "Ki": 5.0, + "Qmax": 0.4300000071525574, + "Qmin": -0.4300000071525574, + "Tft": 0.0, + "Tfv": 0.05000000074505806, + "Tp": 0.25, + "fdbd1": -1.0, + "fdbd2": 1.0, + "Ddn": 0.0, + "Dup": 0.0, + "femax": 99.0, + "femin": -99.0, + "Kpg": 1.0, + "Kig": 0.05000000074505806, + "Pmax": 1.0, + "Pmin": 0.0, + "Tlag": 0.10000000149011612 + } + }, + { + "class": "Genrou", + "id": "8033_H_genrou", + "ports": { + "bus": 8033, + "pmech": 605, + "efd": 606, + "speed": 607 + }, + "params": { + "p0": 11.819999694824219, + "q0": 2.597295045852661, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 1394.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "8033_H_hygov", + "ports": { + "speed": 607, + "pmech": 605 + }, + "params": { + "Trate": 1394.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "8033_H_sexs_pti", + "ports": { + "bus": 8033, + "efd": 606 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Genrou", + "id": "8034_G_genrou", + "ports": { + "bus": 8034, + "pmech": 608, + "efd": 609, + "speed": 610 + }, + "params": { + "p0": 29.459999084472656, + "q0": 2.3936679363250732, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 3754.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "GastPti", + "id": "8034_G_gast_pti", + "ports": { + "pmech": 608, + "speed": 610 + }, + "params": { + "Trate": 3754.0, + "R": 0.07999999821186066, + "T1": 0.30000001192092896, + "T2": 0.30000001192092896, + "T3": 3.0, + "At": 1.0, + "Kt": 2.0, + "Vmax": 1.0, + "Vmin": 0.0, + "Dturb": 0.0 + } + }, + { + "class": "SexsPti", + "id": "8034_G_sexs_pti", + "ports": { + "bus": 8034, + "vs": 611, + "efd": 609 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + }, + { + "class": "Ieeest", + "id": "8034_G_ieeest", + "ports": { + "input": 610, + "output": 611 + }, + "params": { + "A1": 1.0130000114440918, + "A2": 0.013000000268220901, + "A3": 0.0, + "A4": 0.0, + "A5": 1.0130000114440918, + "A6": 0.11299999803304672, + "T1": 3.0, + "T2": 0.019999999552965164, + "T3": 0.0, + "T4": 0.0, + "T5": 1.649999976158142, + "T6": 1.649999976158142, + "Ks": 3.0, + "Lsmin": -0.10000000149011612, + "Lsmax": 0.10000000149011612, + "Vcl": 0.0, + "Vcu": 0.0, + "Tdelay": 0.0 + } + }, + { + "class": "Genrou", + "id": "8034_H_genrou", + "ports": { + "bus": 8034, + "pmech": 612, + "efd": 613, + "speed": 614 + }, + "params": { + "p0": 4.269999980926514, + "q0": 2.3936679363250732, + "H": 3.6600000858306885, + "D": 0.0, + "Ra": 0.0, + "Tdop": 6.0, + "Tdopp": 0.5, + "Tqop": 1.0, + "Tqopp": 0.05000000074505806, + "Xd": 1.399999976158142, + "Xdp": 0.30000001192092896, + "Xdpp": 0.20000000298023224, + "Xq": 1.350000023841858, + "Xqp": 0.6000000238418579, + "Xqpp": 0.20000000298023224, + "Xl": 0.10000000149011612, + "S10": 0.029999999329447746, + "S12": 0.4000000059604645, + "mva": 544.0 + }, + "mon": [ + "omega" + ] + }, + { + "class": "Hygov", + "id": "8034_H_hygov", + "ports": { + "speed": 614, + "pmech": 612 + }, + "params": { + "Trate": 544.0, + "Rperm": 0.05000000074505806, + "Rtemp": 0.07500000298023224, + "Tr": 12.0, + "Tf": 0.5, + "Tg": 20.5, + "Velm": 0.10000000149011612, + "Gmax": 1.0, + "Gmin": 0.0, + "Tw": 15.0, + "At": 1.5, + "Dturb": 0.0, + "Qnl": 0.07999999821186066, + "Tn": 0.0, + "Tnp": 0.0, + "db1": 0.0, + "db2": 0.0, + "Hdam": 1.0 + } + }, + { + "class": "SexsPti", + "id": "8034_H_sexs_pti", + "ports": { + "bus": 8034, + "efd": 613 + }, + "params": { + "Ta": 1.0000000149011612, + "Tb": 10.0, + "Te": 0.10000000149011612, + "K": 100.0, + "Efdmax": 3.0, + "Efdmin": 0.0 + } + } + ] +} diff --git a/crates/latkit-cli/examples/wecc240-fault/verification.json b/crates/latkit-cli/examples/wecc240-fault/verification.json new file mode 100644 index 00000000..b7c2879b --- /dev/null +++ b/crates/latkit-cli/examples/wecc240-fault/verification.json @@ -0,0 +1,22 @@ +{ + "file": "animation.mp4", + "sha256": "cafe2f8bfbeb7187b22cdd7a35af136cad7d53a2f43aa5f877b86cabde7d987c", + "decoder": "7.1-essentials_build-www.gyan.dev built with gcc 14.2.0 (Rev1, Built by MSYS2 project)", + "codec": "h264", + "resolution": [ + 1920, + 1080 + ], + "fps": 60.0, + "decoded_frames": 1561, + "duration_seconds": 26.016666666666666, + "decode_errors": 0, + "inspected_frame_indices": [ + 0, + 250, + 329, + 340, + 960, + 1560 + ] +} diff --git a/crates/latkit-cli/src/args.rs b/crates/latkit-cli/src/args.rs new file mode 100644 index 00000000..908aebe1 --- /dev/null +++ b/crates/latkit-cli/src/args.rs @@ -0,0 +1,416 @@ +//! The command line: what `render`, `validate`, `inspect`, `query`, `tile`, and `schema` take, and the +//! checks that fail as usage errors before anything is read. + +use std::path::{Path, PathBuf}; +use std::time::Duration; + +use clap::{Args, CommandFactory, Parser, Subcommand, ValueEnum, error::ErrorKind}; +use latkit::{ImageFormat, Pixels, Shot}; + +#[derive(Parser)] +#[command(name = "latkit", version, about = "Render scenes of JSON or binary data to images and videos")] +pub(crate) struct Cli { + /// Diagnostics on stderr: errors, and progress while rendering; JSON is one object a line + #[arg(long, global = true, value_enum, default_value = "human")] + pub(crate) diagnostics: Diagnostics, + #[command(subcommand)] + pub(crate) command: Command, +} + +#[derive(Clone, Copy, PartialEq, Eq, ValueEnum)] +pub(crate) enum Diagnostics { + Human, + Json, +} + +#[derive(Subcommand)] +pub(crate) enum Command { + /// Draw scenes of datasets into an image, image sequence, raw frames, or a video + Render(Job), + /// Check everything render reads, frames included, without a GPU + Validate(Job), + /// Describe datasets as JSON: tables, rows, fields and their kinds, the axis and its span + Inspect { + /// Dataset files, each [NAME=]FILE; - reads stdin + #[arg(required = true, value_name = "[NAME=]FILE")] + data: Vec, + /// The longest a dataset may take to load, in seconds + #[arg(long, default_value = "30", value_parser = deadline)] + deadline: Duration, + }, + /// Print the JSON Schema of what latkit reads: every input, or one of them + Schema { + /// One input's schema + #[arg(value_enum)] + input: Option, + }, + /// Read rows back as JSON Lines, an object a row: those a query keeps, sorted and paged + Query { + /// The dataset, [NAME=]FILE; - reads stdin + #[arg(value_name = "[NAME=]FILE")] + data: Source, + /// The query: JSON such as {"of":"Branch","filter":{"op":"gt","args":["loading",90]}}, or a + /// file of it + #[arg(value_name = "QUERY")] + query: String, + /// The longest the dataset may take to load, in seconds + #[arg(long, default_value = "30", value_parser = deadline)] + deadline: Duration, + }, + /// Write a dataset as time tiles: frames.json, which --tiles opens, the dataset without its + /// sampled fields' histories, and their spans at every level of detail + Tile { + /// The dataset, [NAME=]FILE; - reads stdin + #[arg(value_name = "[NAME=]FILE")] + data: Source, + /// The directory the tiles go in + #[arg(short, long, value_name = "DIR")] + output: PathBuf, + /// Entries a span holds: frames, or buckets of a level of detail; a multiple of 8 + #[arg(long, default_value = "256")] + chunk: u32, + /// The longest the dataset may take to load, in seconds + #[arg(long, default_value = "30", value_parser = deadline)] + deadline: Duration, + }, +} + +/// What a render draws and where it goes. +#[derive(Args)] +pub(crate) struct Job { + /// Scene JSON files, one per panel; - reads stdin + #[arg(required = true, value_name = "SCENE")] + pub(crate) scenes: Vec, + /// A dataset: JSON document, latkit bytes, or GeoJSON (which needs a NAME); NAME= renames it + #[arg(short, long, value_name = "[NAME=]FILE")] + pub(crate) data: Vec, + /// Tiles every view fetches as dataset NAME: time tiles' frames.json, or vector tiles' PMTiles + /// file, TileJSON, or {z}/{x}/{y} template + #[arg(long, value_name = "NAME=FILE")] + pub(crate) tiles: Vec, + /// Image file, %d pattern for an image sequence, or - for stdout + #[arg(short, long, value_name = "FILE")] + pub(crate) output: Option, + /// What to write; otherwise the output's extension says, or PNG for stdout + #[arg(long, value_enum)] + pub(crate) format: Option, + /// A JPEG's quality, from 1, smallest, to 100, sharpest + #[arg(long, default_value = "90", value_parser = clap::value_parser!(u8).range(1..=100))] + pub(crate) quality: u8, + /// The picture's width and height in pixels, such as 1920x1080 + #[arg(long, default_value = "1600x900", value_parser = size)] + pub(crate) size: [u32; 2], + /// Pixels per CSS pixel: views lay out size / scale CSS pixels, so 2 draws twice as sharp + #[arg(long, default_value = "1", value_parser = positive)] + pub(crate) scale: f32, + /// A scene's panel of the picture, X,Y,WIDTH,HEIGHT as fractions; one per scene, in order + #[arg(long, value_name = "X,Y,W,H", value_parser = panel)] + pub(crate) panel: Vec<[f32; 4]>, + /// Keep alpha where the themes' backgrounds would be + #[arg(long)] + pub(crate) transparent: bool, + /// The longest a picture, or a video frame, may take, in seconds + #[arg(long, default_value = "30", value_parser = deadline)] + pub(crate) deadline: Duration, + /// TTF/OTF/TTC file; repeat for fallbacks; replaces system fonts + #[arg(long, value_name = "FILE")] + pub(crate) font: Vec, + /// Camera JSON for a scene, in scene order; a view without one fits + #[arg(long, value_name = "FILE")] + pub(crate) camera: Vec, + /// What a view without a camera frames: "all", or a fit as JSON + #[arg(long, default_value = "all", value_name = "FIT")] + pub(crate) fit: String, + /// CSS pixels kept clear at the top, right, bottom, and left, T,R,B,L + #[arg(long, value_name = "T,R,B,L", value_parser = insets)] + pub(crate) insets: Option<[f32; 4]>, + /// The axis coordinate shown; sampled fields read their last frame at or before it + #[arg(long, value_parser = finite, allow_hyphen_values = true)] + pub(crate) at: Option, + /// A still's effect time in seconds, where elapsed time and flowing comets read it + #[arg(long, value_parser = seconds, conflicts_with = "frames")] + pub(crate) elapsed: Option, + /// Frames as JSON Lines, one per output frame, or - for stdin + #[arg(long, value_name = "FILE")] + pub(crate) frames: Option, + /// Output frames a second + #[arg(long, default_value = "60", value_parser = fps)] + pub(crate) fps: f64, + /// MP4 bits a second; about 0.15 bits a pixel a frame otherwise + #[arg(long, value_parser = clap::value_parser!(u32).range(1..))] + pub(crate) bitrate: Option, +} + +/// An input `schema` describes. +#[derive(Clone, Copy, PartialEq, Eq, Debug, ValueEnum)] +pub(crate) enum Input { + /// A scene + Scene, + /// A dataset's JSON document + Data, + /// A patch's JSON + Patch, + /// A query of `latkit query` + Query, + /// A camera of `--camera` + Camera, + /// A fit of `--fit` + Fit, + /// A line of `--frames` + Frames, +} + +/// What an output is. +#[derive(Clone, Copy, PartialEq, Eq, ValueEnum)] +pub(crate) enum Format { + /// PNG, lossless with alpha: one picture, or one a frame where the output has a %d pattern + Png, + /// JPEG at --quality, its alpha dropped: one picture, or one a frame + Jpeg, + /// WebP, lossless with alpha: one picture, or one a frame + Webp, + /// Raw RGBA, straight alpha, frames back to back + Rgba, + /// YUV4MPEG2: 4:2:0 BT.709 limited range, for any encoder + Y4m, + /// H.264 in fragmented MP4, from the platform's encoder + Mp4, +} + +/// A dataset or tiles argument: `[NAME=]FILE`. +#[derive(Clone, Debug)] +pub(crate) struct Source { + pub(crate) name: Option, + pub(crate) path: PathBuf, +} + +impl std::str::FromStr for Source { + type Err = String; + fn from_str(value: &str) -> Result { + let named = value.split_once('=').filter(|(name, _)| { + !name.is_empty() && name.chars().all(|c| c.is_alphanumeric() || matches!(c, '_' | '-' | '.')) + }); + Ok(match named { + Some((name, path)) if !path.is_empty() => Source { name: Some(name.into()), path: path.into() }, + Some(_) => return Err("NAME= names a file".into()), + None => Source { name: None, path: value.into() }, + }) + } +} + +impl Format { + /// The bytes its pictures compose into. + pub(crate) fn pixels(self) -> Pixels { + match self { + Format::Mp4 | Format::Y4m => Pixels::Nv12, + Format::Png | Format::Jpeg | Format::Webp | Format::Rgba => Pixels::Rgba, + } + } + + /// The image file it writes, at `quality` for a JPEG; `None` for raw frames and video. + pub(crate) fn image(self, quality: u8) -> Option { + match self { + Format::Png => Some(ImageFormat::Png), + Format::Jpeg => Some(ImageFormat::Jpeg { quality }), + Format::Webp => Some(ImageFormat::WebP), + Format::Rgba | Format::Y4m | Format::Mp4 => None, + } + } +} + +impl Job { + /// What the output is: `--format`, else its extension, else PNG. + pub(crate) fn format(&self) -> Format { + self.format.unwrap_or_else(|| { + let extension = self.output.as_deref().and_then(Path::extension).and_then(|e| e.to_str()); + match extension.map(str::to_ascii_lowercase).as_deref() { + Some("mp4") => Format::Mp4, + Some("y4m") => Format::Y4m, + Some("rgba") => Format::Rgba, + Some("jpg" | "jpeg") => Format::Jpeg, + Some("webp") => Format::Webp, + _ => Format::Png, + } + }) + } + + /// The picture the job takes: its size, scale, panels, alpha, and deadline. + pub(crate) fn shot(&self) -> Shot { + let shot = Shot::new(self.size).scale(self.scale).deadline(self.deadline).panels(self.panel.clone()); + if self.transparent { shot.transparent() } else { shot } + } + + /// Whether the output names one file a frame: a `%d` or `%0Nd` pattern. + pub(crate) fn sequence(&self) -> bool { + self.output.as_deref().is_some_and(|p| pattern(p).is_some()) + } +} + +/// The `%d` or `%0Nd` of a path's file name, and its width. +pub(crate) fn pattern(path: &Path) -> Option<(std::ops::Range, usize)> { + let text = path.to_str()?; + let at = text.rfind('%')?; + let rest = &text[at + 1..]; + let digits = rest.find('d')?; + let width = &rest[..digits]; + if !width.chars().all(|c| c.is_ascii_digit()) || width.len() > 2 { + return None; + } + Some((at..at + digits + 2, width.parse().unwrap_or(0))) +} + +impl Cli { + /// The checks clap cannot make, failing as usage errors: one reader of stdin, an output a render + /// can write, and a panel for each scene. + pub(crate) fn check(&self) -> clap::error::Result<()> { + let invalid = |message: &str| Self::command().error(ErrorKind::InvalidValue, message); + let job = match &self.command { + Command::Render(job) | Command::Validate(job) => job, + Command::Inspect { data, .. } => { + if data.iter().filter(|s| is_stdio(&s.path)).count() > 1 { + return Err(Self::command().error(ErrorKind::ArgumentConflict, "only one input can read stdin")); + } + return Ok(()); + } + Command::Schema { .. } | Command::Tile { .. } => return Ok(()), + Command::Query { data, query, .. } => { + if is_stdio(&data.path) && query == "-" { + return Err(Self::command().error(ErrorKind::ArgumentConflict, "only one input can read stdin")); + } + return Ok(()); + } + }; + let stdin = job.scenes.iter().chain(job.data.iter().map(|s| &s.path)).chain(&job.frames).chain(&job.camera); + if stdin.filter(|path| is_stdio(path)).count() > 1 { + return Err(Self::command().error(ErrorKind::ArgumentConflict, "only one input can read stdin")); + } + if job.tiles.iter().any(|t| t.name.is_none()) { + return Err(invalid("--tiles takes NAME=FILE")); + } + if job.scenes.len() > 1 && job.panel.len() != job.scenes.len() { + return Err(invalid("a shot of several scenes takes a --panel for each")); + } + if job.scenes.len() == 1 && job.panel.len() > 1 { + return Err(invalid("one scene fills one panel")); + } + if job.camera.len() > job.scenes.len() { + return Err(invalid("--camera is one per scene")); + } + let Some(output) = &job.output else { + if matches!(self.command, Command::Render(_)) { + return Err(Self::command().error(ErrorKind::MissingRequiredArgument, "render takes --output")); + } + return Ok(()); + }; + let format = job.format(); + let extension = output.extension().and_then(|e| e.to_str()).map(str::to_ascii_lowercase); + let known = matches!(extension.as_deref(), Some("png" | "jpg" | "jpeg" | "webp" | "mp4" | "y4m" | "rgba")); + if job.format.is_none() && !is_stdio(output) && !known { + return Err(invalid( + "--output ends in .png, .jpg, .webp, .mp4, .y4m, or .rgba, or --format says what it is", + )); + } + let video = matches!(format, Format::Mp4 | Format::Y4m); + if (video || job.sequence()) && job.frames.is_none() { + return Err(invalid("a video or an image sequence takes --frames")); + } + if job.sequence() && (format.image(job.quality).is_none() || is_stdio(output)) { + return Err(invalid("a %d pattern names an image file a frame")); + } + job.shot().check(format.pixels()).map_err(|e| invalid(&e.to_string())) + } +} + +pub(crate) fn is_stdio(path: &Path) -> bool { + path == Path::new("-") +} + +fn finite(value: &str) -> Result { + value.parse::().ok().filter(|n| n.is_finite()).ok_or_else(|| "expected a finite number".into()) +} + +fn positive(value: &str) -> Result { + let n = finite(value)? as f32; + if n.is_finite() && n > 0.0 { Ok(n) } else { Err("expected a positive number".into()) } +} + +fn seconds(value: &str) -> Result { + Duration::try_from_secs_f64(finite(value)?).map_err(|_| "expected nonnegative seconds".into()) +} + +fn deadline(value: &str) -> Result { + seconds(value).and_then(|d| if d.is_zero() { Err("a deadline is longer than zero".into()) } else { Ok(d) }) +} + +fn fps(value: &str) -> Result { + finite(value).and_then(|f| if (1.0..=240.0).contains(&f) { Ok(f) } else { Err("1 to 240 frames a second".into()) }) +} + +fn size(value: &str) -> Result<[u32; 2], String> { + let (w, h) = value.split_once(['x', 'X']).ok_or("expected WIDTHxHEIGHT")?; + let side = |v: &str| v.trim().parse::().ok().filter(|n| *n > 0).ok_or("a side is a positive whole number"); + Ok([side(w)?, side(h)?]) +} + +fn numbers(value: &str) -> Result<[f32; N], String> { + let parts: Vec = value.split(',').map(|v| finite(v.trim()).map(|n| n as f32)).collect::>()?; + parts.try_into().map_err(|_| format!("expected {N} numbers separated by commas")) +} + +fn panel(value: &str) -> Result<[f32; 4], String> { + numbers::<4>(value) +} + +fn insets(value: &str) -> Result<[f32; 4], String> { + numbers::<4>(value) + .and_then(|n| if n.iter().all(|v| *v >= 0.0) { Ok(n) } else { Err("insets are not negative".into()) }) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn cli_reference_matches_help() { + use std::fmt::Write as _; + + let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../.."); + // This checks repository documentation, which is not part of the published CLI crate. + if !root.join(".readthedocs.yaml").exists() { + return; + } + let mut cli = Cli::command(); + let mut text = format!( + "# Command reference\n\nGenerated from Clap. See the [CLI guide](../cli.md) for examples.\n\n## latkit\n\n```text\n{}```\n", + cli.render_long_help() + ); + for command in cli.get_subcommands_mut() { + let name = command.get_name().to_owned(); + let command = command.clone().bin_name(format!("latkit {name}")); + let mut command = command; + write!(text, "\n## {name}\n\n```text\n{}```\n", command.render_long_help()).unwrap(); + } + let text = text.lines().map(str::trim_end).collect::>().join("\n") + "\n"; + let path = root.join("docs/reference/cli.md"); + if std::env::var_os("LATKIT_BLESS").is_some() { + std::fs::create_dir_all(path.parent().unwrap()).unwrap(); + std::fs::write(&path, &text).unwrap(); + } + assert_eq!(std::fs::read_to_string(path).unwrap().replace("\r\n", "\n"), text); + } + + #[test] + fn sources_patterns_and_sizes_parse() { + let named: Source = "states=data/usa.geojson".parse().unwrap(); + assert_eq!((named.name.as_deref(), named.path), (Some("states"), PathBuf::from("data/usa.geojson"))); + let plain: Source = "C:\\data\\a=b.json".parse().unwrap(); + assert_eq!((plain.name, plain.path), (None, PathBuf::from("C:\\data\\a=b.json"))); + assert_eq!(pattern(Path::new("out/frame-%04d.png")), Some((10..14, 4))); + assert_eq!(pattern(Path::new("out/%d.png")), Some((4..6, 0))); + assert_eq!(pattern(Path::new("out/100%.png")), None); + assert_eq!(size("1920x1080"), Ok([1920, 1080])); + assert!(size("0x10").is_err()); + assert_eq!(panel("0,0.5,1,0.5"), Ok([0.0, 0.5, 1.0, 0.5])); + assert!(insets("1,2,3").is_err()); + } +} diff --git a/crates/latkit-cli/src/inputs.rs b/crates/latkit-cli/src/inputs.rs new file mode 100644 index 00000000..a18715ae --- /dev/null +++ b/crates/latkit-cli/src/inputs.rs @@ -0,0 +1,247 @@ +//! What a job reads: scenes, datasets, cameras, fits, and frames. Datasets and frames' patches are +//! the library's JSON documents, loaded through the host, which reads the files they name. + +use std::fs::File; +use std::io::{self, BufRead, BufReader, Read}; +use std::path::{Path, PathBuf}; +use std::sync::mpsc::{self, Receiver}; +use std::time::Duration; + +use latkit::host::Native; +use latkit::{Camera, Data, Error, Fit, Name, Patch, Patches, Scene}; +use serde::Deserialize; +use serde::de::DeserializeOwned; +use serde::de::IgnoredAny; + +use crate::args::{Source, is_stdio}; +use crate::{Failure, block}; + +/// Frames read and loaded ahead of the one drawing. +const AHEAD: usize = 2; + +/// The bytes at `path`, or stdin's for `-`. +pub(crate) fn read(path: &Path) -> Result, Failure> { + let mut bytes = Vec::new(); + let result = if is_stdio(path) { + io::stdin().lock().read_to_end(&mut bytes).map(drop) + } else { + File::open(path).and_then(|mut f| f.read_to_end(&mut bytes)).map(drop) + }; + result.map_err(|e| Failure::io(&e, path))?; + Ok(bytes) +} + +/// What paths in the document at `path` are relative to: the document, or nothing for stdin. +fn base(path: &Path) -> String { + if is_stdio(path) { String::new() } else { path.to_string_lossy().into_owned() } +} + +/// What the JSON document at `path` holds, read as a `T`. +pub(crate) fn document(path: &Path) -> Result { + let bytes = read(path)?; + let text = std::str::from_utf8(&bytes).map_err(|_| Failure::at(Error::invalid("not UTF-8 text"), path))?; + latkit::from_json(text).map_err(|e| Failure::at(e, path)) +} + +/// A scene from its JSON. +pub(crate) fn scene(path: &Path) -> Result { + document(path) +} + +/// A camera from its JSON. +pub(crate) fn camera(path: &Path) -> Result { + document(path) +} + +/// A fit: `all`, or one as JSON. +pub(crate) fn fit(text: &str) -> Result { + let json = if text.trim_start().starts_with(['{', '"', '[']) { text.to_owned() } else { format!("\"{text}\"") }; + latkit::from_json(&json).map_err(|e| Failure::from(e.at("--fit"))) +} + +/// The dataset `source` names: a JSON document loaded through `host`, latkit bytes, or GeoJSON, +/// named as it says. +pub(crate) fn dataset(source: &Source, host: &Native, deadline: Duration) -> Result { + let path = &source.path; + let bytes = read(path)?; + let at = |error: Error| Failure::at(error, path); + let name = source.name.as_deref(); + if bytes.starts_with(b"LATK") || bytes.starts_with(&[0x1f, 0x8b]) || geojson(&bytes) { + return Data::read(&bytes, name).map_err(|e| at(e.at("NAME=FILE"))); + } + let text = std::str::from_utf8(&bytes).map_err(|_| at(Error::invalid("a dataset is JSON or latkit bytes")))?; + let data = block(deadline, Data::load(text, &base(path), host)).map_err(at)?; + Ok(match name { + Some(name) if name != data.name().as_str() => data.renamed(name), + _ => data, + }) +} + +/// Whether JSON `bytes` are GeoJSON: an object with a `type`. +fn geojson(bytes: &[u8]) -> bool { + #[derive(Deserialize)] + struct Probe { + #[serde(rename = "type")] + kind: Option, + } + serde_json::from_slice::(bytes).is_ok_and(|p| p.kind.is_some()) +} + +/// One output frame's changes, as a line of the frames file says. +#[derive(Deserialize, schemars::JsonSchema)] +#[serde(deny_unknown_fields)] +pub(crate) struct Frame { + /// The axis coordinate every view shows. + pub(crate) at: Option, + /// Patches by dataset name, in the order written. + #[serde(default)] + patch: Patches, + /// Where views look at once: one camera for every view it fits, or one per view. + pub(crate) camera: Option>, + /// Where views ease to. + pub(crate) fly: Option>, + /// What views frame. + pub(crate) fit: Option>, + /// CSS pixels every view keeps clear: top, right, bottom, left. + pub(crate) insets: Option<[f32; 4]>, + /// Degrees a second every map or plane turns. + pub(crate) orbit: Option, +} + +/// One value for every view, or one for each in order, `null` leaving a view as it is. +#[derive(Deserialize, schemars::JsonSchema)] +#[serde(untagged)] +#[schemars(inline)] +pub(crate) enum Each { + Each(Vec>), + All(T), +} + +impl Each { + /// The value for view `i`. + pub(crate) fn of(&self, i: usize) -> Option { + match self { + Each::All(value) => Some(value.clone()), + Each::Each(values) => values.get(i).cloned().flatten(), + } + } +} + +/// A frame's index, what it changes, and its patches by dataset, loaded. +pub(crate) type Next = (usize, Frame, Vec<(Name, Patch)>); + +/// The lines of a frames file, each a frame, its patches loaded through the host. +pub(crate) struct Frames { + path: PathBuf, + lines: io::Lines>, + index: usize, + host: Native, + deadline: Duration, +} + +impl Frames { + pub(crate) fn open(path: &Path, host: Native, deadline: Duration) -> Result { + let input: Box = if is_stdio(path) { + Box::new(BufReader::new(io::stdin())) + } else { + Box::new(BufReader::new(File::open(path).map_err(|e| Failure::io(&e, path))?)) + }; + Ok(Frames { path: path.to_path_buf(), lines: input.lines(), index: 0, host, deadline }) + } + + /// The next frame, its patches loaded; `None` at the end. Blank lines are skipped. + pub(crate) fn next(&mut self) -> Result, Failure> { + loop { + let Some(line) = self.lines.next() else { return Ok(None) }; + let line = line.map_err(|e| Failure::io(&e, &self.path))?; + if line.trim().is_empty() { + continue; + } + let index = self.index; + self.index += 1; + let at = |error: Error| Failure::at(error.at(index).at("frames"), &self.path); + let mut frame: Frame = latkit::from_json(&line).map_err(at)?; + if frame.at.is_some_and(|a| !a.is_finite()) { + return Err(at(Error::invalid("at is finite").at("at"))); + } + let base = base(&self.path); + let patches = std::mem::take(&mut frame.patch).load(&base, &self.host); + let patches = block(self.deadline, patches).map_err(|e| at(e.at("patch")))?; + return Ok(Some((index, frame, patches))); + } + } + + /// The frames read and loaded on a thread of their own, a few ahead of the one taken, so their + /// files are read while frames draw. + pub(crate) fn ahead(mut self) -> Ahead { + let (send, frames) = mpsc::sync_channel(AHEAD); + std::thread::spawn(move || { + while let Some(next) = self.next().transpose() { + let failed = next.is_err(); + if send.send(next).is_err() || failed { + break; + } + } + }); + Ahead(frames) + } +} + +/// Frames loaded ahead of drawing. +pub(crate) struct Ahead(Receiver>); + +impl Iterator for Ahead { + type Item = Result; + + fn next(&mut self) -> Option { + self.0.recv().ok() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn deadline() -> Duration { + Duration::from_secs(10) + } + + #[test] + fn datasets_load_json_slices_bytes_and_geojson_by_name() { + let dir = tempfile::tempdir().unwrap(); + let floats: Vec = [9_f32, 1.25, -2.5].into_iter().flat_map(f32::to_le_bytes).collect(); + std::fs::write(dir.path().join("x.f32"), floats).unwrap(); + let doc = r#"{"name": "grid", "patch": [{"replace": {"table": "Bus", "ids": ["b", "a"], "fields": { + "x": {"file": "x.f32", "dtype": "f32le", "offset": 4, "count": 2}}}}]}"#; + std::fs::write(dir.path().join("grid.json"), doc).unwrap(); + let host = Native::new(); + let load = |text: &str| dataset(&text.parse().unwrap(), &host, deadline()); + let path = dir.path().join("grid.json").to_string_lossy().into_owned(); + let data = load(&path).unwrap(); + assert_eq!(data.table("Bus").unwrap().get("a", "x"), Some(latkit::Value::Number(-2.5))); + assert_eq!(load(&format!("other={path}")).unwrap().name().as_str(), "other"); + std::fs::write(dir.path().join("grid.bin"), data.to_bytes()).unwrap(); + assert_eq!(load(&dir.path().join("grid.bin").to_string_lossy()).unwrap().table("Bus").unwrap().len(), 2); + let geo = r#"{"type": "Feature", "properties": {}, "geometry": {"type": "Point", "coordinates": [1, 2]}}"#; + std::fs::write(dir.path().join("p.geojson"), geo).unwrap(); + let geo_path = dir.path().join("p.geojson").to_string_lossy().into_owned(); + assert!(load(&geo_path).is_err(), "GeoJSON names its dataset"); + assert_eq!(load(&format!("places={geo_path}")).unwrap().table("points").unwrap().len(), 1); + } + + #[test] + fn frames_keep_their_patches_order_and_apply_to_every_view_or_each() { + let frame: Frame = latkit::from_json(r#"{"patch": {"b": [], "a": []}}"#).unwrap(); + let patches = block(deadline(), frame.patch.load("", &Native::new())).unwrap(); + let names: Vec<&str> = patches.iter().map(|(name, _)| name.as_str()).collect(); + assert_eq!(names, ["b", "a"]); + assert!(latkit::from_json::(r#"{"patch": {"a": [], "a": []}}"#).is_err(), "a dataset patched twice"); + let error = latkit::from_json::(r#"{"patch": {"a": [[]]}}"#).map(drop).unwrap_err(); + assert!(error.to_string().starts_with("patch.a[0]"), "{error}"); + let one: Each = latkit::from_json("2").unwrap(); + let each: Each = latkit::from_json("[null, 3]").unwrap(); + assert_eq!((one.of(0), one.of(5)), (Some(2.0), Some(2.0))); + assert_eq!((each.of(0), each.of(1), each.of(2)), (None, Some(3.0), None)); + assert!(fit("all").is_ok() && fit(r#"{"bounds": {"min": [0, 0, 0], "max": [1, 1, 0]}}"#).is_ok()); + } +} diff --git a/crates/latkit-cli/src/main.rs b/crates/latkit-cli/src/main.rs new file mode 100644 index 00000000..2a20cefd --- /dev/null +++ b/crates/latkit-cli/src/main.rs @@ -0,0 +1,203 @@ +//! The latkit command line: scenes and datasets in the library's JSON (or its bytes), drawn by the +//! library natively into images, image sequences, raw frames, and videos. + +mod args; +mod inputs; +mod render; +mod report; +mod sinks; + +use std::future::Future; +use std::io::{self, Write}; +use std::path::Path; +use std::process::ExitCode; +use std::sync::Arc; +use std::task::{Context, Poll, Wake, Waker}; +use std::time::{Duration, Instant}; + +use clap::Parser; +use latkit::{Error, Kind, Query, Values}; +use serde_json::{Value, json}; + +use args::{Cli, Command, Input, Source}; +use report::Report; + +fn main() -> ExitCode { + let cli = Cli::parse(); + if let Err(error) = cli.check() { + error.exit(); + } + let mut report = Report::new(cli.diagnostics); + let result = match &cli.command { + Command::Render(job) => render::render(job, &mut report), + Command::Validate(job) => render::validate(job), + Command::Inspect { data, deadline } => inspect(data, *deadline), + Command::Query { data, query, deadline } => self::query(data, query, *deadline), + Command::Tile { data, output, chunk, deadline } => tile(data, output, *chunk, *deadline), + Command::Schema { input } => schema(*input), + }; + match result { + Ok(()) => ExitCode::SUCCESS, + Err(failure) => { + report.error(&failure); + ExitCode::FAILURE + } + } +} + +/// Why a command failed: the library's error, and the file it came from. +#[derive(Debug)] +pub(crate) struct Failure { + pub(crate) error: Error, + pub(crate) source: Option, +} + +impl Failure { + /// `error`, from the file at `path`. + pub(crate) fn at(error: Error, path: &Path) -> Failure { + Failure { error, source: Some(path.to_string_lossy().into_owned()) } + } + + /// An I/O `error` with the file at `path`. + pub(crate) fn io(error: &io::Error, path: &Path) -> Failure { + Failure::at(Error::Io(error.to_string().into()), path) + } +} + +impl From for Failure { + fn from(error: Error) -> Failure { + Failure { error, source: None } + } +} + +/// Every dataset's description as JSON on stdout: its name, axis and span, and each table's rows and +/// fields. +fn inspect(sources: &[Source], deadline: Duration) -> Result<(), Failure> { + let host = latkit::host::Native::new(); + let mut all = Vec::with_capacity(sources.len()); + for source in sources { + all.push(inputs::dataset(source, &host, deadline)?.describe()); + } + let mut out = io::stdout().lock(); + serde_json::to_writer_pretty(&mut out, &all).map_err(|e| Failure::from(Error::Io(e.to_string().into())))?; + writeln!(out).map_err(|e| Failure::io(&e, Path::new("-"))) +} + +/// The JSON Schema of every input on stdout, or of `input`: its definition, with every definition +/// it is built of. +fn schema(input: Option) -> Result<(), Failure> { + let mut schemas = latkit::schemas(); + let frames = latkit::schema::(); + let defs = schemas["$defs"].as_object_mut().expect("definitions"); + for (name, def) in frames["$defs"].as_object().into_iter().flatten() { + defs.entry(name.clone()).or_insert_with(|| def.clone()); + } + let mut frame = frames.clone(); + frame.as_object_mut().expect("a schema").retain(|key, _| key != "$defs" && key != "$schema"); + defs.insert("Frame".into(), frame); + if let Some(input) = input { + let name = match input { + Input::Scene => "Scene", + Input::Data => "Data", + Input::Patch => "Patch", + Input::Query => "Query", + Input::Camera => "Camera", + Input::Fit => "Fit", + Input::Frames => "Frame", + }; + schemas["$ref"] = json!(format!("#/$defs/{name}")); + } + let mut out = io::stdout().lock(); + serde_json::to_writer_pretty(&mut out, &schemas).map_err(|e| Failure::from(Error::Io(e.to_string().into())))?; + writeln!(out).map_err(|e| Failure::io(&e, Path::new("-"))) +} + +/// The rows `query` reads from the dataset as JSON Lines on stdout: `id`, then each field, a +/// reference as its target's id and a missing value as `null`. +fn query(source: &Source, query: &str, deadline: Duration) -> Result<(), Failure> { + let text = + if query.trim_start().starts_with('{') { query.as_bytes().to_vec() } else { inputs::read(Path::new(query))? }; + let text = std::str::from_utf8(&text).map_err(|_| Failure::from(Error::invalid("not UTF-8 text").at("query")))?; + let query: Query = latkit::from_json(text).map_err(|e| Failure::from(e.at("query")))?; + let (rows, _) = inputs::dataset(source, &latkit::host::Native::new(), deadline)?.query(&query)?; + let columns: Vec<(String, Values)> = + rows.fields().map(|(name, _)| (name.to_string(), rows.values(name).expect("a field the table has"))).collect(); + let mut out = io::BufWriter::new(io::stdout().lock()); + for (row, id) in rows.ids().enumerate() { + let mut line = serde_json::Map::with_capacity(columns.len() + 1); + line.insert("id".into(), json!(id)); + for (name, values) in &columns { + let value = match rows.kind(name) { + Some(Kind::Reference) => values.id(row).map_or(Value::Null, |id| json!(id)), + _ => values.get(row).map_or(Value::Null, |v| json!(v)), + }; + line.insert(name.clone(), value); + } + serde_json::to_writer(&mut out, &line).map_err(|e| Failure::from(Error::Io(e.to_string().into())))?; + writeln!(out).map_err(|e| Failure::io(&e, Path::new("-")))?; + } + out.flush().map_err(|e| Failure::io(&e, Path::new("-"))) +} + +/// The dataset as time tiles in directory `output`: its manifest, the dataset without its sampled +/// fields' histories, and their spans of `chunk` entries. +fn tile(source: &Source, output: &Path, chunk: u32, deadline: Duration) -> Result<(), Failure> { + let data = inputs::dataset(source, &latkit::host::Native::new(), deadline)?; + let mut failure = None; + let written = data.to_tiles(chunk, |path, bytes| { + let file = output.join(path); + let wrote = file.parent().map_or(Ok(()), std::fs::create_dir_all).and_then(|()| std::fs::write(&file, bytes)); + wrote.map_err(|e| { + failure = Some(Failure::io(&e, &file)); + Error::Io(e.to_string().into()) + }) + }); + match (written, failure) { + (Ok(()), _) => Ok(()), + (Err(_), Some(failure)) => Err(failure), + (Err(error), None) => Err(Failure::from(error)), + } +} + +/// `future`'s result, driven on this thread and given up at `deadline`. +pub(crate) fn block(deadline: Duration, future: impl Future>) -> latkit::Result { + until(deadline, future)? +} + +/// A synchronous command needs only one parked thread to drive its future, with a deadline. The +/// future must yield; like other async timeouts this cannot interrupt a synchronous OS or driver call. +fn until(deadline: Duration, future: impl Future) -> latkit::Result { + struct Thread(std::thread::Thread); + impl Wake for Thread { + fn wake(self: Arc) { + self.0.unpark(); + } + fn wake_by_ref(self: &Arc) { + self.0.unpark(); + } + } + let started = Instant::now(); + let waker = Waker::from(Arc::new(Thread(std::thread::current()))); + let mut context = Context::from_waker(&waker); + let mut future = std::pin::pin!(future); + loop { + if let Poll::Ready(result) = future.as_mut().poll(&mut context) { + return Ok(result); + } + if started.elapsed() >= deadline { + return Err(Error::Timeout); + } + std::thread::park_timeout(deadline.saturating_sub(started.elapsed())); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn a_deadline_ends_a_future_that_never_wakes() { + assert_eq!(until(Duration::from_millis(5), std::future::pending::<()>()), Err(Error::Timeout)); + assert_eq!(until(Duration::from_secs(1), async { 42 }), Ok(42)); + } +} diff --git a/crates/latkit-cli/src/render.rs b/crates/latkit-cli/src/render.rs new file mode 100644 index 00000000..1821b41c --- /dev/null +++ b/crates/latkit-cli/src/render.rs @@ -0,0 +1,248 @@ +//! Rendering a job, and validating one: views of the scenes with the datasets, then a still picture, +//! or a video of the frames handed to a sink. Validating reads, loads, and checks everything a render +//! does, frames included, without a GPU; both change frames with [`apply`]. + +use std::path::{Path, PathBuf}; + +use latkit::Tiles; +use latkit::host::Native; +use latkit::{Camera, Data, Error, Fit, Gpu, Mp4, Name, Patch, Scene, Sink, View}; + +use crate::args::{Format, Job, Source}; +use crate::inputs::{self, Ahead, Each, Frame, Frames}; +use crate::report::Report; +use crate::sinks::{Commit, Images, Output, Raw, Y4m}; +use crate::{Failure, block}; + +/// What a job reads before it draws, and the host that read it. +struct Inputs { + scenes: Vec<(PathBuf, Scene)>, + data: Vec, + /// What every view fetches as it draws. + tiles: Vec, + cameras: Vec, + fit: Fit, + host: Native, +} + +impl Inputs { + fn read(job: &Job) -> Result { + let fonts = job.font.iter().map(|p| inputs::read(p)).collect::, _>>()?; + let host = if fonts.is_empty() { Native::new() } else { Native::from_fonts(fonts)? }; + let scenes = + job.scenes.iter().map(|p| inputs::scene(p).map(|s| (p.clone(), s))).collect::, _>>()?; + let data = job.data.iter().map(|s| inputs::dataset(s, &host, job.deadline)).collect::, _>>()?; + let tiles: Vec = job + .tiles + .iter() + .map(|Source { name, path }| { + Tiles::new(name.as_deref().unwrap_or_default(), path.to_string_lossy().as_ref()) + }) + .collect(); + for (path, scene) in &scenes { + scene.validate(&data, &tiles).map_err(|e| Failure::at(e, path))?; + } + let cameras = job.camera.iter().map(|p| inputs::camera(p)).collect::, _>>()?; + for (i, camera) in cameras.iter().enumerate() { + if !camera.fits(scenes[i].1.space()) { + return Err(Failure::at( + Error::invalid("the camera does not look at its scene's space"), + &job.camera[i], + )); + } + } + Ok(Inputs { scenes, data, tiles, cameras, fit: inputs::fit(&job.fit)?, host }) + } + + /// A view of each scene, given every dataset and the tiles, looking where the job says. + fn views(&self, gpu: &Gpu, job: &Job) -> Result, Failure> { + let mut views = Vec::with_capacity(self.scenes.len()); + for (i, (path, scene)) in self.scenes.iter().enumerate() { + let mut view = View::new(gpu, scene.clone()).map_err(|e| Failure::at(e, path))?; + for data in &self.data { + view.set_data(data.clone()); + } + for tiles in &self.tiles { + view.set_tiles(tiles.clone()); + } + if let Some(insets) = job.insets { + view.set_insets(insets); + } + if let Some(at) = job.at { + view.set_at(at); + } + match self.cameras.get(i) { + Some(camera) => view.set_camera(*camera), + None => view.fit(self.fit.clone()), + } + views.push(view); + } + Ok(views) + } +} + +pub(crate) fn render(job: &Job, report: &mut Report) -> Result<(), Failure> { + let mut inputs = Inputs::read(job)?; + let gpu = block(job.deadline, Gpu::new())?; + gpu.set_host(inputs.host.clone()); + let mut views = inputs.views(&gpu, job)?; + let output = job.output.as_deref().expect("render takes an output"); + let Some(path) = &job.frames else { + let mut shot = job.shot(); + if let Some(elapsed) = job.elapsed { + shot = shot.elapsed(elapsed); + } + let image = block(job.deadline, shot.image(&mut views.iter_mut().collect::>()))?; + let mut out = Output::create(output)?; + match job.format().image(job.quality) { + Some(format) => image.write(format, &mut out).map_err(|e| Failure::at(e, output))?, + None => std::io::Write::write_all(&mut out, &image.rgba).map_err(|e| Failure::io(&e, output))?, + } + out.commit()?; + report.done(1, &views, &gpu); + return Ok(()); + }; + let frames = Frames::open(path, inputs.host.clone(), job.deadline)?.ahead(); + let host = inputs.host.clone(); + let mut sequence = Sequence { job, path, gpu: &gpu, views: &mut views, inputs: &mut inputs, report }; + let format = job.format(); + if let Some(image) = format.image(job.quality) { + let images = if job.sequence() { + Images::numbered(output.to_path_buf(), image, host) + } else { + Images::one(Output::create(output)?, image, host) + }; + return sequence.run(frames, images); + } + match format { + Format::Png | Format::Jpeg | Format::Webp => unreachable!("images write above"), + Format::Rgba => sequence.run(frames, Raw::new(Output::create(output)?)), + Format::Y4m => sequence.run(frames, Y4m::new(Output::create(output)?)), + Format::Mp4 => { + let mut mp4 = Mp4::new(Output::create(output)?); + if let Some(bitrate) = job.bitrate { + mp4 = mp4.bitrate(bitrate); + } + sequence.run(frames, mp4) + } + } +} + +/// A video of the frames file at `path`, drawn as each line says. +struct Sequence<'a> { + job: &'a Job, + path: &'a Path, + gpu: &'a Gpu, + views: &'a mut Vec, + inputs: &'a mut Inputs, + report: &'a mut Report, +} + +impl Sequence<'_> { + fn run(&mut self, frames: Ahead, sink: S) -> Result<(), Failure> { + let (job, path) = (self.job, self.path); + let output = job.output.as_deref().unwrap_or(path); + let mut video = job.shot().video(self.gpu, job.fps, sink).map_err(|e| Failure::at(e, output))?; + let mut any = false; + for next in frames { + let (index, frame, patches) = next?; + any = true; + let at = |error: Error| Failure::at(error.at(index).at("frames"), path); + let changed = apply(&mut self.inputs.data, &self.inputs.scenes, &frame, patches).map_err(at)?; + for i in changed { + for view in self.views.iter_mut() { + view.set_data(self.inputs.data[i].clone()); + } + } + steer(self.views, &frame); + block(job.deadline, video.frame(&mut self.views.iter_mut().collect::>())).map_err(at)?; + self.report.progress(video.frames(), video.time()); + } + if !any { + return Err(Failure::at(Error::invalid("the frames are empty"), path)); + } + let frames = video.frames(); + block(job.deadline, video.finish()).map_err(|e| Failure::at(e, output))?.commit()?; + self.report.done(frames, self.views, self.gpu); + Ok(()) + } +} + +/// Applies `frame`'s patches to the datasets they name, in order, and checks the cameras it gives +/// each view against that view's scene: the datasets it changed, by index. +fn apply( + data: &mut [Data], + scenes: &[(PathBuf, Scene)], + frame: &Frame, + patches: Vec<(Name, Patch)>, +) -> latkit::Result> { + // One camera for every view looks through those it fits; one per view must fit its own. + for (option, each) in [("camera", &frame.camera), ("fly", &frame.fly)] { + let Some(Each::Each(cameras)) = each else { continue }; + for (i, camera) in cameras.iter().enumerate() { + let fits = match (camera, scenes.get(i)) { + (None, _) => true, + (Some(camera), Some((_, scene))) => camera.fits(scene.space()), + (Some(_), None) => false, + }; + if !fits { + return Err(Error::invalid("the camera does not look at its view's space").at(i).at(option)); + } + } + } + let mut changed = Vec::new(); + for (name, patch) in patches { + let i = data + .iter() + .position(|d| *d.name() == name) + .ok_or_else(|| Error::invalid(format!("no dataset is named {name}")).at(name.as_str()).at("patch"))?; + data[i].apply(patch).map_err(|e| e.at(name.as_str()).at("patch"))?; + if !changed.contains(&i) { + changed.push(i); + } + } + Ok(changed) +} + +/// Points every view where `frame` says. +fn steer(views: &mut [View], frame: &Frame) { + for (i, view) in views.iter_mut().enumerate() { + if let Some(at) = frame.at { + view.set_at(at); + } + if let Some(insets) = frame.insets { + view.set_insets(insets); + } + if let Some(orbit) = frame.orbit { + view.set_orbit(orbit); + } + if let Some(camera) = frame.camera.as_ref().and_then(|c| c.of(i)) { + view.set_camera(camera); + } + if let Some(camera) = frame.fly.as_ref().and_then(|c| c.of(i)) { + view.fly(camera); + } + if let Some(fit) = frame.fit.as_ref().and_then(|f| f.of(i)) { + view.fit(fit); + } + } +} + +/// Reads, loads, and checks everything `render` would, without a GPU: scenes against the datasets, +/// cameras, fonts, and every frame applied in turn. +pub(crate) fn validate(job: &Job) -> Result<(), Failure> { + let mut inputs = Inputs::read(job)?; + let Some(path) = &job.frames else { return Ok(()) }; + let mut frames = Frames::open(path, inputs.host.clone(), job.deadline)?; + let mut any = false; + while let Some((index, frame, patches)) = frames.next()? { + any = true; + let at = |error: Error| Failure::at(error.at(index).at("frames"), path); + if !apply(&mut inputs.data, &inputs.scenes, &frame, patches).map_err(at)?.is_empty() { + for (_, scene) in &inputs.scenes { + scene.validate(&inputs.data, &inputs.tiles).map_err(at)?; + } + } + } + if any { Ok(()) } else { Err(Failure::at(Error::invalid("the frames are empty"), path)) } +} diff --git a/crates/latkit-cli/src/report.rs b/crates/latkit-cli/src/report.rs new file mode 100644 index 00000000..0f8beed5 --- /dev/null +++ b/crates/latkit-cli/src/report.rs @@ -0,0 +1,86 @@ +//! What a command tells on stderr. As JSON, one object a line, `{ "type", "detail" }` as a view's +//! events cross to JavaScript: `progress` after each frame, `stats` once done, and `error` with the +//! library's `{ code, message, path }` and the file it came from. For people, an error a line, and on +//! a terminal a line of progress that rewrites itself. + +use std::io::{self, IsTerminal, Write}; +use std::time::Instant; + +use latkit::{Gpu, View}; +use serde_json::{Value, json}; + +use crate::Failure; +use crate::args::Diagnostics; + +pub(crate) struct Report { + json: bool, + /// Whether people read stderr on a terminal: then progress shows. + terminal: bool, + started: Instant, + /// Whether a progress line is showing. + showing: bool, +} + +impl Report { + pub(crate) fn new(diagnostics: Diagnostics) -> Report { + Report { + json: diagnostics == Diagnostics::Json, + terminal: io::stderr().is_terminal(), + started: Instant::now(), + showing: false, + } + } + + /// `frames` drawn, the next showing at `time` seconds. + pub(crate) fn progress(&mut self, frames: u64, time: f64) { + if self.json { + Report::line(&json!({"type": "progress", "detail": {"frames": frames, "time": time}})); + } else if self.terminal { + let seconds = self.started.elapsed().as_secs_f64(); + let _ = write!(io::stderr().lock(), "\rlatkit: {frames} frames, {time:.2} s of video, in {seconds:.1} s"); + self.showing = true; + } + } + + /// What was drawn, and what it took. + pub(crate) fn done(&mut self, frames: u64, views: &[View], gpu: &Gpu) { + let seconds = self.started.elapsed().as_secs_f64(); + if self.json { + let views: Vec = + views.iter().map(|v| serde_json::to_value(v.stats()).unwrap_or(Value::Null)).collect(); + let work = serde_json::to_value(gpu.work()).unwrap_or(Value::Null); + let detail = json!({"frames": frames, "seconds": seconds, "views": views, "work": work}); + Report::line(&json!({"type": "stats", "detail": detail})); + } else if self.terminal { + let rate = frames as f64 / seconds.max(1e-9); + let _ = + writeln!(io::stderr().lock(), "\rlatkit: {frames} frames in {seconds:.1} s, {rate:.1} a second "); + self.showing = false; + } + } + + /// Why the command failed. + pub(crate) fn error(&mut self, failure: &Failure) { + if self.json { + let mut detail = serde_json::to_value(&failure.error).unwrap_or(Value::Null); + if let (Some(source), Value::Object(map)) = (&failure.source, &mut detail) { + map.insert("source".into(), json!(source)); + } + Report::line(&json!({"type": "error", "detail": detail})); + return; + } + let mut err = io::stderr().lock(); + if self.showing { + let _ = writeln!(err); + } + // A closed stderr must not turn a failure into a panic. + let _ = match &failure.source { + Some(source) => writeln!(err, "latkit: {source}: {}", failure.error), + None => writeln!(err, "latkit: {}", failure.error), + }; + } + + fn line(value: &Value) { + let _ = writeln!(io::stderr().lock(), "{value}"); + } +} diff --git a/crates/latkit-cli/src/sinks.rs b/crates/latkit-cli/src/sinks.rs new file mode 100644 index 00000000..e790e030 --- /dev/null +++ b/crates/latkit-cli/src/sinks.rs @@ -0,0 +1,292 @@ +//! Where pictures go: one output written whole or not at all, and the sinks a video's frames go to +//! besides the library's MP4: image files, raw RGBA, and YUV4MPEG2. + +use std::collections::VecDeque; +use std::fs::File; +use std::future::{Future, ready}; +use std::io::{self, BufWriter, Write}; +use std::path::{Path, PathBuf}; + +use latkit::host::{Host, Job, Native}; +use latkit::{Encoding, Error, Image, ImageFormat, Mp4, Pending, Pixels, Sink}; + +use crate::Failure; +use crate::args::{is_stdio, pattern}; + +/// Image files encoding at once, on the host's workers. +const ENCODING: usize = 4; + +fn written(error: &io::Error, path: &Path) -> Error { + Error::Io(format!("{}: {error}", path.display()).into()) +} + +/// Bytes to stdout, or to a file that replaces `path` only once every byte is written. +pub(crate) enum Output { + Stdout(BufWriter), + File { path: PathBuf, file: BufWriter, temporary: tempfile::TempPath }, +} + +impl Output { + /// An output to `path`, or stdout for `-`. + pub(crate) fn create(path: &Path) -> Result { + if is_stdio(path) { + return Ok(Output::Stdout(BufWriter::new(io::stdout()))); + } + let parent = path.parent().filter(|p| !p.as_os_str().is_empty()).unwrap_or(Path::new(".")); + let suffix = path.extension().map(|e| format!(".{}", e.to_string_lossy())).unwrap_or_default(); + let temporary = + tempfile::Builder::new().suffix(&suffix).tempfile_in(parent).map_err(|e| Failure::io(&e, path))?; + let (file, temporary) = temporary.into_parts(); + Ok(Output::File { path: path.to_path_buf(), file: BufWriter::new(file), temporary }) + } + + /// Writes what is left and, for a file, replaces its destination. + pub(crate) fn commit(self) -> Result<(), Failure> { + match self { + Output::Stdout(mut out) => out.flush().map_err(|e| Failure::io(&e, Path::new("-"))), + Output::File { path, file, temporary } => { + drop(file.into_inner().map_err(|e| Failure::io(e.error(), &path))?); + temporary.persist(&path).map_err(|e| Failure::io(&e.error, &path)) + } + } + } + + fn path(&self) -> &Path { + match self { + Output::Stdout(_) => Path::new("-"), + Output::File { path, .. } => path, + } + } + + /// Writes `bytes`, naming the destination in its error. + fn put(&mut self, bytes: &[u8]) -> latkit::Result<()> { + self.write_all(bytes).map_err(|e| written(&e, self.path())) + } +} + +impl Write for Output { + fn write(&mut self, bytes: &[u8]) -> io::Result { + match self { + Output::Stdout(out) => out.write(bytes), + Output::File { file, .. } => file.write(bytes), + } + } + + fn flush(&mut self) -> io::Result<()> { + match self { + Output::Stdout(out) => out.flush(), + Output::File { file, .. } => file.flush(), + } + } +} + +/// What a sink leaves once its video is finished: its output, written and in place. +pub(crate) trait Commit { + fn commit(self) -> Result<(), Failure>; +} + +impl Commit for Mp4 { + fn commit(self) -> Result<(), Failure> { + self.into_inner().commit() + } +} + +/// Pictures as image files, encoded on the host's workers a few at once: one a frame, numbered by +/// the pattern of the output's name, each file written whole and in order, a held frame's file the +/// frame before's; or one file, of frames that are one. +pub(crate) struct Images { + to: To, + format: ImageFormat, + host: Native, + size: [u32; 2], + /// Frames under way, oldest first: each frame's index, and a drawn frame's file. + writing: VecDeque<(u64, Option>>)>, + /// The last drawn frame's file. + last: Vec, +} + +/// Where image files go. +enum To { + Numbered(PathBuf), + One(Output), +} + +impl Images { + /// A file a frame, at the paths `pattern` numbers. + pub(crate) fn numbered(pattern: PathBuf, format: ImageFormat, host: Native) -> Images { + Images::new(To::Numbered(pattern), format, host) + } + + /// One file, to `out`. + pub(crate) fn one(out: Output, format: ImageFormat, host: Native) -> Images { + Images::new(To::One(out), format, host) + } + + fn new(to: To, format: ImageFormat, host: Native) -> Images { + Images { to, format, host, size: [0, 0], writing: VecDeque::new(), last: Vec::new() } + } + + /// The path of frame `index` where `names` numbers the frames. + fn path(names: &Path, index: u64) -> PathBuf { + let text = names.to_string_lossy(); + let (range, width) = pattern(names).expect("a pattern"); + format!("{}{index:0width$}{}", &text[..range.start], &text[range.end..]).into() + } + + /// Writes the oldest frame's file once it is encoded. + async fn write_oldest(&mut self) -> latkit::Result<()> { + let Some((index, file)) = self.writing.pop_front() else { return Ok(()) }; + if let Some(file) = file { + self.last = file.await?; + if self.last.is_empty() { + return Err(Error::invalid(format!("the picture could not be written as {}", self.format))); + } + } + match &mut self.to { + To::Numbered(names) => { + let path = Images::path(names, index); + let mut out = Output::create(&path).map_err(|f| f.error)?; + out.put(&self.last)?; + out.commit().map_err(|f| f.error) + } + To::One(out) => out.put(&self.last), + } + } +} + +impl Sink for Images { + const PIXELS: Pixels = Pixels::Rgba; + + fn begin(&mut self, encoding: &Encoding, _: Option<&dyn Host>) -> latkit::Result<()> { + self.size = encoding.size; + Ok(()) + } + + async fn frame(&mut self, index: u64, pixels: Option>) -> latkit::Result<()> { + if index > 0 && matches!(self.to, To::One(_)) { + return Err(Error::invalid("an image file is one frame; a %d pattern in the output writes one a frame")); + } + let file = match pixels { + Some(rgba) => Some(self.host.spawn(Job::encode(&Image::new(self.size, rgba)?, self.format))), + None => None, + }; + self.writing.push_back((index, file)); + while self.writing.len() > ENCODING { + self.write_oldest().await?; + } + Ok(()) + } + + async fn finish(&mut self, end: u64) -> latkit::Result<()> { + if end == 0 { + return Err(Error::invalid("the frames are empty")); + } + while !self.writing.is_empty() { + self.write_oldest().await?; + } + Ok(()) + } +} + +impl Commit for Images { + fn commit(self) -> Result<(), Failure> { + match self.to { + To::Numbered(_) => Ok(()), + To::One(out) => out.commit(), + } + } +} + +/// Raw RGBA, straight alpha, frames back to back; a held frame is the frame before again. +pub(crate) struct Raw { + out: Output, + last: Vec, +} + +impl Raw { + pub(crate) fn new(out: Output) -> Raw { + Raw { out, last: Vec::new() } + } +} + +impl Sink for Raw { + const PIXELS: Pixels = Pixels::Rgba; + + fn frame(&mut self, _: u64, pixels: Option>) -> impl Future> { + if let Some(rgba) = pixels { + self.last = rgba; + } + ready(self.out.put(&self.last)) + } + + fn finish(&mut self, _: u64) -> impl Future> { + ready(self.out.flush().map_err(|e| written(&e, self.out.path()))) + } +} + +impl Commit for Raw { + fn commit(self) -> Result<(), Failure> { + self.out.commit() + } +} + +/// YUV4MPEG2: a header, then each frame's planes, 4:2:0 from the GPU's NV12. A held frame is the +/// frame before again. +pub(crate) struct Y4m { + out: Output, + size: [u32; 2], + /// The last frame written, `FRAME` and planes. + last: Vec, +} + +impl Y4m { + pub(crate) fn new(out: Output) -> Y4m { + Y4m { out, size: [0, 0], last: Vec::new() } + } +} + +impl Sink for Y4m { + const PIXELS: Pixels = Pixels::Nv12; + + fn begin(&mut self, encoding: &Encoding, _: Option<&dyn Host>) -> latkit::Result<()> { + self.size = encoding.size; + let ([width, height], [num, den]) = (encoding.size, encoding.rate()); + // The GPU averages each 2×2 block's chroma: centered, as JPEG sites it. + let header = format!("YUV4MPEG2 W{width} H{height} F{num}:{den} Ip A1:1 C420jpeg XCOLORRANGE=LIMITED\n"); + self.out.put(header.as_bytes()) + } + + fn frame(&mut self, _: u64, pixels: Option>) -> impl Future> { + if let Some(nv12) = pixels { + let luma = (self.size[0] * self.size[1]) as usize; + self.last.clear(); + self.last.extend_from_slice(b"FRAME\n"); + self.last.extend_from_slice(&nv12[..luma]); + let chroma = &nv12[luma..]; + self.last.extend(chroma.iter().step_by(2)); + self.last.extend(chroma.iter().skip(1).step_by(2)); + } + ready(self.out.put(&self.last)) + } + + fn finish(&mut self, _: u64) -> impl Future> { + ready(self.out.flush().map_err(|e| written(&e, self.out.path()))) + } +} + +impl Commit for Y4m { + fn commit(self) -> Result<(), Failure> { + self.out.commit() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn patterns_number_files() { + assert_eq!(Images::path(Path::new("out/frame-%04d.png"), 7), PathBuf::from("out/frame-0007.png")); + assert_eq!(Images::path(Path::new("%d.jpg"), 12), PathBuf::from("12.jpg")); + } +} diff --git a/crates/latkit-cli/tests/cli.rs b/crates/latkit-cli/tests/cli.rs new file mode 100644 index 00000000..ca6c84dc --- /dev/null +++ b/crates/latkit-cli/tests/cli.rs @@ -0,0 +1,372 @@ +//! The executable's contracts: files, pipes, exit codes, diagnostics, and every output a render +//! writes, from a still to a video. + +use std::io::Write; +use std::path::Path; +use std::process::{Command, Output, Stdio}; + +use latkit::Image; + +const SCENE: &str = + r#"{"space":"plane","ease":0,"marks":[{"vertices":{"of":["grid","Bus"],"position":["x","y"],"radius":6}}]}"#; +const DATA: &str = r#"{"name":"grid","patch":[{"replace":{"table":"Bus","ids":[10,20],"fields":{"x":[-10,10],"y":[0,0],"name":["Alpha","Beta"]}}}]}"#; +const CAMERA: &str = r#"{"center":[0,0],"zoom":2,"pitch":0,"bearing":0}"#; + +fn run(dir: &Path, args: &[&str], input: Option<&[u8]>) -> Output { + let mut child = Command::new(env!("CARGO_BIN_EXE_latkit")) + .current_dir(dir) + .args(args) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap(); + if let Some(bytes) = input { + child.stdin.take().unwrap().write_all(bytes).unwrap(); + } + drop(child.stdin.take()); + child.wait_with_output().unwrap() +} + +fn fixture() -> tempfile::TempDir { + let dir = tempfile::tempdir().unwrap(); + std::fs::write(dir.path().join("scene.json"), SCENE).unwrap(); + std::fs::write(dir.path().join("grid.json"), DATA).unwrap(); + std::fs::write(dir.path().join("camera.json"), CAMERA).unwrap(); + dir +} + +/// Whether the machine has no GPU, which only `LATKIT_REQUIRE_GPU` makes a failure. +fn no_gpu(output: &Output) -> bool { + let stderr = String::from_utf8_lossy(&output.stderr); + let missing = !output.status.success() && (stderr.contains("no GPU adapter") || stderr.contains("no GPU device")); + assert!(!missing || std::env::var_os("LATKIT_REQUIRE_GPU").is_none(), "GPU required: {stderr}"); + missing +} + +fn ok(output: &Output) { + assert!(output.status.success(), "{}", String::from_utf8_lossy(&output.stderr)); +} + +/// Writes frames: `x` positions of the two buses, as patches of slices of one binary file. +fn frames(dir: &Path, xs: &[[f32; 2]]) { + let bytes: Vec = xs.iter().flatten().flat_map(|x| x.to_le_bytes()).collect(); + std::fs::create_dir_all(dir.join("sequence")).unwrap(); + std::fs::write(dir.join("sequence/x.f32"), bytes).unwrap(); + let lines: Vec = (0..xs.len()) + .map(|i| { + format!( + r#"{{"at":{i},"patch":{{"grid":[{{"set":{{"table":"Bus","ids":[10,20],"fields":{{"x":{{"file":"x.f32","dtype":"f32le","offset":{},"count":2}}}}}}}}]}}}}"#, + i * 8 + ) + }) + .collect(); + std::fs::write(dir.join("sequence/frames.jsonl"), lines.join("\n")).unwrap(); +} + +const COMMON: [&str; 9] = [ + "render", + "scene.json", + "-d", + "grid.json", + "--camera", + "camera.json", + "--frames", + "sequence/frames.jsonl", + "--size=64x64", +]; + +#[test] +fn usage_errors_exit_2_before_reading_or_drawing() { + let dir = tempfile::tempdir().unwrap(); + let help = run(dir.path(), &["render", "--help"], None); + ok(&help); + assert!(String::from_utf8(help.stdout).unwrap().contains("--frames")); + for args in [ + vec!["render", "missing.json"], + vec!["render", "missing.json", "-o", "out.png", "--size", "0x10"], + vec!["render", "missing.json", "-o", "out.png", "--scale", "NaN"], + vec!["render", "missing.json", "-o", "out.png", "--at", "inf"], + vec!["render", "missing.json", "-o", "out.png", "--elapsed", "1e100"], + vec!["render", "missing.json", "-o", "out.png", "--deadline", "0"], + vec!["render", "missing.json", "-o", "out.gif"], + vec!["render", "missing.json", "-o", "out.mp4"], + vec!["render", "missing.json", "--frames", "f.jsonl", "-o", "out.mp4", "--size", "62x64"], + vec!["render", "missing.json", "--frames", "f.jsonl", "-o", "out.mp4", "--transparent"], + vec!["render", "missing.json", "--frames", "f.jsonl", "-o", "out.mp4", "--fps", "0"], + vec!["render", "missing.json", "--frames", "f.jsonl", "-o", "out/%04d.y4m"], + vec!["render", "missing.json", "-o", "out/%04d.png"], + vec!["render", "a.json", "b.json", "-o", "out.png"], + vec!["render", "a.json", "-o", "out.png", "--tiles", "base.pmtiles"], + vec!["validate", "-", "-d", "-"], + ] { + assert_eq!(run(dir.path(), &args, None).status.code(), Some(2), "{args:?}"); + } +} + +#[test] +fn validation_reads_everything_without_a_gpu_and_is_silent_on_success() { + let dir = fixture(); + frames(dir.path(), &[[-4.0, 4.0], [0.0, 8.0]]); + for (args, stdin) in [ + (vec!["validate", "scene.json", "-d", "grid.json"], None), + (vec!["validate", "-", "-d", "grid.json"], Some(SCENE.as_bytes())), + (vec!["validate", "scene.json", "-d", "-"], Some(DATA.as_bytes())), + (vec!["validate", "scene.json", "-d", "grid.json", "--frames", "sequence/frames.jsonl"], None), + ] { + let output = run(dir.path(), &args, stdin); + ok(&output); + assert!(output.stdout.is_empty() && output.stderr.is_empty()); + } + // A frame naming no dataset fails at its line, as JSON when asked. + let bad = r#"{"at":0,"patch":{"absent":[{"forget":{"before":0}}]}}"#; + std::fs::write(dir.path().join("sequence/bad.jsonl"), format!("{{\"at\":0}}\n{bad}")).unwrap(); + let args = ["--diagnostics", "json", "validate", "scene.json", "-d", "grid.json", "--frames", "sequence/bad.jsonl"]; + let output = run(dir.path(), &args, None); + assert_eq!(output.status.code(), Some(1)); + let told: serde_json::Value = serde_json::from_slice(&output.stderr).unwrap(); + assert_eq!(told["type"], "error"); + assert_eq!(told["detail"]["code"], "invalid"); + assert_eq!(told["detail"]["path"], "frames[1].patch.absent"); + // A camera for each view looks at its own view's space: a plot's cannot look at a plane. + std::fs::write(dir.path().join("sequence/bad.jsonl"), r#"{"camera": [{"x": [0, 1]}]}"#).unwrap(); + let output = run(dir.path(), &args, None); + let told: serde_json::Value = serde_json::from_slice(&output.stderr).unwrap(); + assert_eq!(told["detail"]["path"], "frames[0].camera[0]"); + assert!(told["detail"]["source"].as_str().unwrap().ends_with("bad.jsonl")); +} + +#[test] +fn failures_name_the_part_and_the_file_and_keep_the_output() { + let dir = fixture(); + let output = run(dir.path(), &["--diagnostics", "json", "validate", "scene.json"], None); + assert_eq!(output.status.code(), Some(1)); + let told: serde_json::Value = serde_json::from_slice(&output.stderr).unwrap(); + assert_eq!(told["detail"]["path"], "marks[0].vertices.of"); + assert_eq!(told["detail"]["source"], "scene.json"); + let twice = run(dir.path(), &["validate", "scene.json", "-d", "grid.json", "-d", "grid.json"], None); + assert!(String::from_utf8_lossy(&twice.stderr).contains("duplicate")); + std::fs::write(dir.path().join("out.png"), b"keep this").unwrap(); + assert_eq!(run(dir.path(), &["render", "scene.json", "-o", "out.png"], None).status.code(), Some(1)); + assert_eq!(std::fs::read(dir.path().join("out.png")).unwrap(), b"keep this"); + // A legend shows a color mapped through a colormap with a domain or named categories. + let legend = r#"{"space":"plane","marks":[{"vertices":{"of":["grid","Bus"],"legend":"Buses"}}]}"#; + let output = + run(dir.path(), &["--diagnostics", "json", "validate", "-", "-d", "grid.json"], Some(legend.as_bytes())); + let told: serde_json::Value = serde_json::from_slice(&output.stderr).unwrap(); + assert_eq!(told["detail"]["path"], "marks[0].vertices.legend"); +} + +#[test] +fn inspect_describes_datasets_and_geojson_takes_a_name() { + let dir = fixture(); + let geo = r#"{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"n":1},"geometry":{"type":"Point","coordinates":[1,2]}}]}"#; + std::fs::write(dir.path().join("places.geojson"), geo).unwrap(); + let output = run(dir.path(), &["inspect", "grid.json", "places=places.geojson"], None); + ok(&output); + let told: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap(); + assert_eq!(told[0]["name"], "grid"); + let bus = &told[0]["tables"][0]; + assert_eq!((&bus["name"], &bus["rows"]), (&"Bus".into(), &2.into())); + assert_eq!(bus["fields"][0], serde_json::json!({ "name": "name", "kind": "text" })); + assert_eq!(told[1]["name"], "places"); + assert_eq!(told[1]["tables"][0]["rows"], 1); + assert_eq!(run(dir.path(), &["inspect", "places.geojson"], None).status.code(), Some(1), "GeoJSON needs a name"); +} + +#[test] +fn schema_describes_every_input_and_frames() { + let dir = fixture(); + let output = run(dir.path(), &["schema", "frames"], None); + ok(&output); + let schema: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap(); + assert_eq!(schema["$ref"], "#/$defs/Frame"); + let frame = &schema["$defs"]["Frame"]["properties"]; + assert_eq!(frame["patch"]["$ref"], "#/$defs/Patches"); + assert!(frame["camera"].to_string().contains("#/$defs/Camera"), "{frame}"); + let all: serde_json::Value = serde_json::from_slice(&run(dir.path(), &["schema"], None).stdout).unwrap(); + assert!(all.get("$ref").is_none() && all["$defs"]["Scene"].is_object()); +} + +#[test] +fn query_writes_a_json_line_a_row() { + let dir = fixture(); + let query = + r#"{"of":"Bus","sort":[["x","descending"]],"select":{"name":"name","twice":{"op":"mul","args":["x",2]}}}"#; + let output = run(dir.path(), &["query", "grid.json", query], None); + ok(&output); + let lines: Vec = + String::from_utf8(output.stdout).unwrap().lines().map(|l| serde_json::from_str(l).unwrap()).collect(); + assert_eq!( + lines, + [ + serde_json::json!({ "id": 20, "name": "Beta", "twice": 20.0 }), + serde_json::json!({ "id": 10, "name": "Alpha", "twice": -20.0 }), + ] + ); + std::fs::write(dir.path().join("query.json"), r#"{"of":"Bus","filter":{"op":"lt","args":["x",0]}}"#).unwrap(); + let output = run(dir.path(), &["query", "-", "query.json"], Some(DATA.as_bytes())); + ok(&output); + assert_eq!(String::from_utf8(output.stdout).unwrap().lines().count(), 1); + let output = run(dir.path(), &["query", "grid.json", r#"{"of":"Nope"}"#], None); + assert_eq!(output.status.code(), Some(1)); + assert!(String::from_utf8_lossy(&output.stderr).contains("no such table")); +} + +#[test] +fn a_history_tiles_and_draws_from_its_spans_as_from_itself() { + let dir = tempfile::tempdir().unwrap(); + let at: Vec = (0..2000).map(|t| t.to_string()).collect(); + let v: Vec = (0..2000).map(|t| format!("{:.4}", 0.5 + 0.4 * (f64::from(t) / 40.0).sin())).collect(); + let data = format!( + r#"{{"name":"signals","patch":[{{"axis":{{"name":"time","unit":"s"}}}},{{"replace":{{"table":"Signal","ids":{{"count":1}}}}}},{{"append":{{"at":[{}],"table":"Signal","fields":{{"v":[{}]}}}}}}]}}"#, + at.join(","), + v.join(",") + ); + std::fs::write(dir.path().join("signals.json"), data).unwrap(); + let scene = r##"{"space":"plot","ease":0,"marks":[{"lines":{"of":["signals","Signal"],"trace":"v","color":"#ff0000","width":2}}]}"##; + std::fs::write(dir.path().join("plot.json"), scene).unwrap(); + std::fs::write(dir.path().join("camera.json"), r#"{"x":[100,300],"y":[0,1]}"#).unwrap(); + ok(&run(dir.path(), &["tile", "signals.json", "-o", "tiles", "--chunk", "64"], None)); + for file in ["tiles/frames.json", "tiles/base.latk", "tiles/0/0/0.latk", "tiles/0/1/3.latk"] { + assert!(dir.path().join(file).is_file(), "{file}"); + } + assert_eq!(run(dir.path(), &["tile", "signals.json", "-o", "tiles", "--chunk", "12"], None).status.code(), Some(1)); + let render = |source: [&str; 2]| { + let args = ["render", "plot.json", source[0], source[1], "--camera", "camera.json", "--size", "96x64"]; + run(dir.path(), &[&args[..], &["--format", "rgba", "-o", "-"]].concat(), None) + }; + let whole = render(["-d", "signals.json"]); + if no_gpu(&whole) { + return; + } + ok(&whole); + let tiled = render(["--tiles", "signals=tiles/frames.json"]); + ok(&tiled); + let pixels = |o: &Output| o.stdout.as_chunks::<4>().0.to_vec(); + let differing = pixels(&whole).iter().zip(pixels(&tiled)).filter(|(a, b)| a[0].abs_diff(b[0]) > 8).count(); + assert!(differing < 32, "{differing} pixels differ"); + assert!(pixels(&tiled).iter().any(|p| p[0] > 200 && p[1] < 60), "the trace draws"); +} + +#[test] +fn a_labeled_still_renders_to_a_file_and_to_stdout() { + let dir = fixture(); + let scene = r#"{"space":"diagram","layout":{"layered":{}},"title":"Grid","marks":[{"vertices":{"of":["grid","Bus"],"label":"name"}}]}"#; + std::fs::write(dir.path().join("scene.json"), scene).unwrap(); + std::fs::write(dir.path().join("out.png"), b"replace me").unwrap(); + let args = ["render", "scene.json", "-d", "grid.json", "-o", "out.png", "--size", "127x129", "--transparent"]; + let output = run(dir.path(), &args, None); + if no_gpu(&output) { + return; + } + ok(&output); + assert_eq!(output.stdout, b""); + let image = Image::from_png(&std::fs::read(dir.path().join("out.png")).unwrap()).unwrap(); + assert_eq!(image.size, [127, 129]); + assert!(image.rgba.as_chunks::<4>().0.iter().any(|p| p[3] > 0)); + assert!(image.rgba.as_chunks::<4>().0.iter().any(|p| p[3] == 0)); + let mut args = args.to_vec(); + args[5] = "-"; + let stdout = run(dir.path(), &args, None); + ok(&stdout); + assert_eq!(Image::from_png(&stdout.stdout).unwrap(), image); + assert_eq!(std::fs::read_dir(dir.path()).unwrap().count(), 4, "no temporary output left behind"); + for (file, starts) in [("out.jpg", &[0xff, 0xd8, 0xff][..]), ("out.webp", &b"RIFF"[..])] { + args[5] = file; + ok(&run(dir.path(), &args, None)); + assert!(std::fs::read(dir.path().join(file)).unwrap().starts_with(starts), "{file} is what it says"); + } +} + +#[test] +fn panels_draw_a_scene_each() { + let dir = fixture(); + let plot = r#"{"space":"plot","marks":[]}"#; + std::fs::write(dir.path().join("plot.json"), plot).unwrap(); + let args = [ + "render", + "scene.json", + "plot.json", + "-d", + "grid.json", + "--panel", + "0,0,0.5,1", + "--panel", + "0.5,0,0.5,1", + "--size", + "128x64", + "--format", + "rgba", + "-o", + "-", + ]; + let output = run(dir.path(), &args, None); + if no_gpu(&output) { + return; + } + ok(&output); + assert_eq!(output.stdout.len(), 128 * 64 * 4); +} + +#[test] +fn a_frame_stream_writes_every_output_and_holds_still_frames() { + let dir = fixture(); + // The third frame changes nothing: it is held, and a raw stream repeats the second. + frames(dir.path(), &[[-4.0, 4.0], [0.0, 8.0], [0.0, 8.0]]); + let mut args = COMMON.to_vec(); + args.extend(["--format", "rgba", "-o", "-"]); + let output = run(dir.path(), &args, None); + if no_gpu(&output) { + return; + } + ok(&output); + let frame = 64 * 64 * 4; + assert_eq!(output.stdout.len(), frame * 3); + let [first, second, third] = [0, 1, 2].map(|i| &output.stdout[i * frame..(i + 1) * frame]); + assert_ne!(first, second); + assert_eq!(second, third); + + // A sequence never truncates itself into one PNG, nor destroys an old file. + std::fs::write(dir.path().join("out.png"), b"keep").unwrap(); + let mut args = COMMON.to_vec(); + args.extend(["-o", "out.png"]); + assert_eq!(run(dir.path(), &args, None).status.code(), Some(1)); + assert_eq!(std::fs::read(dir.path().join("out.png")).unwrap(), b"keep"); + + let mut args = COMMON.to_vec(); + args.extend(["-o", "pngs/frame-%03d.png"]); + std::fs::create_dir(dir.path().join("pngs")).unwrap(); + ok(&run(dir.path(), &args, None)); + let names: Vec = std::fs::read_dir(dir.path().join("pngs")) + .unwrap() + .map(|e| e.unwrap().file_name().into_string().unwrap()) + .collect(); + assert_eq!(names.len(), 3, "{names:?}"); + let png = + |n: u32| Image::from_png(&std::fs::read(dir.path().join(format!("pngs/frame-{n:03}.png"))).unwrap()).unwrap(); + assert_eq!(&png(0).rgba[..], first); + assert_eq!(png(1), png(2)); + + let mut args = COMMON.to_vec(); + args.extend(["-o", "out.y4m"]); + ok(&run(dir.path(), &args, None)); + let y4m = std::fs::read(dir.path().join("out.y4m")).unwrap(); + let header = b"YUV4MPEG2 W64 H64 F60:1 Ip A1:1 C420jpeg XCOLORRANGE=LIMITED\n"; + assert!(y4m.starts_with(header)); + assert_eq!(y4m.len(), header.len() + 3 * (6 + 64 * 64 * 3 / 2)); + + #[cfg(windows)] + { + let mut args = COMMON.to_vec(); + args.extend(["-o", "out.mp4"]); + ok(&run(dir.path(), &args, None)); + let mp4 = std::fs::read(dir.path().join("out.mp4")).unwrap(); + assert_eq!(&mp4[4..8], b"ftyp"); + assert!(mp4.windows(4).any(|w| w == b"moov") && mp4.windows(4).any(|w| w == b"moof")); + let absent = "{\"at\":0}\n{\"at\":0,\"patch\":{\"absent\":[]}}"; + std::fs::write(dir.path().join("sequence/frames.jsonl"), absent).unwrap(); + assert_eq!(run(dir.path(), &args, None).status.code(), Some(1)); + assert_eq!(std::fs::read(dir.path().join("out.mp4")).unwrap(), mp4, "a failed video keeps the file before"); + } +} diff --git a/crates/latkit-js/Cargo.toml b/crates/latkit-js/Cargo.toml new file mode 100644 index 00000000..fcfda995 --- /dev/null +++ b/crates/latkit-js/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "latkit-js" +description = "The latkit npm package: wasm bindings for the browser." +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +publish = false + +[lib] +crate-type = ["cdylib", "rlib"] + +[target.'cfg(target_arch = "wasm32")'.dependencies] +futures-util.workspace = true +latkit = { workspace = true, features = ["gpu", "web"] } +wasm-bindgen.workspace = true +wasm-bindgen-futures.workspace = true +js-sys.workspace = true +web-sys = { workspace = true, features = ["HtmlCanvasElement", "OffscreenCanvas"] } +serde.workspace = true +serde_json.workspace = true +console_error_panic_hook.workspace = true + +[lints] +workspace = true diff --git a/crates/latkit-js/src/canvas.rs b/crates/latkit-js/src/canvas.rs new file mode 100644 index 00000000..a3810012 --- /dev/null +++ b/crates/latkit-js/src/canvas.rs @@ -0,0 +1,27 @@ +//! Canvases: a canvas shows views in panels. + +use latkit::web::PageView; +use wasm_bindgen::prelude::*; + +use crate::Error; + +/// A view, for a canvas to show or a shot to draw: what `view.handle()` gives. +#[wasm_bindgen] +pub struct Handle(pub(crate) PageView); + +/// The views `handles` name. +pub(crate) fn views_of(handles: Vec) -> Vec { + handles.into_iter().map(|h| h.0).collect() +} + +/// Views shown in the panels of a `` or an `OffscreenCanvas`; freeing it stops drawing them. +#[wasm_bindgen] +pub struct Canvas(pub(crate) latkit::web::Canvas); + +#[wasm_bindgen] +impl Canvas { + /// Shows `views`, one per panel, in place of those it showed. + pub fn show(&self, views: Vec) -> Result<(), Error> { + Ok(self.0.show(&views_of(views))?) + } +} diff --git a/crates/latkit-js/src/convert.rs b/crates/latkit-js/src/convert.rs new file mode 100644 index 00000000..40c03513 --- /dev/null +++ b/crates/latkit-js/src/convert.rs @@ -0,0 +1,89 @@ +//! latkit's rows and ids to JavaScript, and ids back: a query's columns cross as typed arrays and +//! arrays, built here once; everything else crosses as bytes or JSON. + +use js_sys::{Array, Float64Array, Object, Reflect}; +use latkit::Error; +use wasm_bindgen::{JsCast, JsValue}; + +/// The largest whole number a JavaScript number holds exactly: 2^53 - 1. +const SAFE: f64 = 9_007_199_254_740_991.0; + +/// A value for JavaScript: a number, boolean, or text; a geometry as nested `[x, y]` arrays; a row a +/// reference names as its id. +fn value(value: &latkit::Value) -> JsValue { + let xy = |p: &[f64; 2]| -> JsValue { Array::of2(&p[0].into(), &p[1].into()).into() }; + let path = |p: &Vec<[f64; 2]>| -> JsValue { p.iter().map(xy).collect::().into() }; + match value { + latkit::Value::Number(n) => (*n).into(), + latkit::Value::Bool(b) => (*b).into(), + latkit::Value::Text(t) => JsValue::from_str(t), + latkit::Value::Point(p) => xy(p), + latkit::Value::Path(p) => path(p), + latkit::Value::Parts(parts) => parts.iter().map(path).collect::().into(), + latkit::Value::Polygons(polygons) => polygons + .iter() + .map(|rings| -> JsValue { rings.iter().map(path).collect::().into() }) + .collect::() + .into(), + latkit::Value::Row(row) => id_value(&row.id), + } +} + +/// `table` as a query answers it: `{ table, ids, fields, total }`, numbers as a `Float64Array` +/// (missing NaN), other values as arrays (missing `null`), a reference as `{ reference, ids }`. +pub(crate) fn table(table: &latkit::Table, total: usize) -> JsValue { + let fields = Object::create(JsValue::NULL.unchecked_ref::()); + for field in table.describe().fields { + let values = table.values(&field.name).unwrap_or_else(|| latkit::Values::from(Vec::::new())); + let column: JsValue = match (&field.to, values.numbers()) { + (Some(to), _) => object(&[("reference", JsValue::from_str(to)), ("ids", ids_value(&values))]), + (None, Some(numbers)) => Float64Array::from(&numbers[..]).into(), + (None, None) => { + (0..values.len()).map(|i| values.get(i).map_or(JsValue::NULL, |v| value(&v))).collect::().into() + } + }; + let _ = Reflect::set(&fields, &JsValue::from_str(&field.name), &column); + } + let ids: Array = table.ids().map(|id| id_value(&id)).collect(); + object(&[ + ("table", JsValue::from_str(table.name())), + ("ids", ids.into()), + ("fields", fields.into()), + ("total", (total as f64).into()), + ]) +} + +/// Ids held as values, missing `null`. +fn ids_value(values: &latkit::Values) -> JsValue { + (0..values.len()).map(|i| values.id(i).map_or(JsValue::NULL, |id| id_value(&id))).collect::().into() +} + +/// An object of `entries`. +pub(crate) fn object(entries: &[(&str, JsValue)]) -> JsValue { + let object = Object::new(); + for (key, value) in entries { + let _ = Reflect::set(&object, &JsValue::from_str(key), value); + } + object.into() +} + +/// An id as a number or a text: a number too large for JavaScript's as its decimal text, which +/// names the same row. +pub(crate) fn id_value(id: &latkit::Id) -> JsValue { + match id { + latkit::Id::Number(n) if *n as f64 <= SAFE => (*n as f64).into(), + latkit::Id::Number(n) => JsValue::from_str(&n.to_string()), + latkit::Id::Text(t) => JsValue::from_str(t), + } +} + +/// The id JavaScript names: a whole number from 0 to 2^53 - 1, or a text. +pub(crate) fn id(value: &JsValue) -> Result { + if let Some(text) = value.as_string() { + return Ok(latkit::Id::from(text)); + } + match value.as_f64() { + Some(n) if n.fract() == 0.0 && (0.0..=SAFE).contains(&n) => Ok(latkit::Id::Number(n as u64)), + _ => Err(Error::invalid("an id is a whole number from 0 to 2^53 - 1, or a text").at("id")), + } +} diff --git a/crates/latkit-js/src/error.rs b/crates/latkit-js/src/error.rs new file mode 100644 index 00000000..f9eb236b --- /dev/null +++ b/crates/latkit-js/src/error.rs @@ -0,0 +1,26 @@ +//! Errors as JavaScript throws them: an `Error` with latkit's message, its `code` (`invalid`, +//! `unsupported`, `limit`, `io`, `device-lost`, `cancelled`, or `timeout`), and for invalid input the +//! `path` to the part. + +use js_sys::Reflect; +use wasm_bindgen::JsValue; + +/// A latkit error, thrown as a JavaScript `Error`. +pub struct Error(JsValue); + +impl From for Error { + fn from(error: latkit::Error) -> Error { + let thrown = js_sys::Error::new(&error.to_string()); + let _ = Reflect::set(&thrown, &"code".into(), &error.code().into()); + if let latkit::Error::Invalid { path, .. } = &error { + let _ = Reflect::set(&thrown, &"path".into(), &path.to_string().into()); + } + Error(thrown.into()) + } +} + +impl From for JsValue { + fn from(error: Error) -> JsValue { + error.0 + } +} diff --git a/crates/latkit-js/src/lib.rs b/crates/latkit-js/src/lib.rs new file mode 100644 index 00000000..7fb47678 --- /dev/null +++ b/crates/latkit-js/src/lib.rs @@ -0,0 +1,506 @@ +//! The latkit npm package: data and views for the browser, over WebGPU. +//! +//! What crosses is bytes or JSON, in the forms `latkit` reads and writes. Patches cross as their byte +//! frames, which the package's TypeScript writes itself; scenes, cameras, fits, queries, and rows go +//! in as JSON, and events, hits, stats, and work come out as JSON, a view's events a batch at a time. +//! A query's columns come out as typed arrays, copied once. + +#![cfg(target_arch = "wasm32")] +#![allow(unsafe_code, reason = "wasm-bindgen's generated glue")] +#![allow(missing_docs, reason = "documented in the npm package's TypeScript")] + +mod canvas; +mod convert; +mod error; +mod shot; + +use wasm_bindgen::JsCast; +use wasm_bindgen::prelude::*; + +pub use canvas::{Canvas, Handle}; +pub use error::Error; +pub use shot::{Image, Video, image, set_encoder}; + +#[wasm_bindgen(start)] +fn start() { + console_error_panic_hook::set_once(); +} + +/// What `text` holds, in the JSON form latkit reads; or why not, at the path from `what`. +fn json(what: &str, text: &str) -> Result { + latkit::from_json(text).map_err(|e| e.at(what).into()) +} + +/// `value` in the JSON form the npm package's types describe. +fn to_json(value: &impl serde::Serialize) -> String { + serde_json::to_string(value).expect("view state serializes") +} + +/// A promise of what `future` answers, its error thrown as latkit's. +fn promise>(future: impl Future> + 'static) -> js_sys::Promise { + wasm_bindgen_futures::future_to_promise(async move { + future.await.map(Into::into).map_err(|e| JsValue::from(Error::from(e))) + }) +} + +/// The GPU device views draw with. +#[wasm_bindgen] +pub struct Gpu(latkit::Gpu); + +#[wasm_bindgen] +impl Gpu { + /// Requests a WebGPU device. + pub async fn create() -> Result { + Ok(Gpu(latkit::Gpu::new().await?)) + } + + /// A view of `scene` (JSON), telling `tell` its events from the start: each batch a JSON array of + /// `{ type, detail }`. A canvas shows it; a shot draws it with or without one. + pub fn view(&self, scene: &str, tell: js_sys::Function) -> Result { + let view = latkit::web::PageView::new(latkit::View::new(&self.0, json("scene", scene)?)?); + let telling = view.on(move |events| { + let _ = tell.call1(&JsValue::NULL, &JsValue::from_str(&to_json(&events))); + }); + Ok(View { view, _telling: telling }) + } + + /// A canvas showing views in `panels` (JSON) of `target`: a `` element, or an + /// `OffscreenCanvas` at `pixel_ratio` pixels a CSS pixel. + pub fn canvas(&self, target: &JsValue, panels: &str, pixel_ratio: Option) -> Result { + let panels: latkit::Panels = json("panels", panels)?; + let canvas = if let Some(element) = target.dyn_ref::() { + latkit::web::Canvas::new(&self.0, element, panels)? + } else if let Some(offscreen) = target.dyn_ref::() { + latkit::web::Canvas::offscreen(&self.0, offscreen, panels, pixel_ratio.unwrap_or(1.0))? + } else { + return Err(latkit::Error::invalid("a canvas draws into a or an OffscreenCanvas").into()); + }; + Ok(Canvas(canvas)) + } + + /// Calls `listener` with the frame's timestamp every animation frame, before the views draw. + #[wasm_bindgen(js_name = onFrame)] + pub fn on_frame(&self, listener: js_sys::Function) -> Listener { + Listener(latkit::web::on_frame(&self.0, move |now| { + let _ = listener.call1(&JsValue::NULL, &now.into()); + })) + } + + /// Whether the device was lost. + #[wasm_bindgen(getter)] + pub fn lost(&self) -> bool { + self.0.lost() + } + + /// How much GPU memory data takes, as JSON `{ bytes, uploadPerFrame }`. + #[wasm_bindgen(getter)] + pub fn budget(&self) -> String { + to_json(&self.0.budget()) + } + + /// Sets how much GPU memory data takes, from JSON `{ bytes, uploadPerFrame }`. + #[wasm_bindgen(js_name = setBudget)] + pub fn set_budget(&self, budget: &str) -> Result<(), Error> { + self.0.set_budget(json("budget", budget)?); + Ok(()) + } + + /// What the GPU did since it was made, counted exactly, as JSON. + #[wasm_bindgen(getter)] + pub fn work(&self) -> String { + to_json(&self.0.work()) + } + + /// Draws one frame now at `now`, milliseconds as an animation frame's timestamp; from the first, + /// no animation frames are asked for. + pub fn step(&self, now: f64) { + latkit::web::step(&self.0, now); + } + + /// Resolves once the GPU finished what was submitted, every readback landed, and every pipeline + /// asked for compiled. + pub fn done(&self) -> js_sys::Promise { + let gpu = self.0.clone(); + promise(async move { + latkit::web::done(&gpu).await; + Ok(JsValue::UNDEFINED) + }) + } + + /// Resolves when work a view waits on lands after this call, or a view asks for a frame. + pub fn landed(&self) -> js_sys::Promise { + let landed = latkit::web::landed(&self.0); + promise(async move { + landed.await; + Ok(JsValue::UNDEFINED) + }) + } +} + +#[wasm_bindgen] +impl Gpu { + /// A video of `shot`'s (JSON) pictures at `fps` frames a second, encoded by WebCodecs at + /// `bitrate` bits a second, or about 0.15 bits a pixel a frame. + pub fn video(&self, shot: &str, fps: f64, bitrate: Option) -> Result { + shot::video(&self.0, shot, fps, bitrate) + } +} + +/// A listener; freeing it stops it. +#[wasm_bindgen] +pub struct Listener(#[allow(dead_code, reason = "kept until freed")] latkit::web::Listener); + +/// A named collection of tables, changed in place by patches; a snapshot keeps a version. +#[wasm_bindgen] +pub struct Data(latkit::Data); + +#[wasm_bindgen] +impl Data { + #[wasm_bindgen(constructor)] + pub fn new(name: &str) -> Data { + Data(latkit::Data::new(name)) + } + + /// The dataset latkit bytes hold, renamed `name` when given. + #[allow(clippy::needless_pass_by_value, reason = "wasm-bindgen hands optional texts over owned")] + pub fn read(bytes: &[u8], name: Option) -> Result { + if !bytes.starts_with(b"LATK") { + return Err(latkit::Error::invalid("not latkit bytes").at("bytes").into()); + } + Ok(Data(latkit::Data::read(bytes, name.as_deref())?)) + } + + /// A promise of the dataset its JSON document builds, its slices fetched relative to `base`. + pub fn load(json: String, base: String) -> js_sys::Promise { + promise(async move { Ok(Data(latkit::Data::load(&json, &base, &latkit::host::Browser).await?)) }) + } + + #[wasm_bindgen(getter)] + pub fn name(&self) -> String { + self.0.name().to_string() + } + + /// The first and last axis coordinates the sampled fields span. + #[wasm_bindgen(getter)] + pub fn span(&self) -> Option> { + self.0.span().map(Vec::from) + } + + /// Applies the patch `bytes` hold: every change, or none when one is invalid. + pub fn apply(&mut self, bytes: &[u8]) -> Result<(), Error> { + Ok(self.0.apply(latkit::Patch::from_bytes(bytes)?)?) + } + + /// This version, kept as `apply` changes this one: O(1), sharing every page. + #[must_use] + pub fn snapshot(&self) -> Data { + Data(self.0.clone()) + } + + #[wasm_bindgen(js_name = toBytes)] + pub fn to_bytes(&self) -> Vec { + self.0.to_bytes() + } + + /// The value of `field` for the row with `id` in `table`, at axis coordinate `at` when given, as + /// JSON; `null` when missing. + pub fn get(&self, table: &str, id: &JsValue, field: &str, at: Option) -> Result { + let row = latkit::Row::new(self.0.name(), table, convert::id(id)?); + let value = match at { + Some(at) => self.0.get_at(&row, field, at), + None => self.0.get(&row, field), + }; + Ok(to_json(&value)) + } + + /// The names of the tables. + pub fn tables(&self) -> Vec { + self.0.tables().map(|t| t.name().to_string()).collect() + } + + /// Every row's id of `table`, in row order. + pub fn ids(&self, table: &str) -> js_sys::Array { + self.0.table(table).map(|t| t.ids().map(|id| convert::id_value(&id)).collect()).unwrap_or_default() + } + + /// The names of `table`'s fields. + pub fn fields(&self, table: &str) -> Vec { + self.0.table(table).map(|t| t.fields().map(|(name, _)| name.to_string()).collect()).unwrap_or_default() + } + + /// What the dataset holds, as JSON. + pub fn describe(&self) -> String { + to_json(&self.0.describe()) + } + + /// The rows `query` (JSON) keeps, as `{ table, ids, fields, total }`: fields in the forms a patch + /// writes, `total` the rows kept before paging. + pub fn query(&self, query: &str) -> Result { + let (table, total) = self.0.query(&json("query", query)?)?; + Ok(convert::table(&table, total)) + } + + /// Each row's least and greatest value of sampled `field` of `table` over `spans` spans of + /// `range`: of every row, or of rows `ids` (JSON), as `{ at, least, greatest }` typed arrays. + pub fn envelope( + &self, + table: &str, + field: &str, + range: &[f64], + spans: u32, + ids: Option, + ) -> Result { + let table = self.0.table(table).ok_or_else(|| latkit::Error::invalid("no such table").at(table))?; + let [from, to] = range else { return Err(latkit::Error::invalid("a range is [from, to]").into()) }; + let ids: Option = ids.map(|ids| json("ids", &ids)).transpose()?; + let envelope = table.envelope(field, [*from, *to], spans as usize, ids.as_ref())?; + Ok(convert::object(&[ + ("at", js_sys::Float64Array::from(&envelope.at[..]).into()), + ("least", js_sys::Float32Array::from(&envelope.least[..]).into()), + ("greatest", js_sys::Float32Array::from(&envelope.greatest[..]).into()), + ])) + } +} + +/// A promise of the bytes of the patch its JSON makes, its slices fetched relative to `base`. +#[wasm_bindgen(js_name = loadPatch)] +pub fn load_patch(json: String, base: String) -> js_sys::Promise { + promise(async move { + let patch = latkit::Patch::load(&json, &base, &latkit::host::Browser).await?; + Ok(js_sys::Uint8Array::from(&patch.to_bytes()[..])) + }) +} + +/// A view of a scene, telling its events from the start. +#[wasm_bindgen] +pub struct View { + view: latkit::web::PageView, + _telling: latkit::web::Listener, +} + +#[wasm_bindgen] +impl View { + /// Draws `scene` (JSON) instead; an invalid scene changes nothing. + pub fn show(&self, scene: &str) -> Result<(), Error> { + let scene = json("scene", scene)?; + Ok(self.view.with(|v| v.show(scene))?) + } + + #[wasm_bindgen(js_name = setData)] + pub fn set_data(&self, data: &Data) { + self.view.with(|v| v.set_data(data.0.clone())); + } + + /// Fetches the vector tiles at `url` as the camera asks for them, drawn as dataset `name`. + #[wasm_bindgen(js_name = setTiles)] + pub fn set_tiles(&self, name: &str, url: &str) { + self.view.with(|v| v.set_tiles(latkit::Tiles::new(name, url))); + } + + #[wasm_bindgen(js_name = removeData)] + pub fn remove_data(&self, name: &str) { + self.view.with(|v| v.remove_data(name)); + } + + /// The dataset named `name`: one given, or the tiles the view fetched. + pub fn data(&self, name: &str) -> Option { + self.view.read(|v| v.data(name).cloned()).map(Data) + } + + #[wasm_bindgen(getter)] + pub fn at(&self) -> f64 { + self.view.read(latkit::View::at) + } + + #[wasm_bindgen(setter)] + pub fn set_at(&self, at: f64) { + self.view.with(|v| v.set_at(at)); + } + + /// The camera as JSON. + #[wasm_bindgen(getter)] + pub fn camera(&self) -> String { + self.view.read(|v| to_json(v.camera())) + } + + /// Looks through the camera (JSON) at once. + #[wasm_bindgen(js_name = setCamera)] + pub fn set_camera(&self, camera: &str) -> Result<(), Error> { + let camera = json("camera", camera)?; + self.view.with(|v| v.set_camera(camera)); + Ok(()) + } + + /// Eases to the camera (JSON). + pub fn fly(&self, camera: &str) -> Result<(), Error> { + let camera = json("camera", camera)?; + self.view.with(|v| v.fly(camera)); + Ok(()) + } + + /// Frames what `fit` (JSON) names. + pub fn fit(&self, fit: &str) -> Result<(), Error> { + let fit = json("fit", fit)?; + self.view.with(|v| v.fit(fit)); + Ok(()) + } + + /// Lays every vertex row without a position out again by the scene's layout: a promise of the + /// bytes of a patch to each dataset, writing the places into the data. + pub fn arrange(&self) -> js_sys::Promise { + let pending = self.view.with(latkit::View::arrange); + promise(async move { + let patches = pending.await?; + Ok(patches.iter().map(|patch| js_sys::Uint8Array::from(&patch.to_bytes()[..])).collect::()) + }) + } + + /// Where `position` (x, y, elevation) lands on screen, CSS pixels from the top left. + pub fn point(&self, position: &[f64]) -> Option> { + let position: [f64; 3] = position.try_into().ok()?; + self.view.read(|v| v.point(position)).map(Vec::from) + } + + /// The position on the ground under screen point `point`. + pub fn ground(&self, point: &[f32]) -> Option> { + let point: [f32; 2] = point.try_into().ok()?; + self.view.read(|v| v.ground(point)).map(Vec::from) + } + + #[wasm_bindgen(getter)] + pub fn insets(&self) -> Vec { + self.view.read(|v| v.insets().to_vec()) + } + + #[wasm_bindgen(setter)] + pub fn set_insets(&self, insets: &[f32]) -> Result<(), Error> { + let insets: [f32; 4] = insets.try_into().map_err(|_| latkit::Error::invalid("four insets").at("insets"))?; + self.view.with(|v| v.set_insets(insets)); + Ok(()) + } + + #[wasm_bindgen(getter)] + pub fn orbit(&self) -> f64 { + self.view.read(latkit::View::orbit) + } + + #[wasm_bindgen(setter)] + pub fn set_orbit(&self, degrees_per_second: f64) { + self.view.with(|v| v.set_orbit(degrees_per_second)); + } + + /// The rows selected, as JSON sets of rows. + #[wasm_bindgen(getter)] + pub fn selection(&self) -> String { + self.view.read(|v| to_json(&v.selection())) + } + + /// Selects the rows (JSON sets of rows), and no others. + pub fn select(&self, rows: &str) -> Result<(), Error> { + let rows: Vec = json("rows", rows)?; + self.view.with(|v| v.select(rows)); + Ok(()) + } + + /// What the user points at, as a JSON hit or `null`. + #[wasm_bindgen(getter)] + pub fn hovered(&self) -> String { + self.view.read(|v| to_json(&v.hovered())) + } + + /// Every mark that draws nothing because its data no longer fits it, as JSON failures. + #[wasm_bindgen(getter)] + pub fn failures(&self) -> String { + self.view.read(|v| to_json(&v.failures().collect::>())) + } + + /// What the view does each frame, as JSON. + #[wasm_bindgen(getter)] + pub fn stats(&self) -> String { + to_json(&self.view.read(latkit::View::stats)) + } + + /// Whether the view wants a frame: it changed, or work it waited on landed. + #[wasm_bindgen(getter, js_name = wantsFrame)] + pub fn wants_frame(&self) -> bool { + self.view.wants_frame() + } + + /// Every row within `radius` CSS pixels of `point`, nearest first, as JSON hits. + pub fn pick(&self, point: &[f32], radius: f32) -> Result { + let point: [f32; 2] = point.try_into().map_err(|_| latkit::Error::invalid("a point is [x, y]").at("point"))?; + let pending = self.view.with(|v| v.pick(point, radius)); + Ok(promise(async move { Ok(JsValue::from_str(&to_json(&pending.await?))) })) + } + + /// Where the row (JSON) lies on screen, `[x, y]`, or `null`. + pub fn locate(&self, row: &str) -> Result { + let row: latkit::Row = json("row", row)?; + let pending = self.view.with(|v| v.locate(&row)); + Ok(promise(async move { + let point = pending.await?; + Ok(point.map_or(JsValue::NULL, |p| js_sys::Array::of2(&p[0].into(), &p[1].into()).into())) + })) + } + + /// The rows joined to the row (JSON), as JSON sets of rows: a vertex's neighbors across edges and + /// nets, or an edge's or a net's vertices. + pub fn neighbors(&self, row: &str) -> Result { + let row: latkit::Row = json("row", row)?; + Ok(self.view.read(|v| to_json(&v.neighbors(&row)))) + } + + /// The view, for a canvas to show or a shot to draw. + pub fn handle(&self) -> Handle { + Handle(self.view.clone()) + } +} + +/// Has views' jobs done by `run`: `(bytes: Uint8Array) => Promise`, the page's workers. +#[wasm_bindgen(js_name = setJobs)] +pub fn set_jobs(run: js_sys::Function) { + latkit::host::Browser::set_jobs(run); +} + +/// Does a job a view handed the page, in a worker: its answer's bytes. +#[wasm_bindgen] +pub fn job(bytes: &[u8]) -> Vec { + latkit::host::Job::from_bytes(bytes.to_vec()).run() +} + +/// The job reading GeoJSON `bytes`, gzip-compressed or not, as dataset `name`, for a worker to do: it +/// answers the bytes of the patch building the dataset, or nothing when the bytes are no GeoJSON. +#[wasm_bindgen(js_name = geojsonJob)] +pub fn geojson_job(name: &str, bytes: &[u8]) -> Vec { + latkit::host::Job::geojson(name, bytes).into_bytes() +} + +/// The compiled module, for workers to instantiate. +#[wasm_bindgen] +pub fn module() -> JsValue { + wasm_bindgen::module() +} + +/// A CSS gradient through `map` (JSON), a catalog name or colors of your own, toward `direction`: the +/// colors the GPU draws, a band each for a categorical map's categories. +#[wasm_bindgen(js_name = colormapCss)] +pub fn colormap_css(map: &str, direction: &str) -> Result { + let map: latkit::Colormap = json("colormap", map)?; + let css = |color: latkit::Color| { + let [r, g, b, a] = color.to_rgba8(); + format!("rgba({r}, {g}, {b}, {:.3})", f32::from(a) / 255.0) + }; + let percent = |at: f32| format!("{}%", (at * 1e4).round() / 100.0); + let stops: Vec = if map.kind() == latkit::ColormapKind::Categorical { + let n = map.count(); + (0..n) + .map(|i| { + let span = [i, i + 1].map(|at| percent(at as f32 / n as f32)); + format!("{} {} {}", css(map.sample(i as f32)), span[0], span[1]) + }) + .collect() + } else { + (0..=32).map(|i| format!("{} {}", css(map.sample(i as f32 / 32.0)), percent(i as f32 / 32.0))).collect() + }; + Ok(format!("linear-gradient({direction}, {})", stops.join(", "))) +} diff --git a/crates/latkit-js/src/shot.rs b/crates/latkit-js/src/shot.rs new file mode 100644 index 00000000..46801ea5 --- /dev/null +++ b/crates/latkit-js/src/shot.rs @@ -0,0 +1,192 @@ +//! Pictures and videos of views: a shot crosses as JSON, +//! `{ size, scale, panels, transparent, deadline, elapsed }` with times in seconds, and draws the views +//! given, whose canvases hold their last frames meanwhile. An image's pixels cross once and its files +//! are written in workers; a video hands back the bytes each frame made, for the page to write. + +use std::cell::RefCell; +use std::io::Write; +use std::rc::Rc; + +use futures_util::future::{AbortHandle, Abortable}; +use wasm_bindgen::prelude::*; + +use crate::Error; +use crate::canvas::{Handle, views_of}; + +/// RGBA pixels, straight alpha, rows top to bottom. +#[wasm_bindgen] +pub struct Image(latkit::Image); + +#[wasm_bindgen] +impl Image { + #[wasm_bindgen(getter)] + pub fn width(&self) -> u32 { + self.0.size[0] + } + + #[wasm_bindgen(getter)] + pub fn height(&self) -> u32 { + self.0.size[1] + } + + /// The pixels, copied. + #[wasm_bindgen(getter)] + pub fn rgba(&self) -> Vec { + self.0.rgba.to_vec() + } + + /// The job writing the image as a `png`, `jpeg` at `quality` from 1 to 100, or `webp` file, for a + /// worker to do. + #[wasm_bindgen(js_name = encodeJob)] + pub fn encode_job(&self, format: &str, quality: Option) -> Result, Error> { + let quality = match quality { + None => 90, + Some(q) if (1.0..=100.0).contains(&q) => q.round() as u8, + Some(_) => return Err(latkit::Error::invalid("a quality runs from 1 to 100").at("quality").into()), + }; + let format = match format { + "png" => latkit::ImageFormat::Png, + "jpeg" => latkit::ImageFormat::Jpeg { quality }, + "webp" => latkit::ImageFormat::WebP, + other => return Err(latkit::Error::invalid(format!("no image format {other:?}")).at("format").into()), + }; + Ok(latkit::host::Job::encode(&self.0, format).into_bytes()) + } +} + +/// The picture `shot` (JSON) takes of the views of `views`, one per panel, once they are complete +/// and still. +#[wasm_bindgen] +pub fn image(shot: &str, views: Vec) -> Result { + let shot: latkit::Shot = crate::json("shot", shot)?; + let views = views_of(views); + Ok(wasm_bindgen_futures::future_to_promise(async move { + let image = latkit::web::image(&shot, &views).await.map_err(|e| JsValue::from(Error::from(e)))?; + Ok(Image(image).into()) + })) +} + +/// Bytes a video wrote and the page has not yet taken. +#[derive(Clone, Default)] +struct Written(Rc>>); + +impl Write for Written { + fn write(&mut self, bytes: &[u8]) -> std::io::Result { + self.0.borrow_mut().extend_from_slice(bytes); + Ok(bytes.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + +/// A video of a shot's pictures, encoded by WebCodecs as frames are drawn. +#[wasm_bindgen] +pub struct Video { + /// The video, or nothing while a frame draws it, and once it is finished. + inner: Rc>>>>, + written: Written, + fps: f64, + frames: Rc>, + active: Rc>>, +} + +#[wasm_bindgen] +impl Video { + /// Seconds into the video the next frame shows at. + #[wasm_bindgen(getter)] + pub fn time(&self) -> f64 { + *self.frames.borrow() as f64 / self.fps + } + + /// Frames drawn or held so far. + #[wasm_bindgen(getter)] + pub fn frames(&self) -> f64 { + *self.frames.borrow() as f64 + } + + /// Draws the next frame of the views of `views`, one per panel; resolves to the bytes of the file + /// ready to write, once there is room for another frame. + pub fn frame(&self, views: Vec) -> js_sys::Promise { + let (inner, written, frames) = (self.inner.clone(), self.written.clone(), self.frames.clone()); + let views = views_of(views); + self.cancellable(async move { + let taken = inner.borrow_mut().take(); + let error = || latkit::Error::invalid("a video draws one frame at a time, until it is finished"); + let mut video = taken.ok_or_else(|| JsValue::from(Error::from(error())))?; + let drawn = latkit::web::frame(&mut video, &views).await; + *frames.borrow_mut() = video.frames(); + *inner.borrow_mut() = Some(video); + drawn.map_err(|e| JsValue::from(Error::from(e)))?; + Ok(js_sys::Uint8Array::from(&std::mem::take(&mut *written.0.borrow_mut())[..]).into()) + }) + } + + /// Cancels an in-flight operation, releasing its views and encoder when the future is dropped. + pub fn cancel(&self) { + if let Some(active) = self.active.borrow_mut().take() { + active.abort(); + } + self.inner.borrow_mut().take(); + } + + /// Encodes every frame under way and ends the video; resolves to the file's last bytes. + pub fn finish(&self) -> js_sys::Promise { + let (inner, written) = (self.inner.clone(), self.written.clone()); + self.cancellable(async move { + let taken = inner.borrow_mut().take(); + let video = taken.ok_or_else(|| JsValue::from(Error::from(latkit::Error::Cancelled)))?; + video.finish().await.map_err(|e| JsValue::from(Error::from(e)))?; + Ok(js_sys::Uint8Array::from(&std::mem::take(&mut *written.0.borrow_mut())[..]).into()) + }) + } +} + +impl Video { + fn cancellable( + &self, + future: impl std::future::Future> + 'static, + ) -> js_sys::Promise { + let mut active = self.active.borrow_mut(); + if active.is_some() { + return js_sys::Promise::reject(&JsValue::from(Error::from(latkit::Error::invalid( + "a video runs one operation at a time", + )))); + } + let (abort, registration) = AbortHandle::new_pair(); + *active = Some(abort); + let active = self.active.clone(); + wasm_bindgen_futures::future_to_promise(async move { + let result = Abortable::new(future, registration).await; + active.borrow_mut().take(); + result.unwrap_or_else(|_| Err(JsValue::from(Error::from(latkit::Error::Cancelled)))) + }) + } +} + +impl Drop for Video { + fn drop(&mut self) { + self.cancel(); + } +} + +/// A video of `shot`'s (JSON) pictures at `fps` frames a second, as MP4 at `bitrate` bits a second +/// or about 0.15 bits a pixel a frame. +pub(crate) fn video(gpu: &latkit::Gpu, shot: &str, fps: f64, bitrate: Option) -> Result { + let shot: latkit::Shot = crate::json("shot", shot)?; + let written = Written::default(); + let mut mp4 = latkit::Mp4::new(written.clone()); + if let Some(bitrate) = bitrate { + mp4 = mp4.bitrate(bitrate as u32); + } + let video = shot.video(gpu, fps, mp4)?; + Ok(Video { inner: Rc::new(RefCell::new(Some(video))), written, fps, frames: Rc::default(), active: Rc::default() }) +} + +/// Has videos encoded by what `create` makes of `(width, height, fps, bitrate)`: the npm package's +/// WebCodecs encoder. +#[wasm_bindgen(js_name = setEncoder)] +pub fn set_encoder(create: js_sys::Function) { + latkit::host::Browser::set_encoder(create); +} diff --git a/crates/latkit/ARCHITECTURE.md b/crates/latkit/ARCHITECTURE.md new file mode 100644 index 00000000..ada7b81a --- /dev/null +++ b/crates/latkit/ARCHITECTURE.md @@ -0,0 +1,371 @@ +# latkit + +Columnar data drawn as vertices, edges, faces, lines, and areas on the GPU. This file is the plan. +✓ done · ◐ partial · ○ to do. + +```sh +cargo xtask check # fmt, clippy, tests, docs, TypeScript, browser gate +cargo xtask browser # the browser gate: shader compile budgets, then every example page in Chrome +cargo xtask bench # every scenario swept over sizes in Chrome: time, work, and how each grows +cargo xtask wasm # latkit-js → npm/pkg, the npm wrapper → npm/dist (--dev: no LTO) +cargo xtask examples # wasm --dev, then the examples at http://127.0.0.1:5200 (--open: in the browser) +``` + +## Foundation + +1. **One direction:** data → derived data → motion → pixels. Structure comes from data on the CPU, + never from a readback; readbacks only answer questions (pick, locate), size GPU work, and carry + pictures out. +2. **The camera is only an eye:** no derivation reads it. Labels hang from world anchors projected + every frame; screen-space decisions (legibility, map label collisions) only toggle visibility, + and only labels that show have their texts set. +3. **Derived data is data:** places, sizes, boxes, routes, lanes, triangles, and earth paths are + columns the view keeps beside each table, row for row, paged, uploaded, and eased like any column. + Every derivation shares one lifecycle (`src/derive/`): a stamp of what it reads; work that fits + the frame's one budget done on it; the rest a host job answering a `Patch`, kept only where what + it was asked from still holds. Tiles are the camera asking: the one derivation reading it. +4. **Motion eases changes, never drives them:** data and derived data ease alike; changes during a + drag apply at once; geometry morphs point by point, by fraction along where the counts differ. + **Time is an input:** every frame and input carries the time of whatever draws it (an animation + frame, a video frame, a test's step), and each view's clock moves by the steps between, a quarter + second at most and never back. Eases, flights, coasting, orbits, fades, and `elapsed()` read it, + never the wall, and what reads it evaluates only when it moves. +5. **Primitives:** points, strokes, triangles, glyphs. A stroke runs along one path kind, fixed per + pipeline: ends (straight, geodesic, lanes), trace (samples), or geometry (any written polyline); + a triangle's corners come from ends (faces) or geometry (areas). Geometry is a field: vertices + read points, lines paths and rings, areas polygons, from `geometry` unless told otherwise. A text + run is rasterized once by the host and made a distance field on the GPU: any size, halo from the + field. +6. **Lists:** count → scan → write. Capacity is a CPU-known bound; a list past it coarsens every + item instead of dropping the last. +7. **Eyes:** every pass draws through an `Eye` (projection, size, pixel ratio): the view or the shadow + light. A picture is a frame like any other, drawn at a size of its own. +8. **Geometry is the world's:** lanes bow by a share of their edge's length, arcs follow great + circles, and both are pieces of the path, so the camera never reshapes them. The globe writes its + depth a hair under its surface, and a mark past its horizon draws nothing. A segment list keeps + each segment's distance along its path, so dashes and comets run on across segments. +9. **Work follows what shows:** a view plans what it draws within its share of the `Budget`. A + table draws whole while it fits and is no denser than a screen shows; a larger one a mark places + on a map or a plane draws through tiles. A job gives each row the coarsest level it shows at, by + its size, then its `priority`; edges land by their own, carrying their ends. The rows of the tiles + the camera wants, as many as the plan holds, are the dataset marks draw, so glow, lanes, + transitions, and labels work unchanged, and picks and selection name source rows. A table a mark + traces draws whole, its traces as coarse in time as fit. GPU pages are one size in one pool, the + least recently drawn evicted first, so what draws always fits. +10. **Complete:** a frame is complete when nothing in it stands in for work under way: no page + waiting to upload, no tile drawn as its ancestor, no table as its first sample, no row standing + where it was until a layout lands, no wire drawn as elbows, no area as its earlier triangles, no + label at its estimated size, no fit due. Every derivation says so of itself, and `Stats::waiting` + names what a frame stood in for; pictures, video frames, tests, and the benchmark wait on the one + predicate. +11. **Events tell what the application did not do itself:** setters are silent. An intent (click, + open, menu, drag, connect, delete) is told once, in the order the user acted; one waiting on a + pick holds the intents after it. A change (hover, selection, camera, `Waiting`) tells only its + latest, and its state can always be read (`hovered`, `selection`, `camera`, `Stats::waiting`, + `failures`), so a listener added late reads what it missed. Every intent and hover carries its + `Trigger`: point, keys, and device. The keys are a device: Tab and arrows step the hover through + rows. Events cross to JavaScript as JSON, a batch per dispatch, like all of a view's state. + +## Rules + +- CPU per frame is O(marks), plus O(changed pages) on new data, O(sampled pages) when `at` moves, + and O(rows drawn) when the tiles the camera wants change. +- Work superlinear in graph size runs in a host job, never on the frame. +- Picks probe what the frame drew, through the draws' own geometry: one probe program per kind of + mark answers the hover, picks, boxes, and `locate`, a step at a time. Hover follows the frame: + what the pointer rests on is probed again whenever the frame changes under it, one probe in flight; + `Controls::hover` only says whether it glows. +- A scene asks for every pipeline it can use the first time it draws into a target: what it draws + and changes with, all at once, then what lights rows, probes, and answers queries, a few at a time + while frames draw. In a browser they compile off the GPU's thread: the view draws once the first + landed, and lights rows, probes, and answers queries once the rest did, so no frame waits on a + compile and nothing compiles where it is first used (`Work::late` counts what does); only custom + markers compile WGSL at runtime. +- Nothing is read back that the CPU knows: a diagram's sheet and tiles' pyramids frame a fit at once, + labels place once a fit has moved the camera, and a segment list's count is read back one at a time + only when the places its paths bend by change. +- Motion is the view's own only where the user's system allows it (`Controls::motion`): under + reduced motion changes apply at once, flights jump, nothing coasts or orbits, labels show without + fading, and comets and what reads `elapsed()` hold still, so a still view needs no frames. +- Every order the user can see comes from count → scan → write or a sort on the CPU, never from + the order atomic appends land in. +- Every shader passes naga at build time and Chrome within its compile budget. +- Every wait races a deadline; readbacks are taken, never awaited. A view sleeps while it waits: + readbacks, jobs, and fetches wake it as they land, and a frame whose work the next one lands + (uploads past the budget, a fit or layout due) asks for it. Canvases and shots draw on that alone. +- Size never fails a draw: the plan always fits the budget, and `priority` decides what draws first, + on top, and labeled. +- No public type before it draws. `Stats::gpu_ms` is the median of the last frames the device timed. +- Work is counted exactly (`Gpu::work`: bytes uploaded and written, rows evaluated, readbacks, jobs, + texts, pipelines); every write goes through the counting queue. The benchmark (`benchmark/`) climbs + each scenario's sizes while the last one fits a phase's limit, times each phase from its action to + the frame where every view is complete, holds it to how it may grow, to the committed work, and to + this machine's times, and stops the sweep at a lost device. +- A dataset's versions ease from one to the next; another dataset of the same name replaces it, its + rows fading in as the old fade out. Rows that only fade evaluate once. +- Every input is a form: a plain struct serde reads, its schema the format (`latkit::schemas`), and + `latkit::from_json` names the path to what it could not read. JSON, JavaScript, and the CLI decode + through the same forms, and npm's types are written from them (`npm/schema.json` → + `npm/src/inputs.ts`, `outputs.ts`); a test fails when either drifts. Data documents stream their + values, never made a JSON value first. +- One build holds every part. Features choose only drawing and a host: `gpu` (on by default; + without it, a build of data, bytes, and JSON alone), `native` (`host::Native`: system fonts, + workers, files, and Media Foundation's H.264 on Windows), and `web` (`host::Browser`, and `web`'s + `Canvas` and `PageView`, for `wasm32`). Shaders store each distinct declaration once; a variant + joins its own. +- A picture composes on the GPU into exactly the bytes its consumer takes, RGBA for an image and + NV12 for an encoder; the CPU touches no pixel. A view draws at one size at a time: while a shot + draws it, its canvas holds its last frame. + +## Spaces + +| Space | Positions | Lengths | Camera | Only here | +| --------- | ------------------- | ------------------------- | -------------------------------- | ----------------------------------------------- | +| `Earth` | longitude, latitude | CSS px, or `units` | pitch, bearing; mercator ↔ globe | geodesic edges, tiles, daylight, atmosphere | +| `Plane` | x, y, elevation | CSS px, or `units` | pitch, bearing | | +| `Plot` | axis, value | CSS px | x and y ranges | axes, playhead | +| `Diagram` | x, y down | units: a CSS px at zoom 0 | center, zoom | ports, groups, nets, orthogonal routes, layouts | + +## Diagram + +A 2D sheet. Every length is a unit, theme lengths included; strokes keep at least a hairline, and +only glow, halo, and pick radius stay pixels. Zooming scales one fixed picture. + +- **Sheet** (`src/sheet/`): sizes (a block without one fits its label and ports) → places → boxes + (groups innermost first: members, padding, header band) → wires (routes, or elbows until a job + lands). It writes a derived table beside each table it draws. +- **Structure reads data only:** position and size can't read hover, zoom, time, or sampled fields + (a compile error naming the option). Looks read anything on the GPU, so live values recolor a + diagram without touching its structure. `visible` is a look: hidden rows fade, nothing moves. +- **Stable:** places persist by row id, even after a row leaves, and a row that loses its position + stays where it stood. A layout places only rows without one, with placed rows as pins. A wire + routes again only when its terminals move or a box near it changes. `View::arrange` lays every + row without a position out again; rows stand where they are until it lands, then ease there. +- **Interaction:** a drag's patches show at once; a moved row's wires route again on the frame, and + a large change routes in a job, its wires keeping their routes, or elbows where their ends moved, + until it lands. `locate` answers from the sheet. +- **Look:** labels hang from their anchors every frame, scale with the sheet, show while they fit, + and fade below a legible size; port labels sit inside their markers. Groups draw a header band + with their title, a hairline border, and a fill tinted by depth. Wires round their bends, dot + their junctions, and point at inputs; outputs drive their nets. Free ports are hollow. Hover + glows; nothing grows. + +## Geography + +- **Data:** `Data::read(bytes, Some(name))` reads GeoJSON (gzip-compressed or not) into tables + `points`, `lines`, and `polygons`, properties as fields; npm reads it in a worker. +- **Tiles:** `View::set_tiles(Tiles::new(name, url))` takes a PMTiles archive, TileJSON, or a + `{z}/{x}/{y}` template. The camera picks tiles that draw at most their size, nearest first; the host + fetches them (`Host::fetch`, ranges for archives); jobs decode them, clipped to their tile, into a + dataset the view owns. A layer is a table of the kind its marks draw (or `layer:polygons|lines|points`); + row ids come from the tile and the feature's place, so they are stable. A tile not loaded draws its + nearest loaded ancestor; fetched bytes stay within a budget, least recently drawn first. +- **Shapes:** areas triangulate by ear clipping with holes, in a job when large, kept per page and per + row so a tile landing shapes only its rows. On the earth, longitudes unwrap across the antimeridian, + triangles split along a 2° grid and paths gain points every 2°, so both bend with the globe. +- **Look:** `Earth::daylight(seconds)` lights the ground and what stands on it by the sun at that + instant plus the view's axis coordinate, down to the theme's `night`; `atmosphere` rings the globe. + Globe gestures keep the point under the pointer exactly. + +## Pictures and video + +- **Shot** (`src/shot.rs`): plain data, a picture of views each drawn into its panel of `size` pixels + at `scale` pixels per CSS pixel. `image(views)` steps the views' clocks a sixtieth of a second while + they ease and waits while work is under way, within a deadline, until every view is complete and + still; `compute/compose.wesl` then writes each panel in whole words, and a plain buffer copy + reads the RGBA back. `Image::encode` writes it as PNG, JPEG, or lossless WebP; jobs do the same + on the host's workers, as npm's `Image.encode` does. `Panels` lay views out in a picture, a + video, and a browser canvas alike. +- **Browser** (`src/web.rs`): a `PageView` is a view the page holds, with or without a canvas; a + `Canvas` shows views in the panels of a ``, or an `OffscreenCanvas` in a worker, and + feeds each the input landing on its panel. One view filling a canvas draws straight into it; + several draw into textures of their own, only those that changed, copied into place. +- **Video** (`src/video/`): a shot's frames at a fixed rate handed in order to a `Sink`, which + says the `Pixels` it takes (RGBA or NV12), composed on the GPU, and begins with the video's + `Encoding` and the host; three frames under way (one drawing, one reading back, one in the sink). + A frame where nothing moved is neither drawn nor read back: the sink is told it is held. `Mp4` is + the sink most videos take: the host's `Encoder` (`host::Encoder`, owned NV12 in, Annex B out, no + B-frames: WebCodecs in a browser, which npm hands the host; Media Foundation natively on Windows, + hardware where present, on a thread of its own) and `mp4.rs`, fragmented MP4 written as it goes, + a fragment per keyframe run. A frame lasts until the next one's time, so held frames cost nothing. +- **Titles and legends**: a scene's `title` and `subtitle`, and a mark's `legend` (its colormap + across the domain, or a cell a category), draw as overlay sprites with a plot's axes, O(legends). +- **Lending:** views lend themselves to a drawing a step at a time (`shot::Views`), so a canvas's + view is borrowed only while a step draws it and the page reads it between steps. + +## Tree + +``` +crates/latkit/ +├── build.rs, build/ link WESL, validate with naga, store each declaration once, mirror shared +│ constants; colormaps; shaders.json +├── shaders/ +│ ├── lib/ types, bind, read, trace, project, state, color, focus, points, path, triangles, +│ │ stroke, marker, label, shade, lists, mark, reduce +│ ├── compute/ evaluate, freeze, bounds, normals, probe, lists, labels (map label collisions), +│ │ compose (a shot's panels into RGBA or NV12), fields (text's distance fields) +│ └── draw/ backdrop (daylight, atmosphere), points, strokes, triangles, areas, glyphs, shade, overlay +├── src/ +│ ├── lib.rs the only entry point +│ ├── tiles.rs Tiles, TileKey: data fetched in pieces by key +│ ├── error.rs, pending.rs, image.rs (PNG, JPEG, WebP), time.rs (bounded waits), panels.rs +│ ├── schema.rs every input's JSON Schema, from its form +│ ├── shot.rs Shot, the drawing that steps views and composes their panels +│ ├── video/ Video, Sink, Pixels, Mp4, Encoder, Encoding, Unit; mp4 (fragmented, as it goes) +│ ├── data/ columns, ids, samples, tables, patches, bytes (streamed), forms (what JSON and +│ │ JavaScript write), JSON loads, query, describe and envelope, inverse references +│ ├── expr/ compile, form, color, colormap, ramp (the build's too), cpu: the executor structure reads +│ ├── scene/ Scene, marks (Vertices, Edges, Faces, Lines, Areas), Label, Port, Marker, Layout, Theme, +│ │ Controls, spaces, form +│ ├── derive/ Derive, Jobs (one budget, one pool), Derivations: graph (marks, joins, links), lanes, +│ │ places, stars, shapes, tiles; sight (what +│ │ the camera sees, as tiles), pyramid (each row's level, in jobs), tiled (the rows drawn) +│ ├── sheet/ a diagram's sizes, places, and boxes (mod), and its wires: a derivation +│ ├── layout/ layered, stress, overlap, pack, route (groups as soft obstacles) +│ ├── view/ View; clock, camera, rig, gestures, input, event; probe, focus, query, fit, axes, legends; plan, marks, +│ │ program, sync, rows, transition, lists, labels, graph, shadows, variants, resources, +│ │ uniforms, wake, timer, passes, frame +│ ├── gpu/ Gpu, Budget, work (Work, the counting queue), arena (fixed pages, one pool), pipelines, +│ │ atlas (distance fields), readback, colormaps, icons +│ ├── host/ Host (text, jobs, fetch, encoder), Job, browser (workers, canvas text, fetch, WebCodecs), +│ │ native (fonts, workers, files, Media Foundation) +│ ├── geo/ geojson, mvt, pmtiles, tiles, shapes, earcut +│ └── web.rs Canvas: its surface, frames, input, events; pictures and video frames of canvases +└── tests/ + +benchmark/ the benchmark: one page (scenarios, the stage measuring phases, data), the runner, + the judge (rules, orders, baselines), the report, baselines/ (work, times per machine) +``` + +## API + +```rust +use latkit::*; + +// Data: named tables, changed in place by patches; a clone is an O(1) snapshot. A reference names rows of another table. +let mut grid = Data::new("grid"); +grid.apply( + Patch::new() + .replace(Table::new("Bus", Ids::count(3)).field("lon", [-97.7, -96.8, -95.4]).field("lat", [30.3, 32.8, 29.8]).field("name", ["A", "B", "C"]).field("kv", [345.0, 138.0, 69.0])) + .replace(Table::new("Branch", Ids::count(2)).reference("from", "Bus", [0_u64, 1]).reference("to", "Bus", [1_u64, 2]).field("p", [120.0, -40.0]).field("kv", [345.0, 138.0])), +)?; +grid.apply(Patch::new().append([0.5], "Bus", [("vm", [1.01, 0.99, 1.0])]))?; // a sampled frame +let grid = Data::load(&json, "data/grid.json", &host).await?; // any language's JSON; files' slices fetched + +// Reading back: a query is plain data run through the expressions marks draw with; it returns a table. +let hot = grid.query(&Query::of("Branch").filter(field("p").gt(100.0)).sort(field("p"), Order::Descending).limit(12))?; +let described = grid.describe(); // tables, rows, kinds, axis, span +let envelope = grid.table("Bus").unwrap().envelope("vm", [0.0, 3600.0], 600, None)?; // least and greatest, from levels +while let Some((patch, used)) = Patch::decode(&buffer, 1 << 28)? { // patches back to back, as a socket brings them + grid.apply(patch)?; + buffer.drain(..used); +} + +// A map: marks name their data; options are expressions. Geometry is a field. +view.set_data(Data::read(&bytes, Some("states"))?); +view.set_tiles(Tiles::new("base", "https://tiles.openfreemap.org/planet")); +let map = Scene::new(Earth::globe().daylight(1_782_043_200.0).atmosphere(true)) + .draw(Areas::of("base", "water").color(Color::hex("#1d3557")?)) + .draw(Areas::of("states", "polygons").color(field("load").colormap(Colormap::MAKO))) + .draw(Lines::of("base", "transportation").width(field("lanes"))) + .draw(Edges::of("grid", "Branch").ends("from", "to").flow(field("p")).priority(field("kv"))) + .draw( + Vertices::of("grid", "Bus") + .position("lon", "lat") + .priority(field("kv")) // draws first, on top, and labeled; shows coarsest + .color(field("vm").colormap(Colormap::BALANCE).domain(0.95..=1.05)) + .label(Label::new("name")), + ); + +// A plot of a sampled field across the data's axis. +let plot = Scene::new(Plot::default()).draw(Lines::of("grid", "Bus").trace("vm")); + +// A diagram: blocks with ports, nets, and groups, placed in ranks and wired around blocks. +let diagram = Scene::new(Diagram::default()) + .layout(Layered::default()) // layouts are a diagram's alone + .controls(Controls { connect: true, delete: true, select_box: true, ..Controls::default() }) + .draw(Vertices::of("plant", "Group").contains("Block", "group").label(Label::new("name"))) + .draw(Edges::of("plant", "Signal").route(Route::Orthogonal).arrows(true)) + .draw( + Vertices::of("plant", "Block") + .position("x", "y") // rows without x and y are placed + .size(120.0, 44.0) // without it, a block fits its label and ports + .marker(Shape::Rounded) + .port("in", Side::Left) + .port("out", Port::output(Side::Right)) // outputs drive their nets: ranks and arrows follow + .drag(true) + .label(Label::new("name")), + ); + +// A view draws a scene from data by name into the caller's encoder, and turns input into events. +gpu.set_budget(Budget { bytes: 512 << 20, upload_per_frame: 32 << 20 }); // before data draws +let mut view = View::new(&gpu, diagram)?; +view.set_data(plant); // cheap: unchanged pages are shared +view.fit(Fit::All); +view.render(&mut encoder, &frame); // each frame, at its time; the caller submits +view.input(&input, time); +for event in view.events() { // in the order the user acted + match event { + Event::Drag { hit, position, .. } => {} // patch hit.row's x and y to position + Event::Connect { from, to: Some(to), .. } => {} // name from's net in to's port + Event::Delete { rows, .. } => {} // remove the rows + Event::Menu { hits, trigger } => {} // a menu at trigger.point, for the keys too + _ => {} + } +} +let hits = view.pick([120.0, 80.0], 6.0); // Pending>, nearest first +view.arrange(); // lay out every row without a position again +let Stats { rows, drawn, draws, resident, waiting, .. } = view.stats(); // rows, draw calls, GPU bytes, work under way + +// Pictures and video: plain data, drawn once every view is complete. +let png = Shot::new([3840, 2160]).scale(2.0).image(&mut [&mut view]).await?.encode(ImageFormat::Png)?; +let shot = Shot::new([1920, 1080]).scale(1.5).panels([[0.0, 0.0, 1.0, 0.7], [0.0, 0.7, 1.0, 0.3]]); +let mut video = shot.video(&gpu, 60.0, Mp4::new(file))?; // or any Sink: raw frames, PNGs +while video.time() < 24.0 { + map.set_at(video.time() * 3600.0); // the script is the loop + video.frame(&mut [&mut map, &mut plot]).await?; +} +video.finish().await?; +``` + +npm `latkit` mirrors the crate with scenes as JSON; its `Data.apply` changes data in place and +`snapshot()` keeps a version, GeoJSON (`Data.read`) and `Image.encode` run in a worker, and +`Shot.video` encodes with WebCodecs: + +```ts +const panels = [ + [0, 0, 1, 0.7], + [0, 0.7, 1, 0.3], +] as const; +const [map, plot] = [gpu.view(mapScene), gpu.view(plotScene)]; +gpu.canvas(element, { panels }).show([map, plot]); // one canvas, input routed by panel +const png = await ( + await new Shot([3840, 2160]).scale(2).panels(panels).image([map, plot]) +).encode('png'); +const video = new Shot([1920, 1080]).panels(panels).video(gpu, 60, writable, { signal }); +await video.record( + [map, plot], + (time) => ((map.at = plot.at = time * 3600), time < 24), + onProgress, +); +``` + +## Milestones + +| Step | Contents | Status | +| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | +| M1–M4 | data, expressions, arena, probes; transitions, shadows; labels, picks, samples; graph, layouts, routes, groups | ✓ | +| Gate, Cutover, Pages | browser gate; host jobs in workers, path kinds, lists that coarsen; telemetry and diagram studio pages | ✓ | +| Sheet | `Diagram`; derived data and geometry pages; the CPU executor; the sheet with incremental layout and routing; jobs answer with patches; stress as a job; `Port::output`; `arrange`; anchored labels and distance-field text; drags apply at once; the diagram page rebuilt on it. Removed folding, the GPU groups and stress passes, stand-ins, and the view's layout and route words | ✓ | +| M5 | `src/derive/`: one lifecycle, budget, and pool for the sheet, lanes, shapes, and tiles; geometry as a field (lines along paths and rings); `Areas` (ear clipping in jobs, cached per page and row, earth grid split); `geo::geojson`; `Host::fetch`, PMTiles, TileJSON, MVT decoded in jobs into a view-owned dataset; daylight, atmosphere, exact globe gestures; groups as soft router obstacles; atlas residency by placement; Grid at scale and Colors pages | ✓ | +| Scale | `cargo xtask bench` and budgets; GPU time in `Stats`; fixed pages in one pool within a `Budget`; plans that always fit; tiles for anything large (pyramids in jobs, edges with their ends); `priority`; views that sleep while they wait; lanes as world-space bows; globe occlusion by depth; dashes and comets along paths; focus draws only lit rows; bulk column reads; the 2M-bus grid and Grid operations pages | ✓ | +| M6 | time as an input (`Frame`, `input(time)`, the view's clock); `complete`; `Shot` and `Image` (compose pass, PNG in a worker); `Video` (NV12 on the GPU, three frames under way, held frames free, fragmented MP4, `Host::encoder` with WebCodecs); npm `Shot`, `Image`, `Video` | ✓ | +| Interaction | `Event` as intents and changes in one ordered queue (picks hold their place, changes keep their latest); `Trigger` (point, keys, `Device`) on every intent and hover; silent setters; `hovered`, `failures`, the `Waiting` event; hover follows the frame, `Controls::hover` only glows; the keys step, open, and select; npm events and view state as JSON, a batch per dispatch; ids checked, never truncated | ✓ | +| CLI | `latkit-cli`: render, validate, inspect, frames loaded ahead; `Sink`, `Pixels`, `Mp4`, the encoder seam in `host`; `Native` a shared handle with H.264 (Media Foundation), files, and fetches on its workers; `Data`/`Patch` loaded from JSON through the host, `Values` and `Ids` from loose values by one rule, `Shot` as JSON; titles, mark legends; views ask for the frame their work lands on; no `serde` feature | ✓ | +| Capture | `Panels` for pictures, videos, and canvases; a browser `Canvas` showing several views, input routed per panel, `OffscreenCanvas` in workers; `PageView`; `ImageFormat` (PNG, JPEG, lossless WebP) encoded on the host's workers; npm `Video.record`/`abort`; label placement that settles under time-reading channels; an Export section on every page | ✓ | +| Data contract | `Data::query` (filter, sort, top-k, page, select, `at`), `describe`, `Table::envelope` from levels, `Table::values`; `Patch::decode` for streams with a byte limit, `Patches` for frames; one decoder for JSON and JavaScript (`forms.rs`, typed arrays as bytes); frames keep their numbers through bytes and gathers; ids above 2^53 cross as text; `latkit::schemas`, `latkit schema`, `latkit query`, npm types written from the schema | ✓ | +| Controls | `Zoom` (wheel, modifier as a trackpad's pinch sends it, off), click cycling, long press for touch and pen menus, `Motion` with `prefers-reduced-motion`, `Controls::none`/`inspect`; pipelines staged over the opening frames for the hover and the controls' intents; transitions of no length so comets follow rows moved without easing; `arrange` answers patches of the places; layouts place points on planes and the earth | ✓ | +| Drawing | sizes in units kept within CSS pixels (`at_least`, `at_most`); `Edges::poles`; nets outside diagrams as stars (`Edges::joins`); label `font` and `max` (a radix select on the GPU); one ramp for the catalog and your own maps, blended in OKLab with placed stops; `colormapCss` for any map, a band per category; `Stats::draws`, `instances`, `tiles`, `tiles_loading` | ✓ | +| Retire | pages ported: Telemetry's quantities, ranges, colormaps, and hot list by `query`; the diagram's menu, rename on open, neighbors, unplugging, layouts four ways, light theme, zoom; Grid at scale's map alone, download progress, insets; Colors' light field, kinds, and a map with alpha; Signals, two views on one canvas under one playhead; a motion choice; models tested with vitest; vector tiles clipped whole and earcut as of 3.2, so holes across a tile's edge no longer fill it; `packages/`, `examples/`, `benchmark/`, `docs/` deleted; one pnpm workspace of `npm/`, CI, and a release of the crates and the npm package together | ✓ | +| Foundation | one build of every part (part features removed); WGSL stored once per declaration; picks as data, so `assemble` compiles once; evaluation by row block (only the pages a patch wrote) and transitions as a blend pass; one budget per `Gpu`, shares granted max-min fair with pages several views draw counted once, and the plan a stamped derivation; samples a sparse pyramid of runs, any level held anywhere, `cover` drawing coarser stand-ins; `Tiling` for map tiles and time spans; time tiles (`Data::to_tiles`, `latkit tile`, `frames.json`, `Patch::frames`, op 6); rows drawn through tiles keep their places, arrivals filling holes; JSON errors naming their path (`from_json`) | ✓ | +| Opening | every pipeline a scene uses asked for at once and compiled side by side off Chrome's GPU thread, the view drawing once they landed (`View::ready`, `Waiting::compiling`, `Work::late`); fits framed from the sheet and tiles without a readback, labels placed once a fit moved the camera, one segment count in flight keyed by places; a patch of values writes only the rows that changed in tables drawn in part; strokes cut at the near plane and their pixels interpolated on screen; geometry picks only when asked; a lit group glows about its border, lit rows keep their ports on top, wires stop at port rims, no repeated points in rounded wires, drags keep where a row was grabbed, unlabeled blocks make room for their ports; error paths through the mark's kind (`marks[2].vertices.color`); the bench steps its frames, each waiting for the GPU (`step`, `done`, `landed`) | ✓ | diff --git a/crates/latkit/Cargo.toml b/crates/latkit/Cargo.toml new file mode 100644 index 00000000..897adac5 --- /dev/null +++ b/crates/latkit/Cargo.toml @@ -0,0 +1,98 @@ +[package] +name = "latkit" +description = "Columnar data drawn as vertices, edges, lines, and areas on the GPU." +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +repository.workspace = true +homepage.workspace = true +keywords = ["visualization", "webgpu", "graph", "map", "plot"] +categories = ["visualization", "rendering", "graphics", "wasm"] +include = ["LICENSE", "src/**", "tests/fixtures/**", "build/**", "build.rs", "shaders/**", "colormaps/catalog.txt", "colormaps/NOTICES.md", "THIRD_PARTY.md", "README.md"] + +# Every feature's API, as CI documents it; target-gated code (Windows video, browser glue) compiles +# out of this one target. +[package.metadata.docs.rs] +all-features = true +targets = ["x86_64-unknown-linux-gnu"] + +[features] +default = ["gpu"] +gpu = ["dep:wgpu", "dep:glam", "dep:web-time", "dep:wesl", "dep:naga"] +native = ["gpu", "dep:cosmic-text", "dep:windows", "dep:windows-core"] +web = ["gpu", "dep:wasm-bindgen", "dep:wasm-bindgen-futures", "dep:web-sys", "dep:js-sys"] + +[dependencies] +url.workspace = true +thiserror.workspace = true +hashbrown.workspace = true +rustc-hash.workspace = true +bytemuck.workspace = true +# JSON: scenes, data, shots, and view state, with the schema of what is read and the path to what +# could not be; GeoJSON and tiles' metadata. Gzip-compressed bytes. +serde = { workspace = true } +serde_json.workspace = true +serde_path_to_error.workspace = true +schemars.workspace = true +flate2.workspace = true +# Images: icons read from PNG; pictures written as PNG, JPEG, or lossless WebP. +image-webp.workspace = true +jpeg-encoder.workspace = true +png.workspace = true +wgpu = { workspace = true, optional = true } +glam = { workspace = true, optional = true } +web-time = { workspace = true, optional = true } + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +cosmic-text = { workspace = true, optional = true } + +# Native video: H.264 from the platform's encoder. +[target.'cfg(windows)'.dependencies] +windows = { workspace = true, optional = true } +windows-core = { workspace = true, optional = true } + +[target.'cfg(target_arch = "wasm32")'.dependencies] +wasm-bindgen = { workspace = true, optional = true } +wasm-bindgen-futures = { workspace = true, optional = true } +js-sys = { workspace = true, optional = true } +web-sys = { workspace = true, optional = true, features = [ + "AddEventListenerOptions", + "CssStyleDeclaration", + "DedicatedWorkerGlobalScope", + "DomRect", + "Element", + "Event", + "EventTarget", + "HtmlCanvasElement", + "Headers", + "HtmlElement", + "ImageData", + "KeyboardEvent", + "MediaQueryList", + "MouseEvent", + "OffscreenCanvas", + "OffscreenCanvasRenderingContext2d", + "PointerEvent", + "Request", + "RequestInit", + "ResizeObserver", + "Response", + "TextMetrics", + "WheelEvent", + "Window", + "WorkerGlobalScope", +] } + +[build-dependencies] +wesl = { workspace = true, optional = true } +naga = { workspace = true, optional = true } + +[dev-dependencies] +proptest.workspace = true +pollster.workspace = true +wgpu.workspace = true +bytemuck.workspace = true + +[lints] +workspace = true diff --git a/packages/gpu/LICENSE b/crates/latkit/LICENSE similarity index 100% rename from packages/gpu/LICENSE rename to crates/latkit/LICENSE diff --git a/crates/latkit/README.md b/crates/latkit/README.md new file mode 100644 index 00000000..b6bc63a4 --- /dev/null +++ b/crates/latkit/README.md @@ -0,0 +1,34 @@ +# latkit + +Columnar data, queries, and scenes rendered with WebGPU, Vulkan, Metal, or DX12. +[Guides](https://latkit.readthedocs.io) | [Rust API](https://docs.rs/latkit) + +```sh +cargo add latkit +``` + +```rust +use latkit::{Data, Ids, Patch, Query, Table, field}; + +fn main() -> Result<(), latkit::Error> { + let mut data = Data::new("grid"); + data.apply(Patch::new().replace(Table::new("Bus", Ids::count(2)).field("kv", vec![115.0, 230.0])))?; + let (high_voltage, total) = data.query(&Query::of("Bus").filter(field("kv").ge(200.0)))?; + assert_eq!((high_voltage.len(), total), (1, 1)); + Ok(()) +} +``` + +- `default-features = false`: data, patches, LATK, JSON loading, queries, expressions, colormaps, + GeoJSON, and images; no GPU dependency. +- `gpu` (default): scenes, views, picking, layouts, and rendering into wgpu targets. +- `native`: system fonts, file loading, jobs, and Windows Media Foundation video. +- `web`: browser integration on `wasm32-unknown-unknown`. + +`cargo install latkit-cli` installs the `latkit` executable. `npm install latkit` installs +the browser runtime and plain-data builders. + +LATK v1 uses 64-bit absolute frame indexes. Sampled values use `f32`; coordinates use `f64`. +See the [format specification](https://latkit.readthedocs.io/en/latest/formats.html). + +MIT licensed. Notices are included in `THIRD_PARTY.md` and `colormaps/NOTICES.md`. diff --git a/crates/latkit/THIRD_PARTY.md b/crates/latkit/THIRD_PARTY.md new file mode 100644 index 00000000..31675b68 --- /dev/null +++ b/crates/latkit/THIRD_PARTY.md @@ -0,0 +1,21 @@ +# Third-party code + +`src/geo/earcut.rs` implements Mapbox Earcut's polygon triangulation algorithm. +Upstream: https://github.com/mapbox/earcut (ISC license). + +Copyright (c) 2024, Mapbox + +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. + +The colormap catalog's source notices and licenses are in `colormaps/NOTICES.md` +(`NOTICES.md` in the npm package). diff --git a/crates/latkit/build.rs b/crates/latkit/build.rs new file mode 100644 index 00000000..43f7e303 --- /dev/null +++ b/crates/latkit/build.rs @@ -0,0 +1,23 @@ +//! Generates the Rust side of the GPU contract from the WESL shaders, and bakes the colormap catalog. + +fn main() { + println!("cargo::rerun-if-changed=build.rs"); + println!("cargo::rerun-if-changed=build"); + println!("cargo::rerun-if-changed=shaders"); + println!("cargo::rerun-if-changed=src/expr/ramp.rs"); + #[cfg(feature = "gpu")] + { + shaders::generate(); + } + colormaps::generate(); +} + +#[cfg(feature = "gpu")] +#[path = "build/shaders.rs"] +mod shaders; + +#[path = "build/colormaps.rs"] +mod colormaps; + +#[path = "src/expr/ramp.rs"] +mod ramp; diff --git a/crates/latkit/build/colormaps.rs b/crates/latkit/build/colormaps.rs new file mode 100644 index 00000000..0bb9462b --- /dev/null +++ b/crates/latkit/build/colormaps.rs @@ -0,0 +1,68 @@ +//! Bakes `colormaps/catalog.txt` into `OUT_DIR/colormaps.rs`: per map its name, label, kind, color +//! count, and 256 sRGB texels, made by the crate's own `ramp`. + +use crate::ramp::{Spread, texels}; +use std::env; +use std::fmt::Write as _; +use std::fs; +use std::path::{Path, PathBuf}; + +pub(crate) fn generate() { + let manifest = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + let catalog = fs::read_to_string(manifest.join("colormaps/catalog.txt")).unwrap(); + let mut entries = String::new(); + let mut consts = String::new(); + let mut names = Vec::new(); + for (index, line) in catalog.lines().filter(|l| !l.trim().is_empty()).enumerate() { + let (head, hex) = line.split_once('|').expect("name kind label|colors"); + let mut words = head.splitn(3, ' '); + let (name, kind, label) = (words.next().unwrap(), words.next().unwrap(), words.next().unwrap()); + let colors: Vec<[u8; 3]> = hex + .as_bytes() + .as_chunks::<6>() + .0 + .iter() + .map(|digits| { + let byte = + |at: usize| u8::from_str_radix(std::str::from_utf8(&digits[at..at + 2]).unwrap(), 16).unwrap(); + [byte(0), byte(2), byte(4)] + }) + .collect(); + let (kind, spread) = match kind { + "sequential" | "multihue" => ("Sequential", Spread::Continuous), + "diverging" => ("Diverging", Spread::Continuous), + "cyclic" => ("Cyclic", Spread::Cyclic), + "categorical" => ("Categorical", Spread::Categorical), + other => panic!("unknown colormap kind {other}"), + }; + let stops: Vec<_> = + colors.iter().map(|c| (None, [c[0], c[1], c[2], 255].map(|b| f32::from(b) / 255.0))).collect(); + let texels: Vec = texels(spread, &stops).iter().map(|t| format!("{t:?}")).collect(); + writeln!( + entries, + " Entry {{ name: {name:?}, label: {label:?}, kind: ColormapKind::{kind}, count: {}, texels: [{}] }},", + colors.len(), + texels.join(", ") + ) + .unwrap(); + let doc = format!("/// {label}, a {} colormap.", kind.to_lowercase()); + writeln!( + consts, + " {doc}\n pub const {}: Colormap = Colormap(Map::Catalog({index}));", + name.to_uppercase() + ) + .unwrap(); + names.push(format!("{name:?}")); + } + let count = names.len(); + let rust = format!( + "// Generated by build/colormaps.rs from colormaps/catalog.txt. Do not edit.\n\n\ + static CATALOG: [Entry; {count}] = [\n{entries}];\n\n\ + #[allow(clippy::doc_markdown, reason = \"the docs name colormaps by their labels\")]\n\ + impl Colormap {{\n{consts}\n /// The names of every colormap in the catalog.\n pub const NAMES: [&'static str; {count}] = [{}];\n}}\n", + names.join(", ") + ); + let out = PathBuf::from(env::var("OUT_DIR").unwrap()); + fs::write(out.join("colormaps.rs"), rust).unwrap(); + println!("cargo::rerun-if-changed={}", Path::new("colormaps").display()); +} diff --git a/crates/latkit/build/shaders.rs b/crates/latkit/build/shaders.rs new file mode 100644 index 00000000..6cdafd69 --- /dev/null +++ b/crates/latkit/build/shaders.rs @@ -0,0 +1,415 @@ +//! Links every WESL entry, validates it with naga, and writes `OUT_DIR/shaders.rs`: +//! +//! - every constant and struct of `lib/types.wesl`, as Rust constants and `#[repr(C)]` mirrors whose +//! size is checked against WGSL; +//! - the shared bind group layouts of `lib/bind.wesl` (group 0 per view, group 1 per mark); +//! - per shader and variant: its declarations, entry points, the layout of its pass group (group 2), +//! and whether it reads the shared groups at all. +//! +//! Variants share most of what they link, so each distinct top-level declaration is stored once, in +//! `OUT_DIR/shaders.wgsl`, and a variant is the list of its declarations, which join back into exactly +//! the module it linked. +//! +//! It also writes each variant's whole module and `OUT_DIR/shaders.json`, every variant's file, entry +//! points, and the pipeline constants it is made with, from which the browser gate times each +//! pipeline in Chrome. + +use std::collections::{BTreeMap, HashMap}; +use std::env; +use std::fmt::Write as _; +use std::fs; +use std::path::{Path, PathBuf}; + +use naga::valid::{Capabilities, ModuleInfo, ValidationFlags, Validator}; +use naga::{AddressSpace, ArraySize, ImageClass, ImageDimension, ScalarKind, StorageAccess, TypeInner, VectorSize}; + +/// A shader module and the variants it is linked in: each variant turns on its WESL features. +struct Entry { + module: &'static str, + variants: &'static [(&'static str, &'static [&'static str])], +} + +const ENTRIES: &[Entry] = &[ + Entry { module: "compute::evaluate", variants: &[("main", &["writes"])] }, + Entry { module: "compute::freeze", variants: &[("main", &[])] }, + Entry { module: "compute::bounds", variants: &[("main", &[])] }, + Entry { module: "compute::normals", variants: &[("main", &[])] }, + Entry { module: "compute::probe", variants: &[("main", &[]), ("multisampled", &["multisampled"])] }, + Entry { module: "compute::lists", variants: &[("main", &["lists"])] }, + Entry { module: "draw::backdrop", variants: &[("main", &[])] }, + Entry { + module: "draw::points", + variants: &[ + ("main", &[]), + ("cast", &["casts"]), + ("custom", &["custom"]), + ("custom_cast", &["custom", "casts"]), + ("custom_focus", &["custom", "focused"]), + ("ports", &["ports"]), + ("focus", &["focused"]), + ], + }, + Entry { module: "draw::strokes", variants: &[("main", &[]), ("cast", &["casts"]), ("focus", &["focused"])] }, + Entry { module: "draw::triangles", variants: &[("main", &[]), ("cast", &["casts"])] }, + Entry { module: "draw::areas", variants: &[("main", &[]), ("focus", &["focused"])] }, + Entry { module: "draw::shade", variants: &[("main", &[])] }, + Entry { module: "draw::glyphs", variants: &[("main", &[]), ("ports", &["ports"])] }, + Entry { module: "compute::labels", variants: &[("main", &[])] }, + Entry { module: "draw::overlay", variants: &[("main", &[])] }, + Entry { module: "compute::compose", variants: &[("main", &[])] }, + Entry { module: "compute::fields", variants: &[("main", &[])] }, +]; + +const FEATURES: &[&str] = &["writes", "casts", "custom", "multisampled", "lists", "ports", "focused"]; + +/// What a custom marker supplies, for validating its variant. +const CUSTOM_MARKER: &str = "fn marker(f: MarkerFragment) -> MarkerColor { return MarkerColor(f.color, 0.0); }"; + +/// Uniforms bound at a dynamic offset: each mark's, each pass's eye, and each probe dispatch's step. +const DYNAMIC: &[&str] = &["mark", "eye", "step"]; + +/// The values each pipeline constant is made with, as constants of `lib/types.wesl`: the primitive a +/// probe reads, and the path a stroke reads. +const OVERRIDES: &[(&str, &[&str])] = &[ + ("PROBED", &["POINTS", "STROKES", "TRIANGLES"]), + ("PATH", &["PATH_ENDS", "PATH_TRACE", "PATH_GEOMETRY", "PATH_POLES"]), +]; + +pub(crate) fn generate() { + let root = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join("shaders"); + let out = PathBuf::from(env::var("OUT_DIR").unwrap()); + let mut rust = String::from("// Generated by build/shaders.rs from the WESL shaders. Do not edit.\n\n"); + + let types = link(&root, "lib::types", &[], true); + let (types_module, _) = validate("lib::types", &types); + mirror_consts(&types_module, &mut rust); + mirror_structs(&types_module, &mut rust); + + let bind = link(&root, "lib::bind", &[], true); + let (bind_module, _) = validate("lib::bind", &bind); + for (group, name) in [(0, "VIEW_GROUP"), (1, "MARK_GROUP")] { + let bindings = bindings(&bind_module, None, group); + writeln!(rust, "pub(crate) static {name}: &[Binding] = &[{}];\n", bindings.join(", ")).unwrap(); + } + + let mut shaders = String::new(); + let mut sources = String::new(); + let mut manifest = Vec::new(); + let mut pieces = Pieces::default(); + for entry in ENTRIES { + for &(variant, features) in entry.variants { + let source = link(&root, entry.module, features, false); + // A custom marker's variant lacks the marker an application supplies; a stand-in validates it. + let custom = features.contains(&"custom"); + let checked = if custom { format!("{source}\n{CUSTOM_MARKER}") } else { source.clone() }; + let (module, info) = validate(&format!("{}.{variant}", entry.module), &checked); + check_shared(&module, &bind_module, entry.module); + let file = format!("{}.{variant}.wgsl", entry.module.replace("::", ".")); + fs::write(out.join(&file), &source).unwrap(); + manifest.push(manifest_entry(entry.module, &file, &module, &types_module, custom)); + let name = shader_name(entry.module, variant); + writeln!(shaders, " {name},").unwrap(); + let pass = bindings(&module, Some(&info), 2); + let overrides: Vec = module.overrides.iter().filter_map(|(_, o)| o.name.clone()).collect(); + let shared = module.global_variables.iter().any(|(_, g)| g.binding.as_ref().is_some_and(|b| b.group < 2)); + writeln!( + sources, + " Shader::{name} => &ShaderSource {{ label: {label:?}, pieces: &{refs:?}, pass: &[{pass}], overrides: &{overrides:?}, shared: {shared} }},", + label = format!("latkit {}.{variant}", entry.module), + refs = pieces.add(&source), + pass = pass.join(", "), + ) + .unwrap(); + } + } + fs::write(out.join("shaders.wgsl"), &pieces.text).unwrap(); + writeln!( + rust, + "/// Where each declaration lies in `shaders.wgsl`.\npub(crate) static PIECES: &[(u32, u32)] = &{:?};\n", + pieces.ranges + ) + .unwrap(); + writeln!(rust, "/// Every linked shader and variant.\n#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]\npub(crate) enum Shader {{\n{shaders}}}\n").unwrap(); + writeln!(rust, "impl Shader {{\n pub(crate) fn source(self) -> &'static ShaderSource {{\n match self {{\n{sources} }}\n }}\n}}").unwrap(); + fs::write(out.join("shaders.rs"), rust).unwrap(); + fs::write(out.join("shaders.json"), format!("[\n{}\n]\n", manifest.join(",\n"))).unwrap(); +} + +/// Top-level declarations, each stored once: their text back to back, and where each lies. +#[derive(Default)] +struct Pieces { + text: String, + ranges: Vec<(u32, u32)>, + index: HashMap, +} + +impl Pieces { + /// The declarations of `source`, as indices, storing those not stored yet; they join back into + /// `source` exactly. + fn add(&mut self, source: &str) -> Vec { + let refs: Vec = source + .split(SEPARATOR) + .map(|piece| { + *self.index.entry(piece.to_owned()).or_insert_with(|| { + let start = self.text.len() as u32; + self.text.push_str(piece); + self.ranges.push((start, self.text.len() as u32)); + u16::try_from(self.ranges.len() - 1).expect("fewer than 65536 declarations") + }) + }) + .collect(); + let joined: Vec<&str> = refs + .iter() + .map(|&r| &self.text[self.ranges[r as usize].0 as usize..self.ranges[r as usize].1 as usize]) + .collect(); + assert_eq!(joined.join(SEPARATOR), source, "a variant's declarations join back into the module it linked"); + refs + } +} + +/// What separates top-level declarations in a linked module, and joins them back. +const SEPARATOR: &str = "\n\n"; + +/// A variant as JSON: its file, whether it draws, its compute entry points, every combination of the +/// pipeline constants it declares, and the WGSL appended to make it whole (a custom marker's stand-in). +fn manifest_entry(shader: &str, file: &str, module: &naga::Module, types: &naga::Module, custom: bool) -> String { + let compute: Vec = module + .entry_points + .iter() + .filter(|e| e.stage == naga::ShaderStage::Compute) + .map(|e| format!("{:?}", e.name)) + .collect(); + let mut combinations: Vec> = vec![Vec::new()]; + for (_, o) in module.overrides.iter() { + let name = o.name.as_deref().expect("a named override"); + let (_, values) = OVERRIDES.iter().find(|(n, _)| *n == name).unwrap_or_else(|| panic!("no values for {name}")); + combinations = combinations + .iter() + .flat_map(|before| { + values.iter().map(move |value| { + let mut next = before.clone(); + next.push((name, type_constant(types, value))); + next + }) + }) + .filter(|c| made(shader, c, types)) + .collect(); + } + let constants: Vec = combinations + .iter() + .map(|c| format!("{{{}}}", c.iter().map(|(n, v)| format!("{n:?}: {v}")).collect::>().join(", "))) + .collect(); + format!( + " {{ \"file\": {file:?}, \"draws\": {draws}, \"compute\": [{}], \"constants\": [{}], \"append\": {:?} }}", + compute.join(", "), + constants.join(", "), + if custom { CUSTOM_MARKER } else { "" }, + draws = compute.is_empty(), + ) +} + +/// Whether a pipeline of `module` is ever made with `constants`: faces read their ends and areas +/// their geometry; a probe made for points reads no path, so it keeps the default one, and one made +/// for triangles reads a face's ends or an area's geometry. +fn made(module: &str, constants: &[(&str, u32)], types: &naga::Module) -> bool { + let value = |name: &str| constants.iter().find(|(n, _)| *n == name).map(|&(_, v)| v); + let path = value("PATH"); + match module { + "draw::triangles" => return path == Some(type_constant(types, "PATH_ENDS")), + "draw::areas" => return path == Some(type_constant(types, "PATH_GEOMETRY")), + _ => {} + } + match (value("PROBED"), path) { + (Some(probed), Some(path)) => { + probed == type_constant(types, "STROKES") + || path == type_constant(types, "PATH_ENDS") + || (probed == type_constant(types, "TRIANGLES") && path == type_constant(types, "PATH_GEOMETRY")) + } + _ => true, + } +} + +/// The value of `lib/types.wesl`'s `u32` constant `name`. +fn type_constant(types: &naga::Module, name: &str) -> u32 { + let (_, constant) = types.constants.iter().find(|(_, c)| c.name.as_deref() == Some(name)).expect("a constant"); + match types.global_expressions[constant.init] { + naga::Expression::Literal(naga::Literal::U32(v)) => v, + _ => panic!("{name} is not a u32"), + } +} + +fn shader_name(module: &str, variant: &str) -> String { + let words = module.split("::").skip(1).chain((variant != "main").then_some(variant)); + words + .flat_map(|w| w.split('_')) + .map(|w| { + let mut chars = w.chars(); + chars.next().map(|c| c.to_ascii_uppercase().to_string() + chars.as_str()).unwrap_or_default() + }) + .collect() +} + +fn link(root: &Path, module: &str, features: &[&str], keep_main: bool) -> String { + let mut options = + wesl::CompileOptions { mangler: wesl::ManglerKind::None, validate: false, keep_main, ..Default::default() }; + for feature in FEATURES { + options.features.set(*feature, features.contains(feature)); + } + let path = format!("package::{module}").parse().unwrap(); + wesl::Compiler::new(options) + .compile_module(root, &path) + .unwrap_or_else(|e| panic!("WESL {module} {features:?}: {e}")) + .to_string() +} + +fn validate(name: &str, source: &str) -> (naga::Module, ModuleInfo) { + let module = naga::front::wgsl::parse_str(source) + .unwrap_or_else(|e| panic!("WGSL {name}:\n{}\n{source}", e.emit_to_string(source))); + let info = Validator::new(ValidationFlags::all(), Capabilities::empty()) + .validate(&module) + .unwrap_or_else(|e| panic!("WGSL {name}:\n{}", e.emit_to_string(source))); + (module, info) +} + +/// Every `const` of a scalar type, as a Rust constant. +fn mirror_consts(module: &naga::Module, rust: &mut String) { + for (_, constant) in module.constants.iter() { + let Some(name) = &constant.name else { continue }; + let value = match module.global_expressions[constant.init] { + naga::Expression::Literal(naga::Literal::U32(v)) => format!("u32 = {v:#x}"), + naga::Expression::Literal(naga::Literal::I32(v)) => format!("i32 = {v}"), + naga::Expression::Literal(naga::Literal::F32(v)) => format!("f32 = {v:?}"), + _ => continue, + }; + writeln!(rust, "#[allow(dead_code)]\npub(crate) const {name}: {value};").unwrap(); + } + rust.push('\n'); +} + +/// Every struct as a `#[repr(C)]` mirror with explicit padding. +fn mirror_structs(module: &naga::Module, rust: &mut String) { + for (_, ty) in module.types.iter() { + let (Some(name), TypeInner::Struct { members, span }) = (&ty.name, &ty.inner) else { continue }; + writeln!( + rust, + "#[repr(C)]\n#[derive(Clone, Copy, Debug, bytemuck::Pod, bytemuck::Zeroable)]\npub(crate) struct {name} {{" + ) + .unwrap(); + let mut at = 0; + let mut pads = 0; + for member in members { + pad(rust, &mut at, member.offset, &mut pads); + let (field_type, size) = rust_type(module, member.ty); + writeln!(rust, " pub(crate) {}: {field_type},", member.name.as_deref().unwrap()).unwrap(); + at = member.offset + size; + } + pad(rust, &mut at, *span, &mut pads); + writeln!(rust, "}}\n\nconst _: () = assert!(size_of::<{name}>() == {span});\n").unwrap(); + } +} + +fn pad(rust: &mut String, at: &mut u32, to: u32, pads: &mut u32) { + if to > *at { + assert_eq!((to - *at) % 4, 0, "padding is whole words"); + writeln!(rust, " pub(crate) _pad{pads}: [u32; {}],", (to - *at) / 4).unwrap(); + *pads += 1; + *at = to; + } +} + +fn rust_type(module: &naga::Module, ty: naga::Handle) -> (String, u32) { + let scalar = |s: naga::Scalar| match (s.kind, s.width) { + (ScalarKind::Float, 4) => "f32", + (ScalarKind::Uint, 4) => "u32", + (ScalarKind::Sint, 4) => "i32", + other => panic!("no mirror for scalar {other:?}"), + }; + let size = |v: VectorSize| v as u32; + match &module.types[ty].inner { + TypeInner::Scalar(s) => (scalar(*s).into(), 4), + TypeInner::Vector { size: n, scalar: s } => (format!("[{}; {}]", scalar(*s), size(*n)), 4 * size(*n)), + TypeInner::Matrix { columns, rows, scalar: s } => { + assert_eq!(*rows, VectorSize::Quad, "matrix columns are padded to four rows"); + (format!("[[{}; 4]; {}]", scalar(*s), size(*columns)), 16 * size(*columns)) + } + TypeInner::Array { base, size: ArraySize::Constant(n), stride } => { + let (element, element_size) = rust_type(module, *base); + assert_eq!(element_size, *stride, "array elements are not padded"); + (format!("[{element}; {n}]"), stride * n.get()) + } + TypeInner::Struct { span, .. } => (module.types[ty].name.clone().expect("a named struct"), *span), + other => panic!("no mirror for {other:?}"), + } +} + +/// The bindings of `group` as `Binding` literals; with `info`, visibility is where entry points use them. +fn bindings(module: &naga::Module, info: Option<&ModuleInfo>, group: u32) -> Vec { + let mut found = BTreeMap::new(); + for (handle, global) in module.global_variables.iter() { + let Some(binding) = &global.binding else { continue }; + if binding.group != group { + continue; + } + let stages = match info { + Some(info) => module + .entry_points + .iter() + .enumerate() + .filter(|(i, _)| !info.get_entry_point(*i)[handle].is_empty()) + .map(|(_, e)| match e.stage { + naga::ShaderStage::Vertex => "VERTEX", + naga::ShaderStage::Fragment => "FRAGMENT", + naga::ShaderStage::Compute => "COMPUTE", + other => panic!("unexpected stage {other:?}"), + }) + .collect::>(), + None => vec!["VERTEX", "FRAGMENT", "COMPUTE"], + }; + let kind = match (global.space, &module.types[global.ty].inner) { + (AddressSpace::Uniform, _) => "Kind::Uniform".to_owned(), + (AddressSpace::Storage { access }, _) => { + format!("Kind::Storage {{ read_only: {} }}", !access.contains(StorageAccess::STORE)) + } + (AddressSpace::Handle, TypeInner::Sampler { .. }) => "Kind::Sampler".to_owned(), + ( + AddressSpace::Handle, + TypeInner::Image { dim: ImageDimension::D2, class: ImageClass::Depth { multi }, .. }, + ) => { + format!("Kind::Depth {{ multisampled: {multi} }}") + } + (AddressSpace::Handle, TypeInner::Image { dim: ImageDimension::D2, arrayed, class }) => { + let filterable = matches!(class, ImageClass::Sampled { kind: ScalarKind::Float, multi: false }); + format!("Kind::Texture {{ array: {arrayed}, filterable: {filterable} }}") + } + other => panic!("unsupported binding {:?}: {other:?}", global.name), + }; + let mut stages = stages; + stages.sort_unstable(); + stages.dedup(); + let stages = if stages.is_empty() { "0".to_owned() } else { stages.join(" | ") }; + let dynamic = global.name.as_deref().is_some_and(|name| DYNAMIC.contains(&name)); + let entry = + format!("Binding {{ slot: {}, kind: {kind}, stages: {stages}, dynamic: {dynamic} }}", binding.binding); + assert!(found.insert(binding.binding, entry).is_none(), "binding {group}.{} twice", binding.binding); + } + found.into_values().collect() +} + +/// Every group 0 and 1 binding a shader declares must match the shared declaration. +fn check_shared(module: &naga::Module, shared: &naga::Module, name: &str) { + for (_, global) in module.global_variables.iter() { + let Some(binding) = &global.binding else { continue }; + if binding.group > 1 { + continue; + } + let same = shared + .global_variables + .iter() + .any(|(_, s)| s.binding.as_ref() == Some(binding) && s.name == global.name && s.space == global.space); + assert!( + same, + "{name}: {:?} at group {} binding {} is not the shared declaration", + global.name, binding.group, binding.binding + ); + } +} diff --git a/packages/gpu/THIRD_PARTY_NOTICES.md b/crates/latkit/colormaps/NOTICES.md similarity index 100% rename from packages/gpu/THIRD_PARTY_NOTICES.md rename to crates/latkit/colormaps/NOTICES.md diff --git a/crates/latkit/colormaps/catalog.txt b/crates/latkit/colormaps/catalog.txt new file mode 100644 index 00000000..08b6e17a --- /dev/null +++ b/crates/latkit/colormaps/catalog.txt @@ -0,0 +1,46 @@ +amber sequential Amber|261400ffc733 +amp sequential Amp|f1edecf1ecebf0ebe9efe9e8efe8e7eee7e5eee6e4ede5e3ede3e1ece2e0ece1deebe0ddebdfdceadddaeadcd9e9dbd7e9dad6e9d9d4e8d8d3e8d6d2e7d5d0e7d4cfe6d3cde6d2cce6d1cae5cfc9e5cec8e4cdc6e4ccc5e4cbc3e3c9c2e3c8c0e2c7bfe2c6bde2c5bce1c4bbe1c3b9e1c1b8e0c0b6e0bfb5dfbeb3dfbdb2dfbcb0debaafdeb9aedeb8acddb7abddb6a9ddb5a8dcb4a6dcb2a5dcb1a3dbb0a2dbafa1dbae9fdaad9edaac9cd9aa9bd9a999d9a898d8a796d8a695d8a594d7a492d7a291d7a18fd6a08ed69f8cd69e8bd59d89d59c88d59a87d49985d49884d49782d39681d3957fd3947ed2927dd2917bd2907ad18f78d18e77d18d76d08c74d08b73d08971cf8870cf876fcf866dce856cce846acd8369cd8168cd8066cc7f65cc7e64cc7d62cb7c61cb7a60cb795eca785dca775bc9765ac97559c97457c87256c87155c87054c76f52c76e51c66d50c66b4ec66a4dc5694cc5684ac56749c46548c46447c36346c36244c36143c25f42c25e41c15d3fc15c3ec05b3dc0593cc0583bbf573abf5639be5438be5336bd5235bd5134bd4f33bc4e32bc4d31bb4c30bb4a30ba492fba482eb9462db9452cb8442bb8422bb7412ab74029b63f29b53d28b53c27b43b27b43926b33826b23726b23525b13425b03325b03125af3024ae2f24ae2d24ad2c24ac2b24ab2a24aa2824aa2724a92624a82524a72424a62225a52125a42025a31f25a21e25a11d25a01c269f1b269e1a269d19269c18279b17279a16279915279815279714289513289413289312289211289111299010298e10298d10298c0f298b0f29890f29880f29870e29850e29840e29830e29810e29800e297f0e297d0e297c0e297b0e29790e29780e28770e28750e28740e28730e27710e27700e276f0e266d0e266c0f266b0f25690f25680f25670f24650f24640e23630e23610e22600e225f0e215d0e215c0e215b0e205a0e1f580e1f570e1e560e1e540d1d530d1d520d1c510d1c4f0d1b4e0d1a4d0c1a4b0c194a0c19490c18480b17460b17450b16440b16430a15410a14400a143f0a133d09123c0912 +batlow sequential Batlow|011959021b59031c5a041e5a051f5a06215b07225b07245b08255b09275c0a285c0a2a5c0b2b5c0b2d5d0c2e5d0c2f5d0d315d0d325e0d335e0e355e0e365e0e375e0f385f0f395f0f3b5f0f3c5f103d5f103e5f103f60104060114160114260114360114460124561124661124761124861134961134a61134b61144c62144d62144e62154f62154f621650621651621752621753621854621855621956621957621a57621b58621b59621c5a621d5b621e5c621e5d621f5d61205e61215f6122606123606024616025626026635f27635f28645f2a655e2b655e2c665d2d675d2f675c30685c31695b33695a346a5a356a59376b58386c583a6c573b6d563c6d563e6e553f6e54416f53426f5244705245705147715048714f4a724e4c724d4d734d4f734c50744b52744a5375495575485776475876465a77455b77455d78445f7843607942627941637a40657a3f677b3e687b3e6a7b3d6c7c3c6d7c3b6f7d3a717d39737e38747e38767f37787f367980357b80347d81347f813381823282823184833186833088842f8a842f8c852e8e852e8f862d91862d93872c95872c97882c99882c9b892b9d892b9f892ba18a2ba38a2ca58b2ca78b2ca98c2cab8c2dad8c2daf8d2eb18d2fb38e2fb58e30b78e31b98f32bb8f33bd8f34be9035c09036c29037c49138c6913ac8913bca923ccb923ecd923fcf9340d19342d29343d49445d69446d89448d9954adb954bdd954dde964fe09651e19752e39754e49756e69858e7985ae9995cea995eeb9a60ed9a62ee9b64ef9b67f09c69f19d6bf29d6df39e70f49f72f59f74f6a077f7a179f8a17bf8a27ef9a380f9a382faa485faa587fba689fba68cfca78efca890fca993fca995fdaa97fdab9afdac9cfdac9efdada0fdaea2fdafa5fdafa7fdb0a9fdb1abfdb2adfdb2affdb3b1fdb4b4fdb4b6fdb5b8fdb6bafdb7bcfdb7befdb8c0fdb9c2fdbac4fdbac7fdbbc9fdbccbfdbccdfcbdcffcbed1fcbfd3fcbfd6fcc0d8fcc1dafcc2dcfcc3dffcc3e1fcc4e3fcc5e5fbc6e8fbc6eafbc7ecfbc8effbc9f1fbcaf3fbcaf6facbf8faccfa +cividis sequential Cividis|00224e00234f00245100255300255400265600275800285900285b00295d002a5f002a61002b62002c64002c66002d68002e6a002e6c002f6d00306f0030700031700031710132710533710833700c34700f357012357014367016377018376f1a386f1c396f1e3a6f203a6f213b6e233c6e243c6e263d6e273e6e293f6e2a3f6d2b406d2d416d2e416d2f426d31436d32436d33446d34456c35456c36466c38476c39486c3a486c3b496c3c4a6c3d4a6c3e4b6c3f4c6c404c6c414d6c424e6c434e6c444f6c45506c46516c47516c48526c49536c4a536c4b546c4c556c4d556c4e566c4f576c50576c51586d52596d535a6d545a6d555b6d555c6d565c6d575d6d585e6d595e6e5a5f6e5b606e5c616e5d616e5e626e5e636f5f636f60646f61656f62656f636670646770656870656870666970676a71686a71696b716a6c716b6d726c6d726c6e726d6f726e6f736f70737071737172747272747273747374757474757575757676767777767777777878777979777a7a787b7a787c7b787d7c787e7c787e7d787f7e78807f78817f788280798381798482798582798683798784788885788985788a86788b87788c88788d88788e89788f8a78908b78918b78928c78928d78938e78948e77958f779690779791779892779992779a93769b94769c95769d95769e96769f9775a09875a19975a29975a39a74a49b74a59c74a69c74a79d73a89e73a99f73aaa073aba072aca172ada272aea371afa471b0a571b1a570b3a670b4a76fb5a86fb6a96fb7a96eb8aa6eb9ab6dbaac6dbbad6dbcae6cbdae6cbeaf6bbfb06bc0b16ac1b26ac2b369c3b369c4b468c5b568c6b667c7b767c8b866c9b965cbb965ccba64cdbb63cebc63cfbd62d0be62d1bf61d2c060d3c05fd4c15fd5c25ed6c35dd7c45cd9c55cdac65bdbc75adcc859ddc858dec958dfca57e0cb56e1cc55e2cd54e4ce53e5cf52e6d051e7d150e8d24fe9d34eead34cebd44bedd54aeed649efd748f0d846f1d945f2da44f3db42f5dc41f6dd3ff7de3ef8df3cf9e03afbe138fce236fde334fee434fee535fee636fee838 +crest sequential Crest|a5cd90a4cc90a3cc91a2cb91a0cb919fca919eca919dc9919cc8919bc8919ac79199c79198c69196c69195c59194c59193c49192c49191c39190c3918fc2918ec2918dc1918bc1918ac09189bf9188bf9187be9186be9185bd9184bd9182bc9181bc9180bb917fbb917eba917dba917cb9917bb99179b89178b89177b79176b79175b69074b69073b59072b49071b49070b3906fb3906eb2906db2906cb1906bb1906ab09069b09068af9067ae9066ae9065ad9064ad9063ac9062ac9062ab9061aa9060aa905fa9905ea9905da8905ca8905ba7905ba6905aa69059a59058a59057a49057a49056a39055a29054a29053a19053a19052a090519f90509f90509e904f9e904e9d904e9d904d9c904c9b904b9b904b9a8f4a9a8f49998f49988f48988f47978f47978f46968f45958f45958f44948f43948f43938f42928f41928f41918f40918f40908e3f8f8e3e8f8e3e8e8e3d8e8e3c8d8e3c8c8e3b8c8e3a8b8e3a8b8e398a8e388a8e38898e37888e37888d36878d35878d35868d34858d33858d33848d32848d31838d31828d30828d2f818d2f818d2e808d2d808c2d7f8c2c7e8c2c7e8c2b7d8c2a7d8c2a7c8c297b8c287b8c287a8c277a8c27798c26788c25788c25778c24778b24768b23758b23758b22748b22748b21738b21728b20728b20718b20718b1f708b1f6f8a1e6f8a1e6e8a1e6d8a1e6d8a1d6c8a1d6c8a1d6b8a1d6a8a1d6a8a1c69891c68891c68891c67891c66891c66891c65891c64881c64881c63881d63881d62881d61881d61871d60871d5f871d5f871e5e871e5d861e5d861e5c861e5b861f5b861f5a851f59851f5985205885205784205784205684215584215583215483225383225283225282225182235082235081234f81244e81244e80244d80254c80254c7f254b7f254a7f26497e26497e26487e27477d27477d27467c27457c28457c28447b28437b28427a29427a29417a2940792940792a3f782a3e782a3d782a3d772a3c772a3b762b3b762b3a762b39752b38752b38752b37742b36742c35742c35732c34732c33732c32722c31722c3172 +deep sequential Deep|fdfeccfbfdcbf9fccaf7fbc8f5fac7f3fac6f1f9c5eff8c4edf7c3ebf7c1e9f6c0e7f5bfe5f4bee3f4bde1f3bcdff2bbddf2badbf1b9d9f0b8d7efb7d4efb6d2eeb5d0edb4ceecb3ccecb3caebb2c8eab1c6eab0c4e9afc1e8afbfe7aebde7adbbe6acb9e5acb7e5abb5e4aab2e3aab0e2a9aee2a9ace1a8aae0a8a7e0a7a5dfa7a3dea6a1dda69fdda59cdca59adba598daa496daa494d9a492d8a490d7a48dd7a38bd6a389d5a387d4a385d3a383d3a381d2a37fd1a37dd0a37ccfa37acea378cea376cda375cca373cba371caa370c9a36ec8a36dc7a36bc6a36ac5a469c4a467c3a466c2a465c2a464c1a463c0a462bfa461bea460bda45fbca45ebba45dbaa45cb9a45bb8a45ab7a45ab6a459b4a458b3a458b2a457b1a456b0a456afa455aea355ada354aca353aba353aaa352a9a352a8a351a7a351a6a251a5a250a4a250a3a24fa2a24fa1a24fa0a24e9fa14e9ea14d9da14d9ca14d9ba14c9aa04c99a04b98a04b97a04b96a04a959f4a949f4a939f49929f49919e49909e488f9e488e9e488d9d478c9d478b9d478a9d46899d46889c46879c45869c45859c45849b44839b44829b44819b44809b437f9a437e9a437d9a427c9a427b99427a994279994178994177994176984075984074984073984072984071973f70973f6f973f6e973f6d973f6c963e6b963e6a963e69963e68963e67953e66953e65953e64953e63943e62943e61943e60943e5f933e5e933e5c933e5b933e5a923e59923e58923e57913e56913f55903f54903f538f3f528f3f508e404f8d404e8d404d8c404c8b414b8a414a8941498841488741478541468441458341448142438041427e41417d41407b41407a413f78413e76413d75403c73403c71403b70403a6e3f396c3f386b3f38693e37673e36663d35643d35623d34613c335f3c325d3b325c3b315a3a30583a3057392f55392e54382d52382d51372c4f362b4d362a4c352a4a35294934284734284633274432264332254131254030243e30233d2f223b2f223a2e21392d20372d1f362c1f342b1e332b1d322a1c30291c2f281b2d281a2c +devon sequential Devon|2c1a4c2c1b4d2c1c4e2b1c4f2b1d502b1e512b1f522b20532b21542b22552b23562b24572b25582b26582b27592a285a2a295b2a295c2a2a5d2a2b5e2a2c5f2a2d602a2e612a2f6229306329316429326529336629346729356829366929376a29386a28396b28396c283a6d283b6e283c6f283d70283e71283f7228407327417427427527437627447827457927467a27477b27487c27497d274a7e274c7f274d81274e82274f8327508427518627528727538828548a28558b28568c28578e29588f295990295a922a5b932a5c952b5d962b5d982c5e992c5f9a2d609c2e619d2e629f2f62a03063a23064a33165a43265a63266a73367a93468aa3568ab3669ad376aae386ab0396bb13a6cb23b6db43c6db53d6eb73e6fb83f70b94171bb4272bc4472bd4573bf4774c04875c14a76c34c77c44d78c54f79c6517ac8537bc9557cca577ccb597dcc5b7ecd5d7fce5f80cf6181d06382d16583d26784d36985d46b86d56d87d66f88d77188d87389d8758ad9778bda798cdb7b8ddc7d8edc7e8fdd808fde8290df8491df8692e08893e18a94e18c95e28d95e38f96e39197e49398e59599e5969ae6989be79a9be79b9ce89d9de89e9ee9a09fe9a2a0eaa3a1eaa4a2eba6a3eba7a4eca8a5ecaaa5edaba6edaca7edada8eeaea9eeafaaeeb0abeeb1acefb2adefb3adefb4aeefb5aff0b6b0f0b7b1f0b8b2f0b9b3f0bab3f1bab4f1bbb5f1bcb6f1bdb7f1beb8f2beb9f2bfb9f2c0baf2c1bbf2c2bcf2c2bdf3c3bef3c4bff3c5c0f3c6c0f3c6c1f3c7c2f4c8c3f4c9c4f4cac5f4cac6f4cbc6f4ccc7f4cdc8f5cec9f5cecaf5cfcbf5d0ccf5d1cdf5d2cdf6d2cef6d3cff6d4d0f6d5d1f6d6d2f6d6d3f7d7d4f7d8d4f7d9d5f7dad6f7dad7f7dbd8f8dcd9f8dddaf8dedbf8dedcf8dfdcf8e0ddf9e1def9e2dff9e3e0f9e3e1f9e4e2fae5e3fae6e4fae7e4fae8e5fae8e6fae9e7fbeae8fbebe9fbeceafbedebfbedecfbeeedfcefeefcf0eefcf1effcf2f0fcf2f1fcf3f2fdf4f3fdf5f4fdf6f5fdf7f6fdf7f7fdf8f8fef9f9fefaf9fefbfafefcfbfefcfcfefdfdfffefeffffffff +flare sequential Flare|edb081edaf80edae7fedad7fedac7eedab7eecaa7deca97ceca87ceca77beca67beca57aeca479eca379eca278eca178eca077ec9f76eb9e76eb9d75eb9c75eb9b74eb9a73eb9973eb9972eb9872eb9771ea9671ea9570ea946fea936fea926eea916eea906dea8f6cea8e6ce98d6be98c6be98b6ae98a6ae98969e98868e98768e98667e88567e88466e88366e88265e88165e88064e87f64e77e63e77d63e77c63e77b62e77a62e67961e67861e67760e67660e67560e5745fe5735fe5725fe5715ee5705ee46f5ee46e5ee46d5de46c5de36b5de36a5de3695de3685ce2675ce2665ce2655ce1645ce1635ce1625ce0615ce0605ce05f5cdf5f5cdf5e5cde5d5cde5c5cde5b5cdd5a5cdd595cdc585cdc575cdb565ddb565dda555dda545dd9535dd9525ed8525ed7515ed7505ed64f5fd64f5fd54e5fd44d60d44c60d34c60d24b60d24a61d14a61d04962d04962cf4862ce4763cd4763cc4663cc4664cb4564ca4564c94465c84465c84365c74366c64366c54266c44267c34167c24167c14168c14068c04068bf4069be3f69bd3f69bc3f69bb3f6aba3e6ab93e6ab83e6bb73d6bb63d6bb53d6bb43d6bb33c6cb23c6cb13c6cb13c6cb03b6daf3b6dae3b6dad3b6dac3a6dab3a6daa3a6ea93a6ea8396ea7396ea6396ea5396ea4386fa3386fa2386fa1386fa1376fa0376f9f376f9e37709d36709c36709b36709a36709935709835709735709635709534709434709434719334719233719133719033718f33718e32718d32718c32718b32718a3171893171883171873171873171863071853071843071833070822f70812f70802f707f2f707e2f707d2e707c2e707b2e707a2e70792e6f782e6f772d6f762d6f752d6f752d6f742d6e732c6e722c6e712c6e702c6e6f2c6d6e2c6d6d2b6d6c2b6d6b2b6c6a2b6c692b6c682a6c672a6b662a6b652a6b642a6a642a6a63296a62296a6129696029695f29695e28685d28685c28685b28675a27675927675827665827665727665626665526655426655326655225645125645025644f24634f24634e24634d24634c23624b2362 +grays sequential Grays|000000ffffff +haline sequential Haline|2a186c2a196e2a19712b19732b19752c1a782c1a7a2d1a7d2d1a7f2d1b822e1b842e1b872e1c892e1c8c2e1c8e2e1d912e1d932e1e952e1e982e1f9a2d209c2d219d2c229f2b24a02a25a12927a22829a3262ba3252da3242ea32230a32132a22034a21e35a11d37a11c39a01b3aa0193c9f183d9e173f9e16409d15419c14439c13449b12459b11479a1048990f49990f4a980e4c970d4d970d4e960d4f960c50950c51950c52940c53940c54930d55930d56920d57920e58910e59910f5a910f5b90105c90115d8f115e8f125f8f13608e14618e14628e15638e16638d17648d18658d18668c19678c1a688c1b698c1c6a8c1d6b8b1d6b8b1e6c8b1f6d8b206e8b216f8b22708a22718a23718a24728a25738a26748a26758a27768a2876892977892978892a79892b7a892b7b892c7c892d7c892d7d892e7e892f7f892f8089308189318289318288328388338488338588348688348788358888358988368988378a88378b88388c88388d88398e88398f883a90873a90873b91873b92873c93873c94873d95873d96873e97873e98863f99863f9986409a86419b86419c85429d85429e85439f8543a08444a18444a28445a38446a48346a48347a58348a68248a78249a8824aa9814aaa814bab814cac804cad804dae7f4eae7f4faf7e50b07e51b17d51b27d52b37c53b47c54b57b55b67b56b77a57b87958b8795ab9785bba775cbb775dbc765ebd755fbe7561bf7462bf7363c07265c17266c27168c37069c46f6bc46e6cc56e6ec66d70c76c71c86b73c86a75c96977ca6878cb687acb677ccc667ecd6580ce6482ce6384cf6286d06289d0618bd1608dd25f8fd25f92d35e94d35d97d45d99d45d9bd55c9ed65ca0d65ca3d75ca5d75ca8d85caad85cadd85cafd95db1d95db4da5eb6da5fb8db60bbdb61bddc62bfdc63c1dd64c4dd65c6de66c8de67cadf69ccdf6acee06cd0e06dd2e16fd4e170d6e272d8e273dae375dce377dee479e0e57ae1e57ce3e67ee5e680e7e781e9e783ebe885ece987eee989f0ea8af2ea8cf3eb8ef5ec90f7ec92f8ed94faee96fcee98fdef9a +inferno sequential Inferno|00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4 +lajolla sequential Lajolla|1919001a1a011b1a011c1a011d1b021e1b021e1b031f1c03201c04211c04221c05231d05241d06241d07251e07261e08271e08281f09291f092a1f0a2b200a2c200b2d200c2e210c2f210d30210d31220e32220f33220f3423103523103624113724113924123a25133b25133c26143d26143f2615402716412716432817442817452918472919482a1a4a2a1a4b2b1b4d2b1c4e2c1d502c1d512d1e532d1f542e20562e21572f21592f225b30235c30245e312560322661322763332865332967342a69352b6a352c6c362c6e362d70372e72382f743830763931783932793a337b3b347d3b357f3c36813c37833d38853e39873e3a893f3a8b3f3b8d403c8f403d92413e94413e96423f9842409a43409c43419e4442a04442a24543a44544a64644a84645ab4745ad4746af4846b14847b34947b54947b74a48b94a48bb4b48bc4c49be4c49c04d49c24d4ac44e4ac54f4ac7504bc9514bca514bcc524bcd534ccf544cd0554cd1564cd2584cd4594dd55a4dd65b4dd75c4dd75e4dd85f4dd9604eda614edb634edb644edc654edc674edd684edd694fde6b4fde6c4fdf6d4fdf6e4fe0704fe0714fe0724fe1744fe17550e17650e17750e27950e27a50e27b50e37c50e37d50e37f50e38050e48150e48251e48351e48551e58651e58751e58851e58951e68b51e68c51e68d51e68e51e68f52e79052e79252e79352e79452e89552e89652e89752e89852e99a52e99b52e99c52e99d53ea9e53ea9f53eaa153eaa253eba353eba453eba553eba653eba853eca953ecaa54ecab54ecac54edae54edaf54edb054edb154eeb355eeb455eeb555efb655efb856efb956efba56f0bc57f0bd57f0be58f1c058f1c159f1c25af1c45af2c55bf2c75cf2c85df3ca5ff3cb60f4cd61f4ce63f4d065f5d167f5d369f5d46bf6d66df6d76ff7d971f7da74f7dc77f8dd79f8df7cf8e07ff9e282f9e384fae587fae68afae78dfbe890fbea93fbeb96fbec99fced9cfcef9ffcf0a2fcf1a5fdf2a8fdf3abfdf4aefdf5b0fef6b3fef7b6fef8b8fef9bbfefabefefbc0fffcc3fffdc6fffec8fffecb +magma sequential Magma|00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf +mako sequential Mako|0b04050d04060e05080f060910060a11070c12080d13090f140910150a12160b13170c15180d16190e181a0e191b0f1a1c101c1d111d1e111f1f122020132221142322142523152624162825172926172b27182d28192e291930291a312a1b332b1c352c1c362d1d382e1e392e1e3b2f1f3d30203e31214031214232224333234534244734254835254a35264c36274d37284f372851382953382a54392b563a2c583a2c593b2d5b3b2e5d3b2f5f3c30603c31623d31643d32663e33673e34693e356b3f366d3f366f3f3770403872403974403a76403b78403c79413d7b413e7d413e7f413f8041408241418441428541438741448840468a40478b40488d40498e3f4a8f3f4b903f4c923e4d933e4f943e50953d51953d52963c53973c55983b56983b57993b589a3a599a3a5b9b3a5c9b395d9c395e9c385f9c38619d38629d38639d37649e37659e37669e37689f36699f366a9f366b9f366ca0366da0366fa03670a03671a03572a13573a13574a13575a13576a23578a23579a2357aa2357ba3357ca3357da3357ea4347fa43480a43482a43483a53484a53485a53486a53487a63488a63489a6348ba6348ca7348da7348ea7348fa73490a83491a83492a83493a83495a93496a93497a93498a93499aa349aaa359baa359caa359eaa359fab35a0ab35a1ab36a2ab36a3ab36a4ab37a5ac37a6ac37a8ac38a9ac38aaac39abac39acac3aadac3aaead3bafad3cb1ad3cb2ad3db3ad3eb4ad3fb5ad3fb6ad40b7ad41b8ad42b9ad43baad44bcad45bdad46bead47bfad48c0ad49c1ad4bc2ad4cc3ad4dc4ad4fc5ad50c6ad52c7ad53c9ad55caad57cbad59ccad5bcdad5ecdad60ceac62cfac65d0ad68d1ad6ad2ad6dd3ad70d4ad73d4ad76d5ae79d6ae7cd6af7fd7af82d8b085d9b188d9b18bdab28edbb391dbb494dcb596ddb599ddb69cdeb79edfb8a1dfb9a4e0bba6e1bca9e1bdabe2beaee3c0b0e4c1b2e4c2b5e5c4b7e6c5b9e6c7bbe7c8bee8cac0e9ccc2e9cdc4eacfc6ebd1c8ecd2caedd4ccedd6ceeed7d0efd9d2f0dbd4f1dcd6f1ded8f2e0daf3e1dcf4e3def5e5 +oslo sequential Oslo|01010101020302040502050703060904070b04080d05090f050a10060b12060c13070d15080e16080f170910180911190a121b0b131c0b131d0b141e0c151f0c16200d16220d17230d18240d19250d19270d1a280d1b290e1b2a0e1c2c0e1d2d0e1e2e0e1e2f0e1f310e20320f21330f21350f22360f23370f24390f253a10263c10263d10273e102840102941112a43112b44112b45112c47122d48122e4a122f4b12304c13314e13324f13325114335214345414355514365715375815385a15395b163a5d163b5e173b60173c61173d63183e64183f6619406719416919426a1a436c1a446d1b456f1b46701c47721c48731d48751d49761e4a781e4b7a1f4c7b204d7d204e7e214f8021508122518323528523538624548825558926568b26578c27588e285990295a912a5b932b5c942c5d962d5e982e5f992f609b30619c31629e3263a03364a13465a33666a43767a63869a83a6aa93b6bab3d6cac3e6dae406eaf4170b14371b24472b34673b54775b64976b84b77b94c78ba4e7abb507bbc517cbd537dbe547ebf567fc05881c15982c25b83c35c84c35e85c46086c56187c56388c66489c6658ac7678bc7688cc76a8dc86b8ec86c8fc86e90c86f90c97091c97292c97393c97494c97594c97795c97896c97997ca7a98ca7b98ca7d99ca7e9aca7f9bca809bca819cca839dca849eca859eca869fca87a0ca89a0ca8aa1ca8ba2c98ca3c98da3c98ea4c990a5c991a6c992a6c993a7c994a8c996a9c997a9c998aac999abc99aacc99cacc99dadc99eaec99fafc9a0afc9a2b0caa3b1caa4b2caa5b3caa7b4caa8b4caa9b5caaab6caacb7caadb8cbaeb9cbb0bacbb1bbcbb2bcccb4bdccb5bdccb6becdb8bfcdb9c1cdbac2cebcc3cebdc4cfbfc5cfc0c6d0c2c7d1c3c8d1c5c9d2c6cbd3c7ccd3c9cdd4caced5ccd0d6ced1d7cfd2d8d1d3d9d2d5dad4d6dbd5d8dcd7d9ddd8dadedadcdfdbdde0dddee1dee0e2e0e1e4e2e3e5e3e4e6e5e6e7e6e7e9e8e9eae9eaebebecedecedeeeeeeefeff0f1f1f1f2f3f3f4f4f4f5f6f6f6f7f7f8f9f9f9fafafbfcfcfcfdfdfeffffff +plasma sequential Plasma|0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921 +rocket sequential Rocket|03051a04051a05061b06071c07071d08081e0a091f0b09200d0a210e0b22100b23110c24130d25140e26160e27170f28180f291a102a1b112b1d112c1e122d20122e2113302213312414322514332715342815352a16362b16372d17382e173930173a31183b33183c34193d35193e37193f381a403a1a413c1a423d1a423f1b43401b44421b45431c46451c47461c48481c48491d494b1d4a4c1d4b4e1d4b501d4c511e4d531e4d541e4e561e4f581e4f591e505b1e515c1e515e1f52601f52611f53631f53641f54661f54681f55691f556b1f566d1f566e1f57701f57711f57731f58751f58761f58781f597a1f597b1f597d1f5a7f1e5a811e5a821e5a841e5a861e5b871e5b891e5b8b1d5b8c1d5b8e1d5b901d5b921c5b931c5b951c5b971c5b981b5b9a1b5b9c1b5b9e1a5b9f1a5ba11a5ba3195ba4195ba6195aa8185aaa185aab185aad1759af1759b01759b21758b41658b51657b71657b91657ba1656bc1656bd1655bf1654c11754c21753c41753c51852c71951c81951ca1a50cb1b4fcd1c4ece1d4ecf1e4dd11f4cd2204cd3214bd5224ad62449d72549d82748d92847db2946dc2b46dd2c45de2e44df2f44e03143e13342e23442e33641e43841e53940e63b40e73d3fe83f3fe8403ee9423eea443eeb463eeb483eec4a3eec4c3eed4e3eed503eee523fee543fef5640ef5840ef5a41f05c42f05e42f06043f16244f16445f16646f26747f26948f26b49f26d4bf26f4cf3714df3734ef37450f37651f37852f47a54f47c55f47d57f47f58f4815af4835bf4845df4865ef58860f58a61f58b63f58d64f58f66f59067f59269f5946bf5966cf5976ef59970f69b71f69c73f69e75f6a077f6a178f6a37af6a47cf6a67ef6a880f6a981f6ab83f6ad85f6ae87f6b089f6b18bf6b38df6b48ff6b691f6b893f6b995f6bb97f6bc99f6be9bf6bf9df6c19ff7c2a2f7c4a4f7c6a6f7c7a8f7c9aaf7caacf7ccaff7cdb1f7cfb3f7d0b5f8d1b8f8d3baf8d4bcf8d6bef8d7c0f8d9c3f8dac5f8dcc7f9ddc9f9dfcbf9e0cdf9e2d0f9e3d2f9e5d4fae6d6fae8d8fae9dafaebdd +thermal sequential Thermal|04233304243504253704253905263b05273d05273f052841052943062945062a47062b49072b4b072c4d072c50082d52082e54092e56092f590a2f5b0b305d0c30600c30620d31650e31670f326a10326c12326f13337214337416337717337a19337c1a347f1c34821e34841f348721348a23348c25348f2734912a33932c33952e339730339933339b35339c37339d39339e3c339f3e349f40349f4234a04435a04635a04736a049369f4b379f4d379f4e389e50399e52399d533a9d553b9d563b9c583c9c593d9b5b3d9b5c3e9a5e3f9a5f3f996040996241986341986542976643976743966944966a45956c45956d46946e4794704794714893724893744992754a92764a92784b91794b917a4c917c4d907d4d907e4e90804e8f814f8f83508f84508e85518e87518e88528d89528d8b538d8c538c8e548c8f548c90558b92558b93568b95568a96578a97578a9958899a58899c59899d59889f5a88a05a87a25b87a35b86a55c86a65c86a85d85a95d84ab5d84ac5e83ae5e83af5f82b15f82b26081b46080b56180b7617fb8627eba627ebb627dbd637cbe637bc0647bc1647ac36579c46578c66677c76676c96775ca6774cc6873cd6872ce6971d06970d16a6fd36a6ed46b6dd66c6cd76c6bd86d6ada6e69db6e68dc6f66de7065df7064e07163e17262e37260e4735fe5745ee6755de7765be8775aea7859eb7958ec7956ed7a55ee7b54ee7d53ef7e52f07f50f1804ff2814ef3824df3834cf4854bf5864af58749f68848f68a47f78b46f78c45f88e44f88f43f99143f99242f99341fa9541fa9640fa983ffb993ffb9b3efb9c3efb9e3efb9f3dfba13dfca33dfca43dfca63cfca73cfca93cfcaa3cfcac3cfcae3cfcaf3cfcb13cfbb23dfbb43dfbb63dfbb73dfbb93efbbb3efbbc3efabe3ffabf3ffac140fac340f9c441f9c641f9c842f8c943f8cb43f8cd44f7ce45f7d045f7d246f6d347f6d547f5d748f5d849f4da4af4dc4bf3dd4bf3df4cf2e14df2e24ef1e44ff1e650f0e851efe951efeb52eeed53edee54edf055ecf256ebf457eaf558eaf759e9f95ae8fa5b +turku sequential Turku|0000000202020404030606050707070909080b0b0a0d0d0c0e0e0d10100e1111101212111413121515131616141717151818161919171a1a181b1b191c1c191d1d1a1e1e1b1f1f1c20201d21211e22221f23231f2424202525212626222727232828232929242a2a252b2b262c2c272d2d272e2e282f2f2930302a32312a33322b34332c35342d36362d37372e38382f3939303a3a303b3b313c3c323d3d323e3e333f3f3440403441413542423543433644443745453746463847473848483949493a4b4a3a4c4b3b4d4c3b4e4d3c4f4e3c504f3d51503d52513e53523e54533f55543f5656405757405858415959415a5a425b5b425c5c435d5d435e5e445f5f446060456161456262466363466464476565476666476767486868486a69496b6a496c6b4a6d6c4a6e6d4b6f6e4b706f4c71704c72714d73724d75734e76744e77754f78764f7977507b79507c7a517d7b517e7c527f7d52817e53827f538380548581548682558783568984568a85578b86588d87588e8859908a59918b5a938c5b948d5b968e5c978f5d99905e9a915e9c925f9d93609f9461a19461a29562a49663a59764a79864a99965aa9a66ac9a67ad9b68af9c68b09d69b29d6ab39e6bb59f6cb69f6cb8a06db9a06ebba16fbca170bea270bfa271c0a272c2a373c3a374c4a474c6a475c7a476c8a477c9a578cba578cca579cda57acea67bcfa67cd0a67cd1a67dd2a67ed3a67fd4a780d6a780d7a781d8a782d9a783daa784dba885dba886dca887dda888dea889dfa98ae0a98be1a98ce2a98de3aa8ee4aa8fe5aa90e6ab92e7ab93e8ac94e9ac95e9ad97eaad98ebae99ecae9bedaf9ceeb09eefb09fefb1a1f0b2a2f1b3a3f2b3a5f2b4a7f3b5a8f4b6aaf4b7abf5b8adf6b9aef6bab0f7bbb1f7bcb3f8bdb4f8beb6f9bfb7f9c0b9fac1bafac2bcfbc3bdfbc4bffbc5c0fcc6c1fcc7c3fcc8c4fdc9c6fdcbc7fdccc8fdcdcafdcecbfecfccfed0cefed1cffed2d0fed3d1fed4d3fed6d4fed7d5ffd8d6ffd9d7ffdad9ffdbdaffdcdbffdddcffdeddffdfdfffe0e0ffe2e1ffe3e2ffe4e3ffe5e5ffe6e6 +viridis sequential Viridis|44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725 +balance diverging Balance|181c43191e461a1f491b214c1c224f1d23521e25551f265820275b21295f212a62222b65232d69242e6c252f6f25307326327627337a27347d283681283784293888293a8c293b8f293c93293e97293f9a29409e2942a22843a52745a92647ac2548b0234ab3214cb61f4eb81c50ba1952bc1655bd1357be1059be0d5bbe0c5ebe0a60be0a62be0a64be0b66bd0d68bd0f6abd116cbc136ebc1670bc1972bb1b74bb1e76bb2178bb237aba267bba297dba2b7fba2e81ba3083ba3384ba3686ba3888ba3b89ba3e8bba408dba438fba4690ba4892ba4b94ba4e95ba5197ba5399ba569abb599cbb5c9dbb5f9fbb62a0bb65a2bc68a4bc6ba5bc6ea7bd71a8bd75aabe78abbe7bacbf7eaebf81afc085b1c088b2c18bb4c28eb5c391b7c394b8c498bac59bbbc69ebcc7a1bec8a4bfc9a7c1caaac2cbadc4ccb0c5cdb3c7ceb6c9cfb9cad0bcccd2bfcdd3c1cfd4c4d0d5c7d2d7cad4d8cdd5d9d0d7dad3d9dcd5daddd8dcdedbdee0dee0e1e1e1e3e3e3e4e6e5e6e9e7e7ebe9e9eeeaeaf1ececf1ecebf0eae9efe8e6eee5e3ede3e0ece0deebdedbeadcd8e9d9d5e8d7d2e7d5cfe6d2cde5d0cae5cec7e4cbc4e3c9c1e2c7bee1c4bbe1c2b8e0c0b5dfbdb2dfbbb0deb9adddb6aadcb4a7dcb2a4dbafa1daad9edaab9bd9a998d8a696d8a493d7a290d69f8dd69d8ad59b87d49984d39681d3947fd2927cd18f79d18d76d08b73cf8970cf866ece846bcd8268cd7f65cc7d63cb7b60ca795dca765bc97458c87255c76f53c76d50c66b4dc5684bc46648c36346c36143c25f41c15c3fc05a3cbf573abe5538be5236bd5034bc4d32bb4b30ba482eb9452cb8432bb74029b63d28b43b27b33826b23525b13325af3024ae2e24ac2b24ab2924a92624a72424a52125a31f25a11d259f1b269d19269b17279916279714289413289212289010298d10298b0f29880f29860e29830e29800e297e0e297b0e29780e28760e28730e27700e276d0e266b0f25680f25650f24630e23600e225e0e215b0e20580e1f560e1e530d1d510d1c4e0d1b4b0c19490c18460b17440b16410a143f0a133c0912 +berlin diverging Berlin|9eb0ff9cb0fe9ab0fd98affc95affb93affa91aef98eaef78caef68aaef587adf485adf382adf280acf17eacf07bacee79abed76abec74aaeb71aae96fa9e86ca9e66aa8e567a8e365a7e262a6e060a5df5da5dd5ba4db58a3d956a2d754a0d5519fd34f9ed14d9dcf4b9bcd489aca4698c84497c64395c34194c13f92be3e90bc3c8eb93b8db7398bb43889b23787af3685ad3584aa3382a83280a6327ea3317ca1307a9e2f789c2e76992d75972c73942c71922b6f8f2a6d8d296b8b29698828688627668327648126627f25607c245e7a245d78235b7522597322577121556e20546c20526a1f50681e4e651e4d631d4b611c495f1c475c1b465a1a44581a4256194153193f51183d4f173c4d173a4b16384916374715354415334214324014303e132f3c132d3a122c38122a3612293411273211263011242e11232c11212a112028101f26101d25101c23111b21111a2011191e11181c11161b111519111418111317121215121214131112141011140f10150e0e160e0d170d0b180c0a190c091a0c081b0b071c0b061d0b051e0b04200b04210b03220c02230c02240c02250c01260d01270d01280d012a0e012b0e012c0e002d0e002f0e00300f00310f00330f00340f003510003710003810003911003b11003c11013e12013f12014112014213014413014514014714014815024a15024b16024d16024f1703501803521804541905561a05571b06591c075b1d085d1e095f1f0a61200b63210c65230e68240f6a25106c27116e2813702a14732b16752d17772f1979301b7b321c7d341e803620823722843924863b26883d288a3f2a8c402c8e422e904430924632944834964a36984c399a4d3b9c4f3d9e513fa05341a25544a45746a65948a85a4aaa5c4cac5e4fae6051b06253b26455b46658b6685ab86a5cba6b5fbc6d61be6f63c07165c27368c4756ac6776cc8796fca7b71cc7d73ce7f76d08178d2837ad5857dd7877fd98982db8b84dd8d86df8f89e1918be3938ee59590e79792ea9995ec9b97ee9d9af09f9cf2a19ff4a3a1f6a5a3f9a7a6fba9a8fdababffadad +brbg diverging Brown / Green|5430055631055833055b34065d35065f3606613806633906663a07683c076a3d076c3e076e40077141087342087543087745087946087c47097e4909804a09824b09844c09874e0a894f0a8b500a8d520b8f540c91560d93580f955910975b12995d139b5f149d61169f6317a16518a3671aa5691ba76a1da96c1eab6e1fad7021af7222b17423b37625b57826b77928b97b29bb7d2abd7f2cbf812dc08430c28633c38936c48b3ac58e3dc79040c89343c99546ca9849cc9a4ccd9d50cea053cfa256d1a559d2a75cd3aa5fd4ac62d6af65d7b169d8b46cd9b76fdbb972dcbc75ddbe78dec17bdfc37ee0c481e1c684e2c787e3c989e4ca8ce5cc8fe6cd92e7cf94e8d097e8d29ae9d39dead59febd6a2ecd8a5edd9a8eedbaaefdcadf0deb0f1dfb3f1e1b5f2e2b8f3e4bbf4e5bef5e7c0f6e8c3f6e9c5f6e9c7f6eac9f6eacbf6ebcdf6ebcff6ecd1f6ecd3f6edd5f6edd7f6eed9f6eedbf5efdcf5efdef5f0e0f5f0e2f5f1e4f5f1e6f5f2e8f5f2eaf5f3ecf5f3eef5f4f0f5f4f2f5f5f4f4f5f5f2f4f4f0f4f3eff3f3edf3f2ebf3f2e9f2f1e7f2f0e6f1f0e4f1efe2f0eee0f0eedef0edddefeddbefecd9eeebd7eeebd5edead4ede9d2ede9d0ece8ceece8ccebe7cbebe6c9eae6c7eae5c4e9e4c1e8e2bfe7e1bce5dfb9e4deb6e3ddb4e2dbb1e1daaee0d8abdfd7a8ddd5a6dcd4a3dbd3a0dad19dd9d09ad8ce98d7cd95d6cc92d4ca8fd3c98dd2c78ad1c687d0c584cfc381cec27fccc07ccabe79c8bc76c6ba73c3b870c1b66dbfb46abdb267bbb064b9ae61b7ac5eb5aa5bb3a858b0a755aea552aca34faaa14da89f4aa69d47a49b44a299419f973e9d953b9b9338999135978f33958d31938b2f91892d8f872b8d85298b83278a8225888023867e21847c1f827a1d80781a7e76187c74167a7214787012766e10746c0e726a0c71690a6f67086d65066b6304696102675f01655d01645b016259016058015f56015d54015b52015a5001584f01564d01554b015349015147005046004e44004c42004b4000493e00483d00463b004439004337004135003f34003e32003c30 +broc diverging Broc|2c1a4c2c1b4e2c1d4f2b1e512b20522b21542b23552b24572b26582b275a2b295b2b2a5d2a2c5e2a2d602a2e612a30632a31642a336629356729366929386a29396c293b6d293c6f293e71283f7228417428437528447728467828477a29497c294b7d294c7f294e802a50822a51832b53852c55862d57882e58892f5a8b305c8c315e8e335f8f3461913663923765933966953b68963d6a973f6b99416d9a436f9b45719c47729e49749f4b76a04d78a15079a3527ba4547da5567fa65880a75b82a95d84aa5f85ab6187ac6489ad668baf688cb06b8eb16d90b26f92b37193b57495b67697b77899b87b9bba7d9cbb7f9ebc82a0bd84a2be86a3c089a5c18ba7c28da9c390aac592acc694aec797b0c899b2ca9bb3cb9eb5cca0b7cda2b9cea5bbd0a7bcd1aabed2acc0d3aec2d5b1c4d6b3c5d7b5c7d8b8c9dabacbdbbdcddcbfcfddc2d0dfc4d2e0c6d4e1c9d6e2cbd8e4ced9e5d0dbe6d2dde7d5dfe8d7e0e9d9e2eadce4ebdee5ece0e7ece2e8ede4eaede6ebede7ecede9ededeaeeecebeeececefebedefe9edefe8eeefe7eeefe5eeefe3edeee1edeedfecedddececdbebebd9eaead6e9e9d4e8e8d2e7e7cfe6e6cde5e5cbe4e4c8e3e2c6e1e1c4e0e0c1dfdfbfdedebdddddbadcdbb8dadab5d9d9b3d8d8b1d7d7aed5d5acd4d4aad3d3a7d2d2a5d0d0a2cfcfa0cece9ecccc9bcbcb99c9c996c8c894c6c691c5c58fc3c38cc1c18ac0bf87bebe85bcbc83baba80b8b87eb6b67cb4b479b2b277b0b075aeae73acac71aaaa6fa8a86da6a66ba3a369a1a1679f9f659d9d639b9b6299996097975e95955c93935b9191598f8f578d8d568b8b5489895287875185854f83834d81814c7f7f4a7d7d487b7b4779794577774475754274744072723f70703d6e6e3c6c6c3a6a6a386868376666356464346262326160315f5f2f5d5d2d5b5b2c59592a5757295555275454265252245050234e4e214c4c204b4b1f49491d47471c45451a4343194242184040163e3e153c3d143b3b1239391137381036360f34340e32330c31310b2f300a2e2e082c2c072b2b05292904282802262600 +coolwarm diverging Cool / Warm|3b4cc03c4ec23d50c33e51c53f53c64055c84257c94358cb445acc455cce465ecf485fd14961d24a63d34b64d54c66d64e68d84f69d9506bda516ddb536edd5470de5572df5673e05875e15977e35a78e45b7ae55d7ce65e7de75f7fe86180e96282ea6384eb6485ec6687ed6788ee688aef6a8bef6b8df06c8ff16e90f26f92f37093f37295f47396f57597f67699f6779af7799cf87a9df87b9ff97da0f97ea1fa80a3fa81a4fb82a6fb84a7fc85a8fc86a9fc88abfd89acfd8badfd8caffe8db0fe8fb1fe90b2fe92b4fe93b5fe94b6ff96b7ff97b8ff98b9ff9abbff9bbcff9dbdff9ebeff9fbfffa1c0ffa2c1ffa3c2fea5c3fea6c4fea7c5fea9c6fdaac7fdabc8fdadc9fdaec9fcafcafcb1cbfcb2ccfbb3cdfbb5cdfab6cefab7cff9b9d0f9bad0f8bbd1f8bcd2f7bed2f6bfd3f6c0d4f5c1d4f4c3d5f4c4d5f3c5d6f2c6d6f1c7d7f0c9d7f0cad8efcbd8eeccd9edcdd9eccedaebcfdaead1dae9d2dbe8d3dbe7d4dbe6d5dbe5d6dce4d7dce3d8dce2d9dce1dadce0dbdcdedcdddddddcdcdedcdbdfdbd9e0dbd8e1dad6e2dad5e3d9d3e4d9d2e5d8d1e6d7cfe7d7cee8d6cce9d5cbead5c9ead4c8ebd3c6ecd3c5edd2c3edd1c2eed0c0efcfbfefcebdf0cdbbf1cdbaf1ccb8f2cbb7f2cab5f2c9b4f3c8b2f3c7b1f4c6aff4c5adf5c4acf5c2aaf5c1a9f5c0a7f6bfa6f6bea4f6bda2f7bca1f7ba9ff7b99ef7b89cf7b79bf7b599f7b497f7b396f7b194f7b093f7af91f7ad90f7ac8ef7aa8cf7a98bf7a889f7a688f6a586f6a385f6a283f5a081f59f80f59d7ef59c7df49a7bf4987af39778f39577f39475f29274f29072f18f71f18d6ff08b6ef08a6cef886bee8669ee8468ed8366ec8165ec7f63eb7d62ea7b60e97a5fe9785de8765ce7745be67259e57058e46e56e36c55e36b54e26952e16751e0654fdf634ede614ddd5f4bdc5d4ada5a49d95847d85646d75445d65244d55042d44e41d24b40d1493fd0473dcf453ccd423bcc403acb3e38ca3b37c83836c73635c53334c43032c32e31c12b30c0282fbe242ebd1f2dbb1b2cba162bb8122ab70d28b50927b40426 +cork diverging Cork|2c194c2c1b4e2c1d4f2b1e512b20532b22542b23562b25572b26592b285b2b295c2a2b5e2a2c5f2a2e612a2f622a31642a326529346729366829376a29396b293a6d283c6e283d70283f7228407328427528437628457828467928487b284a7c284b7e284d7f294f812950822a52842a53852b55872c57882d598a2e5a8b2f5c8d305e8e325f8f3361913563923664933866953a68963c69973d6b983f6c99416e9b43709c45719d47739e49749f4b76a04c77a14e79a2507aa3527ca4547da5567fa65880a75a82a85c83a95e85aa6086ac6288ad6489ae668baf688db06a8eb16d90b26f92b37193b47395b67597b77798b87a9ab97c9cba7e9dbb819fbd83a1be85a3bf88a4c08aa6c28ca8c38faac491acc594aec796afc899b1c99bb3cb9eb5cca0b7cda3b9cfa5bbd0a8bdd1aabfd3adc1d4b0c3d5b2c5d7b5c7d8b8c9dabacbdbbdcddcc0cfdec2d1dfc5d3e1c8d5e2cad7e3cdd9e5d0dbe6d2dde7d5dfe8d7e1e9dae3eadce5ebdee6ece0e8ede2e9ede3ebede5ecede6edede6edede6edece6eeebe6eeeae5ede8e4ede7e3ece5e2ebe3e0eae1dee9dfdce8dddae7dbd8e5d9d6e4d6d4e2d4d2e1d2cfdfcfcddecdcbdccbc8dbc8c6d9c6c4d7c3c1d6c1bfd4bfbcd3bcbad1bab7cfb7b5ceb5b2ccb2b0cab0aec9adabc7aba9c5a8a6c4a6a4c2a3a1c0a19fbf9f9cbd9c9abb9a97ba9795b89592b79290b5908eb38d8bb28b89b08886ae8684ad8482ab817faa7f7da87d7ba77a78a57876a37674a27371a0716f9f6f6d9d6c6b9c6a689a6866996664976462966160955f5d935d5b925b599059578f57558d55538c52518b504f894e4d884c4b864a498548478446458244438142417f403f7e3e3d7d3c3b7b3a397a383778363577343375323174302f722e2d702c2b6f2a2a6d28286b26266a2525682323662122642020631e1f611d1e5f1b1d5d1a1c5b191b59171a5816195615185414185213175012174e12164c11164b1015490f15470f14450e14430d13410d13400c133e0c123c0b123a0a12380a113709113508113308103107103006102e05102c050f2b040f2903 +icefire diverging Icefire|bde7dbbae5dab7e3d9b4e1d9b2dfd8afddd7acdbd7a9d9d6a7d7d5a4d5d5a1d3d49ed1d39bcfd398cdd295cbd293cad190c8d18dc6d08ac4d087c2cf84c1cf81bfcf7ebdce7bbbce78b9ce75b8ce72b6ce6eb4cd6bb2cd68b0cd65afcd63adcd60abcd5da9cd5aa7cd58a5cd55a3cd53a2cd50a0cd4e9ecd4c9ccd499ace4798ce4596ce4394ce4192ce3f90ce3e8ecf3c8ccf3a89cf3987cf3885d03783d03781d0377fd0377cd0377ad03878cf3975cf3a73ce3b71cd3d6ecc3e6ccb3f69c94167c74265c54363c34560c1465ebe475cbc475ab94858b64956b34954b04952ad4a50a94a4fa5494da1494c9e494a9a48499647479247468e46458a45438644428243417f42407b413e773f3d743e3c703d3b6d3c3a693b386639376338365f37355c363459343356333153323050312f4d302e4a2e2d482d2c452c2b422b2a402a293d29283b28273927263626253425253224243024232e23222d22222b222129212028212026202025201f241f1f231f1f211f1e211f1e201f1e1f1f1e1e1f1e1e201e1e211e1e221e1e231e1e251e1f261e1f271e1f291e202a1e202c1e212d1f212f1f22311f233320233520243720253921263b21273d22283f222841232943232a46242b48242c4a252e4d252f4f26305227315427325728335a28345c29355f2936622937642a38672a396a2b3a6d2b3b702b3c722c3d752c3e782c3f7b2d407e2d40812d41842d42872d428a2e438d2e43902e44932e44962e44992e449c2f459f2f44a22f44a52f44a83044ab3043ae3143b13242b33341b63441b93540bb363fbe373ec0393dc33a3cc53c3cc73d3bc93f3acc4139ce4338d04537d24737d34936d54b35d74e35d95034da5334dc5534de5733df5a33e15c33e25f33e36233e56433e66734e76a34e86d35e96f36ea7238eb753aec783bed7b3eed7e40ee8142ef8445ef8748f0894bf18c4ef18f51f29255f29558f3985bf39a5ff49d63f5a066f5a36af6a56df6a871f7ab75f7ae79f8b07cf8b380f9b684fab887fabb8bfbbe8ffbc192fcc396fcc69afdc99efdcca1fecea5fed1a9ffd4ac +managua diverging Managua|ffcf67fecd66fdcb66fbc965fac764f9c564f8c363f6c162f5bf62f4bd61f3bb60f1b960f0b75fefb55eeeb35eecb15debb05deaae5ce9ac5be8aa5be6a85ae5a659e4a459e3a358e1a158e09f57df9d56de9c56dd9a55db9855da9654d99554d89353d79152d59052d48e51d38c51d28b50d18950cf874fce864fcd844ecc824dcb814dc97f4cc87e4cc77c4bc67b4bc5794ac3774ac27649c17449c07348be7148bd7047bc6e47bb6d46b96c46b86a45b76945b66745b46644b36444b26343b16243af6042ae5f42ad5e42ab5c41aa5b41a85940a75840a6573fa4553fa3543fa1533ea0513e9e503e9d4f3d9c4d3d9a4c3d984b3c97493c95483c94473b92463b91443b8f433b8e423a8c413a8a3f3a893e3a873d39863c39843b39823a398139397f38397e37397c36397a3539793439773339763239743139733039712f3a702f3a6e2e3a6d2d3a6b2d3b6a2c3b692b3c672b3c662a3d652a3d632a3e62293f61293f6029405f29415e29425d28435c28435b28445a284659294758294857294956294a552a4c542a4d542a4e532b50522b51522c53512d54512d56502e58502f594f305b4f315d4e315e4e32604e33624d34644d35664d36684d376a4c396b4c3a6d4c3b6f4c3c714c3d734c3f754c40774c41794c437b4c447d4c457f4c47814c48834c4a854c4b864d4c884d4e8a4d4f8c4d518e4d52904e54914e55934e57954f58974f5a984f5b9a505d9c505e9d51609f5161a15163a25264a45266a55367a75369a8546aaa546cab556eac556fae5671af5672b15774b25775b35877b55878b6597ab7597bb85a7dba5b7ebb5b80bc5c81bd5c83bf5d85c05d86c15e88c25f89c35f8bc5608dc6608ec76190c86292c96293cb6395cc6497cd6498ce659acf669cd0669ed2679fd368a1d468a3d569a5d669a6d76aa8d96baada6bacdb6caddc6dafdd6db1de6eb3df6fb5e16fb6e270b8e371bae472bce572bee673c0e774c2e974c4ea75c5eb76c7ec76c9ed77cbee78cdf078cff179d1f27ad3f37ad5f47bd7f57cd9f77cdbf87dddf97edffa7ee1fb7fe3fd80e5fe81e7ff +piyg diverging Pink / Green|8e015290025492035594045797055999065a9b075c9d085e9f095fa10a61a40b63a60c65a80d66aa0e68ac0f6aae106bb1116db3126fb51370b71472b91574bb1675bd1777c01879c2197ac41a7cc51d7ec62080c72482c82884c92b86ca2f88cb3289cc368bcd3a8dce3d8fcf4191d04493d14895d24c97d34f99d4539bd5579dd65a9fd75ea1d861a2d965a4da69a6db6ca8dc70aadd73acde77aedf79b0df7cb1e07eb3e181b5e283b7e286b8e388bae48bbce58dbee590bfe692c1e795c3e897c4e89ac6e99cc8ea9fcaeba1cbeba3cdeca6cfeda8d1eeabd2eeadd4efb0d6f0b2d7f1b5d9f1b7daf2b8dbf2badcf3bcddf3bddef4bfdff4c1dff5c2e0f5c4e1f5c6e2f6c7e3f6c9e3f7cbe4f7cce5f8cee6f8d0e7f9d1e8f9d3e8fad4e9fad6eafbd8ebfbd9ecfcdbedfcddedfddeeefde0effde1effde2f0fce3f0fce4f0fce5f1fce5f1fbe6f1fbe7f2fbe8f2fbe9f2faeaf2faebf3faecf3faedf3f9eef4f9eef4f9eff4f9f0f5f9f1f5f8f2f5f8f3f6f8f4f6f8f5f6f7f6f7f7f7f7f7f7f6f6f7f5f5f7f3f5f7f2f4f7f0f3f7eff3f6edf2f6ecf1f6eaf1f6e8f0f6e7eff6e5eff6e4eef6e2edf6e1edf6dfecf6deebf6dcebf6dbeaf5d9e9f5d8e9f5d6e8f5d5e7f5d3e7f5d2e6f5d0e4f4cde2f3cae1f3c7dff2c4ddf1c1dbf0bfd9f0bcd8efb9d6eeb6d4edb3d2ecb0d0ecadcfebaacdeaa7cbe9a4c9e8a2c7e89fc6e79cc4e699c2e596c0e593bee490bde38dbbe28ab9e187b7e085b5df82b2dd7fb0dc7daeda7aacd977a9d874a7d672a5d56fa3d36ca1d26a9ed0679ccf649acd6198cc5f95cb5c93c95991c8578fc6548cc5518ac34f88c24c86c04983bf4681bd447fbc417dba407bb93e79b73d77b53c75b43b73b23971b0386faf376dad366bac3469aa3367a83266a73164a52f62a32e60a22d5ea02c5c9e2a5a9d29589b285699275498255296245094234e93224c91214b8f21498d20488c20468a2045881f43861f42841f40831e3f811e3d7f1e3c7d1d3a7b1d397a1d37781c36761c34741c33721c31711b306f1b2e6d1b2d6b1a2b691a2a681a286619276419 +puor diverging Purple / Orange|7f3b08813c08833d08853e088740088941088b42088d43078f44079145079346079548079749079a4a079c4b079e4c07a04d07a24e07a44f07a65107a85206aa5306ac5406ae5506b05606b25706b45906b65a07b75c07b95e08bb5f08bd6109be630ac0640ac2660bc4680bc6690cc76b0cc96d0dcb6e0dcd700ece720fd0730fd27510d47610d57811d77a11d97b12db7d12dc7f13de8013e08214e18417e2861ae3881de58a20e68d23e78f27e8912ae9932dea9530eb9733ed9936ee9b39ef9e3cf0a03ff1a242f2a446f3a649f4a84cf6aa4ff7ac52f8ae55f9b158fab35bfbb55efcb761fdb965fdba68fdbc6bfdbd6efdbf72fdc175fdc278fdc47bfdc57ffdc782fdc885fdca88fdcc8cfecd8ffecf92fed095fed299fed39cfed59ffed7a2fed8a6fedaa9fedbacfeddaffedeb3fee0b6fee1b9fde2bbfde3befde4c0fde5c3fce5c5fce6c8fce7cafce8cdfbe9cffbead2fbebd5faecd7faeddafaeedcfaeedff9efe1f9f0e4f9f1e6f9f2e9f8f3ecf8f4eef8f5f1f7f6f3f7f7f6f6f6f7f5f5f6f4f4f6f3f3f5f2f2f5f0f1f4eff0f4eeeef3ededf3ebecf3eaebf2e9eaf2e8e9f1e7e8f1e5e7f0e4e5f0e3e4efe2e3efe1e2eedfe1eedee0eddddfeddcddecdadcecd9dbebd8daebd7d8ead5d6e9d4d4e8d2d3e7d1d1e6cfcfe5cecde4cccbe3cbc9e2c9c8e1c8c6e0c6c4dfc5c2dec3c0ddc2bedcc0bddbbfbbdabdb9d9bcb7d8bab5d7b9b3d6b7b1d5b6b0d4b4aed3b3acd2b1aad1afa8d0ada6ceaba3cda9a1cba79fcaa59dc8a39bc7a198c59f96c49d94c29b92c19990bf988dbe968bbc9489bb9287b99085b88e82b68c80b58a7eb3887cb2867ab08477af8275ad8073ac7e70ab7d6da97b6aa87967a67764a57661a4745ea2725ba170589f6f559e6d529c6b4f9b6a4c9a684998664697644395634094613d935f3a915d37905c348e5a318d582e8c572b8a5528895326875225845023824f22804d207d4c1f7b4a1d78491c76471a7445187144176f42156c41146a3f12683e11653c0f633b0e61390c5e380b5c3609593508573306553205523003502f024d2d004b +rdbu diverging Red / Blue|67001f6a011f6d02207003207304217605217906227c07227f0823810823840924870a248a0b258d0c25900d26930e26960f279910279c11279f1228a21328a51429a81529ab162aae172ab1182bb3192cb41c2db61f2eb72230b82531ba2832bb2a34bd2d35be3036bf3338c13639c2383ac43b3cc53e3dc6413ec84440c94741cb4942cc4c44ce4f45cf5246d05548d25849d35a4ad55d4cd6604dd7634fd86551da6853db6b55dc6e57dd7059de735cdf765ee17860e27b62e37e64e48066e58368e6866ae8896ce98b6eea8e70eb9172ec9374ee9677ef9979f09c7bf19e7df2a17ff3a481f4a683f5a886f5aa89f5ac8bf6af8ef6b191f6b394f7b596f7b799f7b99cf8bb9ef8bda1f8bfa4f9c2a7f9c4a9f9c6acfac8affacab1fbccb4fbceb7fbd0b9fcd3bcfcd5bffcd7c2fdd9c4fddbc7fddcc9fdddcbfcdecdfcdfcffce0d0fce2d2fbe3d4fbe4d6fbe5d8fbe6dafae7dcfae8defae9dffaeae1f9ebe3f9ede5f9eee7f9efe9f9f0ebf8f1edf8f2eff8f3f0f8f4f2f7f5f4f7f6f6f6f7f7f5f6f7f3f5f6f2f5f6f0f4f6eff3f5edf2f5ecf2f5eaf1f5e9f0f4e7f0f4e6eff4e4eef4e3edf3e1edf3e0ecf3deebf2ddebf2dbeaf2dae9f2d8e9f1d7e8f1d5e7f1d4e6f1d2e6f0d1e5f0cfe4efcce2efcae1eec7e0edc5dfecc2ddecc0dcebbddbeabbdaeab8d8e9b6d7e8b3d6e8b1d5e7aed3e6acd2e5a9d1e5a7d0e4a5cee3a2cde3a0cce29dcbe19bc9e098c8e096c7df93c6de90c4dd8dc2dc8ac0db87beda84bcd981bad87eb8d77bb6d678b4d575b2d471b0d36eaed26bacd168abd065a9cf62a7ce5fa5cd5ca3cb59a1ca569fc9529dc84f9bc74c99c64997c54695c44393c34291c2408fc13f8ec03e8cbf3c8abe3b88be3a87bd3885bc3783bb3681ba3480b9337eb8327cb7307ab62f79b52e77b52c75b42b73b32a71b22870b1276eb0266caf246aae2369ad2267ac2065ab1f63a81e61a51d5fa21c5c9f1b5a9c1a589919569618549317529015508d144e8a134c8712498411478110457e0f437b0e41790d3f760c3d730a3b7009386d08366a073467063264053061 +spectral diverging Spectral|9e0142a00343a20643a40844a70b44a90d45ab0f45ad1246af1446b11747b41947b61b48b81e48ba2049bc2249be254ac1274ac32a4bc52c4bc72e4cc9314ccb334dcd364dd0384ed23a4ed43d4fd63f4fd7414ed8434ed9444dda464ddc484cdd4a4cde4c4bdf4e4be1504be2514ae3534ae45549e55749e75948e85b48e95c47ea5e47eb6046ed6246ee6445ef6645f06744f26944f36b43f46d43f47044f57245f57547f57748f67a49f67c4af67f4bf7814cf7844ef8864ff88950f88c51f98e52f99153f99355fa9656fa9857fa9b58fb9d59fba05bfba35cfca55dfca85efcaa5ffdad60fdaf62fdb163fdb365fdb567fdb768fdb96afdbb6cfdbd6dfdbf6ffdc171fdc372fdc574fdc776fec877feca79fecc7bfece7cfed07efed27ffed481fed683fed884feda86fedc88fede89fee08bfee18dfee28ffee491fee593fee695fee797fee999feea9bfeeb9dfeec9ffeeda1feefa3fff0a6fff1a8fff2aafff3acfff5aefff6b0fff7b2fff8b4fffab6fffbb8fffcbafffdbcfffebeffffbefefebdfdfebbfcfebafbfdb8fafdb7f9fcb5f8fcb4f7fcb2f6fbb0f5fbaff4faadf3faacf2faaaf1f9a9f0f9a7eff9a6eef8a4edf8a3ecf7a1ebf7a0eaf79ee9f69de8f69be7f59ae6f598e4f498e1f399dff299ddf19adaf09ad8ef9bd6ee9bd3ed9cd1ed9ccfec9dcdeb9dcaea9ec8e99ec6e89fc3e79fc1e6a0bfe5a0bce4a0bae3a1b8e2a1b5e1a2b3e0a2b1dfa3aedea3acdda4aadca4a7dba4a4daa4a2d9a49fd8a49cd7a499d6a497d5a494d4a491d3a48fd2a48cd1a489d0a486cfa584cea581cda57ecca57ccaa579c9a576c8a574c7a571c6a56ec5a56bc4a569c3a566c2a564c0a662bda760bba85eb9a95cb7aa5ab4ab58b2ac56b0ad54aead52abae50a9af4ea7b04ba4b149a2b247a0b3459eb4439bb54199b63f97b73d95b83b92b93990ba378ebb358bbc3389bd3387bc3585bb3682ba3880b93a7eb83b7cb73d79b63f77b54175b44273b34471b2466eb1486cb0496aaf4b68ae4d65ad4e63ac5061aa525fa9545ca8555aa75758a65956a55b53a45c51a35e4fa2 +vanimo diverging Vanimo|ffcdfdfdcafbfcc7f9fac4f7f9c1f4f7bef2f6bbf0f4b9eef3b6ecf1b3eaf0b0e8eeade6ecabe4eba8e2e9a5e0e8a2dee6a0dce59ddae39ad8e298d6e095d4de93d2dd90d0db8eceda8bccd889cad786c8d584c6d381c4d27fc2d07dc0cf7abfcd78bdcb76bbca73b9c871b7c76fb5c56db3c36bb2c269b0c067aebe65acbd63aabb61a8b95fa7b85da5b65ba3b45aa1b2589fb1569eaf549cad539aab5198a95096a74e94a54c92a34b90a1498e9f488c9d468a9b4488994386964184944082923e80903d7e8d3c7b8b3a798839778637758336728135707e336e7c326b793169763067742e64712d626e2c606c2b5d692a5b6629596427566126545e25515c244f59234d56224a5421485121464f20444c1f41491e3f471d3d451c3b421c39401b373e1a353b1a3339193137192f35182d33172c31172a2f17282e16272c16252a152429152328152126152025141f24141e23141d22141c21141b20141a1f14191e14181d14181d14171c14161c14161b14151b14151a14141a15141a15131a15131916131916121916121917121917121918111918111a19111a1a111a1a111a1b111b1c111b1d111b1e111c1f111c20111d21121d22121e24121f25121f2612202713212913222a13232c14232d14242f142530142632152734152935162a37162b39162c3b172d3c172e3e182f401831421832441933461934471a36491a374b1b384d1b3a4f1c3b511c3c531d3d551d3f561e40581f415a1f435c20445e204560214762214863224965234b67234c69244d6b244e6c25506e25517026527227547427557528567729577929597b2a5a7c2a5b7e2b5c802c5e812d5f832d60852e62872f63882f648a30658c31678e326890336a92346b93356c95366e97376f9938719b39729d3b749f3c75a13d77a33f79a6407aa8427caa437eac457fae4781b04983b34b85b54d87b74f88ba518abc538cbe558ec15890c35a92c65d94c86096cb6298cd659ad0689cd26b9ed56ea0d772a2da75a4dd78a6df7ca9e27fabe483ade786afea8ab1ec8eb3ef92b5f295b7f599baf79dbcfaa1befda5 +vik diverging Vik|001261011462011563011764011865011a66021c67021d68021f6902206a02226b02236c02256d02276e02286f022a70022b71022d72022e7302307402317502337602347702367802377902397a023a7b033c7c033e7d033f7e03417f034280034481034582034783034984034a85044c86044d87044f8805518905528a06548b06568c07578d08598f095b900b5d910c5e920e6093106294116496136697156798176999196b9a1c6d9c1e6f9d20719e2373a02575a12877a22b79a42d7ba5307da6337fa83681a93983ab3c85ac3f87ad4289af458bb0488db24b90b34e92b45194b65496b75798b95a9aba5d9cbb619ebd64a0be67a2c06aa4c16da6c271a8c474aac577acc67aaec87db0c980b2ca84b4cc87b6cd8ab8ce8dbad090bcd194bed297c0d49ac2d59dc4d6a0c5d8a3c7d9a7c9daaacbdcadcdddb0cfdeb3d1dfb6d3e1bad5e2bdd6e3c0d8e4c3dae5c6dbe6c9dde7ccdfe8cfe0e8d2e1e9d5e3e9d8e4e9dbe5e9dee6e9e0e6e9e2e7e8e5e7e8e7e7e7e8e7e5eae6e4ebe6e2ece5e0ede4deeee3dceee1daeee0d8eeded5eeddd3eedbd0eed9cdedd7cbedd5c8ecd3c5ecd1c3ebd0c0eacebde9ccbae9cab8e8c8b5e7c6b2e6c4b0e5c1ade4bfaae4bea8e3bca5e2baa2e1b8a0e0b69ddfb49adfb298deb095ddae93dcac90dbaa8ddba88bdaa688d9a486d8a283d7a081d69f7ed69d7cd59b79d49977d39774d39572d29470d1926dd0906bcf8e68cf8c66ce8b64cd8961cc875fcc855dcb835aca8258c98056c97e53c87c51c77b4fc6794cc6774ac57548c47445c37243c27041c26e3fc16d3cc06b3abf6938be6736be6533bd6431bc622fbb602dba5e2ab85c28b75a26b65824b55521b3531fb2511db04f1baf4c18ad4a16ab4814a94512a74310a5400fa33e0da13c0b9f390a9c37099a3508983307963107942f06912d068f2b068d29068b2706892606872406852206832106811f067f1e067e1d067c1b067a1a067818067617067415067314067113076f11076d10076c0e076a0d07680c07670a076509076307076206076004085e03085d02085b0108590008 +vlag diverging Vlag|2369bd266abd296cbc2c6dbc2f6ebc316fbc3470bc3671bc3972bc3b73bc3d74bc3f75bc4276bc4477bc4678bc4879bc4a7bbc4c7cbc4e7dbc507ebc517fbc5380bc5581bc5782bc5983bd5b84bd5c85bd5e86bd6087bd6288bd6489be658abe678bbe698cbe6a8dbf6c8ebf6e90bf6f91bf7192c07393c07594c07695c17896c17997c17b98c27d99c27e9ac2809bc3829cc3839dc4859ec487a0c488a1c58aa2c58ba3c68da4c68fa5c790a6c792a7c893a8c895a9c897abc998acc99aadca9baecb9dafcb9fb0cca0b1cca2b2cda3b4cda5b5cea7b6cea8b7cfaab8d0abb9d0adbbd1afbcd1b0bdd2b2bed3b3bfd3b5c0d4b7c2d5b8c3d5bac4d6bbc5d7bdc6d7bfc8d8c0c9d9c2cadac3cbdac5cddbc7cedcc8cfddcad0ddcbd1decdd3dfcfd4e0d0d5e0d2d7e1d4d8e2d5d9e3d7dae4d9dce5dadde5dcdee6dde0e7dfe1e8e1e2e9e2e3eae4e5ebe6e6ece7e7ece9e9edebeaeeecebefeeedf0efeef1f1eff2f2f0f2f3f1f3f5f2f4f6f3f4f7f4f4f8f4f5f9f5f5f9f5f5faf5f5faf5f5faf5f4faf5f4faf4f3faf3f3faf3f2faf2f1faf0eff9efeef9eeedf8edebf7ebeaf7eae8f6e8e7f5e7e5f5e5e4f4e3e2f3e2e0f2e0dff2dfddf1dddbf0dbdaefdad8efd8d6eed7d5edd5d3ecd3d2ecd2d0ebd0ceeacfcdeacdcbe9cbc9e8cac8e7c8c6e7c7c5e6c5c3e5c3c1e5c2c0e4c0bee3bfbde3bdbbe2bcb9e1bab8e1b9b6e0b7b5dfb5b3dfb4b2deb2b0deb1aeddafaddcaeabdcacaadbaba8daa9a7daa8a5d9a6a4d9a5a2d8a3a0d7a29fd7a09dd69f9cd59d9ad59c99d49a97d49896d39794d29593d29491d19290d1918ed08f8dcf8e8bcf8c8ace8b88cd8987cd8885cc8784cc8582cb8481ca827fca817ec97f7dc87e7bc87c7ac77b78c77977c67875c57674c57572c47371c3726fc3706ec26f6dc16d6bc16c6ac06a68c06967bf6765be6664be6463bd6361bc6160bc605ebb5e5dba5d5cb95b5ab95a59b85857b75756b75555b65453b55252b55151b44f4fb34d4eb24c4cb24a4bb1494ab04748af4647af4446ae4244ad4143ac3f42ac3e40ab3c3faa3a3ea9393ca9373b +phase cyclic Phase|a8780da9770fab7611ac7513ae7414af7316b17218b27119b3701bb56f1db66e1eb76d20b96c22ba6b23bb6a25bd6926be6828bf672ac0662bc1652dc2642ec46230c56132c66033c75f35c85e37c95d38ca5c3acb5a3ccc593ecd583fce5741cf5643d05445d05347d15249d2514bd34f4dd44e4fd54d51d54b53d64a55d74957d8475ad8465cd9455ed94361da4263db4066db3f68dc3d6bdc3c6ddd3a70dd3973dd3876de3678de357bde337ede3281df3184df2f87df2e8adf2d8ddf2b90df2a93de2997de289ade289dde27a0dd26a3dd26a6dc25a9dc25addb25b0da25b3da26b6d926b9d827bcd727bed628c1d529c4d42ac7d32bc9d22dccd12eced02fd0cf31d3cd32d5cc34d7cb35d9c937dbc839ddc63adfc53ce1c33ee2c23fe4c041e5be43e7bd45e8bb46e9b948ebb84aecb64bedb44deeb24fefb050efae52f0ac54f1aa55f1a957f2a759f3a45af3a25cf3a05df49e5ff49c60f49a62f49863f49565f49366f49168f48f69f48c6bf38a6cf3876df3856ff28270f18071f17d73f07b74ef7875ef7677ee7378ed7079ec6e7aeb6b7be9687ce8667ee7637fe66080e45d81e35a82e15883df5584de5285dc4f86da4d87d84a87d74788d54589d3428ad1408acf3d8bcd3b8ccb388cc9368dc7348ec4328ec2308fc02e8fbe2c90bc2a90ba2891b82791b62591b42492b22392b02192ae2093ac1f93aa1e93a81d94a61c94a41b94a21a94a019959e19959c18959a17959816969615969414969214969013978e12978c11978a1097880f97860e98840d98820d98800c987e0c987c0b99790b99770b99750c99730d99700e996e0f9a6b119a69139a66159a63179a61199a5e1c9a5b1f9a58219a55249a52279a4f2b9a4c2e9a493199463599433899403c993c4098394398364797324b972f4f962c5396295695265a94235e942061931e65921b6891196b90176f9016728f14748e13778d127a8c117d8b107f8b0f828a0f84890e86880e88870e8b860d8d850d8f840d91830d93830d95820d97810d99800d9b7f0d9d7e0d9f7d0da17c0da27b0da47a0da6790da8780d +romao cyclic RomaO|73395774395675395475385376385177385077384f78384d79384c79384b7a38497b38487c38477c39467d39457e39437e39427f3a41803a40813b3f813b3e823c3d833c3c843d3b843d3a853e39863f388740378740378841368942358a43348b44338c45338c46328d47318e48318f4930904a30914c2f924d2f934e2e94502e94512d95522d96542d97552c98572c99582c9a5a2c9b5b2c9c5d2b9d5f2b9e602b9f622ba0642ca2662ca3672ca4692ca56b2da66d2da76f2da8712ea9732eaa752fab7730ad7930ae7b31af7d32b07f33b18134b28335b48636b58837b68a39b78c3ab88e3bb9913dbb933fbc9540bd9842be9a44bf9c46c19f47c2a149c3a34bc4a54ec5a850c6aa52c8ac54c9af57cab159cbb35cccb55ecdb861ceba63cfbc66cfbe68d0c06bd1c26ed2c470d2c673d3c876d4c978d4cb7bd4cd7ed5ce81d5d083d5d186d6d388d6d48bd6d58ed6d790d6d893d5d995d5da98d5db9ad4dc9cd4dd9fd3dda1d3dea3d2dfa5d1dfa7d0e0a9cfe0abcee0adcde1afcce1b1cbe1b3cae1b5c8e1b6c7e1b8c5e1b9c4e1bbc2e1bcc1e1bebfe1bfbde0c0bbe0c2b9dfc3b8dfc4b6dec5b4dec6b1ddc7afdcc8addcc8abdbc9a9dacaa7d9cba4d8cba2d7cca0d6cc9dd5cd9bd4cd99d3ce96d1ce94d0ce92cfce8fcecf8dcccf8bcbcf88c9cf86c8cf84c6cf81c5cf7fc3cf7dc2ce7bc0ce78bece76bdce74bbcd72b9cd70b8cd6eb6cc6cb4cc6ab2cb68b1cb67afca65adca63abc962a9c960a8c85fa6c75da4c75ca2c65aa0c5599ec4589cc4579bc35699c25597c15495c05393bf5291be528fbd518dbc508bbb508aba4f88b94f86b84f84b74f82b64e80b44e7eb34e7cb24e7ab04f78af4f76ae4f75ac4f73ab5071a9506fa8516da6516ba45269a35267a153669f54649e54629c55609a565f98575d96575b945859935958915a568f5b558d5c538b5c52895d50875e4f855f4d83604c81614b7f62497d63487b63477964467765457666447467437268427068416e69406c6a3f6b6b3f696c3e676c3d656d3d646e3c626f3b606f3b5f703a5d713a5c723a5a723959 +twilight cyclic Twilight|e2d9e2e1d9e2e1d9e2e0d9e2e0d9e2dfd9e1ded9e1ded9e1ddd9e0dcd9e0dcd9dfdbd8dfdad8dfd9d8ded8d8ded7d7ddd6d7ddd5d6dcd4d6dcd3d6dbd2d5dbd1d5dad0d4d9ced3d9cdd3d8ccd2d8cbd2d7c9d1d7c8d0d6c7d0d5c5cfd5c4ced4c2ced4c1cdd3bfccd3beccd2bccbd1bbcad1b9c9d0b8c9d0b6c8cfb5c7cfb3c6ceb2c6ceb0c5cdafc4cdadc3cdacc2ccaac2cca9c1cba7c0cba6bfcaa4becaa3becaa1bdc9a0bcc99ebbc99dbac89cb9c89ab8c899b8c897b7c796b6c795b5c793b4c692b3c691b2c68fb1c68eb1c58db0c58cafc58aaec589adc588acc487abc486aac485a9c484a8c482a7c381a6c380a5c37fa5c37ea4c37da3c37ca2c27ba1c27aa0c2799fc2789ec2779dc2769cc1769bc1759ac17499c17398c17297c17196c17195c07094c06f93c06e92c06e91c06d90c06c8fbf6c8ebf6b8dbf6b8cbf6a8bbf698abf6989be6888be6887be6786be6785be6684bd6683bd6682bd6580bd657fbd647ebc647dbc647cbc637bbc637abb6379bb6278bb6277bb6276ba6275ba6173ba6172ba6171b96170b9616fb9606eb8606db8606cb8606ab76069b76068b66067b66066b65f65b55f64b55f62b45f61b45f60b45f5fb35f5eb35f5db25f5bb25f5ab15f59b15f58b05f57b05f55af5e54ae5e53ae5e52ad5e51ad5e4fac5e4eab5e4dab5e4caa5e4ba95e49a95e48a85e47a75e46a65e45a65e43a55d42a45d41a35d40a25d3ea15d3da15d3ca05d3b9f5d3a9e5c389d5c379c5c369b5c359a5c34995b32985b31965b30955b2f945a2e935a2d925a2b90592a8f59298e59288d58278b58268a572588572487572385562284562182552081551f7f541e7e531e7c531d7a521c79511b77511a75501a744f19724f19704e186f4d176d4c176b4c16694b16684a156649156448156347146147145f46145e45135c44135a4313594212574112564112544012533f12513e11503d114e3d114d3c114b3b114a3a11493a114839114638114537114437114336114236114135114034113f34113e33113d33113c32123b32123a31123a3113393013383014372f143630143731133731133732123733123733123734123834123835113836113836113937113938113939113a3a113a3a113a3b113b3c113b3d113c3e113c3f123d40123d41123d42123e43123e44123f4612404713404813414913414a13424b13424d14434e14434f14445014445215455315455415465615465716475816475916485b16485c17495d17495f174a60184a61184b63184b64194b65194c67194c681a4d691a4d6b1b4d6c1b4e6d1b4e6f1c4e701c4e711d4f721d4f741e4f751e4f761f4f781f4f7920507a20507b21507d21507e22507f23508023508124508325508425508526508627508727508828508a29508b2a508c2a508d2b508e2c508f2d50902e50912f50922f509330509431509532509633509734509835509936509a37509b38509c39509d3a509e3b509f3c50a03d50a03e50a13f50a24050a34150a44250a54350a54450a64550a74650a84750a94850a94950aa4a50ab4b50ac4c50ac4d51ad4e51ae5051af5151af5251b05351b15452b15552b25652b35752b35953b45a53b55b53b55c54b65d54b65e54b75f55b86155b86255b96356b96456ba6557ba6657bb6857bb6958bc6a58bc6b59bd6c5abd6e5abe6f5bbe705bbf715cbf725dc0745dc0755ec0765fc1775fc17960c27a61c27b62c27c63c37d63c37f64c48065c48166c48267c58468c58569c5866ac6876bc6896cc68a6dc68b6ec78c6fc78e71c78f72c89073c89174c89275c89477c99578c99679c9977bca997cca9a7dca9b7fca9c80cb9d82cb9f83cba085cca186cca287cca389cca58bcda68ccda78ecda88fcea991ceab92ceac94cfad96cfae97cfaf99d0b09bd0b29cd0b39ed1b4a0d1b5a1d1b6a3d2b7a5d2b8a7d3b9a8d3baaad4bcacd4bdadd4beafd5bfb1d5c0b3d6c1b4d6c2b6d7c3b8d7c4b9d8c5bbd8c6bdd8c7bed9c8c0d9c9c2dacac3dacbc5dbcbc6dbccc8dccdcadccecbdccfcdddd0ceddd0cfddd1d1ded2d2ded3d3ded3d4dfd4d6dfd4d7dfd5d8e0d6d9e0d6dae0d7dae0d7dbe1d7dce1d8dde1d8dee1d8dfe2d8dfe2d9e0e2d9e1e2d9e1e2d9e2 +dark2 categorical Dark2|1b9e77d95f027570b3e7298a66a61ee6ab02a6761d666666 +okabeito categorical Okabe-Ito|e69f0056b4e9009e73f0e4420072b2d55e00cc79a7000000 +paired categorical Paired|a6cee31f78b4b2df8a33a02cfb9a99e31a1cfdbf6fff7f00cab2d66a3d9affff99b15928 +set2 categorical Set2|66c2a5fc8d628da0cbe78ac3a6d854ffd92fe5c494b3b3b3 +tab10 categorical Tab10|1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf +tab20 categorical Tab20|1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5 +tableau10 categorical Tableau10|4e79a7f28e2ce1575976b7b259a14fedc949af7aa1ff9da79c755fbab0ab +turbo multihue Turbo|30123b32154333184a341b51351e5836215f37246638276d392a733a2d793b2f803c32863d358b3e38913f3b973f3e9c4040a24143a74146ac4249b1424bb5434eba4451bf4454c34456c74559cb455ccf455ed34661d64664da4666dd4669e0466be3476ee64771e94773eb4776ee4778f0477bf2467df44680f64682f84685fa4687fb458afc458cfd448ffe4391fe4294ff4196ff4099ff3e9bfe3d9efe3ba0fd3aa3fc38a5fb37a8fa35abf833adf731aff52fb2f42eb4f22cb7f02ab9ee28bceb27bee925c0e723c3e422c5e220c7df1fc9dd1ecbda1ccdd81bd0d51ad2d21ad4d019d5cd18d7ca18d9c818dbc518ddc218dec018e0bd19e2bb19e3b91ae4b61ce6b41de7b21fe9af20eaac22ebaa25eca727eea42aefa12cf09e2ff19b32f29835f39438f4913cf58e3ff68a43f78746f8844af8804ef97d52fa7a55fa7659fb735dfc6f61fc6c65fd6969fd666dfe6271fe5f75fe5c79fe597dff5680ff5384ff5188ff4e8bff4b8fff4992ff4796fe4499fe429cfe409ffd3fa1fd3da4fc3ca7fc3aa9fb39acfb38affa37b1f936b4f836b7f735b9f635bcf534bef434c1f334c3f134c6f034c8ef34cbed34cdec34d0ea34d2e935d4e735d7e535d9e436dbe236dde037dfdf37e1dd37e3db38e5d938e7d739e9d539ebd339ecd13aeecf3aefcd3af1cb3af2c93af4c73af5c53af6c33af7c13af8be39f9bc39faba39fbb838fbb637fcb336fcb136fdae35fdac34fea933fea732fea431fea130fe9e2ffe9b2dfe992cfe962bfe932afe9029fd8d27fd8a26fc8725fc8423fb8122fb7e21fa7b1ff9781ef9751df8721cf76f1af66c19f56918f46617f36315f26014f15d13f05b12ef5811ed5510ec530feb500eea4e0de84b0ce7490ce5470be4450ae2430ae14109df3f08dd3d08dc3b07da3907d83706d63506d43305d23105d02f05ce2d04cc2b04ca2a04c82803c52603c32503c12302be2102bc2002b91e02b71d02b41b01b21a01af1801ac1701a91601a71401a41301a112019e10019b0f01980e01950d01920b018e0a018b09028808028507028106027e05027a0403 diff --git a/packages/gpu/src/colors/presets/provenance.json b/crates/latkit/colormaps/provenance.json similarity index 100% rename from packages/gpu/src/colors/presets/provenance.json rename to crates/latkit/colormaps/provenance.json diff --git a/crates/latkit/shaders/compute/bounds.wesl b/crates/latkit/shaders/compute/bounds.wesl new file mode 100644 index 00000000..afe01bbf --- /dev/null +++ b/crates/latkit/shaders/compute/bounds.wesl @@ -0,0 +1,85 @@ +// What marks draw, measured for fitting: the least and greatest x, y, and z of each mark's shown +// instances in position units, as ordered words, through the same geometry the draws use: a vertex +// as its box, a stroke as its points, an area as its triangles' corners. While a fit measures chosen +// rows, only rows marked FIT count. + +import package::lib::types::{NONE, FIT, PATH_ENDS, PATH_GEOMETRY, EXTENT_WORDS, VERTEX_POSITION, HALF_UNITS, item}; +import package::lib::bind::{frame, eye, mark, state}; +import package::lib::focus::focus_of; +import package::lib::reduce::ordered; +import package::lib::state::{row_at, vertex_at}; +import package::lib::points::{placed, vertex_half}; +import package::lib::path::{PATH, segment, segment_ends, stroke_style, stroke_instances}; +import package::lib::triangles::{triangle_corner, triangle_row, triangle_instances}; + +@group(2) @binding(2) var extents: array>; + +fn extend(p: vec3f) { + let e = EXTENT_WORDS * mark.index; + atomicMax(&extents[e], ~ordered(p.x)); + atomicMax(&extents[e + 1u], ~ordered(p.y)); + atomicMax(&extents[e + 2u], ~ordered(p.z)); + atomicMax(&extents[e + 3u], ordered(p.x)); + atomicMax(&extents[e + 4u], ordered(p.y)); + atomicMax(&extents[e + 5u], ordered(p.z)); +} + +fn counted(row: u32) -> bool { + return frame.fitting == 0u || (focus_of(row) & FIT) != 0u; +} + +@compute @workgroup_size(256) +fn points(@builtin(global_invocation_id) id: vec3u) { + let i = item(id); + if i >= mark.rows || !counted(i) { + return; + } + let v = vertex_at(row_at(i)); + if (v.flags & 1u) == 0u || !placed(v) { + return; + } + // A marker sized in units is part of the box. One sized in pixels is that size at any zoom, so + // it counts as its position, and the fit's padding holds its pixels: measured at the zoom shown, + // its pixels would stand for any number of units. + let units = (v.flags & HALF_UNITS) != 0u; + let half = select(vec2f(0.0), vertex_half(v) / eye.px_per_unit.x, units); + let p = v.hi + v.lo; + extend(vec3f(p - half, v.elevation)); + extend(vec3f(p + half, v.elevation)); +} + +@compute @workgroup_size(256) +fn strokes(@builtin(global_invocation_id) id: vec3u) { + let i = item(id); + if PATH == PATH_ENDS || i >= stroke_instances() { + return; + } + let s = segment(i); + if s.row >= mark.rows || !counted(s.row) || !stroke_style(s.row).shown { + return; + } + let ends = segment_ends(s); + for (var i = 0u; i < 2u; i++) { + if ends[i].shown { + extend(ends[i].position); + } + } +} + +@compute @workgroup_size(256) +fn areas(@builtin(global_invocation_id) id: vec3u) { + let i = item(id); + if PATH != PATH_GEOMETRY || i >= triangle_instances() { + return; + } + let row = triangle_row(i); + if row >= mark.rows || !counted(row) { + return; + } + for (var k = 0u; k < 3u; k++) { + let c = triangle_corner(i, k); + if c.shown { + extend(c.position); + } + } +} diff --git a/crates/latkit/shaders/compute/compose.wesl b/crates/latkit/shaders/compute/compose.wesl new file mode 100644 index 00000000..25690aa3 --- /dev/null +++ b/crates/latkit/shaders/compute/compose.wesl @@ -0,0 +1,91 @@ +// A shot's panels composed into the bytes a consumer takes, so no pixel is touched on the CPU: RGBA +// rows with straight alpha for an image, or NV12 planes (BT.709, limited range) for an encoder. One +// dispatch per panel writes its panel of the picture in whole words; a fill writes the background +// where no panel draws. + +import package::lib::types::Compose; + +@group(2) @binding(0) var panel: texture_2d; +@group(2) @binding(1) var bytes: array; +@group(2) @binding(2) var compose: Compose; + +// BT.709 luma weights of gamma-encoded color, and the scales of its two chroma differences. +const LUMA: vec3f = vec3f(0.2126, 0.7152, 0.0722); +const BLUE: f32 = 1.8556; +const RED: f32 = 1.5748; + +// A panel's premultiplied color as the picture keeps it: straight with its alpha in a transparent +// image, else over black. +fn kept(c: vec4f) -> vec4f { + if compose.alpha == 0u { + return vec4f(c.rgb, 1.0); + } + if c.a <= 0.0 { + return vec4f(0.0); + } + return vec4f(c.rgb / c.a, c.a); +} + +// Writes the 4×2 block of NV12 at `at` from its eight colors, rows of four. +fn write_block(at: vec2u, rgb: array) { + var chroma = vec4f(0.0); + for (var row = 0u; row < 2u; row++) { + var luma = vec4f(0.0); + for (var column = 0u; column < 4u; column++) { + let c = rgb[row * 4u + column]; + let y = dot(c, LUMA); + luma[column] = y; + // Cb and Cr of each 2×2, averaged. + let pair = column / 2u * 2u; + chroma[pair] += (c.b - y) / BLUE * 0.25; + chroma[pair + 1u] += (c.r - y) / RED * 0.25; + } + bytes[((at.y + row) * compose.picture.x + at.x) / 4u] = pack4x8unorm((16.0 + 219.0 * luma) / 255.0); + } + let words = compose.chroma + (at.y / 2u * compose.picture.x + at.x) / 4u; + bytes[words] = pack4x8unorm((128.0 + 224.0 * chroma) / 255.0); +} + +// One pixel of a panel as an RGBA word. +@compute @workgroup_size(16, 16) +fn rgba(@builtin(global_invocation_id) id: vec3u) { + if any(id.xy >= compose.size) { + return; + } + let at = compose.origin + id.xy; + bytes[at.y * compose.picture.x + at.x] = pack4x8unorm(kept(textureLoad(panel, id.xy, 0))); +} + +// One pixel of the background as an RGBA word. +@compute @workgroup_size(16, 16) +fn fill_rgba(@builtin(global_invocation_id) id: vec3u) { + if any(id.xy >= compose.picture) { + return; + } + bytes[id.y * compose.picture.x + id.x] = pack4x8unorm(compose.background); +} + +// One 4×2 block of a panel as NV12: two words of luma and one of chroma. +@compute @workgroup_size(16, 16) +fn nv12(@builtin(global_invocation_id) id: vec3u) { + let block = id.xy * vec2u(4u, 2u); + if any(block >= compose.size) { + return; + } + var rgb: array; + for (var i = 0u; i < 8u; i++) { + rgb[i] = textureLoad(panel, block + vec2u(i % 4u, i / 4u), 0).rgb; + } + write_block(compose.origin + block, rgb); +} + +// One 4×2 block of the background as NV12. +@compute @workgroup_size(16, 16) +fn fill_nv12(@builtin(global_invocation_id) id: vec3u) { + let block = id.xy * vec2u(4u, 2u); + if any(block >= compose.picture) { + return; + } + let c = compose.background.rgb * compose.background.a; + write_block(block, array(c, c, c, c, c, c, c, c)); +} diff --git a/crates/latkit/shaders/compute/evaluate.wesl b/crates/latkit/shaders/compute/evaluate.wesl new file mode 100644 index 00000000..cf1dc78e --- /dev/null +++ b/crates/latkit/shaders/compute/evaluate.wesl @@ -0,0 +1,435 @@ +// The expression machine: every row of a mark runs the mark's channels, which store into its state. +// All rows run the same instructions, so control flow stays uniform across a workgroup. A dispatch +// covers the row blocks the mark lists, only those whose rows changed when only those did. +// +// While the mark eases (`mark.frozen` set), a row whose visibility flips fades, and rows past +// `mark.rows` left, fading out. While it eases toward what changed (`mark.settled` set), channels +// store into the settled mirror instead, once per change, and each frame `ease` writes what every +// row shows from its frozen and settled state by the mark's progress: numbers and colors mix, positions +// move by their offset, and the rest show as evaluated. No channel runs to ease. + +import package::lib::types::{ + NONE, MISSING, MISSING_COLOR, STACK, VISIBLE, PLACED, FADE_IN, FADE_OUT, ENTERING, BLOCK_ROWS, item, + BLEND_KEEP, BLEND_NUMBER, BLEND_COLOR, BLEND_POSITION, + VERTEX_POSITION, VERTEX_ELEVATION, VERTEX_FLAGS, VERTEX_HALF, VERTEX_RANGE, HALF_UNITS, OWN_HEIGHT, SIZED, MARK_VERTICES, + OP_CONST, OP_MISSING, OP_FIELD, OP_SELECTED, OP_HOVERED, OP_POINTER, OP_ELAPSED, OP_THEME, OP_ZOOM, + OP_NEG, OP_NOT, OP_ABS, OP_SQRT, OP_SIN, OP_COS, OP_FLOOR, OP_LOG, OP_EXP, + OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MIN, OP_MAX, OP_MOD, OP_POW, + OP_LT, OP_LE, OP_GT, OP_GE, OP_EQ, OP_NE, OP_AND, OP_OR, + OP_SELECT, OP_SCALE, OP_COLORMAP, OP_STORE, OP_STORE_COLOR, OP_STORE_FLAG, OP_STORE_POSITION, + OP_POSITION, OP_STORE_END, OP_STORE_CODE, OP_REDUCE, +}; +import package::lib::bind::{frame, program, mark, state}; +import package::lib::state::{travel_words, pack_range}; +import package::lib::read::{column_value, bits_value, missing, missing_bits}; +import package::lib::focus::{is_selected, is_hovered}; +import package::lib::color::{scale, colormap}; +import package::lib::project::{project, to_screen}; +import package::lib::reduce::{ordered, unordered}; + +// Each row's state as drawn when the mark's transition began. +@group(2) @binding(1) var frozen: array; +// Per fitted domain: the order-preserving bits of its least and greatest value. +@group(2) @binding(4) var domains: array>; +// Each row's state as its channels evaluated it, where it settles once the mark's transition ends: +// the state's mirror, written while the mark eases toward it. +@group(2) @binding(14) var settled: array; +// Each mark's row blocks a dispatch covers: at `mark.block`, `mark.blocks` of them. +@group(2) @binding(16) var blocks: array; + +// The row invocation `id` evaluates: row `id.x` of the mark's `id.y`th listed block. +fn row_of(id: vec3u) -> u32 { + return blocks[mark.block + id.y] * BLOCK_ROWS + id.x; +} + +fn constant(i: u32) -> u32 { + return program[mark.constants + i]; +} + +fn constant_float(i: u32) -> f32 { + return bitcast(constant(i)); +} + +// A domain record in constants: fitted flag, least, greatest, reduction index. +fn domain(at: u32) -> vec2f { + if constant(at) == 0u { + return vec2f(constant_float(at + 1u), constant_float(at + 2u)); + } + let d = 2u * (mark.domains + constant(at + 3u)); + let high = atomicLoad(&domains[d + 1u]); + if high == 0u { + return vec2f(0.0, 1.0); + } + return vec2f(unordered(~atomicLoad(&domains[d])), unordered(high)); +} + +fn theme_word(slot: u32) -> u32 { + return frame.theme[slot / 4u][slot % 4u]; +} + +// Where word `word` of `row` lives: a kind word, or past the kind words an extra word. +fn word_at(row: u32, word: u32) -> u32 { + if word < mark.stride { + return mark.state + row * mark.stride + word; + } + return mark.extra + row * mark.extras + (word - mark.stride); +} + +fn easing() -> bool { + return mark.frozen != NONE; +} + +// Whether channels store into the settled mirror: the mark eases toward what they evaluate. +fn settling() -> bool { + return mark.settled != NONE; +} + +// Word `word` of `row` where channels store it: the settled state while the mark eases toward it, +// else the state. The settled state mirrors the state, word for word. +fn load(row: u32, word: u32) -> u32 { + if settling() { + return settled[word_at(row, word)]; + } + return state[word_at(row, word)]; +} + +fn store(row: u32, word: u32, value: u32) { + if settling() { + settled[word_at(row, word)] = value; + } else { + state[word_at(row, word)] = value; + } +} + +// Word `word` of `row` as it was drawn when the transition began. +fn was(row: u32, word: u32) -> u32 { + if word < mark.stride { + return frozen[mark.frozen + row * mark.stride + word]; + } + return frozen[mark.frozen_extra + row * mark.extras + (word - mark.stride)]; +} + +// Whether `row` has nothing to ease from: it entered with this change. +fn entering(row: u32, flags: u32) -> bool { + return (was(row, flags) & ENTERING) != 0u; +} + +fn pointer_distance(row: u32) -> f32 { + let at = word_at(row, VERTEX_POSITION); + let hi = vec2f(bitcast(state[at]), bitcast(state[at + 1u])); + let lo = vec2f(bitcast(state[at + 2u]), bitcast(state[at + 3u])); + let z = bitcast(state[word_at(row, VERTEX_ELEVATION)]); + return distance(to_screen(project(hi, lo, z)), frame.pointer); +} + +fn number(x: u32) -> f32 { + return bitcast(x); +} + +fn word(x: f32) -> u32 { + return bitcast(x); +} + +fn truth(x: bool) -> u32 { + return word(f32(x)); +} + +fn unary(code: u32, a: f32) -> f32 { + switch code { + case OP_NEG: { return -a; } + case OP_NOT: { return f32(a <= 0.5); } + case OP_ABS: { return abs(a); } + case OP_SQRT: { return sqrt(a); } + case OP_SIN: { return sin(a); } + case OP_COS: { return cos(a); } + case OP_FLOOR: { return floor(a); } + case OP_LOG: { return log(a); } + default: { return exp(a); } + } +} + +fn binary(code: u32, a: f32, b: f32) -> f32 { + switch code { + case OP_ADD: { return a + b; } + case OP_SUB: { return a - b; } + case OP_MUL: { return a * b; } + case OP_DIV: { return a / b; } + case OP_MIN: { return min(a, b); } + case OP_MAX: { return max(a, b); } + case OP_MOD: { return a - b * floor(a / b); } + case OP_POW: { return pow(a, b); } + case OP_LT: { return f32(a < b); } + case OP_LE: { return f32(a <= b); } + case OP_GT: { return f32(a > b); } + case OP_GE: { return f32(a >= b); } + case OP_EQ: { return f32(a == b); } + case OP_NE: { return f32(a != b); } + case OP_AND: { return f32(a > 0.5 && b > 0.5); } + default: { return f32(a > 0.5 || b > 0.5); } + } +} + +fn fallback(x: u32, slot: u32) -> u32 { + if slot != NONE && missing_bits(x) { + return theme_word(slot); + } + return x; +} + +// A number eased from what `row` showed; a row that entered shows its own at once, and appears as +// its draw grows it in. +fn ease_number(row: u32, w: u32, now: u32, flags: u32) -> u32 { + if !easing() || missing_bits(now) || entering(row, flags) { + return now; + } + let start = was(row, w); + if missing_bits(start) { + return now; + } + return word(mix(number(start), number(now), mark.motion)); +} + +fn ease_color(row: u32, w: u32, now: u32, flags: u32) -> u32 { + if !easing() || entering(row, flags) { + return now; + } + return pack4x8unorm(mix(unpack4x8unorm(was(row, w)), unpack4x8unorm(now), mark.motion)); +} + +// A position's high word `w` (x or y) eased by its offset from what the row showed, so the +// destination keeps its precision; its low word, two after it, shows as evaluated. +fn ease_position(row: u32, w: u32, now: u32, flags: u32) -> u32 { + if !easing() || entering(row, flags) || (was(row, flags) & PLACED) == 0u { + return now; + } + let now_lo = number(settled[word_at(row, w + 2u)]); + let offset = (number(was(row, w)) - number(now)) + (number(was(row, w + 2u)) - now_lo); + return word(number(now) + offset * (1.0 - mark.motion)); +} + +// Sets or clears `bit` of the flags at word `w`. While easing, a row whose visibility flips stays +// drawn and fades. +fn store_flag(row: u32, w: u32, bit: u32, on: bool) { + let stored = load(row, w); + var flags = select(stored & ~bit, stored | bit, on); + if bit == VISIBLE { + flags &= ~(FADE_IN | FADE_OUT); + if easing() { + let before = entering(row, w) || (was(row, w) & VISIBLE) != 0u; + let fresh = entering(row, w); + if on && (fresh || !before) { + flags |= FADE_IN; + } else if !on && before { + flags |= VISIBLE | FADE_OUT; + } + } + } + store(row, w, flags & ~ENTERING); +} + +// A position, from data or in a diagram from its sheet, as high and low parts of x and y; a row +// without one is not placed. +fn position(row: u32, w: u32, x: vec2u, y: vec2u) { + let flags = w + VERTEX_FLAGS - VERTEX_POSITION; + if missing_bits(x.x) || missing_bits(y.x) { + store(row, flags, load(row, flags) & ~PLACED); + return; + } + store(row, w, x.x); + store(row, w + 1u, y.x); + store(row, w + 2u, x.y); + store(row, w + 3u, y.y); + store(row, flags, load(row, flags) | PLACED); +} + +fn run(row: u32, start: u32, end: u32) { + var stack: array; + var sp = 0u; + for (var pc = start; pc < end; pc++) { + let at = mark.code + pc * 4u; + let code = program[at]; + let a = program[at + 1u]; + let b = program[at + 2u]; + let c = program[at + 3u]; + switch code { + case OP_CONST: { stack[sp] = constant(a); sp++; } + case OP_MISSING: { stack[sp] = MISSING; sp++; } + case OP_FIELD: { stack[sp] = column_value(a, row).x; sp++; } + case OP_SELECTED: { stack[sp] = truth(is_selected(row)); sp++; } + case OP_HOVERED: { stack[sp] = truth(is_hovered(row)); sp++; } + case OP_POINTER: { stack[sp] = word(pointer_distance(row)); sp++; } + case OP_ELAPSED: { stack[sp] = word(frame.elapsed); sp++; } + case OP_ZOOM: { stack[sp] = word(frame.zoom); sp++; } + case OP_THEME: { stack[sp] = theme_word(a); sp++; } + case OP_NEG, OP_NOT, OP_ABS, OP_SQRT, OP_SIN, OP_COS, OP_FLOOR, OP_LOG, OP_EXP: { + stack[sp - 1u] = word(unary(code, number(stack[sp - 1u]))); + } + case OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MIN, OP_MAX, OP_MOD, OP_POW, OP_LT, OP_LE, OP_GT, OP_GE, + OP_EQ, OP_NE, OP_AND, OP_OR: { + sp--; + stack[sp - 1u] = word(binary(code, number(stack[sp - 1u]), number(stack[sp]))); + } + case OP_SELECT: { + sp -= 2u; + stack[sp - 1u] = select(stack[sp + 1u], stack[sp], number(stack[sp - 1u]) > 0.5); + } + case OP_SCALE: { + let range = vec2f(constant_float(b), constant_float(b + 1u)); + stack[sp - 1u] = word(scale(number(stack[sp - 1u]), domain(a), range)); + } + case OP_COLORMAP: { + stack[sp - 1u] = colormap(a & 0xffffu, a >> 16u, number(stack[sp - 1u]), domain(b)); + } + case OP_STORE: { + sp--; + store(row, a, fallback(stack[sp], b)); + } + case OP_STORE_COLOR: { + sp--; + store(row, a, select(stack[sp], theme_word(b), stack[sp] == MISSING_COLOR)); + } + case OP_STORE_CODE: { + sp--; + store(row, a, stack[sp]); + } + case OP_STORE_FLAG: { + sp--; + store_flag(row, a, b, number(stack[sp]) > 0.5); + } + case OP_STORE_POSITION: { + sp -= 2u; + position(row, a, vec2u(stack[sp], 0u), vec2u(stack[sp + 1u], 0u)); + } + case OP_POSITION: { + position(row, a, column_value(b, row), column_value(c, row)); + } + case OP_STORE_END: { + // Without a column, the end is the row itself, as a pole's. + let end_row = select(bits_value(b, row), row, b == NONE); + let first = program[mark.ends + c]; + store(row, a, select(first + end_row, NONE, end_row == NONE || first == NONE)); + } + case OP_REDUCE: { + sp--; + let x = number(stack[sp]); + if !missing(x) { + let d = 2u * (mark.domains + a); + atomicMax(&domains[d], ~ordered(x)); + atomicMax(&domains[d + 1u], ordered(x)); + } + } + default: {} + } + } +} + +// A row that left fades out with its mark's transition; its frozen state is what it showed, but for +// its comets, which travel on. +fn fade_exit(row: u32, flags: u32) { + let travel = travel_words().x; + for (var w = 0u; w < mark.stride; w++) { + if w != travel { + state[word_at(row, w)] = was(row, w); + } + } + state[word_at(row, flags)] = (was(row, flags) & ~FADE_IN) | FADE_OUT; +} + +@compute @workgroup_size(256) +fn evaluate(@builtin(global_invocation_id) id: vec3u) { + let row = row_of(id); + // The flags word is the last kind word of every mark's rows. + let flags = mark.stride - 1u; + if row >= mark.rows { + // Rows that left fade out; while the mark eases toward its settled state, `ease` writes them. + if row < mark.rows + mark.exits && easing() && !settling() { + fade_exit(row, flags); + } + return; + } + for (var k = 0u; k < mark.channels; k++) { + if (mark.mask & (1u << k)) != 0u { + let range = mark.ranges + 2u * k; + run(row, program[range], program[range + 1u]); + } + } + if mark.kind == MARK_VERTICES { + let units = select(0u, HALF_UNITS, (mark.units & (1u << VERTEX_HALF)) != 0u); + let own = select(0u, OWN_HEIGHT, (mark.flags & SIZED) != 0u); + store(row, flags, (load(row, flags) & ~(HALF_UNITS | OWN_HEIGHT)) | units | own); + store(row, VERTEX_RANGE, pack_range(vec2f(mark.size_min, mark.size_max))); + } +} + +// Each frame a mark eases toward its settled state: every word a channel stores shows the frozen +// state moved toward the settled one by the mark's progress, as the program says each eases; rows that left +// fade out. No channel runs. +@compute @workgroup_size(256) +fn ease(@builtin(global_invocation_id) id: vec3u) { + let row = item(id); + let flags = mark.stride - 1u; + if row >= mark.rows { + if row < mark.rows + mark.exits { + fade_exit(row, flags); + } + return; + } + for (var w = 0u; w < mark.stride + mark.extras; w++) { + let blend = program[mark.blends + w]; + if blend == BLEND_KEEP { + continue; + } + let now = settled[word_at(row, w)]; + var shown = now; + switch blend { + case BLEND_NUMBER: { shown = ease_number(row, w, now, flags); } + case BLEND_COLOR: { shown = ease_color(row, w, now, flags); } + case BLEND_POSITION: { shown = ease_position(row, w, now, flags); } + default: {} + } + state[word_at(row, w)] = shown; + } +} + +// Comets travel on by each stroke row's flow over the frame's step, so a flow that changes carries +// on from where its comets are. Wrapped at their spacing, travel keeps its precision however long +// they run. +@compute @workgroup_size(256) +fn travel(@builtin(global_invocation_id) id: vec3u) { + let row = item(id); + let words = travel_words(); + if row >= mark.rows + mark.exits || words.x == NONE { + return; + } + let at = word_at(row, words.x); + let flow = number(state[word_at(row, words.y)]); + let spacing = max(frame.flow_spacing, 1e-6); + var moved = number(state[at]) + select(flow, 0.0, missing(flow)) * frame.flow_step; + moved -= spacing * floor(moved / spacing); + // Words a row never held read as no travel. + state[at] = word(select(0.0, moved, moved >= 0.0 && moved <= spacing)); +} + +// Where a transition moved rows, their comets carry on from where they were: each row takes the +// travel its frozen state holds. +@compute @workgroup_size(256) +fn carry(@builtin(global_invocation_id) id: vec3u) { + let row = item(id); + let travel = travel_words().x; + if row >= mark.rows + mark.exits || travel == NONE || !easing() { + return; + } + state[word_at(row, travel)] = was(row, travel); +} + +@compute @workgroup_size(256) +fn reduce(@builtin(global_invocation_id) id: vec3u) { + let row = item(id); + if row >= mark.rows { + return; + } + for (var k = mark.channels; k < mark.channels + mark.reductions; k++) { + let range = mark.ranges + 2u * k; + run(row, program[range], program[range + 1u]); + } +} diff --git a/crates/latkit/shaders/compute/fields.wesl b/crates/latkit/shaders/compute/fields.wesl new file mode 100644 index 00000000..2cbb8df8 --- /dev/null +++ b/crates/latkit/shaders/compute/fields.wesl @@ -0,0 +1,124 @@ +// Distance fields of text: the coverage a host set for a run, turned into each texel's signed distance +// to the text's edge, inside positive, as a byte of `0.5 + distance / (2 TEXT_SPREAD)`, over the run +// widened by `TEXT_SPREAD` texels on every side. Partial coverage places the edge within its texel, so +// antialiasing becomes subtexel distance. +// +// A texel's squared distance to the text is the least, over the field's texels, of each one's own (none +// inside the text, a partial texel's subtexel distance squared, far outside it) plus the squared +// distance to it; likewise to what lies outside the text. The least splits into one down each column, +// then one along each row, and only texels within the spread bring a texel within it, so each looks +// that far and no farther: exact wherever the field is not clamped. After the columns, one of a +// texel's two distances is its own, none, so one signed word holds both: to the outside above zero, to +// the text below. + +import package::lib::types::{ + TEXT_SPREAD, FIELD_COVERAGE, FIELD_WIDTH, FIELD_HEIGHT, FIELD_COLUMNS, FIELD_AT, FIELD_ROW, FIELD_WORDS, +}; + +// The runs, `FIELD_WORDS` each, then their coverage, four bytes a word, their columns' least +// distances, and their fields, four texels a word. +@group(2) @binding(0) var fields: array; + +// Texels the field reaches past the text, and the column minima a word of four texels reads. +const SPREAD: i32 = i32(TEXT_SPREAD); +const NEAR: i32 = 4 + 2 * SPREAD; +// Farther than any texel within the spread. +const FAR: f32 = 1e20; + +struct Run { + coverage: u32, + // The coverage's width and height. + size: vec2u, + columns: u32, + at: u32, + // Words between the starts of the field's rows. + row: u32, +} + +fn run(i: u32) -> Run { + let w = i * FIELD_WORDS; + return Run( + fields[w + FIELD_COVERAGE], + vec2u(fields[w + FIELD_WIDTH], fields[w + FIELD_HEIGHT]), + fields[w + FIELD_COLUMNS], + fields[w + FIELD_AT], + fields[w + FIELD_ROW], + ); +} + +// Texels across and down its field: its coverage's, and the spread on every side. +fn field_size(r: Run) -> vec2u { + return r.size + vec2u(2u * u32(SPREAD)); +} + +// Field texel `p`'s own squared distances to the text and to what lies outside it. +fn own(r: Run, p: vec2i) -> vec2f { + let q = p - vec2i(SPREAD); + if any(q < vec2i(0)) || any(q >= vec2i(r.size)) { + return vec2f(FAR, 0.0); + } + let i = u32(q.y) * r.size.x + u32(q.x); + let byte = (fields[r.coverage + i / 4u] >> (8u * (i % 4u))) & 255u; + if byte == 255u { + return vec2f(0.0, FAR); + } + if byte == 0u { + return vec2f(FAR, 0.0); + } + // The edge lies where coverage is half. + let d = 0.5 - f32(byte) / 255.0; + return select(vec2f(0.0, d * d), vec2f(d * d, 0.0), d > 0.0); +} + +// Down each column: the least of each texel's own within the spread above and below. +@compute @workgroup_size(16, 16) +fn columns(@builtin(global_invocation_id) id: vec3u) { + let r = run(id.z); + let size = field_size(r); + if any(id.xy >= size) { + return; + } + var least = vec2f(FAR); + for (var dy = -SPREAD; dy <= SPREAD; dy++) { + let y = i32(id.y) + dy; + if y >= 0 && y < i32(size.y) { + least = min(least, own(r, vec2i(i32(id.x), y)) + f32(dy * dy)); + } + } + fields[r.columns + id.y * size.x + id.x] = bitcast(least.y - least.x); +} + +// Along each row, four texels a word: the least of the columns' within the spread to either side, +// then each texel's byte. +@compute @workgroup_size(16, 16) +fn rows(@builtin(global_invocation_id) id: vec3u) { + let r = run(id.z); + let size = field_size(r); + if id.x * 4u >= size.x || id.y >= size.y { + return; + } + // Past the field's edge lies nothing. + var near: array; + let first = i32(id.x * 4u) - SPREAD; + for (var k = 0; k < NEAR; k++) { + let x = first + k; + var d = vec2f(FAR); + if x >= 0 && x < i32(size.x) { + let s = bitcast(fields[r.columns + id.y * size.x + u32(x)]); + d = vec2f(max(-s, 0.0), max(s, 0.0)); + } + near[k] = d; + } + var word = 0u; + for (var t = 0; t < 4; t++) { + var least = vec2f(FAR); + for (var k = 0; k <= 2 * SPREAD; k++) { + let dx = f32(k - SPREAD); + least = min(least, near[t + k] + dx * dx); + } + let d = sqrt(least.y) - sqrt(least.x); + let byte = u32(floor(clamp(0.5 + d / (2.0 * TEXT_SPREAD), 0.0, 1.0) * 255.0 + 0.5)); + word |= byte << (8u * u32(t)); + } + fields[r.at + id.y * r.row + id.x] = word; +} diff --git a/crates/latkit/shaders/compute/freeze.wesl b/crates/latkit/shaders/compute/freeze.wesl new file mode 100644 index 00000000..a5438e0c --- /dev/null +++ b/crates/latkit/shaders/compute/freeze.wesl @@ -0,0 +1,45 @@ +// Freezing: what each row of a mark showed when its transition began, gathered into the frozen +// buffer at the row's new place. The remap words list where each new row was (NONE for a row that +// entered), then the rows that left, which fade out past `mark.rows`. Slot words of a mark whose +// ends point at vertices follow them to their new slots. + +import package::lib::types::{NONE, ENTERING, item}; +import package::lib::bind::{mark, state}; + +@group(2) @binding(1) var frozen: array; +// At `mark.remap`: the old kind and extra offsets, a mask of slot words, where the slot table +// starts or NONE, then a source row per new row and exit. +@group(2) @binding(12) var remap: array; + +@compute @workgroup_size(256) +fn gather(@builtin(global_invocation_id) id: vec3u) { + let i = item(id); + if i >= mark.rows + mark.exits { + return; + } + let old_state = remap[mark.remap]; + let old_extra = remap[mark.remap + 1u]; + let slots = remap[mark.remap + 2u]; + let table = remap[mark.remap + 3u]; + let source = remap[mark.remap + 4u + i]; + let flags = mark.stride - 1u; + for (var w = 0u; w < mark.stride; w++) { + var word = 0u; + if source == NONE { + word = select(0u, ENTERING, w == flags); + } else { + word = state[old_state + source * mark.stride + w]; + if ((slots >> w) & 1u) != 0u && word != NONE && table != NONE { + word = remap[table + word]; + } + } + frozen[mark.frozen + i * mark.stride + w] = word; + } + for (var w = 0u; w < mark.extras; w++) { + var word = 0u; + if source != NONE { + word = state[old_extra + source * mark.extras + w]; + } + frozen[mark.frozen_extra + i * mark.extras + w] = word; + } +} diff --git a/crates/latkit/shaders/compute/labels.wesl b/crates/latkit/shaders/compute/labels.wesl new file mode 100644 index 00000000..cb701728 --- /dev/null +++ b/crates/latkit/shaders/compute/labels.wesl @@ -0,0 +1,329 @@ +// Label placement. `candidates` measures each labeled row's label where its anchor puts it, by the +// size of its text, or an estimate of it while the text is not set, and keys it by its priority, +// then whether it showed before, then its id: a label that arrives later still displaces lesser +// ones, and among equals those shown keep their place. Then rounds of `claim` (each label wanting +// room takes the least key into every cell it covers, or drops if one is held), `decide` (a label +// holding all its cells is placed), and `occupy` (placed labels hold their cells) settle, with cells +// not held cleared between rounds. That places labels as greedily by key as a sequential pass would. +// `ask` then asks for the texts of placed labels the atlas lacks and notes those it holds, so it +// keeps them: texts are set only for labels that show, however many rows are in view. `fade` eases +// each label in or out. Placement only decides which labels show; draws place them from their +// anchors every frame. A diagram's labels scale with its sheet, so they need no placement: only +// `candidates` runs there, to ask for the texts of labels in view. +// +// A mark that shows at most `label_max` labels keeps, of those wanting room, the ones of least key, +// before any claims: keys are unique, so a radix select over three digits of 11, 11, and 10 bits finds +// the greatest key kept exactly, each digit a pass over the candidates and one over its buckets. + +import package::lib::types::{ + NONE, VISIBLE, LABEL_CODE, LABEL_PRIORITY, CANDIDATE_WORDS, CANDIDATE_BOX, CANDIDATE_KEY, CANDIDATE_STATE, + CANDIDATE_ALPHA, WANTS, PLACED_LABEL, DROPPED, STICKY, ESTIMATED, TEXT_ESTIMATE, OCCUPIED, CELL, WANTED, + SPACE_DIAGRAM, item, +}; +import package::lib::bind::{frame, eye, mark, state}; +import package::lib::state::extra_at; +import package::lib::read::missing_bits; +import package::lib::label::{anchor, length_px, legibility, text_at, fits, in_view}; + +@group(2) @binding(13) var labels: array>; + +fn word(at: u32) -> u32 { + return atomicLoad(&labels[at]); +} + +fn put(at: u32, value: u32) { + atomicStore(&labels[at], value); +} + +fn candidate(row: u32) -> u32 { + return mark.candidates + row * CANDIDATE_WORDS; +} + +// Asks the host to set the text of `code`. +fn want(code: u32) { + let asked = atomicAdd(&labels[mark.wanted], 1u); + if asked < WANTED { + put(mark.wanted + 1u + asked, code); + } +} + +// Notes that a label shows the text of `code`, so the atlas keeps it. +fn seen(code: u32) { + atomicOr(&labels[mark.seen + code / 32u], 1u << (code % 32u)); +} + +@compute @workgroup_size(256) +fn candidates(@builtin(global_invocation_id) id: vec3u) { + let row = item(id); + if row >= mark.rows { + return; + } + let at = candidate(row); + let before = word(at + CANDIDATE_STATE); + let sticky = (before & PLACED_LABEL) != 0u; + let code_bits = state[extra_at(row, mark.label + LABEL_CODE)]; + var next = select(0u, STICKY, sticky); + if missing_bits(code_bits) || (state[mark.state + row * mark.stride + mark.stride - 1u] & VISIBLE) == 0u { + put(at + CANDIDATE_STATE, next); + return; + } + let code = u32(bitcast(code_bits)); + let uv0 = word(mark.runs + 2u * code); + let uv1 = word(mark.runs + 2u * code + 1u); + let a = anchor(row); + let size = length_px(mark.label_size); + let diagram = frame.space == SPACE_DIAGRAM; + let estimated = (uv0 & TEXT_ESTIMATE) != 0u; + if (uv0 == 0u && uv1 == 0u) || (estimated && diagram) { + // The atlas lacks this text, and the label cannot wait for placement to ask for it: ask now, + // if it could show, legible and near the view. + let near = 0.25 * eye.size; + if a.shown && legibility(size) > 0.0 && in_view(a.at - near, a.at + near) { + want(code); + } + put(at + CANDIDATE_STATE, next); + return; + } + if estimated { + next |= ESTIMATED; + } + let t = text_at(uv0 & ~TEXT_ESTIMATE, uv1, size, a.at, a.align); + if a.shown && in_view(t.lo, t.hi) { + // A diagram shows every label in view that fits; elsewhere `ask` notes those placed. + if diagram { + seen(code); + } + if fits(t.hi - t.lo, a.room) { + next |= WANTS; + } + } + put(at + CANDIDATE_BOX, bitcast(t.lo.x)); + put(at + CANDIDATE_BOX + 1u, bitcast(t.lo.y)); + put(at + CANDIDATE_BOX + 2u, bitcast(t.hi.x)); + put(at + CANDIDATE_BOX + 3u, bitcast(t.hi.y)); + let level = u32(clamp(bitcast(state[extra_at(row, mark.label + LABEL_PRIORITY)]), 0.0, 255.0)); + let id_bits = (mark.label_id + row + 1u) & 0x7fffffu; + put(at + CANDIDATE_KEY, ((255u - level) << 24u) | select(0x800000u, 0u, sticky) | id_bits); + put(at + CANDIDATE_STATE, next); +} + +// Buckets of a digit of the select capping labels. +const SELECT_BUCKETS: u32 = 2048u; + +// Word `k` of the select's state, past its buckets: the key's digits found, how many of the least +// keys are still to keep, and the digit next counted (4 once fewer want room than the cap). +fn select_word(k: u32) -> u32 { + return mark.label_select + SELECT_BUCKETS + k; +} + +// Where digit `d` of a key starts, and how many bits it has. +fn digit(d: u32) -> vec2u { + switch d { + case 0u: { return vec2u(21u, 11u); } + case 1u: { return vec2u(10u, 11u); } + default: { return vec2u(0u, 10u); } + } +} + +fn wanting(row: u32) -> bool { + return (word(candidate(row) + CANDIDATE_STATE) & WANTS) != 0u; +} + +@compute @workgroup_size(256) +fn select_start(@builtin(global_invocation_id) id: vec3u) { + let i = item(id); + if mark.label_max == NONE { + return; + } + if i < SELECT_BUCKETS { + put(mark.label_select + i, 0u); + } + if i == 0u { + put(select_word(0u), 0u); + put(select_word(1u), mark.label_max); + put(select_word(2u), 0u); + } +} + +@compute @workgroup_size(256) +fn select_count(@builtin(global_invocation_id) id: vec3u) { + let row = item(id); + let d = word(select_word(2u)); + if row >= mark.rows || mark.label_max == NONE || d >= 3u || !wanting(row) { + return; + } + let key = word(candidate(row) + CANDIDATE_KEY); + let at = digit(d); + // Only keys whose higher digits are those found count. + let above = at.x + at.y; + if above < 32u && (key >> above) != word(select_word(0u)) { + return; + } + atomicAdd(&labels[mark.label_select + ((key >> at.x) & (SELECT_BUCKETS - 1u))], 1u); +} + +// The bucket holding the least key still to keep, clearing the buckets for the next digit. +@compute @workgroup_size(1) +fn select_find() { + let d = word(select_word(2u)); + // A cap of none keeps no label: the cut drops them all. + if mark.label_max == NONE || mark.label_max == 0u || d >= 3u { + return; + } + var left = word(select_word(1u)); + var found = SELECT_BUCKETS; + for (var b = 0u; b < SELECT_BUCKETS; b++) { + let n = word(mark.label_select + b); + put(mark.label_select + b, 0u); + if found == SELECT_BUCKETS { + if n >= left { + found = b; + } else { + left -= n; + } + } + } + if found == SELECT_BUCKETS { + // Fewer want room than the cap: each keeps its chance. + put(select_word(2u), 4u); + return; + } + put(select_word(0u), (word(select_word(0u)) << digit(d).y) | found); + put(select_word(1u), left); + put(select_word(2u), d + 1u); +} + +@compute @workgroup_size(256) +fn select_cut(@builtin(global_invocation_id) id: vec3u) { + let row = item(id); + if row >= mark.rows || mark.label_max == NONE || !wanting(row) || word(select_word(2u)) == 4u { + return; + } + let at = candidate(row) + CANDIDATE_STATE; + if mark.label_max == 0u || word(candidate(row) + CANDIDATE_KEY) > word(select_word(0u)) { + put(at, word(at) & ~WANTS); + } +} + +// The cells row `row`'s label covers: least and greatest column and row. +fn cells_of(row: u32) -> vec4u { + let at = candidate(row); + let lo = vec2f(bitcast(word(at + CANDIDATE_BOX)), bitcast(word(at + CANDIDATE_BOX + 1u))); + let hi = vec2f(bitcast(word(at + CANDIDATE_BOX + 2u)), bitcast(word(at + CANDIDATE_BOX + 3u))); + let top = vec2f(f32(frame.cell_columns), f32(frame.cell_rows)) - 1.0; + let a = vec2u(clamp(floor(lo / CELL), vec2f(0.0), top)); + let b = vec2u(clamp(floor(hi / CELL), vec2f(0.0), top)); + return vec4u(a, b); +} + +fn cell(x: u32, y: u32) -> u32 { + return frame.cells + y * frame.cell_columns + x; +} + +// Whether row `row`'s label still wants room this round. +fn undecided(row: u32) -> bool { + let s = word(candidate(row) + CANDIDATE_STATE); + return (s & WANTS) != 0u && (s & (PLACED_LABEL | DROPPED)) == 0u; +} + +@compute @workgroup_size(256) +fn clear_cells(@builtin(global_invocation_id) id: vec3u) { + let i = item(id); + if i < frame.cell_columns * frame.cell_rows { + put(frame.cells + i, NONE); + } +} + +@compute @workgroup_size(256) +fn reset_cells(@builtin(global_invocation_id) id: vec3u) { + let i = item(id); + if i < frame.cell_columns * frame.cell_rows && word(frame.cells + i) != OCCUPIED { + put(frame.cells + i, NONE); + } +} + +@compute @workgroup_size(256) +fn claim(@builtin(global_invocation_id) id: vec3u) { + let row = item(id); + if row >= mark.rows || !undecided(row) { + return; + } + let at = candidate(row); + let key = word(at + CANDIDATE_KEY); + let c = cells_of(row); + for (var y = c.y; y <= c.w; y++) { + for (var x = c.x; x <= c.z; x++) { + if word(cell(x, y)) == OCCUPIED { + put(at + CANDIDATE_STATE, word(at + CANDIDATE_STATE) | DROPPED); + return; + } + atomicMin(&labels[cell(x, y)], key); + } + } +} + +@compute @workgroup_size(256) +fn decide(@builtin(global_invocation_id) id: vec3u) { + let row = item(id); + if row >= mark.rows || !undecided(row) { + return; + } + let at = candidate(row); + let key = word(at + CANDIDATE_KEY); + let c = cells_of(row); + for (var y = c.y; y <= c.w; y++) { + for (var x = c.x; x <= c.z; x++) { + if word(cell(x, y)) != key { + return; + } + } + } + put(at + CANDIDATE_STATE, word(at + CANDIDATE_STATE) | PLACED_LABEL); +} + +@compute @workgroup_size(256) +fn occupy(@builtin(global_invocation_id) id: vec3u) { + let row = item(id); + if row >= mark.rows || (word(candidate(row) + CANDIDATE_STATE) & PLACED_LABEL) == 0u { + return; + } + let c = cells_of(row); + for (var y = c.y; y <= c.w; y++) { + for (var x = c.x; x <= c.z; x++) { + put(cell(x, y), OCCUPIED); + } + } +} + +@compute @workgroup_size(256) +fn ask(@builtin(global_invocation_id) id: vec3u) { + let row = item(id); + if row >= mark.rows { + return; + } + let s = word(candidate(row) + CANDIDATE_STATE); + if (s & PLACED_LABEL) == 0u { + return; + } + let code = u32(bitcast(state[extra_at(row, mark.label + LABEL_CODE)])); + if (s & ESTIMATED) != 0u { + want(code); + } else { + seen(code); + } +} + +@compute @workgroup_size(256) +fn fade(@builtin(global_invocation_id) id: vec3u) { + let row = item(id); + if row >= mark.rows { + return; + } + let at = candidate(row); + // A label placed by an estimate waits for its text to fade in. + let s = word(at + CANDIDATE_STATE); + let placed = (s & PLACED_LABEL) != 0u && (s & ESTIMATED) == 0u; + let alpha = bitcast(word(at + CANDIDATE_ALPHA)); + let next = clamp(select(alpha - frame.label_fade, alpha + frame.label_fade, placed), 0.0, 1.0); + put(at + CANDIDATE_ALPHA, bitcast(select(next, 0.0, missing_bits(bitcast(next))))); +} diff --git a/crates/latkit/shaders/compute/lists.wesl b/crates/latkit/shaders/compute/lists.wesl new file mode 100644 index 00000000..92f857f7 --- /dev/null +++ b/crates/latkit/shaders/compute/lists.wesl @@ -0,0 +1,128 @@ +// The scan of a list: each block of 256 counts scans in its workgroup and leaves its total, one +// workgroup scans the totals, and every count adds its block's offset. Counts become where each +// item's entries start, the total follows them, and the header's indirect arguments take the +// entries the list keeps. Each count is held to its share of a u32, so the total never wraps. +// Reduce-then-scan needs no forward progress between workgroups, so it is safe on every device. + +import package::lib::bind::mark; +import package::lib::types::{ + LIST_ITEMS, LIST_COUNTS, LIST_SUMS, LIST_ENTRIES, LIST_DRAW, LIST_DISPATCH, LIST_KEPT, PATH_TRACE, TRIANGLES, + BLOCK_ROWS, item, +}; +import package::lib::lists::{lists, list_start}; +import package::lib::path::{row_segments, path_point, path_length, PATH}; + +var tile: array; +var shared_items: u32; + +// The list this dispatch scans: the mark's. +fn header() -> u32 { + return mark.list; +} + +// Inclusive scan of `tile` across the workgroup. +fn scan_tile(local: u32) { + for (var d = 1u; d < 256u; d *= 2u) { + let before = select(0u, tile[max(local, d) - d], local >= d); + workgroupBarrier(); + tile[local] += before; + workgroupBarrier(); + } +} + +@compute @workgroup_size(256) +fn scan_blocks(@builtin(local_invocation_id) l: vec3u, @builtin(workgroup_id) g: vec3u) { + let h = header(); + let n = lists[h + LIST_ITEMS]; + let counts = lists[h + LIST_COUNTS]; + // Past one dimension's workgroups, blocks of BLOCK_ROWS items step along the second. + let block = g.y * (BLOCK_ROWS / 256u) + g.x; + let i = block * 256u + l.x; + // Whatever the counts, the starts climb, so every item's writes end. + let share = 0xffffffffu / max(n, 1u); + let own = select(0u, min(lists[counts + min(i, max(n, 1u) - 1u)], share), i < n); + tile[l.x] = own; + workgroupBarrier(); + scan_tile(l.x); + if i < n { + lists[counts + i] = tile[l.x] - own; + } + if l.x == 255u { + lists[lists[h + LIST_SUMS] + block] = tile[255]; + } +} + +@compute @workgroup_size(256) +fn scan_sums(@builtin(local_invocation_id) l: vec3u) { + let h = header(); + if l.x == 0u { + shared_items = lists[h + LIST_ITEMS]; + } + let n = workgroupUniformLoad(&shared_items); + let sums = lists[h + LIST_SUMS]; + let blocks = (n + 255u) / 256u; + var carry = 0u; + for (var start = 0u; start < blocks; start += 256u) { + let i = start + l.x; + let own = select(0u, lists[sums + min(i, max(blocks, 1u) - 1u)], i < blocks); + tile[l.x] = own; + workgroupBarrier(); + scan_tile(l.x); + if i < blocks { + lists[sums + i] = tile[l.x] - own + carry; + } + carry += tile[255]; + workgroupBarrier(); + } + if l.x == 0u { + lists[lists[h + LIST_COUNTS] + n] = carry; + let kept = min(carry, lists[h + LIST_KEPT]); + lists[h + LIST_DRAW + 1u] = kept; + lists[h + LIST_DISPATCH] = (kept + 255u) / 256u; + } +} + +@compute @workgroup_size(256) +fn add_sums(@builtin(global_invocation_id) id: vec3u) { + let i = item(id); + let h = header(); + if i < lists[h + LIST_ITEMS] { + let counts = lists[h + LIST_COUNTS]; + lists[counts + i] += lists[lists[h + LIST_SUMS] + i / 256u]; + } +} + +// A mark's segments, numbered by its list: each row counts the segments of its path, then writes +// its row at each of their places, with how far along its path each starts, so a segment's instance +// finds its row, its index in it, and where dashes and comets stand at its start. +@compute @workgroup_size(256) +fn count_segments(@builtin(global_invocation_id) id: vec3u) { + let i = item(id); + if i < lists[mark.list + LIST_ITEMS] { + lists[lists[mark.list + LIST_COUNTS] + i] = row_segments(i); + } +} + +@compute @workgroup_size(256) +fn write_segments(@builtin(global_invocation_id) id: vec3u) { + let i = item(id); + if i >= lists[mark.list + LIST_ITEMS] { + return; + } + let at = list_start(mark.list, i); + let end = list_start(mark.list, i + 1u); + let entries = lists[mark.list + LIST_ENTRIES]; + // An area's triangles have no distance along. + let measured = mark.primitive != TRIANGLES && PATH != PATH_TRACE; + var along = 0.0; + var last = path_point(i, 0u); + for (var k = at; k < end; k++) { + lists[entries + 2u * k] = i; + lists[entries + 2u * k + 1u] = bitcast(along); + if measured { + let next = path_point(i, k - at + 1u); + along += select(0.0, path_length(last, next), last.shown && next.shown); + last = next; + } + } +} diff --git a/crates/latkit/shaders/compute/normals.wesl b/crates/latkit/shaders/compute/normals.wesl new file mode 100644 index 00000000..3754e758 --- /dev/null +++ b/crates/latkit/shaders/compute/normals.wesl @@ -0,0 +1,34 @@ +// Vertex normals for faces: each face adds its unit normal to its three corners in fixed point, so the +// sums are exact in any order. + +import package::lib::types::{NONE, item}; +import package::lib::bind::mark; +import package::lib::triangles::triangle_corner; + +@group(2) @binding(3) var normals: array>; + +@compute @workgroup_size(256) +fn accumulate(@builtin(global_invocation_id) id: vec3u) { + let i = item(id); + if i >= mark.rows { + return; + } + let a = triangle_corner(i, 0u); + let b = triangle_corner(i, 1u); + let c = triangle_corner(i, 2u); + if !(a.shown && b.shown && c.shown) || a.slot == NONE { + return; + } + let n = cross(b.world - a.world, c.world - a.world); + let length2 = dot(n, n); + if !(length2 > 1e-30) { + return; + } + let q = vec3i(round(n * inverseSqrt(length2) * 65536.0)); + for (var k = 0u; k < 3u; k++) { + let at = select(select(c.slot, b.slot, k == 1u), a.slot, k == 0u) * 3u; + atomicAdd(&normals[at], q.x); + atomicAdd(&normals[at + 1u], q.y); + atomicAdd(&normals[at + 2u], q.z); + } +} diff --git a/crates/latkit/shaders/compute/probe.wesl b/crates/latkit/shaders/compute/probe.wesl new file mode 100644 index 00000000..b9395935 --- /dev/null +++ b/crates/latkit/shaders/compute/probe.wesl @@ -0,0 +1,387 @@ +// Probes and queries: what a frame drew, asked about through the same geometry the draws use. One +// program, made for one primitive's geometry, answers every question a step at a time, the step a +// dispatch's uniform names; each step that reads instances puts each on screen once (`seen`) and asks +// of it what the step needs. +// +// The hover takes three steps over every mark it reaches: `nearest` keeps the least key over every +// instance within reach of the probe (the distance in sixty-fourths of a pixel, then the mark drawn +// last), `topmost` keeps the last instance of that mark at that key, and `describe` writes where that +// hit lies. Rows behind what the frame drew are not reached. `under` writes the nearest depth drawn +// around the probe, which gestures turn and zoom about. +// +// Queries write past the probe's words, each mark from the word its `query` names: `hits` appends every +// instance within reach of the query's point while the mark has room; `boxed` sets a bit for every row +// with an instance in the query's box, hidden or not. `locate` writes where one row lies on screen. + +import package::lib::types::{ + NONE, FADE_OUT, POINTS, STROKES, TRIANGLES, MARK_EDGES, PATH_GEOMETRY, PROBE_KEY, PROBE_INSTANCE, PROBE_DEPTH, + PROBE_X, PROBE_Y, PROBE_UNDER, PROBE_ROW, PROBE_SEGMENT, PROBE_LOCATE_X, PROBE_LOCATE_Y, PROBE_LOCATED, + STEP_NEAREST, STEP_TOPMOST, STEP_DESCRIBE, STEP_HITS, STEP_BOXED, STEP_LOCATE, STEP_UNDER, HIT_WORDS, item, +}; +import package::lib::bind::{frame, eye, mark, state}; +import package::lib::state::row_at; +import package::lib::project::{to_screen, clip_of}; +import package::lib::points::{point, port_at}; +import package::lib::path::{PATH, Segment, segment, segment_screen, stroke_style, stroke_instances, path_count}; +import package::lib::triangles::{triangle_corner, triangle_row, triangle_instances, area_anchor}; +import package::lib::marker::outline_distance; + +// The primitive this pipeline probes: each pipeline is made for one, so it holds only that one's +// geometry and compiles quickly. +override PROBED: u32 = 0u; + +// Which step a dispatch takes. +struct Step { + step: u32, +} + +@group(2) @binding(5) var probe: array>; +@if(multisampled) +@group(2) @binding(6) var depth: texture_depth_multisampled_2d; +@else +@group(2) @binding(6) var depth: texture_depth_2d; +@group(2) @binding(17) var step: Step; + +struct Reach { + distance: f32, + depth: f32, + point: vec2f, + row: u32, + segment: u32, +} + +fn unreached() -> Reach { + return Reach(1e30, 0.0, vec2f(0.0), NONE, 0u); +} + +// An instance as the frame drew it, on screen, depths as z: a point's center and, for a port, the +// port's center as `b`; a segment's ends; a triangle's corners, with whether each is shown, ahead of +// the eye, and in front of it. `part` is a port's number from 1, or a segment's index along its path. +struct Seen { + row: u32, + part: u32, + // The row is the mark's and not fading out. + kept: bool, + // A point is shown; a stroke's style is shown and its segment on screen. + shown: bool, + a: vec3f, + b: vec3f, + c: vec3f, + corners: vec3, + ahead: vec3, + front: vec3, + // A point's half size, a port's radius as x, a stroke's width as x. + half: vec2f, +} + +// A clip position on screen, with its depth as z. +fn screen(clip: vec4f) -> vec3f { + return vec3f(to_screen(clip), clip.z / clip.w); +} + +// The nearest point of segment `a`–`b` to `p`, depth interpolated. +fn nearest_on(p: vec2f, a: vec3f, b: vec3f) -> vec3f { + let ab = b.xy - a.xy; + let t = clamp(dot(p - a.xy, ab) / max(dot(ab, ab), 1e-9), 0.0, 1.0); + return mix(a, b, t); +} + +// Whether a row is fading out: it no longer answers the pointer. +fn leaving(row: u32) -> bool { + return (state[row_at(row) + mark.stride - 1u] & FADE_OUT) != 0u; +} + +// A point's marker, or past the rows one of their ports. +fn seen_point(instance: u32) -> Seen { + var s: Seen; + let port = select(0u, instance - mark.rows, instance >= mark.rows); + let row = select(instance, port / max(mark.ports, 1u), instance >= mark.rows); + let pt = point(row); + s.row = row; + s.kept = row < mark.rows && !leaving(row); + s.shown = pt.shown; + s.a = screen(pt.clip); + s.front = vec3(pt.clip.w > 0.0); + s.half = max(pt.half, vec2f(0.5)); + if instance >= mark.rows { + let k = port % max(mark.ports, 1u); + let at = port_at(pt, k); + s.part = k + 1u; + s.b = vec3f(at.center, s.a.z); + s.half = vec2f(at.half, 0.0); + } + return s; +} + +// A segment of a stroke: the instance's, or, locating, the middle one of row `instance`'s path. +fn seen_segment(instance: u32, locating: bool) -> Seen { + var s: Seen; + var g = Segment(instance, 0u, 0.0); + if locating { + g.index = path_count(instance) / 2u; + } else { + g = segment(instance); + } + s.row = g.row; + s.part = g.index; + s.kept = g.row < mark.rows && !leaving(g.row); + if !s.kept && !locating { + return s; + } + let style = stroke_style(g.row); + let on = segment_screen(g); + s.shown = style.shown && on.shown; + s.front = vec3(on.shown); + s.a = vec3f(on.a, on.ca.z / on.ca.w); + s.b = vec3f(on.b, on.cb.z / on.cb.w); + s.half = vec2f(style.width, 0.0); + return s; +} + +// A triangle: a face, or one of an area's. +fn seen_triangle(instance: u32, locating: bool) -> Seen { + var s: Seen; + let row = select(triangle_row(instance), instance, locating); + s.row = row; + s.kept = row < mark.rows && !leaving(row); + if !s.kept && !locating { + return s; + } + let ka = triangle_corner(instance, 0u); + let kb = triangle_corner(instance, 1u); + let kc = triangle_corner(instance, 2u); + let ca = clip_of(ka.world); + let cb = clip_of(kb.world); + let cc = clip_of(kc.world); + s.corners = vec3(ka.shown, kb.shown, kc.shown); + s.ahead = vec3(ka.ahead, kb.ahead, kc.ahead); + s.front = vec3(ca.w > 0.0, cb.w > 0.0, cc.w > 0.0); + s.shown = all(s.corners) && any(s.ahead) && all(s.front); + s.a = screen(ca); + s.b = screen(cb); + s.c = screen(cc); + return s; +} + +// Instance `instance` of the mark's primitive on screen; locating, row `instance`'s place. +fn seen(instance: u32, locating: bool) -> Seen { + switch PROBED { + case POINTS: { return seen_point(instance); } + case STROKES: { return seen_segment(instance, locating); } + default: { return seen_triangle(instance, locating); } + } +} + +// How far `p` lies from what the instance drew, and the nearest of it on screen with its depth. +fn reach(s: Seen, p: vec2f) -> Reach { + if !s.kept || !s.shown { + return unreached(); + } + switch PROBED { + case POINTS: { + if s.part > 0u { + return Reach(max(length(p - s.b.xy) - s.half.x, 0.0), s.a.z, s.b.xy, s.row, s.part); + } + let d = outline_distance((p - s.a.xy) * vec2f(1.0, -1.0), s.half); + return Reach(max(d, 0.0), s.a.z, s.a.xy, s.row, 0u); + } + case STROKES: { + let q = nearest_on(p, s.a, s.b); + // The nearer end names the sample a trace's hit lies at; for an edge, which of its ends. + var end = select(s.part, s.part + 1u, length(q.xy - s.b.xy) < length(q.xy - s.a.xy)); + if mark.kind == MARK_EDGES { + end = u32(2u * end >= path_count(s.row)); + } + return Reach(max(length(p - q.xy) - 0.5 * s.half.x, 0.0), q.z, q.xy, s.row, end); + } + default: { + let a = s.a; + let b = s.b; + let c = s.c; + let area = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x); + if abs(area) > 1e-9 { + let wb = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) / area; + let wc = ((b.x - a.x) * (p.y - a.y) - (b.y - a.y) * (p.x - a.x)) / area; + if wb >= 0.0 && wc >= 0.0 && wb + wc <= 1.0 { + return Reach(0.0, a.z + (b.z - a.z) * wb + (c.z - a.z) * wc, p, s.row, 0u); + } + } + var q = nearest_on(p, a, b); + let q2 = nearest_on(p, b, c); + let q3 = nearest_on(p, c, a); + q = select(q, q2, length(p - q2.xy) < length(p - q.xy)); + q = select(q, q3, length(p - q3.xy) < length(p - q.xy)); + return Reach(length(p - q.xy), q.z, q.xy, s.row, 0u); + } + } +} + +fn in_box(p: vec2f) -> bool { + return all(p >= frame.query.xy) && all(p <= frame.query.zw); +} + +// Whether the instance lies in the query's box: a point's center, any part of a segment, or a +// triangle's corner. +fn boxed(s: Seen) -> bool { + if !s.kept { + return false; + } + switch PROBED { + case POINTS: { + return s.part == 0u && s.shown && s.front.x && in_box(s.a.xy); + } + case STROKES: { + if !s.shown { + return false; + } + // The segment crosses the box when its ends do, or it passes through it. + for (var k = 0u; k <= 8u; k++) { + if in_box(mix(s.a.xy, s.b.xy, f32(k) / 8.0)) { + return true; + } + } + return false; + } + default: { + let corner = s.corners & s.ahead & s.front; + return (corner.x && in_box(s.a.xy)) || (corner.y && in_box(s.b.xy)) || (corner.z && in_box(s.c.xy)); + } + } +} + +// Where row `row` lies on screen, and 1 as z where it shows: a point's center, a path's middle +// segment's middle, a face's middle; an area lies where its label hangs. +fn located(row: u32) -> vec3f { + if row >= mark.rows { + return vec3f(0.0); + } + if PROBED == TRIANGLES && PATH == PATH_GEOMETRY { + let anchor = area_anchor(row); + let clip = clip_of(anchor.world); + return vec3f(to_screen(clip), f32(anchor.shown && anchor.ahead && clip.w > 0.0)); + } + let s = seen(row, true); + switch PROBED { + case POINTS: { return vec3f(s.a.xy, f32(s.shown && s.front.x)); } + case STROKES: { return vec3f(0.5 * (s.a.xy + s.b.xy), f32(s.front.x)); } + default: { return vec3f((s.a.xy + s.b.xy + s.c.xy) / 3.0, f32(all(s.front))); } + } +} + +fn drawn_depth(texel: vec2i) -> f32 { + return textureLoad(depth, texel, 0); +} + +// Whether the frame drew nothing in front of `r`. Depth is reversed: nearer is greater. +fn shown(r: Reach) -> bool { + let size = vec2f(textureDimensions(depth)); + let texel = vec2i(clamp(r.point * eye.pixel_ratio, vec2f(0.0), size - 1.0)); + return drawn_depth(texel) <= r.depth * 1.01 + 1e-7; +} + +// The nearest depth drawn around the probe. +fn under() -> f32 { + let size = vec2i(textureDimensions(depth)); + let at = vec2i(frame.probe * eye.pixel_ratio); + var nearest = 0.0; + for (var dy = -1; dy <= 1; dy++) { + for (var dx = -1; dx <= 1; dx++) { + nearest = max(nearest, drawn_depth(clamp(at + vec2i(dx, dy), vec2i(0), size - 1))); + } + } + return nearest; +} + +// Instances of the mark's primitive: rows and their ports, a stroke's segments, or triangles. +fn instances() -> u32 { + if PROBED == STROKES { + return stroke_instances(); + } + if PROBED == POINTS { + return mark.rows * (1u + mark.ports); + } + return triangle_instances(); +} + +// Appends hit `r` to the mark's, while it has room: they follow how many it found and how many it +// keeps, `HIT_WORDS` each. +fn append(r: Reach) { + let at = atomicAdd(&probe[mark.query], 1u); + if at >= atomicLoad(&probe[mark.query + 1u]) { + return; + } + let entry = mark.query + 2u + HIT_WORDS * at; + atomicStore(&probe[entry], r.row); + atomicStore(&probe[entry + 1u], min(u32(r.distance * 64.0), 0xffffffu)); + atomicStore(&probe[entry + 2u], r.segment); + atomicStore(&probe[entry + 3u], bitcast(r.point.x)); + atomicStore(&probe[entry + 4u], bitcast(r.point.y)); + atomicStore(&probe[entry + 5u], bitcast(r.depth)); +} + +@compute @workgroup_size(256) +fn answer(@builtin(global_invocation_id) id: vec3u) { + let s = step.step; + // Steps that read one thing take one invocation. + if s == STEP_UNDER || s == STEP_LOCATE || s == STEP_DESCRIBE { + if any(id != vec3u(0u)) { + return; + } + } + if s == STEP_UNDER { + atomicStore(&probe[PROBE_UNDER], bitcast(under())); + return; + } + if s == STEP_LOCATE { + let at = located(bitcast(frame.query.x)); + atomicStore(&probe[PROBE_LOCATE_X], bitcast(at.x)); + atomicStore(&probe[PROBE_LOCATE_Y], bitcast(at.y)); + atomicStore(&probe[PROBE_LOCATED], u32(at.z)); + return; + } + // Describing reads the topmost instance the hover found, when it is this mark's. + var i = item(id); + if s == STEP_DESCRIBE { + let key = atomicLoad(&probe[PROBE_KEY]); + let instance = atomicLoad(&probe[PROBE_INSTANCE]); + if key == NONE || instance == 0u || 255u - (key & 255u) != min(mark.index, 255u) { + return; + } + i = instance - 1u; + } else if i >= instances() { + return; + } + let drawn = seen(i, false); + if s == STEP_BOXED { + if boxed(drawn) { + atomicOr(&probe[mark.query + drawn.row / 32u], 1u << (drawn.row % 32u)); + } + return; + } + let hits = s == STEP_HITS; + let r = reach(drawn, select(frame.probe, frame.query.xy, hits)); + if !(r.distance <= select(frame.probe_radius, frame.query.z, hits)) || !shown(r) { + return; + } + let key = (min(u32(r.distance * 64.0), 0xffffffu) << 8u) | (255u - min(mark.index, 255u)); + switch s { + case STEP_NEAREST: { + atomicMin(&probe[PROBE_KEY], key); + } + case STEP_TOPMOST: { + if key == atomicLoad(&probe[PROBE_KEY]) { + atomicMax(&probe[PROBE_INSTANCE], i + 1u); + } + } + case STEP_DESCRIBE: { + atomicStore(&probe[PROBE_DEPTH], bitcast(r.depth)); + atomicStore(&probe[PROBE_X], bitcast(r.point.x)); + atomicStore(&probe[PROBE_Y], bitcast(r.point.y)); + atomicStore(&probe[PROBE_ROW], r.row); + atomicStore(&probe[PROBE_SEGMENT], r.segment); + } + default: { + append(r); + } + } +} diff --git a/crates/latkit/shaders/draw/areas.wesl b/crates/latkit/shaders/draw/areas.wesl new file mode 100644 index 00000000..5975ecd4 --- /dev/null +++ b/crates/latkit/shaders/draw/areas.wesl @@ -0,0 +1,56 @@ +// Areas: one instanced triangle per triangle of every area, numbered by the mark's list, flat on the +// ground in its row's color and lit by the earth's daylight. Areas lie under what draws after them: +// they test depth but write none. The focus variant draws the triangles of the rows the mark's focus +// lights again, over everything, tinted toward the theme's focus colors. + +import package::lib::types::{SELECTED, HOVERED}; +import package::lib::bind::frame; +import package::lib::project::culled; +import package::lib::triangles::{triangle_corner, triangle_shown, corner_clip}; +import package::lib::focus::focus_of; +import package::lib::shade::daylight; +import package::lib::color::output; + +struct Varyings { + @builtin(position) clip: vec4f, + @location(0) color: vec4f, + @location(1) @interpolate(flat) row: u32, + // The row's focus bits, which the focus draw tints by. + @location(2) @interpolate(flat) focus: u32, +} + +@vertex +fn vertex(@builtin(vertex_index) corner: u32, @builtin(instance_index) instance: u32) -> Varyings { + var out: Varyings; + let c = triangle_corner(instance, corner); + out.row = c.row; + if !triangle_shown(instance) { + out.clip = culled(); + return out; + } + out.clip = corner_clip(c); + out.color = vec4f(c.color.rgb * daylight(c.position.xy), c.color.a); + out.focus = focus_of(c.row); + return out; +} + +@if(!focused) +@fragment +fn fragment(v: Varyings) -> @location(0) vec4f { + return output(vec4f(v.color.rgb * v.color.a, v.color.a)); +} + +@if(focused) +@fragment +fn fragment(v: Varyings) -> @location(0) vec4f { + var rgb = v.color.rgb; + let focus = v.focus; + if (focus & SELECTED) != 0u { + // A selected color with a negative red asks for each row's own, brightened. + let tint = select(frame.selected.rgb, min(rgb * 1.6 + 0.08, vec3f(1.0)), frame.selected.r < 0.0); + rgb = mix(rgb, tint, 0.5); + } else if (focus & HOVERED) != 0u { + rgb = mix(rgb, frame.hover.rgb, 0.6 * frame.hover.a); + } + return output(vec4f(rgb * v.color.a, v.color.a)); +} diff --git a/crates/latkit/shaders/draw/backdrop.wesl b/crates/latkit/shaders/draw/backdrop.wesl new file mode 100644 index 00000000..0490da7b --- /dev/null +++ b/crates/latkit/shaders/draw/backdrop.wesl @@ -0,0 +1,181 @@ +// The backdrop under every mark: a plane's or a diagram's grid, or the earth's surface and graticule, +// darkened where casters shadow the ground, lit by daylight, and on the globe ringed by its air. Lines +// are a pixel wide and antialiased per axis. Their spacing steps by tens, and the next step fades in as +// the lines crowd, so no seam shows. They fade where the view grazes the ground, and on a plane away +// from what the camera looks at. The round globe writes its depth a hair under its surface, so what +// lies behind it hides and what lies on it draws. + +import package::lib::types::{SPACE_EARTH, SPACE_PLANE, SPACE_DIAGRAM, GRID_OFF, GRID_DOTS}; +import package::lib::bind::{frame, eye}; +import package::lib::color::output; +import package::lib::project::{PI, NEAR_Z, FAR_Z, globe_center}; +import package::lib::shade::{lit, daylight}; + +@group(2) @binding(10) var shadows: texture_2d; + +struct Varyings { + @builtin(position) clip: vec4f, + @location(0) ndc: vec2f, +} + +// How far under its surface the globe's depth lies, in its radii: deeper than a chord of a few +// degrees sags, so paths and areas on the ground draw over it. +const SURFACE_BIAS: f32 = 1e-3; + +// What a pixel of the backdrop draws: its color, and the depth of the ground there. +struct Ground { + color: vec4f, + depth: f32, +} + +struct Out { + @location(0) color: vec4f, + @builtin(frag_depth) depth: f32, +} + +@vertex +fn vertex(@builtin(vertex_index) i: u32) -> Varyings { + let uv = vec2f(f32((i << 1u) & 2u), f32(i & 2u)); + let ndc = uv * 2.0 - 1.0; + return Varyings(vec4f(ndc, 0.0, 1.0), ndc); +} + +// Coverage of lines `pitch` apart through `p`, which moves `w` per pixel: a pixel wide, fading out as +// their cells shrink to a few pixels. +fn lines(p: vec2f, w: vec2f, pitch: f32) -> f32 { + let cells = max(w / pitch, vec2f(1e-12)); + let px = abs(fract(p / pitch + 0.5) - 0.5) / cells; + let c = saturate(1.0 - px) * (1.0 - smoothstep(vec2f(0.08), vec2f(0.25), cells)); + return max(c.x, c.y); +} + +fn dots(p: vec2f, w: vec2f, pitch: f32) -> f32 { + let cells = max(w / pitch, vec2f(1e-12)); + let px = abs(fract(p / pitch + 0.5) - 0.5) / cells; + return saturate(1.5 - length(px)) * (1.0 - smoothstep(0.08, 0.25, max(cells.x, cells.y))); +} + +// Lines spaced `pitch` times a power of ten, from the `lowest` power to the `highest`: the spacing +// nearest twenty pixels draws, and the next coarser one fades in as it crowds. +fn grid(p: vec2f, w: vec2f, pitch: f32, lowest: f32, highest: f32, dotted: bool) -> f32 { + let level = clamp(log2(max(max(w.x, w.y) * 20.0 / pitch, 1e-30)) * 0.30103, lowest, highest); + let k = floor(level); + let t = level - k; + let step = pitch * exp2(k * 3.3219281); + if dotted { + return max(dots(p, w, step), dots(p, w, step * 10.0) * t); + } + return max(lines(p, w, step), lines(p, w, step * 10.0) * t); +} + +fn blend(color: vec4f, over: vec4f, coverage: f32) -> vec4f { + return vec4f(mix(color.rgb, over.rgb, coverage * over.a), color.a); +} + +// `color` darkened where casters shadow ground point `g`. +fn shaded(color: vec4f, g: vec3f, ahead: bool) -> vec4f { + let shadow = select(0.0, 1.0 - lit(shadows, g, true), ahead); + return vec4f(mix(color.rgb, frame.shade.color.rgb, shadow), color.a); +} + +// The plane: its grid where the ray meets elevation 0 at `g`, faded where the ray grazes and away +// from the center. +fn plane(g: vec3f, d: vec3f, ahead: bool) -> vec4f { + let p = g.xy + frame.center_hi + frame.center_lo; + let w = fwidth(g.xy); + let ground = shaded(frame.background, g, ahead); + if frame.grid_kind == GRID_OFF { + return ground; + } + let near = 1.0 - smoothstep(0.6, 1.0, length(g.xy) / max(frame.grid_fade, 1e-30)); + let fade = f32(ahead) * smoothstep(0.02, 0.15, abs(d.z)) * select(1.0, near, frame.grid_fade > 0.0); + let c = grid(p, w, frame.grid_pitch, 0.0, 30.0, frame.grid_kind == GRID_DOTS) * fade; + return blend(ground, frame.grid_color, c); +} + +// Longitude and latitude in degrees at world point `w` on the flat map. +fn map_degrees(w: vec3f) -> vec2f { + let lat = degrees(2.0 * atan(exp(w.y + frame.mercator_y)) - 0.5 * PI); + return vec2f(frame.center_hi.x + frame.center_lo.x + degrees(w.x), lat); +} + +// Longitude and latitude in degrees at world point `w` on the globe of `radius`. +fn globe_degrees(w: vec3f, radius: f32) -> vec2f { + let lat0 = radians(frame.center_hi.y + frame.center_lo.y); + let u = normalize(vec3f(w.xy, w.z + radius)); + let v = vec3f(u.x, u.y * cos(lat0) + u.z * sin(lat0), -u.y * sin(lat0) + u.z * cos(lat0)); + let lon = frame.center_hi.x + frame.center_lo.x + degrees(atan2(v.x, v.z)); + return vec2f(lon, degrees(asin(clamp(v.y, -1.0, 1.0)))); +} + +// The earth: the mercator band or the globe's disc, eased between as the projection morphs, lit by +// daylight, the graticule on it, and around the globe its air. +fn earth(o: vec3f, d: vec3f, g: vec3f, ahead: bool) -> Ground { + // The flat map ends where web mercator does, at y = ±π. + let band = PI - abs(g.y + frame.mercator_y); + let flat = saturate(band / max(fwidth(band), 1e-9) + 0.5) * f32(ahead); + let center = globe_center(); + let radius = -center.z; + let to_center = center - o; + let along = dot(to_center, d); + let off = length(to_center - d * along); + let miss = off - radius; + let round = saturate(-miss / max(fwidth(miss), 1e-9) + 0.5) * f32(along > 0.0); + let covered = mix(flat, round, frame.globe); + let hit = o + d * (along - sqrt(max(radius * radius - off * off, 0.0))); + let globe = frame.globe >= 0.5; + var p: vec2f; + var ground = frame.surface; + if globe { + p = globe_degrees(hit, radius); + ground = vec4f(ground.rgb * daylight(p), ground.a); + } else { + p = map_degrees(g); + ground = shaded(vec4f(ground.rgb * daylight(p), ground.a), g, ahead); + } + var color = blend(frame.background, ground, covered); + let facing = dot(normalize(hit - center), -d); + if frame.graticule != 0u { + // Longitude jumps where it wraps; its other wrapping steadies the derivative there. + let wrapped = fract(p.x / 360.0) * 360.0; + let w = vec2f(min(fwidth(p.x), fwidth(wrapped)), fwidth(p.y)); + let fade = select(smoothstep(0.02, 0.15, abs(d.z)), smoothstep(0.0, 0.3, facing), globe); + color = blend(color, frame.grid_color, grid(p, w, 1.0, -2.0, 1.0, false) * fade * covered); + } + if frame.atmosphere.a > 0.0 && frame.globe > 0.0 { + // A rim of air over the globe's edge and a halo past it, lit where the sun is up over the + // ground the ray passes nearest. + let rim = pow(1.0 - saturate(facing), 3.0) * round; + let halo = pow(1.0 - smoothstep(radius, radius * 1.12, off), 2.0) * (1.0 - round) * f32(along > 0.0); + let below = daylight(globe_degrees(o + d * along, radius)); + let air = (rim + halo) * frame.atmosphere.a * frame.globe * mix(0.2, 1.0, below); + color = vec4f(mix(color.rgb, frame.atmosphere.rgb, saturate(air)), color.a); + } + var depth = FAR_Z; + if frame.globe >= 1.0 && round > 0.5 { + let under = eye.clip_from_world * vec4f(hit - normalize(hit - center) * radius * SURFACE_BIAS, 1.0); + depth = clamp(under.z / under.w, FAR_Z, NEAR_Z); + } + return Ground(color, depth); +} + +@fragment +fn fragment(v: Varyings) -> Out { + let near = eye.world_from_clip * vec4f(v.ndc, NEAR_Z, 1.0); + let far = eye.world_from_clip * vec4f(v.ndc, FAR_Z, 1.0); + let o = near.xyz / near.w; + let d = normalize(far.xyz / far.w - o); + // Where the ray meets elevation 0. + let t = -o.z / d.z; + let g = o + d * max(t, 0.0); + var color = frame.background; + var depth = FAR_Z; + if frame.space == SPACE_PLANE || frame.space == SPACE_DIAGRAM { + color = plane(g, d, t > 0.0); + } else if frame.space == SPACE_EARTH { + let ground = earth(o, d, g, t > 0.0); + color = ground.color; + depth = ground.depth; + } + return Out(output(vec4f(color.rgb * color.a, color.a)), depth); +} diff --git a/crates/latkit/shaders/draw/glyphs.wesl b/crates/latkit/shaders/draw/glyphs.wesl new file mode 100644 index 00000000..f18d111d --- /dev/null +++ b/crates/latkit/shaders/draw/glyphs.wesl @@ -0,0 +1,153 @@ +// Glyphs: every labeled row's text, placed from its anchor each frame and shown as placement decided, +// over a halo of the background so it reads over whatever lies under it. The ports variant draws +// each port's label beside it, inside its marker. Text is a distance field: edges stay crisp at any +// size, and the halo is a wider threshold of the same field. + +import package::lib::types::{ + CANDIDATE_WORDS, CANDIDATE_ALPHA, LABEL_CODE, LABEL_COLOR, PORT_WORDS, PORT_CODE, PORT_UV, PORT_SIZE, SIDE_LEFT, + SIDE_RIGHT, SIDE_TOP, TEXT_SPREAD, TEXT_ESTIMATE, SPACE_DIAGRAM, THEME_TEXT, +}; +import package::lib::bind::{frame, eye, mark, state, program, ramp}; +import package::lib::state::extra_at; +import package::lib::read::missing_bits; +import package::lib::points::{point, port_at, port_inward}; +import package::lib::label::{anchor, length_px, legibility, text_at, fits, Text}; +import package::lib::project::culled; +import package::lib::color::output; + +@group(2) @binding(8) var atlas: texture_2d; +@group(2) @binding(13) var labels: array; + +struct Varyings { + @builtin(position) clip: vec4f, + @location(0) uv: vec2f, + @location(1) @interpolate(flat) color: vec4f, + // CSS pixels per atlas texel. + @location(2) @interpolate(flat) scale: f32, +} + +// Corner `corner` of text `t`, drawn in `color`. +fn quad(t: Text, corner: u32, color: vec4f) -> Varyings { + var out: Varyings; + let q = vec2f(f32(corner & 1u), f32(corner >> 1u)); + // Snapped to whole target pixels while it is set at its own size, so text stays crisp. + var p = mix(t.quad_lo, t.quad_hi, q); + if frame.space != SPACE_DIAGRAM { + p = round(p * eye.pixel_ratio) / eye.pixel_ratio; + } + let ndc = p / eye.size * 2.0 - 1.0; + out.clip = vec4f(ndc.x, -ndc.y, 0.0, 1.0); + out.uv = mix(t.uv_lo, t.uv_hi, q); + out.color = color; + out.scale = t.scale; + return out; +} + +fn unshown() -> Varyings { + var out: Varyings; + out.clip = culled(); + return out; +} + +@if(!ports) +@vertex +fn vertex(@builtin(vertex_index) corner: u32, @builtin(instance_index) row: u32) -> Varyings { + if row >= mark.rows { + return unshown(); + } + let code_bits = state[extra_at(row, mark.label + LABEL_CODE)]; + if missing_bits(code_bits) { + return unshown(); + } + let code = u32(bitcast(code_bits)); + let uv0 = labels[mark.runs + 2u * code]; + let uv1 = labels[mark.runs + 2u * code + 1u]; + // Nothing to draw until the text is set. + if (uv0 == 0u && uv1 == 0u) || (uv0 & TEXT_ESTIMATE) != 0u { + return unshown(); + } + let a = anchor(row); + let size = length_px(mark.label_size); + let t = text_at(uv0, uv1, size, a.at, a.align); + // A diagram's labels show while they fit and read; elsewhere as placement decided. + var alpha = bitcast(labels[mark.candidates + row * CANDIDATE_WORDS + CANDIDATE_ALPHA]); + if frame.space == SPACE_DIAGRAM { + alpha = f32(a.shown && fits(t.hi - t.lo, a.room)) * legibility(size); + } + if !(alpha > 0.0) { + return unshown(); + } + let color = unpack4x8unorm(state[extra_at(row, mark.label + LABEL_COLOR)]); + return quad(t, corner, vec4f(color.rgb, color.a * alpha)); +} + +// A port's label: beside the port, inside its marker, aligned away from the side it sits on. It +// shows while it reads and keeps clear of the ports across from it. +@if(ports) +@vertex +fn vertex(@builtin(vertex_index) corner: u32, @builtin(instance_index) instance: u32) -> Varyings { + let n = max(mark.ports, 1u); + let row = instance / n; + let k = instance % n; + if row >= mark.rows { + return unshown(); + } + let info = mark.port_info + k * PORT_WORDS; + let uv0 = program[info + PORT_UV]; + let uv1 = program[info + PORT_UV + 1u]; + if uv0 == 0u && uv1 == 0u { + return unshown(); + } + let p = point(row); + let port = port_at(p, k); + let code = program[info + PORT_CODE]; + let inward = port_inward(code); + let gap = 0.5 * PORT_SIZE * frame.unit; + let at = port.center + inward * (port.half + gap); + var align = vec2f(0.5); + var room = vec2f(2.0 * p.half.x, p.half.y); + switch code & 3u { + case SIDE_LEFT: { + align = vec2f(0.0, 0.5); + room = vec2f(p.half.x - port.half - gap, 2.0 * p.half.y); + } + case SIDE_RIGHT: { + align = vec2f(1.0, 0.5); + room = vec2f(p.half.x - port.half - gap, 2.0 * p.half.y); + } + case SIDE_TOP: { + align = vec2f(0.5, 0.0); + room = vec2f(2.0 * p.half.x / f32(((code >> 10u) & 255u) + 1u), p.half.y); + } + default: { + align = vec2f(0.5, 1.0); + room = vec2f(2.0 * p.half.x / f32(((code >> 10u) & 255u) + 1u), p.half.y); + } + } + let size = length_px(mark.port_label_size); + let t = text_at(uv0, uv1, size, at, align); + let alpha = f32(p.shown && fits(t.hi - t.lo, room)) * legibility(size) * p.color.a; + if !(alpha > 0.0) { + return unshown(); + } + let text = unpack4x8unorm(frame.theme[THEME_TEXT / 4u][THEME_TEXT % 4u]); + return quad(t, corner, vec4f(text.rgb, text.a * alpha)); +} + +// The distance field at `uv`: texels past the text's edge, inside positive. +fn inside(uv: vec2f) -> f32 { + let d = textureSampleLevel(atlas, ramp, uv / vec2f(textureDimensions(atlas)), 0.0).r; + return (d - 0.5) * 2.0 * TEXT_SPREAD; +} + +@fragment +fn fragment(v: Varyings) -> @location(0) vec4f { + // Target pixels past the edge. + let d = inside(v.uv) * v.scale * eye.pixel_ratio; + let a_text = clamp(0.5 + d, 0.0, 1.0) * v.color.a; + let back = frame.background; + let a_halo = clamp(0.5 + d + frame.halo * eye.pixel_ratio, 0.0, 1.0) * v.color.a * back.a * 0.85; + let a = a_text + a_halo * (1.0 - a_text); + let rgb = v.color.rgb * a_text + back.rgb * a_halo * (1.0 - a_text); + return output(vec4f(rgb, a)); +} diff --git a/crates/latkit/shaders/draw/overlay.wesl b/crates/latkit/shaders/draw/overlay.wesl new file mode 100644 index 00000000..c7473e2f --- /dev/null +++ b/crates/latkit/shaders/draw/overlay.wesl @@ -0,0 +1,67 @@ +// The overlay: lines, boxes, filled rectangles, and runs of text in CSS pixels over every mark, such +// as a plot's axes, a scene's title and legends, a selection box, and a connection being drawn. Text +// is the atlas's distance field, its quad reaching over the field's spread. + +import package::lib::types::{Sprite, SPRITE_TEXT, SPRITE_BOX, SPRITE_FILL, TEXT_SPREAD}; +import package::lib::bind::{eye, ramp}; +import package::lib::mark::coverage; +import package::lib::color::output; + +@group(2) @binding(7) var sprites: array; +@group(2) @binding(8) var atlas: texture_2d; + +struct Varyings { + @builtin(position) clip: vec4f, + @location(0) p: vec2f, + @location(1) @interpolate(flat) sprite: u32, +} + +@vertex +fn vertex(@builtin(vertex_index) corner: u32, @builtin(instance_index) sprite: u32) -> Varyings { + let s = sprites[sprite]; + let quad = vec2f(f32(corner & 1u), f32(corner >> 1u)); + var p = mix(s.a, s.b, quad); + if s.kind == SPRITE_BOX { + p = mix(min(s.a, s.b) - 1.0, max(s.a, s.b) + 1.0, quad); + } else if s.kind == SPRITE_FILL { + p = mix(min(s.a, s.b), max(s.a, s.b), quad); + } else if s.kind != SPRITE_TEXT { + let dir = normalize(s.b - s.a + vec2f(1e-6, 0.0)); + let reach = 0.5 * s.width + 1.0; + let along = mix(s.a - dir * reach, s.b + dir * reach, quad.x); + p = along + vec2f(-dir.y, dir.x) * (quad.y * 2.0 - 1.0) * reach; + } + let ndc = p / eye.size * 2.0 - 1.0; + return Varyings(vec4f(ndc.x, -ndc.y, 0.0, 1.0), p, sprite); +} + +@fragment +fn fragment(v: Varyings) -> @location(0) vec4f { + let s = sprites[v.sprite]; + var c = 0.0; + var color = s.color; + if s.kind == SPRITE_TEXT { + let t = (v.p - s.a) / max(s.b - s.a, vec2f(1e-6)); + let uv = mix(s.uv.xy, s.uv.zw, t) / vec2f(textureDimensions(atlas)); + // CSS pixels per texel, then target pixels past the text's edge. + let scale = (s.b.y - s.a.y) / max(s.uv.w - s.uv.y, 1e-6); + let d = (textureSampleLevel(atlas, ramp, uv, 0.0).r - 0.5) * 2.0 * TEXT_SPREAD * scale * eye.pixel_ratio; + c = clamp(0.5 + d, 0.0, 1.0); + } else if s.kind == SPRITE_BOX { + let lo = min(s.a, s.b); + let hi = max(s.a, s.b); + let inside = all(v.p >= lo) && all(v.p <= hi); + let edge = min(min(v.p.x - lo.x, hi.x - v.p.x), min(v.p.y - lo.y, hi.y - v.p.y)); + let line = coverage(abs(edge) - 0.5 * s.width); + c = max(line, f32(inside) * 0.15); + } else if s.kind == SPRITE_FILL { + c = 1.0; + } else { + let ab = s.b - s.a; + let t = clamp(dot(v.p - s.a, ab) / max(dot(ab, ab), 1e-6), 0.0, 1.0); + let d = length(v.p - (s.a + ab * t)) - 0.5 * s.width; + c = coverage(d); + } + let a = color.a * c; + return output(vec4f(color.rgb * a, a)); +} diff --git a/crates/latkit/shaders/draw/points.wesl b/crates/latkit/shaders/draw/points.wesl new file mode 100644 index 00000000..65938fdd --- /dev/null +++ b/crates/latkit/shaders/draw/points.wesl @@ -0,0 +1,172 @@ +// Points: one instanced quad per vertex row, shaded by its marker; a group's rows draw as +// containers. A quad covers its marker and a pixel of edge, no more, and a small one a later one +// covers in a crowded cell is left out. The focus variant draws the rows the mark's focus lights +// again, over everything, reaching out to their glow; a group only glows about its border, so what +// it holds still shows. The cast variant draws the same quads through the light's eye into the +// shadow map; the ports variant draws one quad per port of every row, on its side of the row's +// marker. + +import package::lib::types::{STATUS, MARKER_ICON, GROUP}; +import package::lib::bind::{frame, mark, state, ramp, program, focused}; +import package::lib::state::extra_at; +import package::lib::project::{to_screen, to_clip, nearer, culled}; +import package::lib::points::{Point, point, reach, port_at}; +import package::lib::marker::{ + MarkerColor, MarkerFragment, builtin_marker, container, outline_distance, shape_distance, filled, over, + status_ring, glow, premultiplied, theme_text, +}; +import package::lib::shade::{caster, daylight}; +import package::lib::mark::fringe; +import package::lib::color::output; + +@group(2) @binding(15) var icons: texture_2d_array; + +struct Varyings { + @builtin(position) clip: vec4f, + @location(0) p: vec2f, + @location(1) @interpolate(flat) row: u32, + @location(2) color: vec4f, + @location(3) @interpolate(flat) half: vec2f, + @location(4) @interpolate(flat) status: vec4f, + @location(5) @interpolate(flat) height: f32, + @location(6) @interpolate(flat) shape: u32, + // A group's depth; for a port, 1 when its reference names a net. + @location(7) @interpolate(flat) extra: f32, + // The row's focus bits, which the focus draw glows by. + @location(8) @interpolate(flat) focus: u32, +} + +// What an instance draws: a row's marker, or with `ports` one of a row's ports. +struct Drawn { + p: Point, + center: vec2f, + half: vec2f, + reach: vec2f, + shape: u32, + extra: f32, +} + +@if(!ports && !focused) +fn drawn(instance: u32) -> Drawn { + let p = point(instance); + return Drawn(p, to_screen(p.clip), p.half, reach(p, false), mark.shape, p.depth); +} + +@if(focused) +fn drawn(instance: u32) -> Drawn { + let p = point(focused[mark.focused + instance]); + return Drawn(p, to_screen(p.clip), p.half, reach(p, true), mark.shape, p.depth); +} + +@if(ports) +fn drawn(instance: u32) -> Drawn { + let n = max(mark.ports, 1u); + let p = point(instance / n); + let port = port_at(p, instance % n); + let half = vec2f(port.half); + return Drawn(p, port.center, half, half + 1.0 + fringe(), port.shape, f32(port.wired)); +} + +@vertex +fn vertex(@builtin(vertex_index) corner: u32, @builtin(instance_index) instance: u32) -> Varyings { + let d = drawn(instance); + let quad = vec2f(f32(corner & 1u), f32(corner >> 1u)) * 2.0 - 1.0; + var out: Varyings; + out.clip = nearer(to_clip(d.center + quad * d.reach, d.p.clip)); + out.p = quad * d.reach * vec2f(1.0, -1.0); + out.row = d.p.row; + out.color = vec4f(d.p.color.rgb * daylight(d.p.position), d.p.color.a); + out.half = max(d.half, vec2f(0.5)); + out.status = d.p.status; + out.height = d.p.world.z; + out.shape = d.shape; + out.extra = d.extra; + out.focus = d.p.focus; + if !d.p.shown { + out.clip = culled(); + } + return out; +} + +fn inputs(row: u32) -> array { + var input = array(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); + for (var i = 0u; i < min(mark.inputs, 8u); i++) { + input[i] = bitcast(state[extra_at(row, mark.input + i)]); + } + return input; +} + +// An icon: image `index` of the mark's images, fitted in the marker's box, faded with its row. The +// palette holds how many images there are, then each one's layer of the icon atlas. +fn icon(f: MarkerFragment) -> MarkerColor { + let uv = vec2f(f.p.x, -f.p.y) / (2.0 * f.half) + 0.5; + let count = max(program[mark.palette], 1u); + let layer = program[mark.palette + 1u + min(u32(max(f.input[0], 0.0)), count - 1u)]; + let texel = textureSampleLevel(icons, ramp, uv, layer, 0.0); + let inside = all(uv >= vec2f(0.0)) && all(uv <= vec2f(1.0)); + let d = outline_distance(f.p, f.half); + return MarkerColor(vec4f(texel.rgb, texel.a * f.color.a * f32(inside)), d); +} + +@if(!custom) +fn marker(f: MarkerFragment) -> MarkerColor { + if mark.marker == MARKER_ICON { + return icon(f); + } + return builtin_marker(f); +} + +// A port: its shape in its row's color mixed toward the theme's text, so it reads on the marker in +// either theme, ringed by the background so it reads apart from the marker; hollow while no net plugs +// into it. +@if(ports) +fn shaded(v: Varyings) -> MarkerColor { + let d = shape_distance(v.shape, v.p, v.half); + let ink = vec4f(mix(v.color.rgb, theme_text(), 0.55), v.color.a); + let ring = filled(vec4f(frame.background.rgb, v.color.a), d - 1.5); + if v.extra > 0.5 { + return over(filled(ink, d), ring); + } + let hollow = over(filled(ink, abs(d + 0.75) - 0.75), filled(vec4f(frame.background.rgb, v.color.a), d)); + return over(hollow, ring); +} + +@if(!ports) +fn shaded(v: Varyings) -> MarkerColor { + let f = MarkerFragment(v.p, v.half, v.color, inputs(v.row)); + var m = marker(f); + if (mark.flags & GROUP) != 0u { + m = container(f, v.extra); + } + if (mark.flags & STATUS) != 0u && v.status.a > 0.0 { + m = status_ring(m, v.p, v.half, vec4f(v.status.rgb, v.status.a * v.color.a)); + } + return m; +} + +@if(!casts && !focused) +@fragment +fn fragment(v: Varyings) -> @location(0) vec4f { + return output(premultiplied(shaded(v))); +} + +@if(focused) +@fragment +fn fragment(v: Varyings) -> @location(0) vec4f { + let m = shaded(v); + if (mark.flags & GROUP) != 0u { + // Drawn over what it holds, a group's body would hide it: it glows on both sides of its border. + return output(glow(MarkerColor(vec4f(0.0), abs(m.distance)), v.focus)); + } + return output(glow(m, v.focus)); +} + +@if(casts) +@fragment +fn fragment(v: Varyings) -> @location(0) vec4f { + let m = shaded(v); + if m.color.a <= 0.01 { + discard; + } + return caster(m.color.a, v.height); +} diff --git a/crates/latkit/shaders/draw/shade.wesl b/crates/latkit/shaders/draw/shade.wesl new file mode 100644 index 00000000..a86b41b2 --- /dev/null +++ b/crates/latkit/shaders/draw/shade.wesl @@ -0,0 +1,21 @@ +// One level of the shadow map from the level below: coverage averaged, so it softens; the lowest +// caster kept, and the highest. + +@group(2) @binding(11) var below: texture_2d; + +@vertex +fn vertex(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f { + let uv = vec2f(f32((i << 1u) & 2u), f32(i & 2u)); + return vec4f(uv * 2.0 - 1.0, 0.0, 1.0); +} + +@fragment +fn fragment(@builtin(position) p: vec4f) -> @location(0) vec4f { + let size = vec2i(textureDimensions(below)) - 1; + let at = vec2i(p.xy) * 2; + let a = textureLoad(below, min(at, size), 0); + let b = textureLoad(below, min(at + vec2i(1, 0), size), 0); + let c = textureLoad(below, min(at + vec2i(0, 1), size), 0); + let d = textureLoad(below, min(at + vec2i(1, 1), size), 0); + return vec4f((a.r + b.r + c.r + d.r) * 0.25, min(min(a.g, b.g), min(c.g, d.g)), min(min(a.b, b.b), min(c.b, d.b)), 0.0); +} diff --git a/crates/latkit/shaders/draw/strokes.wesl b/crates/latkit/shaders/draw/strokes.wesl new file mode 100644 index 00000000..a49d1253 --- /dev/null +++ b/crates/latkit/shaders/draw/strokes.wesl @@ -0,0 +1,143 @@ +// Strokes: one instanced quad per segment of every row's path, for edges and lines alike, covering +// the stroke, or its comets where they are wider, and a pixel of edge; a small segment a later one covers in a crowded cell is left out. A +// segment that ends a part of its path carries the arrowhead; in a diagram, a segment of no length is +// a junction, drawn as a dot. The focus variant draws the pieces of the rows the mark's focus lights +// again, over everything, reaching out to their glow. The cast variant draws the same quads through +// the light's eye into the shadow map. + +import package::lib::types::{ARROWS, PATH_TRACE, SPACE_DIAGRAM}; +import package::lib::path::PATH; +import package::lib::bind::{frame, mark, eye}; +import package::lib::project::{to_clip, nearer, culled}; +import package::lib::path::{ + segment, segment_screen, stroke_style, ends_colored, ends_part, path_count, path_length, px_per_length, +}; +import package::lib::marker::{MarkerColor, glow}; +import package::lib::focus::focus_of; +import package::lib::mark::fringe; +import package::lib::stroke::{Stroke, covered, stroke, stroke_distance}; +import package::lib::shade::{caster, daylight}; +import package::lib::color::output; + +struct Varyings { + // The corner in clip space; in the fragment, the target pixel, which `pixel` reads. + @builtin(position) clip: vec4f, + @location(0) @interpolate(flat) a: vec2f, + @location(1) @interpolate(flat) b: vec2f, + @location(2) @interpolate(flat) row: u32, + @location(3) color: vec4f, + // Width, distance along at `a` and at `b`, flow. + @location(4) @interpolate(flat) style: vec4f, + @location(5) height: f32, + // Whether the segment ends in an arrowhead, then whether it dashes. + @location(6) @interpolate(flat) arrow: u32, + // The row's focus bits, which the focus draw glows by. + @location(7) @interpolate(flat) focus: u32, + // Distance along at `a` and at `b` in length units, and how far the row's comets traveled. + @location(8) @interpolate(flat) comet: vec3f, +} + +// Whether this variant draws lit rows, its quads reaching out to their glow. +@if(focused) +const LIT_DRAW: bool = true; +@if(!focused) +const LIT_DRAW: bool = false; + +@vertex +fn vertex(@builtin(vertex_index) corner: u32, @builtin(instance_index) instance: u32) -> Varyings { + var out: Varyings; + let s = segment(instance); + out.row = s.row; + if LIT_DRAW && (s.row >= mark.rows || s.index >= path_count(s.row)) { + out.clip = culled(); + return out; + } + let style = stroke_style(s.row); + let on = segment_screen(s); + let ends = on.ends; + if !style.shown || !on.shown { + out.clip = culled(); + return out; + } + let ca = on.ca; + let cb = on.cb; + let a = on.a; + let b = on.b; + let junction = frame.space == SPACE_DIAGRAM && length(b - a) < 1e-3; + let width = select(style.width, 3.0 * style.width, junction); + let dir = normalize(b - a + vec2f(1e-6, 0.0)); + let normal = vec2f(-dir.y, dir.x); + let arrow = (mark.flags & ARROWS) != 0u && !junction && ends_part(s); + let head = select(0.0, frame.arrow + width, arrow); + let comets = select(0.0, 0.5 * frame.flow_width, style.flow != 0.0 && frame.flow.a > 0.0); + let reach = max(0.5 * width, comets) + head + select(0.0, frame.glow, LIT_DRAW) + fringe(); + let t = f32(corner & 1u); + let side = f32(corner >> 1u) * 2.0 - 1.0; + let screen = mix(a - dir * reach, b + dir * reach, t) + normal * side * reach; + out.clip = nearer(to_clip(screen, select(ca, cb, t > 0.5))); + out.a = a; + out.b = b; + // How far along the whole segment this corner lies, of the part drawn. + let f = mix(on.kept.x, on.kept.y, t); + var color = style.color; + if ends_colored() { + color *= mix(ends[0].color, ends[1].color, f); + } + let light = daylight(mix(ends[0].position.xy, ends[1].position.xy, f)); + out.color = vec4f(color.rgb * light, color.a); + // In length units, a path runs from its start, a listed one's segment from where its list says it + // starts, its ends stopping short where the stroke does. On screen, a trace runs along x, a + // listed path as it does in length units, and else a segment from where its stroke starts. + let along = s.along + path_length(ends[0], ends[1]) * on.kept; + let pixels = length(b - a); + var phase = vec2f(0.0, pixels); + if PATH == PATH_TRACE { + phase = vec2f(a.x, a.x + pixels); + } else if mark.per_row == NONE { + phase = along * px_per_length(); + } + out.style = vec4f(width, phase, style.flow); + out.comet = vec3f(along, style.travel); + out.height = mix(ends[0].world.z, ends[1].world.z, f); + out.arrow = u32(arrow) | (u32(style.dash && !junction) << 1u); + out.focus = focus_of(s.row); + return out; +} + +// The fragment's pixel in CSS pixels, a screen position as `a` and `b` are. Read from the fragment's +// own position, never interpolated: a quad whose ends lie at very different depths skews what is +// interpolated, and a renderer clipping the quad at the screen's edge, as lavapipe does, moves it. +fn pixel(v: Varyings) -> vec2f { + return v.clip.xy / eye.pixel_ratio; +} + +fn segment_of(v: Varyings) -> Stroke { + let dash = (v.arrow & 2u) != 0u; + return Stroke(v.a, v.b, v.style.yz, v.comet.xy, v.style.x, v.color, v.style.w, v.comet.z, dash, (v.arrow & 1u) != 0u); +} + +@if(!casts && !focused) +@fragment +fn fragment(v: Varyings) -> @location(0) vec4f { + let c = stroke(pixel(v), segment_of(v)); + return output(vec4f(c.rgb * c.a, c.a)); +} + +@if(focused) +@fragment +fn fragment(v: Varyings) -> @location(0) vec4f { + let s = segment_of(v); + let p = pixel(v); + return output(glow(MarkerColor(stroke(p, s), stroke_distance(p, s).x), v.focus)); +} + +@if(casts) +@fragment +fn fragment(v: Varyings) -> @location(0) vec4f { + let s = segment_of(v); + let alpha = s.color.a * covered(stroke_distance(pixel(v), s), s); + if alpha <= 0.01 { + discard; + } + return caster(alpha, v.height); +} diff --git a/crates/latkit/shaders/draw/triangles.wesl b/crates/latkit/shaders/draw/triangles.wesl new file mode 100644 index 00000000..ce734c92 --- /dev/null +++ b/crates/latkit/shaders/draw/triangles.wesl @@ -0,0 +1,66 @@ +// Triangles: one instanced triangle per face row, lit from the camera so a flat mesh seen from above +// shows its exact colors; turned away, a face darkens by the theme's shading. Faces receive the +// ground's shadow map. The cast variant draws them through the light's eye into the map. + +import package::lib::bind::{frame, eye}; +import package::lib::project::culled; +import package::lib::triangles::{triangle_corner, triangle_shown, corner_clip}; +import package::lib::marker::{MarkerColor, glow}; +import package::lib::focus::focus_of; +import package::lib::shade::{caster, lit}; +import package::lib::color::output; + +// Each vertex's summed face normals, in fixed point. +@group(2) @binding(3) var normals: array; +@if(!casts) +@group(2) @binding(10) var shadows: texture_2d; + +struct Varyings { + @builtin(position) clip: vec4f, + @location(0) world: vec3f, + @location(1) normal: vec3f, + @location(2) color: vec4f, + @location(3) @interpolate(flat) row: u32, + // The row's focus bits: a lit face tints by them. + @location(4) @interpolate(flat) focus: u32, +} + +@vertex +fn vertex(@builtin(vertex_index) corner: u32, @builtin(instance_index) row: u32) -> Varyings { + var out: Varyings; + out.row = row; + let c = triangle_corner(row, corner); + if !triangle_shown(row) { + out.clip = culled(); + return out; + } + out.clip = corner_clip(c); + out.world = c.world; + let s = c.slot * 3u; + out.normal = vec3f(f32(normals[s]), f32(normals[s + 1u]), f32(normals[s + 2u])); + out.color = c.color; + out.focus = focus_of(row); + return out; +} + +@if(!casts) +@fragment +fn fragment(v: Varyings) -> @location(0) vec4f { + let to_eye = normalize(eye.position.xyz - v.world); + let length2 = dot(v.normal, v.normal); + var n = select(to_eye, v.normal * inverseSqrt(length2), length2 > 1e-12); + n = select(n, -n, dot(n, to_eye) < 0.0); + let facing = max(dot(n, to_eye), 0.0); + let diffuse = 1.0 - frame.shading * (1.0 - facing); + let shine = pow(max(dot(n, normalize(frame.light.xyz + to_eye)), 0.0), 48.0) * 0.3 * frame.shading; + let rim = pow(1.0 - facing, 4.0) * 0.25 * frame.shading; + let rgb = min(v.color.rgb * diffuse + shine + rim, vec3f(1.0)); + let shadowed = mix(rgb, frame.shade.color.rgb, 1.0 - lit(shadows, v.world, false)); + return output(glow(MarkerColor(vec4f(shadowed, v.color.a), 0.0), v.focus)); +} + +@if(casts) +@fragment +fn fragment(v: Varyings) -> @location(0) vec4f { + return caster(v.color.a, v.world.z); +} diff --git a/crates/latkit/shaders/lib/bind.wesl b/crates/latkit/shaders/lib/bind.wesl new file mode 100644 index 00000000..0fee192f --- /dev/null +++ b/crates/latkit/shaders/lib/bind.wesl @@ -0,0 +1,25 @@ +// Bindings every pipeline shares: group 0 per view and frame, group 1 per mark, group 2 per pass. + +import package::lib::types::{Frame, Eye, Mark}; + +@group(0) @binding(0) var frame: Frame; +// Data pages: column values as f32 or u32 words, in blocks the arena hands out. +@group(0) @binding(1) var pages: array; +// Compiled marks: column descriptors, page tables, code, constants, ends. +@group(0) @binding(2) var program: array; +// Selection and hover bits, one word per row. +@group(0) @binding(3) var focus: array; +@group(0) @binding(4) var colormaps: texture_2d_array; +@group(0) @binding(5) var ramp: sampler; +// What the pass draws through, at a dynamic offset. +@group(0) @binding(6) var eye: Eye; +// The rows each mark's focus draw lights: every mark's, at its `focused`. +@group(0) @binding(7) var focused: array; + +@group(1) @binding(0) var mark: Mark; + +// Evaluated rows of every mark: compute passes write them, render passes read them. +@if(writes) +@group(2) @binding(0) var state: array; +@else +@group(2) @binding(0) var state: array; diff --git a/crates/latkit/shaders/lib/color.wesl b/crates/latkit/shaders/lib/color.wesl new file mode 100644 index 00000000..0a068ae9 --- /dev/null +++ b/crates/latkit/shaders/lib/color.wesl @@ -0,0 +1,41 @@ +// Colors are sRGB-encoded, as in CSS, and packed RGBA8 in state. + +import package::lib::types::{MISSING_COLOR, COLORMAP_CYCLIC, COLORMAP_CATEGORICAL}; +import package::lib::bind::{frame, colormaps, ramp}; +import package::lib::read::missing; + +// `x` mapped linearly from `domain` onto `range`, clamped. +fn scale(x: f32, domain: vec2f, range: vec2f) -> f32 { + if missing(x) { + return x; + } + let span = domain.y - domain.x; + let t = select(0.5, (x - domain.x) / span, span != 0.0); + return mix(range.x, range.y, clamp(t, 0.0, 1.0)); +} + +// `x` through colormap `layer` over `domain`, packed; missing for a missing `x`. +fn colormap(layer: u32, kind: u32, x: f32, domain: vec2f) -> u32 { + if missing(x) { + return MISSING_COLOR; + } + if kind == COLORMAP_CATEGORICAL { + let bin = u32(abs(floor(x))) % 256u; + return pack4x8unorm(textureLoad(colormaps, vec2u(bin, 0u), layer, 0)); + } + var t = (x - domain.x) / max(domain.y - domain.x, 1e-30); + t = select(clamp(t, 0.0, 1.0), fract(t), kind == COLORMAP_CYCLIC); + return pack4x8unorm(textureSampleLevel(colormaps, ramp, vec2f((t * 255.0 + 0.5) / 256.0, 0.5), layer, 0.0)); +} + +fn to_linear(c: vec3f) -> vec3f { + return select(pow((c + 0.055) / 1.055, vec3f(2.4)), c / 12.92, c <= vec3f(0.04045)); +} + +// A premultiplied fragment color for the target: sRGB values convert when it stores linear color. +fn output(premultiplied: vec4f) -> vec4f { + if frame.linear == 0u || premultiplied.a <= 0.0 { + return premultiplied; + } + return vec4f(to_linear(premultiplied.rgb / premultiplied.a) * premultiplied.a, premultiplied.a); +} diff --git a/crates/latkit/shaders/lib/focus.wesl b/crates/latkit/shaders/lib/focus.wesl new file mode 100644 index 00000000..a01b61ae --- /dev/null +++ b/crates/latkit/shaders/lib/focus.wesl @@ -0,0 +1,42 @@ +// Selection and hover: one word of bits per row; and how present a row is while its mark eases. + +import package::lib::types::{SELECTED, HOVERED, FADE_IN, FADE_OUT}; +import package::lib::bind::{frame, focus, mark}; + +fn focus_of(row: u32) -> u32 { + if row >= mark.rows { + return 0u; + } + return focus[mark.focus + row]; +} + +fn is_selected(row: u32) -> bool { + return (focus_of(row) & SELECTED) != 0u; +} + +fn is_hovered(row: u32) -> bool { + return (focus_of(row) & HOVERED) != 0u; +} + +// How much of a row shows while its mark eases: rows appearing fade in, rows leaving fade out. +fn presence(flags: u32) -> f32 { + if (flags & FADE_IN) != 0u { + return mark.motion; + } + if (flags & FADE_OUT) != 0u { + return 1.0 - mark.motion; + } + return 1.0; +} + +// How large a row shows while its mark eases: rows appearing grow from nothing. Draws grow them, so +// a mark whose rows only appear evaluates once. +fn growth(flags: u32) -> f32 { + return select(1.0, mark.motion, (flags & FADE_IN) != 0u); +} + +// A row's opacity: rows outside a non-empty selection dim, and rows easing in or out fade. +fn faded(row: u32, flags: u32) -> f32 { + let dim = select(1.0, frame.dim, frame.selecting != 0u && !is_selected(row)); + return dim * presence(flags); +} diff --git a/crates/latkit/shaders/lib/label.wesl b/crates/latkit/shaders/lib/label.wesl new file mode 100644 index 00000000..0609e2ba --- /dev/null +++ b/crates/latkit/shaders/lib/label.wesl @@ -0,0 +1,143 @@ +// Labels: where a labeled row's text hangs, how large it draws, and whether it can show. Draws place +// every label from its anchor each frame, so labels follow the camera and the rows they name exactly; +// placement measures the same box only to decide which labels give way. Text is a distance field set +// at `TEXT_BASE`, drawn at any size: CSS pixels, or units in a diagram, where text scales with the +// sheet and fades out once too small to read. + +import package::lib::types::{ + POINTS, STROKES, MARKER_BLOCK, SIZED, GROUP, PATH_TRACE, PATH_GEOMETRY, TEXT_BASE, TEXT_SPREAD, HEADER_BAND, + SPACE_DIAGRAM, +}; +import package::lib::bind::{frame, eye, mark}; +import package::lib::project::{to_screen, clip_of}; +import package::lib::points::point; +import package::lib::path::{PATH, Segment, segment_screen, path_count}; +import package::lib::triangles::{triangle_corner, area_anchor}; + +// Where row `row`'s label hangs, CSS pixels, how it aligns to that point (0 left or top, 0.5 +// centered), the room it must fit in (none when zero), and whether its row shows. +struct Anchor { + at: vec2f, + align: vec2f, + room: vec2f, + shown: bool, +} + +// CSS pixels a size in length units spans this frame. +fn length_px(size: f32) -> f32 { + return size * frame.unit; +} + +fn anchor(row: u32) -> Anchor { + var a: Anchor; + switch mark.primitive { + case POINTS: { + let p = point(row); + a.shown = p.shown; + let center = to_screen(p.clip); + let text = length_px(mark.label_size); + if (mark.flags & GROUP) != 0u { + // A group's title sits in its header band, inset from the left. + let header = text * HEADER_BAND; + a.at = center + vec2f(-p.half.x + frame.group_padding, -p.half.y + 0.5 * header); + a.align = vec2f(0.0, 0.5); + a.room = vec2f(2.0 * (p.half.x - frame.group_padding), header); + } else if mark.marker == MARKER_BLOCK || (mark.flags & SIZED) != 0u { + // A block, or any marker given a width and height, holds its label while it fits. + a.at = center; + a.align = vec2f(0.5); + a.room = vec2f(2.0 * p.half.x - text, 2.0 * p.half.y); + } else { + a.at = center + vec2f(p.half.x + 0.4 * text, 0.0); + a.align = vec2f(0.0, 0.5); + } + } + case STROKES: { + let count = path_count(row); + // A trace labels its last sample; other paths their middle. + let last = PATH == PATH_TRACE; + let on = segment_screen(Segment(row, select(count / 2u, max(count, 1u) - 1u, last), 0.0)); + a.shown = count > 0u && on.shown; + if last { + a.at = on.b + vec2f(6.0, 0.0); + a.align = vec2f(0.0, 0.5); + } else { + a.at = 0.5 * (on.a + on.b); + a.align = vec2f(0.5); + } + } + default: { + a.align = vec2f(0.5); + if PATH == PATH_GEOMETRY { + // An area's label hangs inside its largest polygon, farthest from its edges. + let c = area_anchor(row); + let clip = clip_of(c.world); + a.shown = c.shown && c.ahead && clip.w > 0.0; + a.at = to_screen(clip); + return a; + } + var sum = vec2f(0.0); + a.shown = true; + for (var k = 0u; k < 3u; k++) { + let c = triangle_corner(row, k); + let clip = clip_of(c.world); + a.shown = a.shown && c.shown && c.ahead && clip.w > 0.0; + sum += to_screen(clip); + } + a.at = sum / 3.0; + } + } + return a; +} + +// How much text `px` CSS pixels tall shows: in a diagram it fades out as the view zooms away from +// it; elsewhere it is set at a size that reads. +fn legibility(px: f32) -> f32 { + if frame.space != SPACE_DIAGRAM { + return 1.0; + } + return smoothstep(3.5, 6.0, px); +} + +// A run of text placed on screen: the text's box and the quad around it, which reaches over the +// distance field's spread, in CSS pixels; its corners in the atlas, texels; and CSS pixels per +// texel. +struct Text { + lo: vec2f, + hi: vec2f, + quad_lo: vec2f, + quad_hi: vec2f, + uv_lo: vec2f, + uv_hi: vec2f, + scale: f32, +} + +// A rectangle's corner in the atlas: 16 bits of x, then 16 of y. +fn corner(word: u32) -> vec2f { + return vec2f(f32(word & 0xffffu), f32(word >> 16u)); +} + +// The run at atlas corners `uv0` and `uv1`, set `size` CSS pixels tall, hung at `at` by `align`. +fn text_at(uv0: u32, uv1: u32, size: f32, at: vec2f, align: vec2f) -> Text { + var t: Text; + t.uv_lo = corner(uv0); + t.uv_hi = corner(uv1); + t.scale = size / TEXT_BASE; + let pad = TEXT_SPREAD * t.scale; + let extent = max((t.uv_hi - t.uv_lo) * t.scale - 2.0 * pad, vec2f(0.0)); + t.lo = at - extent * align; + t.hi = t.lo + extent; + t.quad_lo = t.lo - pad; + t.quad_hi = t.hi + pad; + return t; +} + +// Whether text of extent `extent` fits `room`; no room holds any. +fn fits(extent: vec2f, room: vec2f) -> bool { + return room.x <= 0.0 || all(extent <= room); +} + +// Whether a box reaches into the view. +fn in_view(lo: vec2f, hi: vec2f) -> bool { + return all(hi > vec2f(0.0)) && all(lo < eye.size); +} diff --git a/crates/latkit/shaders/lib/lists.wesl b/crates/latkit/shaders/lib/lists.wesl new file mode 100644 index 00000000..4766eeb7 --- /dev/null +++ b/crates/latkit/shaders/lib/lists.wesl @@ -0,0 +1,37 @@ +// Lists: per-item counts, scanned in place to where each item's entries start, then the entries. + +import package::lib::types::{LIST_ITEMS, LIST_COUNTS, LIST_ENTRIES, LIST_DRAW, LIST_KEPT}; + +@if(lists) +@group(2) @binding(9) var lists: array; +@else +@group(2) @binding(9) var lists: array; + +// Where the counts of the list at `header` start. +fn list_counts(header: u32) -> u32 { + return lists[header + LIST_COUNTS]; +} + +// Where entry `i` of the list at `header` lies. +fn list_entry(header: u32, i: u32) -> u32 { + return lists[header + LIST_ENTRIES] + i; +} + +// Where item `i`'s entries start among those the list at `header` keeps: where it counted them, or, +// when the items counted more than the list keeps, as far in proportion, so every item keeps a share +// of its entries instead of the last items losing all of theirs. +fn list_start(header: u32, i: u32) -> u32 { + let counts = lists[header + LIST_COUNTS]; + let total = lists[counts + lists[header + LIST_ITEMS]]; + let kept = lists[header + LIST_KEPT]; + let start = lists[counts + i]; + if total <= kept { + return start; + } + return min(u32(f32(start) * (f32(kept) / f32(total))), kept); +} + +// Entries the list at `header` keeps. +fn list_total(header: u32) -> u32 { + return lists[header + LIST_DRAW + 1u]; +} diff --git a/crates/latkit/shaders/lib/mark.wesl b/crates/latkit/shaders/lib/mark.wesl new file mode 100644 index 00000000..c4125c45 --- /dev/null +++ b/crates/latkit/shaders/lib/mark.wesl @@ -0,0 +1,28 @@ +// What every mark's shaders share. + +import package::lib::bind::{eye, mark}; + +// A size in CSS pixels: state word `word` holds position units when the mark measures it in units. +fn px(size: f32, word: u32) -> f32 { + return select(size, size * eye.px_per_unit.x, (mark.units & (1u << word)) != 0u); +} + +// A marker's half, CSS pixels, scaled to keep its larger side within `range`: what a size in units +// keeps of its looks at any zoom. +fn within(half: vec2f, range: vec2f) -> vec2f { + let side = max(half.x, half.y); + if side <= 0.0 { + return half; + } + return half * (clamp(side, range.x, range.y) / side); +} + +// Coverage of a signed distance `d` in CSS pixels, antialiased over a target pixel. +fn coverage(d: f32) -> f32 { + return clamp(0.5 - d * eye.pixel_ratio, 0.0, 1.0); +} + +// CSS pixels a quad reaches past the shape it draws: one target pixel, over which its edge fades. +fn fringe() -> f32 { + return 1.0 / eye.pixel_ratio; +} diff --git a/crates/latkit/shaders/lib/marker.wesl b/crates/latkit/shaders/lib/marker.wesl new file mode 100644 index 00000000..127321af --- /dev/null +++ b/crates/latkit/shaders/lib/marker.wesl @@ -0,0 +1,147 @@ +// Markers are signed distance fields in CSS pixels; a custom marker supplies `fn marker`. + +import package::lib::types::{ + SELECTED, HOVERED, SHAPE_RECTANGLE, SHAPE_ROUNDED, SHAPE_DIAMOND, MARKER_GAUGE, MARKER_PIE, MARKER_BLOCK, + LABELED, HEADER_BAND, THEME_TEXT, +}; +import package::lib::bind::{frame, eye, mark, program}; +import package::lib::mark::coverage; +import package::lib::project::TAU; + +struct MarkerColor { + color: vec4f, + distance: f32, +} + +struct MarkerFragment { + // The pixel's offset from the vertex, CSS pixels, y up. + p: vec2f, + // Half the marker's width and height. + half: vec2f, + color: vec4f, + input: array, +} + +fn box_distance(p: vec2f, half: vec2f, corner: f32) -> f32 { + let d = abs(p) - half + corner; + return length(max(d, vec2f(0.0))) + min(max(d.x, d.y), 0.0) - corner; +} + +fn shape_distance(shape: u32, p: vec2f, half: vec2f) -> f32 { + switch shape { + case SHAPE_RECTANGLE: { return box_distance(p, half, 0.0); } + case SHAPE_ROUNDED: { return box_distance(p, half, 0.3 * min(half.x, half.y)); } + case SHAPE_DIAMOND: { return (abs(p.x) / half.x + abs(p.y) / half.y - 1.0) * min(half.x, half.y) * 0.7071; } + default: { return (length(p / half) - 1.0) * min(half.x, half.y); } + } +} + +// The outline a marker's distance is measured from: blocks are rounded boxes, others their shape. +fn outline_distance(p: vec2f, half: vec2f) -> f32 { + if mark.marker == MARKER_BLOCK { + return box_distance(p, half, min(mark.corner, min(half.x, half.y))); + } + return shape_distance(mark.shape, p, half); +} + +// The theme's text color: what borders and ports mix toward, so they read on light and dark grounds. +fn theme_text() -> vec3f { + return unpack4x8unorm(frame.theme[THEME_TEXT / 4u][THEME_TEXT % 4u]).rgb; +} + +// `color` covering where `distance` is negative, antialiased over a pixel. +fn filled(color: vec4f, distance: f32) -> MarkerColor { + return MarkerColor(vec4f(color.rgb, color.a * coverage(distance)), distance); +} + +// `top` over `bottom`. +fn over(top: MarkerColor, bottom: MarkerColor) -> MarkerColor { + let a = top.color.a + bottom.color.a * (1.0 - top.color.a); + let rgb = (top.color.rgb * top.color.a + bottom.color.rgb * bottom.color.a * (1.0 - top.color.a)) / max(a, 1e-6); + return MarkerColor(vec4f(rgb, a), min(top.distance, bottom.distance)); +} + +fn gauge(p: vec2f, half: vec2f, color: vec4f, shape: u32, fill: f32) -> MarkerColor { + let ring = filled(color, abs(shape_distance(shape, p, half)) - 1.0); + let f = clamp(fill, 0.0, 1.0); + let inner = shape_distance(shape, p, half - 2.5); + let around = (fract(atan2(p.x, p.y) / TAU + 1.0) - f) * half.x * TAU; + let cut = select(p.y - mix(-half.y, half.y, f), around, shape == 0u); + return over(ring, filled(color, max(inner, cut))); +} + +// A pie's slice colors are the mark's palette. +fn slice_color(i: u32) -> vec4f { + return unpack4x8unorm(program[mark.palette + i]); +} + +fn pie(p: vec2f, radius: f32, slices: array, count: u32, hole: f32) -> MarkerColor { + var total = 0.0; + for (var i = 0u; i < count; i++) { + total += max(slices[i], 0.0); + } + let angle = fract(atan2(p.x, p.y) / TAU + 1.0) * total; + var start = 0.0; + var color = slice_color(0u); + for (var i = 0u; i < count; i++) { + let end = start + max(slices[i], 0.0); + color = select(color, slice_color(i), angle >= start && angle < end); + start = end; + } + let d = length(p); + return filled(color, max(d - radius, radius * hole - d)); +} + +fn builtin_marker(f: MarkerFragment) -> MarkerColor { + switch mark.marker { + case MARKER_GAUGE: { return gauge(f.p, f.half, f.color, mark.shape, f.input[0]); } + case MARKER_PIE: { return pie(f.p, min(f.half.x, f.half.y), f.input, mark.inputs, mark.hole); } + default: { return filled(f.color, outline_distance(f.p, f.half)); } + } +} + +// A group's container: a rounded box filled in its color, tinted a step toward the text color for +// each group holding it; a header band across its top where its title sits; and a hairline border. +fn container(f: MarkerFragment, depth: f32) -> MarkerColor { + let text = theme_text(); + let fill = mix(f.color.rgb, text, min(0.06 * depth, 0.3)); + let d = box_distance(f.p, f.half, min(6.0 * frame.unit, 0.2 * min(f.half.x, f.half.y))); + var body = filled(vec4f(fill, f.color.a), d); + if (mark.flags & LABELED) != 0u { + // y is up in a marker: the header band runs down from its top. + let header = mark.label_size * frame.unit * HEADER_BAND; + let band = max(d, (f.half.y - header) - f.p.y); + body = over(filled(vec4f(mix(fill, text, 0.07), f.color.a), band), body); + } + let hairline = 0.5 / eye.pixel_ratio; + let border = filled(vec4f(mix(fill, text, 0.4), f.color.a), abs(d + hairline) - hairline); + return MarkerColor(over(border, body).color, d); +} + +// A ring of the status color just outside the marker's outline. +fn status_ring(m: MarkerColor, p: vec2f, half: vec2f, status: vec4f) -> MarkerColor { + let d = outline_distance(p, half); + return over(filled(status, abs(d - 1.5) - 1.25), m); +} + +// `m` premultiplied. +fn premultiplied(m: MarkerColor) -> vec4f { + return vec4f(m.color.rgb * m.color.a, m.color.a); +} + +// A premultiplied color with the glow of focus bits `focus` around its shape: the selection's, the +// hover's, or for the end of a lit edge the hover's, fainter. +fn glow(m: MarkerColor, focus: u32) -> vec4f { + let base = premultiplied(m); + if focus == 0u || frame.glow <= 0.0 { + return base; + } + let own = vec4f(m.color.rgb, frame.selected.a); + let selected = select(frame.selected, own, frame.selected.r < 0.0); + var tint = select(frame.hover, selected, (focus & SELECTED) != 0u); + if (focus & (SELECTED | HOVERED)) == 0u { + tint.a *= 0.55; + } + let halo = tint.a * (1.0 - smoothstep(0.0, frame.glow, max(m.distance, 0.0))); + return base + vec4f(tint.rgb * halo, halo) * (1.0 - base.a); +} diff --git a/crates/latkit/shaders/lib/path.wesl b/crates/latkit/shaders/lib/path.wesl new file mode 100644 index 00000000..e9d59f00 --- /dev/null +++ b/crates/latkit/shaders/lib/path.wesl @@ -0,0 +1,496 @@ +// Paths: the segments a stroke draws, whatever mark it belongs to. A row's path runs between an +// edge's ends (straight, through the bends of a geometry column, or along the great circle on the +// earth, bowed into its lane), through a line's samples across the axis, or through a geometry +// column's points: a route a diagram's sheet worked out, or a path field. Draws, casts, probes, bounds, and labels all read a +// segment through `segment_ends` and `segment_screen`. Which path a pipeline reads is its `PATH`, so +// each compiles one kind of path. + +import package::lib::types::{ + NONE, VISIBLE, PLACED, DASH, ENDS_COLOR, GEODESIC, STEP_BEFORE, STEP_AFTER, MARK_EDGES, PATH_ENDS, PATH_TRACE, + PATH_GEOMETRY, PATH_POLES, EDGE_WIDTH, LINE_WIDTH, GEODESIC_STEP, OWN_HEIGHT, TRIANGLES, MAX_PIECES, BOW_PIECES, SPACE_EARTH, +}; +import package::lib::bind::{frame, eye, mark, focused}; +import package::lib::state::{row_at, edge_at, line_at, vertex_slot, Vertex}; +import package::lib::project::{PI, world, clip_of, shows, to_screen}; +import package::lib::read::{missing_bits, column_value, points_of, point_bits}; +import package::lib::trace::{trace_run, trace_level, trace_axis, trace_entry}; +import package::lib::focus::{faded, growth}; +import package::lib::mark::px; +import package::lib::points::vertex_half; +import package::lib::lists::{lists, list_entry, list_start, list_total}; + +// The path a pipeline's strokes read: one of the `PATH_` codes, fixed when the pipeline is made. +override PATH: u32 = PATH_ENDS; + +// One segment of a row's path, and how far along the path it starts, in length units: position +// units, degrees on the earth. A list keeps each segment's distance along; a row of one segment +// starts at 0. +struct Segment { + row: u32, + index: u32, + along: f32, +} + +// A point a path runs through: where it stands (position units as high and low parts, elevation), +// in world units and in position units, its color, and whether it is shown. Sources set where it +// stands; `path_point` places it in the world once. +struct PathPoint { + hi: vec2f, + lo: vec2f, + z: f32, + world: vec3f, + position: vec3f, + color: vec4f, + // A vertex's half size in CSS pixels, a box when it has its own height; zero elsewhere. + half: vec2f, + boxed: bool, + // Whether it has a place to stand, and whether it lies in front of the globe's horizon. + shown: bool, + ahead: bool, +} + +// How a row's path is stroked: its comets' flow, and how far they traveled. +struct Style { + width: f32, + color: vec4f, + flow: f32, + travel: f32, + dash: bool, + shown: bool, +} + +// A segment on screen: its ends as points, in CSS pixels, and in clip space, whether it shows, and +// the part of it drawn, as fractions of it: cut at the near plane, and stopping short of the vertices +// its ends meet. +struct OnScreen { + ends: array, + a: vec2f, + b: vec2f, + ca: vec4f, + cb: vec4f, + shown: bool, + kept: vec2f, +} + +// The segment drawn as instance `instance`: a fixed number per row, or numbered by the mark's list, +// whose entries are each segment's row and distance along. +@if(!focused) +fn segment(instance: u32) -> Segment { + if mark.per_row != NONE { + let per = max(mark.per_row, 1u); + return Segment(instance / per, instance % per, 0.0); + } + let entry = list_entry(mark.list, 2u * instance); + let row = lists[entry]; + return Segment(row, instance - list_start(mark.list, row), bitcast(lists[entry + 1u])); +} + +// In the focus draw, piece `instance % mark.pieces` of the lit row `instance / mark.pieces`, as far +// along as its list keeps it; pieces past the row's own end draw nothing. +@if(focused) +fn segment(instance: u32) -> Segment { + let pieces = max(mark.pieces, 1u); + let row = focused[mark.focused + instance / pieces]; + let index = instance % pieces; + var along = 0.0; + if mark.per_row == NONE && row < mark.rows && index < path_count(row) { + along = bitcast(lists[list_entry(mark.list, 2u * (list_start(mark.list, row) + index)) + 1u]); + } + return Segment(row, index, along); +} + +// Length units between two points of a path: what a segment adds to the distance along it. +fn path_length(a: PathPoint, b: PathPoint) -> f32 { + return length(b.position.xy - a.position.xy); +} + +// CSS pixels a length unit spans where the camera looks: a degree's on the earth. +fn px_per_length() -> f32 { + return eye.px_per_unit.x * select(1.0, PI / 180.0, frame.space == SPACE_EARTH); +} + +// Segments of every live row's path. +fn stroke_instances() -> u32 { + if mark.per_row != NONE { + return mark.rows * mark.per_row; + } + return list_total(mark.list); +} + +// Segments in row `row`'s path, as drawn. +fn path_count(row: u32) -> u32 { + if mark.per_row != NONE { + return mark.per_row; + } + return list_start(mark.list, row + 1u) - list_start(mark.list, row); +} + +// Segments a geodesic from `a` to `b` takes: one per few degrees of arc. +fn arcs(a: vec2f, b: vec2f) -> u32 { + let p = radians(a); + let q = radians(b); + let d = 2.0 * asin(min(1.0, sqrt(pow(sin(0.5 * (q.y - p.y)), 2.0) + cos(p.y) * cos(q.y) * pow(sin(0.5 * (q.x - p.x)), 2.0)))); + return clamp(u32(ceil(degrees(d) / GEODESIC_STEP)), 1u, MAX_PIECES); +} + +// Points the geometry column gives row `row`: an edge's bends, or a whole path. +fn geometry_count(row: u32) -> u32 { + if row >= mark.rows { + return 0u; + } + return points_of(mark.geometry, row).count; +} + +// Segments row `row`'s path has, or for an area its triangles: the count a list over the mark's rows +// counts. A path between two ends without bends runs in one piece, or bowed into a lane in enough +// for the curve, and along a great circle in one per few degrees of its arc. +fn row_segments(row: u32) -> u32 { + switch PATH { + case PATH_ENDS: { + let middle = geometry_count(row); + if middle > 0u { + return middle + 1u; + } + let pieces = select(1u, BOW_PIECES, lane(row) != 0.0); + if (mark.flags & GEODESIC) == 0u { + return pieces; + } + let e = edge_at(row_at(row)); + if e.a == NONE || e.b == NONE { + return 0u; + } + let a = vertex_slot(e.a); + let b = vertex_slot(e.b); + return max(pieces, arcs(a.hi + a.lo, b.hi + b.lo)); + } + case PATH_GEOMETRY: { + let count = geometry_count(row); + if mark.primitive == TRIANGLES { + // An area's triangles follow the point its label hangs from, three points each. + return select(0u, (count - 1u) / 3u, count > 0u); + } + return max(count, 1u) - 1u; + } + default: { + return mark.per_row; + } + } +} + +// The vertex in slot `slot` as a point of a path, placed. +fn vertex_point(slot: u32) -> PathPoint { + let v = vertex_slot(slot); + var p: PathPoint; + p.hi = v.hi; + p.lo = v.lo; + p.z = v.elevation; + p.color = unpack4x8unorm(v.color); + p.half = vertex_half(v); + p.boxed = (v.flags & OWN_HEIGHT) != 0u; + p.shown = (v.flags & PLACED) != 0u; + return placed_point(p); +} + +// CSS pixels from a vertex's middle to its outline along `dir`: a box's or a circle's. +fn outline(p: PathPoint, dir: vec2f) -> f32 { + if p.boxed { + return min(p.half.x / max(abs(dir.x), 1e-6), p.half.y / max(abs(dir.y), 1e-6)); + } + return p.half.x; +} + +fn hidden() -> PathPoint { + var p: PathPoint; + p.shown = false; + return p; +} + +// A point at `xy` (position units) and elevation `z`. +fn position_point(xy: vec2f, z: f32, color: vec4f) -> PathPoint { + var p: PathPoint; + p.hi = xy; + p.z = z; + p.color = color; + p.shown = true; + return p; +} + +// `p` placed in the world. +fn placed_point(p: PathPoint) -> PathPoint { + var out = p; + out.world = world(p.hi, p.lo, p.z); + out.position = vec3f(p.hi + p.lo, p.z); + out.ahead = shows(out.world); + return out; +} + +// The point a fraction `t` of the way along the great circle from `a` to `b`, in degrees, set off to +// the left by `bow` of the arc's length. +fn along_circle(a: vec2f, b: vec2f, t: f32, bow: f32) -> vec2f { + let p = radians(a); + let q = radians(b); + let u = vec3f(cos(p.y) * cos(p.x), cos(p.y) * sin(p.x), sin(p.y)); + let v = vec3f(cos(q.y) * cos(q.x), cos(q.y) * sin(q.x), sin(q.y)); + // Half the chord's angle, which stays precise for the shortest arcs. + let angle = 2.0 * asin(min(1.0, 0.5 * length(v - u))); + var w = mix(u, v, t); + if angle > 1e-5 { + w = (sin((1.0 - t) * angle) * u + sin(t * angle) * v) / sin(angle); + w = normalize(w + normalize(cross(u, v)) * bow * angle); + } + var lon = degrees(atan2(w.y, w.x)); + // Keep the longitude on the side `a` is on, so the path does not jump across the antimeridian. + lon += 360.0 * round((a.x - lon) / 360.0); + return vec2f(lon, degrees(asin(clamp(w.z, -1.0, 1.0)))); +} + +// The point a fraction `t` of the way from vertex `a` to `b`, set off to the left by `bow` of the +// length between them: along the great circle on the earth, else straight from `a`'s high and low +// parts, so it keeps their precision. +fn between(a: Vertex, b: Vertex, t: f32, bow: f32) -> PathPoint { + var p: PathPoint; + p.z = mix(a.elevation, b.elevation, t); + if (mark.flags & GEODESIC) != 0u { + p.hi = along_circle(a.hi + a.lo, b.hi + b.lo, t, bow); + return p; + } + let d = (b.hi - a.hi) + (b.lo - a.lo); + p.hi = a.hi; + p.lo = a.lo + d * t + vec2f(-d.y, d.x) * bow; + return p; +} + +// Point `i` of an edge's path, placed: its first end, its bends, then its second end. Without bends, +// it runs between its ends in as many pieces as its list kept for it, each lane bowing in world units +// so the camera never moves it. An end reads only its own vertex. Each kind of point is made in one +// place, so shaders compile small. +fn end_point(row: u32, i: u32) -> PathPoint { + let e = edge_at(row_at(row)); + if e.a == NONE || e.b == NONE || e.a == e.b { + return hidden(); + } + let bends = points_of(mark.geometry, row); + let last = select(bends.count + 1u, path_count(row), bends.count == 0u); + if i == 0u || i >= last { + return vertex_point(select(e.b, e.a, i == 0u)); + } + let a = vertex_slot(e.a); + let b = vertex_slot(e.b); + let t = f32(i) / f32(last); + var p: PathPoint; + if bends.count == 0u { + p = between(a, b, t, lane(row) * frame.lane_bow * 4.0 * t * (1.0 - t)); + } else { + let w = point_bits(bends, i - 1u); + if missing_bits(w.x) || missing_bits(w.y) { + return hidden(); + } + p.hi = vec2f(bitcast(w.x), bitcast(w.y)); + } + p.color = mix(unpack4x8unorm(a.color), unpack4x8unorm(b.color), t); + p.shown = (a.flags & PLACED) != 0u && (b.flags & PLACED) != 0u; + return placed_point(p); +} + +// Point `k` of a trace: in a run of buckets, each bucket's least and greatest value at its middle; in +// a run of frames, each frame's value, or with steps the corners between them. A point past its run's +// own breaks the line before the next run. +fn trace_point(row: u32, k: u32) -> PathPoint { + let run = trace_run(k); + let local = k - run.point; + var value = 0u; + var entry = 0u; + if trace_level(run.slot) > 0u { + if local >= 2u * run.entries { + return hidden(); + } + entry = run.first + local / 2u; + value = trace_entry(row, run.slot, entry, local % 2u); + } else { + var across = local; + var up = local; + var count = run.entries; + if (mark.flags & STEP_AFTER) != 0u { + across = (local + 1u) / 2u; + up = local / 2u; + count = 2u * run.entries - 1u; + } else if (mark.flags & STEP_BEFORE) != 0u { + across = local / 2u; + up = (local + 1u) / 2u; + count = 2u * run.entries - 1u; + } + if local >= count { + return hidden(); + } + entry = run.first + across; + value = trace_entry(row, run.slot, run.first + up, 0u); + } + if missing_bits(value) { + return hidden(); + } + let x = trace_axis(run.slot, entry); + var p: PathPoint; + p.hi = vec2f(x.x, bitcast(value)); + p.lo = vec2f(x.y, 0.0); + p.color = vec4f(1.0); + p.shown = true; + return p; +} + +// Point `i` of a geometry column's path: polylines whose parts are broken by a missing point. While +// the mark eases, each point moves from the path it ran through when the transition began: point +// for point when both have as many, else from the old point at the same fraction along. +fn geometry_point(row: u32, i: u32) -> PathPoint { + let now = points_of(mark.geometry, row); + if i >= now.count { + return hidden(); + } + let w = point_bits(now, i); + if missing_bits(w.x) || missing_bits(w.y) { + return hidden(); + } + var xy = vec2f(bitcast(w.x), bitcast(w.y)); + if mark.frozen != NONE && mark.frozen_geometry != NONE && now.count > 0u { + let was = points_of(mark.frozen_geometry, row); + if was.count > 0u { + let along = f32(i) * f32(was.count - 1u) / f32(max(now.count, 2u) - 1u); + let k = select(u32(round(along)), i, was.count == now.count); + let o = point_bits(was, min(k, was.count - 1u)); + if !missing_bits(o.x) && !missing_bits(o.y) { + xy = mix(vec2f(bitcast(o.x), bitcast(o.y)), xy, mark.motion); + } + } + } + return position_point(xy, 0.0, vec4f(1.0)); +} + +// Point `i` of a pole: the row's own vertex where it stands, then the ground beneath it. +fn pole_point(row: u32, i: u32) -> PathPoint { + let e = edge_at(row_at(row)); + if e.a == NONE { + return hidden(); + } + var p = vertex_point(e.a); + if i > 0u { + p.z = 0.0; + p.half = vec2f(0.0); + p = placed_point(p); + } + return p; +} + +// Point `i` of row `row`'s path, whatever it runs through, placed in the world. +fn path_point(row: u32, i: u32) -> PathPoint { + switch PATH { + case PATH_ENDS: { return end_point(row, i); } + case PATH_TRACE: { return placed_point(trace_point(row, i)); } + case PATH_GEOMETRY: { return placed_point(geometry_point(row, i)); } + case PATH_POLES: { return pole_point(row, i); } + default: { return hidden(); } + } +} + +// The two points segment `s` runs between: points `index` and `index + 1` of its row's path. One loop +// makes both, so the path is compiled once. +fn segment_ends(s: Segment) -> array { + var ends: array; + for (var e = 0u; e < 2u; e++) { + ends[e] = path_point(s.row, s.index + e); + } + return ends; +} + +// Whether segment `s` ends a part of its row's path: the path's last, or one before a break. +fn ends_part(s: Segment) -> bool { + if PATH == PATH_GEOMETRY { + let points = points_of(mark.geometry, s.row); + let next = s.index + 2u; + return next >= points.count || missing_bits(point_bits(points, next).x); + } + return s.index + 1u == path_count(s.row); +} + +// Lanes from the middle that row `row` runs in among edges joining the same two vertices. +fn lane(row: u32) -> f32 { + if mark.lane == NONE || row >= mark.rows { + return 0.0; + } + let bits = column_value(mark.lane, row).x; + return select(bitcast(bits), 0.0, missing_bits(bits)); +} + +// The part of the segment from clip position `ca` to `cb` in front of the near plane, as fractions +// along it. Depth is reversed, so a position lies in front where z <= w, and w - z runs linearly along +// the segment: one reaching behind the eye is cut where it crosses, not dropped. Empty where both ends +// lie behind. +fn in_front(ca: vec4f, cb: vec4f) -> vec2f { + let da = ca.w - ca.z; + let db = cb.w - cb.z; + let t = da / (da - db); + return vec2f(select(0.0, t, da < 0.0), select(1.0, t, db < 0.0)); +} + +// Segment `s` on screen: the part in front of the near plane, `kept` saying which part of it shows. +fn segment_screen(s: Segment) -> OnScreen { + let ends = segment_ends(s); + var out: OnScreen; + out.ends = ends; + let ca = clip_of(ends[0].world); + let cb = clip_of(ends[1].world); + let cut = in_front(ca, cb); + // A segment reaching past the globe's edge draws, and the globe's depth cuts it there. + let ahead = ends[0].ahead || ends[1].ahead; + out.shown = ends[0].shown && ends[1].shown && ahead && cut.x < cut.y; + out.ca = mix(ca, cb, cut.x); + out.cb = mix(ca, cb, cut.y); + out.a = to_screen(out.ca); + out.b = to_screen(out.cb); + out.kept = cut; + // Strokes stop at the outlines of the vertices they end at, without passing each other; an end + // cut at the near plane has no vertex there. + let along = out.b - out.a; + let length_along = length(along); + if length_along > 1e-3 { + let dir = along / length_along; + let room = 0.5 * length_along; + let outlines = vec2f(select(outline(ends[0], dir), 0.0, cut.x > 0.0), select(outline(ends[1], dir), 0.0, cut.y < 1.0)); + let short = min(outlines, vec2f(room)); + out.a += dir * short.x; + out.b -= dir * short.y; + out.kept = mix(vec2f(cut.x), vec2f(cut.y), vec2f(short.x, length_along - short.y) / length_along); + } + return out; +} + +// How row `row`'s path is stroked: never thinner than a hairline. Its comets' flow and travel are in +// the lengths the theme's flow measures them in. +fn stroke_style(row: u32) -> Style { + var s: Style; + if mark.kind == MARK_EDGES { + let e = edge_at(row_at(row)); + s.width = clamp(px(e.width, EDGE_WIDTH), mark.size_min, mark.size_max) * growth(e.flags); + // An edge colored by its ends takes their colors where it draws; this only fades it. + s.color = select(unpack4x8unorm(e.color), vec4f(1.0), ends_colored()); + s.color.a *= faded(row, e.flags); + s.flow = e.flow; + s.travel = e.travel; + s.dash = (e.flags & DASH) != 0u; + s.shown = (e.flags & VISIBLE) != 0u; + } else { + let l = line_at(row_at(row)); + s.width = clamp(px(l.width, LINE_WIDTH), mark.size_min, mark.size_max) * growth(l.flags); + s.color = unpack4x8unorm(l.color); + s.color.a *= faded(row, l.flags); + s.flow = l.flow; + s.travel = l.travel; + s.dash = (l.flags & DASH) != 0u; + s.shown = (l.flags & VISIBLE) != 0u; + } + s.width = max(s.width, 0.75); + return s; +} + +// Whether a stroke's color blends its ends' colors. +fn ends_colored() -> bool { + return mark.kind == MARK_EDGES && (mark.flags & ENDS_COLOR) != 0u; +} diff --git a/crates/latkit/shaders/lib/points.wesl b/crates/latkit/shaders/lib/points.wesl new file mode 100644 index 00000000..ca6d5980 --- /dev/null +++ b/crates/latkit/shaders/lib/points.wesl @@ -0,0 +1,121 @@ +// Points: where a vertex row's marker stands, how large, and in what color. Draws, casts, probes, +// bounds, and labels all read a point through `point`. + +import package::lib::types::{ + NONE, VISIBLE, PLACED, SIZED, STATUS, HOVERED, VERTEX_HALF, VERTEX_WORDS, SIDE_LEFT, SIDE_RIGHT, SIDE_TOP, + PORT_WORDS, PORT_CODE, PORT_SHAPE, PORT_COLUMN, PORT_SIZE, HALF_UNITS, OWN_HEIGHT, +}; +import package::lib::bind::{frame, eye, mark, program}; +import package::lib::state::{vertex_slot, Vertex}; +import package::lib::project::{world, clip_of, shows, to_screen}; +import package::lib::focus::{focus_of, faded, growth}; +import package::lib::read::bits_value; +import package::lib::mark::{px, fringe, within}; + +struct Point { + clip: vec4f, + world: vec3f, + // Where it stands, in position units. + position: vec2f, + // Half the marker's width and height, CSS pixels. + half: vec2f, + color: vec4f, + status: vec4f, + depth: f32, + row: u32, + // Its focus bits: selected, hovered, an end of a lit edge. + focus: u32, + shown: bool, +} + +fn placed(v: Vertex) -> bool { + return (v.flags & PLACED) != 0u; +} + +// The marker of row `row` of the current vertex mark. A hovered marker sized in pixels grows; one +// sized in units is part of the drawing, and only glows. +fn point(row: u32) -> Point { + let v = vertex_slot(mark.state / VERTEX_WORDS + row); + var half = vec2f(px(v.half.x, VERTEX_HALF)); + if (mark.flags & SIZED) != 0u { + half.y = px(v.half.y, VERTEX_HALF + 1u); + } + half = within(half, vec2f(mark.size_min, mark.size_max)); + let focus = focus_of(row); + let grows = (mark.units & (1u << VERTEX_HALF)) == 0u && (focus & HOVERED) != 0u; + half *= select(1.0, frame.hover_scale, grows) * growth(v.flags); + let color = unpack4x8unorm(v.color); + var p: Point; + p.world = world(v.hi, v.lo, v.elevation); + p.position = v.hi + v.lo; + p.clip = clip_of(p.world); + p.half = max(half, vec2f(0.0)); + p.color = vec4f(color.rgb, color.a * faded(row, v.flags)); + p.status = unpack4x8unorm(v.status); + p.depth = v.depth; + p.row = row; + p.focus = focus; + p.shown = (v.flags & VISIBLE) != 0u && placed(v) && shows(p.world) && p.clip.w > 0.0; + return p; +} + +// Half the marker of the vertex in any slot, CSS pixels: its flags say whether its size is in +// position units and whether it has its own height. +fn vertex_half(v: Vertex) -> vec2f { + var half = vec2f(v.half.x, select(v.half.x, v.half.y, (v.flags & OWN_HEIGHT) != 0u)); + if (v.flags & HALF_UNITS) != 0u { + half *= eye.px_per_unit.x; + } + return within(half, v.range); +} + +// Where a port sits on a marker of half size `half`, CSS pixels from its center, y down: its side in +// the code's low two bits, then its place among the ports on that side and how many share it. +fn port_place(half: vec2f, code: u32) -> vec2f { + let along = (f32((code >> 2u) & 255u) + 1.0) / (f32((code >> 10u) & 255u) + 1.0) * 2.0 - 1.0; + switch code & 3u { + case SIDE_LEFT: { return vec2f(-half.x, along * half.y); } + case SIDE_RIGHT: { return vec2f(half.x, along * half.y); } + case SIDE_TOP: { return vec2f(along * half.x, -half.y); } + default: { return vec2f(along * half.x, half.y); } + } +} + +// The way into a marker from a port on its side, y down. +fn port_inward(code: u32) -> vec2f { + switch code & 3u { + case SIDE_LEFT: { return vec2f(1.0, 0.0); } + case SIDE_RIGHT: { return vec2f(-1.0, 0.0); } + case SIDE_TOP: { return vec2f(0.0, 1.0); } + default: { return vec2f(0.0, -1.0); } + } +} + +struct Port { + center: vec2f, + // Half its size, CSS pixels: never past a quarter of its marker's shorter side, so a small + // marker still shows under its ports. + half: f32, + shape: u32, + code: u32, + // Whether its reference names a net: a free port draws hollow. + wired: bool, +} + +// Port `k` of the current vertex mark on point `p`'s marker, on screen. +fn port_at(p: Point, k: u32) -> Port { + let info = mark.port_info + k * PORT_WORDS; + let code = program[info + PORT_CODE]; + let center = to_screen(p.clip) + port_place(p.half, code); + let half = min(0.5 * PORT_SIZE * frame.unit, 0.5 * min(p.half.x, p.half.y)); + let column = program[info + PORT_COLUMN]; + let wired = column != NONE && bits_value(column, p.row) != NONE; + return Port(center, half, program[info + PORT_SHAPE], code, wired); +} + +// CSS pixels a point's quad reaches past its center: the marker, its status ring when it has one, a +// target pixel of edge, and when `lit`, as the focus draw draws it, its glow. +fn reach(p: Point, lit: bool) -> vec2f { + let ring = select(0.0, 3.0, (mark.flags & STATUS) != 0u && p.status.a > 0.0); + return p.half + ring + select(0.0, frame.glow, lit) + fringe(); +} diff --git a/crates/latkit/shaders/lib/project.wesl b/crates/latkit/shaders/lib/project.wesl new file mode 100644 index 00000000..fc7b3ed3 --- /dev/null +++ b/crates/latkit/shaders/lib/project.wesl @@ -0,0 +1,106 @@ +// From positions to the screen. Positions are (high, low) pairs: their difference from the camera's +// center is taken in parts, so f64 data keeps its precision at any zoom. Every pass projects through +// its eye: the view, the light that casts shadows, or an exported image. + +import package::lib::types::{SPACE_EARTH}; +import package::lib::bind::{frame, eye}; + +const PI: f32 = 3.14159265; +const TAU: f32 = 6.28318531; +const MAX_LATITUDE: f32 = 85.05113; +// Depth is reversed: the near plane is at 1 and the far plane at 0, which keeps precision far away. +const NEAR_Z: f32 = 1.0; +const FAR_Z: f32 = 0.0; + +// The offset of `p` from the camera's center, in position units. +fn relative(hi: vec2f, lo: vec2f) -> vec2f { + return (hi - frame.center_hi) + (lo - frame.center_lo); +} + +fn mercator_y(latitude: f32) -> f32 { + let lat = radians(clamp(latitude, -MAX_LATITUDE, MAX_LATITUDE)); + return log(tan(PI / 4.0 + lat / 2.0)); +} + +// Web mercator radians from the center; near the center, a local expansion keeps precision. +fn mercator(hi: vec2f, lo: vec2f) -> vec2f { + let d = relative(hi, lo); + let lat = clamp(hi.y + lo.y, -MAX_LATITUDE, MAX_LATITUDE); + let near = radians(d.y) / cos(radians(lat - 0.5 * d.y)); + let far = mercator_y(lat) - frame.mercator_y; + return vec2f(radians(d.x), select(far, near, abs(d.y) < 0.25)); +} + +// `p` on the unit sphere, turned so the camera's center faces +z. +fn on_sphere(hi: vec2f, lo: vec2f) -> vec3f { + let lon = radians(relative(hi, lo).x); + let lat = radians(clamp(hi.y + lo.y, -90.0, 90.0)); + let lat0 = radians(frame.center_hi.y + frame.center_lo.y); + let v = vec3f(cos(lat) * sin(lon), sin(lat), cos(lat) * cos(lon)); + return vec3f(v.x, v.y * cos(lat0) - v.z * sin(lat0), v.y * sin(lat0) + v.z * cos(lat0)); +} + +// World coordinates: plane or plot units, or mercator radians morphing onto the globe. Only the +// morph works out both. +fn world(hi: vec2f, lo: vec2f, z: f32) -> vec3f { + if frame.space != SPACE_EARTH { + return vec3f(relative(hi, lo), z); + } + if frame.globe <= 0.0 { + return vec3f(mercator(hi, lo), z); + } + let lat0 = radians(frame.center_hi.y + frame.center_lo.y); + let s = on_sphere(hi, lo) * (1.0 + z); + let round = vec3f(s.xy, s.z - 1.0) / cos(lat0); + if frame.globe >= 1.0 { + return round; + } + return mix(vec3f(mercator(hi, lo), z), round, frame.globe); +} + +fn clip_of(w: vec3f) -> vec4f { + return eye.clip_from_world * vec4f(w, 1.0); +} + +fn project(hi: vec2f, lo: vec2f, z: f32) -> vec4f { + return clip_of(world(hi, lo, z)); +} + +// The globe's center in world units: a sphere of radius `-center.z` whose top touches the ground at +// the camera's center. +fn globe_center() -> vec3f { + return vec3f(0.0, 0.0, -1.0 / cos(radians(frame.center_hi.y + frame.center_lo.y))); +} + +// Whether world point `w` shows past the globe: on the round globe, whether it lies in front of the +// plane the eye sees the globe's edge on, exactly, at any pitch. On the map, or while the globe +// morphs, everything shows, and what the ground hides is left to its depth. +fn shows(w: vec3f) -> bool { + if frame.space != SPACE_EARTH || frame.globe < 1.0 { + return true; + } + let c = globe_center(); + return dot(w - c, eye.position.xyz - w) > 0.0; +} + +// CSS pixels from the top left. +fn to_screen(clip: vec4f) -> vec2f { + let ndc = clip.xy / clip.w; + return (vec2f(ndc.x, -ndc.y) * 0.5 + 0.5) * eye.size; +} + +// Clip coordinates for a screen point at the depth of `at`. +fn to_clip(screen: vec2f, at: vec4f) -> vec4f { + let ndc = screen / eye.size * 2.0 - 1.0; + return vec4f(vec2f(ndc.x, -ndc.y) * at.w, at.z, at.w); +} + +// `clip` a little toward the camera, so a mark lying on a face draws over it. +fn nearer(clip: vec4f) -> vec4f { + return vec4f(clip.xy, min(clip.z * 1.003, clip.w), clip.w); +} + +// A position outside the clip volume: the primitive is dropped. +fn culled() -> vec4f { + return vec4f(2.0, 2.0, 2.0, 1.0); +} diff --git a/crates/latkit/shaders/lib/read.wesl b/crates/latkit/shaders/lib/read.wesl new file mode 100644 index 00000000..6b6d32aa --- /dev/null +++ b/crates/latkit/shaders/lib/read.wesl @@ -0,0 +1,131 @@ +// Reading columns: page tables in `program` point at blocks of `pages`. Values stay `u32` bits until +// arithmetic needs them, so a missing value is never an `f32` constant (WGSL cannot represent NaN +// constants). + +import package::lib::types::{ + NONE, MISSING, COLUMN_WORDS, COLUMN_FLAGS, COLUMN_ROWS, COLUMN_TABLE, COLUMN_LOW, COLUMN_JOIN, COLUMN_T, + SAMPLED, STEP, PAGE_BITS, PAGE_MASK, POINT_BITS, POINT_MASK, +}; +import package::lib::bind::{pages, program, mark}; + +// Whether `x` is NaN or infinite: missing. +fn missing(x: f32) -> bool { + return missing_bits(bitcast(x)); +} + +fn missing_bits(bits: u32) -> bool { + return (bits & 0x7f800000u) == 0x7f800000u; +} + +fn column_word(column: u32, word: u32) -> u32 { + return program[mark.columns + column * COLUMN_WORDS + word]; +} + +fn page_word(block: u32, offset: u32, fallback: u32) -> u32 { + if block == NONE { + return fallback; + } + return pages[block + offset]; +} + +// A static column's value as (high, low) bits: the low part carries what f32 drops of an f64. +fn static_value(column: u32, row: u32) -> vec2u { + let page = row >> PAGE_BITS; + let local = row & PAGE_MASK; + let table = column_word(column, COLUMN_TABLE); + let hi = page_word(program[table + page], local, MISSING); + let low = column_word(column, COLUMN_LOW); + if low == NONE { + return vec2u(hi, 0u); + } + return vec2u(hi, page_word(program[low + page], local, 0u)); +} + +// A sampled column's value at the shown coordinate, as bits. Each row block has a cursor of six +// words: block and word of this frame, block and word of the next frame, and both frames' row counts. +fn sample_value(column: u32, row: u32) -> u32 { + let cursor = column_word(column, COLUMN_TABLE) + (row >> PAGE_BITS) * 6u; + let local = row & PAGE_MASK; + if local >= program[cursor + 4u] { + return MISSING; + } + let a = page_word(program[cursor], program[cursor + 1u] + local, MISSING); + let flags = column_word(column, COLUMN_FLAGS); + if (flags & STEP) != 0u || program[cursor + 2u] == NONE || local >= program[cursor + 5u] { + return a; + } + let b = page_word(program[cursor + 2u], program[cursor + 3u] + local, MISSING); + if missing_bits(a) || missing_bits(b) { + return a; + } + let t = bitcast(column_word(column, COLUMN_T)); + return bitcast(mix(bitcast(a), bitcast(b), t)); +} + +// A bits column's word: row indices of a reference, NONE where unwired. +fn bits_value(column: u32, row: u32) -> u32 { + if row >= column_word(column, COLUMN_ROWS) { + return NONE; + } + let table = column_word(column, COLUMN_TABLE); + return page_word(program[table + (row >> PAGE_BITS)], row & PAGE_MASK, NONE); +} + +// The row a column reads for `row`: through its join when it reads another table. +fn joined_row(column: u32, row: u32) -> u32 { + let join = column_word(column, COLUMN_JOIN); + if join == NONE { + return row; + } + return bits_value(join, row); +} + +// A column's value for `row` as (high, low) bits. +fn column_value(column: u32, row: u32) -> vec2u { + let r = joined_row(column, row); + if r == NONE || r >= column_word(column, COLUMN_ROWS) { + return vec2u(MISSING, 0u); + } + if (column_word(column, COLUMN_FLAGS) & SAMPLED) != 0u { + return vec2u(sample_value(column, r), 0u); + } + return static_value(column, r); +} + +// One row's points in a geometry column: where its page's blocks of points are listed in `program`, +// its first point among the page's, and how many. Parts are broken by a missing point. +struct Points { + blocks: u32, + first: u32, + count: u32, +} + +// Row `row`'s points of geometry column `column`. The column's table holds, per page, the block of +// each row's first point, where the page's blocks of points are listed in the table, and how many +// points the page has; a block holds `1 << POINT_BITS` points as x and y bits. +fn points_of(column: u32, row: u32) -> Points { + if column == NONE || row >= column_word(column, COLUMN_ROWS) { + return Points(0u, 0u, 0u); + } + let rows = column_word(column, COLUMN_ROWS); + let table = column_word(column, COLUMN_TABLE); + let page = table + 3u * (row >> PAGE_BITS); + let firsts = program[page]; + if firsts == NONE { + return Points(0u, 0u, 0u); + } + let local = row & PAGE_MASK; + let first = pages[firsts + local]; + var end = program[page + 2u]; + if local < PAGE_MASK && row + 1u < rows { + end = pages[firsts + local + 1u]; + } + return Points(table + program[page + 1u], first, end - first); +} + +// Point `k` of a row's points, as x and y bits. +fn point_bits(points: Points, k: u32) -> vec2u { + let i = points.first + k; + let at = program[points.blocks + (i >> POINT_BITS)] + 2u * (i & POINT_MASK); + return vec2u(pages[at], pages[at + 1u]); +} diff --git a/crates/latkit/shaders/lib/reduce.wesl b/crates/latkit/shaders/lib/reduce.wesl new file mode 100644 index 00000000..a7d2d2c5 --- /dev/null +++ b/crates/latkit/shaders/lib/reduce.wesl @@ -0,0 +1,11 @@ +// Reductions with atomics: an `f32` as `u32` bits that sort in the same order, so `atomicMax` of +// `ordered(x)` keeps the greatest value and `atomicMax` of `~ordered(x)` the least. + +fn ordered(x: f32) -> u32 { + let b = bitcast(x); + return select(b | 0x80000000u, ~b, (b & 0x80000000u) != 0u); +} + +fn unordered(u: u32) -> f32 { + return bitcast(select(~u, u & 0x7fffffffu, (u & 0x80000000u) != 0u)); +} diff --git a/crates/latkit/shaders/lib/shade.wesl b/crates/latkit/shaders/lib/shade.wesl new file mode 100644 index 00000000..a6c73007 --- /dev/null +++ b/crates/latkit/shaders/lib/shade.wesl @@ -0,0 +1,65 @@ +// Light: the ground's shadow map, and the earth's daylight. Casters draw into the map through the +// light's eye, blended by MIN: the most covered (1 − coverage), the lowest caster above the ground, +// and the highest (negated). The ground darkens at the level its lowest caster sets, sharp at contact +// and soft from high up; faces compare their height with the highest caster over them. + +import package::lib::types::SPACE_EARTH; +import package::lib::bind::{frame, eye, ramp}; + +// How far the sun stands below the horizon, in the cosine of its angle, where night has fallen. +const TWILIGHT: f32 = 0.1; + +// How lit the earth is at longitude and latitude `p`, in degrees: 1 by day, down to the night's +// brightness, eased across the terminator; 1 everywhere without daylight. +fn daylight(p: vec2f) -> f32 { + let sun = frame.sun; + if frame.space != SPACE_EARTH || dot(sun.xyz, sun.xyz) == 0.0 { + return 1.0; + } + let r = radians(p); + let n = vec3f(cos(r.y) * cos(r.x), cos(r.y) * sin(r.x), sin(r.y)); + return mix(sun.w, 1.0, smoothstep(-TWILIGHT, TWILIGHT * 0.5, dot(n, sun.xyz))); +} + +// What a caster writes, blended by MIN. +fn caster(coverage: f32, height: f32) -> vec4f { + let h = height + eye.lift; + return vec4f(1.0 - coverage, h, -h, 0.0); +} + +// Where world point `p` falls on the map, cast away from the light onto the ground, and its height. +fn on_map(p: vec3f) -> vec3f { + let l = frame.shade.light.xyz; + let ground = p.xy - l.xy / max(l.z, 1e-3) * p.z; + let r = frame.shade.rect; + return vec3f((ground - r.xy) / (r.zw - r.xy), p.z); +} + +// How much light reaches world point `p`: 1 lit, down to 1 − the shadow's alpha. +fn lit(shadows: texture_2d, p: vec3f, ground: bool) -> f32 { + if frame.shade.on == 0u { + return 1.0; + } + let m = on_map(p); + if any(m.xy < vec2f(0.0)) || any(m.xy > vec2f(1.0)) { + return 1.0; + } + let uv = vec2f(m.x, 1.0 - m.y); + let around = textureSampleLevel(shadows, ramp, uv, 3.0); + let spread = frame.shade.light.w / max(frame.shade.texel, 1e-30); + var shadow = 0.0; + if ground { + // The lowest caster around sets how far the shadow spreads. + let gap = max(around.g, 0.0); + let level = clamp(log2(max(gap * spread, 1.0)), 0.0, frame.shade.levels - 1.0); + shadow = 1.0 - textureSampleLevel(shadows, ramp, uv, level).r; + } else { + // A face is shadowed where something stands higher over it on its light ray. + let gap = max(-around.b - m.z, 0.0); + let level = clamp(log2(max(gap * spread, 1.0)), 0.0, frame.shade.levels - 1.0); + let top = -textureSampleLevel(shadows, ramp, uv, level).b; + let bias = 2.0 * frame.shade.texel; + shadow = smoothstep(bias, bias * 4.0, top - m.z); + } + return 1.0 - frame.shade.color.a * shadow; +} diff --git a/crates/latkit/shaders/lib/state.wesl b/crates/latkit/shaders/lib/state.wesl new file mode 100644 index 00000000..65e772fa --- /dev/null +++ b/crates/latkit/shaders/lib/state.wesl @@ -0,0 +1,142 @@ +// Evaluated rows: words of the `state` buffer. A row's kind words sit at `mark.state`, `mark.stride` +// apart, so vertex slots count every vertex mark's rows; its extra words (labels, marker inputs) sit +// at `mark.extra`, `mark.extras` apart. + +import package::lib::types::{ + NONE, VERTEX_WORDS, VERTEX_POSITION, VERTEX_COLOR, VERTEX_STATUS, VERTEX_HALF, VERTEX_ELEVATION, VERTEX_DEPTH, + VERTEX_RANGE, VERTEX_FLAGS, EDGE_FROM, EDGE_TO, EDGE_COLOR, EDGE_WIDTH, EDGE_FLOW, EDGE_TRAVEL, EDGE_FLAGS, FACE_A, FACE_B, + FACE_C, FACE_COLOR, FACE_FLAGS, LINE_COLOR, LINE_WIDTH, LINE_FLOW, LINE_TRAVEL, LINE_FLAGS, AREA_COLOR, + AREA_FLAGS, MARK_EDGES, MARK_LINES, +}; +import package::lib::bind::{state, mark}; + +struct Vertex { + hi: vec2f, + lo: vec2f, + color: u32, + status: u32, + half: vec2f, + elevation: f32, + depth: f32, + // The CSS pixels its marker's half keeps within. + range: vec2f, + flags: u32, +} + +struct Edge { + a: u32, + b: u32, + color: u32, + width: f32, + flow: f32, + travel: f32, + flags: u32, +} + +struct Face { + corners: vec3u, + color: u32, + flags: u32, +} + +struct Line { + color: u32, + width: f32, + flow: f32, + travel: f32, + flags: u32, +} + +struct Area { + color: u32, + flags: u32, +} + +// A range of CSS pixels in one word: each end in sixteenths of a pixel, up to 4095, the top value +// meaning no end. +fn pack_range(range: vec2f) -> u32 { + let ends = vec2u(round(clamp(range, vec2f(0.0), vec2f(4095.9375)) * 16.0)); + let top = select(ends.y, 65535u, range.y > 4095.9375); + return ends.x | (top << 16u); +} + +fn unpack_range(word: u32) -> vec2f { + let ends = vec2f(f32(word & 65535u), f32(word >> 16u)) / 16.0; + // The top of what a word holds is no end at all. + return vec2f(ends.x, select(ends.y, 3.4e38, (word >> 16u) == 65535u)); +} + +fn float_at(at: u32) -> f32 { + return bitcast(state[at]); +} + +// The first kind word of `row` of the current mark. +fn row_at(row: u32) -> u32 { + return mark.state + row * mark.stride; +} + +// Extra word `word` of `row` of the current mark. +fn extra_at(row: u32, word: u32) -> u32 { + return mark.extra + row * mark.extras + word; +} + +fn vertex_at(at: u32) -> Vertex { + let p = at + VERTEX_POSITION; + return Vertex( + vec2f(float_at(p), float_at(p + 1u)), + vec2f(float_at(p + 2u), float_at(p + 3u)), + state[at + VERTEX_COLOR], + state[at + VERTEX_STATUS], + vec2f(float_at(at + VERTEX_HALF), float_at(at + VERTEX_HALF + 1u)), + float_at(at + VERTEX_ELEVATION), + float_at(at + VERTEX_DEPTH), + unpack_range(state[at + VERTEX_RANGE]), + state[at + VERTEX_FLAGS], + ); +} + +// The vertex in graph slot `slot`, from any vertex mark. +fn vertex_slot(slot: u32) -> Vertex { + return vertex_at(slot * VERTEX_WORDS); +} + +fn edge_at(at: u32) -> Edge { + return Edge( + state[at + EDGE_FROM], + state[at + EDGE_TO], + state[at + EDGE_COLOR], + float_at(at + EDGE_WIDTH), + float_at(at + EDGE_FLOW), + float_at(at + EDGE_TRAVEL), + state[at + EDGE_FLAGS], + ); +} + +fn face_at(at: u32) -> Face { + let corners = vec3u(state[at + FACE_A], state[at + FACE_B], state[at + FACE_C]); + return Face(corners, state[at + FACE_COLOR], state[at + FACE_FLAGS]); +} + +fn line_at(at: u32) -> Line { + return Line( + state[at + LINE_COLOR], + float_at(at + LINE_WIDTH), + float_at(at + LINE_FLOW), + float_at(at + LINE_TRAVEL), + state[at + LINE_FLAGS], + ); +} + +// The current mark's words for how far a stroke row's comets traveled and for its flow; NONE for a +// mark that draws no strokes. +fn travel_words() -> vec2u { + switch mark.kind { + case MARK_EDGES: { return vec2u(EDGE_TRAVEL, EDGE_FLOW); } + case MARK_LINES: { return vec2u(LINE_TRAVEL, LINE_FLOW); } + default: { return vec2u(NONE); } + } +} + +fn area_at(at: u32) -> Area { + return Area(state[at + AREA_COLOR], state[at + AREA_FLAGS]); +} diff --git a/crates/latkit/shaders/lib/stroke.wesl b/crates/latkit/shaders/lib/stroke.wesl new file mode 100644 index 00000000..e201a36b --- /dev/null +++ b/crates/latkit/shaders/lib/stroke.wesl @@ -0,0 +1,100 @@ +// Strokes: antialiased segments with dashes, flowing comets, and arrowheads, in CSS pixels. + +import package::lib::bind::frame; +import package::lib::mark::coverage; + +struct Stroke { + a: vec2f, + b: vec2f, + // Distance along the whole line at `a` and at `b`, CSS pixels: dashes and comets run on across + // segments. + phase: vec2f, + // The same in length units, as far along as the line's own points: comets drawn in position + // units run along it. + along: vec2f, + width: f32, + color: vec4f, + // Comet speed, negative backward, 0 for none; and how far the row's comets traveled. + flow: f32, + travel: f32, + dash: bool, + // Whether the segment ends in an arrowhead at `b`. + arrow: bool, +} + +// The arrowhead at `b` pointing along `dir`: a triangle `frame.arrow` long, as a signed distance. +fn head_distance(p: vec2f, b: vec2f, dir: vec2f, width: f32) -> f32 { + let length = frame.arrow + width; + let q = p - b; + let along = dot(q, dir); + let across = abs(dot(q, vec2f(-dir.y, dir.x))); + let half = 0.5 * length * 0.9; + // Inside where it lies behind the tip and within the widening flanks. + let slope = half / length; + let flank = (across - (-along) * slope) / sqrt(1.0 + slope * slope); + return max(max(flank, along), -along - length); +} + +// (distance outside the stroke's edge, distance along the line, fraction of the way from `a` to `b`) +// for pixel `p`. +fn stroke_distance(p: vec2f, s: Stroke) -> vec3f { + let ab = s.b - s.a; + let len = length(ab); + let dir = ab / max(len, 1e-6); + // An arrowhead's stroke stops where the head begins. + let end = select(s.b, s.b - dir * (frame.arrow + s.width) * 0.8, s.arrow && len > frame.arrow); + let ae = end - s.a; + let t = clamp(dot(p - s.a, ae) / max(dot(ae, ae), 1e-6), 0.0, 1.0); + var d = length(p - (s.a + ae * t)) - 0.5 * s.width; + if s.arrow { + d = min(d, head_distance(p, s.b, dir, s.width)); + } + let along = clamp(dot(p - s.a, dir) / max(len, 1e-6), 0.0, 1.0); + return vec3f(d, mix(s.phase.x, s.phase.y, along), along); +} + +// How much of the pixel at `d`, from `stroke_distance`, the line of stroke `s` covers, dashed. +fn covered(d: vec3f, s: Stroke) -> f32 { + var alpha = coverage(d.x); + if s.dash { + alpha *= step(0.5, fract(d.y / max(frame.dash, 1.0))); + } + return alpha; +} + +// How much of the pixel at `d` a comet covers: comets `frame.flow_spacing` apart, moved on by stroke +// `s`'s travel, each a round head `frame.flow_width` wide, never narrower than the stroke, brightest +// at its middle, trailing a tail `frame.flow_length` long that thins and fades. +fn comet(d: vec3f, s: Stroke) -> f32 { + if s.flow == 0.0 || frame.flow.a <= 0.0 { + return 0.0; + } + // Where the pixel lies along the line in the comets' lengths, and CSS pixels per length: position + // units where comets are part of the drawing, else the theme's. + var along = d.y / frame.unit; + var px = frame.unit; + if frame.flow_units != 0u { + along = mix(s.along.x, s.along.y, d.z); + px = length(s.b - s.a) / max(abs(s.along.y - s.along.x), 1e-12); + } + let spacing = max(frame.flow_spacing, 1e-6); + // How far the pixel leads the head behind it, the way comets run, and trails the head ahead. + let lead = fract(sign(s.flow) * (along - s.travel) / spacing) * spacing; + let trail = spacing - lead; + let across = d.x + 0.5 * s.width; + let cap = lead < trail; + let fade = select(saturate(1.0 - trail / max(frame.flow_length, 1e-6)), 1.0, cap); + let reach = 0.5 * max(frame.flow_width, s.width) * mix(0.4, 1.0, fade); + let distance = select(across, length(vec2f(lead * px, across)), cap); + return fade * fade * (1.0 - smoothstep(0.35 * reach, reach, distance)); +} + +// Stroke `s` at pixel `p`, comets over its line; a comet fades with its row. +fn stroke(p: vec2f, s: Stroke) -> vec4f { + let d = stroke_distance(p, s); + let line = s.color.a * covered(d, s); + let head = comet(d, s) * frame.flow.a * s.color.a; + let alpha = head + line * (1.0 - head); + let color = (frame.flow.rgb * head + s.color.rgb * line * (1.0 - head)) / max(alpha, 1e-6); + return vec4f(color, alpha); +} diff --git a/crates/latkit/shaders/lib/trace.wesl b/crates/latkit/shaders/lib/trace.wesl new file mode 100644 index 00000000..90b2de8b --- /dev/null +++ b/crates/latkit/shaders/lib/trace.wesl @@ -0,0 +1,94 @@ +// Traces: what a line draws of a sampled field across the axis: runs of entries left to right, each +// of one level, frames or buckets. The traced column's table holds a header (how many runs, row +// blocks, and levels); per run its level's place among the levels, its first entry, how many, and the +// point it starts at; per level the level, how many axis pages it has, where they are listed, and +// where its row blocks' lists start; per level and row block how many pages of frames or least values +// it has and where they are listed, then of greatest values; then those lists: axis pages as (offset, +// first entry), pages of values as (offset, first entry, words per entry). Offsets within the table +// are relative to it. A line runs through each frame, and through each bucket's least and greatest +// value where it draws; between runs that do not meet, a point is left out, breaking the line. + +import package::lib::types::{NONE, MISSING, COLUMN_TABLE, PAGE_BITS, PAGE_MASK}; +import package::lib::bind::{pages, program, mark}; +import package::lib::read::column_word; + +const HEADER: u32 = 4u; +const RUN_WORDS: u32 = 4u; +const LEVEL_WORDS: u32 = 4u; + +fn trace_table() -> u32 { + return column_word(mark.trace, COLUMN_TABLE); +} + +// The last of `count` items of `stride` words from `at` whose word `key` is at most `value`. +fn last_at_most(at: u32, count: u32, stride: u32, key: u32, value: u32) -> u32 { + var lo = 0u; + var hi = count; + while hi - lo > 1u { + let mid = (lo + hi) / 2u; + if program[at + mid * stride + key] <= value { + lo = mid; + } else { + hi = mid; + } + } + return at + lo * stride; +} + +// A run of the trace: its level's place among the levels, its first entry, how many, and the point +// it starts at. +struct TraceRun { + slot: u32, + first: u32, + entries: u32, + point: u32, +} + +// The run point `k` lies in: the last starting at or before it. +fn trace_run(k: u32) -> TraceRun { + let t = trace_table(); + let r = last_at_most(t + HEADER, max(program[t], 1u), RUN_WORDS, 3u, k); + return TraceRun(program[r], program[r + 1u], program[r + 2u], program[r + 3u]); +} + +// Where level `slot`'s words start. +fn trace_level_at(slot: u32) -> u32 { + let t = trace_table(); + return t + HEADER + RUN_WORDS * program[t] + LEVEL_WORDS * slot; +} + +// The level a run of `slot` draws. +fn trace_level(slot: u32) -> u32 { + return program[trace_level_at(slot)]; +} + +// Where entry `entry` of level `slot` draws along the axis, as (high, low): a frame at its +// coordinate, a bucket at its middle. +fn trace_axis(slot: u32, entry: u32) -> vec2f { + let l = trace_level_at(slot); + let e = last_at_most(trace_table() + program[l + 2u], max(program[l + 1u], 1u), 2u, 1u, entry); + let w = program[e] + (entry - program[e + 1u]) * 2u; + return vec2f(bitcast(pages[w]), bitcast(pages[w + 1u])); +} + +// The bits of `row`'s value of entry `entry` of level `slot`: a frame's, or a bucket's least +// (`side` 0) or greatest (1). +fn trace_entry(row: u32, slot: u32, entry: u32, side: u32) -> u32 { + let t = trace_table(); + let block = row >> PAGE_BITS; + if block >= program[t + 1u] { + return MISSING; + } + let lists = t + program[trace_level_at(slot) + 3u] + 4u * block + 2u * side; + let count = program[lists]; + if count == 0u { + return MISSING; + } + let e = last_at_most(t + program[lists + 1u], count, 3u, 1u, entry); + let local = row & PAGE_MASK; + let per = program[e + 2u]; + if program[e] == NONE || local >= per || entry < program[e + 1u] { + return MISSING; + } + return pages[program[e] + (entry - program[e + 1u]) * per + local]; +} diff --git a/crates/latkit/shaders/lib/triangles.wesl b/crates/latkit/shaders/lib/triangles.wesl new file mode 100644 index 00000000..5d6c474c --- /dev/null +++ b/crates/latkit/shaders/lib/triangles.wesl @@ -0,0 +1,119 @@ +// Triangles: a face row's corners, at the vertices its references name; or an area's triangles, three +// points at a time from its geometry column after the point its label hangs from, numbered by the +// mark's list. Draws, probes, bounds, and labels read a triangle through `triangle_corner`; which kind +// a pipeline reads is its `PATH`: ends for faces, geometry for areas. + +import package::lib::types::{NONE, VISIBLE, PLACED, ENDS_COLOR, PATH_GEOMETRY}; +import package::lib::bind::mark; +import package::lib::state::{row_at, face_at, area_at, vertex_slot}; +import package::lib::project::{world, clip_of, shows}; +import package::lib::focus::faded; +import package::lib::read::{points_of, point_bits, missing_bits}; +import package::lib::path::{PATH, Segment, segment, stroke_instances}; + +struct Corner { + world: vec3f, + // Where it stands, in position units. + position: vec3f, + // A face corner's vertex slot; `NONE` for an area's. + slot: u32, + color: vec4f, + row: u32, + // Whether it has a place to stand, and whether it lies in front of the globe's horizon. + shown: bool, + ahead: bool, +} + +// Triangles every live row draws: a face per row, or each of every area's, as its list numbers them. +fn triangle_instances() -> u32 { + if PATH == PATH_GEOMETRY { + return stroke_instances(); + } + return mark.rows; +} + +// Corner `corner` of triangle `instance`. +fn triangle_corner(instance: u32, corner: u32) -> Corner { + if PATH == PATH_GEOMETRY { + return area_point(segment(instance), 1u + corner); + } + return face_corner(instance, corner); +} + +// Whether triangle `instance` draws: every corner placed, and one in front of the globe's horizon; +// the globe's depth cuts a triangle reaching past its edge. +fn triangle_shown(instance: u32) -> bool { + var ahead = false; + for (var k = 0u; k < 3u; k++) { + let c = triangle_corner(instance, k); + if !c.shown { + return false; + } + ahead = ahead || c.ahead; + } + return ahead; +} + +// The row triangle `instance` belongs to. +fn triangle_row(instance: u32) -> u32 { + if PATH == PATH_GEOMETRY { + return segment(instance).row; + } + return instance; +} + +fn face_corner(row: u32, corner: u32) -> Corner { + var c: Corner; + c.row = row; + let f = face_at(row_at(row)); + if any(f.corners == vec3u(NONE)) || (f.flags & VISIBLE) == 0u { + c.shown = false; + return c; + } + c.slot = f.corners[corner]; + let v = vertex_slot(c.slot); + c.world = world(v.hi, v.lo, v.elevation); + c.position = vec3f(v.hi + v.lo, v.elevation); + let color = select(unpack4x8unorm(f.color), unpack4x8unorm(v.color), (mark.flags & ENDS_COLOR) != 0u); + c.color = vec4f(color.rgb, color.a * faded(row, f.flags)); + c.shown = (v.flags & PLACED) != 0u; + c.ahead = shows(c.world); + return c; +} + +// Point `offset` of the points of triangle `t.index` of area row `t.row`: 0 is where its label hangs, +// 1 to 3 its corners. +fn area_point(t: Segment, offset: u32) -> Corner { + var c: Corner; + c.row = t.row; + c.slot = NONE; + let a = area_at(row_at(t.row)); + let points = points_of(mark.geometry, t.row); + let k = select(3u * t.index + offset, 0u, offset == 0u); + if (a.flags & VISIBLE) == 0u || k >= points.count { + c.shown = false; + return c; + } + let w = point_bits(points, k); + if missing_bits(w.x) || missing_bits(w.y) { + c.shown = false; + return c; + } + let xy = vec2f(bitcast(w.x), bitcast(w.y)); + c.position = vec3f(xy, 0.0); + c.world = world(xy, vec2f(0.0), 0.0); + let color = unpack4x8unorm(a.color); + c.color = vec4f(color.rgb, color.a * faded(t.row, a.flags)); + c.shown = true; + c.ahead = shows(c.world); + return c; +} + +// Where area row `row`'s label hangs: inside its largest polygon, farthest from its edges. +fn area_anchor(row: u32) -> Corner { + return area_point(Segment(row, 0u, 0.0), 0u); +} + +fn corner_clip(c: Corner) -> vec4f { + return clip_of(c.world); +} diff --git a/crates/latkit/shaders/lib/types.wesl b/crates/latkit/shaders/lib/types.wesl new file mode 100644 index 00000000..bbf00cfa --- /dev/null +++ b/crates/latkit/shaders/lib/types.wesl @@ -0,0 +1,592 @@ +// The GPU contract shared with Rust: build.rs mirrors every struct and constant here. + +// No index, slot, or page. +const NONE: u32 = 0xffffffffu; +// A missing number: NaN bits. Any NaN or infinity reads as missing. +const MISSING: u32 = 0x7fc00000u; +// A missing color: transparent magenta, replaced by the theme's color on store. +const MISSING_COLOR: u32 = 0x00ff00ffu; + +// Opcodes of the expression machine; an op is four words: code, a, b, c. +const OP_CONST: u32 = 0u; +const OP_MISSING: u32 = 1u; +const OP_FIELD: u32 = 2u; +const OP_SELECTED: u32 = 3u; +const OP_HOVERED: u32 = 4u; +const OP_POINTER: u32 = 5u; +const OP_ELAPSED: u32 = 6u; +const OP_THEME: u32 = 7u; +const OP_NEG: u32 = 8u; +const OP_NOT: u32 = 9u; +const OP_ABS: u32 = 10u; +const OP_SQRT: u32 = 11u; +const OP_SIN: u32 = 12u; +const OP_COS: u32 = 13u; +const OP_ADD: u32 = 14u; +const OP_SUB: u32 = 15u; +const OP_MUL: u32 = 16u; +const OP_DIV: u32 = 17u; +const OP_MIN: u32 = 18u; +const OP_MAX: u32 = 19u; +const OP_LT: u32 = 20u; +const OP_LE: u32 = 21u; +const OP_GT: u32 = 22u; +const OP_GE: u32 = 23u; +const OP_EQ: u32 = 24u; +const OP_NE: u32 = 25u; +const OP_AND: u32 = 26u; +const OP_OR: u32 = 27u; +const OP_SELECT: u32 = 28u; +const OP_SCALE: u32 = 29u; +const OP_COLORMAP: u32 = 30u; +const OP_STORE: u32 = 31u; +const OP_STORE_COLOR: u32 = 32u; +const OP_STORE_FLAG: u32 = 33u; +const OP_STORE_POSITION: u32 = 34u; +const OP_POSITION: u32 = 35u; +const OP_STORE_END: u32 = 36u; +const OP_REDUCE: u32 = 37u; +const OP_FLOOR: u32 = 38u; +const OP_MOD: u32 = 39u; +const OP_POW: u32 = 40u; +const OP_LOG: u32 = 41u; +const OP_EXP: u32 = 42u; +const OP_ZOOM: u32 = 43u; +const OP_STORE_CODE: u32 = 44u; + +// Values the expression stack holds at once. +const STACK: u32 = 16u; + +// Column descriptor words, eight per column in `meta`. +const COLUMN_WORDS: u32 = 8u; +const COLUMN_FLAGS: u32 = 0u; +const COLUMN_ROWS: u32 = 1u; +const COLUMN_TABLE: u32 = 2u; +const COLUMN_LOW: u32 = 3u; +const COLUMN_JOIN: u32 = 4u; +const COLUMN_T: u32 = 5u; +// Column flags. +const SAMPLED: u32 = 1u; +const STEP: u32 = 2u; +const BITS: u32 = 4u; + +// Rows per data page, as a shift. +const PAGE_BITS: u32 = 16u; +const PAGE_MASK: u32 = 65535u; +// Rows a block holds: a page of every column. A dispatch over more items than one dimension holds +// steps a block at a time in its second, 256 workgroups of 256 wide. +const BLOCK_ROWS: u32 = 65536u; + +// The item invocation `id` of a dispatch over items covers: blocks of BLOCK_ROWS along the second +// dimension, when the first holds too few. +fn item(id: vec3u) -> u32 { + return id.y * BLOCK_ROWS + id.x; +} + +// How a word of a row eases while its mark does: kept as it is (no channel stores it), shown as +// evaluated at once, a number or a color mixed, or a position's high word moved by its offset. +const BLEND_KEEP: u32 = 0u; +const BLEND_SNAP: u32 = 1u; +const BLEND_NUMBER: u32 = 2u; +const BLEND_COLOR: u32 = 3u; +const BLEND_POSITION: u32 = 4u; + +// Points per block of a geometry's points, as a shift: a block of x and y words is a chunk. +const POINT_BITS: u32 = 15u; +const POINT_MASK: u32 = 32767u; + +// Vertex state words. +const VERTEX_WORDS: u32 = 12u; +const VERTEX_POSITION: u32 = 0u; +const VERTEX_COLOR: u32 = 4u; +const VERTEX_STATUS: u32 = 5u; +const VERTEX_HALF: u32 = 6u; +const VERTEX_ELEVATION: u32 = 8u; +// How many groups hold a group row: containers tint by it. +const VERTEX_DEPTH: u32 = 9u; +// The CSS pixels its marker's half keeps within at any zoom, as two halves: the mark's, so every +// mark reading the vertex trims at the outline it draws. +const VERTEX_RANGE: u32 = 10u; +const VERTEX_FLAGS: u32 = 11u; + +// Edge state words. Every kind's flags are its last word. A stroke's travel is how far its comets +// moved, which no channel writes. +const EDGE_WORDS: u32 = 7u; +const EDGE_FROM: u32 = 0u; +const EDGE_TO: u32 = 1u; +const EDGE_COLOR: u32 = 2u; +const EDGE_WIDTH: u32 = 3u; +const EDGE_FLOW: u32 = 4u; +const EDGE_TRAVEL: u32 = 5u; +const EDGE_FLAGS: u32 = 6u; + +// A vertex mark's ports, beside its program: each port's code (its side in two bits, its place +// among the ports on that side and how many share it in eight each, and whether it is an output), +// its shape, the program column of its reference field, and its label's rectangle in the atlas. +const PORT_WORDS: u32 = 5u; +const PORT_CODE: u32 = 0u; +const PORT_SHAPE: u32 = 1u; +const PORT_COLUMN: u32 = 2u; +const PORT_UV: u32 = 3u; +const PORT_OUTPUT: u32 = 0x40000u; +const SIDE_LEFT: u32 = 0u; +const SIDE_RIGHT: u32 = 1u; +const SIDE_TOP: u32 = 2u; +const SIDE_BOTTOM: u32 = 3u; +// Length units across a port's marker: CSS pixels, or units in a diagram. +const PORT_SIZE: f32 = 7.0; +// A group's header band, in label sizes: its title sits in it. +const HEADER_BAND: f32 = 1.8; +// Angle a geodesic segment spans at most, in degrees. +const GEODESIC_STEP: f32 = 2.0; +// Pieces a path between two ends takes at most: along a great circle, or bowed into a lane. +const MAX_PIECES: u32 = 64u; +// Pieces a path bowed into a lane takes at least. +const BOW_PIECES: u32 = 16u; + +// Face state words. +const FACE_WORDS: u32 = 5u; +const FACE_A: u32 = 0u; +const FACE_B: u32 = 1u; +const FACE_C: u32 = 2u; +const FACE_COLOR: u32 = 3u; +const FACE_FLAGS: u32 = 4u; + +// Line state words. +const LINE_WORDS: u32 = 5u; +const LINE_COLOR: u32 = 0u; +const LINE_WIDTH: u32 = 1u; +const LINE_FLOW: u32 = 2u; +const LINE_TRAVEL: u32 = 3u; +const LINE_FLAGS: u32 = 4u; + +// Area state words. +const AREA_WORDS: u32 = 2u; +const AREA_COLOR: u32 = 0u; +const AREA_FLAGS: u32 = 1u; + +// Label words, among a labeled mark's extra words: the text's code, its priority as a level from 0 +// to 255, and its color. +const LABEL_WORDS: u32 = 3u; +const LABEL_CODE: u32 = 0u; +const LABEL_PRIORITY: u32 = 1u; +const LABEL_COLOR: u32 = 2u; + +// A label's words in the labels buffer, per labeled row: the box placement measured it in, CSS +// pixels; its key; its state; and how present it is. Draws place a label from its anchor every +// frame; placement only decides whether it shows. +const CANDIDATE_WORDS: u32 = 7u; +const CANDIDATE_BOX: u32 = 0u; +const CANDIDATE_KEY: u32 = 4u; +const CANDIDATE_STATE: u32 = 5u; +const CANDIDATE_ALPHA: u32 = 6u; +// Text is set once per run at this size, in atlas texels, as a distance field reaching this far +// past the text's edge. +const TEXT_BASE: f32 = 32.0; +const TEXT_SPREAD: f32 = 8.0; +// Candidate states: in view and wanting room, placed, dropped, placed in the frame before, and +// measured by an estimate while its text is not set. +const WANTS: u32 = 1u; +const PLACED_LABEL: u32 = 2u; +const DROPPED: u32 = 4u; +const STICKY: u32 = 8u; +const ESTIMATED: u32 = 16u; +// A text run whose distance field the GPU makes, as words at the start of the fields buffer: where its +// coverage starts, its coverage's width and height, where its columns' least distances start, and +// where its field starts and the words between the starts of its rows. +const FIELD_COVERAGE: u32 = 0u; +const FIELD_WIDTH: u32 = 1u; +const FIELD_HEIGHT: u32 = 2u; +const FIELD_COLUMNS: u32 = 3u; +const FIELD_AT: u32 = 4u; +const FIELD_ROW: u32 = 5u; +const FIELD_WORDS: u32 = 6u; + +// A run table entry whose text is not set yet holds this flag as its first corner and the run's +// estimated size as its second, so its label can be placed before it is set. +const TEXT_ESTIMATE: u32 = 0x80000000u; +// A cell a placed label holds. +const OCCUPIED: u32 = 0u; +// CSS pixels a cell of the label grid covers. +const CELL: f32 = 8.0; +// Codes a mark asks the host to set at most per frame. +const WANTED: u32 = 64u; + +// State flags. +const VISIBLE: u32 = 1u; +// The row has a position: from its data, or in a diagram from its sheet. +const PLACED: u32 = 2u; +const DASH: u32 = 4u; +// While a mark eases, a row that appears fades in and one that disappears or left fades out. +const FADE_IN: u32 = 8u; +const FADE_OUT: u32 = 16u; +// A row that entered with this change: it has no state to ease from. +const ENTERING: u32 = 32u; +// A vertex whose size is in position units, and one with its own height: what any reader of its +// slot needs to know its size in pixels. +const HALF_UNITS: u32 = 64u; +const OWN_HEIGHT: u32 = 128u; + +// Mark kinds. +const MARK_VERTICES: u32 = 0u; +const MARK_EDGES: u32 = 1u; +const MARK_FACES: u32 = 2u; +const MARK_LINES: u32 = 3u; +const MARK_AREAS: u32 = 4u; + +// Primitives. +const POINTS: u32 = 0u; +const STROKES: u32 = 1u; +const TRIANGLES: u32 = 2u; + +// What a stroke's segments run between: two vertices (straight, along a great circle, or through +// bends), samples across the axis, or a geometry column's points. A triangle's corners come from +// three vertices, or from a geometry column three points at a time. +const PATH_ENDS: u32 = 0u; +const PATH_TRACE: u32 = 1u; +const PATH_GEOMETRY: u32 = 2u; +// A pole: from each row's own vertex down to the ground under it. +const PATH_POLES: u32 = 3u; + +// Mark flags. +const SIZED: u32 = 1u; +const ARROWS: u32 = 2u; +const ENDS_COLOR: u32 = 4u; +const GEODESIC: u32 = 8u; +const STATUS: u32 = 16u; +const LABELED: u32 = 32u; +const STEP_BEFORE: u32 = 64u; +const STEP_AFTER: u32 = 128u; +const CASTS: u32 = 256u; +// A vertex mark whose rows hold rows: drawn as containers. +const GROUP: u32 = 512u; + +// Focus bits per row: selected, hovered, and an end of a selected or hovered edge, which the focus +// draw lights over the rest; FIT marks the rows a fit measures. +const SELECTED: u32 = 1u; +const HOVERED: u32 = 2u; +const FIT: u32 = 4u; +const END: u32 = 8u; +const LIT: u32 = 11u; + +// Ordered words per mark in the extents buffer: least x, y, z as complements, then greatest. +const EXTENT_WORDS: u32 = 6u; + +// Probe words: the least key (distance, then the mark drawn last), the instance plus one, where the +// hit lies (its depth and screen point), the nearest depth drawn under the probe, and the instance's +// row and segment. +const PROBE_KEY: u32 = 0u; +const PROBE_INSTANCE: u32 = 1u; +const PROBE_DEPTH: u32 = 2u; +const PROBE_X: u32 = 3u; +const PROBE_Y: u32 = 4u; +const PROBE_UNDER: u32 = 5u; +const PROBE_ROW: u32 = 6u; +const PROBE_SEGMENT: u32 = 7u; +// Where a located row lies on screen, and whether it shows. What queries find follows the probe's words. +const PROBE_LOCATE_X: u32 = 8u; +const PROBE_LOCATE_Y: u32 = 9u; +const PROBE_LOCATED: u32 = 10u; +const PROBE_WORDS: u32 = 12u; + +// The steps of the probe program, as its step uniform names them: the hover's three, then the +// queries', then the depth under the probe. +const STEP_NEAREST: u32 = 0u; +const STEP_TOPMOST: u32 = 1u; +const STEP_DESCRIBE: u32 = 2u; +const STEP_HITS: u32 = 3u; +const STEP_BOXED: u32 = 4u; +const STEP_LOCATE: u32 = 5u; +const STEP_UNDER: u32 = 6u; +const STEPS: u32 = 7u; +// Words of a hit a query finds: its row, distance in sixty-fourths of a pixel, part, screen x and y, +// and depth. +const HIT_WORDS: u32 = 6u; + +// Overlay sprites. +const SPRITE_LINE: u32 = 0u; +const SPRITE_TEXT: u32 = 1u; +const SPRITE_BOX: u32 = 2u; +const SPRITE_FILL: u32 = 3u; + +// Spaces. +const SPACE_EARTH: u32 = 0u; +const SPACE_PLANE: u32 = 1u; +const SPACE_PLOT: u32 = 2u; +const SPACE_DIAGRAM: u32 = 3u; + +// Built-in markers and shapes. +const MARKER_SHAPE: u32 = 0u; +const MARKER_GAUGE: u32 = 1u; +const MARKER_PIE: u32 = 2u; +const MARKER_BLOCK: u32 = 3u; +const MARKER_ICON: u32 = 4u; +const MARKER_CUSTOM: u32 = 5u; +const SHAPE_ELLIPSE: u32 = 0u; +const SHAPE_RECTANGLE: u32 = 1u; +const SHAPE_ROUNDED: u32 = 2u; +const SHAPE_DIAMOND: u32 = 3u; + +// Colormap kinds. +const COLORMAP_SEQUENTIAL: u32 = 0u; +const COLORMAP_DIVERGING: u32 = 1u; +const COLORMAP_CYCLIC: u32 = 2u; +const COLORMAP_CATEGORICAL: u32 = 3u; + +// Theme slots: colors are packed RGBA8, sizes are f32 bits. +const THEME_VERTEX: u32 = 0u; +const THEME_VERTEX_RADIUS: u32 = 1u; +const THEME_EDGE: u32 = 2u; +const THEME_EDGE_WIDTH: u32 = 3u; +const THEME_LINE: u32 = 4u; +const THEME_LINE_WIDTH: u32 = 5u; +const THEME_AREA: u32 = 6u; +const THEME_TEXT: u32 = 7u; +const THEME_MISSING: u32 = 8u; +// Nothing: a fully transparent color, what a missing status draws. +const THEME_CLEAR: u32 = 9u; +// What a group's container is filled with. +const THEME_SURFACE: u32 = 10u; +const THEME_SLOTS: u32 = 16u; + +// Backdrop grids. +const GRID_OFF: u32 = 0u; +const GRID_LINES: u32 = 1u; +const GRID_DOTS: u32 = 2u; + +// A list's header: its item count; where its counts (scanned in place to where each item's entries +// start, then the total), block sums, and entries start; the indirect arguments a draw and a +// dispatch over its entries read; and how many entries it keeps. +const LIST_ITEMS: u32 = 0u; +const LIST_COUNTS: u32 = 1u; +const LIST_SUMS: u32 = 2u; +const LIST_ENTRIES: u32 = 3u; +// Draw arguments: vertices, instances (the total), first vertex, first instance. +const LIST_DRAW: u32 = 4u; +// Dispatch arguments: workgroups over the total, 1, 1. +const LIST_DISPATCH: u32 = 8u; +// Entries the list keeps: past them, entries are counted but not written. +const LIST_KEPT: u32 = 11u; +const LIST_HEADER: u32 = 12u; +// Counts a workgroup of the scan takes. +const SCAN_WORKGROUP: u32 = 256u; + + +// How shadows fall: the light, how they darken and soften, and the ground the map covers. +struct Shade { + color: vec4f, + // The direction toward the light, in world units, and how much shadows spread per unit of height. + light: vec4f, + // The ground the map covers: least x and y, greatest x and y, in world units. + rect: vec4f, + // World units flat marks cast from, world units per texel of the map, its levels, and whether + // anything casts. + lift: f32, + texel: f32, + levels: f32, + on: u32, +} + +// What every draw and dispatch of a frame reads. +struct Frame { + center_hi: vec2f, + center_lo: vec2f, + pointer: vec2f, + // Where a probe looks, CSS pixels, and the box a query covers. + probe: vec2f, + query: vec4f, + // The direction toward the key light faces are lit by, which turns with the camera. + light: vec4f, + space: u32, + globe: f32, + mercator_y: f32, + probe_radius: f32, + elapsed: f32, + selecting: u32, + // 1 while a fit measures only the rows marked FIT. + fitting: u32, + // 1 when the target stores linear color (an sRGB format): outputs convert from sRGB. + linear: u32, + glow: f32, + dim: f32, + dash: f32, + // Comets: the distance between them and how far a tail trails its head, in the theme's lengths + // or with `flow_units` in position units; how wide a head is, in CSS pixels; and the seconds + // they travel this frame. + flow_spacing: f32, + flow_length: f32, + flow_width: f32, + flow_units: u32, + flow_step: f32, + // How far a lane bows, in its edge's lengths at its middle. + lane_bow: f32, + hover_scale: f32, + shading: f32, + arrow: f32, + halo: f32, + // CSS pixels between a group's members and its outline: its title's inset. + group_padding: f32, + // CSS pixels per length unit: per position unit in a diagram, where every length is a unit; 1 + // elsewhere. Lengths in the frame above are already in pixels. + unit: f32, + zoom: f32, + // The label grid: where its cells start in the labels buffer, and its columns and rows; and how + // far labels fade per frame. + cells: u32, + cell_columns: u32, + cell_rows: u32, + label_fade: f32, + // A plane's grid: its kind, pitch in position units, and the world distance from the center it + // fades out by, 0 for none; and whether the earth draws its graticule. + grid_kind: u32, + grid_pitch: f32, + grid_fade: f32, + graticule: u32, + hover: vec4f, + selected: vec4f, + flow: vec4f, + background: vec4f, + surface: vec4f, + grid_color: vec4f, + // The direction toward the sun in the earth's frame (x toward 0° longitude on the equator, z + // toward the north pole), and how bright night stays; no direction where daylight is off. + sun: vec4f, + // The air glowing around the globe; clear where the earth has none. + atmosphere: vec4f, + shade: Shade, + theme: array, +} + +// What one pass draws through: the view, or the light casting shadows. +struct Eye { + clip_from_world: mat4x4f, + world_from_clip: mat4x4f, + // The camera's position in world units. + position: vec4f, + // The target's size in CSS pixels; the light's map counts CSS pixels of the view it serves. + size: vec2f, + px_per_unit: vec2f, + // Target pixels per CSS pixel. + pixel_ratio: f32, + // World units casters are raised by: the shadow's lift in the light's eye, 0 elsewhere. + lift: f32, +} + +// One mark's parameters, at a 256-byte aligned dynamic offset. +struct Mark { + index: u32, + kind: u32, + primitive: u32, + // Rows drawn and evaluated, and rows past them that left and fade out. + rows: u32, + exits: u32, + // Each row's kind words: where row 0's start and how many; then its extra words. + state: u32, + stride: u32, + extra: u32, + extras: u32, + // While the mark eases, where row 0's frozen kind and extra words start; NONE otherwise. + frozen: u32, + frozen_extra: u32, + motion: f32, + // While the mark eases toward what its channels evaluated, where row 0's settled kind and extra + // words start in the settled mirror; NONE otherwise. Where the program holds how each word of a + // row eases, a word each. + settled: u32, + settled_extra: u32, + blends: u32, + // The row blocks a dispatch over the mark's rows covers: at `block` in the blocks buffer, + // `blocks` of them. + block: u32, + blocks: u32, + focus: u32, + domains: u32, + columns: u32, + ranges: u32, + code: u32, + constants: u32, + ends: u32, + channels: u32, + reductions: u32, + mask: u32, + units: u32, + flags: u32, + marker: u32, + shape: u32, + corner: f32, + hole: f32, + // Marker inputs: how many, the extra word of the first, and where their colors start in the constants. + inputs: u32, + input: u32, + palette: u32, + // The program column a line traces, or NONE. + trace: u32, + // Segments of each row when every row has as many; NONE when the mark's list numbers them. + per_row: u32, + // Where the header of the mark's list of segments starts in the lists buffer, and where what the + // running query finds of it starts among the probe's words. + list: u32, + query: u32, + // Where the mark's remap words start, while its transition is being frozen. + remap: u32, + // The rows its focus draw lights, at `focused` in the focused buffer, how many, and the + // instances each takes: a point one, a path as many as its longest piece count. + focused: u32, + focused_rows: u32, + pieces: u32, + // Program columns: the geometry a stroke's path runs through (a route or bends), the geometry + // it ran through when its transition began, and each row's lane among edges joining the same + // two vertices; NONE without. + geometry: u32, + frozen_geometry: u32, + lane: u32, + // Each port of a vertex mark's rows, and how many each row has. + port_info: u32, + ports: u32, + // The extra word of the label's code, or NONE; the labels buffer's offsets of its candidates, its + // run table (two words per code), its wanted codes (a count, then codes), and its seen codes (a + // bit per code shown in view); the id of its first candidate, unique across marks; the size + // labels and port labels are set at, in length units. + label: u32, + candidates: u32, + runs: u32, + wanted: u32, + seen: u32, + label_id: u32, + label_size: f32, + port_label_size: f32, + // The most labels shown, or NONE; and where the labels buffer holds the select that caps them. + label_max: u32, + label_select: u32, + // The CSS pixels the mark's size keeps within at any zoom: a vertex's half, a stroke's width. + size_min: f32, + size_max: f32, +} + +// A line or a run of text drawn over the marks, in CSS pixels. +struct Sprite { + // A line's ends, or a text's top left and bottom right. + a: vec2f, + b: vec2f, + // A text's rectangle in the atlas, texels. + uv: vec4f, + color: vec4f, + width: f32, + kind: u32, +} + +// One panel of a shot composed into the bytes a consumer takes: RGBA rows for an image, or NV12 +// planes for an encoder. Pixels are the shot's. +struct Compose { + // Where the panel's top left lands in the picture, and its size. + origin: vec2u, + size: vec2u, + // The picture's size. + picture: vec2u, + // Where NV12's interleaved chroma plane starts, in words. + chroma: u32, + // Whether pixels keep their alpha: an image of a transparent shot. + alpha: u32, + // What shows where no panel draws: straight sRGB. + background: vec4f, +} diff --git a/crates/latkit/src/data/bits.rs b/crates/latkit/src/data/bits.rs new file mode 100644 index 00000000..e75ce1e3 --- /dev/null +++ b/crates/latkit/src/data/bits.rs @@ -0,0 +1,146 @@ +use std::ops::Range; + +use super::buffer::Buffer; + +/// A shared, immutable bit vector, used for booleans and validity. +#[derive(Clone, Default)] +pub(crate) struct Bits { + words: Buffer, + offset: usize, + len: usize, +} + +impl Bits { + pub(crate) fn len(&self) -> usize { + self.len + } + + pub(crate) fn get(&self, i: usize) -> bool { + debug_assert!(i < self.len); + let bit = self.offset + i; + self.words[bit >> 6] >> (bit & 63) & 1 == 1 + } + + pub(crate) fn slice(&self, range: Range) -> Bits { + assert!(range.start <= range.end && range.end <= self.len, "slice out of range"); + let bit = self.offset + range.start; + let first = bit >> 6; + let last = (self.offset + range.end).div_ceil(64); + Bits { words: self.words.slice(first..last.max(first)), offset: bit & 63, len: range.end - range.start } + } + + /// `len` bits, bit `i` being `bit(i)`, packed a word at a time. + pub(crate) fn from_fn(len: usize, bit: impl Fn(usize) -> bool) -> Bits { + let words = (0..len.div_ceil(64)) + .map(|w| { + let base = w * 64; + (base..(base + 64).min(len)).fold(0_u64, |word, i| word | u64::from(bit(i)) << (i - base)) + }) + .collect::>(); + Bits { words: words.into(), offset: 0, len } + } + + /// How many bits are set. + pub(crate) fn count(&self) -> usize { + if self.offset != 0 { + return (0..self.len).filter(|&i| self.get(i)).count(); + } + self.to_words().iter().map(|w| w.count_ones() as usize).sum() + } + + pub(crate) fn all(&self) -> bool { + if self.offset != 0 { + return (0..self.len).all(|i| self.get(i)); + } + let (full, rest) = (self.len / 64, self.len % 64); + let mask = (1_u64 << rest).wrapping_sub(1); + self.words[..full].iter().all(|&w| w == u64::MAX) && (rest == 0 || self.words[full] & mask == mask) + } + + /// The bits as little-endian words starting at bit 0, for byte encoding. + pub(crate) fn to_words(&self) -> Vec { + if self.offset == 0 { + let mut words = self.words[..self.len.div_ceil(64)].to_vec(); + if !self.len.is_multiple_of(64) + && let Some(last) = words.last_mut() + { + *last &= (1 << (self.len % 64)) - 1; + } + return words; + } + let mut builder = BitsBuilder::with_capacity(self.len); + for i in 0..self.len { + builder.push(self.get(i)); + } + builder.finish().words[..].to_vec() + } + + pub(crate) fn from_words(words: Vec, len: usize) -> Bits { + assert!(words.len() * 64 >= len, "too few words"); + Bits { words: words.into(), offset: 0, len } + } +} + +impl FromIterator for Bits { + fn from_iter>(iter: I) -> Bits { + let iter = iter.into_iter(); + let mut builder = BitsBuilder::with_capacity(iter.size_hint().0); + for bit in iter { + builder.push(bit); + } + builder.finish() + } +} + +impl std::fmt::Debug for Bits { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_list().entries((0..self.len).map(|i| self.get(i))).finish() + } +} + +/// Builds [`Bits`] one bit at a time, keeping the word it fills apart. +pub(crate) struct BitsBuilder { + words: Vec, + word: u64, + len: usize, +} + +impl BitsBuilder { + pub(crate) fn with_capacity(bits: usize) -> BitsBuilder { + BitsBuilder { words: Vec::with_capacity(bits.div_ceil(64)), word: 0, len: 0 } + } + + pub(crate) fn push(&mut self, bit: bool) { + self.word |= u64::from(bit) << (self.len & 63); + self.len += 1; + if self.len.is_multiple_of(64) { + self.words.push(std::mem::take(&mut self.word)); + } + } + + pub(crate) fn finish(mut self) -> Bits { + if !self.len.is_multiple_of(64) { + self.words.push(self.word); + } + Bits { words: self.words.into(), offset: 0, len: self.len } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn slices_keep_bit_positions() { + let bits: Bits = (0..200).map(|i| i % 3 == 0).collect(); + let slice = bits.slice(70..150); + assert_eq!(slice.len(), 80); + for i in 0..80 { + assert_eq!(slice.get(i), (i + 70) % 3 == 0); + } + let words = slice.to_words(); + for i in 0..80 { + assert_eq!(words[i >> 6] >> (i & 63) & 1 == 1, (i + 70) % 3 == 0); + } + } +} diff --git a/crates/latkit/src/data/buffer.rs b/crates/latkit/src/data/buffer.rs new file mode 100644 index 00000000..9ef9a4cd --- /dev/null +++ b/crates/latkit/src/data/buffer.rs @@ -0,0 +1,61 @@ +use std::ops::{Deref, Range}; +use std::sync::Arc; + +/// A shared, immutable slice: making one from a vector, cloning it, and slicing it never copy. +pub(crate) struct Buffer { + data: Arc>, + start: usize, + end: usize, +} + +impl Clone for Buffer { + fn clone(&self) -> Buffer { + Buffer { data: self.data.clone(), start: self.start, end: self.end } + } +} + +impl Buffer { + pub(crate) fn slice(&self, range: Range) -> Buffer { + assert!(range.start <= range.end && self.start + range.end <= self.end, "slice out of range"); + Buffer { data: self.data.clone(), start: self.start + range.start, end: self.start + range.end } + } +} + +impl Default for Buffer { + fn default() -> Buffer { + Buffer::from(Vec::new()) + } +} + +impl Deref for Buffer { + type Target = [T]; + + fn deref(&self) -> &[T] { + &self.data[self.start..self.end] + } +} + +impl From> for Buffer { + fn from(values: Vec) -> Buffer { + let end = values.len(); + Buffer { data: Arc::new(values), start: 0, end } + } +} + +impl From<&[T]> for Buffer { + fn from(values: &[T]) -> Buffer { + Buffer::from(values.to_vec()) + } +} + +impl FromIterator for Buffer { + fn from_iter>(iter: I) -> Buffer { + iter.into_iter().collect::>().into() + } +} + +impl std::fmt::Debug for Buffer { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_list().entries(self.iter()).finish() + } +} diff --git a/crates/latkit/src/data/bytes.rs b/crates/latkit/src/data/bytes.rs new file mode 100644 index 00000000..ca00e975 --- /dev/null +++ b/crates/latkit/src/data/bytes.rs @@ -0,0 +1,797 @@ +//! One byte encoding for patches and datasets: a frame of a magic, its length, the name of the +//! dataset its patch changes (empty when it names none), and the patch's operations. Little endian +//! throughout. A frame says its length up front, so frames back to back split without decoding, and a +//! stream knows at once whether it holds a whole one. A dataset's bytes are the patch to it that +//! builds it. +//! +//! | Part | Layout | +//! | -------- | ------------------------------------------------------------------------------------- | +//! | frame | `b"LATK"`, `u16` version (1), `u16` flags (0), `u64` length of the whole frame, name, `u32` op count, ops | +//! | op | `u8` tag and its payload: axis, replace, set, remove, append, forget, or frames | +//! | axis | name, unit | +//! | replace | table, as `set` | +//! | remove | table name, ids | +//! | append | table name, `u8` 1 and ids or `u8` 0 for every row, `u32` frames, `f64` coordinates, | +//! | | `u32` field count; per field: name, values frame-major | +//! | forget | `f64` before | +//! | frames | table name, field name, `u32` rows, run | +//! | table | name, ids, `u32` field count; per field: name, `u8` tag, payload | +//! | field | values; a reference's table and its target ids as values; or samples | +//! | ids | `u8` 0 and `u32` count, or `u8` 1 and values: `u64`, `u32` read as `u64`, or texts | +//! | values | `u8` storage, `u32` len, data, `u8` has-validity, validity words (`u64`) | +//! | samples | `u32` rows, `u64` first frame read, `u64` frames read, `u8` highest level, `u32` run count, runs; buckets | +//! | | whose eight entries a level below are held are left out, as they follow from those | +//! | run | `u8` level, `u64` first entry, `u32` entries, `f64` coordinates (a frame's own; a | +//! | | bucket's first and last frame's), `f32` values entry-major: a frame's per row, or a | +//! | | bucket's least per row and, after every bucket's, its greatest (NaN missing) | +//! | `str` | `u32` byte length, UTF-8 | + +use std::sync::Arc; + +use super::bits::Bits; +use super::column::Column; +use super::geometry::Geometry; +use super::ids::{IdList, Ids, RowIds}; +use super::name::{Name, Version}; +use super::patch::{Op, Patch}; +use super::samples::{self, MAX_LEVEL, Run, Samples}; +use super::table::{Field, Reference, Table}; +use super::text::Text; +use super::values::{Array, Values}; +use crate::{Error, Result}; + +const MAGIC: &[u8; 4] = b"LATK"; +/// Magic, version, flags, and total frame length. +const HEADER: usize = 16; +const VERSION: u16 = 1; + +/// Limits for one binary frame. These bound encoded bytes and conservative decoded storage +/// accounting; applying a patch and retaining datasets have separate memory costs. +#[derive(Clone, Copy, Debug)] +pub struct DecodeLimits { + /// Maximum encoded frame size; checked as soon as the header arrives. + pub frame_bytes: usize, + /// Budget for decoded vectors, names, operations, pages, and derived sample buckets. + pub decoded_bytes: usize, +} + +impl Default for DecodeLimits { + fn default() -> Self { + Self { frame_bytes: 256 << 20, decoded_bytes: 512 << 20 } + } +} + +const OP_AXIS: u8 = 0; +const OP_REPLACE: u8 = 1; +const OP_SET: u8 = 2; +const OP_REMOVE: u8 = 3; +const OP_APPEND: u8 = 4; +const OP_FORGET: u8 = 5; +const OP_FRAMES: u8 = 6; + +const FIELD_VALUES: u8 = 0; +const FIELD_REFERENCE: u8 = 1; +const FIELD_SAMPLED: u8 = 2; + +const STORE_F64: u8 = 0; +const STORE_F32: u8 = 1; +const STORE_I32: u8 = 2; +const STORE_U32: u8 = 3; +const STORE_U64: u8 = 4; +const STORE_BOOL: u8 = 5; +const STORE_TEXT: u8 = 6; +const STORE_GEOMETRY: u8 = 7; + +pub(crate) fn encode(patch: &Patch) -> Vec { + let mut w = Writer(Vec::new()); + w.0.extend_from_slice(MAGIC); + w.0.extend_from_slice(&VERSION.to_le_bytes()); + w.0.extend_from_slice(&0_u16.to_le_bytes()); + w.0.extend_from_slice(&[0; 8]); + w.str(patch.data.as_deref().unwrap_or("")); + w.u32(patch.ops.len()); + for op in &patch.ops { + match op { + Op::Axis { name, unit } => { + w.u8(OP_AXIS); + w.str(name); + w.str(unit); + } + Op::Replace(table) => { + w.u8(OP_REPLACE); + w.table(table); + } + Op::Set(table) => { + w.u8(OP_SET); + w.table(table); + } + Op::Remove { table, ids } => { + w.u8(OP_REMOVE); + w.str(table); + w.ids(ids); + } + Op::Append { table, at, ids, fields } => { + w.u8(OP_APPEND); + w.str(table); + match ids { + Some(ids) => { + w.u8(1); + w.ids(ids); + } + None => w.u8(0), + } + w.u32(at.len()); + for &t in at { + w.f64(t); + } + w.u32(fields.len()); + for (name, values) in fields { + w.str(name); + w.values(values); + } + } + Op::Forget { before } => { + w.u8(OP_FORGET); + w.f64(*before); + } + Op::Frames { table, field, run, at, values } => { + w.u8(OP_FRAMES); + w.str(table); + w.str(field); + let per_row = run.len() * samples::sides(run.level); + w.u32(values.len().checked_div(per_row).unwrap_or(0)); + w.run(run, at, values); + } + } + } + let length = w.0.len() as u64; + w.0[8..HEADER].copy_from_slice(&length.to_le_bytes()); + w.0 +} + +/// The patch `bytes` hold, every byte of them. +pub(crate) fn decode(bytes: &[u8]) -> Result { + match decode_with_limits(bytes, DecodeLimits::default())? { + Some((patch, used)) if used == bytes.len() => Ok(patch), + Some(_) => Err(malformed("trailing bytes")), + None => Err(malformed("truncated")), + } +} + +/// The patch at the start of `bytes` and how many bytes it takes; `None` while `bytes` hold only +/// its start. A frame its length says runs past `limit` bytes is an error at once. +pub(crate) fn decode_prefix(bytes: &[u8], limit: usize) -> Result> { + decode_with_limits(bytes, DecodeLimits { frame_bytes: limit, ..DecodeLimits::default() }) +} + +pub(crate) fn decode_with_limits(bytes: &[u8], limits: DecodeLimits) -> Result> { + let limit = limits.frame_bytes; + let held = bytes.len().min(MAGIC.len()); + if bytes[..held] != MAGIC[..held] { + return Err(malformed("not latkit bytes")); + } + if let Some(version) = bytes.get(4..6) + && version != VERSION.to_le_bytes() + { + return Err(malformed("unsupported LATK version")); + } + if let Some(flags) = bytes.get(6..8) + && flags != [0, 0] + { + return Err(malformed("unsupported LATK flags")); + } + let Some(length) = bytes.get(8..HEADER) else { return Ok(None) }; + let length = u64::from_le_bytes(length.try_into().expect("eight bytes")); + let length = usize::try_from(length).map_err(|_| too_long(limit))?; + if length > limit { + return Err(too_long(limit)); + } + if length < HEADER { + return Err(malformed("a frame shorter than its header")); + } + let Some(frame) = bytes.get(..length) else { return Ok(None) }; + let mut r = Reader { bytes: frame, at: HEADER, remaining: limits.decoded_bytes }; + let patch = r.patch()?; + if r.at != frame.len() { + return Err(malformed("a frame longer than its patch")); + } + Ok(Some((patch, length))) +} + +impl Reader<'_> { + fn patch(&mut self) -> Result { + let r = self; + let name = r.name()?; + let count = r.len(1)?; + r.charge(count, size_of::())?; + let mut patch = Patch { data: (!name.is_empty()).then_some(name), ops: Vec::with_capacity(count) }; + for _ in 0..count { + let op = match r.u8()? { + OP_AXIS => Op::Axis { name: r.name()?, unit: r.name()? }, + OP_REPLACE => Op::Replace(r.table()?), + OP_SET => Op::Set(r.table()?), + OP_REMOVE => Op::Remove { table: r.name()?, ids: r.ids()? }, + OP_APPEND => { + let table = r.name()?; + let ids = match r.u8()? { + 0 => None, + 1 => Some(r.ids()?), + _ => return Err(malformed("an append names its rows or none")), + }; + let frames = r.len(8)?; + let at = r.vec(frames)?; + let count = r.len(1)?; + r.charge(count, size_of::<(Name, Values)>())?; + let fields = (0..count).map(|_| Ok((r.name()?, r.values()?))).collect::>()?; + Op::Append { table, at, ids, fields } + } + OP_FORGET => Op::Forget { before: r.f64()? }, + OP_FRAMES => { + let (table, field) = (r.name()?, r.name()?); + let rows = r.u32()? as usize; + let (run, at, values) = r.run(rows)?; + Op::Frames { table, field, run, at, values } + } + tag => return Err(malformed(format!("unknown operation {tag}"))), + }; + patch.ops.push(op); + } + Ok(patch) + } +} + +fn malformed(reason: impl Into>) -> Error { + Error::invalid(reason).at("bytes") +} + +fn too_long(limit: usize) -> Error { + Error::Limit(format!("a patch longer than {limit} bytes").into()) +} + +struct Writer(Vec); + +impl Writer { + fn u8(&mut self, v: u8) { + self.0.push(v); + } + + fn u32(&mut self, v: usize) { + self.0.extend_from_slice(&u32::try_from(v).expect("counts fit in u32").to_le_bytes()); + } + + fn u64(&mut self, v: u64) { + self.0.extend_from_slice(&v.to_le_bytes()); + } + + fn f64(&mut self, v: f64) { + self.0.extend_from_slice(&v.to_le_bytes()); + } + + fn str(&mut self, s: &str) { + self.u32(s.len()); + self.0.extend_from_slice(s.as_bytes()); + } + + fn slice(&mut self, values: &[T]) { + #[cfg(target_endian = "little")] + self.0.extend_from_slice(bytemuck::cast_slice(values)); + #[cfg(target_endian = "big")] + compile_error!("latkit's byte format is written on little-endian targets"); + } + + fn table(&mut self, table: &Table) { + self.str(&table.name); + match &table.ids { + RowIds::Count(n) => { + self.u8(0); + self.u32(*n as usize); + } + RowIds::Listed(column) => { + self.u8(1); + self.values(&column.values()); + } + } + self.u32(table.fields.len()); + for (name, field) in &table.fields { + self.str(name); + match field { + Field::Values(column, _) => { + self.u8(FIELD_VALUES); + self.column(column); + } + Field::Reference(reference) => { + self.u8(FIELD_REFERENCE); + self.str(&reference.to); + self.column(&reference.ids); + } + Field::Sampled(samples, _) => { + self.u8(FIELD_SAMPLED); + self.u32(table.len()); + self.u64(samples.start()); + self.u64(samples.end() - samples.start()); + self.u8(samples.levels() as u8); + let runs = samples.stored_runs(); + self.u32(runs.len()); + let rows: Vec = (0..table.len()).collect(); + for run in &runs { + let (at, values) = samples.read(run, &rows); + self.run(run, &at, &values); + } + } + } + } + } + + /// `run`: its level, first entry, and entries, its coordinates `at`, and its `values`. + fn run(&mut self, run: &Run, at: &[f64], values: &[f32]) { + self.u8(run.level as u8); + self.u64(run.entries.start); + self.u32(run.len()); + self.slice(at); + self.slice(values); + } + + fn ids(&mut self, ids: &Ids) { + match &ids.0 { + IdList::Count(n) => { + self.u8(0); + self.u32(*n as usize); + } + IdList::Listed(values) => { + self.u8(1); + self.values(values); + } + } + } + + fn column(&mut self, column: &Column) { + self.values(&column.values()); + } + + fn values(&mut self, values: &Values) { + let len = values.len(); + match &values.array { + Array::F64(v) => self.numbers(STORE_F64, v), + Array::F32(v) => self.numbers(STORE_F32, v), + Array::I32(v) => self.numbers(STORE_I32, v), + Array::U32(v) => self.numbers(STORE_U32, v), + Array::U64(v) => self.numbers(STORE_U64, v), + Array::Bool(bits) => { + self.u8(STORE_BOOL); + self.u32(len); + self.slice(&bits.to_words()); + } + Array::Text(text) => { + self.u8(STORE_TEXT); + self.u32(len); + let (offsets, bytes) = text.compact(); + self.slice(&offsets); + self.str(bytes); + } + Array::Geometry(geometry) => { + self.u8(STORE_GEOMETRY); + self.u32(len); + self.u8(geometry.depth()); + let (levels, coords) = geometry.compact(); + for level in &levels { + self.u32(level.len()); + self.slice(level); + } + self.u32(coords.len()); + self.slice(bytemuck::cast_slice::<[f64; 2], f64>(&coords)); + } + } + match &values.valid { + Some(bits) => { + self.u8(1); + self.slice(&bits.to_words()); + } + None => self.u8(0), + } + } + + fn numbers(&mut self, store: u8, values: &[T]) { + self.u8(store); + self.u32(values.len()); + self.slice(values); + } +} + +/// Reads one frame, whose bytes are all there. +struct Reader<'a> { + bytes: &'a [u8], + at: usize, + remaining: usize, +} + +impl Reader<'_> { + fn charge(&mut self, count: usize, size: usize) -> Result<()> { + let bytes = count.checked_mul(size).ok_or_else(|| malformed("decoded size overflow"))?; + self.remaining = self + .remaining + .checked_sub(bytes) + .ok_or_else(|| Error::Limit("decoded patch exceeds its storage budget".into()))?; + Ok(()) + } + + /// Whether `n` more bytes are in the frame. + fn reach(&self, n: usize) -> Result<()> { + if self.at.saturating_add(n) > self.bytes.len() { + return Err(malformed("truncated")); + } + Ok(()) + } + + fn take(&mut self, n: usize) -> Result<&[u8]> { + self.reach(n)?; + let end = self.at + n; + let slice = &self.bytes[self.at..end]; + self.at = end; + Ok(slice) + } + + fn u8(&mut self) -> Result { + Ok(self.take(1)?[0]) + } + + fn u32(&mut self) -> Result { + Ok(u32::from_le_bytes(self.take(4)?.try_into().expect("four bytes"))) + } + + /// A count of items at least `size` bytes each, checked against the bytes left. + fn len(&mut self, size: usize) -> Result { + let n = self.u32()? as usize; + self.reach(n.saturating_mul(size))?; + Ok(n) + } + + fn u64(&mut self) -> Result { + Ok(u64::from_le_bytes(self.take(8)?.try_into().expect("eight bytes"))) + } + + fn f64(&mut self) -> Result { + Ok(f64::from_le_bytes(self.take(8)?.try_into().expect("eight bytes"))) + } + + fn name(&mut self) -> Result { + let n = self.len(1)?; + self.charge(n, 1)?; + self.charge(1, size_of::())?; + let bytes = self.take(n)?; + std::str::from_utf8(bytes).map(Name::from).map_err(|_| malformed("text is not UTF-8")) + } + + fn vec(&mut self, n: usize) -> Result> { + // Includes conversion into column pages and the sampled levels derived from runs. + self.charge(n, 4 * size_of::())?; + let bytes = self.take(n.checked_mul(size_of::()).ok_or_else(|| malformed("too large"))?)?; + Ok(bytes.chunks_exact(size_of::()).map(bytemuck::pod_read_unaligned).collect()) + } + + fn ids(&mut self) -> Result { + match self.u8()? { + 0 => Ok(Ids(IdList::Count(self.u32()?))), + 1 => Ok(Ids(IdList::Listed(self.id_values()?))), + tag => Err(malformed(format!("unknown ids {tag}"))), + } + } + + fn column(&mut self) -> Result { + Ok(Column::new(&self.values()?)) + } + + /// Ids as values: `u32` ids, as writers without 64-bit integers send them, read as the `u64` every + /// numbered id is. + fn id_values(&mut self) -> Result { + let values = self.values()?; + Ok(match values.array { + Array::U32(ids) => { + Values { array: Array::U64(ids.iter().map(|&id| u64::from(id)).collect::>().into()), ..values } + } + _ => values, + }) + } + + fn table(&mut self) -> Result { + let name = self.name()?; + let ids = match self.ids()? { + Ids(IdList::Count(n)) => RowIds::Count(n), + Ids(IdList::Listed(values)) => RowIds::Listed(Column::new(&values)), + }; + let structure = Version::next(); + let mut table = Table { name, ids, index: Arc::default(), fields: Vec::new(), structure, order: structure }; + let fields = self.len(1)?; + self.charge(fields, size_of::<(Name, Field)>())?; + for _ in 0..fields { + let name = self.name()?; + let field = match self.u8()? { + FIELD_VALUES => Field::Values(self.column()?, Version::next()), + FIELD_REFERENCE => { + let to = self.name()?; + Field::Reference(Reference::new(to, Column::new(&self.id_values()?))) + } + FIELD_SAMPLED => Field::Sampled(self.samples().map_err(|e| e.at(&name))?, Version::next()), + tag => return Err(malformed(format!("unknown field {tag}"))), + }; + table.insert(name, field); + } + Ok(table) + } + + /// A sampled field: its runs put in level by level, each level's buckets that follow from the + /// level below written before its own runs. + fn samples(&mut self) -> Result { + let rows = self.u32()? as usize; + let first = self.u64()?; + let frames = self.u64()?; + let end = first.checked_add(frames).ok_or_else(|| malformed("too many frames"))?; + let levels = u32::from(self.u8()?); + if levels > MAX_LEVEL { + return Err(malformed("unsupported sample level")); + } + let count = self.len(13)?; + self.charge(count, size_of::<(Run, Vec, Vec)>())?; + let runs = (0..count).map(|_| self.run(rows)).collect::>>()?; + let mut samples = Samples::from_frame(first); + if runs.iter().any(|(run, ..)| run.level > levels) { + return Err(malformed("run above sample levels")); + } + for level in 0..=levels { + if level > 0 { + samples.derive(level); + } + for (run, at, values) in runs.iter().filter(|(run, ..)| run.level == level) { + samples.insert(run, at, values, rows)?; + } + } + samples.reads(first..end); + Ok(samples) + } + + /// A run of entries of `rows` rows: what it holds, its coordinates, and its values. + fn run(&mut self, rows: usize) -> Result<(Run, Vec, Vec)> { + let level = u32::from(self.u8()?); + if level > MAX_LEVEL { + return Err(malformed(format!("no level {level}"))); + } + let first = self.u64()?; + let n = self.u32()?; + let run = Run { + level, + entries: first..first.checked_add(u64::from(n)).ok_or_else(|| malformed("too many entries"))?, + }; + let n = n as usize; + let coordinates = n.checked_mul(samples::coordinates(level)); + let values = n.checked_mul(rows).and_then(|v| v.checked_mul(samples::sides(level))); + let (Some(coordinates), Some(values)) = (coordinates, values) else { return Err(malformed("too large")) }; + let at = self.vec(coordinates)?; + let values = self.vec(values)?; + Ok((run, at, values)) + } + + fn values(&mut self) -> Result { + let store = self.u8()?; + let len = self.u32()? as usize; + let array = match store { + STORE_F64 => Array::F64(self.vec::(len)?.into()), + STORE_F32 => Array::F32(self.vec::(len)?.into()), + STORE_I32 => Array::I32(self.vec::(len)?.into()), + STORE_U32 => Array::U32(self.vec::(len)?.into()), + STORE_U64 => Array::U64(self.vec::(len)?.into()), + STORE_BOOL => Array::Bool(Bits::from_words(self.vec(len.div_ceil(64))?, len)), + STORE_TEXT => { + let offsets = self.vec::(len.checked_add(1).ok_or_else(|| malformed("too many text values"))?)?; + let n = self.len(1)?; + self.charge(n, 2)?; + let bytes = String::from_utf8(self.take(n)?.to_vec()).map_err(|_| malformed("text is not UTF-8"))?; + Array::Text(Text::from_parts(offsets, bytes).ok_or_else(|| malformed("text offsets"))?) + } + STORE_GEOMETRY => { + let depth = self.u8()?; + let levels = (0..depth.min(4)) + .map(|_| { + let n = self.len(4)?; + self.vec::(n) + }) + .collect::>>()?; + let n = self.len(16)?; + let flat: Vec = self.vec(n * 2)?; + let coords = flat.as_chunks::<2>().0.to_vec(); + let geometry = + Geometry::from_parts(depth, levels, coords).ok_or_else(|| malformed("geometry offsets"))?; + if geometry.len() != len { + return Err(malformed("geometry length")); + } + Array::Geometry(geometry) + } + store => return Err(malformed(format!("unknown storage {store}"))), + }; + let valid = match self.u8()? { + 0 => None, + 1 => Some(Bits::from_words(self.vec(len.div_ceil(64))?, len)), + _ => return Err(malformed("validity")), + }; + Ok(Values { array, valid }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Data, Row, Value}; + + #[test] + fn v1_fixture_and_large_indexes_are_stable() { + let hex = include_str!("../../tests/fixtures/latk-v1.hex").trim(); + let bytes: Vec = + (0..hex.len()).step_by(2).map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap()).collect(); + let patch = Patch::new().frames("T", "v", 0, (1_u64 << 32) + 3, [0.0, 1.0], [1.0, 2.0]); + assert_eq!(patch.to_bytes(), bytes); + assert_eq!(Patch::from_bytes(&bytes).unwrap().to_bytes(), bytes); + let mut data = Data::new("test"); + data.apply(Patch::new().replace(Table::new("T", Ids::count(1))).extend(patch)).unwrap(); + data.apply(Patch::new().append([2.0], "T", [("v", vec![3.0_f32])])).unwrap(); + assert_eq!(data.span(), Some([0.0, 2.0])); + assert_eq!(Data::from_bytes(&data.to_bytes()).unwrap().to_bytes(), data.to_bytes()); + let mut files = std::collections::HashMap::new(); + data.to_tiles(8, |path, bytes| { + files.insert(path.to_owned(), bytes.to_vec()); + Ok(()) + }) + .unwrap(); + assert!(files.keys().any(|p| p.contains("536870912"))); + let mut version = bytes.clone(); + version[4] = 2; + assert!(Patch::from_bytes(&version).is_err()); + let mut flags = bytes.clone(); + flags[6] = 1; + assert!(Patch::from_bytes(&flags).is_err()); + assert!(matches!( + Patch::decode_with_limits(&bytes, DecodeLimits { frame_bytes: 1024, decoded_bytes: 1 }), + Err(Error::Limit(_)) + )); + } + + #[test] + fn frame_overflow_is_atomic_and_high_levels_round_trip() { + let mut data = Data::new("test"); + data.apply(Patch::new().replace(Table::new("T", Ids::count(1))).frames( + "T", + "v", + 0, + u64::MAX - 1, + [0.0], + [1.0], + )) + .unwrap(); + let before = data.to_bytes(); + assert!(data.apply(Patch::new().append([1.0], "T", [("v", vec![2.0_f32])])).is_err()); + assert_eq!(data.to_bytes(), before); + let mut data = Data::new("test"); + data.apply(Patch::new().replace(Table::new("T", Ids::count(1))).frames( + "T", + "v", + 12, + 0, + [0.0, 1.0], + [1.0, 2.0], + )) + .unwrap(); + assert_eq!(Data::from_bytes(&data.to_bytes()).unwrap().to_bytes(), data.to_bytes()); + } + + fn grid() -> Data { + let mut data = Data::new("grid"); + data.apply( + Patch::new() + .axis("time", "s") + .set( + Table::new("Bus", vec!["a", "b", "c"]) + .field("kv", vec![Some(230.0), None, Some(115.0)]) + .field("name", vec!["North", "Mid", "South"]) + .field("point", vec![[0.0, 1.0], [2.0, 3.0], [4.0, 5.0]]) + .field("open", vec![true, false, true]), + ) + .set(Table::new("Branch", Ids::count(2)).reference("from", "Bus", vec!["a", "b"]).reference( + "to", + "Bus", + vec!["b", "c"], + )), + ) + .expect("valid"); + data.apply(Patch::new().append([1.0], "Bus", [("vm", vec![1.0, 1.01, 0.99])])).expect("frame"); + data.apply(Patch::new().append([2.0], "Bus", [("vm", vec![1.02, f64::NAN, 0.98])])).expect("frame"); + data + } + + #[test] + fn datasets_round_trip() { + let data = grid(); + let bytes = data.to_bytes(); + let back = Data::from_bytes(&bytes).expect("decodes"); + assert_eq!(back.name(), "grid"); + assert_eq!(back.axis(), Some(("time", "s"))); + let bus = |id: &str| Row::new("grid", "Bus", id); + for field in ["kv", "name", "point", "open", "vm"] { + for id in ["a", "b", "c"] { + assert_eq!(back.get(&bus(id), field), data.get(&bus(id), field), "{field} of {id}"); + } + } + assert_eq!(back.get_at(&bus("a"), "vm", 1.5), Some(Value::Number(f64::from(1.0_f32)))); + assert_eq!(back.get(&Row::new("grid", "Branch", 1_u64), "to"), Some(Value::Row(bus("c")))); + assert_eq!(back.to_bytes(), bytes, "encoding is deterministic"); + } + + #[test] + fn patches_round_trip() { + let patch = Patch::new().remove("Bus", vec!["a"]).append([3.0], "Bus", [("vm", vec![1.0, 1.0, 1.0])]); + let bytes = patch.to_bytes(); + assert_eq!(Patch::from_bytes(&bytes).expect("decodes").to_bytes(), bytes); + assert!(Data::from_bytes(&bytes).is_err()); + } + + #[test] + fn patches_back_to_back_decode_one_by_one() { + let patches = [grid().to_patch(), Patch::new().forget(1.5), Patch::new().remove("Bus", vec!["a"])]; + let stream: Vec = patches.iter().flat_map(Patch::to_bytes).collect(); + let (mut at, mut read) = (0, Vec::new()); + // Arriving a few bytes at a time, as from a socket. + for end in (0..=stream.len()).step_by(5).chain([stream.len()]) { + while let Some((patch, used)) = Patch::decode(&stream[at..end], usize::MAX).expect("valid so far") { + read.push(patch.to_bytes()); + at += used; + } + } + assert_eq!(read, patches.iter().map(Patch::to_bytes).collect::>()); + assert!(Patch::decode(b"LATX....", 64).is_err(), "not latkit bytes, however many follow"); + // A length past the limit fails at once rather than waiting for bytes that may never come. + let long = Patch::new().set(Table::new("Bus", Ids::count(1)).field("name", vec!["x".repeat(100)])).to_bytes(); + assert!(matches!(Patch::decode(&long[..70], 64), Err(Error::Limit(_)))); + assert!(Patch::decode(&long[..70], 1 << 20).expect("short").is_none()); + } + + #[test] + fn frames_keep_their_numbers_through_bytes_and_gathers() { + let mut data = grid(); + data.apply(Patch::new().forget(1.5)).expect("forget"); + let first = |data: &Data| match data.table("Bus").and_then(|t| t.field_named("vm")) { + Some(Field::Sampled(samples, _)) => samples.start(), + _ => panic!("sampled"), + }; + assert_eq!(first(&data), 1); + assert_eq!(first(&Data::from_bytes(&data.to_bytes()).expect("decodes")), 1); + data.apply(Patch::new().remove("Bus", vec!["b"])).expect("remove"); + assert_eq!(first(&data), 1, "rows removed keep the frames' numbers"); + } + + #[test] + fn time_tiles_round_trip_with_their_holes() { + let mut data = grid(); + // The bucket of frames 64..72, and frames 200 and 201, past a hole. + let bucket = Patch::new().frames("Bus", "vm", 1, 8, [64.0, 71.0], [0.9, 0.95, 0.97, 1.1, 1.05, 1.0]); + let tile = bucket.frames("Bus", "vm", 0, 200, [200.0, 201.0], [1.0, 1.0, 1.0, 0.5, 0.5, 0.5]); + let bytes = tile.to_bytes(); + assert_eq!(Patch::from_bytes(&bytes).expect("decodes").to_bytes(), bytes); + data.apply(tile.clone()).expect("tiles"); + assert!(data.apply(tile).is_err(), "entries held already"); + let back = Data::from_bytes(&data.to_bytes()).expect("decodes"); + assert_eq!(back.to_bytes(), data.to_bytes()); + let bus = |id: &str| Row::new("grid", "Bus", id); + assert_eq!(back.get_at(&bus("c"), "vm", 201.5), Some(Value::Number(0.5))); + assert_eq!(back.get_at(&bus("a"), "vm", 100.0), None, "a hole holds no frame"); + assert_eq!(back.describe().span, Some([1.0, 201.0])); + } + + #[test] + fn malformed_bytes_are_invalid_not_panics() { + let bytes = grid().to_bytes(); + for end in 0..bytes.len() { + assert!(Data::from_bytes(&bytes[..end]).is_err()); + } + let mut flipped = bytes.clone(); + for i in (0..flipped.len()).step_by(7) { + flipped[i] ^= 0x5a; + let _ = Data::from_bytes(&flipped); + } + } +} diff --git a/crates/latkit/src/data/column.rs b/crates/latkit/src/data/column.rs new file mode 100644 index 00000000..d8aefba9 --- /dev/null +++ b/crates/latkit/src/data/column.rs @@ -0,0 +1,353 @@ +use std::sync::Arc; + +use super::name::PageId; +use super::values::{Kind, Picks, Value, Values}; +use crate::Result; + +/// Rows per page: pages are the unit of sharing between versions and of upload to the GPU. +pub(crate) const PAGE_BITS: u32 = 16; +pub(crate) const PAGE_ROWS: usize = 1 << PAGE_BITS; +pub(crate) const PAGE_MASK: usize = PAGE_ROWS - 1; + +/// Writes a page remembers back: past them, it reads as written whole. +const REMEMBERED: u8 = 8; + +/// One page of a column: up to [`PAGE_ROWS`] values, the id of exactly these contents, and, when it +/// was written over another page, which page and which rows. +#[derive(Clone, Debug)] +pub(crate) struct Page { + pub(crate) id: PageId, + pub(crate) values: Values, + pub(crate) written: Option>, +} + +/// What a page was written from: the page it copied, the rows written over it there, offsets into +/// the page, and how that page was written in turn. +#[derive(Debug)] +pub(crate) struct Written { + pub(crate) from: PageId, + pub(crate) rows: Box<[u32]>, + pub(crate) before: Option>, + depth: u8, +} + +impl Page { + pub(crate) fn new(values: Values) -> Page { + Page { id: PageId::next(), values, written: None } + } + + /// `values`: page `old` with `rows` written over it, offsets into the page. + fn over(values: Values, old: &Page, rows: Vec) -> Page { + let before = old.written.clone().filter(|w| w.depth < REMEMBERED); + let depth = before.as_ref().map_or(1, |w| w.depth + 1); + let written = Written { from: old.id, rows: rows.into(), before, depth }; + Page { id: PageId::next(), values, written: Some(Arc::new(written)) } + } + + /// The rows written since page `before`, offsets into the page, in order: `None` unless this page + /// was written over it, a few writes back at most. + pub(crate) fn rows_since(&self, before: PageId) -> Option> { + if self.id == before { + return Some(Vec::new()); + } + let mut rows = Vec::new(); + let mut at = self.written.as_deref(); + while let Some(written) = at { + rows.extend_from_slice(&written.rows); + if written.from == before { + rows.sort_unstable(); + rows.dedup(); + return Some(rows); + } + at = written.before.as_deref(); + } + None + } +} + +/// A field's values in pages. Writes replace only the pages they touch; others keep their ids. +#[derive(Clone, Debug)] +pub(crate) struct Column { + len: usize, + pages: Arc<[Page]>, + /// An empty slice of the column's storage, so an empty column still knows what it holds. + like: Values, +} + +impl Column { + pub(crate) fn new(values: &Values) -> Column { + let len = values.len(); + let pages = (0..len.div_ceil(PAGE_ROWS)) + .map(|p| Page::new(values.slice(p * PAGE_ROWS..len.min((p + 1) * PAGE_ROWS)))) + .collect(); + Column { len, pages, like: values.slice(0..0) } + } + + /// `len` missing values stored like `like`. + pub(crate) fn missing(like: &Values, len: usize) -> Column { + let empty = Column { len: 0, pages: Arc::new([]), like: like.slice(0..0) }; + empty.write(len, &[], &empty).expect("same storage") + } + + /// A column of whole pages; every page but the last holds [`PAGE_ROWS`] values. + pub(crate) fn from_pages(pages: Vec, like: &Values) -> Column { + debug_assert!(pages.iter().rev().skip(1).all(|p| p.len() == PAGE_ROWS)); + let len = pages.iter().map(Values::len).sum(); + Column { len, pages: pages.into_iter().map(Page::new).collect(), like: like.slice(0..0) } + } + + /// A column of `pages` as they are, their ids kept; every page but the last holds + /// [`PAGE_ROWS`] values. + pub(crate) fn of_pages(pages: Vec, like: &Values) -> Column { + debug_assert!(pages.iter().rev().skip(1).all(|p| p.values.len() == PAGE_ROWS)); + let len = pages.iter().map(|p| p.values.len()).sum(); + Column { len, pages: pages.into(), like: like.slice(0..0) } + } + + pub(crate) fn len(&self) -> usize { + self.len + } + + pub(crate) fn kind(&self) -> Kind { + self.like.kind() + } + + pub(crate) fn pages(&self) -> &[Page] { + &self.pages + } + + pub(crate) fn like(&self) -> &Values { + &self.like + } + + pub(crate) fn get(&self, row: usize) -> Option { + self.pages.get(row >> PAGE_BITS)?.values.get(row & PAGE_MASK) + } + + /// The column with `len` rows (at least the current count) and `writes` applied. + /// + /// `writes` are `(row, row of source)` sorted by row with no row twice; a [`HOLE`](super::values::HOLE) + /// for the row of source writes a missing value. Pages that no write touches and whose length does + /// not change keep their ids; new rows not written are missing. + pub(crate) fn write(&self, len: usize, writes: &[(usize, usize)], source: &Column) -> Result { + debug_assert!(len >= self.len); + debug_assert!(writes.windows(2).all(|w| w[0].0 < w[1].0)); + let count = len.div_ceil(PAGE_ROWS); + let mut pages: Vec = Vec::with_capacity(count); + let mut sources: Vec<&Values> = vec![&self.like]; + sources.extend(source.pages.iter().map(|p| &p.values)); + sources.push(&source.like); + let mut next = 0; + for p in 0..count { + let start = p * PAGE_ROWS; + let page_len = (len - start).min(PAGE_ROWS); + let first = next; + while next < writes.len() && writes[next].0 < start + page_len { + next += 1; + } + let page_writes = &writes[first..next]; + let old = self.pages.get(p); + if page_writes.is_empty() + && let Some(old) = old + && old.values.len() == page_len + { + pages.push(old.clone()); + continue; + } + let mut from = vec![None; page_len]; + for &(row, k) in page_writes { + from[row - start] = Some(k); + } + sources[0] = old.map_or(&self.like, |o| &o.values); + let kept = sources[0].len(); + let values = Values::assemble(&sources, Picks::Writes { from: &from, kept })?; + pages.push(match old { + // The page remembers what it was written over: the rows written, and those past its end. + Some(old) => { + let mut rows: Vec = page_writes.iter().map(|&(row, _)| (row - start) as u32).collect(); + rows.extend(kept as u32..page_len as u32); + Page::over(values, old, rows) + } + None => Page::new(values), + }); + } + Ok(Column { len, pages: pages.into(), like: self.like.clone() }) + } + + /// The rows written since `before`, which this column was written from a few writes back at most, + /// in order: `None` where a page of it was not, or the number of rows changed. A row written the + /// value it held counts. + pub(crate) fn rows_since(&self, before: &Column) -> Option> { + if self.len != before.len { + return None; + } + let mut rows = Vec::new(); + for (p, (now, then)) in self.pages.iter().zip(before.pages.iter()).enumerate() { + if now.id != then.id { + rows.extend(now.rows_since(then.id)?.into_iter().map(|r| p * PAGE_ROWS + r as usize)); + } + } + Some(rows) + } + + /// Every value in row order, as one run: a single page's without copying, else the pages copied + /// one after another. + pub(crate) fn values(&self) -> Values { + match &self.pages[..] { + [] => self.like.clone(), + [page] => page.values.clone(), + pages => Values::concat(&pages.iter().map(|p| &p.values).collect::>()), + } + } + + /// The rows whose values differ from `before`'s, in order: of the rows written since, while the + /// pages remember them, those that now hold another value; else every row of the pages that + /// changed, compared. + pub(crate) fn changed_since(&self, before: &Column) -> Vec { + let Some(written) = self.rows_since(before) else { return self.differing(before) }; + written + .into_iter() + .filter(|&row| !self.holds(row, &before.pages[row / PAGE_ROWS].values, row % PAGE_ROWS)) + .collect() + } + + /// Whether row `row` holds what row `at` of `values` does. + pub(crate) fn holds(&self, row: usize, values: &Values, at: usize) -> bool { + self.pages[row / PAGE_ROWS].values.same_row(row % PAGE_ROWS, values, at) + } + + /// The rows whose values differ from `before`'s, in order. A page both share holds the same values, + /// so only the pages that changed are compared, row by row; rows past the shorter column differ. + pub(crate) fn differing(&self, before: &Column) -> Vec { + let mut rows = Vec::new(); + for p in 0..self.pages.len().max(before.pages.len()) { + let (now, then) = (self.pages.get(p), before.pages.get(p)); + if let (Some(a), Some(b)) = (now, then) + && a.id == b.id + { + continue; + } + let (a, b) = (now.map_or(&self.like, |a| &a.values), then.map_or(&before.like, |b| &b.values)); + let (start, both) = (p * PAGE_ROWS, a.len().min(b.len())); + rows.extend((0..a.len().max(b.len())).filter(|&i| i >= both || !a.same_row(i, b, i)).map(|i| start + i)); + } + rows + } + + /// The column of rows `rows`, in that order, missing for a [`HOLE`](super::values::HOLE). Leading + /// pages whose rows are unchanged keep their ids. + pub(crate) fn gather(&self, rows: &[usize]) -> Column { + let kept = rows.iter().enumerate().take_while(|&(i, &r)| i == r).count(); + let kept_pages = (kept / PAGE_ROWS).min(rows.len() / PAGE_ROWS); + let sources: Vec<&Values> = std::iter::once(&self.like).chain(self.pages.iter().map(|p| &p.values)).collect(); + let mut pages: Vec = self.pages[..kept_pages].to_vec(); + for p in kept_pages..rows.len().div_ceil(PAGE_ROWS) { + let chunk = &rows[p * PAGE_ROWS..rows.len().min((p + 1) * PAGE_ROWS)]; + pages.push(Page::new(Values::assemble(&sources, Picks::Rows(chunk)).expect("one storage"))); + } + Column { len: rows.len(), pages: pages.into(), like: self.like.clone() } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn numbers(n: usize) -> Values { + Values::from((0..n).map(|i| i as f64).collect::>()) + } + + #[test] + fn writes_touch_only_their_pages() { + let column = Column::new(&numbers(PAGE_ROWS * 2 + 10)); + let source = Column::new(&Values::from(vec![-1.0_f64])); + let written = column.write(column.len(), &[(PAGE_ROWS + 3, 0)], &source).expect("numbers"); + assert_eq!(written.pages()[0].id, column.pages()[0].id); + assert_ne!(written.pages()[1].id, column.pages()[1].id); + assert_eq!(written.pages()[2].id, column.pages()[2].id); + assert_eq!(written.get(PAGE_ROWS + 3), Some(Value::Number(-1.0))); + assert_eq!(written.get(PAGE_ROWS + 4), Some(Value::Number((PAGE_ROWS + 4) as f64))); + } + + #[test] + fn holes_write_and_gather_missing() { + let column = Column::new(&numbers(4)); + let source = Column::new(&Values::from(vec![7.0_f64])); + let written = column.write(5, &[(1, super::super::values::HOLE), (4, 0)], &source).expect("numbers"); + assert_eq!( + (written.get(0), written.get(1), written.get(4)), + (Some(Value::Number(0.0)), None, Some(Value::Number(7.0))) + ); + let gathered = column.gather(&[3, super::super::values::HOLE, 0]); + assert_eq!((gathered.get(0), gathered.get(1)), (Some(Value::Number(3.0)), None)); + } + + #[test] + fn growth_pads_with_missing() { + let column = Column::new(&numbers(3)); + let grown = column.write(5, &[(4, 0)], &Column::new(&Values::from(vec![9.0_f64]))).expect("numbers"); + assert_eq!(grown.len(), 5); + assert_eq!(grown.get(3), None); + assert_eq!(grown.get(4), Some(Value::Number(9.0))); + assert_eq!(Column::missing(&numbers(0), 4).get(2), None); + } + + #[test] + fn differing_rows_are_found_in_the_pages_that_changed() { + let column = Column::new(&numbers(PAGE_ROWS * 2 + 10)); + let source = Column::new(&Values::from(vec![-1.0_f64, (PAGE_ROWS + 4) as f64])); + // Row 3 of the second page changes; its row 4 is written the value it already held. + let written = column.write(column.len(), &[(PAGE_ROWS + 3, 0), (PAGE_ROWS + 4, 1)], &source); + let written = written.expect("numbers"); + assert_eq!(written.differing(&column), [PAGE_ROWS + 3]); + assert_eq!(column.differing(&column), Vec::::new(), "a column holds what it holds"); + let longer = column.write(column.len() + 2, &[], &source).expect("numbers"); + assert_eq!(longer.differing(&column), [PAGE_ROWS * 2 + 10, PAGE_ROWS * 2 + 11], "rows past it differ"); + } + + #[test] + fn written_pages_remember_the_rows_written_since() { + let column = Column::new(&numbers(PAGE_ROWS + 10)); + let source = Column::new(&Values::from(vec![-1.0_f64, -2.0])); + let once = column.write(column.len(), &[(3, 0), (PAGE_ROWS + 4, 1)], &source).expect("numbers"); + let twice = once.write(once.len(), &[(5, 0)], &source).expect("numbers"); + assert_eq!(twice.rows_since(&column), Some(vec![3, 5, PAGE_ROWS + 4]), "every write since, in order"); + assert_eq!(twice.rows_since(&once), Some(vec![5])); + assert_eq!(twice.rows_since(&twice), Some(Vec::new())); + assert_eq!(column.rows_since(&twice), None, "nothing is written backward"); + assert_eq!(Column::new(&numbers(PAGE_ROWS + 10)).rows_since(&column), None, "nor from another column"); + let grown = column.write(column.len() + 2, &[], &source).expect("numbers"); + assert_eq!(grown.rows_since(&column), None, "rows added change the rows themselves"); + // A page remembers a few writes back; past them, it reads as written whole. + let mut near = once.clone(); + for _ in 1..REMEMBERED { + near = near.write(near.len(), &[(7, 0)], &source).expect("numbers"); + } + assert_eq!(near.rows_since(&column), Some(vec![3, 7, PAGE_ROWS + 4])); + let far = near.write(near.len(), &[(7, 0)], &source).expect("numbers"); + assert_eq!(far.rows_since(&column), None); + assert_eq!(far.rows_since(&near), Some(vec![7])); + } + + #[test] + fn rows_written_the_value_they_held_have_not_changed() { + let column = Column::new(&numbers(PAGE_ROWS + 10)); + // Row 4 holds 4. + let source = Column::new(&Values::from(vec![-1.0_f64, 4.0])); + let written = column.write(column.len(), &[(3, 0), (4, 1), (PAGE_ROWS + 4, 0)], &source).expect("numbers"); + assert_eq!(written.rows_since(&column), Some(vec![3, 4, PAGE_ROWS + 4]), "every row written"); + assert_eq!(written.changed_since(&column), vec![3, PAGE_ROWS + 4], "the rows whose values changed"); + let far = (0..REMEMBERED).fold(written, |c, _| c.write(c.len(), &[(3, 0)], &source).expect("numbers")); + assert_eq!(far.changed_since(&column), vec![3, PAGE_ROWS + 4], "compared where the pages forgot"); + } + + #[test] + fn gather_keeps_leading_pages() { + let column = Column::new(&numbers(PAGE_ROWS + 5)); + let rows: Vec = (0..PAGE_ROWS).chain([PAGE_ROWS + 2, PAGE_ROWS + 4]).collect(); + let gathered = column.gather(&rows); + assert_eq!(gathered.len(), PAGE_ROWS + 2); + assert_eq!(gathered.pages()[0].id, column.pages()[0].id); + assert_eq!(gathered.get(PAGE_ROWS + 1), Some(Value::Number((PAGE_ROWS + 4) as f64))); + } +} diff --git a/crates/latkit/src/data/dataset.rs b/crates/latkit/src/data/dataset.rs new file mode 100644 index 00000000..682d7a04 --- /dev/null +++ b/crates/latkit/src/data/dataset.rs @@ -0,0 +1,303 @@ +use std::hash::{Hash, Hasher}; +use std::sync::Arc; + +use rustc_hash::FxHasher; + +use super::name::{Name, Row, Version}; +use super::patch::{Appends, Op, Patch}; +use super::samples::Samples; +use super::table::{Field, Table}; +use super::values::Value; +use crate::{Error, Result}; + +/// A named collection of tables, changed in place by patches. +/// +/// Cloning is O(1) and a clone is a snapshot: [`apply`](Data::apply) changes only `self`, and every +/// page it does not write stays shared with earlier snapshots. +/// +/// ``` +/// # use latkit::{Data, Ids, Patch, Table}; +/// let mut grid = Data::new("grid"); +/// grid.apply( +/// Patch::new() +/// .axis("time", "s") +/// .replace(Table::new("Bus", vec![1_u64, 2]).field("kv", vec![230.0, 115.0])) +/// .replace(Table::new("Branch", Ids::count(1)).reference("from", "Bus", vec![1_u64]).reference("to", "Bus", vec![2_u64])), +/// )?; +/// grid.apply(Patch::new().append([0.0], "Bus", [("vm", vec![1.01, 0.99])]))?; +/// # Ok::<(), latkit::Error>(()) +/// ``` +#[derive(Clone)] +pub struct Data(pub(crate) Arc); + +#[derive(Clone)] +pub(crate) struct Inner { + pub(crate) name: Name, + pub(crate) axis: Option<(Name, Name)>, + /// Sorted by name. + pub(crate) tables: Vec
, + pub(crate) version: Version, + /// The version the dataset began at, which every version applied from it shares: a view eases + /// rows from one of them to the next, and replaces the rows of another dataset of the same name. + pub(crate) origin: Version, + /// Changes when a table, field, or kind is added or changed; marks recompile only then. + pub(crate) schema: u64, +} + +impl Data { + /// An empty dataset named `name`. + pub fn new(name: impl Into) -> Data { + let version = Version::next(); + Data(Arc::new(Inner { name: name.into(), axis: None, tables: Vec::new(), version, origin: version, schema: 0 })) + } + + /// The dataset's name. + pub fn name(&self) -> &Name { + &self.0.name + } + + /// The name and unit of the axis sampled fields are recorded over. + pub fn axis(&self) -> Option<(&str, &str)> { + self.0.axis.as_ref().map(|(name, unit)| (name.as_str(), unit.as_str())) + } + + /// Every table, by name. + pub fn tables(&self) -> impl Iterator + '_ { + self.0.tables.iter() + } + + /// The table named `name`. + pub fn table(&self, name: &str) -> Option<&Table> { + self.0.table(name) + } + + /// The axis coordinates the sampled fields span. + pub fn span(&self) -> Option<[f64; 2]> { + let spans = self.0.tables.iter().flat_map(|t| &t.fields).filter_map(|(_, field)| match field { + Field::Sampled(samples, _) => samples.span(), + _ => None, + }); + spans.reduce(|a, b| [a[0].min(b[0]), a[1].max(b[1])]) + } + + /// The value of `field` for `row`; a sampled field reads its last frame. + pub fn get(&self, row: &Row, field: &str) -> Option { + self.get_at(row, field, f64::INFINITY) + } + + /// The value of `field` for `row` at axis coordinate `at`: the last frame at or before it. + pub fn get_at(&self, row: &Row, field: &str, at: f64) -> Option { + if row.data != self.0.name { + return None; + } + let table = self.table(&row.table)?; + let index = table.row(row.id.as_ref())?; + match table.field_named(field)? { + Field::Reference(reference) => { + let Value::Number(target) = reference.rows.get(index)? else { return None }; + let target_table = self.table(&reference.to)?; + let id = target_table.ids.id(target as usize)?; + Some(Value::Row(Row { data: self.0.name.clone(), table: reference.to.clone(), id })) + } + _ => table.value(index, field, at), + } + } + + /// Applies every change in `patch`, or none of them when one is invalid. A patch to another + /// dataset is an error. + /// + /// The error's path names the change and part, such as `patch[1].Bus.kv`. + pub fn apply(&mut self, patch: impl Into) -> Result<()> { + let patch = patch.into(); + if let Some(data) = &patch.data + && *data != self.0.name + { + return Err(Error::invalid(format!("a patch to '{data}' applied to '{}'", self.0.name))); + } + if patch.ops.is_empty() { + return Ok(()); + } + let mut next = (*self.0).clone(); + let mut ops = patch.ops.into_iter().enumerate().peekable(); + while let Some((i, op)) = ops.next() { + let op = match op { + // A run of appends to the same fields of every row of a table records as one. + Op::Append { table, at, ids: None, fields } => { + let rows = next.table(&table).map(Table::len); + let mut run = Appends::new(table, at, fields); + while let Some((_, Op::Append { table, at, ids: None, fields })) = ops.peek() + && run.continues(table, at, fields, rows) + { + let Some((_, Op::Append { at, fields, .. })) = ops.next() else { break }; + run.push(at, fields); + } + run.op() + } + op => op, + }; + op.apply(&mut next).map_err(|e| e.at(i).at("patch"))?; + } + next.resolve()?; + next.schema = next.signature(); + next.version = Version::next(); + self.0 = Arc::new(next); + Ok(()) + } + + /// The patch to this dataset that builds it from an empty one. + pub fn to_patch(&self) -> Patch { + let mut patch = Patch::to(self.0.name.clone()); + if let Some((name, unit)) = &self.0.axis { + patch = patch.axis(name, unit); + } + self.0.tables.iter().fold(patch, |patch, table| patch.replace(table.clone())) + } + + /// The dataset as bytes: the patch to it that builds it. + pub fn to_bytes(&self) -> Vec { + self.to_patch().to_bytes() + } + + /// A dataset from [`to_bytes`](Data::to_bytes), or any bytes of a patch to a dataset. + pub fn from_bytes(bytes: &[u8]) -> Result { + let patch = Patch::from_bytes(bytes)?; + let Some(name) = patch.data.clone() else { + return Err(Error::invalid("the bytes hold a patch to no dataset").at("bytes")); + }; + let mut data = Data::new(name); + data.apply(patch)?; + Ok(data) + } + + /// A dataset from bytes: latkit's own, as [`to_bytes`](Data::to_bytes) writes them, or GeoJSON, + /// gzip-compressed or not. GeoJSON's features become rows of tables `points`, `lines`, and + /// `polygons` by their geometry, each with its geometry as field `geometry` and its properties as + /// fields. `name` names the dataset, as GeoJSON needs; latkit's bytes name their own unless given + /// one. + /// + /// ``` + /// let city = latkit::Data::read(br#"{"type": "Feature", "properties": {"name": "Hall"}, + /// "geometry": {"type": "Point", "coordinates": [-97.74, 30.27]}}"#, Some("city"))?; + /// assert_eq!(city.table("points").map(latkit::Table::len), Some(1)); + /// # Ok::<(), latkit::Error>(()) + /// ``` + pub fn read(bytes: &[u8], name: Option<&str>) -> Result { + if bytes.starts_with(b"LATK") { + let data = Data::from_bytes(bytes)?; + return Ok(match name { + Some(name) if name != data.name().as_str() => data.renamed(name), + _ => data, + }); + } + let name = name.ok_or_else(|| Error::invalid("GeoJSON names its dataset").at("name"))?; + crate::geo::geojson(name, bytes) + } + + /// The same tables as dataset `name`: another dataset, which views draw apart from this one. + #[must_use] + pub fn renamed(&self, name: impl Into) -> Data { + let version = Version::next(); + Data(Arc::new(Inner { name: name.into(), version, origin: version, ..(*self.0).clone() })) + } + + pub(crate) fn schema(&self) -> u64 { + self.0.schema + } + + /// The version the dataset began at; see [`Inner::origin`]. + pub(crate) fn origin(&self) -> Version { + self.0.origin + } + + /// Changes sampled field `field` of table `table` with `change`, starting it empty where the table + /// has no field of its name: what time tiles put in and let go of. Whether anything changed: not + /// where `change` says so, or where there is no such table or the field holds no samples. + pub(crate) fn sampled(&mut self, table: &str, field: &str, change: impl FnOnce(&mut Samples) -> bool) -> bool { + let Ok(i) = self.0.position(table) else { return false }; + let mut samples = match self.0.tables[i].field_named(field) { + None => Samples::default(), + Some(Field::Sampled(samples, _)) => samples.clone(), + Some(_) => return false, + }; + if !change(&mut samples) { + return false; + } + let mut next = (*self.0).clone(); + next.tables[i].insert(field.into(), Field::Sampled(samples, Version::next())); + next.schema = next.signature(); + next.version = Version::next(); + self.0 = Arc::new(next); + true + } + + /// A version of `self` holding `tables` instead, its name, axis, schema, and origin kept: what a + /// view draws of a dataset it draws in part, eased from one version to the next like `self`'s. + pub(crate) fn drawn(&self, mut tables: Vec
) -> Data { + tables.sort_by(|a, b| a.name.cmp(&b.name)); + Data(Arc::new(Inner { + name: self.0.name.clone(), + axis: self.0.axis.clone(), + tables, + version: Version::next(), + origin: self.0.origin, + schema: self.0.schema, + })) + } +} + +impl PartialEq for Data { + fn eq(&self, other: &Data) -> bool { + self.0.version == other.0.version + } +} + +impl std::fmt::Debug for Data { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Data").field("name", &self.0.name).field("tables", &self.0.tables).finish() + } +} + +impl Inner { + pub(crate) fn table(&self, name: &str) -> Option<&Table> { + let i = self.tables.binary_search_by(|t| t.name.as_str().cmp(name)).ok()?; + Some(&self.tables[i]) + } + + pub(crate) fn position(&self, name: &str) -> std::result::Result { + self.tables.binary_search_by(|t| t.name.as_str().cmp(name)) + } + + /// Resolves every reference whose ids or target rows changed. + fn resolve(&mut self) -> Result<()> { + for t in 0..self.tables.len() { + for f in 0..self.tables[t].fields.len() { + let (name, Field::Reference(reference)) = &self.tables[t].fields[f] else { continue }; + let target = self.table(&reference.to).ok_or_else(|| { + Error::invalid(format!("no table {}", reference.to)).at(name).at(&self.tables[t].name) + })?; + if !reference.stale(target.order, target.structure) { + continue; + } + let resolved = reference.resolve(target)?; + self.tables[t].fields[f].1 = Field::Reference(resolved); + } + } + Ok(()) + } + + /// A deterministic digest of every table's name and every field's name, kind, and target. + fn signature(&self) -> u64 { + let mut hasher = FxHasher::default(); + for table in &self.tables { + table.name.hash(&mut hasher); + for (name, field) in &table.fields { + name.hash(&mut hasher); + field.kind().hash(&mut hasher); + if let Field::Reference(reference) = field { + reference.to.hash(&mut hasher); + } + } + } + hasher.finish() + } +} diff --git a/crates/latkit/src/data/describe.rs b/crates/latkit/src/data/describe.rs new file mode 100644 index 00000000..922c7916 --- /dev/null +++ b/crates/latkit/src/data/describe.rs @@ -0,0 +1,148 @@ +//! Reading data back without moving it: what a dataset holds, and a sampled field's extremes over +//! spans of its axis. + +use super::column::{PAGE_BITS, PAGE_MASK}; +use super::dataset::Data; +use super::ids::Ids; +use super::name::Name; +use super::table::{Field, Table}; +use super::values::Kind; +use crate::{Error, Result}; + +/// The most values an envelope holds, least and greatest each: rows times spans. +const ENVELOPE_VALUES: usize = 1 << 26; + +/// What a dataset holds: its tables, their rows and fields, and the axis its sampled fields are +/// recorded over and span. +#[derive(Clone, PartialEq, Debug, serde::Serialize, schemars::JsonSchema)] +pub struct Description { + /// The dataset's name. + pub name: Name, + /// The axis's name and unit. + pub axis: Option<[Name; 2]>, + /// The first and last coordinates its sampled fields hold. + pub span: Option<[f64; 2]>, + /// Its tables, by name. + pub tables: Vec, +} + +/// A table described: its rows, and its fields by name. +#[derive(Clone, PartialEq, Debug, serde::Serialize, schemars::JsonSchema)] +pub struct TableDescription { + /// The table's name. + pub name: Name, + /// How many rows it has. + pub rows: usize, + /// Its fields, by name. + pub fields: Vec, +} + +/// A field described: what it holds, the table a reference names, the coordinates samples span. +#[derive(Clone, PartialEq, Debug, serde::Serialize, schemars::JsonSchema)] +pub struct FieldDescription { + /// The field's name. + pub name: Name, + /// What it holds. + pub kind: Kind, + /// The table a reference names. + #[serde(skip_serializing_if = "Option::is_none")] + pub to: Option, + /// The first and last coordinates a sampled field holds. + #[serde(skip_serializing_if = "Option::is_none")] + pub span: Option<[f64; 2]>, +} + +impl Data { + /// What the dataset holds: tables, rows, fields and their kinds, the axis and its span. + pub fn describe(&self) -> Description { + Description { + name: self.name().clone(), + axis: self.axis().map(|(name, unit)| [name.into(), unit.into()]), + span: self.span(), + tables: self.tables().map(Table::describe).collect(), + } + } +} + +impl Table { + /// What the table holds: its rows, and its fields' kinds, targets, and spans. + pub fn describe(&self) -> TableDescription { + let fields = self.fields.iter().map(|(name, field)| FieldDescription { + name: name.clone(), + kind: field.kind(), + to: match field { + Field::Reference(reference) => Some(reference.to.clone()), + _ => None, + }, + span: match field { + Field::Sampled(samples, _) => samples.span(), + _ => None, + }, + }); + TableDescription { name: self.name.clone(), rows: self.len(), fields: fields.collect() } + } + + /// Each row's least and greatest value of sampled field `field` over `spans` equal spans of the + /// axis from `range[0]` to `range[1]`: of every row, or of the rows `ids` names, in its order. A + /// span reads the coarsest levels of detail the field holds that fit inside it, so it costs a few + /// reads, however many frames it covers; where the field holds only coarser ones, as time tiles + /// still loading leave it, those stand in. + pub fn envelope(&self, field: &str, range: [f64; 2], spans: usize, ids: Option<&Ids>) -> Result { + let Some(Field::Sampled(samples, _)) = self.field_named(field) else { + return Err(Error::invalid("not a sampled field").at(field)); + }; + if !(range[0].is_finite() && range[1].is_finite() && range[0] <= range[1]) || spans == 0 { + return Err(Error::invalid("an envelope spans a finite range, in one span or more")); + } + let rows: Vec = match ids { + None => (0..self.len()).collect(), + Some(ids) => (0..ids.len()) + .map(|i| ids.key(i).and_then(|key| self.row(key)).ok_or_else(|| Error::invalid("no such row").at(i))) + .collect::>()?, + }; + if rows.len().saturating_mul(spans) > ENVELOPE_VALUES { + return Err(Error::Limit( + format!("an envelope holds at most {ENVELOPE_VALUES} values: rows times spans").into(), + )); + } + let width = (range[1] - range[0]) / spans as f64; + let at: Vec = + (0..=spans).map(|s| if s == spans { range[1] } else { range[0] + width * s as f64 }).collect(); + // A span holds the frames from its start up to the next span's; the last holds its end too. + let bounds: Vec = at.iter().enumerate().map(|(s, &t)| samples.bound(t, s == spans)).collect(); + let pieces: Vec> = bounds.windows(2).map(|b| samples.pieces(b[0]..b[1])).collect(); + let mut least = vec![f32::NAN; rows.len() * spans]; + let mut greatest = least.clone(); + // Rows by block, so each piece's page is read once for all of a block's rows. + let mut by_block: Vec<(usize, usize)> = + rows.iter().enumerate().map(|(i, &row)| (row >> PAGE_BITS, i)).collect(); + by_block.sort_unstable(); + for run in by_block.chunk_by(|a, b| a.0 == b.0) { + let block = run[0].0; + let mut extent = + vec![[f32::NAN; 2]; run.iter().map(|&(_, i)| (rows[i] & PAGE_MASK) + 1).max().unwrap_or(0)]; + for (s, pieces) in pieces.iter().enumerate() { + extent.fill([f32::NAN; 2]); + for &piece in pieces { + samples.fold(block, piece, &mut extent); + } + for &(_, i) in run { + let [lo, hi] = extent[rows[i] & PAGE_MASK]; + (least[i * spans + s], greatest[i * spans + s]) = (lo, hi); + } + } + } + Ok(Envelope { at, least, greatest }) + } +} + +/// Rows' least and greatest values of a sampled field over spans of its axis. +#[derive(Clone, PartialEq, Debug, serde::Serialize)] +pub struct Envelope { + /// Where each span starts, then where the last ends: one more coordinate than spans. + pub at: Vec, + /// Each row's least value in each span, row after row: NaN where it has none. + pub least: Vec, + /// Each row's greatest value in each span, row after row: NaN where it has none. + pub greatest: Vec, +} diff --git a/crates/latkit/src/data/forms.rs b/crates/latkit/src/data/forms.rs new file mode 100644 index 00000000..a62d1ef9 --- /dev/null +++ b/crates/latkit/src/data/forms.rs @@ -0,0 +1,766 @@ +//! What JSON writes for data, decoded once: a patch's changes, a table's fields, values, and ids. A +//! slice of a file is the one form read later, by [`Patch::load`] through a host; everything else is +//! decoded as it is read. JavaScript writes the byte frames instead. + +use std::fmt; +use std::sync::Arc; + +use std::borrow::Cow; + +use schemars::{JsonSchema, Schema, SchemaGenerator, json_schema}; +use serde::Deserialize; +use serde::de::{self, DeserializeSeed, Deserializer, IgnoredAny, MapAccess, SeqAccess, Visitor}; + +use super::ids::Ids; +use super::name::Id; +use super::patch::{Op, Patch}; +use super::table::Table; +use super::values::{Value, Values}; +use crate::{Error, Result}; + +/// The largest whole number a number names an id by when written with a fraction: 2^53 − 1. +const SAFE: f64 = 9_007_199_254_740_991.0; + +const NUMERIC_ID: &str = "a numeric id is a whole number from 0 to 2^53 - 1"; + +/// A dataset: its name and the patch that builds it. +#[derive(Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] +pub(crate) struct DataForm { + pub(crate) name: String, + #[serde(default)] + pub(crate) patch: Vec, +} + +/// One change of a patch, named by the method that makes it. +#[derive(Deserialize, JsonSchema)] +#[serde(rename_all = "lowercase", deny_unknown_fields)] +#[schemars(rename = "Change")] +pub(crate) enum OpForm { + /// Names the axis sampled fields are recorded over, such as `time` in `s`. + Axis { name: String, unit: String }, + /// Replaces a table with these rows and fields, or adds it. + Replace(TableForm), + /// Writes fields for these rows: rows with known ids change, others are added, and fields left + /// out keep their values. + Set(TableForm), + /// Removes the rows with these ids. + Remove { table: String, ids: IdsForm }, + /// Records a frame at each axis coordinate of `at`: for each field, a value per row at every + /// coordinate, frame-major; of every row, or of the rows `ids` names, the rest holding their last + /// values. + Append { + at: At, + table: String, + #[serde(default)] + ids: Option, + fields: Fields, + }, + /// Forgets every sampled field's frames before axis coordinate `before`. + Forget { before: f64 }, + /// Holds a run of sampled field `field`'s entries of level `level`, numbered from `first`: at + /// level 0 frames, each a coordinate in `at` and a value per row in `values`; at level `k` buckets + /// of `8^k` frames, each its first and last frame's coordinates, and each row's least value over + /// each bucket, then each row's greatest. Null is missing. + Frames { + table: String, + field: String, + #[serde(default)] + level: u32, + first: u64, + at: Vec, + values: Vec>, + }, +} + +#[derive(Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] +#[schemars(inline)] +pub(crate) struct TableForm { + table: String, + ids: IdsForm, + #[serde(default)] + fields: Fields, +} + +/// One axis coordinate, or several. +#[derive(Deserialize, JsonSchema)] +#[serde(untagged)] +#[schemars(inline)] +pub(crate) enum At { + One(f64), + Many(Vec), +} + +/// A dataset's JSON document. +impl JsonSchema for super::dataset::Data { + fn schema_name() -> Cow<'static, str> { + "Data".into() + } + + fn json_schema(generator: &mut SchemaGenerator) -> Schema { + DataForm::json_schema(generator) + } +} + +/// A patch's JSON: its changes in order. +impl JsonSchema for Patch { + fn schema_name() -> Cow<'static, str> { + "Patch".into() + } + + fn json_schema(generator: &mut SchemaGenerator) -> Schema { + >::json_schema(generator) + } +} + +impl JsonSchema for Ids { + fn schema_name() -> Cow<'static, str> { + "Ids".into() + } + + fn json_schema(generator: &mut SchemaGenerator) -> Schema { + IdsForm::json_schema(generator) + } +} + +impl JsonSchema for IdsForm { + fn schema_name() -> Cow<'static, str> { + "Ids".into() + } + + fn json_schema(generator: &mut SchemaGenerator) -> Schema { + let id = generator.subschema_for::>(); + json_schema!({ + "description": "Row ids: numbers or texts (null leaves a reference unwired), or `{count}` naming rows 0..count.", + "anyOf": [ + { "type": "array", "items": id }, + { + "type": "object", + "properties": { "count": { "type": "integer", "minimum": 0, "maximum": u32::MAX } }, + "required": ["count"], + "additionalProperties": false, + }, + ], + }) + } +} + +impl JsonSchema for Fields { + fn inline_schema() -> bool { + true + } + + fn schema_name() -> Cow<'static, str> { + "Fields".into() + } + + fn json_schema(generator: &mut SchemaGenerator) -> Schema { + let column = Column::json_schema(generator); + json_schema!({ "description": "Fields by name, in the order written.", "type": "object", "additionalProperties": column }) + } +} + +impl JsonSchema for Column { + fn schema_name() -> Cow<'static, str> { + "Column".into() + } + + fn json_schema(generator: &mut SchemaGenerator) -> Schema { + let element = generator.subschema_for::(); + let ids = generator.subschema_for::(); + let dtype = generator.subschema_for::(); + json_schema!({ + "description": "A field's values: an array of one kind of value; a reference naming another table's rows by id; or a slice of a binary file beside the document.", + "anyOf": [ + { "type": "array", "items": element }, + { "type": "object", "properties": { "reference": { "type": "string" }, "ids": ids }, "required": ["reference", "ids"], "additionalProperties": false }, + { + "type": "object", + "properties": { "file": { "type": "string" }, "dtype": dtype, "offset": { "type": "integer", "minimum": 0 }, "count": { "type": "integer", "minimum": 0 } }, + "required": ["file", "dtype", "count"], + "additionalProperties": false, + }, + ], + }) + } +} + +impl JsonSchema for Element { + fn schema_name() -> Cow<'static, str> { + "Value".into() + } + + fn json_schema(generator: &mut SchemaGenerator) -> Schema { + let geometry = generator.subschema_for::(); + json_schema!({ + "description": "One value: a number, boolean, text, or geometry; null, or an empty geometry, is missing.", + "anyOf": [{ "type": "number" }, { "type": "boolean" }, { "type": "string" }, { "type": "null" }, geometry], + }) + } +} + +impl JsonSchema for Geometry { + fn schema_name() -> Cow<'static, str> { + "Geometry".into() + } + + fn json_schema(generator: &mut SchemaGenerator) -> Schema { + let geometry = generator.subschema_for::(); + json_schema!({ + "description": "A point `[x, y]` (a third coordinate is read past), or a list of geometries one level shallower: a path, its parts, or polygons.", + "anyOf": [ + { "type": "array", "prefixItems": [{ "type": "number" }, { "type": "number" }], "items": { "type": "number" }, "minItems": 2, "maxItems": 3 }, + { "type": "array", "items": geometry }, + ], + }) + } +} + +/// A patch deserializes from its JSON: every change but a slice of a file, which [`Patch::load`] +/// reads. +impl<'de> Deserialize<'de> for Patch { + fn deserialize>(deserializer: D) -> std::result::Result { + patch(Vec::::deserialize(deserializer)?).map_err(de::Error::custom) + } +} + +/// Ids deserialize from a list of numbers and texts, or `{count}`. +impl<'de> Deserialize<'de> for Ids { + fn deserialize>(deserializer: D) -> std::result::Result { + IdsForm::deserialize(deserializer).map(|form| form.0) + } +} + +/// An id is a whole number from 0, or a text. +impl schemars::JsonSchema for Id { + fn schema_name() -> std::borrow::Cow<'static, str> { + "Id".into() + } + + fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema { + schemars::json_schema!({ + "description": "A row's id: a whole number from 0, or a text. A number above 2^53 - 1 is written as its decimal text, which names the same row.", + "anyOf": [{ "type": "integer", "minimum": 0 }, { "type": "string" }], + }) + } +} + +/// An id deserializes from a whole number from 0 to 2^53 − 1, or a text. +impl<'de> Deserialize<'de> for Id { + fn deserialize>(deserializer: D) -> std::result::Result { + Key::deserialize(deserializer)?.0.ok_or_else(|| de::Error::custom("an id is a whole number or a text")) + } +} + +impl OpForm { + /// The columns its fields are written as. + pub(crate) fn columns(&mut self) -> &mut [(String, Column)] { + match self { + OpForm::Replace(TableForm { fields, .. }) + | OpForm::Set(TableForm { fields, .. }) + | OpForm::Append { fields, .. } => &mut fields.0, + _ => &mut [], + } + } +} + +/// The patch `ops` make, every slice of a file read already. +pub(crate) fn patch(ops: Vec) -> Result { + let mut patch = Patch::new(); + for (i, op) in ops.into_iter().enumerate() { + let op = match op { + OpForm::Axis { name, unit } => Op::Axis { name: name.into(), unit: unit.into() }, + OpForm::Replace(form) => Op::Replace(form.table().map_err(|e| e.at(i))?), + OpForm::Set(form) => Op::Set(form.table().map_err(|e| e.at(i))?), + OpForm::Remove { table, ids } => Op::Remove { table: table.into(), ids: ids.0 }, + OpForm::Append { at, table, ids, fields } => { + let at = match at { + At::One(at) => vec![at], + At::Many(at) => at, + }; + let mut columns = Vec::with_capacity(fields.0.len()); + for (name, column) in fields.0 { + let values = match column { + Column::Reference { .. } => Err(Error::invalid("append records values, not references")), + column => column.values(), + }; + columns.push(( + name.as_str().into(), + values.map_err(|e| e.at(name.as_str()).at(table.as_str()).at(i))?, + )); + } + Op::Append { table: table.into(), at, ids: ids.map(|ids| ids.0), fields: columns } + } + OpForm::Forget { before } => Op::Forget { before }, + OpForm::Frames { table, field, level, first, at, values } => { + let values = values.iter().map(|v| v.map_or(f32::NAN, |v| v as f32)).collect(); + Op::frames(table.into(), field.into(), level, first, at, values) + } + }; + patch.ops.push(op); + } + Ok(patch) +} + +impl TableForm { + fn table(self) -> Result
{ + let name = self.table; + let mut table = Table::new(name.as_str(), self.ids.0); + for (field, column) in self.fields.0 { + table = match column { + Column::Reference { to, ids } => table.reference(field, to, ids), + column => { + let values = column.values().map_err(|e| e.at(field.as_str()).at(name.as_str()))?; + table.field(field, values) + } + }; + } + Ok(table) + } +} + +/// A field's column as written: values, a reference, or a slice of a file. +pub(crate) enum Column { + Values(Values), + Reference { to: String, ids: Ids }, + Slice(Slice), +} + +/// `count` values of `dtype` from byte `offset` of `file`. +pub(crate) struct Slice { + pub(crate) file: String, + dtype: Dtype, + pub(crate) offset: u64, + count: u64, +} + +impl Slice { + /// The byte after the slice. + pub(crate) fn end(&self) -> Result { + let length = + self.count.checked_mul(self.dtype.width()).ok_or_else(|| Error::invalid("the slice is too long"))?; + self.offset.checked_add(length).ok_or_else(|| Error::invalid("the slice ends past every file")) + } + + /// The values its fetched `bytes` hold. + pub(crate) fn read(&self, bytes: &[u8]) -> Result { + let length = self.end()? - self.offset; + if bytes.len() as u64 != length { + let file = &self.file; + return Err(Error::Io(format!("{file}: {} bytes of the slice's {length}", bytes.len()).into())); + } + Ok(self.dtype.decode(bytes)) + } +} + +/// How a slice's bytes hold values: little endian; `bool` a byte each, nonzero true. +#[derive(Clone, Copy, Deserialize, JsonSchema)] +enum Dtype { + #[serde(rename = "f32le")] + F32, + #[serde(rename = "f64le")] + F64, + #[serde(rename = "i32le")] + I32, + #[serde(rename = "u32le")] + U32, + #[serde(rename = "u64le")] + U64, + #[serde(rename = "u8")] + U8, + #[serde(rename = "bool")] + Bool, +} + +impl Dtype { + fn width(self) -> u64 { + match self { + Dtype::U8 | Dtype::Bool => 1, + Dtype::F32 | Dtype::I32 | Dtype::U32 => 4, + Dtype::F64 | Dtype::U64 => 8, + } + } + + /// The values little-endian `bytes` hold, whole values only. + fn decode(self, bytes: &[u8]) -> Values { + macro_rules! decode { + ($t:ty, $n:literal) => { + bytes.as_chunks::<$n>().0.iter().map(|v| <$t>::from_le_bytes(*v)).collect::>().into() + }; + } + match self { + Dtype::F32 => decode!(f32, 4), + Dtype::F64 => decode!(f64, 8), + Dtype::I32 => decode!(i32, 4), + Dtype::U32 => decode!(u32, 4), + Dtype::U64 => decode!(u64, 8), + Dtype::U8 => bytes.iter().map(|&b| u32::from(b)).collect::>().into(), + Dtype::Bool => bytes.iter().map(|&b| b != 0).collect::>().into(), + } + } +} + +impl Column { + /// The values, read already: a slice of a file is read by [`Patch::load`]. + fn values(self) -> Result { + match self { + Column::Values(values) => Ok(values), + Column::Reference { .. } => unreachable!("references are fields of their own"), + Column::Slice(slice) => { + Err(Error::invalid(format!("{}: a slice of a file is read by Patch::load", slice.file))) + } + } + } +} + +/// A table's fields in the order written. +#[derive(Default)] +pub(crate) struct Fields(pub(crate) Vec<(String, Column)>); + +impl<'de> Deserialize<'de> for Fields { + fn deserialize>(deserializer: D) -> std::result::Result { + struct Map; + impl<'de> Visitor<'de> for Map { + type Value = Fields; + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("an object of fields") + } + fn visit_map>(self, mut map: A) -> std::result::Result { + let mut fields = Vec::new(); + while let Some(name) = map.next_key::()? { + if fields.iter().any(|(n, _)| *n == name) { + return Err(de::Error::custom(format!("field {name} is written twice"))); + } + let column = map.next_value_seed(ColumnSeed(&name))?; + fields.push((name, column)); + } + Ok(Fields(fields)) + } + } + deserializer.deserialize_map(Map) + } +} + +/// A column, named for its errors. +struct ColumnSeed<'a>(&'a str); + +impl<'de> DeserializeSeed<'de> for ColumnSeed<'_> { + type Value = Column; + fn deserialize>(self, deserializer: D) -> std::result::Result { + deserializer.deserialize_any(ColumnVisitor(self.0)) + } +} + +struct ColumnVisitor<'a>(&'a str); + +impl<'de> Visitor<'de> for ColumnVisitor<'_> { + type Value = Column; + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "field {}: an array of values, a reference, or a slice of a file", self.0) + } + + fn visit_seq>(self, mut seq: A) -> std::result::Result { + let mut values = Vec::with_capacity(seq.size_hint().unwrap_or(0)); + while let Some(Element(value)) = seq.next_element()? { + values.push(value); + } + Values::try_from(values).map(Column::Values).map_err(|e| { + let reason = if let Error::Invalid { reason, .. } = e { reason } else { e.to_string().into() }; + de::Error::custom(format!("field {}: {reason}", self.0)) + }) + } + + fn visit_map>(self, mut map: A) -> std::result::Result { + let (mut reference, mut ids, mut file, mut dtype, mut offset, mut count) = (None, None, None, None, None, None); + while let Some(key) = map.next_key::()? { + match key.as_str() { + "reference" => reference = Some(map.next_value::()?), + "ids" => ids = Some(map.next_value::()?.0), + "file" => file = Some(map.next_value::()?), + "dtype" => dtype = Some(map.next_value::()?), + "offset" => offset = Some(map.next_value::()?), + "count" => count = Some(map.next_value::()?), + other => { + map.next_value::()?; + return Err(de::Error::custom(format!("field {}: unknown key {other}", self.0))); + } + } + } + let missing = |what: &str| de::Error::custom(format!("field {}: {what}", self.0)); + match (reference, file) { + (Some(to), None) if dtype.is_none() && offset.is_none() && count.is_none() => { + Ok(Column::Reference { to, ids: ids.ok_or_else(|| missing("a reference names its ids"))? }) + } + (None, Some(file)) if ids.is_none() => Ok(Column::Slice(Slice { + file, + dtype: dtype.ok_or_else(|| missing("a slice names its dtype"))?, + offset: offset.unwrap_or(0), + count: count.ok_or_else(|| missing("a slice names its count"))?, + })), + _ => Err(missing("an object is {reference, ids} or {file, dtype, offset, count}")), + } + } +} + +/// One value of an array column: a number, boolean, text, or `[x, y]` geometry; `null`, or an empty +/// geometry, missing. +struct Element(Option); + +impl<'de> Deserialize<'de> for Element { + fn deserialize>(deserializer: D) -> std::result::Result { + struct One; + impl<'de> Visitor<'de> for One { + type Value = Element; + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("a number, boolean, text, [x, y] geometry, or null") + } + fn visit_unit(self) -> std::result::Result { + Ok(Element(None)) + } + fn visit_none(self) -> std::result::Result { + Ok(Element(None)) + } + fn visit_f64(self, v: f64) -> std::result::Result { + Ok(Element(Some(Value::Number(v)))) + } + fn visit_u64(self, v: u64) -> std::result::Result { + Ok(Element(Some(Value::Number(v as f64)))) + } + fn visit_i64(self, v: i64) -> std::result::Result { + Ok(Element(Some(Value::Number(v as f64)))) + } + fn visit_bool(self, v: bool) -> std::result::Result { + Ok(Element(Some(Value::Bool(v)))) + } + fn visit_str(self, v: &str) -> std::result::Result { + Ok(Element(Some(Value::Text(Arc::from(v))))) + } + fn visit_seq>(self, seq: A) -> std::result::Result { + GeometryVisitor.visit_seq(seq)?.value().map(Element).map_err(de::Error::custom) + } + } + deserializer.deserialize_any(One) + } +} + +/// A geometry as written: a point, or a list of geometries one level shallower. +enum Geometry { + Point([f64; 2]), + List(Vec), +} + +impl Geometry { + /// How deep it nests below its points: 0 a point, 1 a path, 2 parts, 3 polygons. + fn depth(&self) -> usize { + match self { + Geometry::Point(_) => 0, + Geometry::List(items) => 1 + items.first().map_or(0, Geometry::depth), + } + } + + fn point(self) -> [f64; 2] { + match self { + Geometry::Point(p) => p, + Geometry::List(_) => [f64::NAN; 2], + } + } + + fn list(self, item: impl Fn(Geometry) -> T) -> Vec { + match self { + Geometry::Point(_) => Vec::new(), + Geometry::List(items) => items.into_iter().map(item).collect(), + } + } + + /// The value it writes: `None` when it is empty. + fn value(self) -> std::result::Result, &'static str> { + if matches!(&self, Geometry::List(items) if items.is_empty()) { + return Ok(None); + } + Ok(Some(match self.depth() { + 0 => Value::Point(self.point()), + 1 => Value::Path(self.list(Geometry::point)), + 2 => Value::Parts(self.list(|path| path.list(Geometry::point))), + 3 => Value::Polygons(self.list(|parts| parts.list(|path| path.list(Geometry::point)))), + _ => return Err("geometries nest at most polygons of rings of [x, y] points"), + })) + } +} + +struct GeometryVisitor; + +impl<'de> Visitor<'de> for GeometryVisitor { + type Value = Geometry; + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("an [x, y] point or a list of geometries") + } + fn visit_seq>(self, mut seq: A) -> std::result::Result { + let Some(first) = seq.next_element::()? else { return Ok(Geometry::List(Vec::new())) }; + match first { + Part::Number(x) => { + let y: f64 = seq.next_element()?.ok_or_else(|| de::Error::custom("a point is [x, y]"))?; + // A third coordinate, elevation in GeoJSON, is read past. + while seq.next_element::()?.is_some() {} + Ok(Geometry::Point([x, y])) + } + Part::Geometry(first) => { + let mut items = vec![first]; + while let Some(item) = seq.next_element_seed(GeometrySeed)? { + items.push(item); + } + Ok(Geometry::List(items)) + } + } + } +} + +struct GeometrySeed; + +impl<'de> DeserializeSeed<'de> for GeometrySeed { + type Value = Geometry; + fn deserialize>(self, deserializer: D) -> std::result::Result { + deserializer.deserialize_seq(GeometryVisitor) + } +} + +/// The first item of a geometry's list: a coordinate, or a geometry. +enum Part { + Number(f64), + Geometry(Geometry), +} + +impl<'de> Deserialize<'de> for Part { + fn deserialize>(deserializer: D) -> std::result::Result { + struct One; + impl<'de> Visitor<'de> for One { + type Value = Part; + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("a coordinate or a geometry") + } + fn visit_f64(self, v: f64) -> std::result::Result { + Ok(Part::Number(v)) + } + fn visit_u64(self, v: u64) -> std::result::Result { + Ok(Part::Number(v as f64)) + } + fn visit_i64(self, v: i64) -> std::result::Result { + Ok(Part::Number(v as f64)) + } + fn visit_seq>(self, seq: A) -> std::result::Result { + GeometryVisitor.visit_seq(seq).map(Part::Geometry) + } + } + deserializer.deserialize_any(One) + } +} + +/// Ids as written: numbers or texts with `null` for none, as [`Ids`] takes them, or `{count}`. +pub(crate) struct IdsForm(pub(crate) Ids); + +impl<'de> Deserialize<'de> for IdsForm { + fn deserialize>(deserializer: D) -> std::result::Result { + struct Any; + impl<'de> Visitor<'de> for Any { + type Value = IdsForm; + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("ids: numbers or texts, or {count}") + } + fn visit_map>(self, mut map: A) -> std::result::Result { + let mut count = None; + while let Some(key) = map.next_key::()? { + match key.as_str() { + "count" => count = Some(map.next_value::()?), + other => return Err(de::Error::custom(format!("ids: unknown key {other}"))), + } + } + count.map(|n| IdsForm(Ids::count(n))).ok_or_else(|| de::Error::custom("ids as a count are {count}")) + } + fn visit_seq>(self, mut seq: A) -> std::result::Result { + let mut ids = Vec::with_capacity(seq.size_hint().unwrap_or(0)); + while let Some(Key(id)) = seq.next_element()? { + ids.push(id); + } + Ok(IdsForm(Ids::from(ids))) + } + } + deserializer.deserialize_any(Any) + } +} + +/// One id as written. +struct Key(Option); + +impl<'de> Deserialize<'de> for Key { + fn deserialize>(deserializer: D) -> std::result::Result { + struct One; + impl Visitor<'_> for One { + type Value = Key; + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("an id: a whole number, a text, or null") + } + fn visit_unit(self) -> std::result::Result { + Ok(Key(None)) + } + fn visit_none(self) -> std::result::Result { + Ok(Key(None)) + } + fn visit_u64(self, v: u64) -> std::result::Result { + Ok(Key(Some(Id::Number(v)))) + } + fn visit_i64(self, v: i64) -> std::result::Result { + let n = u64::try_from(v).map_err(|_| E::custom(NUMERIC_ID))?; + Ok(Key(Some(Id::Number(n)))) + } + fn visit_f64(self, v: f64) -> std::result::Result { + if v.fract() == 0.0 && (0.0..=SAFE).contains(&v) { + Ok(Key(Some(Id::Number(v as u64)))) + } else { + Err(E::custom(NUMERIC_ID)) + } + } + fn visit_str(self, v: &str) -> std::result::Result { + Ok(Key(Some(Id::from(v)))) + } + } + deserializer.deserialize_any(One) + } +} + +#[cfg(test)] +mod tests { + use crate::{Data, Id, Ids, Patch, Value}; + + #[test] + fn patches_decode_as_written() { + let ops = serde_json::json!([ + {"replace": {"table": "Bus", "ids": [7, 9], "fields": { + "kv": [1.5, 2.5], + "on": [true, false], + "name": ["a", null], + }}}, + {"remove": {"table": "Bus", "ids": [9]}}, + ]); + let patch: Patch = serde_json::from_value(ops).expect("a patch"); + let mut data = Data::new("grid"); + data.apply(patch).expect("valid"); + let bus = data.table("Bus").expect("Bus"); + assert_eq!(bus.ids().collect::>(), [Id::Number(7)]); + assert_eq!(bus.get(7_u64, "kv"), Some(Value::Number(1.5))); + assert_eq!(bus.get(7_u64, "on"), Some(Value::Bool(true))); + assert_eq!(bus.get(7_u64, "name"), Some(Value::Text("a".into()))); + } + + #[test] + fn forms_refuse_what_they_cannot_read_now() { + let slice = serde_json::json!([{"replace": {"table": "Bus", "ids": {"count": 1}, "fields": { + "kv": {"file": "kv.f64", "dtype": "f64le", "count": 1}}}}]); + let error = serde_json::from_value::(slice).expect_err("a slice needs Patch::load").to_string(); + assert!(error.contains("Patch::load"), "{error}"); + assert!(serde_json::from_value::(serde_json::json!(3)).is_err(), "a bare number is no count"); + assert_eq!(serde_json::from_value::(serde_json::json!({"count": 3})).expect("a count").len(), 3); + assert_eq!(serde_json::from_value::(serde_json::json!(3)).expect("an id"), Id::Number(3)); + assert!(serde_json::from_value::(serde_json::json!(1.5)).is_err()); + assert!(serde_json::from_value::(serde_json::json!(null)).is_err()); + } +} diff --git a/crates/latkit/src/data/frames.rs b/crates/latkit/src/data/frames.rs new file mode 100644 index 00000000..ea4b5e58 --- /dev/null +++ b/crates/latkit/src/data/frames.rs @@ -0,0 +1,211 @@ +//! Time tiles: a dataset written as the files a view fetches its sampled fields' histories from, in +//! spans, as it asks for them. A span of level `k` holds `chunk` entries of the level: frames at level +//! 0, else buckets of `8^k` frames. Eight spans make the one a level up, as four map tiles make the +//! tile a zoom out, so a span still loading draws the nearest span above it that has landed. +//! +//! | File | What it holds | +//! | ------------- | ------------------------------------------------------------------------------- | +//! | `frames.json` | the manifest: `data`, `chunk`, `url`, and `frames`, each sampled field's table, | +//! | | name, and the frames it reads, `[first, end]` | +//! | `base.latk` | the dataset with every sampled field reading its frames but holding none | +//! | spans | at `url`, `{field}` the field's place in `frames`: a patch holding the span's | +//! | | entries, one `frames` change for each run of them | + +use std::ops::Range; + +use super::dataset::Data; +use super::name::Name; +use super::patch::{Op, Patch}; +use super::samples::Run; +use super::table::Field; +use crate::{Error, Result}; + +/// The manifest's name. +pub(crate) const MANIFEST: &str = "frames.json"; +/// The dataset without its sampled fields' entries. +const BASE: &str = "base.latk"; +/// Where each span lies, beside the manifest. +const URL: &str = "{field}/{level}/{index}.latk"; + +/// A sampled field a manifest lists: its table and name, and the frames it reads, `[first, end]`. +#[derive(Clone, PartialEq, Debug, serde::Serialize, serde::Deserialize)] +pub(crate) struct Listed { + pub(crate) table: Name, + pub(crate) field: Name, + pub(crate) levels: u32, + #[serde(with = "range")] + pub(crate) frames: Range, +} + +/// What a manifest says: where the dataset without its sampled fields' entries lies, the entries a +/// span holds, where each span lies, and the fields listed. +#[derive(Clone, PartialEq, Debug, serde::Serialize, serde::Deserialize)] +pub(crate) struct Manifest { + pub(crate) data: String, + pub(crate) chunk: u32, + pub(crate) url: String, + #[serde(rename = "frames")] + pub(crate) fields: Vec, +} + +/// Frames `first..end`, written `[first, end]`. +mod range { + use std::ops::Range; + + use serde::{Deserialize, Deserializer, Serialize, Serializer, de}; + + pub(super) fn serialize(frames: &Range, s: S) -> Result { + [frames.start, frames.end].serialize(s) + } + + pub(super) fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result, D::Error> { + match <[u64; 2]>::deserialize(d)? { + [first, end] if first <= end => Ok(first..end), + _ => Err(de::Error::custom("frames are [first, end], the first at most the end")), + } + } +} + +impl Manifest { + /// The manifest `bytes` hold; `None` where they hold none, being no JSON object listing `frames`. + pub(crate) fn from_bytes(bytes: &[u8]) -> Option> { + let json: serde_json::Value = serde_json::from_slice(bytes).ok()?; + json.get("frames")?.as_array()?; + let manifest = crate::json::read::(&json).and_then(|m| { + if !chunks(m.chunk) { + return Err(Error::invalid("a span holds a multiple of 8 entries, 8 to 2^20").at("chunk")); + } + for (i, field) in m.fields.iter().enumerate() { + if field.levels > super::samples::MAX_LEVEL { + return Err(Error::invalid("sample levels run from 0 to 21").at("levels").at(i).at("frames")); + } + } + Ok(m) + }); + Some(manifest.map_err(|e| e.at(MANIFEST))) + } + + /// Where span `index` of `level` of the field listed `field`th lies, `url` its template. + pub(crate) fn span(url: &str, field: usize, level: u32, index: u64) -> String { + url.replace("{field}", &field.to_string()) + .replace("{level}", &level.to_string()) + .replace("{index}", &index.to_string()) + } +} + +/// Whether a span may hold `chunk` entries: a multiple of 8, so a bucket a level up never straddles two. +fn chunks(chunk: u32) -> bool { + (8..=1 << 20).contains(&chunk) && chunk.is_multiple_of(8) +} + +impl Data { + /// The dataset as time tiles, each file's path and bytes handed to `write`: `frames.json`, the + /// manifest a view's tiles open; `base.latk`, the dataset with its sampled fields reading their + /// frames but holding none; and a patch for each span of `chunk` entries of each level of each + /// sampled field that holds any, at `{field}/{level}/{index}.latk`. A view given the manifest as + /// [`Tiles`](crate::Tiles) fetches the spans its lines draw, at the level of detail its plot + /// window asks, and those about the coordinate it shows; until a span lands, the span above it + /// draws. + /// + /// The manifest is written last, so a reader finding it finds every file it names. + pub fn to_tiles(&self, chunk: u32, mut write: impl FnMut(&str, &[u8]) -> Result<()>) -> Result<()> { + if !chunks(chunk) { + return Err(Error::invalid("a span holds a multiple of 8 entries, 8 to 2^20").at("chunk")); + } + let entries_per_span = u64::from(chunk); + let mut base = self.clone(); + let mut fields = Vec::new(); + for table in self.tables() { + let rows: Vec = (0..table.len()).collect(); + for (name, field) in &table.fields { + let Field::Sampled(samples, _) = field else { continue }; + let place = fields.len(); + fields.push(Listed { + table: table.name.clone(), + field: name.clone(), + levels: samples.levels(), + frames: samples.start()..samples.end(), + }); + // Runs come level by level, in order, so each span is whole once the next begins. + let mut span: Option<((u32, u64), Patch)> = None; + for run in samples.runs() { + for index in run.entries.start / entries_per_span..run.entries.end.div_ceil(entries_per_span) { + let entries = run.entries.start.max(index * entries_per_span) + ..run.entries.end.min((index + 1).saturating_mul(entries_per_span)); + let part = Run { level: run.level, entries }; + let (at, values) = samples.read(&part, &rows); + let op = + Op::frames(table.name.clone(), name.clone(), part.level, part.entries.start, at, values); + if span.as_ref().is_some_and(|(key, _)| *key != (part.level, index)) + && let Some(((level, index), tile)) = span.take() + { + write(&Manifest::span(URL, place, level, index), &tile.to_bytes())?; + } + span.get_or_insert_with(|| ((part.level, index), Patch::to(self.name().clone()))) + .1 + .ops + .push(op); + } + } + if let Some(((level, index), tile)) = span { + write(&Manifest::span(URL, place, level, index), &tile.to_bytes())?; + } + let emptied = samples.emptied(); + base.sampled(&table.name, name, |samples| { + *samples = emptied; + true + }); + } + } + write(BASE, &base.to_bytes())?; + let manifest = Manifest { data: BASE.to_owned(), chunk, url: URL.to_owned(), fields }; + write(MANIFEST, serde_json::to_string_pretty(&manifest).expect("JSON").as_bytes()) + } +} + +#[cfg(test)] +mod tests { + use std::collections::BTreeMap; + + use super::*; + use crate::{Ids, Table}; + + #[test] + fn a_history_writes_as_spans_a_manifest_names() { + let mut data = Data::new("grid"); + data.apply( + Patch::new().axis("time", "s").replace(Table::new("Bus", Ids::count(2)).field("kv", vec![1.0, 2.0])), + ) + .expect("rows"); + let at: Vec = (0..100).map(f64::from).collect(); + let values: Vec = (0..200).map(|v| f64::from(v % 7)).collect(); + data.apply(Patch::new().append(&at, "Bus", [("vm", values)])).expect("frames"); + let mut files = BTreeMap::new(); + data.to_tiles(16, |path, bytes| { + files.insert(path.to_owned(), bytes.to_vec()); + Ok(()) + }) + .expect("tiles"); + let manifest = Manifest::from_bytes(&files[MANIFEST]).expect("a manifest").expect("valid"); + assert_eq!(manifest.fields, [Listed { table: "Bus".into(), field: "vm".into(), levels: 2, frames: 0..100 }]); + // 100 frames: 7 spans of 16 at level 0; 12 buckets of 8 in 1 span at level 1; 1 of 64 at level 2. + let spans: Vec<&str> = files + .keys() + .map(String::as_str) + .filter(|p| std::path::Path::new(p).extension().is_some_and(|e| e == "latk") && *p != BASE) + .collect(); + assert_eq!(spans.len(), 7 + 1 + 1); + let mut back = Data::from_bytes(&files[BASE]).expect("the base"); + assert_eq!(back.describe().span, None, "the base holds no entries"); + for path in &spans { + back.apply(Patch::from_bytes(&files[*path]).expect("a span")).expect("held once"); + } + assert_eq!(back.to_bytes(), data.to_bytes(), "every span put back makes the history again"); + assert!(Manifest::from_bytes(br#"{"tiles": []}"#).is_none(), "TileJSON is no manifest"); + let backwards = + br#"{"data": "b", "chunk": 16, "url": "u", "frames": [{"table": "t", "field": "f", "levels": 0, "frames": [3, 1]}]}"#; + let error = Manifest::from_bytes(backwards).expect("a manifest").unwrap_err(); + assert!(error.to_string().starts_with("frames.json.frames[0].frames"), "{error}"); + assert!(data.to_tiles(12, |_, _| Ok(())).is_err()); + } +} diff --git a/crates/latkit/src/data/geometry.rs b/crates/latkit/src/data/geometry.rs new file mode 100644 index 00000000..25c4705f --- /dev/null +++ b/crates/latkit/src/data/geometry.rs @@ -0,0 +1,309 @@ +use std::ops::Range; + +use super::buffer::Buffer; +use super::values::Value; + +/// Shared, immutable geometries of one depth: nested offsets over `[x, y]` coordinates. +/// +/// Depth 0 is a point per row, 1 a path, 2 parts (rings of a polygon, or the paths of a multi-path), +/// and 3 polygons. `levels[0]` is indexed by row; each level's offsets index the next level, and the +/// last level indexes `coords`. Offsets are absolute, so slicing rows slices only `levels[0]`. +#[derive(Clone)] +pub(crate) struct Geometry { + depth: u8, + levels: Vec>, + coords: Buffer<[f64; 2]>, +} + +/// The deepest geometry: polygons of rings of coordinates. +pub(crate) const MAX_DEPTH: u8 = 3; + +impl Geometry { + pub(crate) fn depth(&self) -> u8 { + self.depth + } + + pub(crate) fn len(&self) -> usize { + match self.levels.first() { + Some(rows) => rows.len().saturating_sub(1), + None => self.coords.len(), + } + } + + pub(crate) fn slice(&self, range: Range) -> Geometry { + let mut levels = self.levels.clone(); + let coords = match levels.first_mut() { + Some(rows) => { + *rows = rows.slice(range.start..range.end + 1); + self.coords.clone() + } + None => self.coords.slice(range), + }; + Geometry { depth: self.depth, levels, coords } + } + + /// The span `item` of `level` covers in the next level, or in `coords` from the last level. + pub(crate) fn span(&self, level: usize, item: usize) -> Range { + let offsets = &self.levels[level]; + offsets[item] as usize..offsets[item + 1] as usize + } + + pub(crate) fn coords(&self) -> &[[f64; 2]] { + &self.coords + } + + /// Whether row `row` holds exactly what `other`'s row `other_row` does: the same parts of the same + /// coordinates, compared by their bits. + pub(crate) fn same_row(&self, row: usize, other: &Geometry, other_row: usize) -> bool { + fn same(a: &[[f64; 2]], b: &[[f64; 2]]) -> bool { + a.len() == b.len() && a.iter().zip(b).all(|(p, q)| p.map(f64::to_bits) == q.map(f64::to_bits)) + } + fn walk(a: &Geometry, b: &Geometry, level: usize, i: usize, j: usize) -> bool { + let (span, other) = (a.span(level, i), b.span(level, j)); + if span.len() != other.len() { + return false; + } + if level + 1 == a.levels.len() { + return same(&a.coords[span], &b.coords[other]); + } + span.zip(other).all(|(i, j)| walk(a, b, level + 1, i, j)) + } + if self.depth != other.depth { + return false; + } + if self.depth == 0 { + return same(&self.coords[row..=row], &other.coords[other_row..=other_row]); + } + walk(self, other, 0, row, other_row) + } + + /// Row `row`'s coordinates, every part's in order. + pub(crate) fn row_coords(&self, row: usize) -> &[[f64; 2]] { + if self.depth == 0 { + return &self.coords[row..=row]; + } + let mut span = row..row + 1; + for offsets in &self.levels { + span = offsets[span.start] as usize..offsets[span.end] as usize; + } + &self.coords[span] + } + + /// A digest of row `row`: its coordinates and how they break into parts. + pub(crate) fn row_hash(&self, row: usize) -> u64 { + use std::hash::Hasher; + let mut hasher = rustc_hash::FxHasher::default(); + let mut span = row..row + 1; + for offsets in &self.levels { + let first = offsets[span.start]; + for &offset in &offsets[span.clone()] { + hasher.write_u32(offset - first); + } + span = first as usize..offsets[span.end] as usize; + } + hasher.write_usize(span.len()); + for point in self.row_coords(row) { + hasher.write_u64(point[0].to_bits()); + hasher.write_u64(point[1].to_bits()); + } + hasher.finish() + } + + /// Coordinates the rows span, every part's. + pub(crate) fn coords_spanned(&self) -> usize { + if self.depth == 0 { + return self.len(); + } + let mut span = 0..self.len(); + for offsets in &self.levels { + span = offsets[span.start] as usize..offsets[span.end] as usize; + } + span.len() + } + + /// How many points row `row`'s path takes as shaders read it: every coordinate, and a break + /// between its parts or rings. + pub(crate) fn row_points(&self, row: usize) -> usize { + if self.depth == 0 { + return 1; + } + // The row's parts or rings: the items of the level above its coordinates. + let mut span = row..row + 1; + for offsets in &self.levels[..self.levels.len() - 1] { + span = offsets[span.start] as usize..offsets[span.end] as usize; + } + let breaks = if self.depth == 1 { 0 } else { span.len().saturating_sub(1) }; + self.row_coords(row).len() + breaks + } + + pub(crate) fn get(&self, row: usize) -> Value { + match self.depth { + 0 => Value::Point(self.coords[row]), + 1 => Value::Path(self.coords[self.span(0, row)].to_vec()), + 2 => Value::Parts(self.span(0, row).map(|p| self.coords[self.span(1, p)].to_vec()).collect()), + _ => Value::Polygons( + self.span(0, row) + .map(|polygon| self.span(1, polygon).map(|ring| self.coords[self.span(2, ring)].to_vec()).collect()) + .collect(), + ), + } + } + + /// Offsets relative to each level's first entry and the coordinates the rows span. + pub(crate) fn compact(&self) -> (Vec>, Vec<[f64; 2]>) { + let mut builder = GeometryBuilder::new(self.depth); + for row in 0..self.len() { + builder.push_from(self, row); + } + let Geometry { levels, coords, .. } = builder.finish(); + (levels.iter().map(|l| l.to_vec()).collect(), coords.to_vec()) + } + + pub(crate) fn from_parts(depth: u8, levels: Vec>, coords: Vec<[f64; 2]>) -> Option { + if depth > MAX_DEPTH || levels.len() != depth as usize { + return None; + } + let mut next = coords.len(); + for offsets in levels.iter().rev() { + let ok = offsets.first() == Some(&0) + && offsets.windows(2).all(|w| w[0] <= w[1]) + && offsets.last().is_some_and(|&end| end as usize == next); + if !ok { + return None; + } + next = offsets.len() - 1; + } + Some(Geometry { depth, levels: levels.into_iter().map(Buffer::from).collect(), coords: coords.into() }) + } +} + +impl std::fmt::Debug for Geometry { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_list().entries((0..self.len()).map(|row| self.get(row))).finish() + } +} + +/// Builds [`Geometry`] one row at a time. +pub(crate) struct GeometryBuilder { + depth: u8, + levels: Vec>, + coords: Vec<[f64; 2]>, +} + +impl GeometryBuilder { + pub(crate) fn new(depth: u8) -> GeometryBuilder { + GeometryBuilder { depth, levels: (0..depth).map(|_| vec![0]).collect(), coords: Vec::new() } + } + + pub(crate) fn push_from(&mut self, source: &Geometry, row: usize) { + debug_assert_eq!(source.depth, self.depth); + if self.depth == 0 { + self.coords.push(source.coords[row]); + } else { + self.copy(source, 0, row); + } + } + + fn copy(&mut self, source: &Geometry, level: usize, item: usize) { + let span = source.span(level, item); + if level + 1 == source.levels.len() { + self.coords.extend_from_slice(&source.coords[span]); + } else { + for child in span { + self.copy(source, level + 1, child); + } + } + self.close(level); + } + + /// An empty row: no coordinates, or a missing point. + pub(crate) fn push_empty(&mut self) { + if self.depth == 0 { + self.coords.push([f64::NAN; 2]); + } else { + self.close(0); + } + } + + pub(crate) fn push_path(&mut self, path: &[[f64; 2]]) { + self.coords.extend_from_slice(path); + } + + /// Ends the current item of `level`: its children are everything pushed since the last close. + pub(crate) fn close(&mut self, level: usize) { + let next = match self.levels.get(level + 1) { + Some(offsets) => offsets.len() - 1, + None => self.coords.len(), + }; + self.levels[level].push(u32::try_from(next).expect("a geometry page holds at most 2^32 items")); + } + + pub(crate) fn push_value(&mut self, value: &Value) -> bool { + match (self.depth, value) { + (0, Value::Point(p)) => self.coords.push(*p), + (1, Value::Path(path)) => { + self.push_path(path); + self.close(0); + } + (2, Value::Parts(parts)) => { + for part in parts { + self.push_path(part); + self.close(1); + } + self.close(0); + } + (3, Value::Polygons(polygons)) => { + for polygon in polygons { + for ring in polygon { + self.push_path(ring); + self.close(2); + } + self.close(1); + } + self.close(0); + } + _ => return false, + } + true + } + + pub(crate) fn finish(self) -> Geometry { + Geometry { + depth: self.depth, + levels: self.levels.into_iter().map(Buffer::from).collect(), + coords: self.coords.into(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn polygons() -> Geometry { + let mut builder = GeometryBuilder::new(3); + let square = vec![[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]]; + builder.push_value(&Value::Polygons(vec![vec![square.clone()], vec![square.clone(), square.clone()]])); + builder.push_empty(); + builder.push_value(&Value::Polygons(vec![vec![square]])); + builder.finish() + } + + #[test] + fn rows_round_trip_through_slices() { + let geometry = polygons(); + assert_eq!(geometry.len(), 3); + let tail = geometry.slice(1..3); + assert_eq!(tail.len(), 2); + assert_eq!(tail.get(0), Value::Polygons(Vec::new())); + assert_eq!(tail.get(1), geometry.get(2)); + } + + #[test] + fn compact_parts_validate() { + let geometry = polygons().slice(1..3); + let (levels, coords) = geometry.compact(); + let rebuilt = Geometry::from_parts(3, levels, coords).expect("valid"); + assert_eq!(rebuilt.get(1), geometry.get(1)); + } +} diff --git a/crates/latkit/src/data/ids.rs b/crates/latkit/src/data/ids.rs new file mode 100644 index 00000000..b1796042 --- /dev/null +++ b/crates/latkit/src/data/ids.rs @@ -0,0 +1,417 @@ +use std::hash::BuildHasher; + +use hashbrown::HashTable; +use hashbrown::hash_table::Entry; +use rustc_hash::FxBuildHasher; + +use super::column::{Column, PAGE_BITS, PAGE_MASK}; +use super::name::{Id, IdRef}; +use super::values::{Array, Values}; +use crate::{Error, Result}; + +/// Row ids, as given to [`Table::new`](crate::Table::new) or [`Patch::remove`](crate::Patch::remove), +/// and the target ids of a reference. +/// +/// [`Ids::count`] names rows `0..n`. Lists convert from vectors, arrays, and slices of numbers or +/// texts; for a reference, `None` leaves a row unwired. A bare number is never a count. +/// +/// ``` +/// # use latkit::{Ids, Table}; +/// let buses = Table::new("Bus", Ids::count(3)); // ids 0, 1, 2 +/// let lines = Table::new("Line", [101_u64, 205]); // ids 101 and 205 +/// ``` +#[derive(Clone, Debug)] +pub struct Ids(pub(crate) IdList); + +#[derive(Clone, Debug)] +pub(crate) enum IdList { + Count(u32), + Listed(Values), +} + +/// Ids are equal when they name the same rows in the same order. +impl PartialEq for Ids { + fn eq(&self, other: &Ids) -> bool { + self.len() == other.len() && (0..self.len()).all(|i| self.key(i) == other.key(i)) + } +} + +impl Ids { + /// Ids `0..n`, one per row in row order. + pub fn count(n: u32) -> Ids { + Ids(IdList::Count(n)) + } + + /// The number of ids. + pub fn len(&self) -> usize { + match &self.0 { + IdList::Count(n) => *n as usize, + IdList::Listed(v) => v.len(), + } + } + + /// Whether there are no ids. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub(crate) fn key(&self, i: usize) -> Option> { + match &self.0 { + IdList::Count(_) => Some(IdRef::Number(i as u64)), + IdList::Listed(values) => key(values, i), + } + } +} + +pub(crate) fn key(values: &Values, i: usize) -> Option> { + if !values.is_valid(i) { + return None; + } + match &values.array { + Array::U64(v) => Some(IdRef::Number(v[i])), + Array::Text(v) => Some(IdRef::Text(v.get(i))), + _ => None, + } +} + +macro_rules! listed { + ($($t:ty),*) => {$( + impl From<$t> for Ids { + fn from(ids: $t) -> Ids { + Ids::listed(Values::from(ids)) + } + } + )*}; +} + +listed!( + Vec, + &[u64], + Vec>, + Vec, + &[String], + Vec<&str>, + &[&str], + Vec>, + Vec> +); + +impl From<[&str; N]> for Ids { + fn from(ids: [&str; N]) -> Ids { + Ids::listed(Values::from(ids)) + } +} + +impl From<[u64; N]> for Ids { + fn from(ids: [u64; N]) -> Ids { + Ids::listed(Values::from(ids)) + } +} + +impl From> for Ids { + fn from(ids: Vec) -> Ids { + Ids::listed(Values::from(ids.into_iter().map(u64::from).collect::>())) + } +} + +impl From<&[u32]> for Ids { + fn from(ids: &[u32]) -> Ids { + Ids::listed(Values::from(ids.iter().copied().map(u64::from).collect::>())) + } +} + +impl From>> for Ids { + fn from(ids: Vec>) -> Ids { + Ids::listed(Values::from(ids.into_iter().map(|id| id.map(u64::from)).collect::>())) + } +} + +impl From> for Ids { + fn from(ids: Vec) -> Ids { + Ids::from(ids.into_iter().map(Some).collect::>()) + } +} + +impl From>> for Ids { + fn from(ids: Vec>) -> Ids { + if ids.iter().flatten().all(|id| matches!(id, Id::Number(_))) { + let numbers = ids.into_iter().map(|id| id.map(|id| if let Id::Number(n) = id { n } else { 0 })); + return Ids::from(numbers.collect::>()); + } + Ids::from(ids.into_iter().map(|id| id.map(|id| id.to_string())).collect::>()) + } +} + +impl Ids { + fn listed(values: Values) -> Ids { + Ids(IdList::Listed(values)) + } +} + +/// A table's row ids: a count when they are `0..n` in row order, else a paged column. +#[derive(Clone, Debug)] +pub(crate) enum RowIds { + Count(u32), + Listed(Column), +} + +impl RowIds { + pub(crate) fn new(ids: &Ids) -> RowIds { + match &ids.0 { + IdList::Count(n) => RowIds::Count(*n), + IdList::Listed(values) => RowIds::Listed(Column::new(values)), + } + } + + pub(crate) fn len(&self) -> usize { + match self { + RowIds::Count(n) => *n as usize, + RowIds::Listed(c) => c.len(), + } + } + + pub(crate) fn key(&self, row: usize) -> Option> { + match self { + RowIds::Count(_) => Some(IdRef::Number(row as u64)), + RowIds::Listed(c) => key(&c.pages()[row >> PAGE_BITS].values, row & PAGE_MASK), + } + } + + pub(crate) fn id(&self, row: usize) -> Option { + self.key(row).map(IdRef::to_id) + } + + /// The ids with `added` appended; a count stays a count while the new ids continue it. Ids of + /// another kind than the table's (texts for a table of numbers) are an error. + pub(crate) fn extend(&self, added: &[Id]) -> Result { + if added.is_empty() { + return Ok(self.clone()); + } + if let RowIds::Count(n) = self + && added.iter().enumerate().all(|(i, id)| *id == Id::Number(u64::from(*n) + i as u64)) + { + return Ok(RowIds::Count(n + added.len() as u32)); + } + let column = self.listed(); + let IdList::Listed(source) = Ids::from(added.to_vec()).0 else { unreachable!("a list of ids") }; + if source.kind() != column.kind() { + return Err(Error::invalid("ids of another kind than the table's: numbers and texts do not mix")); + } + let len = column.len() + added.len(); + let writes: Vec<(usize, usize)> = (0..added.len()).map(|k| (column.len() + k, k)).collect(); + Ok(RowIds::Listed(column.write(len, &writes, &Column::new(&source))?)) + } + + /// The ids with `len` rows (at least the current count) and `writes` applied, `(row, row of + /// source)` by row, a hole where the row of source is a [`HOLE`](super::values::HOLE). Pages no + /// write touches keep their ids. + pub(crate) fn write(&self, len: usize, writes: &[(usize, usize)], source: &RowIds) -> Result { + // The ids written, gathered first, so a count's ids are made only for those. + let from: Vec = writes.iter().map(|&(_, s)| s).collect(); + let written = match source { + RowIds::Count(_) => { + let ids: Vec> = + from.iter().map(|&s| (s != super::values::HOLE).then_some(s as u64)).collect(); + Column::new(&Values::from(ids)) + } + RowIds::Listed(column) => column.gather(&from), + }; + let at: Vec<(usize, usize)> = writes.iter().enumerate().map(|(k, &(row, _))| (row, k)).collect(); + Ok(RowIds::Listed(self.listed().write(len, &at, &written)?)) + } + + /// The ids of `rows`, in that order. + pub(crate) fn gather(&self, rows: &[usize]) -> RowIds { + if rows.iter().enumerate().all(|(i, &r)| i == r) { + return match self { + RowIds::Count(_) => RowIds::Count(rows.len() as u32), + RowIds::Listed(c) => RowIds::Listed(c.gather(rows)), + }; + } + RowIds::Listed(self.listed().gather(rows)) + } + + fn listed(&self) -> Column { + match self { + RowIds::Count(n) => Column::new(&Values::from((0..u64::from(*n)).collect::>())), + RowIds::Listed(c) => c.clone(), + } + } + + /// Every page's numbered ids, when every id is a number: what lookups read without matching each + /// id's kind. + pub(crate) fn numbers(&self) -> Option> { + let RowIds::Listed(column) = self else { return None }; + column + .pages() + .iter() + .map(|page| match (&page.values.array, &page.values.valid) { + (Array::U64(v), None) => Some(&v[..]), + _ => None, + }) + .collect() + } + + /// The first row without an id: a hole, which only the rows a view draws of a table drawn through + /// tiles have. + pub(crate) fn hole(&self) -> Option { + let RowIds::Listed(column) = self else { return None }; + let mut start = 0; + for page in column.pages() { + if let Some(valid) = &page.values.valid + && let Some(i) = (0..page.values.len()).find(|&i| !valid.get(i)) + { + return Some(start + i); + } + start += page.values.len(); + } + None + } + + /// How many rows are holes, without an id. + pub(crate) fn holes(&self) -> usize { + let RowIds::Listed(column) = self else { return 0 }; + column.pages().iter().filter_map(|p| p.values.valid.as_ref().map(|v| p.values.len() - v.count())).sum() + } + + /// The id → row index, past holes; an error names a repeated id. + pub(crate) fn index(&self) -> Result { + let RowIds::Listed(_) = self else { return Ok(Index::Identity(self.len() as u32)) }; + if let Some(pages) = self.numbers() { + return numbered(&pages, self.len()); + } + let mut table = HashTable::with_capacity(self.len()); + for row in 0..self.len() { + let Some(key) = self.key(row) else { continue }; + let eq = |&r: &u32| self.key(r as usize) == Some(key); + let rehash = |&r: &u32| hash(self.key(r as usize).expect("indexed rows have ids")); + match table.entry(hash(key), eq, rehash) { + Entry::Occupied(_) => return Err(Error::invalid(format!("id {key:?} appears twice")).at(row)), + Entry::Vacant(slot) => { + slot.insert(row as u32); + } + } + } + Ok(Index::Table(table)) + } +} + +/// The index of numbered ids, read page by page. +fn numbered(pages: &[&[u64]], len: usize) -> Result { + let id = |r: u32| pages[r as usize >> PAGE_BITS][r as usize & PAGE_MASK]; + let mut table = HashTable::with_capacity(len); + for (p, page) in pages.iter().enumerate() { + for (i, &n) in page.iter().enumerate() { + let row = p << PAGE_BITS | i; + match table.entry(hash(IdRef::Number(n)), |&r| id(r) == n, |&r| hash(IdRef::Number(id(r)))) { + Entry::Occupied(_) => return Err(Error::invalid(format!("id {n} appears twice")).at(row)), + Entry::Vacant(slot) => { + slot.insert(row as u32); + } + } + } + } + Ok(Index::Table(table)) +} + +/// Finds a row by id without allocating. +#[derive(Debug)] +pub(crate) enum Index { + Identity(u32), + Table(HashTable), +} + +pub(crate) fn hash(key: IdRef<'_>) -> u64 { + FxBuildHasher.hash_one(key) +} + +impl Index { + /// The rows numbered ids `ids` name, `unwired` where one names none or is missing, and whether a + /// present id named no row: the loop chosen once for the ids' and the rows' kinds. + pub(crate) fn resolve(&self, rows: &RowIds, ids: &Values, unwired: u32) -> (Vec, bool) { + let valid = |i: usize| ids.valid.as_ref().is_none_or(|v| v.get(i)); + let mut dangling = false; + let mut found = |row: Option| { + dangling |= row.is_none(); + row.map_or(unwired, |r| r as u32) + }; + let resolved = match (self, &ids.array, rows.numbers()) { + (Index::Identity(count), Array::U64(v), _) => { + let count = u64::from(*count); + v.iter() + .enumerate() + .map(|(i, &n)| if valid(i) { found((n < count).then_some(n as usize)) } else { unwired }) + .collect() + } + (Index::Table(table), Array::U64(v), Some(pages)) => { + let id = |r: u32| pages[r as usize >> PAGE_BITS][r as usize & PAGE_MASK]; + v.iter() + .enumerate() + .map(|(i, &n)| { + if !valid(i) { + return unwired; + } + found(table.find(hash(IdRef::Number(n)), |&r| id(r) == n).map(|&r| r as usize)) + }) + .collect() + } + _ => (0..ids.len()).map(|i| key(ids, i).map_or(unwired, |key| found(self.get(rows, key)))).collect(), + }; + (resolved, dangling) + } + + /// The row with id `key`. A numbered row is also named by its id in decimal text, as ids too + /// large for a JSON or JavaScript number are written. + pub(crate) fn get(&self, ids: &RowIds, key: IdRef<'_>) -> Option { + let number = |text: &str| text.parse::().ok().and_then(|n| self.get(ids, IdRef::Number(n))); + match (self, key) { + (Index::Identity(n), IdRef::Number(i)) => (i < u64::from(*n)).then_some(i as usize), + (Index::Identity(_), IdRef::Text(text)) => number(text), + (Index::Table(table), key) => table + .find(hash(key), |&r| ids.key(r as usize) == Some(key)) + .map(|&r| r as usize) + .or_else(|| if let IdRef::Text(text) = key { number(text) } else { None }), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn counts_extend_as_counts() { + let ids = RowIds::Count(3).extend(&[Id::Number(3), Id::Number(4)]).expect("numbers"); + assert!(matches!(ids, RowIds::Count(5))); + let ids = ids.extend(&[Id::Number(9)]).expect("numbers"); + assert_eq!(ids.len(), 6); + assert_eq!(ids.id(5), Some(Id::Number(9))); + let index = ids.index().expect("unique"); + assert_eq!(index.get(&ids, IdRef::Number(9)), Some(5)); + assert_eq!(index.get(&ids, IdRef::Number(2)), Some(2)); + assert!(ids.extend(&[Id::from("a")]).is_err(), "texts do not join numbers"); + } + + #[test] + fn repeated_ids_are_invalid() { + let ids = RowIds::new(&Ids::from(vec!["a", "b", "a"])); + assert!(ids.index().is_err()); + } + + #[test] + fn gather_keeps_ids() { + let ids = RowIds::new(&Ids::from(vec!["a", "b", "c"])).gather(&[2, 0]); + assert_eq!(ids.id(0), Some(Id::from("c"))); + assert_eq!(RowIds::Count(4).gather(&[0, 2]).id(1), Some(Id::Number(2))); + } + + #[test] + fn holes_have_no_id_and_index_past() { + let ids = RowIds::new(&Ids::from(vec!["a", "b", "c"])).gather(&[2, super::super::values::HOLE, 0]); + assert_eq!((ids.id(1), ids.hole()), (None, Some(1))); + let index = ids.index().expect("unique past the hole"); + assert_eq!(index.get(&ids, IdRef::Text("a")), Some(2)); + let numbered = RowIds::Count(3).gather(&[1, super::super::values::HOLE]); + assert_eq!(numbered.index().expect("unique").get(&numbered, IdRef::Number(1)), Some(0)); + } +} diff --git a/crates/latkit/src/data/json.rs b/crates/latkit/src/data/json.rs new file mode 100644 index 00000000..700e6501 --- /dev/null +++ b/crates/latkit/src/data/json.rs @@ -0,0 +1,214 @@ +//! Datasets and patches as JSON: the format is documented on [`Patch::load`], its forms in +//! `forms.rs`; slices of binary files are fetched through a host. + +use serde::Deserialize; + +use super::dataset::Data; +use super::forms::{Column, DataForm, OpForm, patch}; +use super::name::Name; +use super::ordered::Ordered; +use super::patch::Patch; +use crate::resource::{Fetch, Request}; +use crate::{Error, Result}; + +impl Patch { + /// A patch from its JSON: what any language writes without latkit. The patch is a list of the + /// changes [`Patch`]'s methods make, each named by its method with its parameters by name. + /// + /// ```json + /// [ + /// {"replace": {"table": "Bus", "ids": [101, 205], "fields": {"x": [0, 10], "name": ["North", "South"]}}}, + /// {"replace": {"table": "Branch", "ids": {"count": 1}, "fields": {"from": {"reference": "Bus", "ids": [101]}}}}, + /// {"axis": {"name": "time", "unit": "s"}}, + /// {"append": {"at": [0, 0.5], "table": "Bus", "fields": {"vm": {"file": "vm.f32", "dtype": "f32le", "count": 4}}}} + /// ] + /// ``` + /// + /// - `replace` and `set` take `{table, ids, fields}`, `remove` `{table, ids}`, `append` `{at, table, + /// ids?, fields}`, `forget` `{before}`, `axis` `{name, unit}`, and `frames` `{table, field, + /// level?, first, at, values}`, as [`Patch::frames`] takes them. + /// - `ids` is a count naming rows `0..n`, or numbers or texts; `null` leaves a reference unwired. + /// - A field is an array of one kind of value, as [`Values`](crate::Values) takes them; `{"reference": table, + /// "ids": ids}`; or a slice of a binary file, `{"file", "dtype", "offset", "count"}`: `count` + /// values from byte `offset` (0 unless given) of dtype `f32le`, `f64le`, `i32le`, `u32le`, + /// `u64le`, `u8` (numbers), or `bool` (a byte each, nonzero true). + /// - `append`'s `at` is one axis coordinate or several, as [`Patch::append`] takes them. + /// - An error names the path to what could not be read, such as `[2].set.fields.x`. + /// + /// Slices are fetched through `host`, all at once: a file's path or URL relative to `base`, the + /// document's own, or as it is when `base` is empty or the file's is absolute. + /// + /// ```no_run + /// # async fn example(host: &impl latkit::resource::Fetch) -> latkit::Result<()> { + /// let json = r#"[{"append": {"at": 0.5, "table": "Bus", "fields": {"vm": {"file": "vm.f32", "dtype": "f32le", "count": 3}}}}]"#; + /// let patch = latkit::Patch::load(json, "data/grid.json", host).await?; // reads data/vm.f32 + /// # Ok(()) } + /// ``` + pub async fn load(json: &str, base: &str, host: &(impl Fetch + ?Sized)) -> Result { + let ops: Vec = crate::from_json(json)?; + build(ops, base, host).await + } +} + +impl Data { + /// A dataset from its JSON, `{"name": ..., "patch": [...]}`: its name and the patch that builds it, + /// as its bytes are. The patch loads as [`Patch::load`] loads one. + pub async fn load(json: &str, base: &str, host: &(impl Fetch + ?Sized)) -> Result { + let form: DataForm = crate::from_json(json)?; + if form.name.is_empty() { + return Err(Error::invalid("a dataset is named").at("name")); + } + let patch = build(form.patch, base, host).await.map_err(|e| e.at("patch"))?; + let mut data = Data::new(form.name); + data.apply(patch)?; + Ok(data) + } +} + +/// Patches by dataset name, in the order written: what one step of a stream of changes carries, as +/// JSON `{"grid": [...], "weather": [...]}`, each patch in [`Patch::load`]'s form. +#[derive(Default, Deserialize)] +pub struct Patches(Ordered>); + +impl schemars::JsonSchema for Patches { + fn schema_name() -> std::borrow::Cow<'static, str> { + "Patches".into() + } + + fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema { + let mut schema = >>::json_schema(generator); + schema.insert("description".into(), "Patches by dataset name, in the order written.".into()); + schema + } +} + +impl Patches { + /// Each dataset's patch, in order, their slices fetched through `host` relative to `base`. + pub async fn load(self, base: &str, host: &(impl Fetch + ?Sized)) -> Result> { + let mut patches = Vec::with_capacity(self.0.0.len()); + for (name, ops) in self.0.0 { + let patch = build(ops, base, host).await.map_err(|e| e.at(name.as_str()))?; + patches.push((name, patch)); + } + Ok(patches) + } +} + +/// The patch `ops` make: their slices of files fetched through `host` at once, relative to `base`, +/// then each change built in order. +async fn build(mut ops: Vec, base: &str, host: &(impl Fetch + ?Sized)) -> Result { + let mut slices: Vec<&mut Column> = ops + .iter_mut() + .flat_map(|op| op.columns().iter_mut().map(|(_, column)| column)) + .filter(|column| matches!(column, Column::Slice(_))) + .collect(); + let fetching = slices + .iter() + .map(|column| { + let Column::Slice(slice) = &**column else { unreachable!("slices only") }; + Ok(host.fetch(&Request::range(crate::url::resolve(base, &slice.file), slice.offset..slice.end()?))) + }) + .collect::>>()?; + for (column, bytes) in slices.iter_mut().zip(fetching) { + let Column::Slice(slice) = &**column else { unreachable!("slices only") }; + let values = slice.read(&bytes.await?)?; + **column = Column::Values(values); + } + drop(slices); + patch(ops) +} + +#[cfg(test)] +mod tests { + use std::collections::HashMap; + + use super::*; + use crate::{Kind, Pending, Row, Value}; + + /// A host fetching from files in memory, and counting what it fetched. + #[derive(Default)] + struct Files(HashMap>, std::sync::Mutex>); + + impl Fetch for Files { + fn fetch(&self, request: &Request) -> Pending> { + self.1.lock().unwrap().push(request.clone()); + let bytes = self.0.get(&*request.url).map_or_else(Vec::new, |bytes| { + let range = request.range.clone().unwrap_or(0..bytes.len() as u64); + bytes[range.start as usize..(range.end as usize).min(bytes.len())].to_vec() + }); + Pending::ready(Ok(bytes)) + } + } + + fn load_data(json: &str, host: &Files) -> Result { + pollster::block_on(Data::load(json, "docs/grid.json", host)) + } + + #[test] + fn a_dataset_reads_its_tables_references_and_geometry() { + let json = r#"{"name": "grid", "patch": [ + {"replace": {"table": "Bus", "ids": ["b", "a"], "fields": { + "x": [1.5, null], "on": [true, false], "name": ["B", null], + "at": [[0, 1], [2, 3, 9]], "path": [[[0, 0], [1, 1]], []]}}}, + {"replace": {"table": "Branch", "ids": {"count": 1}, "fields": {"from": {"reference": "Bus", "ids": ["a"]}}}} + ]}"#; + let data = load_data(json, &Files::default()).unwrap(); + let bus = data.table("Bus").unwrap(); + assert_eq!(bus.get("b", "x"), Some(Value::Number(1.5))); + assert_eq!(bus.get("a", "x"), None); + assert_eq!(bus.get("a", "on"), Some(Value::Bool(false))); + assert_eq!(bus.get("b", "name"), Some(Value::Text("B".into()))); + assert_eq!(bus.get("a", "at"), Some(Value::Point([2.0, 3.0]))); + assert_eq!(bus.kind("path"), Some(Kind::Path)); + assert_eq!(bus.get("b", "path"), Some(Value::Path(vec![[0.0, 0.0], [1.0, 1.0]]))); + let row = Row { data: "grid".into(), table: "Branch".into(), id: 0_u64.into() }; + let target = Row { data: "grid".into(), table: "Bus".into(), id: "a".into() }; + assert_eq!(data.get(&row, "from"), Some(Value::Row(target))); + } + + #[test] + fn slices_fetch_at_once_relative_to_the_document_and_append_frames() { + let floats: Vec = [9_f32, 1.0, 2.0, 3.0, 4.0].into_iter().flat_map(f32::to_le_bytes).collect(); + let host = Files([("docs/v.f32".to_owned(), floats)].into(), std::sync::Mutex::default()); + let json = r#"{"name": "grid", "patch": [ + {"replace": {"table": "Bus", "ids": {"count": 2}, "fields": {"kv": {"file": "v.f32", "dtype": "f32le", "offset": 4, "count": 2}}}}, + {"axis": {"name": "time", "unit": "s"}}, + {"append": {"at": [0, 1], "table": "Bus", "fields": {"vm": {"file": "v.f32", "dtype": "f32le", "offset": 4, "count": 4}}}}, + {"forget": {"before": -1}} + ]}"#; + let data = load_data(json, &host).unwrap(); + let asked: Vec = host.1.lock().unwrap().clone(); + assert_eq!(asked, [Request::range("docs/v.f32", 4..12), Request::range("docs/v.f32", 4..20)]); + assert_eq!(data.span(), Some([0.0, 1.0])); + let row = |id: u64| Row { data: "grid".into(), table: "Bus".into(), id: id.into() }; + assert_eq!(data.get(&row(1), "kv"), Some(Value::Number(2.0))); + assert_eq!(data.get_at(&row(1), "vm", 1.0), Some(Value::Number(4.0))); + } + + #[test] + fn errors_name_the_change_table_and_field() { + let error = |json: &str| { + pollster::block_on(Patch::load(json, "", &Files::default())).map(|_| ()).unwrap_err().to_string() + }; + assert!( + error(r#"[{"replace": {"table": "Bus", "ids": {"count": 2}, "fields": {"x": [1, "a"]}}}]"#) + .contains("field x") + ); + assert!(error(r#"[{"bend": {}}]"#).contains("unknown variant")); + let named = error(r#"[{"axis": {"name": "t", "unit": "s"}}, {"remove": {"table": 3, "ids": []}}]"#); + assert!(named.starts_with("[1].remove.table"), "{named}"); + assert!( + error( + r#"[{"replace": {"table": "Bus", "ids": {"count": 1}, "fields": {"x": {"file": "f", "count": 1}}}}]"# + ) + .contains("dtype") + ); + let missing = r#"[{"replace": {"table": "Bus", "ids": {"count": 1}, "fields": {"x": {"file": "f.bin", "dtype": "f64le", "count": 1}}}}]"#; + assert_eq!(error(missing), "io: f.bin: 0 bytes of the slice's 8"); + let invalid = load_data( + r#"{"name": "grid", "patch": [{"replace": {"table": "Bus", "ids": [1, 1]}}]}"#, + &Files::default(), + ); + assert!(matches!(invalid, Err(Error::Invalid { path, .. }) if path.to_string().starts_with("patch[0]"))); + } +} diff --git a/crates/latkit/src/data/mod.rs b/crates/latkit/src/data/mod.rs new file mode 100644 index 00000000..bcdd1133 --- /dev/null +++ b/crates/latkit/src/data/mod.rs @@ -0,0 +1,53 @@ +//! Datasets: named tables of paged, immutable columns, changed only by patches. + +mod bits; +mod buffer; +mod bytes; +mod column; +mod dataset; +mod describe; +mod forms; +mod frames; +mod geometry; +mod ids; +mod json; +mod name; +mod ordered; +mod patch; +mod query; +mod samples; +mod table; +mod text; +mod values; + +pub use bytes::DecodeLimits; +pub use dataset::Data; +pub use describe::{Description, Envelope, FieldDescription, TableDescription}; +pub use ids::Ids; +pub use name::{Id, Name, Row, Rows}; +pub use patch::Patch; +pub use table::Table; +pub use values::{Kind, Value, Values}; +pub use { + json::Patches, + query::{Order, Query}, +}; + +pub(crate) use {geometry::Geometry, table::Field}; + +// What the GPU side reads of the data. +#[cfg(feature = "gpu")] +pub(crate) use { + column::{Column, PAGE_ROWS, Page}, + frames::{Listed, Manifest}, + geometry::GeometryBuilder, + ids::RowIds, + name::{PageId, Version}, + patch::Op, + samples::{AxisPage, FRAME_PAGE_WORDS, FramePage, MAX_LEVEL, Run, Samples, bucket_frames, detail, sides}, + table::{Inverse, Reference, UNWIRED}, + values::HOLE, +}; + +#[cfg(test)] +mod tests; diff --git a/crates/latkit/src/data/name.rs b/crates/latkit/src/data/name.rs new file mode 100644 index 00000000..edd16fae --- /dev/null +++ b/crates/latkit/src/data/name.rs @@ -0,0 +1,309 @@ +use std::borrow::Borrow; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::ops::Deref; +use std::sync::Arc; +use std::sync::atomic::{AtomicU64, Ordering}; + +/// The name of a dataset, table, or field: cheap to clone, compared and ordered by its text. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)] +#[serde(transparent)] +pub struct Name(Arc); + +/// A name is a text. +impl schemars::JsonSchema for Name { + fn inline_schema() -> bool { + true + } + + fn schema_name() -> std::borrow::Cow<'static, str> { + "Name".into() + } + + fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema { + schemars::json_schema!({ "type": "string" }) + } +} + +impl Name { + /// The name's text. + pub fn as_str(&self) -> &str { + &self.0 + } +} + +impl Deref for Name { + type Target = str; + + fn deref(&self) -> &str { + &self.0 + } +} + +impl Borrow for Name { + fn borrow(&self) -> &str { + &self.0 + } +} + +impl AsRef for Name { + fn as_ref(&self) -> &str { + &self.0 + } +} + +impl From<&str> for Name { + fn from(name: &str) -> Name { + Name(name.into()) + } +} + +impl From for Name { + fn from(name: String) -> Name { + Name(name.into()) + } +} + +impl From<&String> for Name { + fn from(name: &String) -> Name { + Name(name.as_str().into()) + } +} + +impl From<&Name> for Name { + fn from(name: &Name) -> Name { + name.clone() + } +} + +impl From> for Name { + fn from(name: Arc) -> Name { + Name(name) + } +} + +impl PartialEq for Name { + fn eq(&self, other: &str) -> bool { + &*self.0 == other + } +} + +impl PartialEq<&str> for Name { + fn eq(&self, other: &&str) -> bool { + &*self.0 == *other + } +} + +impl fmt::Display for Name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(&self.0) + } +} + +impl fmt::Debug for Name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&*self.0, f) + } +} + +/// A row's identity within its table: a number or a text. A number above 2^53 − 1 serializes as +/// decimal text, which names the same row, since JSON readers such as JavaScript's round it. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] +pub enum Id { + /// A numeric id. + Number(u64), + /// A text id. + Text(Arc), +} + +impl Id { + pub(crate) fn as_ref(&self) -> IdRef<'_> { + match self { + Id::Number(n) => IdRef::Number(*n), + Id::Text(t) => IdRef::Text(t), + } + } +} + +/// The largest whole number every JSON reader holds exactly. +const SAFE: u64 = (1 << 53) - 1; + +impl serde::Serialize for Id { + fn serialize(&self, serializer: S) -> Result { + match self { + Id::Number(n) if *n <= SAFE => serializer.serialize_u64(*n), + Id::Number(n) => serializer.collect_str(n), + Id::Text(t) => serializer.serialize_str(t), + } + } +} + +impl Hash for Id { + fn hash(&self, state: &mut H) { + self.as_ref().hash(state); + } +} + +impl fmt::Display for Id { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Id::Number(n) => write!(f, "{n}"), + Id::Text(t) => f.write_str(t), + } + } +} + +impl fmt::Debug for Id { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Id::Number(n) => write!(f, "{n}"), + Id::Text(t) => write!(f, "{t:?}"), + } + } +} + +macro_rules! number_ids { + ($($t:ty),*) => {$( + impl From<$t> for Id { + fn from(n: $t) -> Id { + Id::Number(u64::from(n)) + } + } + )*}; +} + +number_ids!(u32, u16, u8); + +impl From for Id { + fn from(n: u64) -> Id { + Id::Number(n) + } +} + +impl From for Id { + fn from(n: usize) -> Id { + Id::Number(n as u64) + } +} + +impl From<&str> for Id { + fn from(text: &str) -> Id { + Id::Text(text.into()) + } +} + +impl From for Id { + fn from(text: String) -> Id { + Id::Text(text.into()) + } +} + +impl From> for Id { + fn from(text: Arc) -> Id { + Id::Text(text) + } +} + +/// A borrowed [`Id`], for lookups that must not allocate. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub(crate) enum IdRef<'a> { + Number(u64), + Text(&'a str), +} + +impl IdRef<'_> { + pub(crate) fn to_id(self) -> Id { + match self { + IdRef::Number(n) => Id::Number(n), + IdRef::Text(t) => Id::Text(t.into()), + } + } +} + +/// A row of a table in a dataset. It survives any change that keeps the names and the id. +#[derive( + Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema, +)] +pub struct Row { + /// The dataset's name. + pub data: Name, + /// The table's name. + pub table: Name, + /// The row's id in the table. + pub id: Id, +} + +impl Row { + /// The row with `id` in `table` of `data`. + pub fn new(data: impl Into, table: impl Into, id: impl Into) -> Row { + Row { data: data.into(), table: table.into(), id: id.into() } + } +} + +/// Rows of one table in a dataset, by id: what a view selects, fits, and tells as sets of rows. +#[derive(Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +pub struct Rows { + /// The dataset's name. + pub data: Name, + /// The table's name. + pub table: Name, + /// The rows' ids in the table. + pub ids: Vec, +} + +impl Rows { + /// The rows with `ids` in `table` of `data`. + pub fn new>(data: impl Into, table: impl Into, ids: impl IntoIterator) -> Rows { + Rows { data: data.into(), table: table.into(), ids: ids.into_iter().map(Into::into).collect() } + } + + /// Each row, in order. + pub fn rows(&self) -> impl Iterator + '_ { + self.ids.iter().map(|id| Row { data: self.data.clone(), table: self.table.clone(), id: id.clone() }) + } + + /// `rows` as sets of rows, a set per table in the order each first appears. + pub(crate) fn group(rows: impl IntoIterator) -> Vec { + let mut sets: Vec = Vec::new(); + for Row { data, table, id } in rows { + match sets.iter_mut().rev().find(|s| s.data == data && s.table == table) { + Some(set) => set.ids.push(id), + None => sets.push(Rows { data, table, ids: vec![id] }), + } + } + sets + } + + /// Every row of `sets`, in order. + pub(crate) fn flatten(sets: impl IntoIterator) -> Vec { + sets.into_iter().flat_map(|set| set.rows().collect::>()).collect() + } +} + +impl From for Rows { + fn from(row: Row) -> Rows { + Rows { data: row.data, table: row.table, ids: vec![row.id] } + } +} + +macro_rules! counter { + ($($(#[$doc:meta])* $t:ident),*) => {$( + $(#[$doc])* + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + pub(crate) struct $t(u64); + + impl $t { + pub(crate) fn next() -> $t { + static NEXT: AtomicU64 = AtomicU64::new(1); + $t(NEXT.fetch_add(1, Ordering::Relaxed)) + } + } + )*}; +} + +counter!( + /// Identifies one state of something that changes: a dataset, a table's rows, or a field. + Version, + /// Identifies the contents of one page; a written page gets a new id. + PageId +); diff --git a/crates/latkit/src/data/ordered.rs b/crates/latkit/src/data/ordered.rs new file mode 100644 index 00000000..4a87a916 --- /dev/null +++ b/crates/latkit/src/data/ordered.rs @@ -0,0 +1,59 @@ +//! Named entries in the order written: what a JSON object means where order matters, such as a +//! patch's fields or a query's selected columns. + +use std::fmt; +use std::marker::PhantomData; + +use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor}; + +use super::name::Name; + +/// Entries in the order written, each name once. +#[derive(Clone, PartialEq, Debug)] +pub(crate) struct Ordered(pub(crate) Vec<(Name, V)>); + +impl Default for Ordered { + fn default() -> Ordered { + Ordered(Vec::new()) + } +} + +/// Named entries as an object of them. +impl schemars::JsonSchema for Ordered { + fn inline_schema() -> bool { + true + } + + fn schema_name() -> std::borrow::Cow<'static, str> { + format!("Ordered_{}", V::schema_name()).into() + } + + fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema { + >::json_schema(generator) + } +} + +impl<'de, V: Deserialize<'de>> Deserialize<'de> for Ordered { + fn deserialize>(deserializer: D) -> Result, D::Error> { + struct Entries(PhantomData); + impl<'de, V: Deserialize<'de>> Visitor<'de> for Entries { + type Value = Ordered; + + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("an object, each name once") + } + + fn visit_map>(self, mut map: A) -> Result, A::Error> { + let mut entries: Vec<(Name, V)> = Vec::new(); + while let Some(name) = map.next_key::()? { + if entries.iter().any(|(n, _)| n.as_str() == name) { + return Err(de::Error::custom(format!("{name} is named twice"))); + } + entries.push((name.into(), map.next_value()?)); + } + Ok(Ordered(entries)) + } + } + deserializer.deserialize_map(Entries(PhantomData)) + } +} diff --git a/crates/latkit/src/data/patch.rs b/crates/latkit/src/data/patch.rs new file mode 100644 index 00000000..a46742b7 --- /dev/null +++ b/crates/latkit/src/data/patch.rs @@ -0,0 +1,469 @@ +use std::sync::Arc; + +use super::column::Column; +use super::dataset::Inner; +use super::ids::Ids; +use super::name::{Name, Version}; +use super::samples::{Run, Samples}; +use super::table::{Field, Reference, Table}; +use super::values::Values; +use crate::{Error, Result}; + +/// Changes to a dataset, applied in order and all at once by [`Data::apply`](crate::Data::apply). +/// +/// Code builds patches and sockets carry them as bytes; every change reaches a dataset the same way. +/// A patch made by [`Patch::to`] names the dataset it changes, as a stream of several datasets' patches +/// does: applying it to another dataset is an error. +#[derive(Clone, Default, Debug)] +pub struct Patch { + pub(crate) data: Option, + pub(crate) ops: Vec, +} + +#[derive(Clone, Debug)] +pub(crate) enum Op { + /// Names the axis sampled fields are recorded over. + Axis { name: Name, unit: Name }, + /// Replaces a whole table, sampled fields included. + Replace(Table), + /// Writes the given fields of the given rows; unknown ids add rows, unknown tables are added. + Set(Table), + /// Removes rows by id; ids that name no row are ignored. + Remove { table: Name, ids: Ids }, + /// Records frames of sampled fields, frame-major: of every row, or of the rows `ids` names, the + /// rest holding their last values. + Append { table: Name, at: Vec, ids: Option, fields: Vec<(Name, Values)> }, + /// Forgets every sampled field's frames before a coordinate. + Forget { before: f64 }, + /// Holds a run of a sampled field's entries: their coordinates, and their values entry-major. + Frames { table: Name, field: Name, run: Run, at: Vec, values: Vec }, +} + +impl Patch { + /// An empty patch, for whichever dataset it is applied to. + pub fn new() -> Patch { + Patch::default() + } + + /// An empty patch to dataset `data`. + pub fn to(data: impl Into) -> Patch { + Patch { data: Some(data.into()), ops: Vec::new() } + } + + /// The dataset the patch changes, when it names one. + pub fn data(&self) -> Option<&Name> { + self.data.as_ref() + } + + /// Names the axis sampled fields are recorded over, such as `("time", "s")`. + #[must_use] + pub fn axis(mut self, name: impl Into, unit: impl Into) -> Patch { + self.ops.push(Op::Axis { name: name.into(), unit: unit.into() }); + self + } + + /// Replaces table `table.name()` with `table`, or adds it. + #[must_use] + pub fn replace(mut self, table: Table) -> Patch { + self.ops.push(Op::Replace(table)); + self + } + + /// Writes `table`'s fields for its rows: rows with known ids change, others are added, and fields + /// it leaves out keep their values. Adds the table when there is none of its name. + #[must_use] + pub fn set(mut self, table: Table) -> Patch { + self.ops.push(Op::Set(table)); + self + } + + /// Removes the rows of `table` with `ids`. + #[must_use] + pub fn remove(mut self, table: impl Into, ids: impl Into) -> Patch { + self.ops.push(Op::Remove { table: table.into(), ids: ids.into() }); + self + } + + /// Records a frame at each axis coordinate of `at`: for each field, a value per row of `table` + /// at every coordinate, frame-major, every row's at the first coordinate, then at the next. + /// + /// A field's first frame makes it sampled. Coordinates never decrease; at equal coordinates the + /// last frame reads. + #[must_use] + pub fn append( + mut self, + at: impl AsRef<[f64]>, + table: impl Into, + fields: impl IntoIterator, + ) -> Patch + where + F: Into, + V: Into, + { + let fields = fields.into_iter().map(|(name, values)| (name.into(), values.into())).collect(); + self.ops.push(Op::Append { table: table.into(), at: at.as_ref().to_vec(), ids: None, fields }); + self + } + + /// Records a frame at each axis coordinate of `at` for the rows of `table` that `ids` names, as + /// [`append`](Patch::append) does for every row: a value per row named at every coordinate, + /// frame-major. Rows left out hold their last value. + #[must_use] + pub fn append_rows( + mut self, + at: impl AsRef<[f64]>, + table: impl Into, + ids: impl Into, + fields: impl IntoIterator, + ) -> Patch + where + F: Into, + V: Into, + { + let fields = fields.into_iter().map(|(name, values)| (name.into(), values.into())).collect(); + self.ops.push(Op::Append { table: table.into(), at: at.as_ref().to_vec(), ids: Some(ids.into()), fields }); + self + } + + /// Forgets every sampled field's frames before axis coordinate `before`. Whole frame pages drop, + /// so it costs O(pages); older versions of the dataset keep what they read. + #[must_use] + pub fn forget(mut self, before: f64) -> Patch { + self.ops.push(Op::Forget { before }); + self + } + + /// Holds a run of sampled field `field`'s entries of level `level`, numbered from `first`: what a + /// time tile holds, as `latkit tile` writes them. At level 0 the entries are frames, each a + /// coordinate in `at` and a value per row of `table` in `values`. At level `k` they are buckets of + /// `8^k` frames, each its first and last frame's coordinates in `at`, and in `values` each row's + /// least value over each bucket, then each row's greatest. NaN is missing. + /// + /// No entry may be held already; frames past the field's widen it, and those it skips stay missing. + /// + /// ``` + /// # use latkit::{Data, Ids, Patch, Table}; + /// let mut grid = Data::new("grid"); + /// grid.apply(Patch::new().replace(Table::new("Bus", Ids::count(2))))?; + /// // Frames 100 and 101, then the bucket of frames 0..8. + /// grid.apply(Patch::new().frames("Bus", "vm", 0, 100, [100.0, 101.0], [1.0, 0.9, 1.02, 0.98]))?; + /// grid.apply(Patch::new().frames("Bus", "vm", 1, 0, [0.0, 7.0], [0.95, 0.9, 1.05, 1.0]))?; + /// assert_eq!(grid.describe().span, Some([0.0, 101.0])); + /// # Ok::<(), latkit::Error>(()) + /// ``` + #[must_use] + pub fn frames( + mut self, + table: impl Into, + field: impl Into, + level: u32, + first: u64, + at: impl Into>, + values: impl Into>, + ) -> Patch { + self.ops.push(Op::frames(table.into(), field.into(), level, first, at.into(), values.into())); + self + } + + /// This patch followed by `next`'s changes, to this patch's dataset. + #[must_use] + pub fn extend(mut self, next: Patch) -> Patch { + self.ops.extend(next.ops); + self + } + + /// Whether the patch changes nothing. + pub fn is_empty(&self) -> bool { + self.ops.is_empty() + } + + /// The patch as bytes: one frame, naming its dataset when it has one. + pub fn to_bytes(&self) -> Vec { + super::bytes::encode(self) + } + + /// A patch from [`Patch::to_bytes`] or [`Data::to_bytes`](crate::Data::to_bytes). + pub fn from_bytes(bytes: &[u8]) -> Result { + super::bytes::decode(bytes) + } + + /// The patch at the start of `bytes` and how many bytes it takes, or `None` while `bytes` hold + /// only its start: frames back to back, as files, pipes, and sockets carry them, decode one by + /// one, and each says its length up front, so a partial one costs nothing to wait on. A frame + /// longer than `limit` bytes is [`Error::Limit`](crate::Error::Limit) at once, so a stream of + /// untrusted bytes never waits on more than `limit`. + /// + /// ``` + /// # use latkit::{Ids, Patch, Table}; + /// let mut stream = Patch::to("grid").set(Table::new("Bus", Ids::count(1))).to_bytes(); + /// stream.extend(Patch::to("grid").remove("Bus", [0_u64]).to_bytes()); + /// let limit = 1 << 20; + /// let (first, used) = Patch::decode(&stream, limit)?.expect("a whole patch"); + /// let (second, rest) = Patch::decode(&stream[used..], limit)?.expect("a whole patch"); + /// assert_eq!(used + rest, stream.len()); + /// assert_eq!(second.data().map(|d| d.as_str()), Some("grid")); + /// assert!(Patch::decode(&stream[..used - 1], limit)?.is_none(), "more bytes to come"); + /// assert!(Patch::decode(&stream, 8).is_err(), "longer than the limit"); + /// # Ok::<(), latkit::Error>(()) + /// ``` + pub fn decode_with_limits(bytes: &[u8], limits: super::bytes::DecodeLimits) -> Result> { + super::bytes::decode_with_limits(bytes, limits) + } + + /// Decodes one frame with an encoded byte limit and the default decoded storage budget. + pub fn decode(bytes: &[u8], limit: usize) -> Result> { + super::bytes::decode_prefix(bytes, limit) + } +} + +impl From
for Patch { + fn from(table: Table) -> Patch { + Patch::new().set(table) + } +} + +/// Appends to the same fields of every row of one table, one after another: recorded as one, so a +/// field takes its frames in one write however many changes carried them. +pub(crate) struct Appends { + table: Name, + at: Vec, + fields: Vec<(Name, Vec)>, +} + +impl Appends { + pub(crate) fn new(table: Name, at: Vec, fields: Vec<(Name, Values)>) -> Appends { + Appends { table, at, fields: fields.into_iter().map(|(name, values)| (name, vec![values])).collect() } + } + + /// Whether an append of `fields` at `at` to `table`, which has `rows` rows, carries the run on: the + /// same fields of the same kinds, a value for every row at each coordinate, coordinates that never + /// decrease. One that does not records on its own, so its error names it. + pub(crate) fn continues(&self, table: &Name, at: &[f64], fields: &[(Name, Values)], rows: Option) -> bool { + let Some(rows) = rows else { return false }; + let last = self.at.last().copied().unwrap_or(f64::NEG_INFINITY); + *table == self.table + && fields.len() == self.fields.len() + && fields.iter().zip(&self.fields).all(|((name, values), (run, parts))| { + name == run && values.kind() == parts[0].kind() && values.len() == at.len() * rows + }) + && at.iter().all(|t| t.is_finite()) + && at.first().is_none_or(|&first| first >= last) + && at.windows(2).all(|w| w[0] <= w[1]) + } + + pub(crate) fn push(&mut self, at: Vec, fields: Vec<(Name, Values)>) { + self.at.extend(at); + for ((_, parts), (_, values)) in self.fields.iter_mut().zip(fields) { + parts.push(values); + } + } + + /// The run as one append. + pub(crate) fn op(self) -> Op { + let fields = self + .fields + .into_iter() + .map(|(name, mut parts)| { + let values = if parts.len() == 1 { + parts.pop().expect("a part") + } else { + Values::concat(&parts.iter().collect::>()) + }; + (name, values) + }) + .collect(); + Op::Append { table: self.table, at: self.at, ids: None, fields } + } +} + +impl Op { + /// Holds entries of `level` from `first`, as many as `at` holds coordinates of. + pub(crate) fn frames(table: Name, field: Name, level: u32, first: u64, at: Vec, values: Vec) -> Op { + let entries = (at.len() / super::samples::coordinates(level)) as u64; + let run = Run { level, entries: first..first.saturating_add(entries) }; + Op::Frames { table, field, run, at, values } + } + + pub(crate) fn apply(self, data: &mut Inner) -> Result<()> { + match self { + Op::Axis { name, unit } => { + data.axis = Some((name, unit)); + Ok(()) + } + Op::Replace(table) => { + let name = table.name.clone(); + table.check().map_err(|e| e.at(&name))?; + match data.position(&name) { + Ok(i) => data.tables[i] = table, + Err(i) => data.tables.insert(i, table), + } + Ok(()) + } + Op::Set(table) => { + let name = table.name.clone(); + table.check().map_err(|e| e.at(&name))?; + if let Some((field, _)) = table.fields.iter().find(|(_, f)| matches!(f, Field::Sampled(..))) { + return Err(Error::invalid("set writes values and references; append records samples") + .at(field) + .at(&name)); + } + match data.position(&name) { + Ok(i) => data.tables[i] = set(&data.tables[i], table).map_err(|e| e.at(&name))?, + Err(i) => data.tables.insert(i, table), + } + Ok(()) + } + Op::Remove { table, ids } => { + let i = data.position(&table).map_err(|_| Error::invalid("no such table").at(&table))?; + data.tables[i] = remove(&data.tables[i], &ids).map_err(|e| e.at(&table))?; + Ok(()) + } + Op::Append { table, at, ids, fields } => { + let i = data.position(&table).map_err(|_| Error::invalid("no such table").at(&table))?; + let target = &mut data.tables[i]; + let rows = ids.map(|ids| rows_named(target, &ids)).transpose().map_err(|e| e.at(&table))?; + for (name, values) in fields { + let mut samples = match target.field_named(&name) { + None => Samples::default(), + Some(Field::Sampled(samples, _)) => samples.clone(), + Some(_) => { + return Err(Error::invalid("not a sampled field").at(&name).at(&table)); + } + }; + let appended = match &rows { + None => samples.append(&at, &values, target.len()), + Some(rows) => samples.append_rows(&at, &values, rows, target.len()), + }; + appended.map_err(|e| e.at(&name).at(&table))?; + target.insert(name, Field::Sampled(samples, Version::next())); + } + Ok(()) + } + Op::Forget { before } => { + for table in &mut data.tables { + for (_, field) in &mut table.fields { + if let Field::Sampled(samples, version) = field + && samples.forget(before) + { + *version = Version::next(); + } + } + } + Ok(()) + } + Op::Frames { table, field, run, at, values } => { + let i = data.position(&table).map_err(|_| Error::invalid("no such table").at(&table))?; + let target = &mut data.tables[i]; + let per_row = run.len() * super::samples::sides(run.level); + let rows = values.len().checked_div(per_row).unwrap_or(0); + if rows > target.len() { + return Err(Error::invalid(format!("values for {rows} rows of {}", target.len())) + .at(&field) + .at(&table)); + } + let mut samples = match target.field_named(&field) { + None => Samples::default(), + Some(Field::Sampled(samples, _)) => samples.clone(), + Some(_) => return Err(Error::invalid("not a sampled field").at(&field).at(&table)), + }; + samples.insert(&run, &at, &values, rows).map_err(|e| e.at(&field).at(&table))?; + target.insert(field, Field::Sampled(samples, Version::next())); + Ok(()) + } + } + } +} + +/// The row of `table` each of `ids` names; an id naming none is an error, as an append records +/// frames of rows the table holds. +fn rows_named(table: &Table, ids: &Ids) -> Result> { + let index = table.index()?; + (0..ids.len()) + .map(|k| { + let key = ids.key(k).ok_or_else(|| Error::invalid("a row needs an id").at(k).at("ids"))?; + index.get(&table.ids, key).ok_or_else(|| Error::invalid(format!("no row {key:?}")).at(k).at("ids")) + }) + .collect() +} + +/// `existing` with `input`'s fields written for `input`'s rows. +fn set(existing: &Table, input: Table) -> Result
{ + let index = existing.index()?; + let mut added = Vec::new(); + let mut writes = Vec::with_capacity(input.len()); + for k in 0..input.len() { + let key = input.ids.key(k).expect("checked ids"); + let row = index.get(&existing.ids, key).unwrap_or_else(|| { + added.push(key.to_id()); + existing.len() + added.len() - 1 + }); + writes.push((row, k)); + } + writes.sort_unstable(); + let len = existing.len() + added.len(); + let mut table = existing.clone(); + if !added.is_empty() { + table.ids = existing.ids.extend(&added).map_err(|e| e.at("ids"))?; + table.index = Arc::default(); + table.structure = Version::next(); + } + for (name, field) in input.fields { + let next = match (existing.field_named(&name), field) { + (Some(Field::Values(column, _)), Field::Values(source, _)) => { + Field::Values(column.write(len, &writes, &source).map_err(|e| e.at(&name))?, Version::next()) + } + (None, Field::Values(source, _)) => { + let column = Column::missing(source.like(), existing.len()).write(len, &writes, &source)?; + Field::Values(column, Version::next()) + } + (Some(Field::Reference(old)), Field::Reference(source)) if old.to == source.to => { + let ids = old.ids.write(len, &writes, &source.ids).map_err(|e| e.at(&name))?; + Field::Reference(Reference { ids, version: Version::next(), inverse: Arc::default(), ..old.clone() }) + } + (None, Field::Reference(source)) => { + let ids = Column::missing(source.ids.like(), existing.len()).write(len, &writes, &source.ids)?; + Field::Reference(Reference::new(source.to, ids)) + } + (Some(old), new) => { + let reason = format!("{:?} values for a {:?} field", new.kind(), old.kind()); + return Err(Error::invalid(reason).at(&name)); + } + (None, Field::Sampled(..)) => unreachable!("set refuses sampled fields"), + }; + table.insert(name, next); + } + if !added.is_empty() { + for (_, field) in &mut table.fields { + match field { + Field::Values(column, version) if column.len() < len => { + *column = column.write(len, &[], column)?; + *version = Version::next(); + } + Field::Reference(reference) if reference.ids.len() < len => { + reference.ids = reference.ids.write(len, &[], &reference.ids)?; + reference.version = Version::next(); + } + _ => {} + } + } + } + Ok(table) +} + +/// `existing` without the rows named by `ids`. +fn remove(existing: &Table, ids: &Ids) -> Result
{ + let index = existing.index()?; + let mut doomed = vec![false; existing.len()]; + let mut any = false; + for i in 0..ids.len() { + if let Some(row) = ids.key(i).and_then(|key| index.get(&existing.ids, key)) { + doomed[row] = true; + any = true; + } + } + if !any { + return Ok(existing.clone()); + } + let keep: Vec = (0..existing.len()).filter(|&r| !doomed[r]).collect(); + Ok(existing.rows(&keep)) +} diff --git a/crates/latkit/src/data/query.rs b/crates/latkit/src/data/query.rs new file mode 100644 index 00000000..44a7e13e --- /dev/null +++ b/crates/latkit/src/data/query.rs @@ -0,0 +1,230 @@ +//! Reading data back: the rows of a table a query keeps, in the order it sorts them, a page of them, +//! with their fields or what expressions make of them. Queries run on the CPU through the same +//! expressions marks draw with, a plain field read page by page, and return a table, so what comes +//! back has the shape of what goes in. + +use std::cmp::Ordering; + +use super::ids::Ids; +use super::name::Name; +use super::ordered::Ordered; +use super::table::{Field, Table}; +use super::values::Values; +use super::{Data, column::Column}; +use crate::expr::Expr; +use crate::expr::cpu::Rows; +use crate::{Error, Result}; + +/// The rows of a table to read back: of the rows `ids` names (every row unless set), those `filter` +/// keeps, sorted by `sort`, a page of them from `offset` of at most `limit`, with the fields `select` +/// names or computes; sampled fields read at axis coordinate `at`, their last frame by default. Plain +/// data, like a scene. +/// +/// ``` +/// use latkit::{Data, Ids, Order, Query, Table, field}; +/// let mut data = Data::new("grid"); +/// data.apply(Table::new("Branch", Ids::count(3)).field("loading", vec![40.0, 95.0, 120.0]).field("name", vec!["a", "b", "c"]))?; +/// let (hot, kept) = data.query(&Query::of("Branch").filter(field("loading").gt(90.0)).sort(field("loading"), Order::Descending).limit(1))?; +/// assert_eq!(hot.get(2_u64, "name"), Some(latkit::Value::Text("c".into()))); +/// assert_eq!((hot.len(), kept), (1, 2)); +/// # Ok::<(), latkit::Error>(()) +/// ``` +#[derive(Clone, PartialEq, Debug, serde::Deserialize, schemars::JsonSchema)] +#[serde(deny_unknown_fields)] +#[schemars(description = "The rows of a table to read back, run through the expressions marks draw with.")] +pub struct Query { + /// The table read. + of: Name, + /// The rows read, in this order unless sorted; every row unless set. Ids that name no row are + /// passed over. + #[serde(default)] + ids: Option, + /// Keeps the rows it is true for. + #[serde(default)] + filter: Option, + /// Keys to sort by, each after those before it; rows a key reads nothing for come last, and rows + /// all keys order alike keep their order. + #[serde(default)] + sort: Vec<(Expr, Order)>, + /// The kept rows skipped first. + #[serde(default)] + offset: usize, + /// The most rows read; a limit picks them in linear time before sorting only those. + limit: Option, + /// Fields to read by name: a field as it is, anything else as numbers. Every field unless set. + #[serde(default)] + select: Ordered, + /// The axis coordinate sampled fields are read at; their last frame unless set. + at: Option, +} + +/// Which way a sort runs; rows a key reads nothing for come last either way. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, serde::Deserialize, schemars::JsonSchema)] +#[serde(rename_all = "lowercase")] +pub enum Order { + /// Least first. + #[default] + Ascending, + /// Greatest first. + Descending, +} + +impl Query { + /// Every row of table `table`, every field. + pub fn of(table: impl Into) -> Query { + Query { + of: table.into(), + ids: None, + filter: None, + sort: Vec::new(), + offset: 0, + limit: None, + select: Ordered::default(), + at: None, + } + } + + /// Reads only the rows `ids` names, in that order unless sorted. + #[must_use] + pub fn ids(mut self, ids: impl Into) -> Query { + self.ids = Some(ids.into()); + self + } + + /// Keeps the rows `keep` is true for. + #[must_use] + pub fn filter(mut self, keep: impl Into) -> Query { + self.filter = Some(keep.into()); + self + } + + /// Sorts by `key`, after the keys given before; rows it orders alike keep their order. + #[must_use] + pub fn sort(mut self, key: impl Into, order: Order) -> Query { + self.sort.push((key.into(), order)); + self + } + + /// Skips the first `offset` rows kept. + #[must_use] + pub fn offset(mut self, offset: usize) -> Query { + self.offset = offset; + self + } + + /// Reads at most `limit` rows. + #[must_use] + pub fn limit(mut self, limit: usize) -> Query { + self.limit = Some(limit); + self + } + + /// Reads field `name` as `value` makes it: a field as it is, anything else as numbers. With none + /// selected, every field is read. + #[must_use] + pub fn select(mut self, name: impl Into, value: impl Into) -> Query { + self.select.0.push((name.into(), value.into())); + self + } + + /// Reads sampled fields at axis coordinate `at`. + #[must_use] + pub fn at(mut self, at: f64) -> Query { + self.at = Some(at); + self + } +} + +impl Data { + /// The rows of a table `query` asks for, as a table of their own: their ids, and their fields or + /// what the query computes, sampled fields read at its coordinate; and how many rows its filter + /// kept, before the page. A limit picks its rows in linear time before sorting only them. + pub fn query(&self, query: &Query) -> Result<(Table, usize)> { + let table = self.table(&query.of).ok_or_else(|| Error::invalid("no such table").at(query.of.as_str()))?; + let at = query.at.unwrap_or(f64::INFINITY); + let all = std::slice::from_ref(self); + let rows = Rows::new(table, all).at(at); + let named: Vec = match &query.ids { + Some(ids) => (0..ids.len()).filter_map(|k| table.row(ids.key(k)?)).collect(), + None => (0..table.len()).collect(), + }; + let mut picked: Vec = match &query.filter { + Some(keep) => { + let kept = rows.numbers(keep, |x| x > 0.5); + named.into_iter().filter(|&r| kept[r]).collect() + } + None => named, + }; + let total = picked.len(); + let end = query.limit.map_or(picked.len(), |limit| query.offset.saturating_add(limit).min(picked.len())); + if !query.sort.is_empty() { + let keys: Vec<(Vec, Order)> = + query.sort.iter().map(|(key, order)| (rows.numbers(key, |x| x), *order)).collect(); + let compare = |a: &usize, b: &usize| { + keys.iter() + .map(|(values, order)| compare(values[*a], values[*b], *order)) + .find(|o| o.is_ne()) + .unwrap_or(Ordering::Equal) + .then(a.cmp(b)) + }; + if end < picked.len() { + picked.select_nth_unstable_by(end, compare); + picked.truncate(end); + } + picked.sort_unstable_by(compare); + } + let page = &picked[query.offset.min(end)..end]; + let version = super::name::Version::next(); + let mut out = Table { + name: table.name.clone(), + ids: table.ids.gather(page), + index: std::sync::Arc::default(), + fields: Vec::new(), + structure: version, + order: version, + }; + if query.select.0.is_empty() { + for (name, field) in &table.fields { + out.insert(name.clone(), plain(field, at, page)); + } + return Ok((out, total)); + } + for (name, value) in &query.select.0 { + let field = if let Some(f) = value.field_name() { + let Some(field) = table.field_named(f) else { + return Err(Error::invalid(format!("no field {f}")).at(name.as_str()).at("select")); + }; + plain(field, at, page) + } else { + let numbers = rows.numbers(value, |x| x.is_finite().then_some(x)); + let values = Values::from(page.iter().map(|&r| numbers[r]).collect::>()); + Field::Values(Column::new(&values), super::name::Version::next()) + }; + out.insert(name.clone(), field); + } + Ok((out, total)) + } +} + +/// How two sort keys order rows: missing last, whichever way the sort runs. +fn compare(a: f64, b: f64, order: Order) -> Ordering { + match (a.is_finite(), b.is_finite()) { + (true, true) if order == Order::Descending => b.total_cmp(&a), + (true, true) => a.total_cmp(&b), + (true, false) => Ordering::Less, + (false, true) => Ordering::Greater, + (false, false) => Ordering::Equal, + } +} + +/// `field` of rows `rows` as plain values: a sampled field read at `at`, one frame, not its history. +fn plain(field: &Field, at: f64, rows: &[usize]) -> Field { + match field { + Field::Sampled(samples, _) => { + let frame = samples.frame_at(at); + let values: Vec> = rows.iter().map(|&row| frame.and_then(|f| samples.value(row, f))).collect(); + Field::Values(Column::new(&Values::from(values)), super::name::Version::next()) + } + other => other.gather(rows), + } +} diff --git a/crates/latkit/src/data/samples.rs b/crates/latkit/src/data/samples.rs new file mode 100644 index 00000000..4a108930 --- /dev/null +++ b/crates/latkit/src/data/samples.rs @@ -0,0 +1,1336 @@ +//! Samples: a field's values over the data's axis. Level 0 holds frames, each row's value at one +//! coordinate; each level `k` above it holds buckets of `8^k` frames, each row's least and greatest over +//! them, so a long history draws from as few entries as there are pixels. Every level keeps its +//! entries in pages, with each entry's coordinates (a frame's own; a bucket's first and last frame's), +//! so a level draws without the levels below it. Frames are numbered from the first ever written, and +//! a version reads `start..end`. +//! +//! Any entry may be missing. Frames appended grow the newest pages in place and seal each bucket whose +//! entries below are all held; runs of entries read from bytes or fetched as time tiles fill any span, +//! whatever lies around them. An entry is held when its level's coordinates hold it: every write writes +//! an entry's coordinates and every row block's values together. + +use std::ops::Range; +use std::sync::{Arc, PoisonError, RwLock}; + +use super::column::{PAGE_BITS, PAGE_MASK, PAGE_ROWS}; +use super::name::PageId; +use super::values::Values; +use crate::{Error, Result}; + +/// Words in a frame page: entries of one row block, entry-major. An axis page holds as many words on +/// the GPU, two for each entry. +pub(crate) const FRAME_PAGE_WORDS: usize = 1 << 16; +/// Levels of detail kept above frames: level `k` holds each row's least and greatest value over buckets +/// of `8^k` frames. +pub(crate) const LEVELS: u32 = 6; +/// Highest format level: a bucket spans 2^63 frames and still fits a u64. +pub(crate) const MAX_LEVEL: u32 = 21; + +/// Frames an entry of level `level` spans: a frame, or a bucket's frames. +pub(crate) fn bucket_frames(level: u32) -> u64 { + 1 << (3 * level) +} + +/// The level of detail `frames` frames draw at across `columns` pixel columns: frames while there are +/// at most two a column, else the finest level whose buckets are no fewer. +pub(crate) fn detail(frames: u64, columns: u32) -> u32 { + let needed = frames.div_ceil(2 * u64::from(columns.max(1))); + if needed <= 1 { 0 } else { (1..=MAX_LEVEL).find(|&k| bucket_frames(k) >= needed).unwrap_or(MAX_LEVEL) } +} + +/// Coordinates an entry of `level` holds: a frame its own, a bucket its first and last frame's. +pub(crate) fn coordinates(level: u32) -> usize { + if level == 0 { 1 } else { 2 } +} + +/// Values a row holds of an entry of `level`: a frame's, or a bucket's least and greatest. +pub(crate) fn sides(level: u32) -> usize { + if level == 0 { 1 } else { 2 } +} + +/// The log of a row block holding `level`'s values of `side`: its frames, or a level's least (0) or +/// greatest (1). +fn slot(level: u32, side: usize) -> usize { + if level == 0 { 0 } else { 2 * level as usize - 1 + side } +} + +/// Entries `entries` of level `level`. +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub(crate) struct Run { + pub(crate) level: u32, + pub(crate) entries: Range, +} + +impl Run { + /// Number of entries; runs in memory always fit the address space. + pub(crate) fn len(&self) -> usize { + usize::try_from(self.entries.end - self.entries.start).expect("run fits in memory") + } + + /// The frames its entries span. + pub(crate) fn frames(&self) -> Range { + let span = bucket_frames(self.level); + self.entries.start.saturating_mul(span)..self.entries.end.saturating_mul(span) + } + + /// How many coordinates it holds, and how many values for `rows` rows. + pub(crate) fn sizes(&self, rows: usize) -> Option<(usize, usize)> { + let n = usize::try_from(self.entries.end.checked_sub(self.entries.start)?).ok()?; + Some((n.checked_mul(coordinates(self.level))?, n.checked_mul(rows)?.checked_mul(sides(self.level))?)) + } +} + +/// Appends `run` to `runs`, joining it to the last where it follows it at the same level. +fn join(runs: &mut Vec, run: Run) { + match runs.last_mut() { + Some(last) if last.level == run.level && last.entries.end == run.entries.start => { + last.entries.end = run.entries.end; + } + _ => runs.push(run), + } +} + +/// A list shared between versions. Indices are absolute: a version reads items `start..end`, so +/// forgetting the oldest never renumbers the rest. +/// +/// A version that appends while it is the newest grows the shared list in place; any other change, an +/// older version appending, an item put between others or taken out, forks a copy of what it reads. +pub(crate) struct Log { + items: Arc>>, + /// The absolute index of `items[0]`. + base: usize, + start: usize, + end: usize, +} + +impl Clone for Log { + fn clone(&self) -> Log { + Log { items: self.items.clone(), base: self.base, start: self.start, end: self.end } + } +} + +impl Default for Log { + fn default() -> Log { + Log { items: Arc::default(), base: 0, start: 0, end: 0 } + } +} + +impl Log { + pub(crate) fn push(&mut self, item: T) { + { + let mut items = self.items.write().unwrap_or_else(PoisonError::into_inner); + if self.base + items.len() == self.end { + items.push(item); + self.end += 1; + return; + } + } + self.edit(|items| items.push(item)); + } + + /// Changes the items this version reads in a copy of its own. + fn edit(&mut self, f: impl FnOnce(&mut Vec)) { + let mut items = self.read(<[T]>::to_vec); + f(&mut items); + self.end = self.start + items.len(); + self.items = Arc::new(RwLock::new(items)); + self.base = self.start; + } + + /// Reads items `start..end`. + pub(crate) fn read(&self, f: impl FnOnce(&[T]) -> R) -> R { + let items = self.items.read().unwrap_or_else(PoisonError::into_inner); + f(&items[self.start - self.base..self.end - self.base]) + } + + pub(crate) fn last(&self) -> Option { + self.read(|items| items.last().cloned()) + } + + /// Stops reading items before absolute index `start`. Storage shared with other versions stays + /// theirs; this version copies what it keeps once the forgotten part outgrows a quarter of it. + pub(crate) fn forget(&mut self, start: usize) { + self.start = start.clamp(self.start, self.end); + if self.start - self.base > (self.end - self.start) / 4 + 16 { + let kept = self.read(<[T]>::to_vec); + self.items = Arc::new(RwLock::new(kept)); + self.base = self.start; + } + } +} + +/// What a page stores, shared by every version reading it, and whether appends grow it. +struct Store { + grows: bool, + items: RwLock>, +} + +/// Consecutive entries of a level, `per` values each, entry-major: a row block's frames or a level's +/// least or greatest values, `per` its rows; or a level's coordinates, `per` an entry's. A page an +/// append opened grows in place while it is the newest version's last; a version reads at most `cap` +/// entries of it, fewer than it stores where a newer version grew it. +#[derive(Clone)] +pub(crate) struct Page { + pub(crate) id: PageId, + pub(crate) first: u64, + pub(crate) per: u32, + cap: u32, + store: Arc>, +} + +/// A page of a row block's frames, or of a level's least or greatest values: `per` rows an entry. +pub(crate) type FramePage = Page; +/// A page of a level's coordinates: `per` an entry, a frame's own or a bucket's first and last. +pub(crate) type AxisPage = Page; + +impl Page { + fn new(first: u64, per: usize, items: Vec, grows: bool) -> Page { + Page { + id: PageId::next(), + first, + per: per as u32, + cap: u32::MAX, + store: Arc::new(Store { grows, items: RwLock::new(items) }), + } + } + + /// Reads the page's stored items. + pub(crate) fn read(&self, f: impl FnOnce(&[T]) -> R) -> R { + f(&self.store.items.read().unwrap_or_else(PoisonError::into_inner)) + } + + /// Whether appends grow it: it takes room to grow into on the GPU. + pub(crate) fn grows(&self) -> bool { + self.store.grows + } + + /// Entries this version reads of it. + pub(crate) fn len(&self) -> u32 { + ((self.read(<[T]>::len) / self.per.max(1) as usize) as u32).min(self.cap) + } + + pub(crate) fn end(&self) -> u64 { + self.first + u64::from(self.len()) + } + + /// Appends `entry`'s `items` where this version reads the whole page, appends grow it, and the + /// entry follows its last and fits within `limit` items. + fn extend(&self, entry: u64, items: &[T], limit: usize) -> bool { + if entry != self.end() { + return false; + } + let mut stored = self.store.items.write().unwrap_or_else(PoisonError::into_inner); + let at = (entry - self.first) as usize * self.per as usize; + let fits = items.len() == self.per as usize && at + items.len() <= limit; + if !self.store.grows || self.cap != u32::MAX || stored.len() != at || !fits { + return false; + } + stored.extend_from_slice(items); + true + } + + /// The page as a version that reads only its first `len` entries sees it. + fn capped(&self, len: u32) -> Page { + Page { cap: len, ..self.clone() } + } +} + +impl AxisPage { + /// Coordinate `which` of entry `index`: a frame's own, a bucket's first (0) or last (1) frame's. + fn coordinate(&self, index: u64, which: u32) -> Option { + if index < self.first || index >= self.end() { + return None; + } + let i = (index - self.first) as usize * self.per as usize + which.min(self.per - 1) as usize; + self.read(|c| c.get(i).copied()) + } + + /// Where entry `index` draws: a frame at its coordinate, a bucket at its middle. + fn drawn(&self, index: u64) -> Option { + Some(f64::midpoint(self.coordinate(index, 0)?, self.coordinate(index, 1)?)) + } + + /// Words the page takes on the GPU: where each entry draws, as a high and a low `f32`. + pub(crate) fn words_len(&self) -> usize { + 2 * (self.read(<[f64]>::len) / self.per as usize) + } + + /// The page's GPU words from word `from` on: a growing page uploads only its new tail. + pub(crate) fn words(&self, from: usize) -> Vec { + let per = self.per as usize; + self.read(|c| { + let drawn = |e: usize| if per == 1 { c[e] } else { f64::midpoint(c[per * e], c[per * e + 1]) }; + (from / 2..c.len() / per).flat_map(|e| split(drawn(e))).collect() + }) + } +} + +fn split(x: f64) -> [u32; 2] { + let hi = x as f32; + [hi.to_bits(), ((x - f64::from(hi)) as f32).to_bits()] +} + +/// The page of `log` holding entry `index`, where one does. +fn holding(log: &Log>, index: u64) -> Option> { + log.read(|pages| { + let i = pages.partition_point(|p| p.first <= index).checked_sub(1)?; + (index < pages[i].end()).then(|| pages[i].clone()) + }) +} + +/// The pages of `log` holding any of `entries`, in order, each with those it holds. A page that stores +/// entries past the next page's first, where a version forked, holds them no longer. +fn held(log: &Log>, entries: Range) -> Vec<(Page, Range)> { + if entries.is_empty() { + return Vec::new(); + } + log.read(|pages| { + let from = pages.partition_point(|p| p.first <= entries.start).saturating_sub(1); + let mut out = Vec::new(); + for (i, page) in pages.iter().enumerate().skip(from) { + if page.first >= entries.end { + break; + } + let end = pages.get(i + 1).map_or(page.end(), |next| next.first.min(page.end())); + let range = page.first.max(entries.start)..end.min(entries.end); + if !range.is_empty() { + out.push((page.clone(), range)); + } + } + out + }) +} + +/// The first of `entries` a page of `log` holds. +fn first_held(log: &Log>, entries: Range) -> Option { + log.read(|pages| { + let from = pages.partition_point(|p| p.first <= entries.start).saturating_sub(1); + for (i, page) in pages.iter().enumerate().skip(from) { + let start = page.first.max(entries.start); + if start >= entries.end { + return None; + } + let end = pages.get(i + 1).map_or(page.end(), |next| next.first.min(page.end())); + if start < end { + return Some(start); + } + } + None + }) +} + +/// Puts `page` in its place in `log`, among pages holding none of its entries. +fn place(log: &mut Log>, page: Page) { + let (at, tip) = log.read(|pages| { + let at = pages.partition_point(|p| p.first < page.first); + (at, at == pages.len()) + }); + if tip { log.push(page) } else { log.edit(|pages| pages.insert(at, page)) } +} + +/// Makes the last page of `log` hold no entry from `end` on, as a version reading entries before `end` +/// sees it, before the version writes past `end`. +fn cap(log: &mut Log>, end: u64) { + if log.last().is_some_and(|page| page.end() > end) { + log.edit(|pages| { + let last = pages.last_mut().expect("a last page"); + *last = last.capped(end.saturating_sub(last.first) as u32); + }); + } +} + +/// Takes the pages of `log` holding only entries of `entries` out of it. +fn take_out(log: &mut Log>, entries: &Range) { + let (from, to) = log.read(|pages| { + let from = pages.partition_point(|p| p.first < entries.start); + (from, from + pages[from..].iter().take_while(|p| p.end() <= entries.end).count()) + }); + if to > from { + log.edit(|pages| drop(pages.drain(from..to))); + } +} + +/// Forgets the pages of `log` whose entries all lie before entry `index`. +fn forget_before(log: &mut Log>, index: u64) { + let dropped = log.read(|pages| pages.partition_point(|p| p.end() <= index)); + let start = log.start; + log.forget(start + dropped); +} + +/// Writes entry `entry`, `items` of it, after the last of `log`: into its last page where that grows +/// and has room within `limit` items, else into a new page that grows. +fn grow(log: &mut Log>, entry: u64, items: &[T], limit: usize) { + if !log.last().is_some_and(|page| page.extend(entry, items, limit)) { + log.push(Page::new(entry, items.len(), items.to_vec(), true)); + } +} + +/// Writes `entries` of a level, `items` of `per` each, as pages placed in order, as many entries to a +/// page as `limit` items allow. +fn put(log: &mut Log>, entries: &Range, items: &[T], per: usize, limit: usize) { + let step = (limit / per.max(1)).max(1); + for (k, chunk) in items.chunks(step * per.max(1)).enumerate() { + let first = entries.start + (k * step) as u64; + place(log, Page::new(first, per, chunk.to_vec(), false)); + } +} + +/// The logs a write writes into: every level's coordinates, and each row block's logs. +struct Logs { + axes: Vec>, + blocks: Vec>>, +} + +/// A field's samples over the data's axis: frames, and levels of detail above them, with holes. +#[derive(Clone, Default)] +pub(crate) struct Samples { + /// Frames this version reads, numbered from the first ever written. + start: u64, + end: u64, + /// Frames before this one were forgotten: pages may still store some, which this version must not + /// read again. + forgotten: u64, + /// Per level from 0: its entries' coordinates; empty until anything is written. + axes: Arc<[Log]>, + /// Per row block: its frames, then each level's least and greatest values. + blocks: Arc<[Vec>]>, +} + +impl Samples { + /// No frames yet, the first to be appended numbered `first`: what samples read back from bytes or + /// gathered from others start from, so their frames keep their numbers. + pub(crate) fn from_frame(first: u64) -> Samples { + Samples { start: first, end: first, ..Samples::default() } + } + + /// The first frame this version reads. + pub(crate) fn start(&self) -> u64 { + self.start + } + + /// One past the last frame. + pub(crate) fn end(&self) -> u64 { + self.end + } + + /// Reads frames `frames`: what bytes say, after the runs they hold are put in. + pub(crate) fn reads(&mut self, frames: Range) { + (self.start, self.end) = (frames.start, frames.end); + } + + /// The same frames, none of them held: what a dataset written as time tiles starts from. + pub(crate) fn emptied(&self) -> Samples { + let mut empty = Samples::from_frame(self.start); + empty.reads(self.start..self.end); + empty + } + + /// The entries of `level` this version reads: those whose frames lie before its end, from the one + /// holding its first frame. + fn visible(&self, level: u32) -> Range { + let k = 3 * level; + self.start >> k..self.end >> k + } + + /// Copies of the logs to write into, with every level's and at least `blocks` row blocks'. + fn logs(&self, blocks: usize) -> Logs { + self.logs_at(blocks, LEVELS) + } + + /// Highest level stored; the binary format records it independently of the append policy. + pub(crate) fn levels(&self) -> u32 { + self.axes.iter().rposition(|log| log.read(|pages| !pages.is_empty())).unwrap_or(0) as u32 + } + + fn logs_at(&self, blocks: usize, level: u32) -> Logs { + let levels = (level as usize + 1).max(self.axes.len()); + let slots = 1 + 2 * levels.saturating_sub(1); + let mut axes = self.axes.to_vec(); + axes.resize_with(levels, Log::default); + let mut all = self.blocks.to_vec(); + all.resize_with(blocks.max(all.len()), Vec::new); + for block in &mut all { + block.resize_with(slots, Log::default); + } + Logs { axes, blocks: all } + } + + fn keep(&mut self, logs: Logs) { + self.axes = logs.axes.into(); + self.blocks = logs.blocks.into(); + } + + /// The log of row block `block` holding `level`'s values of `side`. + fn log(&self, block: usize, level: u32, side: usize) -> Option<&Log> { + self.blocks.get(block)?.get(slot(level, side)) + } + + /// The page of `level`'s coordinates holding entry `index`, where this version holds it. + fn axis_page(&self, level: u32, index: u64) -> Option { + if !self.visible(level).contains(&index) { + return None; + } + holding(self.axes.get(level as usize)?, index) + } + + /// Whether no entry is held, of any level. + pub(crate) fn is_empty(&self) -> bool { + self.axes.iter().enumerate().all(|(level, log)| first_held(log, self.visible(level as u32)).is_none()) + } + + /// Whether entry `index` of `level` is held. + pub(crate) fn held(&self, level: u32, index: u64) -> bool { + self.axis_page(level, index).is_some() + } + + /// Coordinate `which` of entry `index` of `level`: a frame's own, a bucket's first (0) or last (1). + pub(crate) fn coordinate(&self, level: u32, index: u64, which: u32) -> Option { + self.axis_page(level, index)?.coordinate(index, which) + } + + /// Where entry `index` of `level` draws: a frame at its coordinate, a bucket at its middle. + pub(crate) fn drawn_at(&self, level: u32, index: u64) -> Option { + self.axis_page(level, index)?.drawn(index) + } + + /// The coordinate of `frame`, where it is held. + pub(crate) fn at(&self, frame: u64) -> Option { + self.coordinate(0, frame, 0) + } + + /// The runs of entries held, level by level, each as long as held entries follow one another. + pub(crate) fn runs(&self) -> Vec { + let mut runs = Vec::new(); + for (level, log) in self.axes.iter().enumerate() { + let level = level as u32; + for (_, entries) in held(log, self.visible(level)) { + join(&mut runs, Run { level, entries }); + } + } + runs + } + + /// The runs bytes hold: every run held but the buckets whose eight entries a level below are all + /// held, since those follow from them. + pub(crate) fn stored_runs(&self) -> Vec { + let runs = self.runs(); + let mut stored = Vec::new(); + for run in &runs { + if run.level == 0 { + stored.push(run.clone()); + continue; + } + // Buckets that follow from the runs below, in order: what this run leaves out. + let derived = runs + .iter() + .filter(|r| r.level + 1 == run.level) + .map(|r| r.entries.start.div_ceil(8)..r.entries.end / 8) + .filter(|d| !d.is_empty()); + let mut at = run.entries.start; + for d in derived { + let (from, to) = (d.start.max(at), d.end.min(run.entries.end)); + if from >= to { + continue; + } + if at < from { + stored.push(Run { level: run.level, entries: at..from }); + } + at = to; + } + if at < run.entries.end { + stored.push(Run { level: run.level, entries: at..run.entries.end }); + } + } + stored + } + + /// The first and last coordinates of what this version holds, at any level. + pub(crate) fn span(&self) -> Option<[f64; 2]> { + let mut span: Option<[f64; 2]> = None; + for (level, log) in self.axes.iter().enumerate() { + let pages = held(log, self.visible(level as u32)); + let (Some((first, a)), Some((last, b))) = (pages.first(), pages.last()) else { continue }; + let (Some(lo), Some(hi)) = (first.coordinate(a.start, 0), last.coordinate(b.end - 1, 1)) else { continue }; + span = Some(span.map_or([lo, hi], |s| [s[0].min(lo), s[1].max(hi)])); + } + span + } + + /// The coordinate of the last frame, or of the last entry of any level. + fn last_coordinate(&self) -> Option { + self.end.checked_sub(1).and_then(|f| self.at(f)).or_else(|| self.span().map(|s| s[1])) + } + + /// Appends frames: `values` holds `at.len()` frames of `rows` values each, frame-major. + pub(crate) fn append(&mut self, at: &[f64], values: &Values, rows: usize) -> Result<()> { + if at.len().checked_mul(rows) != Some(values.len()) { + return Err(Error::invalid(format!("{} values for {} frames of {rows} rows", values.len(), at.len()))); + } + self.end.checked_add(at.len() as u64).ok_or_else(|| Error::invalid("too many frames"))?; + let mut last = self.last_coordinate(); + for &t in at { + if !t.is_finite() { + return Err(Error::invalid("a frame's coordinate must be finite")); + } + if last.is_some_and(|last| t < last) { + return Err(Error::invalid("frame coordinates must not decrease")); + } + last = Some(t); + } + let blocks = rows.div_ceil(PAGE_ROWS); + let mut logs = self.logs(blocks); + let mut frame_values = vec![0.0_f32; rows]; + for (f, &t) in at.iter().enumerate() { + let frame = self.end; + for (row, value) in frame_values.iter_mut().enumerate() { + let i = f * rows + row; + *value = if values.is_valid(i) { values.number(i) as f32 } else { f32::NAN }; + } + for (b, block) in logs.blocks.iter_mut().enumerate().take(blocks) { + let slice = &frame_values[b * PAGE_ROWS..rows.min((b + 1) * PAGE_ROWS)]; + grow(&mut block[0], frame, slice, FRAME_PAGE_WORDS); + } + grow(&mut logs.axes[0], frame, &[t], FRAME_PAGE_WORDS / 2); + self.end += 1; + seal(&mut logs, frame); + } + self.keep(logs); + Ok(()) + } + + /// Appends frames of some rows: `values` holds `at.len()` frames of a value per row of `rows`, + /// frame-major. The rest of the `total` rows hold their last frame's values, missing before any. + pub(crate) fn append_rows(&mut self, at: &[f64], values: &Values, rows: &[usize], total: usize) -> Result<()> { + let given = rows.len(); + if at.len().checked_mul(given) != Some(values.len()) { + return Err(Error::invalid(format!("{} values for {} frames of {given} rows", values.len(), at.len()))); + } + let mut frame = vec![f32::NAN; total]; + if self.end > self.start { + self.read_frame(self.end - 1, &mut frame); + } + let mut dense = + Vec::with_capacity(at.len().checked_mul(total).ok_or_else(|| Error::invalid("too many values"))?); + for f in 0..at.len() { + for (k, &row) in rows.iter().enumerate() { + let i = f * given + k; + frame[row] = if values.is_valid(i) { values.number(i) as f32 } else { f32::NAN }; + } + dense.extend_from_slice(&frame); + } + self.append(at, &Values::from(dense), total) + } + + /// Puts `run`, held nowhere yet, in: its `coordinates` ([`coordinates`] an entry), and its values + /// for `rows` rows, entry-major, at level 0 one a row, above each row's least then, after every + /// entry's, each row's greatest. What it spans past this version's frames widens them. + pub(crate) fn insert(&mut self, run: &Run, coordinates: &[f64], values: &[f32], rows: usize) -> Result<()> { + let level = run.level; + if level > MAX_LEVEL { + return Err(Error::invalid(format!("no level {level}: levels run to {MAX_LEVEL}"))); + } + let (per, sides) = (self::coordinates(level), sides(level)); + if run.entries.is_empty() || run.sizes(rows) != Some((coordinates.len(), values.len())) { + return Err(Error::invalid(format!("a run of {} entries of level {level} for {rows} rows", run.len()))); + } + if coordinates.iter().any(|c| !c.is_finite()) || coordinates.windows(2).any(|w| w[1] < w[0]) { + return Err(Error::invalid("a run's coordinates must be finite and must not decrease")); + } + let frames = run.frames(); + if run.entries.end.checked_mul(bucket_frames(level)).is_none() { + return Err(Error::invalid("a run past the last frame a field numbers")); + } + if frames.start < self.forgotten { + return Err(Error::invalid("a run before frames the field forgot")); + } + let visible = self.visible(level); + let within = run.entries.start.max(visible.start)..run.entries.end.min(visible.end); + if self.axes.get(level as usize).is_some_and(|log| first_held(log, within).is_some()) { + return Err(Error::invalid(format!("entries {:?} of level {level} are held already", run.entries))); + } + let blocks = rows.div_ceil(PAGE_ROWS); + let mut logs = self.logs_at(blocks, level); + // What a newer version grew past this one's frames stays the newer version's. + cap(&mut logs.axes[level as usize], visible.end); + put(&mut logs.axes[level as usize], &run.entries, coordinates, per, FRAME_PAGE_WORDS / 2); + let n = run.len(); + for (b, block) in logs.blocks.iter_mut().enumerate().take(blocks) { + let width = rows.min((b + 1) * PAGE_ROWS) - b * PAGE_ROWS; + for side in 0..sides { + let side_values = &values[side * n * rows..(side + 1) * n * rows]; + let mut page = Vec::with_capacity(n * width); + for entry in side_values.chunks(rows) { + page.extend_from_slice(&entry[b * PAGE_ROWS..b * PAGE_ROWS + width]); + } + let log = &mut block[slot(level, side)]; + cap(log, visible.end); + put(log, &run.entries, &page, width, FRAME_PAGE_WORDS); + } + } + self.keep(logs); + if self.start == self.end { + (self.start, self.end) = (frames.start, frames.end); + } else { + self.start = self.start.min(frames.start); + self.end = self.end.max(frames.end); + } + Ok(()) + } + + /// Takes the pages holding only entries of `run` out: a span let go of. + pub(crate) fn remove(&mut self, run: &Run) { + let mut logs = self.logs(0); + take_out(&mut logs.axes[run.level as usize], &run.entries); + for block in &mut logs.blocks { + for side in 0..sides(run.level) { + take_out(&mut block[slot(run.level, side)], &run.entries); + } + } + self.keep(logs); + } + + /// Writes each bucket of `level` not held whose eight entries a level below are all held: what + /// bytes leave out, as they follow from those. + pub(crate) fn derive(&mut self, level: u32) { + let below: Vec = self.runs().into_iter().filter(|r| r.level + 1 == level).collect(); + for run in below { + let buckets = run.entries.start.div_ceil(8)..run.entries.end / 8; + for missing in self.missing(level, buckets) { + let (coordinates, values, rows) = self.bucket_values(level, &missing); + let run = Run { level, entries: missing }; + self.insert(&run, &coordinates, &values, rows).expect("buckets held nowhere"); + } + } + } + + /// The parts of `entries` of `level` not held. + fn missing(&self, level: u32, entries: Range) -> Vec> { + let visible = self.visible(level); + let held_runs = self + .axes + .get(level as usize) + .map_or_else(Vec::new, |log| held(log, entries.start.max(visible.start)..entries.end.min(visible.end))); + let mut out = Vec::new(); + let mut at = entries.start; + for (_, range) in held_runs { + if at < range.start { + out.push(at..range.start); + } + at = range.end; + } + if at < entries.end { + out.push(at..entries.end); + } + out + } + + /// Buckets `buckets` of `level`, each from its eight entries a level below: their coordinates, and + /// their values as [`insert`](Samples::insert) takes them, with how many rows. + fn bucket_values(&self, level: u32, buckets: &Range) -> (Vec, Vec, usize) { + let children = buckets.start * 8..buckets.end * 8; + let mut coordinates = Vec::with_capacity(2 * (buckets.end - buckets.start) as usize); + for b in buckets.clone() { + coordinates.push(self.coordinate(level - 1, 8 * b, 0).unwrap_or(f64::NAN)); + coordinates.push(self.coordinate(level - 1, 8 * b + 7, 1).unwrap_or(f64::NAN)); + } + let rows = self.rows(); + let n = (buckets.end - buckets.start) as usize; + let mut values = vec![f32::NAN; 2 * n * rows]; + for block in 0..self.blocks.len() { + for side in 0..2 { + let from = if level == 1 { 0 } else { side }; + let Some(log) = self.log(block, level - 1, from) else { continue }; + for (page, range) in held(log, children.clone()) { + page.read(|stored| { + for e in range { + let bucket = (e / 8 - buckets.start) as usize; + let base = ((e - page.first) * u64::from(page.per)) as usize; + let out = side * n * rows + bucket * rows + block * PAGE_ROWS; + for (r, &v) in stored[base..base + page.per as usize].iter().enumerate() { + let o = &mut values[out + r]; + *o = if side == 0 { o.min(v) } else { o.max(v) }; + } + } + }); + } + } + } + (coordinates, values, rows) + } + + /// Rows the row blocks' pages hold values of. + fn rows(&self) -> usize { + let block_rows = |b: usize| self.blocks[b].iter().filter_map(|log| log.last().map(|p| p.per as usize)).max(); + (0..self.blocks.len()) + .rev() + .find_map(|b| block_rows(b).filter(|&r| r > 0).map(|r| b * PAGE_ROWS + r)) + .unwrap_or(0) + } + + /// `run`'s coordinates, and its values for rows `rows`, in that order, as + /// [`insert`](Samples::insert) takes them. + pub(crate) fn read(&self, run: &Run, rows: &[usize]) -> (Vec, Vec) { + let per = coordinates(run.level); + let n = run.len(); + let mut at = Vec::with_capacity(n * per); + for (page, range) in self.axis_pages(run.level, run.entries.clone()) { + let (from, to) = ((range.start - page.first) as usize * per, (range.end - page.first) as usize * per); + page.read(|c| at.extend_from_slice(&c[from..to])); + } + at.resize(n * per, f64::NAN); + let sides = sides(run.level); + let mut values = vec![f32::NAN; sides * n * rows.len()]; + // Rows by block, so each page is read once for all of a block's rows. + let mut by_block: Vec<(usize, usize)> = + rows.iter().enumerate().map(|(i, &row)| (row >> PAGE_BITS, i)).collect(); + by_block.sort_unstable(); + for group in by_block.chunk_by(|a, b| a.0 == b.0) { + for side in 0..sides { + for (page, range) in self.pages(group[0].0, run.level, side, run.entries.clone()) { + page.read(|stored| { + for e in range { + let base = ((e - page.first) * u64::from(page.per)) as usize; + let out = side * n * rows.len() + (e - run.entries.start) as usize * rows.len(); + for &(_, i) in group { + let local = rows[i] & PAGE_MASK; + if local < page.per as usize { + values[out + i] = stored[base + local]; + } + } + } + }); + } + } + } + (at, values) + } + + /// Forgets frames before coordinate `before`; pages that hold only forgotten entries drop. True + /// when anything was forgotten. + pub(crate) fn forget(&mut self, before: f64) -> bool { + let first = self.bound(before, false).min(self.end); + if first <= self.start { + return false; + } + (self.start, self.forgotten) = (first, first); + let mut logs = self.logs(0); + for (level, log) in logs.axes.iter_mut().enumerate() { + forget_before(log, first >> (3 * level)); + } + for block in &mut logs.blocks { + for (s, log) in block.iter_mut().enumerate() { + forget_before(log, first >> (3 * s.div_ceil(2))); + } + } + self.keep(logs); + true + } + + /// How many entries of `level` lie before `at` (with `past`, at it too), each by its coordinate + /// `which`: by its last (1), those wholly before; by its first (0), those begun before. Where the + /// entries held of the level settle it; else where the hole holding `at` starts. + fn locate(&self, level: u32, at: f64, past: bool, which: u32) -> std::result::Result { + let before = |t: f64| if past { t <= at } else { t < at }; + let visible = self.visible(level); + let Some(log) = self.axes.get(level as usize) else { return Err(visible.start) }; + let pages = held(log, visible.clone()); + // The first page whose last entry does not lie before `at`. + let i = pages.partition_point(|(p, r)| p.coordinate(r.end - 1, which).is_some_and(before)); + let gap = if i == 0 { visible.start } else { pages[i - 1].1.end }; + let Some((page, range)) = pages.get(i) else { + return if gap == visible.end { Ok(gap) } else { Err(gap) }; + }; + let per = page.per as usize; + let edge = (which as usize).min(per - 1); + let n = page.read(|c| { + let entries = &c[(range.start - page.first) as usize * per..(range.end - page.first) as usize * per]; + let (mut lo, mut hi) = (0, entries.len() / per); + while lo < hi { + let mid = lo + (hi - lo) / 2; + if before(entries[mid * per + edge]) { + lo = mid + 1; + } else { + hi = mid; + } + } + lo + }) as u64; + if n > 0 || range.start == gap { Ok(range.start + n) } else { Err(gap) } + } + + /// The frames before `at`, or with `past` at or before it: frames where held, else the whole + /// buckets before it of the finest level held there. Where no level settles it, where the hole + /// holding it starts. + pub(crate) fn bound(&self, at: f64, past: bool) -> u64 { + let mut hole = None; + for level in 0..self.axes.len() as u32 { + match self.locate(level, at, past, 1) { + Ok(n) => return n.saturating_mul(bucket_frames(level)).clamp(self.start, self.end), + Err(gap) if first_held(&self.axes[level as usize], self.visible(level)).is_some() => { + hole = Some(gap.saturating_mul(bucket_frames(level))); + } + Err(_) => {} + } + } + hole.unwrap_or(self.start).clamp(self.start, self.end) + } + + /// The frames at or before `at`, as finely as the finest level settling it tells: where frames + /// are held, exactly; else the whole buckets at or before it and as far into the next as `at` lies + /// between its first and last frame's coordinates. + fn position(&self, at: f64) -> Option { + (0..self.axes.len() as u32).find_map(|level| { + let n = self.locate(level, at, true, 1).ok()?; + let into = match (self.coordinate(level, n, 0), self.coordinate(level, n, 1)) { + (Some(first), Some(last)) if level > 0 && first <= at && first < last => (at - first) / (last - first), + _ => 0.0, + }; + Some((n as f64 + into) * bucket_frames(level) as f64) + }) + } + + /// The frames a trace across `across` draws: from the last frame at or before its start through + /// the first after its end, as finely as what is held tells. + pub(crate) fn across(&self, [x0, x1]: [f64; 2]) -> Range { + let (Some(a), Some(b)) = (self.position(x0), self.position(x1)) else { return self.start..self.end }; + let first = (a.floor() as u64).saturating_sub(1).max(self.start); + let last = (b.ceil() as u64).saturating_add(1).min(self.end); + first..last.max(first) + } + + /// The first frame held from `frame` on, of any level: where a hole ends. + fn next_held(&self, frame: u64) -> Option { + let mut next: Option = None; + for (level, log) in self.axes.iter().enumerate() { + let (span, visible) = (bucket_frames(level as u32), self.visible(level as u32)); + if let Some(entry) = first_held(log, (frame / span).max(visible.start)..visible.end) { + let at = (entry * span).max(frame); + next = Some(next.map_or(at, |n| n.min(at))); + } + } + next + } + + /// What covers frames `frames`, left to right: `(level, index)`, the coarsest held bucket that fits + /// at each step, or a held frame as level 0; where neither does, the finest held bucket holding the + /// frame stands in, reaching past the frames. Frames nothing holds are skipped. + pub(crate) fn pieces(&self, frames: Range) -> Vec<(u32, u64)> { + let mut pieces = Vec::new(); + let (mut f, end) = (frames.start.max(self.start), frames.end.min(self.end)); + while f < end { + let fits = (1..=self.levels()).rev().find(|&k| { + let span = bucket_frames(k); + f.is_multiple_of(span) && f.saturating_add(span) <= end && self.held(k, f / span) + }); + if let Some(k) = fits { + pieces.push((k, f / bucket_frames(k))); + f += bucket_frames(k); + } else if self.held(0, f) { + pieces.push((0, f)); + f += 1; + } else if let Some(k) = (1..=self.levels()).find(|&k| self.held(k, f / bucket_frames(k))) { + let bucket = f / bucket_frames(k); + pieces.push((k, bucket)); + f = (bucket + 1) * bucket_frames(k); + } else { + let Some(next) = self.next_held(f + 1) else { break }; + f = next; + } + } + pieces + } + + /// What draws frames `frames` at `level`, left to right: runs of that level's entries where held; + /// else the nearest coarser level's entry holding them, standing in; else finer levels' entries. + /// Frames nothing holds draw nothing. + pub(crate) fn cover(&self, frames: Range, level: u32) -> Vec { + let mut runs = Vec::new(); + let frames = frames.start.max(self.start)..frames.end.min(self.end); + self.cover_into(frames, level.min(self.levels()), &mut runs); + runs + } + + fn cover_into(&self, frames: Range, level: u32, runs: &mut Vec) { + let span = bucket_frames(level); + let (mut e, last) = (frames.start / span, frames.end.div_ceil(span)); + let visible = self.visible(level); + while e < last { + let here = self.axes.get(level as usize).and_then(|log| { + held(log, e.max(visible.start)..last.min(visible.end)).into_iter().next().map(|(_, r)| r) + }); + if let Some(range) = here.filter(|r| r.start == e) { + e = range.end; + join(runs, Run { level, entries: range }); + continue; + } + let frame = (e * span).max(frames.start); + if let Some(k) = (level + 1..=self.levels()).find(|&k| self.held(k, frame / bucket_frames(k))) { + let bucket = frame / bucket_frames(k); + join(runs, Run { level: k, entries: bucket..bucket + 1 }); + e = (bucket + 1).saturating_mul(bucket_frames(k)).div_ceil(span); + continue; + } + let entry_end = (e + 1).saturating_mul(span).min(frames.end); + match self.next_held(frame) { + Some(next) if next < entry_end && level > 0 => { + self.cover_into(next..entry_end, level - 1, runs); + e += 1; + } + Some(next) => e = (next / span).max(e + 1), + None => break, + } + } + } + + /// Folds piece `(level, index)` of row block `block` into `extent`, a least and a greatest value per + /// row of the block, NaN until one is read. + pub(crate) fn fold(&self, block: usize, (level, index): (u32, u64), extent: &mut [[f32; 2]]) { + if !self.held(level, index) { + return; + } + for side in 0..sides(level) { + let Some(page) = self.log(block, level, side).and_then(|log| holding(log, index)) else { continue }; + let base = ((index - page.first) * u64::from(page.per)) as usize; + page.read(|values| { + for (e, &v) in extent.iter_mut().zip(&values[base..base + page.per as usize]) { + if level == 0 || side == 0 { + e[0] = e[0].min(v); + } + if level == 0 || side == 1 { + e[1] = e[1].max(v); + } + } + }); + } + } + + /// The last frame held at or before `at`. + pub(crate) fn frame_at(&self, at: f64) -> Option { + let frame = self.locate(0, at, true, 0).ok()?.checked_sub(1)?; + self.held(0, frame).then_some(frame) + } + + /// How far `at` lies from `frame` toward the next frame, in `0..=1`. + pub(crate) fn t(&self, frame: u64, at: f64) -> f32 { + match (self.at(frame), self.at(frame + 1)) { + (Some(a), Some(b)) if b > a => ((at - a) / (b - a)).clamp(0.0, 1.0) as f32, + _ => 0.0, + } + } + + /// The page holding `frame` of `block` and the word where the frame starts in it. + pub(crate) fn cursor(&self, block: usize, frame: u64) -> Option<(FramePage, u32)> { + if !self.held(0, frame) { + return None; + } + let page = holding(self.log(block, 0, 0)?, frame)?; + let base = (frame - page.first) * u64::from(page.per); + Some((page, base as u32)) + } + + /// The pages of `block` holding any of `level`'s entries `entries`, each with those it holds: + /// frames, or a bucket's least (`side` 0) or greatest (1) values. + pub(crate) fn pages( + &self, + block: usize, + level: u32, + side: usize, + entries: Range, + ) -> Vec<(FramePage, Range)> { + let visible = self.visible(level); + let entries = entries.start.max(visible.start)..entries.end.min(visible.end); + self.log(block, level, side).map_or_else(Vec::new, |log| held(log, entries)) + } + + /// The coordinate pages of `level` holding any of entries `entries`, each with those it holds. + pub(crate) fn axis_pages(&self, level: u32, entries: Range) -> Vec<(AxisPage, Range)> { + let visible = self.visible(level); + let entries = entries.start.max(visible.start)..entries.end.min(visible.end); + self.axes.get(level as usize).map_or_else(Vec::new, |log| held(log, entries)) + } + + /// The value of `row` in `frame`, or `None` when missing. + pub(crate) fn value(&self, row: usize, frame: u64) -> Option { + self.entry(row, 0, 0, frame) + } + + /// The value of `row` at entry `index` of `level`: a frame's, or a bucket's least (`side` 0) or + /// greatest (1); `None` when missing. + pub(crate) fn entry(&self, row: usize, level: u32, side: usize, index: u64) -> Option { + if !self.held(level, index) { + return None; + } + let page = holding(self.log(row >> PAGE_BITS, level, side)?, index)?; + let local = (row & PAGE_MASK) as u32; + let value = (local < page.per) + .then(|| page.read(|v| v[((index - page.first) * u64::from(page.per) + u64::from(local)) as usize]))?; + (!value.is_nan()).then_some(f64::from(value)) + } + + /// `frame`'s values for the first `rows` rows into `out`; rows the frame lacks are NaN. + fn read_frame(&self, frame: u64, out: &mut [f32]) { + out.fill(f32::NAN); + let rows = out.len(); + for block in 0..rows.div_ceil(PAGE_ROWS) { + let Some((page, base)) = self.cursor(block, frame) else { continue }; + let start = block * PAGE_ROWS; + let n = (page.per as usize).min(rows - start); + page.read(|v| out[start..start + n].copy_from_slice(&v[base as usize..base as usize + n])); + } + } + + /// The samples of rows `rows`, in that order, at every level. + pub(crate) fn gather(&self, rows: &[usize]) -> Samples { + self.gather_runs(rows, &self.runs(), self.start..self.end) + } + + /// The samples of rows `rows`, in that order, over the frames of `frames` held: what a table drawn + /// in part shows of them about one coordinate. + pub(crate) fn gather_frames(&self, rows: &[usize], frames: Range) -> Samples { + let start = frames.start.max(self.start); + let frames = start..frames.end.min(self.end).max(start); + let runs: Vec = self + .runs() + .into_iter() + .filter(|r| r.level == 0) + .map(|r| Run { level: 0, entries: r.entries.start.max(frames.start)..r.entries.end.min(frames.end) }) + .filter(|r| !r.entries.is_empty()) + .collect(); + self.gather_runs(rows, &runs, frames) + } + + /// The samples of rows `rows` over `runs`, reading frames `frames`. + fn gather_runs(&self, rows: &[usize], runs: &[Run], frames: Range) -> Samples { + let mut gathered = Samples::from_frame(frames.start); + for run in runs { + let (at, values) = self.read(run, rows); + gathered.insert(run, &at, &values, rows.len()).expect("runs held apart"); + } + gathered.reads(frames); + gathered + } +} + +/// After `frame` is appended to `logs`, writes each bucket it completes whose eight entries a level +/// below are all held, level by level: its first and last frame's coordinates, and per row block the +/// least of its entries' least values and the greatest of their greatest. +fn seal(logs: &mut Logs, frame: u64) { + let next = frame + 1; + for level in 1..=LEVELS { + let span = bucket_frames(level); + if !next.is_multiple_of(span) { + break; + } + let bucket = next / span - 1; + let children = bucket * 8..bucket * 8 + 8; + let below = held(&logs.axes[level as usize - 1], children.clone()); + if below.iter().map(|(_, r)| (r.end - r.start) as usize).sum::() != 8 { + break; + } + let first = below[0].0.coordinate(children.start, 0); + let last = below[below.len() - 1].0.coordinate(children.end - 1, 1); + let (Some(first), Some(last)) = (first, last) else { break }; + grow(&mut logs.axes[level as usize], bucket, &[first, last], FRAME_PAGE_WORDS / 2); + for block in &mut logs.blocks { + for side in 0..2 { + let from = &block[slot(level - 1, if level == 1 { 0 } else { side })]; + let parts = held(from, children.clone()); + let Some(rows) = parts.iter().map(|(p, _)| p.per as usize).max() else { continue }; + let mut sealed = vec![f32::NAN; rows]; + for (page, range) in &parts { + page.read(|values| { + for e in range.clone() { + let base = ((e - page.first) * u64::from(page.per)) as usize; + for (out, &v) in sealed.iter_mut().zip(&values[base..base + page.per as usize]) { + *out = if side == 0 { out.min(v) } else { out.max(v) }; + } + } + }); + } + grow(&mut block[slot(level, side)], bucket, &sealed, FRAME_PAGE_WORDS); + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn levels_keep_each_buckets_least_and_greatest() { + let mut samples = Samples::default(); + for t in 0..130 { + let v = if t == 70 { -5.0 } else { f64::from(t) }; + samples.append(&[f64::from(t)], &Values::from(vec![v, 2.0 * v]), 2).expect("frame"); + } + assert!(samples.held(1, 15) && !samples.held(1, 16), "130 frames seal 16 buckets of 8"); + assert!(samples.held(2, 1) && !samples.held(2, 2), "and 2 of 64"); + // Bucket 8 spans frames 64..72, where frame 70 dips to -5. + assert_eq!(samples.entry(0, 1, 0, 8), Some(-5.0)); + assert_eq!(samples.entry(1, 1, 0, 8), Some(-10.0)); + assert_eq!(samples.entry(1, 1, 1, 8), Some(142.0)); + // Bucket 1 of level 2 spans frames 64..128. + assert_eq!(samples.entry(1, 2, 0, 1), Some(-10.0)); + assert_eq!(samples.entry(0, 2, 1, 1), Some(127.0)); + assert_eq!(samples.coordinate(2, 1, 0), Some(64.0), "a bucket holds its first frame's coordinate"); + assert_eq!(samples.coordinate(2, 1, 1), Some(127.0), "and its last's"); + assert_eq!(samples.drawn_at(2, 1), Some(95.5), "and draws at their middle"); + } + + #[test] + fn appends_read_back_by_coordinate() { + let mut samples = Samples::default(); + samples.append(&[0.0, 1.0], &Values::from(vec![1.0_f64, 2.0, 3.0, 4.0]), 2).expect("frames"); + assert_eq!(samples.end(), 2); + assert_eq!(samples.frame_at(0.5), Some(0)); + assert_eq!(samples.value(1, 1), Some(4.0)); + assert_eq!(samples.frame_at(-1.0), None); + assert_eq!(samples.bound(0.5, false), 1); + assert!(samples.append(&[0.5], &Values::from(vec![0.0_f64, 0.0]), 2).is_err()); + } + + #[test] + fn newest_version_grows_in_place_and_older_versions_fork() { + let mut newest = Samples::default(); + newest.append(&[0.0], &Values::from(vec![1.0_f64]), 1).expect("frame"); + let older = newest.clone(); + newest.append(&[1.0], &Values::from(vec![2.0_f64]), 1).expect("frame"); + let page = |s: &Samples| s.cursor(0, 0).expect("a page").0.id; + assert_eq!(page(&newest), page(&older)); + let mut forked = older.clone(); + forked.append(&[2.0], &Values::from(vec![3.0_f64]), 1).expect("frame"); + assert_eq!(forked.value(0, 1), Some(3.0)); + assert_eq!(newest.value(0, 1), Some(2.0)); + assert_eq!(older.end(), 1); + assert_eq!(older.value(0, 1), None, "a version reads only its own frames"); + } + + #[test] + fn an_older_version_writing_past_its_end_keeps_the_newer_ones_frames_out() { + let mut newest = Samples::default(); + newest.append(&[0.0, 1.0], &Values::from(vec![1.0_f64, 2.0]), 1).expect("frames"); + let mut older = newest.clone(); + newest.append(&[2.0, 3.0], &Values::from(vec![3.0_f64, 4.0]), 1).expect("frames"); + // The older version holds frames 0 and 1; frames 4 and 5 widen it past a hole at 2 and 3. + older.insert(&Run { level: 0, entries: 4..6 }, &[4.0, 5.0], &[5.0, 6.0], 1).expect("a run"); + assert_eq!(older.value(0, 2), None, "the newer version's frame 2 is not the older one's"); + assert_eq!(older.value(0, 4), Some(5.0)); + assert_eq!(newest.value(0, 2), Some(3.0)); + } + + #[test] + fn forgetting_keeps_frame_numbers_and_older_versions() { + let rows = 4096; + let mut samples = Samples::default(); + for t in 0..100 { + samples.append(&[f64::from(t)], &Values::from(vec![t as f32; rows]), rows).expect("frame"); + } + let older = samples.clone(); + let pages = |s: &Samples| s.blocks[0][0].read(<[FramePage]>::len); + let before = pages(&samples); + assert!(samples.forget(50.0)); + assert!(!samples.forget(50.0), "nothing more to forget"); + assert_eq!((samples.start(), samples.end()), (50, 100)); + assert_eq!(samples.value(7, 60), Some(60.0), "frames keep their numbers"); + assert_eq!(samples.at(49), None); + assert!(pages(&samples) < before, "whole pages before the first kept frame drop"); + assert_eq!(older.value(7, 10), Some(10.0), "an older version still reads them"); + samples.append(&[100.0], &Values::from(vec![1.0_f32; rows]), rows).expect("frame"); + assert_eq!(samples.end(), 101); + let run = Run { level: 0, entries: 10..11 }; + assert!(samples.insert(&run, &[10.0], &vec![0.0; rows], rows).is_err(), "frames forgotten stay so"); + } + + #[test] + fn gather_keeps_each_rows_history() { + let mut samples = Samples::default(); + samples.append(&[0.0, 1.0], &Values::from(vec![1.0_f64, 2.0, 3.0, 4.0]), 2).expect("frames"); + let gathered = samples.gather(&[1]); + assert_eq!(gathered.value(0, 0), Some(2.0)); + assert_eq!(gathered.value(0, 1), Some(4.0)); + let one = samples.gather_frames(&[0], 1..2); + assert_eq!((one.start(), one.end(), one.value(0, 1), one.value(0, 0)), (1, 2, Some(3.0), None)); + } + + /// Level 1 buckets 0..4 (frames 0..32) and the frames of bucket 1, of two rows. + fn holed() -> (Samples, Run, Run) { + let mut samples = Samples::default(); + let buckets = Run { level: 1, entries: 0..4 }; + let at: Vec = (0..4).flat_map(|b| [f64::from(b * 8), f64::from(b * 8 + 7)]).collect(); + let least: Vec = (0..4).flat_map(|b| [b as f32, -(b as f32)]).collect(); + let greatest: Vec = (0..4).flat_map(|b| [b as f32 + 10.0, 10.0 - b as f32]).collect(); + samples.insert(&buckets, &at, &[least, greatest].concat(), 2).expect("buckets"); + let frames = Run { level: 0, entries: 8..16 }; + let coordinates: Vec = (8..16).map(f64::from).collect(); + let values: Vec = (8..16).flat_map(|f| [f as f32, -(f as f32)]).collect(); + samples.insert(&frames, &coordinates, &values, 2).expect("frames"); + (samples, buckets, frames) + } + + #[test] + fn runs_fill_any_span_and_cover_draws_the_finest_held() { + let (mut samples, buckets, frames) = holed(); + assert_eq!((samples.start(), samples.end()), (0, 32)); + let (at, values) = samples.read(&frames, &[0, 1]); + assert!(samples.insert(&frames, &at, &values, 2).is_err(), "held already"); + assert_eq!( + samples.cover(0..32, 0), + vec![Run { level: 1, entries: 0..1 }, Run { level: 0, entries: 8..16 }, Run { level: 1, entries: 2..4 },], + "frames where held, else the buckets standing in" + ); + assert_eq!(samples.cover(0..32, 1), vec![buckets.clone()]); + assert_eq!(samples.entry(1, 1, 1, 2), Some(8.0)); + assert_eq!(samples.value(0, 9), Some(9.0)); + assert_eq!(samples.frame_at(12.5), Some(12)); + assert_eq!(samples.frame_at(20.0), None, "frame 20 is not held"); + assert_eq!(samples.bound(20.0, false), 16, "past the frames, whole buckets count"); + assert_eq!(samples.pieces(0..32), vec![(1, 0), (1, 1), (1, 2), (1, 3)]); + let read = samples.read(&buckets, &[0, 1]); + let mut copy = Samples::default(); + copy.insert(&buckets, &read.0, &read.1, 2).expect("read back"); + assert_eq!(copy.entry(0, 1, 0, 3), Some(3.0)); + assert_eq!(samples.runs(), vec![frames.clone(), buckets.clone()]); + let stored = vec![frames.clone(), Run { level: 1, entries: 0..1 }, Run { level: 1, entries: 2..4 }]; + assert_eq!(samples.stored_runs(), stored); + samples.remove(&frames); + assert!(!samples.held(0, 9), "a span let go of"); + assert_eq!(samples.cover(0..32, 0), vec![buckets]); + } + + #[test] + fn derived_buckets_follow_from_the_entries_below() { + let mut samples = Samples::default(); + for t in 0..64 { + samples.append(&[f64::from(t)], &Values::from(vec![f64::from(t % 10)]), 1).expect("frame"); + } + let stored = samples.stored_runs(); + assert_eq!(stored, vec![Run { level: 0, entries: 0..64 }], "every bucket follows from the frames"); + let mut copy = Samples::from_frame(0); + let (at, values) = samples.read(&stored[0], &[0]); + copy.insert(&stored[0], &at, &values, 1).expect("frames"); + for level in 1..=LEVELS { + copy.derive(level); + } + assert_eq!(copy.runs(), samples.runs()); + for b in 0..8 { + assert_eq!(copy.entry(0, 1, 0, b), samples.entry(0, 1, 0, b)); + assert_eq!(copy.entry(0, 1, 1, b), samples.entry(0, 1, 1, b)); + assert_eq!(copy.coordinate(1, b, 1), samples.coordinate(1, b, 1)); + } + assert_eq!(copy.entry(0, 2, 1, 0), Some(9.0)); + } + + #[test] + fn appends_after_a_run_seal_only_whole_buckets() { + let mut samples = Samples::default(); + let run = Run { level: 0, entries: 4..8 }; + samples.insert(&run, &[4.0, 5.0, 6.0, 7.0], &[1.0, 2.0, 3.0, 4.0], 1).expect("run"); + let at: Vec = (8..16).map(f64::from).collect(); + samples.append(&at, &Values::from(vec![5.0_f64; 8]), 1).expect("frames"); + assert!(!samples.held(1, 0), "frames 0..4 are missing"); + assert!(samples.held(1, 1)); + assert_eq!(samples.cover(0..16, 1), vec![run, Run { level: 1, entries: 1..2 }]); + } +} diff --git a/crates/latkit/src/data/table.rs b/crates/latkit/src/data/table.rs new file mode 100644 index 00000000..6a67f000 --- /dev/null +++ b/crates/latkit/src/data/table.rs @@ -0,0 +1,425 @@ +use std::sync::{Arc, OnceLock}; + +use super::bits::Bits; +use super::column::{Column, Page}; +use super::ids::{Ids, Index, RowIds}; +use super::name::{Id, IdRef, Name, PageId, Version}; +use super::samples::Samples; +use super::values::{Array, Kind, Value, Values}; +use crate::{Error, Result}; + +/// A named set of rows with fields: the rows of one type in a dataset, or rows to write into one. +/// +/// ``` +/// # use latkit::{Ids, Table}; +/// let buses = Table::new("Bus", vec![101_u64, 102, 103]) +/// .field("lon", vec![-97.7, -97.6, -97.5]) +/// .field("name", vec!["North", "Mid", "South"]); +/// let branches = Table::new("Branch", Ids::count(2)).reference("from", "Bus", vec![101_u64, 102]); +/// ``` +#[derive(Clone)] +pub struct Table { + pub(crate) name: Name, + pub(crate) ids: RowIds, + pub(crate) index: Arc>, + pub(crate) fields: Vec<(Name, Field)>, + /// Changes when rows are added or removed. + pub(crate) structure: Version, + /// Changes when rows are removed, which moves the rows after them. + pub(crate) order: Version, +} + +/// The values of one field of a table. +#[derive(Clone)] +pub(crate) enum Field { + Values(Column, Version), + Reference(Reference), + Sampled(Samples, Version), +} + +/// A field naming rows of another table by id. Row indices derive from the ids and the target's rows. +#[derive(Clone)] +pub(crate) struct Reference { + pub(crate) to: Name, + pub(crate) ids: Column, + /// Target row of each row as `u32`; missing where unwired or the id names no row. Its pages align + /// with the pages of `ids`. + pub(crate) rows: Column, + /// What each page of `rows` was resolved from. + pub(crate) resolved: Arc<[Resolved]>, + pub(crate) version: Version, + /// The rows naming each target row, built on first use from `rows`, and shared by every snapshot + /// holding them. + pub(crate) inverse: Arc>, +} + +/// A reference row's target where it names no row. +pub(crate) const UNWIRED: u32 = u32::MAX; + +/// The rows naming each target row of a reference: target `t`'s are `rows[starts[t]..starts[t + 1]]`, +/// in row order. +#[derive(Default)] +pub(crate) struct Inverse { + starts: Vec, + rows: Vec, +} + +impl Inverse { + /// The rows naming target row `target`. + pub(crate) fn of(&self, target: usize) -> &[u32] { + match (self.starts.get(target), self.starts.get(target + 1)) { + (Some(&start), Some(&end)) => &self.rows[start as usize..end as usize], + _ => &[], + } + } +} + +/// The inputs one page of a reference's rows was resolved from. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub(crate) struct Resolved { + pub(crate) ids: PageId, + pub(crate) order: Version, + pub(crate) structure: Version, + /// Whether an id on the page named no row. + pub(crate) dangling: bool, +} + +impl Field { + pub(crate) fn kind(&self) -> Kind { + match self { + Field::Values(column, _) => column.kind(), + Field::Reference(_) => Kind::Reference, + Field::Sampled(..) => Kind::Sampled, + } + } + + /// Changes whenever the field's values do. + pub(crate) fn version(&self) -> Version { + match self { + Field::Values(_, v) | Field::Sampled(_, v) => *v, + Field::Reference(r) => r.version, + } + } + + /// The field of rows `rows`, in that order: a reference names the same targets by id, resolved + /// again once applied; samples keep every frame. + pub(crate) fn gather(&self, rows: &[usize]) -> Field { + match self { + Field::Values(column, _) => Field::Values(column.gather(rows), Version::next()), + Field::Reference(reference) => Field::Reference(Reference { + ids: reference.ids.gather(rows), + version: Version::next(), + inverse: Arc::default(), + ..reference.clone() + }), + Field::Sampled(samples, _) => Field::Sampled(samples.gather(rows), Version::next()), + } + } +} + +impl Reference { + pub(crate) fn new(to: Name, ids: Column) -> Reference { + let rows = Column::missing(&Values::from(Vec::::new()), 0); + Reference { to, ids, rows, resolved: Arc::new([]), version: Version::next(), inverse: Arc::default() } + } + + /// The target row row `row` names. + pub(crate) fn target(&self, row: usize) -> Option { + match self.rows.get(row)? { + Value::Number(n) => Some(n as u32), + _ => None, + } + } + + /// Every row's target row, [`UNWIRED`] where it names none: read page by page, not value by value. + pub(crate) fn targets(&self) -> Vec { + let mut out = Vec::with_capacity(self.rows.len()); + for page in self.rows.pages() { + let values = &page.values; + match (&values.array, &values.valid) { + (Array::U32(rows), None) => out.extend_from_slice(rows), + (Array::U32(rows), Some(valid)) => { + out.extend(rows.iter().enumerate().map(|(i, &t)| if valid.get(i) { t } else { UNWIRED })); + } + _ => out.extend((0..values.len()).map(|i| match values.get(i) { + Some(Value::Number(n)) => n as u32, + _ => UNWIRED, + })), + } + } + out + } + + /// The rows naming each target row: counted, the counts summed, then each row written at its + /// target's place. + pub(crate) fn inverse(&self) -> &Inverse { + self.inverse.get_or_init(|| { + let targets = self.targets(); + let count = targets.iter().filter(|&&t| t != UNWIRED).max().map_or(0, |&t| t as usize + 1); + let mut starts = vec![0_u32; count + 1]; + for &t in targets.iter().filter(|&&t| t != UNWIRED) { + starts[t as usize + 1] += 1; + } + for t in 0..count { + starts[t + 1] += starts[t]; + } + let mut next = starts.clone(); + let mut rows = vec![0_u32; starts[count] as usize]; + for (row, &t) in targets.iter().enumerate() { + if t != UNWIRED { + rows[next[t as usize] as usize] = row as u32; + next[t as usize] += 1; + } + } + Inverse { starts, rows } + }) + } + + /// This reference for ids `ids`, naming rows `targets` of a target table of `order` and + /// `structure`, [`UNWIRED`] where none: resolved already, as a table drawn in part holds it. + /// `targets` holds a row for each id. A page of `kept`, as it was resolved before, whose ids and + /// targets are those of the same page now, keeps its id, so it does not upload again. + pub(crate) fn resolved_to( + &self, + ids: Column, + targets: &[u32], + order: Version, + structure: Version, + kept: Option<&Reference>, + ) -> Reference { + let mut pages = Vec::with_capacity(ids.pages().len()); + let mut resolved = Vec::with_capacity(ids.pages().len()); + let mut start = 0; + for (p, page) in ids.pages().iter().enumerate() { + let rows = &targets[start..start + page.values.len()]; + start += rows.len(); + let dangling = (0..rows.len()).any(|i| rows[i] == UNWIRED && page.values.is_valid(i)); + let same = + kept.and_then(|k| Some((k.rows.pages().get(p)?, k.ids.pages().get(p)?))).filter(|(old, old_ids)| { + old_ids.id == page.id && matches!(&old.values.array, Array::U32(old) if old[..] == *rows) + }); + if let Some((old, _)) = same { + pages.push(old.clone()); + } else { + let valid = Bits::from_fn(rows.len(), |i| rows[i] != UNWIRED); + let values = Values { array: Array::U32(rows.to_vec().into()), valid: (!valid.all()).then_some(valid) }; + pages.push(Page::new(values)); + } + resolved.push(Resolved { ids: page.id, order, structure, dangling }); + } + Reference { + to: self.to.clone(), + ids, + rows: Column::of_pages(pages, &Values::from(Vec::::new())), + resolved: resolved.into(), + version: Version::next(), + inverse: Arc::default(), + } + } + + /// Whether `rows` must be resolved again against a target with these versions. + pub(crate) fn stale(&self, order: Version, structure: Version) -> bool { + self.resolved.len() != self.ids.pages().len() + || self + .ids + .pages() + .iter() + .zip(self.resolved.iter()) + .any(|(page, r)| r.ids != page.id || r.order != order || (r.dangling && r.structure != structure)) + } + + /// Resolves the pages whose inputs changed against `target`. + pub(crate) fn resolve(&self, target: &Table) -> Result { + let index = target.index()?; + let (order, structure) = (target.order, target.structure); + let mut pages = Vec::with_capacity(self.ids.pages().len()); + let mut resolved = Vec::with_capacity(self.ids.pages().len()); + for (p, page) in self.ids.pages().iter().enumerate() { + let old = self.resolved.get(p).zip(self.rows.pages().get(p)); + if let Some((r, rows)) = old + && r.ids == page.id + && r.order == order + && (!r.dangling || r.structure == structure) + { + pages.push(rows.values.clone()); + resolved.push(*r); + continue; + } + let (rows, dangling) = index.resolve(&target.ids, &page.values, UNWIRED); + let valid = Bits::from_fn(rows.len(), |i| rows[i] != UNWIRED); + pages.push(Values { array: Array::U32(rows.into()), valid: (!valid.all()).then_some(valid) }); + resolved.push(Resolved { ids: page.id, order, structure, dangling }); + } + Ok(Reference { + to: self.to.clone(), + ids: self.ids.clone(), + rows: Column::from_pages(pages, &Values::from(Vec::::new())), + resolved: resolved.into(), + version: Version::next(), + inverse: Arc::default(), + }) + } +} + +impl Table { + /// A table named `name` with rows `ids`: a count for rows `0..n`, or a list of numbers or texts. + pub fn new(name: impl Into, ids: impl Into) -> Table { + let version = Version::next(); + Table { + name: name.into(), + ids: RowIds::new(&ids.into()), + index: Arc::default(), + fields: Vec::new(), + structure: version, + order: version, + } + } + + /// Adds or replaces field `name`: one value per row. + #[must_use] + pub fn field(mut self, name: impl Into, values: impl Into) -> Table { + let column = Column::new(&values.into()); + self.insert(name.into(), Field::Values(column, Version::next())); + self + } + + /// Adds or replaces field `name` naming rows of table `to` by id; `None` leaves a row unwired. + #[must_use] + pub fn reference(mut self, name: impl Into, to: impl Into, ids: impl Into) -> Table { + let ids = match RowIds::new(&ids.into()) { + RowIds::Count(n) => Column::new(&Values::from((0..u64::from(n)).collect::>())), + RowIds::Listed(column) => column, + }; + self.insert(name.into(), Field::Reference(Reference::new(to.into(), ids))); + self + } + + /// The table's name. + pub fn name(&self) -> &Name { + &self.name + } + + /// The number of rows. + pub fn len(&self) -> usize { + self.ids.len() + } + + /// Whether the table has no rows. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Every row's id, in row order. + pub fn ids(&self) -> impl Iterator + '_ { + (0..self.len()).filter_map(|row| self.ids.id(row)) + } + + /// Every field's name and kind, by name. + pub fn fields(&self) -> impl Iterator + '_ { + self.fields.iter().map(|(name, field)| (name, field.kind())) + } + + /// What field `name` holds. + pub fn kind(&self, name: &str) -> Option { + self.field_named(name).map(Field::kind) + } + + /// The value of `field` for the row with `id`. A sampled field reads its last frame; a reference + /// reads the target's id. + pub fn get(&self, id: impl Into, field: &str) -> Option { + let row = self.row(id.into().as_ref())?; + self.value(row, field, f64::INFINITY) + } + + /// Every row's value of `field`, in row order: a reference's as the target ids, a sampled + /// field's at its last frame. + pub fn values(&self, field: &str) -> Option { + Some(match self.field_named(field)? { + Field::Values(column, _) => column.values(), + Field::Reference(reference) => reference.ids.values(), + Field::Sampled(samples, _) => { + let frame = samples.frame_at(f64::INFINITY); + Values::from((0..self.len()).map(|row| frame.and_then(|f| samples.value(row, f))).collect::>()) + } + }) + } + + pub(crate) fn value(&self, row: usize, field: &str, at: f64) -> Option { + match self.field_named(field)? { + Field::Values(column, _) => column.get(row), + Field::Reference(reference) => reference.ids.get(row), + Field::Sampled(samples, _) => samples.value(row, samples.frame_at(at)?).map(Value::Number), + } + } + + /// The table of rows `rows` of this one, in that order, with every field: what removing rows + /// keeps, and what a query reads back. + pub(crate) fn rows(&self, rows: &[usize]) -> Table { + let version = Version::next(); + Table { + name: self.name.clone(), + ids: self.ids.gather(rows), + index: Arc::default(), + fields: self.fields.iter().map(|(name, field)| (name.clone(), field.gather(rows))).collect(), + structure: version, + order: version, + } + } + + /// The row with `id`. + pub(crate) fn row(&self, id: IdRef<'_>) -> Option { + self.index().ok()?.get(&self.ids, id) + } + + pub(crate) fn index(&self) -> Result<&Index> { + if let Some(index) = self.index.get() { + return Ok(index); + } + let index = self.ids.index()?; + Ok(self.index.get_or_init(|| index)) + } + + pub(crate) fn field_named(&self, name: &str) -> Option<&Field> { + let i = self.fields.binary_search_by(|(n, _)| n.as_str().cmp(name)).ok()?; + Some(&self.fields[i].1) + } + + pub(crate) fn insert(&mut self, name: Name, field: Field) { + match self.fields.binary_search_by(|(n, _)| n.cmp(&name)) { + Ok(i) => self.fields[i].1 = field, + Err(i) => self.fields.insert(i, (name, field)), + } + } + + /// Checks that every field has one value per row and the ids are present and unique. + pub(crate) fn check(&self) -> Result<()> { + if self.name.is_empty() { + return Err(Error::invalid("a table needs a name")); + } + if let Some(row) = self.ids.hole() { + return Err(Error::invalid("a row needs an id").at(row).at("ids")); + } + self.index().map_err(|e| e.at("ids"))?; + for (name, field) in &self.fields { + let len = match field { + Field::Values(column, _) => column.len(), + Field::Reference(reference) => reference.ids.len(), + Field::Sampled(..) => continue, + }; + if len != self.len() { + return Err(Error::invalid(format!("{len} values for {} rows", self.len())).at(name)); + } + } + Ok(()) + } +} + +impl std::fmt::Debug for Table { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Table") + .field("name", &self.name) + .field("rows", &self.len()) + .field("fields", &self.fields().collect::>()) + .finish_non_exhaustive() + } +} diff --git a/crates/latkit/src/data/tests.rs b/crates/latkit/src/data/tests.rs new file mode 100644 index 00000000..ce89e2d8 --- /dev/null +++ b/crates/latkit/src/data/tests.rs @@ -0,0 +1,400 @@ +//! Patches applied to a dataset agree with a plain model of rows, whatever the sequence. + +use proptest::prelude::*; + +use crate::{Data, Error, Id, Ids, Patch, Row, Table, Value}; + +/// One row of the model: id, number field `x`, and reference `r` to another row's id. +type ModelRow = (u64, Option, Option); + +#[derive(Clone, Debug)] +enum Change { + Set(Vec<(u64, Option, Option)>, bool, bool), + Remove(Vec), + Append(Vec>), +} + +fn change() -> impl Strategy { + let id = 0..12_u64; + let row = (id.clone(), proptest::option::of(-10.0..10.0_f64), proptest::option::of(0..14_u64)); + prop_oneof![ + 3 => (proptest::collection::vec(row, 0..8), any::(), any::()).prop_map(|(rows, x, r)| { + let mut seen = std::collections::HashSet::new(); + Change::Set(rows.into_iter().filter(|(id, ..)| seen.insert(*id)).collect(), x, r) + }), + 1 => proptest::collection::vec(id, 0..5).prop_map(Change::Remove), + 1 => proptest::collection::vec(proptest::option::of(-1.0..1.0_f64), 0..1).prop_map(Change::Append), + ] +} + +struct Model { + rows: Vec, + /// Frames of field `s`: per frame, the value of each row present then. + frames: Vec)>>, +} + +impl Model { + fn apply(&mut self, change: &Change) -> Patch { + match change { + Change::Set(rows, write_x, write_r) => { + let mut table = Table::new("T", rows.iter().map(|r| r.0).collect::>()); + if *write_x { + table = table.field("x", rows.iter().map(|r| r.1).collect::>()); + } + if *write_r { + table = table.reference("r", "T", rows.iter().map(|r| r.2).collect::>()); + } + for &(id, x, r) in rows { + let at = self.rows.iter().position(|m| m.0 == id).unwrap_or_else(|| { + self.rows.push((id, None, None)); + self.rows.len() - 1 + }); + if *write_x { + self.rows[at].1 = x; + } + if *write_r { + self.rows[at].2 = r; + } + } + Patch::new().set(table) + } + Change::Remove(ids) => { + self.rows.retain(|m| !ids.contains(&m.0)); + Patch::new().remove("T", ids.clone()) + } + Change::Append(values) => { + let values: Vec> = + (0..self.rows.len()).map(|i| values.first().copied().flatten().map(|v| v + i as f64)).collect(); + let at = self.frames.len() as f64; + self.frames.push(self.rows.iter().zip(&values).map(|(m, v)| (m.0, *v)).collect()); + Patch::new().append([at], "T", [("s", values)]) + } + } + } + + fn check(&self, data: &Data) { + let table = data.table("T").expect("the table exists"); + let ids: Vec = table.ids().collect(); + assert_eq!(ids, self.rows.iter().map(|m| Id::Number(m.0)).collect::>()); + for &(id, x, r) in &self.rows { + let row = Row::new("grid", "T", id); + let has_x = table.kind("x").is_some(); + assert_eq!(data.get(&row, "x"), if has_x { x.map(Value::Number) } else { None }, "x of {id}"); + let wired = r.filter(|r| self.rows.iter().any(|m| m.0 == *r)); + assert_eq!(data.get(&row, "r"), wired.map(|r| Value::Row(Row::new("grid", "T", r))), "r of {id}"); + } + } +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(256))] + + #[test] + fn patches_agree_with_the_model(changes in proptest::collection::vec(change(), 1..12)) { + let mut data = Data::new("grid"); + data.apply(Patch::new().set(Table::new("T", Vec::::new()))).expect("an empty table"); + let mut model = Model { rows: Vec::new(), frames: Vec::new() }; + for change in &changes { + let before = data.clone(); + let before_bytes = before.to_bytes(); + let patch = model.apply(change); + data.apply(patch).expect("valid patches apply"); + model.check(&data); + prop_assert_eq!(before.to_bytes(), before_bytes, "an earlier snapshot never changes"); + let back = Data::from_bytes(&data.to_bytes()).expect("round trip"); + model.check(&back); + } + for (frame, rows) in model.frames.iter().enumerate() { + for &(id, value) in rows { + if let Some(at) = model.rows.iter().position(|m| m.0 == id) { + let read = data.get_at(&Row::new("grid", "T", id), "s", frame as f64); + let want = value.map(|v| Value::Number(f64::from(v as f32))); + prop_assert_eq!(read, want, "frame {} of {} (row {})", frame, id, at); + } + } + } + } +} + +#[test] +fn a_failed_patch_changes_nothing() { + let mut data = Data::new("grid"); + data.apply(Table::new("Bus", vec![1_u64, 2]).field("kv", vec![230.0, 115.0])).expect("valid"); + let before = data.to_bytes(); + let error = data + .apply( + Patch::new() + .set(Table::new("Bus", vec![3_u64]).field("kv", vec![69.0])) + .set(Table::new("Bus", vec![4_u64]).field("kv", vec!["text"])), + ) + .expect_err("text into a number field"); + assert!(matches!(&error, Error::Invalid { .. }), "{error}"); + assert_eq!(error.to_string(), "patch[1].Bus.kv: Text values for a Number field"); + assert_eq!(data.to_bytes(), before); +} + +#[test] +fn appends_one_after_another_record_as_one_and_name_their_own_errors() { + let table = || Table::new("Bus", vec![1_u64, 2]).field("kv", vec![230.0, 115.0]); + let mut one = Data::new("grid"); + one.apply(Patch::new().replace(table()).append( + [0.0, 1.0, 2.0], + "Bus", + [("vm", vec![1.0_f32, 2.0, 3.0, 4.0, 5.0, 6.0])], + )) + .expect("valid"); + let mut each = Data::new("grid"); + let mut patch = Patch::new().replace(table()); + for f in 0..3 { + let v = 2.0 * f as f32; + patch = patch.append([f64::from(f)], "Bus", [("vm", vec![v + 1.0, v + 2.0])]); + } + each.apply(patch).expect("valid"); + assert_eq!(each.to_bytes(), one.to_bytes(), "a frame a change records as the frames in one"); + let error = each + .apply( + Patch::new() + .append([3.0], "Bus", [("vm", vec![1.0_f32, 1.0])]) + .append([4.0], "Bus", [("vm", vec![1.0_f32])]) + .append([5.0], "Bus", [("vm", vec![1.0_f32, 1.0])]), + ) + .expect_err("a frame short of a row"); + assert!(error.to_string().starts_with("patch[1].Bus.vm"), "{error}"); +} + +#[test] +fn field_lengths_must_match_rows() { + let mut data = Data::new("grid"); + let error = data.apply(Table::new("Bus", Ids::count(3)).field("kv", vec![1.0, 2.0])).expect_err("short field"); + assert_eq!(error.to_string(), "patch[0].Bus.kv: 2 values for 3 rows"); +} + +#[test] +fn repeated_ids_are_refused() { + let mut data = Data::new("grid"); + let error = data.apply(Table::new("Bus", vec!["a", "a"])).expect_err("repeated id"); + assert!(error.to_string().starts_with("patch[0].Bus.ids[1]"), "{error}"); +} + +#[test] +fn references_to_unknown_tables_are_refused() { + let mut data = Data::new("grid"); + let error = + data.apply(Table::new("Branch", Ids::count(1)).reference("from", "Bus", vec![1_u64])).expect_err("no Bus"); + assert_eq!(error.to_string(), "Branch.from: no table Bus"); +} + +#[test] +fn dangling_references_wire_up_when_the_row_arrives() { + let mut data = Data::new("grid"); + data.apply(Patch::new().set(Table::new("Bus", vec![1_u64])).set(Table::new("Branch", Ids::count(1)).reference( + "to", + "Bus", + vec![2_u64], + ))) + .expect("valid"); + let branch = Row::new("grid", "Branch", 0_u64); + assert_eq!(data.get(&branch, "to"), None); + data.apply(Table::new("Bus", vec![2_u64])).expect("valid"); + assert_eq!(data.get(&branch, "to"), Some(Value::Row(Row::new("grid", "Bus", 2_u64)))); + data.apply(Patch::new().remove("Bus", vec![1_u64])).expect("valid"); + assert_eq!(data.get(&branch, "to"), Some(Value::Row(Row::new("grid", "Bus", 2_u64)))); +} + +#[test] +fn inverses_follow_every_change_and_snapshots_keep_theirs() { + let inverse = |data: &Data, target: usize| { + let Some(super::table::Field::Reference(r)) = data.table("Branch").and_then(|t| t.field_named("from")) else { + panic!("a reference"); + }; + r.inverse().of(target).to_vec() + }; + let mut data = Data::new("grid"); + data.apply( + Patch::new().set(Table::new("Bus", vec![1_u64, 2, 3])).set(Table::new("Branch", Ids::count(4)).reference( + "from", + "Bus", + vec![1_u64, 2, 1, 3], + )), + ) + .expect("valid"); + assert_eq!(inverse(&data, 0), vec![0, 2]); + assert_eq!(inverse(&data, 2), vec![3]); + let before = data.clone(); + data.apply(Table::new("Branch", vec![1_u64]).reference("from", "Bus", vec![3_u64])).expect("valid"); + assert_eq!((inverse(&data, 0), inverse(&data, 2)), (vec![0, 2], vec![1, 3])); + data.apply(Patch::new().remove("Bus", vec![1_u64])).expect("valid"); + // Bus 1 left: what named it names nothing, and the rest moved up a row. + assert_eq!((inverse(&data, 0), inverse(&data, 1)), (vec![], vec![1, 3])); + assert_eq!(inverse(&before, 0), vec![0, 2]); +} + +/// A dataset of `rows` rows of `Line` with a `flow` sampled over `frames` frames, one a second. +fn sampled(rows: usize, frames: usize) -> Data { + let mut data = Data::new("grid"); + let at: Vec = (0..frames).map(|f| f as f64).collect(); + let flow: Vec = (0..frames * rows).map(|i| ((i * 7919) % 1000) as f64 - 500.0).collect(); + data.apply( + Patch::new() + .axis("time", "s") + .replace(Table::new("Line", Ids::count(rows as u32)).reference("from", "Bus", vec![0_u32; rows])) + .replace(Table::new("Bus", Ids::count(1)).field("name", vec!["a"])) + .append(at, "Line", [("flow", flow)]), + ) + .expect("valid"); + data +} + +#[test] +fn describe_names_tables_fields_and_spans() { + let description = sampled(3, 10).describe(); + assert_eq!(description.axis, Some(["time".into(), "s".into()])); + assert_eq!(description.span, Some([0.0, 9.0])); + let line = description.tables.iter().find(|t| t.name.as_str() == "Line").expect("Line"); + assert_eq!(line.rows, 3); + let json = serde_json::to_value(line).expect("serializes"); + assert_eq!( + json["fields"], + serde_json::json!([ + { "name": "flow", "kind": "sampled", "span": [0.0, 9.0] }, + { "name": "from", "kind": "reference", "to": "Bus" }, + ]) + ); +} + +#[test] +fn envelopes_read_levels_as_frames_would() { + let (rows, frames) = (3, 700); + let data = sampled(rows, frames); + let line = data.table("Line").expect("Line"); + let value = |row: usize, frame: usize| (((frame * rows + row) * 7919) % 1000) as f32 - 500.0; + for (range, spans) in [([0.0, 699.0], 1), ([0.0, 699.0], 7), ([13.5, 600.0], 5), ([650.0, 2000.0], 3)] { + let envelope = line.envelope("flow", range, spans, None).expect("an envelope"); + assert_eq!(envelope.at.len(), spans + 1); + for row in 0..rows { + for s in 0..spans { + let (lo, hi) = (envelope.at[s], envelope.at[s + 1]); + let inside = + (0..frames).filter(|&f| f as f64 >= lo && (f as f64) < hi || s == spans - 1 && f as f64 == hi); + let values: Vec = inside.map(|f| value(row, f)).collect(); + let least = values.iter().copied().reduce(f32::min).unwrap_or(f32::NAN); + let greatest = values.iter().copied().reduce(f32::max).unwrap_or(f32::NAN); + let i = row * spans + s; + let same = |a: f32, b: f32| a == b || a.is_nan() && b.is_nan(); + assert!( + same(envelope.least[i], least) && same(envelope.greatest[i], greatest), + "{range:?}/{spans} row {row} span {s}" + ); + } + } + } + let picked = line.envelope("flow", [0.0, 699.0], 2, Some(&vec![2_u32, 0].into())).expect("an envelope"); + let all = line.envelope("flow", [0.0, 699.0], 2, None).expect("an envelope"); + assert_eq!(picked.least, [&all.least[4..6], &all.least[0..2]].concat()); + assert!(line.envelope("from", [0.0, 1.0], 1, None).is_err()); + assert!(line.envelope("flow", [0.0, 1.0], 1, Some(&vec![9_u32].into())).is_err()); +} + +#[cfg(feature = "gpu")] +#[test] +fn queries_filter_sort_page_and_select() { + use crate::{Order, Query, field}; + let mut data = Data::new("grid"); + let loading = vec![40.0, 95.0, 120.0, 95.0, 10.0]; + data.apply( + Table::new("Branch", Ids::count(5)).field("loading", loading).field("name", vec!["a", "b", "c", "d", "e"]), + ) + .expect("valid"); + let names = |table: &Table| table.ids().map(|id| table.get(id, "name")).collect::>(); + let text = |s: &str| Some(Value::Text(s.into())); + let hot = Query::of("Branch").filter(field("loading").gt(90.0)).sort(field("loading"), Order::Descending); + let (sorted, kept) = data.query(&hot).expect("a query"); + assert_eq!((names(&sorted), kept), (vec![text("c"), text("b"), text("d")], 3), "ties keep their order"); + let (page, kept) = data.query(&hot.clone().offset(1).limit(1)).expect("a query"); + assert_eq!((names(&page), kept), (vec![text("b")], 3), "the filter kept three, the page one"); + let (least, _) = + data.query(&Query::of("Branch").sort(field("loading"), Order::Ascending).limit(2)).expect("a query"); + assert_eq!(names(&least), [text("e"), text("a")]); + let (selected, _) = + data.query(&Query::of("Branch").limit(1).select("double", field("loading") * 2.0)).expect("a query"); + assert_eq!(selected.fields().map(|(name, _)| name.as_str()).collect::>(), ["double"]); + assert_eq!(selected.get(0_u64, "double"), Some(Value::Number(80.0))); + let json: Query = serde_json::from_value(serde_json::json!({ + "of": "Branch", "filter": { "op": "lt", "args": ["loading", 100] }, "sort": [["loading", "descending"]], "limit": 2, + })) + .expect("a query"); + assert_eq!(names(&data.query(&json).expect("a query").0), [text("b"), text("d")]); + let (named, _) = data.query(&Query::of("Branch").ids([3_u64, 1, 9])).expect("by ids"); + assert_eq!(names(&named), [text("d"), text("b")], "in the order named, unknown ids passed over"); + let (lake, _) = data.query(&Query::of("Branch").filter(field("name").contains("C"))).expect("contains"); + assert_eq!(names(&lake), [text("c")], "ignoring case"); + assert!(data.query(&Query::of("Nope")).is_err()); +} + +#[cfg(feature = "gpu")] +#[test] +fn queries_read_sampled_fields_at_a_coordinate() { + use crate::{Query, field}; + let data = sampled(2, 4); + let (at_two, _) = data.query(&Query::of("Line").at(2.0).select("flow", field("flow"))).expect("a query"); + let flow = |row: usize, frame: usize| Value::Number(((((frame * 2 + row) * 7919) % 1000) as f64) - 500.0); + assert_eq!(at_two.get(1_u64, "flow"), Some(flow(1, 2))); + let (last, _) = data.query(&Query::of("Line")).expect("a query"); + assert_eq!(last.kind("flow"), Some(crate::Kind::Number)); + assert_eq!(last.get(0_u64, "flow"), Some(flow(0, 3))); +} + +#[test] +fn ids_too_large_for_json_numbers_cross_as_text() { + let big = (1_u64 << 53) + 1; + let mut data = Data::new("grid"); + data.apply(Table::new("Bus", vec![big, 7]).field("kv", vec![1.0, 2.0])).expect("valid"); + assert_eq!(serde_json::to_string(&Id::Number(big)).expect("an id"), format!("\"{big}\"")); + assert_eq!(serde_json::to_string(&Id::Number(7)).expect("an id"), "7"); + let bus = data.table("Bus").expect("Bus"); + assert_eq!(bus.get(Id::from(big.to_string()), "kv"), Some(Value::Number(1.0)), "the text names the row"); + assert_eq!(bus.get(big, "kv"), Some(Value::Number(1.0))); + assert_eq!(bus.values("kv").and_then(|v| v.numbers()), Some(vec![1.0, 2.0])); + let counted = Table::new("Count", Ids::count(3)).field("x", vec![0.0, 1.0, 2.0]); + data.apply(counted).expect("valid"); + assert_eq!(data.table("Count").expect("Count").get(Id::from("2"), "x"), Some(Value::Number(2.0))); +} + +#[test] +fn schema_changes_only_with_fields() { + let mut data = Data::new("grid"); + data.apply(Table::new("Bus", Ids::count(2)).field("kv", vec![1.0, 2.0])).expect("valid"); + let schema = data.schema(); + data.apply(Table::new("Bus", Ids::count(3)).field("kv", vec![1.0, 2.0, 3.0])).expect("valid"); + assert_eq!(data.schema(), schema); + data.apply(Table::new("Bus", Ids::count(1)).field("name", vec!["a"])).expect("valid"); + assert_ne!(data.schema(), schema); +} + +#[test] +fn rows_appended_by_id_leave_the_rest_holding() { + let mut data = Data::new("grid"); + data.apply(Patch::new().set(Table::new("Bus", [10_u64, 20, 30])).append( + [0.0], + "Bus", + [("vm", vec![1.0, 1.1, 1.2])], + )) + .expect("valid"); + data.apply(Patch::new().append_rows([1.0], "Bus", [30_u64], [("vm", vec![0.9])])).expect("by id"); + let vm = |id: u64| data.get_at(&Row::new("grid", "Bus", id), "vm", 1.0); + assert_eq!(vm(10), Some(Value::Number(1.0)), "held"); + assert_eq!(vm(30), Some(Value::Number(f64::from(0.9_f32))), "recorded"); + let error = data.apply(Patch::new().append_rows([2.0], "Bus", [40_u64], [("vm", vec![1.0])])); + assert!(error.is_err_and(|e| e.to_string().contains("no row")), "rows appended to are rows the table holds"); +} + +#[test] +fn a_patch_to_a_dataset_changes_it_alone() { + let mut grid = Data::new("grid"); + grid.apply(Patch::to("grid").set(Table::new("Bus", Ids::count(1)))).expect("its own"); + let error = grid.apply(Patch::to("weather").set(Table::new("Cell", Ids::count(1)))); + assert!(error.is_err_and(|e| e.to_string().contains("weather"))); + let bytes = grid.to_bytes(); + assert_eq!(Patch::from_bytes(&bytes).expect("a patch").data().map(crate::Name::as_str), Some("grid")); + assert!(Data::from_bytes(&Patch::new().to_bytes()).is_err(), "a dataset is a patch to one"); +} diff --git a/crates/latkit/src/data/text.rs b/crates/latkit/src/data/text.rs new file mode 100644 index 00000000..b78958e5 --- /dev/null +++ b/crates/latkit/src/data/text.rs @@ -0,0 +1,95 @@ +use std::ops::Range; +use std::sync::Arc; + +use super::buffer::Buffer; + +/// Shared, immutable texts: offsets into one UTF-8 string. +#[derive(Clone)] +pub(crate) struct Text { + offsets: Buffer, + bytes: Arc, +} + +impl Text { + pub(crate) fn len(&self) -> usize { + self.offsets.len().saturating_sub(1) + } + + pub(crate) fn get(&self, i: usize) -> &str { + &self.bytes[self.offsets[i] as usize..self.offsets[i + 1] as usize] + } + + pub(crate) fn slice(&self, range: Range) -> Text { + Text { offsets: self.offsets.slice(range.start..range.end + 1), bytes: self.bytes.clone() } + } + + pub(crate) fn iter(&self) -> impl Iterator + '_ { + (0..self.len()).map(|i| self.get(i)) + } + + /// The UTF-8 bytes the slice spans and offsets relative to them. + pub(crate) fn compact(&self) -> (Vec, &str) { + let base = self.offsets.first().copied().unwrap_or(0); + let end = self.offsets.last().copied().unwrap_or(0); + (self.offsets.iter().map(|o| o - base).collect(), &self.bytes[base as usize..end as usize]) + } + + pub(crate) fn from_parts(offsets: Vec, bytes: String) -> Option { + let valid = offsets.first() == Some(&0) + && offsets.windows(2).all(|w| w[0] <= w[1]) + && offsets.last().is_some_and(|&end| end as usize == bytes.len()) + && offsets.iter().all(|&o| bytes.is_char_boundary(o as usize)); + valid.then(|| Text { offsets: offsets.into(), bytes: bytes.into() }) + } +} + +impl Default for Text { + fn default() -> Text { + Text { offsets: vec![0].into(), bytes: "".into() } + } +} + +impl<'a> FromIterator<&'a str> for Text { + fn from_iter>(iter: I) -> Text { + let mut builder = TextBuilder::default(); + for text in iter { + builder.push(text); + } + builder.finish() + } +} + +impl std::fmt::Debug for Text { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_list().entries(self.iter()).finish() + } +} + +/// Builds [`Text`] one string at a time. +pub(crate) struct TextBuilder { + offsets: Vec, + bytes: String, +} + +impl Default for TextBuilder { + fn default() -> TextBuilder { + TextBuilder { offsets: vec![0], bytes: String::new() } + } +} + +impl TextBuilder { + pub(crate) fn with_capacity(texts: usize) -> TextBuilder { + let mut offsets = Vec::with_capacity(texts + 1); + offsets.push(0); + TextBuilder { offsets, bytes: String::new() } + } + + pub(crate) fn push(&mut self, text: &str) { + self.bytes.push_str(text); + self.offsets.push(u32::try_from(self.bytes.len()).expect("a text page holds at most 4 GiB")); + } + + pub(crate) fn finish(self) -> Text { + Text { offsets: self.offsets.into(), bytes: self.bytes.into() } + } +} diff --git a/crates/latkit/src/data/values.rs b/crates/latkit/src/data/values.rs new file mode 100644 index 00000000..f7b8b737 --- /dev/null +++ b/crates/latkit/src/data/values.rs @@ -0,0 +1,803 @@ +use std::ops::Range; +use std::sync::Arc; + +use super::bits::{Bits, BitsBuilder}; +use super::buffer::Buffer; +use super::column::{PAGE_BITS, PAGE_MASK}; +use super::geometry::{Geometry, GeometryBuilder}; +use super::name::Row; +use super::text::{Text, TextBuilder}; +use crate::{Error, Result}; + +/// One column of values, as given to [`Table::field`](crate::Table::field) or read from a page. +/// +/// Converts from vectors and slices of numbers, booleans, texts, and geometries, with `Option` for +/// missing values. Slicing and cloning never copy. +#[derive(Clone)] +pub struct Values { + pub(crate) array: Array, + pub(crate) valid: Option, +} + +#[derive(Clone)] +pub(crate) enum Array { + F64(Buffer), + F32(Buffer), + I32(Buffer), + U32(Buffer), + U64(Buffer), + Bool(Bits), + Text(Text), + Geometry(Geometry), +} + +/// What a field holds. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +#[serde(rename_all = "lowercase")] +pub enum Kind { + /// Numbers. + Number, + /// Booleans. + Bool, + /// Texts. + Text, + /// `[x, y]` points. + Point, + /// Paths of points. + Path, + /// Parts: the rings of a polygon, or the paths of a multi-path. + Parts, + /// Polygons of rings. + Polygons, + /// Rows of another table, by id. + Reference, + /// Numbers sampled over the data's axis. + Sampled, +} + +impl Kind { + /// The geometry of `depth` levels below its points: 0 a point, 1 a path, 2 parts, 3 polygons. + pub(crate) fn geometry(depth: u8) -> Kind { + match depth { + 0 => Kind::Point, + 1 => Kind::Path, + 2 => Kind::Parts, + _ => Kind::Polygons, + } + } + + /// How many levels a geometry nests below its points; `None` for any other kind. + pub(crate) fn depth(self) -> Option { + match self { + Kind::Point => Some(0), + Kind::Path => Some(1), + Kind::Parts => Some(2), + Kind::Polygons => Some(3), + _ => None, + } + } +} + +/// One value read from a dataset. +#[derive(Clone, PartialEq, Debug)] +pub enum Value { + /// A number. + Number(f64), + /// A boolean. + Bool(bool), + /// A text. + Text(Arc), + /// A point. + Point([f64; 2]), + /// A path. + Path(Vec<[f64; 2]>), + /// Parts: the rings of a polygon, or the paths of a multi-path. + Parts(Vec>), + /// Polygons of rings. + Polygons(Vec>>), + /// The row a reference names. + Row(Row), +} + +/// A value writes as JSON: a number (`null` when not finite), boolean, or text; a geometry as nested +/// `[x, y]` points; a reference as the id of the row it names. +impl serde::Serialize for Value { + fn serialize(&self, serializer: S) -> Result { + match self { + Value::Number(n) if n.is_finite() => serializer.serialize_f64(*n), + Value::Number(_) => serializer.serialize_none(), + Value::Bool(b) => serializer.serialize_bool(*b), + Value::Text(t) => serializer.serialize_str(t), + Value::Point(p) => p.serialize(serializer), + Value::Path(p) => p.serialize(serializer), + Value::Parts(p) => p.serialize(serializer), + Value::Polygons(p) => p.serialize(serializer), + Value::Row(row) => row.id.serialize(serializer), + } + } +} + +/// A value as JSON writes it. +impl schemars::JsonSchema for Value { + fn schema_name() -> std::borrow::Cow<'static, str> { + "Value".into() + } + + fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema { + schemars::json_schema!({ + "description": "A value read from a dataset: a number (`null` when not finite), boolean, or text; a geometry as nested `[x, y]` points; a reference as the id of the row it names.", + "anyOf": [ + { "type": ["number", "boolean", "string", "null"] }, + { "type": "array", "items": { "type": "number" }, "minItems": 2, "maxItems": 2 }, + { "type": "array", "items": { "type": "array" } }, + ], + }) + } +} + +/// A row picked that names none: the value made of it is missing, as a hole among the rows drawn +/// of a table drawn through tiles is. +pub(crate) const HOLE: usize = usize::MAX; + +/// Where each value an assembly makes comes from, among its sources: the first, then pages of +/// [`PAGE_ROWS`](super::column::PAGE_ROWS) rows each. A concrete type rather than a closure, so +/// [`Values::assemble`] is compiled once. +#[derive(Clone, Copy)] +pub(crate) enum Picks<'a> { + /// Value `i` is row `rows[i]` of the pages, missing for a [`HOLE`]. + Rows(&'a [usize]), + /// Value `i` is row `from[i]` of the pages where it is written, missing for a [`HOLE`], else row + /// `i` of the first source while `i < kept`, else missing. + Writes { from: &'a [Option], kept: usize }, +} + +impl Picks<'_> { + fn len(self) -> usize { + match self { + Picks::Rows(rows) => rows.len(), + Picks::Writes { from, .. } => from.len(), + } + } + + /// The source and row of value `i`, or `None` where it is missing. + #[inline] + fn get(self, i: usize) -> Option<(usize, usize)> { + let paged = |row: usize| (row != HOLE).then_some((1 + (row >> PAGE_BITS), row & PAGE_MASK)); + match self { + Picks::Rows(rows) => paged(rows[i]), + Picks::Writes { from, kept } => match from[i] { + Some(row) => paged(row), + None => (i < kept).then_some((0, i)), + }, + } + } +} + +impl Values { + /// The number of values. + pub fn len(&self) -> usize { + match &self.array { + Array::F64(v) => v.len(), + Array::F32(v) => v.len(), + Array::I32(v) => v.len(), + Array::U32(v) => v.len(), + Array::U64(v) => v.len(), + Array::Bool(v) => v.len(), + Array::Text(v) => v.len(), + Array::Geometry(v) => v.len(), + } + } + + /// Whether there are no values. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// What the values are. + pub fn kind(&self) -> Kind { + match &self.array { + Array::F64(_) | Array::F32(_) | Array::I32(_) | Array::U32(_) | Array::U64(_) => Kind::Number, + Array::Bool(_) => Kind::Bool, + Array::Text(_) => Kind::Text, + Array::Geometry(g) => Kind::geometry(g.depth()), + } + } + + /// Whether value `i` is present. + pub fn is_valid(&self, i: usize) -> bool { + i < self.len() && self.valid.as_ref().is_none_or(|v| v.get(i)) + } + + /// Value `i`, or `None` when it is missing. + pub fn get(&self, i: usize) -> Option { + if !self.is_valid(i) { + return None; + } + Some(match &self.array { + Array::Bool(v) => Value::Bool(v.get(i)), + Array::Text(v) => Value::Text(v.get(i).into()), + Array::Geometry(v) => v.get(i), + _ => Value::Number(self.number(i)), + }) + } + + /// Value `i` as a row id, exactly: `None` when missing, or neither a whole number nor a text. + pub fn id(&self, i: usize) -> Option { + super::ids::key(self, i).map(super::name::IdRef::to_id) + } + + /// Every value as a number, missing as NaN: `None` unless the values are numbers. + pub fn numbers(&self) -> Option> { + (self.kind() == Kind::Number).then(|| self.map_numbers(|x| x.unwrap_or(f64::NAN))) + } + + /// A zero-copy slice. + #[must_use] + pub fn slice(&self, range: Range) -> Values { + let array = match &self.array { + Array::F64(v) => Array::F64(v.slice(range.clone())), + Array::F32(v) => Array::F32(v.slice(range.clone())), + Array::I32(v) => Array::I32(v.slice(range.clone())), + Array::U32(v) => Array::U32(v.slice(range.clone())), + Array::U64(v) => Array::U64(v.slice(range.clone())), + Array::Bool(v) => Array::Bool(v.slice(range.clone())), + Array::Text(v) => Array::Text(v.slice(range.clone())), + Array::Geometry(v) => Array::Geometry(v.slice(range.clone())), + }; + Values { array, valid: self.valid.as_ref().map(|v| v.slice(range)) } + } + + /// Every value as `number` reads it, `None` where missing, mapped by `f`: a loop per storage, so + /// the storage is matched once rather than per value. + pub(crate) fn map_numbers(&self, mut f: impl FnMut(Option) -> T) -> Vec { + macro_rules! each { + ($v:expr, $number:expr) => { + match &self.valid { + None => $v.iter().map(|&x| f(Some($number(x)))).collect(), + Some(valid) => $v.iter().enumerate().map(|(i, &x)| f(valid.get(i).then(|| $number(x)))).collect(), + } + }; + } + match &self.array { + Array::F64(v) => each!(v, |x: f64| x), + Array::F32(v) => each!(v, f64::from), + Array::I32(v) => each!(v, f64::from), + Array::U32(v) => each!(v, f64::from), + Array::U64(v) => each!(v, |x: u64| x as f64), + _ => (0..self.len()).map(|i| f(self.is_valid(i).then(|| self.number(i)))).collect(), + } + } + + /// Calls `f` with every value as `number` reads it, `None` where missing: a loop per storage, + /// allocating nothing. + pub(crate) fn each_number(&self, mut f: impl FnMut(Option)) { + macro_rules! each { + ($v:expr, $number:expr) => { + match &self.valid { + None => $v.iter().for_each(|&x| f(Some($number(x)))), + Some(valid) => $v.iter().enumerate().for_each(|(i, &x)| f(valid.get(i).then(|| $number(x)))), + } + }; + } + match &self.array { + Array::F64(v) => each!(v, |x: f64| x), + Array::F32(v) => each!(v, f64::from), + Array::I32(v) => each!(v, f64::from), + Array::U32(v) => each!(v, f64::from), + Array::U64(v) => each!(v, |x: u64| x as f64), + _ => (0..self.len()).for_each(|i| f(self.is_valid(i).then(|| self.number(i)))), + } + } + + /// Value `i` as a number; booleans are 0 or 1, others NaN. + pub(crate) fn number(&self, i: usize) -> f64 { + match &self.array { + Array::F64(v) => v[i], + Array::F32(v) => f64::from(v[i]), + Array::I32(v) => f64::from(v[i]), + Array::U32(v) => f64::from(v[i]), + Array::U64(v) => v[i] as f64, + Array::Bool(v) => f64::from(u8::from(v.get(i))), + Array::Text(_) | Array::Geometry(_) => f64::NAN, + } + } + + /// The values as `u32`s, when they are stored so and none is missing. + pub(crate) fn u32s(&self) -> Option<&[u32]> { + match (&self.array, &self.valid) { + (Array::U32(v), None) => Some(v), + _ => None, + } + } + + /// The values as `u64`s, when they are stored so and none is missing. + pub(crate) fn u64s(&self) -> Option<&[u64]> { + match (&self.array, &self.valid) { + (Array::U64(v), None) => Some(v), + _ => None, + } + } + + pub(crate) fn text(&self) -> Option<&Text> { + match &self.array { + Array::Text(t) => Some(t), + _ => None, + } + } + + pub(crate) fn geometry(&self) -> Option<&Geometry> { + match &self.array { + Array::Geometry(g) => Some(g), + _ => None, + } + } + + /// Geometries as values, every one present. + pub(crate) fn of_geometry(geometry: Geometry) -> Values { + Values { array: Array::Geometry(geometry), valid: None } + } + + /// The values `picks` names among `sources`, missing where it names none. + /// + /// The result keeps the first source's storage; numbers from other sources convert to it. A + /// source of another kind is an error. + pub(crate) fn assemble(sources: &[&Values], picks: Picks<'_>) -> Result { + let (len, pick) = (picks.len(), |i: usize| picks.get(i)); + let like = sources.first().expect("a source"); + let kind = like.kind(); + if let Some(other) = sources.iter().find(|s| s.kind() != kind) { + return Err(Error::invalid(format!("{:?} values for a {kind:?} field", other.kind()))); + } + macro_rules! numbers { + ($variant:ident, $t:ty, $store:expr) => {{ + let cast: Vec = sources.iter().map(|s| s.cast(|x| x as $t, $store)).collect(); + let typed: Vec<&[$t]> = cast + .iter() + .map(|values| match &values.array { + Array::$variant(v) => &v[..], + _ => unreachable!("cast to the first source's storage"), + }) + .collect(); + Array::$variant((0..len).map(|i| pick(i).map_or(<$t>::default(), |(s, r)| typed[s][r])).collect()) + }}; + } + let array = match &like.array { + Array::F64(_) => numbers!(F64, f64, Store::F64), + Array::F32(_) => numbers!(F32, f32, Store::F32), + Array::I32(_) => numbers!(I32, i32, Store::I32), + Array::U32(_) => numbers!(U32, u32, Store::U32), + Array::U64(_) => numbers!(U64, u64, Store::U64), + Array::Bool(_) => Array::Bool( + (0..len) + .map(|i| pick(i).is_some_and(|(s, r)| matches!(&sources[s].array, Array::Bool(v) if v.get(r)))) + .collect(), + ), + Array::Text(_) => { + let mut builder = TextBuilder::with_capacity(len); + for i in 0..len { + builder.push(pick(i).and_then(|(s, r)| sources[s].text().map(|t| t.get(r))).unwrap_or("")); + } + Array::Text(builder.finish()) + } + Array::Geometry(g) => { + let mut builder = GeometryBuilder::new(g.depth()); + for i in 0..len { + match pick(i).and_then(|(s, r)| sources[s].geometry().map(|g| (g, r))) { + Some((geometry, r)) => builder.push_from(geometry, r), + None => builder.push_empty(), + } + } + Array::Geometry(builder.finish()) + } + }; + let mut bits = BitsBuilder::with_capacity(len); + let mut all = true; + for i in 0..len { + let valid = pick(i).is_some_and(|(s, r)| sources[s].is_valid(r)); + all &= valid; + bits.push(valid); + } + Ok(Values { array, valid: (!all).then(|| bits.finish()) }) + } + + /// Whether `other` holds exactly these values in the same storage, compared where they are stored: + /// floats by their bits, so a NaN equals itself, and no value is made to compare it. + pub(crate) fn same(&self, other: &Values) -> bool { + let len = self.len(); + if other.len() != len || (0..len).any(|i| self.is_valid(i) != other.is_valid(i)) { + return false; + } + let bits = |a: &[f64], b: &[f64]| a.iter().zip(b).all(|(x, y)| x.to_bits() == y.to_bits()); + match (&self.array, &other.array) { + (Array::F64(a), Array::F64(b)) => bits(a, b), + (Array::F32(a), Array::F32(b)) => a.iter().zip(b.iter()).all(|(x, y)| x.to_bits() == y.to_bits()), + (Array::I32(a), Array::I32(b)) => a[..] == b[..], + (Array::U32(a), Array::U32(b)) => a[..] == b[..], + (Array::U64(a), Array::U64(b)) => a[..] == b[..], + (Array::Bool(a), Array::Bool(b)) => (0..len).all(|i| a.get(i) == b.get(i)), + (Array::Text(a), Array::Text(b)) => a.iter().eq(b.iter()), + (Array::Geometry(a), Array::Geometry(b)) => (0..len).all(|i| a.same_row(i, b, i)), + _ => false, + } + } + + /// Whether value `i` and `other`'s value `j` are the same, compared where they are stored: floats by + /// their bits, so a NaN equals itself, and missing values alike; values in different storages + /// differ. + pub(crate) fn same_row(&self, i: usize, other: &Values, j: usize) -> bool { + let valid = self.is_valid(i); + if valid != other.is_valid(j) { + return false; + } + if !valid { + return true; + } + match (&self.array, &other.array) { + (Array::F64(a), Array::F64(b)) => a[i].to_bits() == b[j].to_bits(), + (Array::F32(a), Array::F32(b)) => a[i].to_bits() == b[j].to_bits(), + (Array::I32(a), Array::I32(b)) => a[i] == b[j], + (Array::U32(a), Array::U32(b)) => a[i] == b[j], + (Array::U64(a), Array::U64(b)) => a[i] == b[j], + (Array::Bool(a), Array::Bool(b)) => a.get(i) == b.get(j), + (Array::Text(a), Array::Text(b)) => a.get(i) == b.get(j), + (Array::Geometry(a), Array::Geometry(b)) => a.same_row(i, b, j), + _ => false, + } + } + + /// `parts` one after another, in the first part's storage: what a column's pages make, a copy per + /// part with nothing picked. Every part holds the first's kind. + pub(crate) fn concat(parts: &[&Values]) -> Values { + let first = parts.first().expect("a part"); + debug_assert!(parts.iter().all(|p| p.kind() == first.kind())); + let len = parts.iter().map(|p| p.len()).sum(); + macro_rules! numbers { + ($variant:ident, $t:ty, $store:expr) => {{ + let mut out: Vec<$t> = Vec::with_capacity(len); + for part in parts { + match &part.cast(|x| x as $t, $store).array { + Array::$variant(v) => out.extend_from_slice(v), + _ => unreachable!("cast to the first part's storage"), + } + } + Array::$variant(Buffer::from(out)) + }}; + } + let array = match &first.array { + Array::F64(_) => numbers!(F64, f64, Store::F64), + Array::F32(_) => numbers!(F32, f32, Store::F32), + Array::I32(_) => numbers!(I32, i32, Store::I32), + Array::U32(_) => numbers!(U32, u32, Store::U32), + Array::U64(_) => numbers!(U64, u64, Store::U64), + Array::Bool(_) => { + let mut bits = BitsBuilder::with_capacity(len); + for part in parts { + if let Array::Bool(v) = &part.array { + (0..v.len()).for_each(|i| bits.push(v.get(i))); + } + } + Array::Bool(bits.finish()) + } + Array::Text(_) => { + let mut builder = TextBuilder::with_capacity(len); + for text in parts.iter().filter_map(|p| p.text()) { + (0..text.len()).for_each(|i| builder.push(text.get(i))); + } + Array::Text(builder.finish()) + } + Array::Geometry(g) => { + let mut builder = GeometryBuilder::new(g.depth()); + for geometry in parts.iter().filter_map(|p| p.geometry()) { + (0..geometry.len()).for_each(|i| builder.push_from(geometry, i)); + } + Array::Geometry(builder.finish()) + } + }; + let valid = parts.iter().any(|p| p.valid.is_some()).then(|| { + let mut bits = BitsBuilder::with_capacity(len); + for part in parts { + (0..part.len()).for_each(|i| bits.push(part.is_valid(i))); + } + bits.finish() + }); + Values { array, valid } + } + + /// Numbers converted to `store`; other kinds unchanged. + fn cast(&self, convert: impl Fn(f64) -> T, store: Store) -> Values + where + Buffer: Into, + { + let same = matches!( + (&self.array, store), + (Array::F64(_), Store::F64) + | (Array::F32(_), Store::F32) + | (Array::I32(_), Store::I32) + | (Array::U32(_), Store::U32) + | (Array::U64(_), Store::U64) + ); + if same || self.kind() != Kind::Number { + return self.clone(); + } + let converted = self.map_numbers(|x| convert(x.unwrap_or(0.0))); + Values { array: Buffer::from(converted).into(), valid: self.valid.clone() } + } +} + +#[derive(Clone, Copy)] +enum Store { + F64, + F32, + I32, + U32, + U64, +} + +macro_rules! array_from_buffer { + ($($variant:ident: $t:ty),*) => {$( + impl From> for Array { + fn from(buffer: Buffer<$t>) -> Array { + Array::$variant(buffer) + } + } + )*}; +} + +array_from_buffer!(F64: f64, F32: f32, I32: i32, U32: u32, U64: u64); + +macro_rules! numbers_from { + ($($variant:ident: $t:ty),*) => {$( + impl From> for Values { + fn from(values: Vec<$t>) -> Values { + Values { array: Array::$variant(values.into()), valid: None } + } + } + + impl From<&[$t]> for Values { + fn from(values: &[$t]) -> Values { + Values { array: Array::$variant(values.into()), valid: None } + } + } + + impl From<[$t; N]> for Values { + fn from(values: [$t; N]) -> Values { + Values::from(&values[..]) + } + } + + impl From>> for Values { + fn from(values: Vec>) -> Values { + let valid = Bits::from_fn(values.len(), |i| values[i].is_some()); + let array = Array::$variant(values.iter().map(|v| v.unwrap_or_default()).collect()); + Values { array, valid: (!valid.all()).then_some(valid) } + } + } + )*}; +} + +numbers_from!(F64: f64, F32: f32, I32: i32, U32: u32, U64: u64); + +impl From> for Values { + fn from(values: Vec) -> Values { + Values::from(&values[..]) + } +} + +impl From<&[bool]> for Values { + fn from(values: &[bool]) -> Values { + Values { array: Array::Bool(Bits::from_fn(values.len(), |i| values[i])), valid: None } + } +} + +impl From>> for Values { + fn from(values: Vec>) -> Values { + let valid = Bits::from_fn(values.len(), |i| values[i].is_some()); + let array = Array::Bool(Bits::from_fn(values.len(), |i| values[i] == Some(true))); + Values { array, valid: (!valid.all()).then_some(valid) } + } +} + +fn texts<'a>(texts: impl IntoIterator>) -> Values { + let mut builder = TextBuilder::default(); + let mut valid = BitsBuilder::with_capacity(0); + let mut all = true; + for text in texts { + all &= text.is_some(); + valid.push(text.is_some()); + builder.push(text.unwrap_or("")); + } + Values { array: Array::Text(builder.finish()), valid: (!all).then(|| valid.finish()) } +} + +impl From> for Values { + fn from(values: Vec) -> Values { + texts(values.iter().map(|t| Some(t.as_str()))) + } +} + +impl From> for Values { + fn from(values: Vec<&str>) -> Values { + texts(values.into_iter().map(Some)) + } +} + +impl From<&[&str]> for Values { + fn from(values: &[&str]) -> Values { + texts(values.iter().copied().map(Some)) + } +} + +impl From<&[String]> for Values { + fn from(values: &[String]) -> Values { + texts(values.iter().map(|t| Some(t.as_str()))) + } +} + +impl From<[&str; N]> for Values { + fn from(values: [&str; N]) -> Values { + texts(values.into_iter().map(Some)) + } +} + +impl From>> for Values { + fn from(values: Vec>) -> Values { + texts(values.iter().map(Option::as_deref)) + } +} + +impl From>> for Values { + fn from(values: Vec>) -> Values { + texts(values) + } +} + +fn geometries(depth: u8, values: impl IntoIterator) -> Values { + let mut builder = GeometryBuilder::new(depth); + for value in values { + builder.push_value(&value); + } + Values { array: Array::Geometry(builder.finish()), valid: None } +} + +impl From> for Values { + fn from(points: Vec<[f64; 2]>) -> Values { + Values { array: Array::Geometry(Geometry::from_parts(0, Vec::new(), points).expect("points")), valid: None } + } +} + +impl From>> for Values { + fn from(paths: Vec>) -> Values { + geometries(1, paths.into_iter().map(Value::Path)) + } +} + +impl From>>> for Values { + fn from(parts: Vec>>) -> Values { + geometries(2, parts.into_iter().map(Value::Parts)) + } +} + +impl From>>>> for Values { + fn from(polygons: Vec>>>) -> Values { + geometries(3, polygons.into_iter().map(Value::Polygons)) + } +} + +/// A column of values of one kind, `None` missing, as JSON and JavaScript arrays give them: the first +/// present value decides what the rest are, numbers, booleans, texts, or geometries nesting alike. +/// A column of nothing present is numbers; a missing point is NaN, a missing path or polygon empty. +impl TryFrom>> for Values { + type Error = Error; + + fn try_from(values: Vec>) -> Result { + fn all(values: Vec>, of: impl Fn(Value) -> Option) -> Result>> { + let mixed = || { + Error::invalid( + "a column holds one kind of value: numbers, booleans, texts, or geometries nesting alike", + ) + }; + values.into_iter().map(|v| v.map(|v| of(v).ok_or_else(mixed)).transpose()).collect() + } + let Some(first) = values.iter().flatten().next() else { return Ok(vec![None::; values.len()].into()) }; + Ok(match first { + Value::Number(_) => all(values, |v| if let Value::Number(n) = v { Some(n) } else { None })?.into(), + Value::Bool(_) => all(values, |v| if let Value::Bool(b) = v { Some(b) } else { None })?.into(), + Value::Text(_) => { + let texts_of = all(values, |v| if let Value::Text(t) = v { Some(t) } else { None })?; + texts(texts_of.iter().map(Option::as_deref)) + } + Value::Point(_) => { + let points = all(values, |v| if let Value::Point(p) = v { Some(p) } else { None })?; + points.into_iter().map(|p| p.unwrap_or([f64::NAN; 2])).collect::>().into() + } + Value::Path(_) => { + let paths = all(values, |v| if let Value::Path(p) = v { Some(p) } else { None })?; + paths.into_iter().map(Option::unwrap_or_default).collect::>().into() + } + Value::Parts(_) => { + let parts = all(values, |v| if let Value::Parts(p) = v { Some(p) } else { None })?; + parts.into_iter().map(Option::unwrap_or_default).collect::>().into() + } + Value::Polygons(_) => { + let polygons = all(values, |v| if let Value::Polygons(p) = v { Some(p) } else { None })?; + polygons.into_iter().map(Option::unwrap_or_default).collect::>().into() + } + Value::Row(_) => return Err(Error::invalid("a column names rows as a reference: {reference, ids}")), + }) + } +} + +impl From for Vec> { + fn from(values: Values) -> Vec> { + (0..values.len()).map(|i| values.get(i)).collect() + } +} + +impl std::fmt::Debug for Values { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_list().entries((0..self.len()).map(|i| self.get(i))).finish() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn assemble_scatters_and_converts() { + let base = Values::from(vec![1.0_f64, 2.0, 3.0]); + let source = Values::from(vec![10_i32, 20]); + let from = [None, Some(1), None, Some(0)]; + let out = Values::assemble(&[&base, &source], Picks::Writes { from: &from, kept: 1 }).expect("numbers"); + assert_eq!( + Vec::>::from(out), + vec![Some(Value::Number(1.0)), Some(Value::Number(20.0)), None, Some(Value::Number(10.0))] + ); + } + + #[test] + fn assemble_refuses_another_kind() { + let base = Values::from(vec![1.0_f64]); + let source = Values::from(vec!["a"]); + assert!(Values::assemble(&[&base, &source], Picks::Rows(&[0])).is_err()); + } + + #[test] + fn same_compares_what_is_stored() { + let a = Values::from(vec![Some(1.0_f64), None, Some(f64::NAN)]); + assert!(a.same(&a.slice(0..3)), "a NaN equals itself"); + assert!(!a.same(&Values::from(vec![Some(1.0_f64), Some(0.0), Some(f64::NAN)])), "missing differs"); + assert!(!a.same(&Values::from(vec![1.0_f32, 0.0, 0.0])), "another storage differs"); + let path = |x: f64| Values::from(vec![vec![[0.0, 0.0], [x, 1.0]]]); + assert!(path(2.0).same(&path(2.0))); + assert!(!path(2.0).same(&path(3.0))); + } + + #[test] + fn concat_joins_parts_in_the_first_storage() { + let a = Values::from(vec![Some(1.0_f64), None]); + let b = Values::from(vec![3_i32]); + let joined = Values::concat(&[&a, &b]); + assert_eq!(Vec::>::from(joined), vec![Some(Value::Number(1.0)), None, Some(Value::Number(3.0))]); + let texts = Values::concat(&[&Values::from(vec!["x"]), &Values::from(vec![Some("y"), None])]); + assert_eq!(texts.get(1), Some(Value::Text("y".into()))); + assert_eq!(texts.get(2), None); + } + + #[test] + fn texts_keep_missing() { + let values = Values::from(vec![Some("a"), None, Some("c")]); + assert_eq!(values.get(1), None); + assert_eq!(values.slice(1..3).get(1), Some(Value::Text("c".into()))); + } + + #[test] + fn assemble_gathers_across_sources() { + let a = Values::from(vec!["x", "y"]); + let b = Values::from(vec!["z"]); + let from = [None, None, Some(0)]; + let joined = Values::assemble(&[&a, &b], Picks::Writes { from: &from, kept: 2 }).expect("texts"); + assert_eq!(joined.len(), 3); + assert_eq!(joined.get(2), Some(Value::Text("z".into()))); + } +} diff --git a/crates/latkit/src/derive/graph.rs b/crates/latkit/src/derive/graph.rs new file mode 100644 index 00000000..99091d04 --- /dev/null +++ b/crates/latkit/src/derive/graph.rs @@ -0,0 +1,205 @@ +//! The graph the marks draw: one vertex mark and one edge mark per table, and where edges meet +//! vertices, by their two ends or by the ports naming a net. Layouts link vertices by it, a diagram's +//! wires run along it, and nets' stars join it. + +use crate::data::{Data, Field, Inverse, Name, Reference, Row, Table, Value}; +use crate::expr::cpu::Rows; +use crate::host::Key; +use crate::scene::mark::Style; +use crate::{Edges, Mark, Port, Vertices}; + +/// The vertex mark a table's rows take their places from, and the vertex index of its first row. +pub(crate) struct VertexMark<'a> { + pub(crate) mark: &'a Vertices, + pub(crate) data: &'a Data, + pub(crate) table: &'a Table, + pub(crate) first: usize, +} + +/// The edge mark a table's rows take their paths from. +pub(crate) struct EdgeMark<'a> { + pub(crate) mark: &'a Edges, + pub(crate) data: &'a Data, + pub(crate) table: &'a Table, +} + +/// The vertex marks and edge marks of the scene, one per table: its unnamed mark of the kind, else +/// its first; each vertex mark with the vertex index of its first row. +pub(crate) fn marks<'a>(input: &super::Input<'a>) -> (Vec>, Vec>) { + let (mut vertices, mut edges): (Vec>, Vec>) = (Vec::new(), Vec::new()); + for mark in &input.scene.marks { + let style = mark.style(); + let Some(data) = input.data.iter().find(|d| *d.name() == style.data) else { continue }; + let Some(table) = data.table(&style.table) else { continue }; + match mark { + Mark::Vertices(v) => { + let shown = VertexMark { mark: v, data, table, first: 0 }; + match taken(vertices.iter().map(|vm| &vm.mark.style), style) { + None => vertices.push(shown), + Some(at) if replaces(&vertices[at].mark.style, style) => vertices[at] = shown, + Some(_) => {} + } + } + Mark::Edges(e) => { + let shown = EdgeMark { mark: e, data, table }; + match taken(edges.iter().map(|em| &em.mark.style), style) { + None => edges.push(shown), + Some(at) if replaces(&edges[at].mark.style, style) => edges[at] = shown, + Some(_) => {} + } + } + Mark::Faces(_) | Mark::Lines(_) | Mark::Areas(_) => {} + } + } + let mut first = 0; + for vm in &mut vertices { + vm.first = first; + first += vm.table.len(); + } + (vertices, edges) +} + +/// Which of the marks taken, by their styles, draws `style`'s table already. +fn taken<'s>(mut styles: impl Iterator, style: &Style) -> Option { + styles.position(|s| s.data == style.data && s.table == style.table) +} + +/// Whether the mark of `style` takes its table from the one of `before`: an unnamed mark from a +/// named one. +fn replaces(before: &Style, style: &Style) -> bool { + before.name.is_some() && style.name.is_none() +} + +/// The vertex mark drawing `table` of dataset `data`, which ends and members attach to. +pub(crate) fn drawing(vertex_marks: &[VertexMark<'_>], data: &Name, table: &Name) -> Option { + vertex_marks.iter().position(|vm| vm.data.name() == data && vm.table.name() == table) +} + +/// The position row `row`'s data gives it, if any: its position, else its point geometry. +pub(crate) fn position(mark: &Vertices, rows: &Rows<'_>, row: usize) -> Option<[f64; 2]> { + match &mark.position { + Some([x, y]) => Some([rows.number(x, row)?, rows.number(y, row)?]), + None => match rows.table.value(row, mark.point_field(), f64::INFINITY)? { + Value::Point(p) if p.iter().all(|v| v.is_finite()) => Some(p), + _ => None, + }, + } +} + +/// A row's key in a job: its table and id. +pub(crate) fn key_of(row: &Row) -> Key { + (row.table.clone(), row.id.clone()) +} + +/// What a layout links: each edge's two ends, and each net from its outputs to its inputs, by vertex. +pub(crate) fn links(marks: &[VertexMark<'_>], edge_marks: &[EdgeMark<'_>]) -> Vec<[u32; 2]> { + let codes: Vec> = marks.iter().map(|vm| port_codes(vm.mark)).collect(); + let mut links = Vec::new(); + for em in edge_marks { + let joins = Joins::new(marks, &codes, em); + for row in 0..em.table.len() { + if let Some([a, b]) = joins.ends(row) { + if a != b { + links.push([a as u32, b as u32]); + } + continue; + } + let terminals: Vec<(u32, bool)> = + joins.terminals(marks, row).into_iter().map(|(v, _, output)| (v as u32, output)).collect(); + links.extend(net_links(&terminals)); + } + } + links +} + +/// Where an edge mark's rows meet vertices: the references naming each row's two ends, with the +/// first vertex of the table each names; or, for nets, every port reference naming its rows. +pub(crate) struct Joins<'a> { + ends: Option<[(&'a Reference, usize); 2]>, + ports: Vec>, +} + +/// A port reference naming a net table's rows: the vertex mark, the port's code and whether it is an +/// output, and the rows naming each net. +struct Naming<'a> { + mark: usize, + code: u32, + output: bool, + inverse: &'a Inverse, +} + +impl<'a> Joins<'a> { + pub(crate) fn new(marks: &[VertexMark<'a>], codes: &[Vec], em: &EdgeMark<'a>) -> Joins<'a> { + let table: &'a Table = em.table; + let end = |field: &str| { + let Some(Field::Reference(r)) = table.field_named(field) else { return None }; + let m = drawing(marks, em.data.name(), &r.to)?; + Some((r, marks[m].first)) + }; + if let Some((from, to)) = &em.mark.ends { + return Joins { ends: end(from).zip(end(to)).map(|(a, b)| [a, b]), ports: Vec::new() }; + } + let mut ports = Vec::new(); + for (m, vm) in marks.iter().enumerate().filter(|(_, vm)| vm.data.name() == em.data.name()) { + let vertices: &'a Table = vm.table; + for (k, (name, port)) in vm.mark.ports.iter().enumerate() { + if let Some(Field::Reference(r)) = vertices.field_named(name) + && r.to == *table.name() + { + ports.push(Naming { mark: m, code: codes[m][k], output: port.output, inverse: r.inverse() }); + } + } + } + Joins { ends: None, ports } + } + + /// Row `row`'s two ends, by vertex. + pub(crate) fn ends(&self, row: usize) -> Option<[usize; 2]> { + let [(a, first_a), (b, first_b)] = self.ends?; + Some([first_a + a.target(row)? as usize, first_b + b.target(row)? as usize]) + } + + /// Net row `row`'s terminals: each vertex naming it at a port, the port's code, and whether it is + /// an output. + pub(crate) fn terminals(&self, marks: &[VertexMark<'_>], row: usize) -> Vec<(usize, u32, bool)> { + let mut terminals = Vec::new(); + for naming in &self.ports { + let first = marks[naming.mark].first; + terminals.extend(naming.inverse.of(row).iter().map(|&v| (first + v as usize, naming.code, naming.output))); + } + terminals + } +} + +/// Each port's code on a vertex mark's rows. +pub(crate) fn port_codes(mark: &Vertices) -> Vec { + Port::codes(&mark.ports.iter().map(|(_, port)| port).collect::>()) +} + +/// The links of a net whose terminals are `ends`, each a vertex and whether it drives the net: every +/// driver to its first reader, and its first driver to every reader, so a wide net adds as many links +/// as it has terminals. A net without both drivers and readers runs from its first terminal. +fn net_links(ends: &[(u32, bool)]) -> Vec<[u32; 2]> { + let (mut drivers, mut readers): (Vec, Vec) = (Vec::new(), Vec::new()); + for &(vertex, drives) in ends { + if drives { drivers.push(vertex) } else { readers.push(vertex) } + } + if drivers.is_empty() || readers.is_empty() { + drivers = ends.iter().take(1).map(|e| e.0).collect(); + readers = ends.iter().skip(1).map(|e| e.0).collect(); + } + let (Some(&driver), Some(&reader)) = (drivers.first(), readers.first()) else { return Vec::new() }; + let links = drivers.iter().map(|&d| [d, reader]).chain(readers.iter().skip(1).map(|&r| [driver, r])); + links.filter(|[a, b]| a != b).collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn nets_link_their_drivers_to_their_readers() { + assert_eq!(net_links(&[(0, false), (1, true), (2, false)]), vec![[1, 0], [1, 2]]); + assert_eq!(net_links(&[(4, false), (5, false)]), vec![[4, 5]], "without a driver, the first drives"); + } +} diff --git a/crates/latkit/src/derive/lanes.rs b/crates/latkit/src/derive/lanes.rs new file mode 100644 index 00000000..9be4932c --- /dev/null +++ b/crates/latkit/src/derive/lanes.rs @@ -0,0 +1,182 @@ +//! Lanes: outside a diagram, each edge row's lane among the edges joining the same two vertices, so +//! they bow apart instead of drawing over each other. A lane is data, made from the table's ends +//! alone: the stroke bows in world space by its lane, so it never moves as the camera does. Derived +//! again only when the table's rows or ends change: on the frame while that fits its budget, else in +//! a job; a table whose edges share no ends derives nothing. + +use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet}; + +use super::{Derive, Derived, Input, Jobs, Tables, beside, kept, stamp_of}; +use crate::Mark; +use crate::Pending; +use crate::data::{Field, Ids, Name, Patch, Reference, Table, UNWIRED, Values}; +use crate::host::Job; + +/// Microseconds a row takes to find its lane, by estimate. +const LANE_COST: f64 = 0.06; + +/// What a table's lanes were made from, and a job under way. +type Made = Derived<(), Pending>>; + +#[derive(Default)] +pub(crate) struct Lanes { + tables: Tables, + /// Each table's lanes, made or making. + made: FxHashMap<(Name, Name), Made>, +} + +impl Derive for Lanes { + fn update(&mut self, input: &Input<'_>, jobs: &mut Jobs<'_>) -> bool { + let mut changed = false; + let mut drawn: FxHashSet<(Name, Name)> = FxHashSet::default(); + for mark in &input.scene.marks { + let Mark::Edges(edges) = mark else { continue }; + let Some((from, to)) = &edges.ends else { continue }; + let style = &edges.style; + let Some(table) = input.data(&style.data).and_then(|d| d.table(&style.table)) else { continue }; + let (Some(a), Some(b)) = (reference(table, from), reference(table, to)) else { continue }; + let key = (style.data.clone(), style.table.clone()); + if !drawn.insert(key.clone()) { + continue; + } + let stamp = stamp_of((table.structure, table.order, a.version, b.version)); + let made = self.made.entry(key.clone()).or_default(); + if let Some((landed, bytes)) = made.landed() + && landed == stamp + { + made.make(stamp, ()); + changed |= keep(&mut self.tables, key.clone(), table, answered(&bytes)); + continue; + } + if !made.due(stamp) { + continue; + } + let rows = table.len(); + if jobs.fits((rows as f64 * LANE_COST) as u64) { + made.make(stamp, ()); + changed |= keep(&mut self.tables, key, table, lanes(&a.targets(), &b.targets())); + } else { + made.start(stamp, jobs.spawn(Job::lanes(&a.targets(), &b.targets()))); + } + } + let before = self.tables.len(); + self.tables.retain(|key, _| drawn.contains(key)); + self.made.retain(|key, _| drawn.contains(key)); + changed || self.tables.len() != before + } + + fn busy(&self) -> bool { + self.made.values().any(Derived::busy) + } + + fn tables(&self) -> &Tables { + &self.tables + } + + fn clear(&mut self) { + self.tables.clear(); + self.made.clear(); + } +} + +/// Keeps `lanes` beside `table` as its field `lane`, or drops its lanes when there are none; whether +/// anything changed. +fn keep(tables: &mut Tables, key: (Name, Name), table: &Table, lanes: Option>) -> bool { + match lanes.filter(|l| l.len() == table.len()) { + Some(lanes) => { + let lane = kept("lane", &Values::from(lanes), table, tables.get(&key)); + tables.insert(key, beside(table, [("lane".into(), lane)])); + true + } + None => tables.remove(&key).is_some(), + } +} + +/// The reference field `name` of `table`. +fn reference<'t>(table: &'t Table, name: &str) -> Option<&'t Reference> { + match table.field_named(name)? { + Field::Reference(reference) => Some(reference), + _ => None, + } +} + +/// The lanes a lanes job answered: its table's field `lane`, or none. +fn answered(bytes: &[u8]) -> Option> { + let patch = Patch::from_bytes(bytes).ok()?; + patch.ops.into_iter().find_map(|op| match op { + crate::data::Op::Set(table) => { + let Some(Field::Values(column, _)) = table.field_named("lane") else { return None }; + let pages = column.pages().iter(); + Some(pages.flat_map(|page| (0..page.values.len()).map(|i| page.values.number(i) as f32)).collect()) + } + _ => None, + }) +} + +/// Each row's lane among the rows joining the same two vertices, from the rows' two ends +/// ([`UNWIRED`] where a reference names no row): offsets from the middle, signed so rows joining them +/// either way bow apart. `None` when no two rows share their ends. Counts each pair once, then hands +/// out lanes only to the pairs shared, so it allocates nothing per pair. +pub(crate) fn lanes(from: &[u32], to: &[u32]) -> Option> { + let key = |r: usize| { + let (a, b) = (from[r], to[r]); + (a != UNWIRED && b != UNWIRED && a != b).then(|| u64::from(a.min(b)) << 32 | u64::from(a.max(b))) + }; + let rows = from.len().min(to.len()); + let mut counts: FxHashMap = FxHashMap::with_capacity_and_hasher(rows, FxBuildHasher); + let mut shared = false; + for r in 0..rows { + if let Some(k) = key(r) { + let n = counts.entry(k).or_insert(0); + *n += 1; + shared |= *n > 1; + } + } + if !shared { + return None; + } + counts.retain(|_, n| *n > 1); + let mut taken: FxHashMap = FxHashMap::with_capacity_and_hasher(counts.len(), FxBuildHasher); + Some( + (0..rows) + .map(|r| { + let Some((k, &n)) = key(r).and_then(|k| Some((k, counts.get(&k)?))) else { return 0.0 }; + let next = taken.entry(k).or_insert(0); + let lane = *next as f32 - (n - 1) as f32 / 2.0; + *next += 1; + if from[r] > to[r] { -lane } else { lane } + }) + .collect(), + ) +} + +/// Lanes as a job's answer: a table of every row's lane, or one without rows when there are none. +pub(crate) fn answer(from: &[u32], to: &[u32]) -> Patch { + let lanes = lanes(from, to).unwrap_or_default(); + Patch::new().set(Table::new("lanes", Ids::count(lanes.len() as u32)).field("lane", lanes)) +} + +/// Each of `rows` rows' lane among the rows joining the same two ends, which `ends` names: the +/// sheet's straight wires spread by it. `None` when no two share their ends. +pub(crate) fn spread(rows: usize, ends: impl Fn(usize) -> Option<[usize; 2]>) -> Option> { + let (from, to): (Vec, Vec) = + (0..rows).map(|r| ends(r).map_or((UNWIRED, UNWIRED), |[a, b]| (a as u32, b as u32))).unzip(); + lanes(&from, &to).map(|lanes| lanes.into_iter().map(f64::from).collect()) +} + +#[cfg(test)] +mod tests { + use super::{UNWIRED, lanes}; + + #[test] + fn rows_joining_the_same_ends_bow_apart_either_way() { + // Rows 0, 1, and 3 join vertices 1 and 2, row 3 the other way; row 2 is alone. + let lanes = lanes(&[1, 1, 4, 2, UNWIRED], &[2, 2, 5, 1, 0]).expect("shared ends"); + assert_eq!(lanes, vec![-1.0, 0.0, 0.0, -1.0, 0.0]); + } + + #[test] + fn tables_sharing_no_ends_have_no_lanes() { + assert_eq!(lanes(&[0, 1, 2], &[1, 2, 0]), None); + } +} diff --git a/crates/latkit/src/derive/mod.rs b/crates/latkit/src/derive/mod.rs new file mode 100644 index 00000000..cde5b9fb --- /dev/null +++ b/crates/latkit/src/derive/mod.rs @@ -0,0 +1,492 @@ +//! Derived data: what the view works out rather than is given. Every derivation shares one lifecycle: +//! a stamp of what it reads, so it works again only when that changes; work small enough for the +//! frame done on it, within one budget all derivations share; larger work a host job answering a +//! patch, kept only while what it was asked from still holds; and tables it writes beside the tables +//! marks draw, row for row, which marks read like data. What the GPU works out (the shadow map, +//! normals, segment counts, label placement) follows the same stamps, its answers read back. +//! +//! The derivations: a diagram's sheet (places, sizes, boxes, wires); elsewhere the lanes of edges +//! sharing their ends, the stars of nets, and where the scene has a layout the places of vertex rows +//! without positions; +//! the triangles of every area; and the tiles the camera asks for, which patch datasets the view +//! owns. + +pub(crate) mod graph; +mod lanes; +pub(crate) mod places; +pub(crate) mod pyramid; +mod shapes; +pub(crate) mod sight; +mod stars; +pub(crate) mod tiled; +pub(crate) mod tiles; +mod tiling; + +pub(crate) use lanes::{answer as lanes_answer, spread}; + +use std::hash::{Hash, Hasher}; +use std::sync::{Arc, Mutex}; +use std::task::Waker; + +use rustc_hash::{FxHashMap, FxHasher}; + +use crate::data::{Column, Data, Field, Name, Op, Page, Patch, Table, Value, Values, Version}; +use crate::gpu::readback::Readback; +use crate::gpu::work::{Count, Counters}; +use crate::host::{Host, Job, Key, Request}; +use crate::sheet::Sheet; +use crate::{Pending, Result, Scene, Space}; +use places::Places; +use tiles::TileSets; + +/// A stamp of `inputs`: never 0, which no value is made from. +pub(crate) fn stamp_of(inputs: impl Hash) -> u64 { + let mut hasher = FxHasher::default(); + inputs.hash(&mut hasher); + hasher.finish().max(1) +} + +/// Work that lands later: bytes the GPU reads back, or a job or fetch the host does. +pub(crate) trait Answer { + /// The bytes once they landed, taking them; `None` while they have not. + fn take(&self) -> Option>>; +} + +impl Answer for Readback { + fn take(&self) -> Option>> { + Readback::take(self) + } +} + +impl Answer for Pending> { + fn take(&self) -> Option>> { + Pending::take(self) + } +} + +/// A derived product: its value, the stamp it was made from, and the work under way toward the value +/// of a newer stamp. +pub(crate) struct Derived { + pub(crate) value: T, + stamp: u64, + working: Option<(u64, A)>, +} + +impl Default for Derived { + fn default() -> Self { + Derived { value: T::default(), stamp: 0, working: None } + } +} + +impl Derived { + /// The stamp the value was made from; 0 before it was. + pub(crate) fn stamp(&self) -> u64 { + self.stamp + } + + /// Whether `stamp` is neither what the value was made from nor what work under way is for. + pub(crate) fn due(&self, stamp: u64) -> bool { + stamp != self.stamp && self.working.as_ref().is_none_or(|(s, _)| *s != stamp) + } + + /// Takes `value` as made from `stamp`, dropping any work under way. + pub(crate) fn make(&mut self, stamp: u64, value: T) { + self.value = value; + self.stamp = stamp; + self.working = None; + } + + /// Takes the value as made from `stamp` as it stands, dropping any work under way. + pub(crate) fn mark(&mut self, stamp: u64) { + self.stamp = stamp; + self.working = None; + } + + /// Starts `work` toward the value of `stamp`, replacing any under way. + pub(crate) fn start(&mut self, stamp: u64, work: A) { + self.working = Some((stamp, work)); + } + + /// The bytes of work that landed, and the stamp it was for. Work that failed lands as made, + /// keeping the value, so it is not tried again until what it reads changes. + pub(crate) fn landed(&mut self) -> Option<(u64, Vec)> { + let (stamp, work) = self.working.as_ref()?; + let stamp = *stamp; + let landed = work.take()?; + self.working = None; + let Ok(bytes) = landed else { + self.stamp = stamp; + return None; + }; + Some((stamp, bytes)) + } + + /// Whether work is under way. + pub(crate) fn busy(&self) -> bool { + self.working.is_some() + } +} + +/// Microseconds of work, by estimate, the derivations do on one frame between them; what does not fit +/// goes to the host as jobs. +const FRAME_WORK: u32 = 4000; + +/// The frame's budget of inline work and the host's pool, which every derivation shares. Each job +/// and fetch wakes the view when it lands. +pub(crate) struct Jobs<'a> { + errors: &'a Arc>>, + host: Option<&'a dyn Host>, + waker: &'a Waker, + /// What counts the jobs handed out. + counters: &'a Counters, + /// Microseconds of inline work left this frame, by estimate. + left: u32, +} + +impl<'a> Jobs<'a> { + pub(crate) fn new( + host: Option<&'a dyn Host>, + waker: &'a Waker, + counters: &'a Counters, + errors: &'a Arc>>, + ) -> Jobs<'a> { + Jobs { host, waker, counters, errors, left: FRAME_WORK } + } + + /// Whether work of `cost` microseconds fits what is left of the frame's budget, spending it if so. + pub(crate) fn fits(&mut self, cost: u64) -> bool { + let fits = cost <= u64::from(self.left); + if fits { + self.left -= cost as u32; + } + fits + } + + /// Microseconds of inline work left this frame, by estimate. + pub(crate) fn left(&self) -> u64 { + u64::from(self.left) + } + + /// Spends `cost` microseconds of the budget whether it fits or not: work the frame cannot defer. + pub(crate) fn spend(&mut self, cost: u64) { + self.left = self.left.saturating_sub(cost.min(u64::from(u32::MAX)) as u32); + } + + /// Has the host do `job` off the frame; without a host, at once. + pub(crate) fn spawn(&self, job: Job) -> Pending> { + self.counters.add(Count::Jobs, 1); + let pending = match self.host { + Some(host) => host.spawn(job), + None => Pending::ready(Ok(job.run())), + }; + pending.report_errors(self.errors); + pending.notify(self.waker); + pending + } + + /// Has the host fetch `request`; without a host, nothing can be fetched. + pub(crate) fn fetch(&self, request: &Request) -> Pending> { + let pending = match self.host { + Some(host) => host.fetch(request), + None => Pending::ready(Err(crate::Error::Unsupported("fetching needs a host".into()))), + }; + pending.notify(self.waker); + pending + } +} + +/// What every derivation reads: the scene and its data, the host that measures text, and whether +/// rows are being dragged. Jobs go through the frame's [`Jobs`]. +pub(crate) struct Input<'a> { + pub(crate) scene: &'a Scene, + /// Bumps whenever the scene changes. + pub(crate) scene_version: u64, + pub(crate) data: &'a [Data], + pub(crate) host: Option<&'a dyn Host>, + /// Whether rows are being dragged: what they move derives on the frame, however much. + pub(crate) dragging: bool, +} + +impl Input<'_> { + /// The dataset named `name`. + pub(crate) fn data(&self, name: &str) -> Option<&Data> { + self.data.iter().find(|d| d.name() == name) + } + + /// Hashes what the structure of the scene's marks reads: of each table drawn, its rows and the + /// fields its places, sizes, groups, ports, wires, and nets read. A field only a look reads, such + /// as a value streaming in, changes nothing it hashes. + pub(crate) fn structure(&self, hasher: &mut impl Hasher) { + self.reads(&mut |read| match read { + Read::Rows { data, table, rows } => (data, table, rows.structure, rows.order).hash(hasher), + Read::Field { data, table, name, field, .. } => (data, table, name, field.map(Field::version)).hash(hasher), + }); + } + + /// Hands `read` what the structure of the scene's marks reads, in order: each table drawn, then + /// each field its places, sizes, groups, ports, wires, and nets read. + pub(crate) fn reads<'a>(&'a self, read: &mut impl FnMut(Read<'a>)) { + for mark in &self.scene.marks { + let style = mark.style(); + let Some(rows) = self.data(&style.data).and_then(|d| d.table(&style.table)) else { continue }; + read(Read::Rows { data: &style.data, table: &style.table, rows }); + let own = (&style.data, &style.table); + match mark { + crate::Mark::Vertices(v) => { + match &v.position { + Some([x, y]) => { + self.read_expr(own, x, true, read); + self.read_expr(own, y, true, read); + } + None => self.read_field(own, v.point_field(), read), + } + for size in v.size.iter().flatten().chain(&v.radius) { + self.read_expr(own, &size.expr, true, read); + } + if let Some(label) = &style.label { + self.read_expr(own, &label.text, true, read); + } + for (reference, _) in &v.ports { + self.read_field(own, reference, read); + } + if let Some((members, reference)) = &v.contains { + self.read_field((&style.data, members), reference, read); + } + } + crate::Mark::Edges(e) => { + for name in e.ends.iter().flat_map(|(from, to)| [from, to]).chain(&e.bends) { + self.read_field(own, name, read); + } + if let Some((members, reference)) = &e.joins { + self.read_field((&style.data, members), reference, read); + } + } + crate::Mark::Faces(_) | crate::Mark::Lines(_) | crate::Mark::Areas(_) => {} + } + } + } + + /// Hands `read` every field `expr` of a mark drawing `table` reads: a field of the table itself is + /// one it sizes or places each row by, `own`, unless a domain fits it to every row's. + fn read_expr<'a>( + &'a self, + table: (&'a Name, &'a Name), + expr: &'a crate::Expr, + own: bool, + read: &mut impl FnMut(Read<'a>), + ) { + let own = own && !expr.fits(); + expr.for_each_field(&mut |f| { + let (data, of) = f.of.as_ref().map_or(table, |(d, t)| (d, t)); + let field = self.data(data).and_then(|d| d.table(of)).and_then(|t| t.field_named(&f.name)); + read(Read::Field { data, table: of, name: f.name.as_str(), field, own: own && f.of.is_none() }); + }); + } + + /// Hands `read` field `name` of `table`. + fn read_field<'a>(&'a self, (data, table): (&'a Name, &'a Name), name: &'a str, read: &mut impl FnMut(Read<'a>)) { + let field = self.data(data).and_then(|d| d.table(table)).and_then(|t| t.field_named(name)); + read(Read::Field { data, table, name, field, own: false }); + } +} + +/// What the structure of the scene's marks reads. +pub(crate) enum Read<'a> { + /// A table a mark draws: its rows. + Rows { data: &'a Name, table: &'a Name, rows: &'a Table }, + /// A field: whether it exists, and as what; and whether it is `own`, a value of a vertex mark's + /// own table that sizes or places each row by that row's value alone. + Field { data: &'a Name, table: &'a Name, name: &'a str, field: Option<&'a Field>, own: bool }, +} + +/// Derived tables, by the dataset and table each stands beside. +pub(crate) type Tables = FxHashMap<(Name, Name), Table>; + +/// One derivation: what it reads, stamped; what it works out, on the frame or as jobs; and the tables +/// it writes. +pub(crate) trait Derive { + /// Brings what it derives up to `input`, handing `jobs` what the frame cannot afford; whether its + /// tables changed. + fn update(&mut self, input: &Input<'_>, jobs: &mut Jobs<'_>) -> bool; + + /// Whether work it asked for is under way. + fn busy(&self) -> bool; + + /// Whether what it derived is final: nothing it writes stands in for work under way. Rows + /// standing where they were until a layout lands, elbows until routes land, earlier triangles + /// until shapes land, and straight edges until lanes land all stand in. + fn complete(&self) -> bool { + !self.busy() + } + + /// The tables it derives. + fn tables(&self) -> &Tables; + + /// Forgets what it derived: its space no longer asks for it. + fn clear(&mut self); + + /// Failures to tell since last asked, such as texts its host could not measure. + fn take_errors(&mut self) -> Vec { + Vec::new() + } +} + +/// Every derivation of a view, run in order each frame with one budget. +#[derive(Default)] +pub(crate) struct Derivations { + /// A diagram's sheet. + pub(crate) sheet: Sheet, + /// Elsewhere, the lanes of edges sharing their ends. + lanes: lanes::Lanes, + /// Elsewhere, where the scene has a layout, the places of vertex rows without positions. + places: Places, + /// Elsewhere, the stars of nets joining vertex rows. + stars: stars::Stars, + shapes: shapes::Shapes, + /// The tiles the camera asks for, as datasets the view owns. + pub(crate) tiles: TileSets, + /// What the view draws of each dataset it draws in part. + pub(crate) tiled: tiled::Tiled, +} + +/// The derived tables beside one drawn table: the sheet's or the lanes', then the shapes'. +pub(crate) type Beside<'a> = [Option<&'a Table>; 2]; + +impl Derivations { + /// Brings every derivation up to `input`, spending what the tiles left of the frame's `jobs`; + /// whether any table changed. + pub(crate) fn update(&mut self, input: &Input<'_>, jobs: &mut Jobs<'_>) -> bool { + let mut changed = if matches!(input.scene.space, Space::Diagram(_)) { + self.lanes.clear(); + self.places.clear(); + self.stars.clear(); + self.sheet.update(input, jobs) + } else { + self.sheet.clear(); + let placed = self.places.update(input, jobs); + self.lanes.update(input, jobs) | placed | self.stars.update(input, self.places.tables()) + }; + changed |= self.shapes.update(input, jobs); + changed + } + + /// Lays every vertex row without a position out again: a diagram's sheet, or elsewhere the + /// places. + pub(crate) fn arrange(&mut self, diagram: bool) { + if diagram { self.sheet.arrange() } else { self.places.arrange() } + } + + /// What the last arranging laid out, once it landed: each row placed, and where, in the + /// space's coordinates. + pub(crate) fn take_arranged(&mut self) -> Option> { + self.sheet.take_arranged().or_else(|| self.places.take_arranged()) + } + + /// Whether everything derived is final: no layout, route, lane, or shape job stands in, no tile + /// draws its ancestor, and no table drawn in part draws its first sample. + pub(crate) fn complete(&self) -> bool { + self.sheet.complete() + && self.lanes.complete() + && self.places.complete() + && self.shapes.complete() + && self.tiles.complete() + && self.tiled.complete() + } + + /// Whether shapes are being triangulated or bent: until they land, marks draw the ones before. + pub(crate) fn shaping(&self) -> bool { + self.shapes.busy() + } + + /// Failures every derivation has to tell since last asked. + pub(crate) fn take_errors(&mut self) -> Vec { + let mut errors = self.sheet.take_errors(); + errors.extend(self.places.take_errors()); + errors.extend(self.tiles.take_errors()); + errors + } + + /// The derived tables beside table `table` of dataset `data`. + pub(crate) fn beside(&self, data: &Name, table: &Name) -> Beside<'_> { + let key = (data.clone(), table.clone()); + let first = [self.sheet.tables(), self.places.tables(), self.stars.tables(), self.lanes.tables()] + .into_iter() + .find_map(|tables| tables.get(&key)); + [first, self.shapes.tables().get(&key)] + } +} + +/// A table beside `source`, row for row, holding `fields`. +pub(crate) fn beside(source: &Table, fields: impl IntoIterator) -> Table { + let mut table = Table { + name: source.name.clone(), + ids: source.ids.clone(), + index: source.index.clone(), + fields: Vec::new(), + structure: source.structure, + order: source.order, + }; + for (name, field) in fields { + table.insert(name, field); + } + table +} + +/// Field `name` of a table beside `source`, holding `values`: `before`'s own while it holds exactly +/// them, so nothing uploads again; else a column keeping each of `before`'s pages that holds what its +/// page would, so only the pages that changed upload and evaluate again. +pub(crate) fn kept(name: &str, values: &Values, source: &Table, before: Option<&Table>) -> Field { + let fresh = Column::new(values); + let old = before.filter(|b| b.structure == source.structure).and_then(|b| match b.field_named(name) { + Some(Field::Values(column, version)) if column.len() == fresh.len() => Some((column, *version)), + _ => None, + }); + let Some((column, version)) = old else { return Field::Values(fresh, Version::next()) }; + let pages: Vec = fresh + .pages() + .iter() + .zip(column.pages()) + .map(|(new, old)| if new.values.same(&old.values) { old.clone() } else { new.clone() }) + .collect(); + if pages.iter().zip(column.pages()).all(|(page, old)| page.id == old.id) { + return Field::Values(column.clone(), version); + } + Field::Values(Column::of_pages(pages, column.like()), Version::next()) +} + +/// The values `fields` an answer's patch writes for each row it names, by its key. +pub(crate) fn answers(bytes: &[u8], fields: &[&str]) -> Vec<(Key, Vec>)> { + let Ok(patch) = Patch::from_bytes(bytes) else { return Vec::new() }; + let mut out = Vec::new(); + for op in patch.ops { + let Op::Set(table) = op else { continue }; + for row in 0..table.len() { + let Some(id) = table.ids.id(row) else { continue }; + let values = fields.iter().map(|f| table.value(row, f, f64::INFINITY)).collect(); + out.push(((table.name.clone(), id), values)); + } + } + out +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::data::PAGE_ROWS; + + #[test] + fn kept_keeps_the_pages_that_hold_the_same() { + let rows = PAGE_ROWS + 10; + let source = Table::new("T", crate::Ids::count(rows as u32)); + let numbers = |changed: f64| { + Values::from((0..rows).map(|r| if r == rows - 1 { changed } else { 1.0 }).collect::>()) + }; + let first = beside(&source, [(Name::from("x"), kept("x", &numbers(1.0), &source, None))]); + let same = kept("x", &numbers(1.0), &source, Some(&first)); + assert_eq!(same.version(), first.field_named("x").expect("x").version(), "nothing changed"); + let Field::Values(before, _) = first.field_named("x").expect("x") else { panic!("values") }; + let Field::Values(after, _) = kept("x", &numbers(2.0), &source, Some(&first)) else { panic!("values") }; + assert_eq!(after.pages()[0].id, before.pages()[0].id, "the first page held the same"); + assert_ne!(after.pages()[1].id, before.pages()[1].id, "the last page changed"); + } +} diff --git a/crates/latkit/src/derive/places.rs b/crates/latkit/src/derive/places.rs new file mode 100644 index 00000000..156e0688 --- /dev/null +++ b/crates/latkit/src/derive/places.rs @@ -0,0 +1,182 @@ +//! Places outside diagrams: where a vertex row without a position stands on a plane or the earth, +//! by the scene's layout. Rows whose data positions them pin the layout, and links are the edges +//! between them, so a row without coordinates stands among its neighbors; gaps are in the space's +//! units. As on a diagram's sheet, a place persists by row, layouts place only rows without one +//! until arranging lays every row without a position out again, and the layout is a host job. The +//! places are a table beside each vertex table: its rows' positions, given or laid out, which the +//! vertex marks read. + +use rustc_hash::FxHashMap; + +use super::graph::{key_of, links, marks, position}; +use super::{Derive, Input, Jobs, Tables, answers, beside, kept}; +use crate::data::{Name, Row, Value, Values}; +use crate::expr::cpu::Rows; +use crate::host::{Job, Key, Placement}; +use crate::{Layout, Pending}; + +#[derive(Default)] +pub(crate) struct Places { + tables: Tables, + /// Where layouts placed rows without positions, kept by row. + laid: FxHashMap, + /// What the tables were last made from. + stamp: u64, + /// Bumps when places start over, so layouts asked before are dropped. + generation: u64, + /// Whether every row without a position is to be laid out again. + arranging: bool, + /// What the last arranging laid out, until the view takes it. + arranged: Option>, + placing: Option, + /// Bumps whenever an answer lands. + landed: u64, +} + +/// A layout under way: the generation it was asked in, and the row each key it answers names. +struct Placing { + pending: Pending>, + generation: u64, + rows: FxHashMap, +} + +impl Derive for Places { + fn update(&mut self, input: &Input<'_>, jobs: &mut Jobs<'_>) -> bool { + if matches!(input.scene.layout, Layout::None) { + let had = !self.tables.is_empty(); + self.clear(); + if self.arranging { + self.arranging = false; + self.arranged = Some(Vec::new()); + } + return had; + } + let mut changed = false; + // A job its host does at once is taken before the frame draws. + for _ in 0..4 { + self.settle(); + let mut hasher = rustc_hash::FxHasher::default(); + std::hash::Hash::hash(&(input.scene_version, self.landed, self.generation), &mut hasher); + input.structure(&mut hasher); + let stamp = std::hash::Hasher::finish(&hasher).max(1); + if stamp == self.stamp { + break; + } + self.stamp = stamp; + self.build(input, jobs); + changed = true; + } + changed + } + + fn busy(&self) -> bool { + self.placing.is_some() + } + + fn tables(&self) -> &Tables { + &self.tables + } + + /// Forgets the tables but keeps the places: a scene with a layout again finds its rows where they + /// stood. + fn clear(&mut self) { + self.tables.clear(); + self.stamp = 0; + } +} + +impl Places { + /// Lays every row without a position out again. + pub(crate) fn arrange(&mut self) { + self.arranging = true; + self.placing = None; + self.generation += 1; + self.stamp = 0; + } + + /// What the last arranging laid out, once it landed: each row placed, and where. + pub(crate) fn take_arranged(&mut self) -> Option> { + self.arranged.take() + } + + fn settle(&mut self) { + let Some(answer) = self.placing.as_ref().and_then(|p| p.pending.take()) else { return }; + let placing = self.placing.take().expect("a layout under way"); + if placing.generation == self.generation { + let mut placed = Vec::new(); + for (key, values) in answer.map(|bytes| answers(&bytes, &["x", "y"])).unwrap_or_default() { + if let (Some(row), [Some(Value::Number(x)), Some(Value::Number(y))]) = + (placing.rows.get(&key), &values[..]) + { + // The plane and the earth run y up, as layouts do. + self.laid.insert(row.clone(), [*x, *y]); + placed.push((row.clone(), [*x, *y])); + } + } + if std::mem::take(&mut self.arranging) { + self.arranged = Some(placed); + } + } + self.landed += 1; + } + + /// Writes each vertex table's positions, asking the layout for the rows without one. + fn build(&mut self, input: &Input<'_>, jobs: &Jobs<'_>) { + let (vertex_marks, edge_marks) = marks(input); + let mut keys = Vec::new(); + let mut pins = Vec::new(); + for vm in &vertex_marks { + let rows = Rows::new(vm.table, input.data); + for row in 0..vm.table.len() { + let id = vm.table.ids.id(row).expect("every row has an id"); + keys.push(Row { data: vm.data.name().clone(), table: vm.table.name().clone(), id }); + pins.push(position(vm.mark, &rows, row)); + } + } + let arranging = self.arranging; + let wanted = |i: usize| pins[i].is_none() && (arranging || !self.laid.contains_key(&keys[i])); + if self.placing.is_none() && (0..keys.len()).any(wanted) { + let pinned: Vec> = (0..keys.len()) + .map(|i| pins[i].or_else(|| (!arranging).then(|| self.laid.get(&keys[i]).copied()).flatten())) + .collect(); + let mut rows = FxHashMap::default(); + let job_keys: Vec> = (0..keys.len()) + .map(|i| { + let key = key_of(&keys[i]); + (wanted(i) && rows.insert(key.clone(), keys[i].clone()).is_none()).then_some(key) + }) + .collect(); + let (sizes, groups, pads) = + (vec![[0.0; 2]; keys.len()], vec![None; keys.len()], vec![[0.0; 4]; keys.len()]); + let links = links(&vertex_marks, &edge_marks); + let placement = Placement { + sizes: &sizes, + pinned: &pinned, + groups: &groups, + pads: &pads, + links: &links, + keys: &job_keys, + }; + let pending = jobs.spawn(Job::layout(&input.scene.layout, &placement)); + self.placing = Some(Placing { pending, generation: self.generation, rows }); + } else if self.arranging && self.placing.is_none() { + // Nothing to lay out: the arranging is done as asked. + self.arranging = false; + self.arranged = Some(Vec::new()); + } + let mut tables = Tables::default(); + let mut at = 0; + for vm in &vertex_marks { + let own = at..at + vm.table.len(); + at = own.end; + let place = |i: usize| pins[i].or_else(|| self.laid.get(&keys[i]).copied()); + let column = |k: usize| Values::from(own.clone().map(|i| place(i).map(|p| p[k])).collect::>()); + let key: (Name, Name) = (vm.data.name().clone(), vm.table.name().clone()); + let before = self.tables.get(&key); + let fields = [("x", column(0)), ("y", column(1))] + .map(|(name, values)| (Name::from(name), kept(name, &values, vm.table, before))); + tables.insert(key, beside(vm.table, fields)); + } + self.tables = tables; + } +} diff --git a/crates/latkit/src/derive/pyramid.rs b/crates/latkit/src/derive/pyramid.rs new file mode 100644 index 00000000..908e95cc --- /dev/null +++ b/crates/latkit/src/derive/pyramid.rs @@ -0,0 +1,732 @@ +//! Pyramids: a table's rows grouped into tiles by the coarsest level each shows at, worked out in a +//! job. Each level splits the tiles above it four ways, and each tile holds a grid of cells, a row to +//! a cell, so no tile holds more rows than its grid has cells. Rows land by priority: each at the +//! coarsest level where its cell is free, so what matters more shows from farther out, and rows +//! crowding one cell wait for a finer level, where they spread over cells of their own. A row never +//! lands finer than its size allows, so its tile grown by half its own size holds it whole. An edge +//! lands by its own priority, in the cell of its middle, and edges joining the same two vertices land +//! together; what draws an edge draws its ends with it. A table drawn whole by priority is one tile, +//! its rows in priority order. + +use std::ops::Range; +use std::sync::Arc; + +use rustc_hash::{FxHashMap, FxHashSet}; + +use super::sight::{Domain, Region, Sight, TILE_PX, meets}; +use crate::data::{Field, Ids, Op, Patch, Table}; +use crate::tiles::TileKey; + +/// Cells across a tile's grid, as a shift: a tile holds at most `4^GRID_BITS` rows of its level. +pub(crate) const GRID_BITS: u32 = 7; +/// The finest level. +pub(crate) const MAX_LEVEL: u8 = 24; +/// A level no row has landed at yet. +const NEVER: u8 = u8::MAX; +/// Tiles a camera may ask a pyramid for at most: past it, tiles stop splitting. +const MAX_TILES: usize = 1024; + +/// What a pyramid job places: tables of rows in a square of their space. +#[derive(Clone, Debug)] +pub(crate) struct Leveling { + pub(crate) domain: Domain, + /// The tables, every table an edge table's ends name before it. + pub(crate) tables: Vec, +} + +/// Where a table's rows lie, in position units: none where nothing places them, a point each, or the +/// box a geometry spans (west, south, east, north). NaN places nothing. Single precision places a +/// row within a centimeter on the earth, finer than any tile's cell. +#[derive(Clone, Debug, Default)] +pub(crate) enum Places { + #[default] + None, + Points(Arc<[[f32; 2]]>), + Boxes(Arc<[[f32; 4]]>), +} + +/// One table a pyramid job places. +#[derive(Clone, Debug, Default)] +pub(crate) struct Placing { + pub(crate) rows: u32, + /// Whether its rows land in tiles by level; else every row is one tile, in priority order. + pub(crate) leveled: bool, + /// Whether the answer holds its pyramid: a table placed only for the edges ending at it is not. + pub(crate) answered: bool, + pub(crate) places: Places, + /// Each row's priority, higher first; none where rows are alike. + pub(crate) priority: Arc<[f32]>, + /// For a table placed by its ends, the table they name and each end's rows there. + pub(crate) ends: Option<(u32, Vec>)>, +} + +/// Where each row of `places` lies across `domain`'s square, fixed point (a turn of `u32` spans it, +/// from the west and from the north), and half its size alike; nothing where it lies nowhere. +fn anchored(places: &Places, domain: &Domain) -> (Vec<[u32; 2]>, Vec) { + let fixed = |u: f64| (u.clamp(0.0, 1.0) * 4_294_967_295.0) as u32; + match places { + Places::None => (Vec::new(), Vec::new()), + Places::Points(points) => { + let anchors = points + .iter() + .map(|p| p.map(f64::from)) + .map(|p| if p.iter().all(|v| v.is_finite()) { domain.unit(p).map(fixed) } else { [0, 0] }) + .collect(); + (anchors, Vec::new()) + } + Places::Boxes(boxes) => boxes + .iter() + .map(|b| { + let b = b.map(f64::from); + if b.iter().any(|v| !v.is_finite()) || b[0] > b[2] { + return ([0, 0], 0); + } + let (lo, hi) = (domain.unit([b[0], b[1]]), domain.unit([b[2], b[3]])); + let center = [lo[0].midpoint(hi[0]), lo[1].midpoint(hi[1])]; + (center.map(fixed), fixed((hi[0] - lo[0]).abs().max((hi[1] - lo[1]).abs()) / 2.0)) + }) + .unzip(), + } +} + +/// The pyramid of each table a job answered for, by its place among the tables asked, with where +/// each row lies across the square and how far it reaches. +pub(crate) fn answer(leveling: &Leveling) -> Patch { + let wraps = leveling.domain == Domain::Earth; + let mut anchors: Vec> = Vec::with_capacity(leveling.tables.len()); + let mut patch = Patch::new(); + for (i, table) in leveling.tables.iter().enumerate() { + let n = table.rows as usize; + let (own_anchors, extents, floor, pairs) = if let Some((target, ends)) = &table.ends { + let Some(at) = anchors.get(*target as usize) else { return Patch::new() }; + let (own, extents) = by_ends(ends, at, wraps, n); + // A row with an end naming no row draws nothing: it lands only at the finest level. + let floor = (0..n) + .map(|r| { + let wired = ends.iter().all(|end| end.get(r).is_some_and(|&t| (t as usize) < at.len())); + if wired { 0 } else { NEVER } + }) + .collect(); + let pairs = (ends.len() == 2).then(|| pairs(&ends[0], &ends[1])); + (own, extents, floor, pairs) + } else { + let (own, extents) = anchored(&table.places, &leveling.domain); + (own, extents, vec![0; n], None) + }; + let leveled = table.leveled && own_anchors.len() == n; + let sorted = if leveled { along(&own_anchors) } else { Vec::new() }; + let ranks = ranks(&table.priority, n); + let level = if leveled { place(&sorted, &extents, &ranks, &floor, pairs.as_deref()) } else { vec![0; n] }; + if table.answered { + let (order, tiles) = if leveled { + tiled(&sorted, &own_anchors, &extents, &ranks, &level) + } else { + let mut order: Vec = (0..table.rows).collect(); + order.sort_unstable_by_key(|&r| ranks[r as usize]); + (order, vec![(pack(TileKey { z: 0, x: 0, y: 0 }), table.rows, u32::MAX)]) + }; + let (keys, (ends, reaches)): (Vec, (Vec, Vec)) = + tiles.into_iter().map(|(k, e, r)| (k, (e, r))).unzip(); + patch = patch + .set( + Table::new(format!("tiles{i}"), Ids::count(keys.len() as u32)) + .field("key", keys) + .field("end", ends) + .field("reach", reaches), + ) + .set(Table::new(format!("order{i}"), Ids::count(order.len() as u32)).field("row", order)); + if leveled { + let (u, v): (Vec, Vec) = own_anchors.iter().map(|a| (a[0], a[1])).unzip(); + let mut placed = Table::new(format!("anchors{i}"), Ids::count(n as u32)).field("u", u).field("v", v); + if !extents.is_empty() { + placed = placed.field("extent", extents.clone()); + } + patch = patch.set(placed); + } + } + anchors.push(own_anchors); + } + patch +} + +/// Where each of `n` rows placed by `ends` lies, among rows anchored at `at`: the middle of the box +/// its ends span, and half that box's size. An end naming no row anchors nothing. +fn by_ends(ends: &[Arc<[u32]>], at: &[[u32; 2]], wraps: bool, n: usize) -> (Vec<[u32; 2]>, Vec) { + let mut anchors = Vec::with_capacity(n); + let mut extents = Vec::with_capacity(n); + for r in 0..n { + let wired = !ends.is_empty() && ends.iter().all(|end| end.get(r).is_some_and(|&t| (t as usize) < at.len())); + if !wired { + anchors.push([0, 0]); + extents.push(0); + continue; + } + // The box of offsets from the end of the lowest row, the short way round where the square + // wraps: the same whichever way the row joins its ends. + let first = at[ends.iter().map(|end| end[r]).min().unwrap_or(0) as usize]; + let (mut lo, mut hi) = ([0_i64; 2], [0_i64; 2]); + for end in ends { + let t = at[end[r] as usize]; + let du = if wraps { + i64::from(t[0].wrapping_sub(first[0]) as i32) + } else { + i64::from(t[0]) - i64::from(first[0]) + }; + let dv = i64::from(t[1]) - i64::from(first[1]); + lo = [lo[0].min(du), lo[1].min(dv)]; + hi = [hi[0].max(du), hi[1].max(dv)]; + } + let mid = [lo[0].midpoint(hi[0]), lo[1].midpoint(hi[1])]; + let u = if wraps { + first[0].wrapping_add(mid[0] as i32 as u32) + } else { + (i64::from(first[0]) + mid[0]).clamp(0, i64::from(u32::MAX)) as u32 + }; + let v = (i64::from(first[1]) + mid[1]).clamp(0, i64::from(u32::MAX)) as u32; + anchors.push([u, v]); + extents.push(((hi[0] - lo[0]).max(hi[1] - lo[1]) / 2).min(i64::from(u32::MAX)) as u32); + } + (anchors, extents) +} + +/// For each row, the next row joining the same two vertices, round to itself: a cycle per pair. Such +/// rows share their anchor, so they lie side by side along the curve. +fn mates(sorted: &[(u64, u32)], pairs: &[u64]) -> Vec { + let mut mates: Vec = (0..sorted.len() as u32).collect(); + let mut i = 0; + while i < sorted.len() { + let mut j = i + 1; + while j < sorted.len() && sorted[j].0 == sorted[i].0 { + j += 1; + } + if j - i > 1 { + let mut alike: Vec = sorted[i..j].iter().map(|&(_, r)| r).collect(); + alike.sort_unstable_by_key(|&r| pairs[r as usize]); + let mut k = 0; + while k < alike.len() { + let pair = pairs[alike[k] as usize]; + let end = k + alike[k..].partition_point(|&r| pairs[r as usize] == pair); + for g in k..end { + mates[alike[g] as usize] = alike[if g + 1 < end { g + 1 } else { k }]; + } + k = end; + } + } + i = j; + } + mates +} + +/// Each row's pair of ends, the same whichever way it joins them. +fn pairs(from: &[u32], to: &[u32]) -> Vec { + from.iter().zip(to).map(|(&a, &b)| u64::from(a.min(b)) << 32 | u64::from(a.max(b))).collect() +} + +/// A hash of `row`, for breaking ties evenly. +fn tie(row: u32) -> u32 { + (u64::from(row).wrapping_mul(0x9E37_79B9_7F4A_7C15) >> 32) as u32 +} + +/// Each of `n` rows' rank, higher first: its priority, missing lowest, then the hash of its place, +/// so equals spread evenly. +fn ranks(priority: &[f32], n: usize) -> Vec { + (0..n) + .map(|r| { + let p = priority.get(r).copied().filter(|p| !p.is_nan()).map_or(0, |p| { + let bits = p.to_bits(); + if bits >> 31 == 1 { !bits } else { bits | 0x8000_0000 } + }); + u64::from(p) << 32 | u64::from(tie(r as u32)) + }) + .collect() +} + +/// Rows along the curve, by their place on it. +fn along(anchors: &[[u32; 2]]) -> Vec<(u64, u32)> { + let mut sorted: Vec<(u64, u32)> = anchors.iter().enumerate().map(|(r, &a)| (morton(a), r as u32)).collect(); + sorted.sort_unstable_by_key(|&(m, _)| m); + sorted +} + +/// The finest level whose tile, grown by half its size, holds a row reaching `extent` from its +/// anchor. +fn fit(extent: u32) -> u8 { + (0..=MAX_LEVEL).rev().find(|&z| u64::from(extent) <= 1_u64 << (31 - u32::from(z))).unwrap_or(0) +} + +/// `x`'s bits spread to every other bit. +fn spread_bits(x: u32) -> u64 { + let mut x = u64::from(x); + x = (x | (x << 16)) & 0x0000_FFFF_0000_FFFF; + x = (x | (x << 8)) & 0x00FF_00FF_00FF_00FF; + x = (x | (x << 4)) & 0x0F0F_0F0F_0F0F_0F0F; + x = (x | (x << 2)) & 0x3333_3333_3333_3333; + (x | (x << 1)) & 0x5555_5555_5555_5555 +} + +/// The point's place along the curve that visits every cell of a level before the next cell of the +/// level above: cells at every level are runs of it. +fn morton([u, v]: [u32; 2]) -> u64 { + spread_bits(u) | spread_bits(v) << 1 +} + +/// The tile at level `z` holding a point anchored at `anchor`. +fn tile_of(anchor: [u32; 2], z: u8) -> TileKey { + let shift = 32 - u32::from(z); + let at = |c: u32| if shift >= 32 { 0 } else { c >> shift }; + TileKey { z, x: at(anchor[0]), y: at(anchor[1]) } +} + +/// `cover` grown to hold tile `key`: a box from the west and the north, fixed point. +fn covering(cover: [u64; 4], key: TileKey) -> [u64; 4] { + let shift = 32 - u32::from(key.z); + let (x, y) = (u64::from(key.x) << shift, u64::from(key.y) << shift); + let size = 1_u64 << shift; + [cover[0].min(x), cover[1].min(y), cover[2].max(x + size), cover[3].max(y + size)] +} + +/// Whether a row anchored at `anchor`, reaching `extent` from it, reaches into `cover`. +pub(crate) fn reaches(cover: &[u64; 4], anchor: [u32; 2], extent: u32) -> bool { + let (u, v, e) = (u64::from(anchor[0]), u64::from(anchor[1]), u64::from(extent)); + u + e >= cover[0] && u.saturating_sub(e) < cover[2] && v + e >= cover[1] && v.saturating_sub(e) < cover[3] +} + +/// A tile as a job's answer numbers it: in 53 bits, so a number holds it exactly. +pub(crate) fn pack(key: TileKey) -> u64 { + u64::from(key.z) << 48 | u64::from(key.x) << 24 | u64::from(key.y) +} + +fn unpack(key: u64) -> TileKey { + TileKey { z: (key >> 48) as u8, x: ((key >> 24) & 0xFF_FFFF) as u32, y: (key & 0xFF_FFFF) as u32 } +} + +/// The level each row lands at: rows in each cell of each level, coarsest first, give way by rank; a +/// row lands at the first level where it outranks every row left in its cell, no coarser than +/// `floor`, at the finest its size allows when it has not landed by then. +/// +/// Rows along the curve are taken in runs, each the rows left in one cell. While a run stays in one +/// cell level after level, those levels take its highest rows in rank order at once; where it +/// spreads over several cells, each cell's rows go on as a run of their own. So a crowd sharing a +/// cell for many levels costs its size once, not once a level. +fn place(sorted: &[(u64, u32)], extents: &[u32], ranks: &[u64], floor: &[u8], pairs: Option<&[u64]>) -> Vec { + let n = sorted.len(); + let fits: Vec = (0..n).map(|r| extents.get(r).map_or(MAX_LEVEL, |&e| fit(e))).collect(); + let mates = pairs.map(|pairs| mates(sorted, pairs)).unwrap_or_default(); + let mut level = vec![NEVER; n]; + let mut work: Vec<(u64, u32)> = sorted.to_vec(); + let mut runs: Vec<(usize, usize, u8)> = vec![(0, n, 0)]; + let mut scratch: Vec<(u64, u32)> = Vec::new(); + let mut forced: Vec = Vec::new(); + // Lands row `r` at level `l`, with the rows joining the same two vertices. + let land = |r: u32, l: u8, level: &mut [u8]| { + level[r as usize] = l; + let mut m = mates.get(r as usize).copied().unwrap_or(r); + while m != r { + if level[m as usize] == NEVER { + level[m as usize] = l; + } + m = mates[m as usize]; + } + }; + while let Some((a, mut b, mut z)) = runs.pop() { + while a < b && z <= MAX_LEVEL { + let (first, last) = (work[a].0, work[b - 1].0); + let common = if first == last { 64 } else { (first ^ last).leading_zeros() }; + // The finest level whose cells hold the whole run. + let single = i64::from(common / 2) - i64::from(GRID_BITS); + if single < i64::from(z) { + // The run spreads over several cells of this level: each goes on alone. + let shift = 2 * (32 - u32::from(z) - GRID_BITS); + let mut i = a; + while i < b { + let cell = work[i].0 >> shift; + let j = i + work[i..b].partition_point(|&(m, _)| m >> shift <= cell); + runs.push((i, j, z)); + i = j; + } + b = a; + break; + } + let deepest = single.min(i64::from(MAX_LEVEL)) as u8; + // One row a level, in rank order: for one level the highest, for more a heap of them. + if deepest == z { + let best = work[a..b] + .iter() + .filter(|&&(_, r)| floor[r as usize] == 0) + .max_by_key(|&&(_, r)| ranks[r as usize]) + .map(|&(_, r)| r); + if let Some(r) = best { + land(r, z, &mut level); + } + } else { + scratch.clear(); + scratch.extend( + work[a..b].iter().map(|&(_, r)| (ranks[r as usize], r)).filter(|&(_, r)| floor[r as usize] == 0), + ); + let mut heap = std::collections::BinaryHeap::from(std::mem::take(&mut scratch)); + for l in z..=deepest { + // A row too large for this level lands where its size says, below. + while let Some((_, r)) = heap.pop() { + if level[r as usize] == NEVER && fits[r as usize] >= l { + land(r, l, &mut level); + break; + } + } + } + scratch = heap.into_vec(); + } + // Rows no finer level holds land where their size says. + if !extents.is_empty() { + forced.clear(); + forced.extend(work[a..b].iter().map(|&(_, r)| r).filter(|&r| fits[r as usize] <= deepest)); + for &r in &forced { + if level[r as usize] == NEVER { + level[r as usize] = fits[r as usize].max(z); + } + } + } + // What is left goes on, along the curve, a level finer. + let mut kept = a; + for i in a..b { + if level[work[i].1 as usize] == NEVER { + work[kept] = work[i]; + kept += 1; + } + } + b = kept; + z = deepest + 1; + } + // Rows no level held, as rows naming no vertex, land at the finest. + for &(_, r) in &work[a..b] { + if level[r as usize] == NEVER { + level[r as usize] = MAX_LEVEL; + } + } + } + level +} + +/// Rows by tile, coarsest level first, each tile's rows in priority order, highest last; and each +/// tile packed, where its rows end, and how far they reach past it, fixed point. `sorted` holds the +/// rows along the curve. +fn tiled( + sorted: &[(u64, u32)], + anchors: &[[u32; 2]], + extents: &[u32], + ranks: &[u64], + level: &[u8], +) -> (Vec, Vec<(u64, u32, u32)>) { + let n = anchors.len(); + // Rows by level, along the curve within each, so each tile's rows are a run. + let mut starts = vec![0_usize; usize::from(MAX_LEVEL) + 2]; + for &l in level { + starts[usize::from(l) + 1] += 1; + } + for z in 0..=usize::from(MAX_LEVEL) { + starts[z + 1] += starts[z]; + } + let mut by_level = vec![0_u32; n]; + let mut next = starts.clone(); + for &(_, r) in sorted { + let z = usize::from(level[r as usize]); + by_level[next[z]] = r; + next[z] += 1; + } + let mut order = Vec::with_capacity(n); + let mut tiles = Vec::new(); + for z in 0..=MAX_LEVEL { + let rows = &by_level[starts[usize::from(z)]..starts[usize::from(z) + 1]]; + let mut i = 0; + while i < rows.len() { + let key = tile_of(anchors[rows[i] as usize], z); + let mut j = i; + let mut reach = 0; + while j < rows.len() && tile_of(anchors[rows[j] as usize], z) == key { + reach = reach.max(extents.get(rows[j] as usize).copied().unwrap_or(0)); + j += 1; + } + let start = order.len(); + order.extend_from_slice(&rows[i..j]); + // By priority alone: rows alike draw in either order. + order[start..].sort_unstable_by_key(|&r| (ranks[r as usize] >> 32) as u32); + tiles.push((pack(key), order.len() as u32, reach)); + i = j; + } + } + (order, tiles) +} + +/// One tile of a pyramid: where its rows lie in the pyramid's order, and how far they reach past it, +/// across the square. +#[derive(Clone, Debug, PartialEq)] +pub(crate) struct Tile { + pub(crate) key: TileKey, + pub(crate) rows: Range, + pub(crate) reach: f64, +} + +/// The tiles the camera asks of a pyramid, each with whether it is one of the finest asked, and the +/// part of the square, from the west and the north, the finest cover: a coarser tile draws only its +/// rows reaching into it. +#[derive(Clone, Debug, Default, PartialEq, Hash)] +pub(crate) struct Wanted { + pub(crate) tiles: Vec<(u32, bool)>, + pub(crate) cover: Option<[u64; 4]>, +} + +/// A table's rows grouped into tiles: a job's answer, read. +#[derive(Debug, Default)] +pub(crate) struct Pyramid { + /// Rows by tile, coarsest level first, each tile's rows in priority order, highest last. + pub(crate) order: Vec, + pub(crate) tiles: Vec, + /// Where each row lies across the square, fixed point, and half its size alike: none for a + /// table in one tile, and no sizes for points. + pub(crate) anchors: Vec<[u32; 2]>, + pub(crate) extents: Vec, + index: FxHashMap, + /// Every tile with tiles below it. + above: FxHashSet, +} + +impl Pyramid { + /// The pyramids a job answered, by the place of the table among those asked. + pub(crate) fn read(bytes: &[u8]) -> FxHashMap { + Patch::from_bytes(bytes).map(Pyramid::answered).unwrap_or_default() + } + + /// The pyramids `patch` answers, by the place of the table among those asked. + pub(crate) fn answered(patch: Patch) -> FxHashMap { + let mut tiles: FxHashMap> = FxHashMap::default(); + let mut orders: FxHashMap> = FxHashMap::default(); + let mut placed: FxHashMap, Vec)> = FxHashMap::default(); + for op in patch.ops { + let Op::Set(table) = op else { continue }; + let number = |prefix: &str| table.name.strip_prefix(prefix).and_then(|i| i.parse::().ok()); + let column = |name: &str| match table.field_named(name) { + Some(Field::Values(column, _)) => Some(column.clone()), + _ => None, + }; + // Words read as they are stored, page by page. + let words = |name: &str| -> Vec { + column(name).map_or_else(Vec::new, |c| { + c.pages().iter().flat_map(|p| p.values.u32s().unwrap_or(&[]).iter().copied()).collect() + }) + }; + if let Some(i) = number("tiles") { + let keys: Vec = column("key").map_or_else(Vec::new, |c| { + c.pages().iter().flat_map(|p| p.values.u64s().unwrap_or(&[]).iter().copied()).collect() + }); + let (ends, reaches) = (words("end"), words("reach")); + let mut start = 0; + let read = keys.iter().zip(&ends).zip(&reaches).map(|((&key, &end), &reach)| { + let rows = start..end; + start = end; + Tile { key: unpack(key), rows, reach: f64::from(reach) / 4_294_967_296.0 } + }); + tiles.insert(i, read.collect()); + } else if let Some(i) = number("order") { + orders.insert(i, words("row")); + } else if let Some(i) = number("anchors") { + let anchors = words("u").into_iter().zip(words("v")).map(|(u, v)| [u, v]).collect(); + placed.insert(i, (anchors, words("extent"))); + } + } + tiles + .into_iter() + .filter_map(|(i, tiles)| { + let mut pyramid = Pyramid::new(orders.remove(&i)?, tiles); + (pyramid.anchors, pyramid.extents) = placed.remove(&i).unwrap_or_default(); + Some((i, pyramid)) + }) + .collect() + } + + pub(crate) fn new(order: Vec, tiles: Vec) -> Pyramid { + let index = tiles.iter().enumerate().map(|(i, t)| (t.key, i as u32)).collect(); + let mut above = FxHashSet::default(); + for tile in &tiles { + for up in 1..=tile.key.z { + if !above.insert(tile.key.ancestor(up)) { + break; + } + } + } + Pyramid { order, tiles, anchors: Vec::new(), extents: Vec::new(), index, above } + } + + /// The tiles the camera asks for, coarsest first: at each level, every tile its rows reach into + /// what the camera shows from, splitting while a tile draws larger than its size. A level whose + /// rows would pass `rows` goes, coarser ones drawing whole in its place. + pub(crate) fn wanted(&self, sight: &Sight<'_>, domain: &Domain, rows: u32) -> Wanted { + if self.tiles.len() == 1 && self.tiles[0].key.z == 0 { + return Wanted { tiles: vec![(0, true)], cover: None }; + } + let region: Region = sight.region(); + let focus = sight.focus(); + let limit = TILE_PX * 1.25; + let mut out: Vec<(u32, bool)> = Vec::new(); + let mut cover = [u64::MAX, u64::MAX, 0, 0]; + let mut total = 0_u32; + let mut level = vec![TileKey { z: 0, x: 0, y: 0 }]; + // The tiles of the level above that split, and where among those found each is. + let mut split: Vec<(TileKey, Option)> = Vec::new(); + while !level.is_empty() { + let mut found = Vec::new(); + let mut leaves = Vec::new(); + let mut splitting = Vec::new(); + let mut added = 0_u32; + let mut next = Vec::new(); + for key in level { + let grow = 0.5 / f64::from(1_u32 << key.z); + if !meets(®ion, domain.bounds(key, grow)) { + continue; + } + let splits = self.above.contains(&key) + && next.len() < MAX_TILES + && sight.measure(&focus, domain.bounds(key, 0.0)).0 > limit; + let mut at = None; + if let Some(&t) = self.index.get(&key) { + let tile = &self.tiles[t as usize]; + if meets(®ion, domain.bounds(key, tile.reach)) { + at = Some(out.len() + found.len()); + found.push((t, !splits)); + added = added.saturating_add(tile.rows.len() as u32); + } + } + if splits { + next.extend(key.children()); + splitting.push((key, at)); + } else { + leaves.push(key); + } + } + if total.saturating_add(added) > rows && !out.is_empty() { + // The tiles that split draw whole instead. + for (key, at) in split { + cover = covering(cover, key); + if let Some(at) = at { + out[at].1 = true; + } + } + break; + } + total = total.saturating_add(added); + out.extend(found); + for key in leaves { + cover = covering(cover, key); + } + split = splitting; + level = next; + } + Wanted { tiles: out, cover: (cover[0] <= cover[2]).then_some(cover) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::data::UNWIRED; + + /// Fixed point across the square. + fn at(u: f64, v: f64) -> [u32; 2] { + [(u * 4_294_967_296.0) as u32, (v * 4_294_967_296.0) as u32] + } + + /// A unit square of a plane, its rows placed `u` from the west and `v` from the north. + fn square(points: &[[f64; 2]]) -> (Domain, Places) { + let domain = Domain::Plane { min: [0.0, 0.0], size: 1.0 }; + (domain, Places::Points(points.iter().map(|&[u, v]| [u as f32, (1.0 - v) as f32]).collect())) + } + + #[test] + fn crowded_rows_wait_for_finer_levels_by_priority() { + // Two rows in one cell: the higher lands at the root, the lower a level finer. + let anchors = [at(0.3, 0.3), at(0.3, 0.3), at(0.8, 0.8)]; + let level = place(&along(&anchors), &[], &ranks(&[1.0, 2.0, 0.0], 3), &[0, 0, 0], None); + assert_eq!(level[1], 0, "the higher priority lands at the root"); + assert_eq!(level[2], 0, "a row alone in its cell lands at the root"); + assert_eq!(level[0], 1, "the lower lands once the higher has left its cell"); + let alike = [at(0.3, 0.3); 4]; + let level = place(&along(&alike), &[], &ranks(&[], 4), &[0; 4], None); + let mut sorted = level.clone(); + sorted.sort_unstable(); + assert_eq!(sorted, vec![0, 1, 2, 3], "a row a level, equals in an order of their own"); + } + + #[test] + fn no_tile_holds_more_rows_than_cells() { + let n = 50_000_u32; + let anchors: Vec<[u32; 2]> = + (0..n).map(|i| at(f64::from(i % 250) / 250.0, f64::from(i / 250) / 200.0)).collect(); + let sorted = along(&anchors); + let ranks = ranks(&[], n as usize); + let level = place(&sorted, &[], &ranks, &vec![0; n as usize], None); + let (order, tiles) = tiled(&sorted, &anchors, &[], &ranks, &level); + assert_eq!(order.len(), n as usize); + let mut start = 0; + for &(_, end, _) in &tiles { + assert!(end - start <= 1 << (2 * GRID_BITS), "a tile holds at most its grid's cells"); + start = end; + } + assert!(tiles.len() > 1); + } + + #[test] + fn large_rows_stay_coarse_and_edges_land_by_their_own_priority() { + let anchors = [at(0.1, 0.1), at(0.9, 0.9)]; + let extents = [1 << 30, 0]; + let level = place(&along(&anchors), &extents, &ranks(&[0.0, 0.0], 2), &[0, 0], None); + assert!(level[0] <= 1, "a row reaching a quarter of the square stays coarse"); + // Two vertices crowd one cell; the edges between them land by their own priority, parallel + // ones together, and one naming no row only at the finest level. + let (domain, places) = square(&[[0.3, 0.3], [0.3, 0.3], [0.31, 0.3]]); + let leveling = Leveling { + domain, + tables: vec![ + Placing { + rows: 3, + leveled: true, + answered: true, + places, + priority: [2.0, 1.0, 0.0].into(), + ..Placing::default() + }, + Placing { + rows: 3, + leveled: true, + answered: true, + ends: Some((0, vec![[1, 2, UNWIRED].into(), [2, 1, 0].into()])), + ..Placing::default() + }, + ], + }; + let pyramids = Pyramid::read(&answer(&leveling).to_bytes()); + let edges = &pyramids[&1]; + let level_of = |p: &Pyramid, row: u32| { + let at = p.order.iter().position(|&r| r == row).unwrap() as u32; + p.tiles.iter().find(|t| t.rows.contains(&at)).unwrap().key.z + }; + assert_eq!(level_of(edges, 0), 0, "an edge alone in its cell shows from the root, its ends carried"); + assert_eq!(level_of(edges, 1), 0, "with the edge joining the same vertices"); + assert_eq!(level_of(edges, 2), MAX_LEVEL, "an edge naming no row waits for the finest level"); + } + + #[test] + fn tiles_number_exactly() { + let key = TileKey { z: MAX_LEVEL, x: (1 << 24) - 1, y: 12_345 }; + assert_eq!(unpack(pack(key)), key); + assert_eq!(unpack(pack(key) as f64 as u64), key, "a number holds it exactly"); + } + + #[test] + fn whole_tables_order_rows_by_priority() { + let leveling = Leveling { + domain: Domain::Earth, + tables: vec![Placing { rows: 3, answered: true, priority: [5.0, 1.0, 3.0].into(), ..Placing::default() }], + }; + let pyramids = Pyramid::read(&answer(&leveling).to_bytes()); + assert_eq!(pyramids[&0].order, vec![1, 2, 0], "highest last, drawn on top"); + assert_eq!(pyramids[&0].tiles.len(), 1); + } +} diff --git a/crates/latkit/src/derive/shapes.rs b/crates/latkit/src/derive/shapes.rs new file mode 100644 index 00000000..bcdaf274 --- /dev/null +++ b/crates/latkit/src/derive/shapes.rs @@ -0,0 +1,294 @@ +//! Shapes: what geometry fields become to draw, written beside the tables marks draw them from. Every +//! area's triangles, the point its label hangs from first; and on the earth every line's path, +//! unwrapped across the antimeridian and bent with the globe. Shapes are made page by page from a +//! field's pages and kept while a page holds; a page written again keeps the shapes of its rows +//! whose geometry did not change, so a tile landing shapes only its own rows. Triangles that do not +//! fit the frame's budget are made in a job, their rows drawing nothing until it lands; bending a +//! path is cheap, and done at once. + +use rustc_hash::FxHashMap; + +use super::{Derive, Input, Jobs, Tables, answers, beside, stamp_of}; +use crate::data::{Column, Field, GeometryBuilder, Id, Name, PAGE_ROWS, Page, PageId, Table, Value, Values, Version}; +use crate::host::{Job, Shaping}; +use crate::scene::areas::triangles_of; +use crate::scene::lines::path_of; +use crate::{Mark, Pending, Space}; + +/// Microseconds a point takes to triangulate, by estimate. +const TRIANGULATE: f64 = 0.5; + +/// Rows by id, each with the digest of the geometry it was shaped from. +type Digests = FxHashMap; + +/// A field to shape: its dataset, table, and field, and how. +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +struct Want { + data: Name, + table: Name, + field: Name, + shaping: Shaping, +} + +impl Want { + /// The derived field the shapes are written as. + fn derived(&self) -> Name { + match self.shaping { + Shaping::Triangles { .. } => triangles_of(&self.field), + Shaping::Path => path_of(&self.field), + } + } +} + +/// One field's shapes: the last whole set made, the derived field written, shapes made but not yet +/// written, and a job under way. +#[derive(Default)] +struct Shaped { + /// The source table, its field, and the derived column the shapes were last wholly made from. + made: Option<(Table, Column, Column)>, + /// The derived field written last, and the stamp of what it was written from. + field: Option, + stamp: u64, + /// Shapes made since, by row id: the digest of the geometry each was made from, and the shape. + landed: FxHashMap, + /// A job under way, with the digest of each row it shapes. + working: Option<(Pending>, Digests)>, + /// Bumps whenever a job's answer lands. + landings: u64, +} + +#[derive(Default)] +pub(crate) struct Shapes { + tables: Tables, + shaped: FxHashMap, +} + +impl Derive for Shapes { + fn update(&mut self, input: &Input<'_>, jobs: &mut Jobs<'_>) -> bool { + let wants = wants(input); + self.shaped.retain(|want, _| wants.contains(want)); + let mut changed = false; + for want in &wants { + let Some(source) = input.data(&want.data).and_then(|d| d.table(&want.table)) else { continue }; + let shaped = self.shaped.entry(want.clone()).or_default(); + changed |= shaped.update(want, source, jobs); + } + // Each drawn table's derived table holds every field shaped from it. + let mut fields: FxHashMap<(Name, Name), Vec<(Name, Field)>> = FxHashMap::default(); + for want in &wants { + if let Some(field) = self.shaped.get(want).and_then(|s| s.field.clone()) { + fields.entry((want.data.clone(), want.table.clone())).or_default().push((want.derived(), field)); + } + } + let before = self.tables.len(); + self.tables.retain(|key, _| fields.contains_key(key)); + changed |= self.tables.len() != before; + if changed { + for (key, fields) in fields { + let Some(source) = input.data(&key.0).and_then(|d| d.table(&key.1)) else { continue }; + self.tables.insert(key, beside(source, fields)); + } + } + changed + } + + fn busy(&self) -> bool { + self.shaped.values().any(|s| s.working.is_some()) + } + + fn tables(&self) -> &Tables { + &self.tables + } + + fn clear(&mut self) { + self.tables.clear(); + self.shaped.clear(); + } +} + +/// The fields the scene's marks shape: every area's polygons, and on the earth every line's paths. +fn wants(input: &Input<'_>) -> Vec { + let earth = matches!(input.scene.space, Space::Earth(_)); + let mut wants: Vec = Vec::new(); + for mark in &input.scene.marks { + let (field, shaping) = match mark { + Mark::Areas(areas) => (areas.field(), Shaping::Triangles { earth }), + Mark::Lines(lines) if earth => (lines.traced(), Shaping::Path), + _ => continue, + }; + let style = mark.style(); + let want = Want { data: style.data.clone(), table: style.table.clone(), field, shaping }; + if !wants.contains(&want) { + wants.push(want); + } + } + wants +} + +impl Shaped { + /// Brings the shapes up to `source`; whether the derived field changed. + fn update(&mut self, want: &Want, source: &Table, jobs: &mut Jobs<'_>) -> bool { + if let Some((pending, asked)) = &self.working + && let Some(answer) = pending.take() + { + for ((_, id), values) in answer.map(|bytes| answers(&bytes, &["shape"])).unwrap_or_default() { + if let (Some(&digest), Some(Some(shape))) = (asked.get(&id), values.into_iter().next()) { + self.landed.insert(id, (digest, shape)); + } + } + self.working = None; + self.landings += 1; + } + let Some(Field::Values(column, version)) = source.field_named(&want.field) else { + let had = self.field.take().is_some(); + self.stamp = 0; + return had; + }; + let depth = column.kind().depth(); + let ((Some(depth @ (2 | 3)), Shaping::Triangles { .. }) | (Some(depth @ 1..), Shaping::Path)) = + (depth, want.shaping) + else { + return self.field.take().is_some(); + }; + let stamp = stamp_of((source.structure, *version, self.landings, want.shaping)); + if stamp == self.stamp { + return false; + } + self.stamp = stamp; + // Rows shaped on the frame land at once; a second pass writes them. + for _ in 0..2 { + let (derived, missing) = self.build(want, source, column, depth); + if missing.is_empty() { + self.field = Some(Field::Values(derived.clone(), Version::next())); + self.made = Some((source.clone(), column.clone(), derived)); + self.landed.clear(); + return true; + } + let points: usize = missing.iter().map(|&(row, ..)| points_of(column, row)).sum(); + if jobs.fits((points as f64 * TRIANGULATE).ceil() as u64) { + for (row, id, digest) in missing { + let Some(value) = column.get(row) else { continue }; + let shape = want.shaping.shape(&value).unwrap_or(value); + self.landed.insert(id, (digest, shape)); + } + continue; + } + if self.working.is_none() { + let rows: Vec = missing.iter().map(|&(row, ..)| row).collect(); + let job = Job::shapes(want.shaping, rows_of(source, column, &rows)); + let asked = missing.into_iter().map(|(_, id, digest)| (id, digest)).collect(); + self.working = Some((jobs.spawn(job), asked)); + } + // Until the job lands, its rows draw nothing and the rest draw as they were. + self.field = Some(Field::Values(derived, Version::next())); + return true; + } + false + } + + /// The derived column for `column` of `source`, page by page: a page whose source page is the + /// one shaped last keeps its shapes; others are assembled row by row from shapes landed, or kept + /// from the last set where a row's geometry did not change. Rows with neither are missing: each + /// row, its id, and the digest of its geometry. + fn build(&self, want: &Want, source: &Table, column: &Column, depth: u8) -> (Column, Vec<(usize, Id, u64)>) { + let made_pages: FxHashMap = self + .made + .iter() + .flat_map(|(_, field, derived)| field.pages().iter().map(|p| p.id).zip(derived.pages())) + .collect(); + let depth = want.shaping.depth(depth); + let mut pages: Vec = Vec::with_capacity(column.pages().len()); + let mut missing = Vec::new(); + for (p, page) in column.pages().iter().enumerate() { + if let Some(&kept) = made_pages.get(&page.id) { + pages.push(kept.clone()); + continue; + } + let Some(geometry) = page.values.geometry() else { + pages.push(Page::new(Values::of_geometry(GeometryBuilder::new(depth).finish()))); + continue; + }; + // A path page that needs no bending is its own shape: shared, nothing uploads again. + if want.shaping == Shaping::Path && !bends(geometry.coords()) { + pages.push(page.clone()); + continue; + } + let mut shapes = GeometryBuilder::new(depth); + for local in 0..page.values.len() { + let row = p * PAGE_ROWS + local; + let Some(id) = source.ids.id(row) else { + shapes.push_empty(); + continue; + }; + if !page.values.is_valid(local) { + shapes.push_empty(); + continue; + } + let digest = geometry.row_hash(local); + if let Some((d, shape)) = self.landed.get(&id) + && *d == digest + { + shapes.push_value(shape); + } else if let Some((page, at)) = self.kept(&id, digest) { + shapes.push_from(page, at); + } else if want.shaping == Shaping::Path { + // Bending is cheap, so done here; rows that need none keep their geometry. + match page.values.get(local).and_then(|v| want.shaping.shape(&v)) { + Some(shape) => { + shapes.push_value(&shape); + } + None => shapes.push_from(geometry, local), + } + } else { + missing.push((row, id, digest)); + shapes.push_empty(); + } + } + pages.push(Page::new(Values::of_geometry(shapes.finish()))); + } + let like = Values::of_geometry(GeometryBuilder::new(depth).finish()); + (Column::of_pages(pages, &like), missing) + } + + /// Where the last whole set holds the shape of the row with `id`, when its geometry's digest was + /// `digest`: the derived page's geometry and the row's place in it. + fn kept(&self, id: &Id, digest: u64) -> Option<(&crate::data::Geometry, usize)> { + let (table, field, derived) = self.made.as_ref()?; + let row = table.row(id.as_ref())?; + let (page, at) = (row / PAGE_ROWS, row % PAGE_ROWS); + let was = field.pages().get(page)?.values.geometry()?; + if !field.pages()[page].values.is_valid(at) || was.row_hash(at) != digest { + return None; + } + Some((derived.pages().get(page)?.values.geometry()?, at)) + } +} + +/// Whether any two coordinates in a row of `coords` lie farther apart than an earth path's step: a +/// page with none needs no bending. +fn bends(coords: &[[f64; 2]]) -> bool { + let step = crate::geo::shapes::EARTH_STEP; + coords.windows(2).any(|w| (w[1][0] - w[0][0]).abs() > step || (w[1][1] - w[0][1]).abs() > step) +} + +/// How many points row `row` of geometry column `column` holds. +fn points_of(column: &Column, row: usize) -> usize { + let Some(page) = column.pages().get(row / PAGE_ROWS) else { return 0 }; + page.values.geometry().map_or(0, |g| g.row_coords(row % PAGE_ROWS).len()) +} + +/// Rows `rows` of `source`, by id, with their geometry from `column` as field `geometry`: what a +/// shapes job reads. +fn rows_of(source: &Table, column: &Column, rows: &[usize]) -> Table { + let ids: Vec = rows.iter().filter_map(|&row| source.ids.id(row)).collect(); + let depth = column.kind().depth().expect("a geometry column"); + let mut geometry = GeometryBuilder::new(depth); + for &row in rows { + let page = &column.pages()[row / PAGE_ROWS]; + match page.values.geometry() { + Some(g) if page.values.is_valid(row % PAGE_ROWS) => geometry.push_from(g, row % PAGE_ROWS), + _ => geometry.push_empty(), + } + } + Table::new(source.name.clone(), ids).field("geometry", Values::of_geometry(geometry.finish())) +} diff --git a/crates/latkit/src/derive/sight.rs b/crates/latkit/src/derive/sight.rs new file mode 100644 index 00000000..8d199c3a --- /dev/null +++ b/crates/latkit/src/derive/sight.rs @@ -0,0 +1,264 @@ +//! What the camera sees, as tiles: the one place derivations read the camera. Tiles split a +//! square of the space four ways a level, the earth's web mercator square or a square of a plane; a +//! tile is wanted where it meets what the camera shows, and splits while it draws larger than its +//! size where it lies nearest the camera's focus. + +use glam::DVec3; + +use crate::tiles::TileKey; +use crate::view::Projected; + +/// CSS pixels a tile spans drawn at its own level. +pub(crate) const TILE_PX: f64 = 512.0; +/// The latitude web mercator reaches, north and south. +const MAX_LATITUDE: f64 = 85.051_128_779_806_59; + +/// Where a space's tiles lie: the earth's web mercator square, or a square of a plane. +#[derive(Clone, Copy, PartialEq, Debug)] +pub(crate) enum Domain { + Earth, + /// A plane's square: its west and south edges and its size, in position units. + Plane { + min: [f64; 2], + size: f64, + }, +} + +impl Domain { + /// The square holding positions within `bounds` (west, south, east, north) on a plane, with a + /// little room so nothing lies on its edge. + pub(crate) fn plane(bounds: [f64; 4]) -> Domain { + let [w, s, e, n] = if bounds[0] <= bounds[2] { bounds } else { [0.0, 0.0, 1.0, 1.0] }; + let size = (e - w).max(n - s).max(1e-9) * 1.02; + let center = [w.midpoint(e), s.midpoint(n)]; + Domain::Plane { min: [center[0] - size / 2.0, center[1] - size / 2.0], size } + } + + /// Where position `p` lies across the square, 0 to 1 from the west and from the north. + pub(crate) fn unit(&self, p: [f64; 2]) -> [f64; 2] { + match *self { + Domain::Earth => { + let lat = p[1].clamp(-MAX_LATITUDE, MAX_LATITUDE).to_radians(); + let y = 0.5 - (std::f64::consts::FRAC_PI_4 + lat / 2.0).tan().ln() / std::f64::consts::TAU; + [((p[0] + 180.0) / 360.0).rem_euclid(1.0), y] + } + Domain::Plane { min, size } => [(p[0] - min[0]) / size, 1.0 - (p[1] - min[1]) / size], + } + } + + /// The position at `u` across the square. + pub(crate) fn position(&self, u: [f64; 2]) -> [f64; 2] { + match *self { + Domain::Earth => { + let lat = (std::f64::consts::PI * (1.0 - 2.0 * u[1])).sinh().atan().to_degrees(); + [u[0] * 360.0 - 180.0, lat] + } + Domain::Plane { min, size } => [min[0] + u[0] * size, min[1] + (1.0 - u[1]) * size], + } + } + + /// West, south, east, and north of tile `key`, grown on every side by `grow` across the square, + /// within the square. + pub(crate) fn bounds(&self, key: TileKey, grow: f64) -> [f64; 4] { + let n = f64::from(1_u32 << key.z); + let (x, y) = (f64::from(key.x), f64::from(key.y)); + let west = (x / n - grow).max(0.0); + let east = ((x + 1.0) / n + grow).min(1.0); + let north = (y / n - grow).max(0.0); + let south = ((y + 1.0) / n + grow).min(1.0); + let [w, s] = self.position([west, south]); + let [e, n] = self.position([east, north]); + [w, s, e, n] + } +} + +/// What the camera sees: where tiles are wanted and how large they draw. +pub(crate) struct Sight<'a> { + pub(crate) projected: &'a Projected, + /// The view's size, CSS pixels. + pub(crate) size: [f64; 2], + pub(crate) earth: bool, +} + +/// West, south, east, north boxes, in position units: what the camera shows, in one box, or on the +/// earth two where it wraps the antimeridian. +pub(crate) type Region = Vec<[f64; 4]>; + +impl Sight<'_> { + /// Where position `p` lands on screen, if it shows. + fn project(&self, p: [f64; 2]) -> Option<[f64; 2]> { + let w = self.projected.world([p[0], p[1], 0.0]); + if !self.facing(w) { + return None; + } + self.projected.screen(w).map(|s| [s[0], s[1]]) + } + + /// The position on the ground under screen point `p`. + fn ground(&self, p: [f64; 2]) -> Option<[f64; 2]> { + let w = self.projected.surface(p)?; + let [x, y, _] = self.projected.position(w); + Some([x, y]) + } + + /// The center of the globe the earth is, and its radius, in world units. + fn sphere(&self) -> (DVec3, f64) { + let radius = 1.0 / self.projected.center[1].to_radians().cos(); + (DVec3::new(0.0, 0.0, -radius), radius) + } + + fn globe(&self) -> bool { + self.earth && self.projected.globe >= 0.5 + } + + /// Whether world point `w` faces the camera: always on a map, on the globe its near side. + fn facing(&self, w: DVec3) -> bool { + if !self.globe() { + return true; + } + let (center, _) = self.sphere(); + (w - center).dot(self.projected.eye - w) > 0.0 + } + + /// Where tiles draw largest: where the camera looks, and tilted, the nearest ground it shows. + pub(crate) fn focus(&self) -> Vec<[f64; 2]> { + let center = [self.projected.center[0], self.projected.center[1]]; + let near = self.ground([self.size[0] / 2.0, self.size[1]]); + std::iter::once(center).chain(near).collect() + } + + /// The ground the camera shows, sampled on a grid of points across the view. + pub(crate) fn region(&self) -> Region { + const SAMPLES: usize = 7; + let globe = self.globe(); + let center = self.projected.center; + let (mut w, mut s, mut e, mut n) = (f64::INFINITY, f64::INFINITY, f64::NEG_INFINITY, f64::NEG_INFINITY); + let mut missed = false; + let last = (SAMPLES - 1) as f64; + for i in 0..SAMPLES { + for j in 0..SAMPLES { + let at = [self.size[0] * i as f64 / last, self.size[1] * j as f64 / last]; + let Some([x, y]) = self.ground(at) else { + missed = true; + continue; + }; + // Longitudes kept beside the center's, so a view across the antimeridian is one span. + let x = if globe { center[0] + turn(center[0], x) } else { x }; + (w, e, s, n) = (w.min(x), e.max(x), s.min(y), n.max(y)); + } + } + if !self.earth { + if w > e { + return Vec::new(); + } + if missed { + // A tilted plane past its horizon: everything toward it. + let size = (e - w).max(n - s) * 4.0; + return vec![[w - size, s - size, e + size, n + size]]; + } + return vec![[w, s, e, n]]; + } + if globe { + if missed { + return self.cap(); + } + let shows = |lat: f64| { + self.project([center[0], lat]) + .is_some_and(|p| p[0] >= 0.0 && p[1] >= 0.0 && p[0] <= self.size[0] && p[1] <= self.size[1]) + }; + if shows(90.0) { + return boxes(-180.0, 180.0, s, 90.0); + } + if shows(-90.0) { + return boxes(-180.0, 180.0, -90.0, n); + } + } + if w > e { + return vec![[-180.0, -90.0, 180.0, 90.0]]; + } + if missed { + // A tilted map past its horizon: everything toward it. + let size = (e - w).max(n - s) * 4.0; + return boxes(w - size, e + size, s - size, n + size); + } + let (pad_x, pad_y) = ((e - w) * 0.02, (n - s) * 0.02); + if globe { + return boxes(w - pad_x, e + pad_x, s - pad_y, n + pad_y); + } + vec![[(w - pad_x).max(-180.0), (s - pad_y).max(-90.0), (e + pad_x).min(180.0), (n + pad_y).min(90.0)]] + } + + /// The cap of the globe the camera can see past its horizon. + fn cap(&self) -> Region { + let (center, radius) = self.sphere(); + let out = self.projected.eye - center; + let reach = (radius / out.length().max(radius)).acos().to_degrees(); + let [lon, lat, _] = self.projected.position(center + out.normalize_or_zero() * radius); + if reach >= 89.0 { + return vec![[-180.0, -90.0, 180.0, 90.0]]; + } + let (south, north) = (lat - reach, lat + reach); + if north >= 90.0 || south <= -90.0 { + return boxes(-180.0, 180.0, south, north); + } + let half = (reach.to_radians().sin() / lat.to_radians().cos()).min(1.0).asin().to_degrees(); + boxes(lon - half, lon + half, south, north) + } + + /// How large a tile of bounds `b` draws where it lies nearest each focus, and how far from the + /// view's middle that lands. + pub(crate) fn measure(&self, focus: &[[f64; 2]], b: [f64; 4]) -> (f64, f64) { + let [w, s, e, n] = b; + let (dx, dy) = ((e - w) / 64.0, (n - s) / 64.0); + let (mut size, mut distance) = (0.0_f64, f64::INFINITY); + for &[fx, fy] in focus { + let near = if self.earth { fx + 360.0 * ((w.midpoint(e) - fx) / 360.0).round() } else { fx }; + let (x, y) = (near.clamp(w, e - dx), fy.clamp(s, n - dy)); + let Some(p) = self.project([x, y]) else { continue }; + let reach = |q: Option<[f64; 2]>| q.map_or(0.0, |q| 64.0 * (q[0] - p[0]).hypot(q[1] - p[1])); + size = size.max(reach(self.project([x + dx, y]))).max(reach(self.project([x, y + dy]))); + distance = distance.min((p[0] - self.size[0] / 2.0).hypot(p[1] - self.size[1] / 2.0)); + } + (size, distance) + } +} + +/// The shortest turn from longitude `from` to `to`, in degrees. +fn turn(from: f64, to: f64) -> f64 { + (to - from + 540.0).rem_euclid(360.0) - 180.0 +} + +/// The boxes of a longitude range that may wrap, and a latitude range. +fn boxes(west: f64, east: f64, south: f64, north: f64) -> Region { + let (s, n) = (south.max(-90.0), north.min(90.0)); + if east - west >= 360.0 { + return vec![[-180.0, s, 180.0, n]]; + } + let w = (west + 180.0).rem_euclid(360.0) - 180.0; + let e = w + (east - west); + if e <= 180.0 { vec![[w, s, e, n]] } else { vec![[w, s, 180.0, n], [-180.0, s, e - 360.0, n]] } +} + +/// Whether box `b` meets what the camera shows. +pub(crate) fn meets(region: &Region, b: [f64; 4]) -> bool { + region.iter().any(|r| b[0] <= r[2] && b[2] >= r[0] && b[1] <= r[3] && b[3] >= r[1]) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn domains_place_positions_across_their_square() { + let earth = Domain::Earth; + let u = earth.unit([0.0, 0.0]); + assert!((u[0] - 0.5).abs() < 1e-12 && (u[1] - 0.5).abs() < 1e-12); + let back = earth.position(earth.unit([-97.5, 30.25])); + assert!((back[0] + 97.5).abs() < 1e-9 && (back[1] - 30.25).abs() < 1e-9); + let plane = Domain::plane([0.0, 0.0, 10.0, 5.0]); + let u = plane.unit([5.0, 2.5]); + assert!((u[0] - 0.5).abs() < 1e-12 && (u[1] - 0.5).abs() < 1e-12, "the middle of the data"); + let b = plane.bounds(TileKey { z: 1, x: 0, y: 0 }, 0.0); + assert!(b[0] < 0.0 && b[3] > 5.0, "the northwest quarter: {b:?}"); + } +} diff --git a/crates/latkit/src/derive/stars.rs b/crates/latkit/src/derive/stars.rs new file mode 100644 index 00000000..3a1c6830 --- /dev/null +++ b/crates/latkit/src/derive/stars.rs @@ -0,0 +1,104 @@ +//! Stars outside diagrams: a net's edges. Each row of an edge mark that `joins` a table is a net +//! joining the vertex rows whose reference field names it, drawn from their middle to each, as the +//! vertex mark drawing them places them. The star of each net row is a path field beside the net +//! table, which the mark draws as any geometry; it works again only when the data or scene change. + +use super::graph::{VertexMark, marks, position}; +use super::{Input, Tables, beside, kept}; +use crate::data::{Field, Name, UNWIRED, Values}; +use crate::expr::cpu::Rows; +use crate::{Mark, Space}; + +#[derive(Default)] +pub(crate) struct Stars { + tables: Tables, + stamp: u64, +} + +impl Stars { + /// Brings the stars up to `input`, the members placed by their data or by `places`, the layout's + /// places beside their tables; whether a table changed. + pub(crate) fn update(&mut self, input: &Input<'_>, places: &Tables) -> bool { + let joining = input.scene.marks.iter().any(|m| matches!(m, Mark::Edges(e) if e.joins.is_some())); + if matches!(input.scene.space, Space::Diagram(_)) || !joining { + let had = !self.tables.is_empty(); + self.clear(); + return had; + } + let field = |t: &crate::Table, name: &str| t.field_named(name).map(Field::version); + let placed: Vec<_> = places.iter().map(|(key, t)| (key, field(t, "x"), field(t, "y"))).collect(); + let mut hasher = rustc_hash::FxHasher::default(); + std::hash::Hash::hash(&(input.scene_version, placed), &mut hasher); + input.structure(&mut hasher); + let stamp = std::hash::Hasher::finish(&hasher).max(1); + if stamp == self.stamp { + return false; + } + self.stamp = stamp; + let (vertex_marks, _) = marks(input); + let mut tables = Tables::default(); + for mark in &input.scene.marks { + let Mark::Edges(edges) = mark else { continue }; + let Some((members, reference)) = &edges.joins else { continue }; + let style = &edges.style; + let Some(data) = input.data(&style.data) else { continue }; + let Some(nets) = data.table(&style.table) else { continue }; + let Some(vm) = vertex_marks.iter().find(|vm| vm.data.name() == data.name() && vm.table.name() == members) + else { + continue; + }; + let Some(Field::Reference(named)) = vm.table.field_named(reference) else { continue }; + if named.to != *nets.name() { + continue; + } + let placed = places.get(&(data.name().clone(), members.clone())); + let mut points: Vec> = vec![Vec::new(); nets.len()]; + let rows = Rows::new(vm.table, input.data); + for (row, net) in named.targets().into_iter().enumerate() { + if net == UNWIRED { + continue; + } + if let (Some(point), Some(members)) = (place(vm, &rows, row, placed), points.get_mut(net as usize)) { + members.push(point); + } + } + let stars: Vec>> = points.iter().map(|members| star(members)).collect(); + let key = (data.name().clone(), nets.name().clone()); + let before = self.tables.get(&key); + let route = kept("route", &Values::from(stars), nets, before); + tables.insert(key, beside(nets, [(Name::from("route"), route)])); + } + self.tables = tables; + true + } + + pub(crate) fn tables(&self) -> &Tables { + &self.tables + } + + pub(crate) fn clear(&mut self) { + self.tables.clear(); + self.stamp = 0; + } +} + +/// Where member row `row` stands: as its data positions it, else where the layout placed it. +fn place(vm: &VertexMark<'_>, rows: &Rows<'_>, row: usize, placed: Option<&crate::Table>) -> Option<[f64; 2]> { + position(vm.mark, rows, row).or_else(|| { + let table = placed?; + match (table.value(row, "x", f64::INFINITY)?, table.value(row, "y", f64::INFINITY)?) { + (crate::Value::Number(x), crate::Value::Number(y)) => Some([x, y]), + _ => None, + } + }) +} + +/// A net's star: a path from the middle of `members` to each; none for fewer than two. +fn star(members: &[[f64; 2]]) -> Vec> { + if members.len() < 2 { + return Vec::new(); + } + let n = members.len() as f64; + let middle = [members.iter().map(|p| p[0]).sum::() / n, members.iter().map(|p| p[1]).sum::() / n]; + members.iter().map(|&p| vec![middle, p]).collect() +} diff --git a/crates/latkit/src/derive/tiled.rs b/crates/latkit/src/derive/tiled.rs new file mode 100644 index 00000000..0d877db0 --- /dev/null +++ b/crates/latkit/src/derive/tiled.rs @@ -0,0 +1,1133 @@ +//! Tables drawn in part. A table with a priority draws its rows in priority order, the highest on +//! top; one too large to draw whole draws the rows of the tiles the camera asks for, or where nothing +//! places its rows, those that matter most. What a view draws of such a dataset is a dataset of its +//! own, of the same name, ids, and origin: each such table's rows drawn in drawing order, with the +//! rows the edges drawn end at carried along and the rows pinned (selected, or framed by a fit) +//! kept; other tables as they are, their references naming the rows drawn. Marks draw it like any +//! other dataset, so picks, selection, hover, transitions, lanes, and labels follow it. +//! +//! Each table's pyramid is worked out from where its rows lie and their priority: on the frame while +//! that fits its budget, else in a job of its own, so a dataset's tables are placed side by side and +//! each draws once its own lands; until then a table draws an even sample of its rows, as many as a +//! first look needs. A pyramid serves while the rows it was placed from hold. The rows drawn are laid +//! out again when the tiles asked for, the rows pinned, or the rows a table holds change; when only +//! values change, every row stays where it is drawn and each field writes only the rows whose values +//! changed, so a patch of one row costs one row. Only the fields marks read are gathered. + +use std::sync::Arc; + +use rustc_hash::{FxHashMap, FxHashSet}; + +use super::pyramid::{Leveling, Places, Placing, Pyramid, Wanted, answer, reaches}; +use super::sight::{Domain, Sight}; +use super::{Jobs, stamp_of}; +use crate::data::{Data, Field, Name, RowIds, Table, UNWIRED, Version}; +use crate::expr::cpu::Rows; +use crate::expr::{Expr, Node}; +use crate::host::Job; +use crate::{Pending, Row}; + +/// Microseconds placing a row takes, by estimate. +const PLACE_COST: f64 = 1.0; +/// Rows a table drawn in part draws at most until its pyramid lands: a first look at all of it. +const SAMPLE: u32 = 1 << 16; + +/// How a table draws. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub(crate) enum Draw { + /// Every row. + Whole, + /// The rows of the tiles the camera asks for, as many as `rows` at most. + Tiles { rows: u32 }, + /// The `rows` rows that matter most. + First { rows: u32 }, +} + +/// Where a table's rows lie, as the mark drawing them places them. +#[derive(Clone, Debug, PartialEq)] +pub(crate) enum Place { + /// Nowhere a camera's tiles reach: off a map or a plane. + Nowhere, + /// At a point each: x and y. + Points([Expr; 2]), + /// Along a geometry field. + Geometry(Name), + /// Between the rows its reference fields name. + Ends(Vec), +} + +/// How one table draws, and what that reads. +#[derive(Clone, Debug, PartialEq)] +pub(crate) struct Planned { + pub(crate) draw: Draw, + /// Each row's priority, as the first mark giving one has it. + pub(crate) priority: Option, + pub(crate) place: Place, + /// The fields marks read of it, which its rows drawn hold with every reference field; `None` + /// where they hold every field. + pub(crate) reads: Option>, +} + +impl Planned { + /// Whether the table draws as it is: whole, in its own order. + pub(crate) fn as_is(&self) -> bool { + self.draw == Draw::Whole && self.priority.is_none() + } +} + +/// How each table drawn draws, by dataset and table. +pub(crate) type Plans = FxHashMap<(Name, Name), Planned>; + +/// What drawing in part reads this frame. +pub(crate) struct Ask<'a> { + pub(crate) sources: &'a [Data], + pub(crate) plans: &'a Plans, + /// What the camera sees, on a map or a plane. + pub(crate) sight: Option<&'a Sight<'a>>, + pub(crate) earth: bool, + /// Rows drawn whatever the tiles: those selected, and those a fit frames. + pub(crate) pinned: &'a [Row], + /// The axis coordinate shown, which sampled fields drawn in part are gathered about. + pub(crate) at: f64, +} + +/// What each dataset drawn in part draws. +#[derive(Default)] +pub(crate) struct Tiled { + sets: Vec, +} + +impl Tiled { + /// Brings what each dataset drawn in part draws up to `ask`: the datasets drawn that changed, and + /// the names of those no longer drawn in part, which draw as they are. + pub(crate) fn update(&mut self, ask: &Ask<'_>, jobs: &mut Jobs<'_>) -> (Vec, Vec) { + let mut wanted: Vec<&Name> = Vec::new(); + for ((data, _), planned) in ask.plans { + if !planned.as_is() && !wanted.contains(&data) { + wanted.push(data); + } + } + let mut gone = Vec::new(); + self.sets.retain(|set| { + let keep = wanted.contains(&&set.name) && ask.sources.iter().any(|d| *d.name() == set.name); + if !keep { + gone.push(set.name.clone()); + } + keep + }); + let mut changed = Vec::new(); + for name in wanted { + let Some(source) = ask.sources.iter().find(|d| d.name() == name) else { continue }; + let i = self.sets.iter().position(|s| s.name == *name).unwrap_or_else(|| { + self.sets.push(Set::new(name.clone())); + self.sets.len() - 1 + }); + if let Some(drawn) = self.sets[i].update(source, ask, jobs) { + changed.push(drawn); + } + } + (changed, gone) + } + + /// Whether every table drawn in part draws from its pyramid, its rows in drawing order: none draws + /// its first sample while its pyramid is worked out, nor waits to be laid out again. + pub(crate) fn complete(&self) -> bool { + self.sets.iter().all(|s| s.working.is_empty() && !s.deferred && !s.sampling && s.settled()) + } + + /// Whether a dataset waits for a frame: to ask for its pyramids, or to lay its rows out again in + /// drawing order once the camera rests. + pub(crate) fn due(&self) -> bool { + self.sets.iter().any(|s| s.deferred || !s.settled()) + } + + /// Whether dataset `name` draws in part. + pub(crate) fn draws(&self, name: &str) -> bool { + self.sets.iter().any(|s| *s.name == *name) + } + + /// The bounds of every row of table `table` of dataset `data` drawn through tiles, west, south, + /// east, north in position units: what a fit of everything frames, whatever tiles are drawn. + pub(crate) fn bounds(&self, data: &Name, table: &Name) -> Option<[f64; 4]> { + let set = self.sets.iter().find(|s| s.name == *data)?; + set.placed.get(table).and_then(|placed| placed.bounds) + } +} + +/// A table's pyramid: the rows it was placed from (the table's structure and order), the square it +/// tiles, the bounds of its rows in position units, and the version that tells it from any other. +struct Placed { + made: Version, + rows: (Version, Version), + domain: Domain, + pyramid: Pyramid, + bounds: Option<[f64; 4]>, +} + +/// A pyramid job under way: the table it places, where the answer holds its pyramid, and what the +/// pyramid is kept with once it lands. +struct Working { + table: Name, + pending: Pending>, + answered: u32, + placed: Placed, +} + +/// One table's rows drawn last time and where each lies, the versions of the table drawn while they +/// hold, and its fields as gathered with what each was gathered from. +#[derive(Default)] +struct Gathered { + /// Each row drawn: its source row, or a [`HOLE`]. + rows: Option>, + slots: Slots, + /// The rows written since the ids and fields kept were gathered, `(row, source row or HOLE)` by + /// row; `None` where every row was laid out afresh, and they gather again. + writes: Option>, + versions: Option<(Version, Version)>, + ids: Option, + fields: FxHashMap, + /// Each reference field's ids as gathered and resolved, as of a version of it, and of that version + /// and the versions the rows it names hold where they are drawn; and every row's target by it, as + /// of a version of it. + references: FxHashMap, + targets: FxHashMap)>, +} + +/// A field as gathered: a stamp of what it was gathered from, that field of the table, and the field +/// drawn. +struct Kept { + stamp: u64, + source: Field, + drawn: Field, +} + +/// One dataset drawn in part. +struct Set { + name: Name, + /// The stamp of everything its pyramids are placed from: every table placed, and the square. + stamp: u64, + /// Each table's pyramid, as last placed. + placed: FxHashMap>, + working: Vec, + /// Whether asking for its pyramids waits for a frame that gathers nothing. + deferred: bool, + /// What decides which rows draw and where, and what they hold, as last gathered. + laid: u64, + held: u64, + /// Updates since its rows were laid out. + quiet: u32, + tables: FxHashMap, + /// Each table drawn in part as last laid out: its rows drawn, and the versions it holds while they + /// do. + rows: FxHashMap>, + versions: FxHashMap, + /// Whether a table draws an even sample of its rows until its pyramid lands. + sampling: bool, +} + +impl Set { + fn new(name: Name) -> Set { + Set { + name, + stamp: 0, + placed: FxHashMap::default(), + working: Vec::new(), + deferred: false, + laid: 0, + held: 0, + quiet: 0, + tables: FxHashMap::default(), + rows: FxHashMap::default(), + versions: FxHashMap::default(), + sampling: false, + } + } + + /// Whether every table's rows lie in drawing order: none waits to be laid out again. + fn settled(&self) -> bool { + self.tables.values().all(|g| g.slots.ordered || g.slots.rows.is_empty()) + } + + /// Brings the pyramids and the rows drawn up to `ask`; the dataset drawn, when it changed. + fn update(&mut self, source: &Data, ask: &Ask<'_>, jobs: &mut Jobs<'_>) -> Option { + let placing = placed(source, ask); + // Pyramids that landed serve from now on. + let mut i = 0; + while i < self.working.len() { + let Some(landed) = self.working[i].pending.take() else { + i += 1; + continue; + }; + let working = self.working.swap_remove(i); + if let Ok(bytes) = landed + && let Some(pyramid) = Pyramid::read(&bytes).remove(&working.answered) + { + self.placed + .insert(working.table, Arc::new(Placed { pyramid, made: Version::next(), ..working.placed })); + } + } + let stamp = stamp(source, ask, &placing); + let due = !placing.is_empty() && stamp != self.stamp; + // Pyramids small enough are placed at once, before the rows drawn are gathered from them; + // asking jobs for larger ones waits for a frame that gathers nothing, so no frame does both. + let cost: f64 = placing + .iter() + .map(|(t, p)| { + t.len() as f64 * if matches!(p.draw, Draw::Tiles { .. }) { PLACE_COST } else { PLACE_COST / 20.0 } + }) + .sum(); + let at_once = cost <= jobs.left() as f64; + if due && at_once { + self.level(&placing, ask, stamp, jobs); + } + let drawn = self.gather(source, ask); + self.deferred = due && !at_once && drawn.is_some(); + if due && !at_once && drawn.is_none() { + self.level(&placing, ask, stamp, jobs); + } + drawn + } + + /// Asks for the pyramids of `placing`, from what `stamp` stamps: at once where one fits the + /// frame, else in a job of its own. + fn level(&mut self, placing: &[(&Table, &Planned)], ask: &Ask<'_>, stamp: u64, jobs: &mut Jobs<'_>) { + { + self.stamp = stamp; + // What was asked before no longer serves once it lands. + self.working.clear(); + let (leveling, bounds) = leveling(ask, placing); + let domain = leveling.domain; + for (i, table) in leveling.tables.iter().enumerate().filter(|(_, t)| t.answered) { + let name = placing[i].0.name.clone(); + // A table placed by its ends goes with the table they name, which only anchors it. + let mut alone = Leveling { domain, tables: Vec::with_capacity(2) }; + let mut table = table.clone(); + if let Some((target, _)) = table.ends.as_mut() { + let at = &leveling.tables[*target as usize]; + alone.tables.push(Placing { rows: at.rows, places: at.places.clone(), ..Placing::default() }); + *target = 0; + } + let answered = alone.tables.len() as u32; + let rows = (placing[i].0.structure, placing[i].0.order); + alone.tables.push(table); + // Placing a row takes about a microsecond; ordering one by priority alone, far less. + let per_row = if alone.tables[answered as usize].leveled { PLACE_COST } else { PLACE_COST / 20.0 }; + let cost = per_row * alone.tables.iter().map(|t| f64::from(t.rows)).sum::(); + let made = Version::next(); + let placed = + Placed { made, rows, domain, pyramid: Pyramid::default(), bounds: bounds.get(&name).copied() }; + if jobs.fits(cost as u64) { + let pyramid = Pyramid::answered(answer(&alone)).remove(&answered).unwrap_or_default(); + self.placed.insert(name, Arc::new(Placed { pyramid, ..placed })); + } else { + let job = Job::pyramid(&alone); + let pending = jobs.spawn(job); + self.working.push(Working { table: name, pending, answered, placed }); + } + } + } + } + + /// Table `name`'s pyramid while it serves: placed from the rows the table holds. + fn pyramid(&self, source: &Data, name: &Name) -> Option> { + let table = source.table(name)?; + self.placed.get(name).filter(|p| p.rows == (table.structure, table.order)).cloned() + } + + /// The dataset drawn, gathered again when what it is gathered from changed. + fn gather(&mut self, source: &Data, ask: &Ask<'_>) -> Option { + // Each table's tiles drawn, or how many of its rows, by what it draws. + let mut chosen: Vec<(Name, Choice)> = Vec::new(); + let mut serving: Vec<(Name, Arc)> = Vec::new(); + for table in source.tables() { + let Some(planned) = ask.plans.get(&(source.name().clone(), table.name.clone())) else { continue }; + if planned.as_is() { + continue; + } + let placed = self.pyramid(source, &table.name); + if let Some(placed) = &placed { + serving.push((table.name.clone(), placed.clone())); + } + let pyramid = placed.as_deref().map(|placed| (&placed.pyramid, &placed.domain)); + let choice = match (pyramid, planned.draw) { + (None, Draw::Whole) => Choice::AsIs, + (None, Draw::Tiles { rows } | Draw::First { rows }) => { + Choice::Sample((table.len() as u32).div_ceil(rows.clamp(1, SAMPLE)).max(1)) + } + (Some(_), Draw::Whole) => Choice::Tiles(Wanted { tiles: vec![(0, true)], cover: None }), + (Some((pyramid, _)), Draw::First { rows }) => Choice::Last(rows.min(pyramid.order.len() as u32)), + (Some((pyramid, domain)), Draw::Tiles { rows }) => { + Choice::Tiles(ask.sight.map(|sight| pyramid.wanted(sight, domain, rows)).unwrap_or_default()) + } + }; + chosen.push((table.name.clone(), choice)); + } + self.sampling = chosen.iter().any(|(_, choice)| matches!(choice, Choice::Sample(_))); + let pinned: Vec<&Row> = ask.pinned.iter().filter(|r| r.data == self.name).collect(); + let frames: Vec> = sampled_frames(source, ask); + let pyramids: Vec = serving.iter().map(|(_, p)| p.made).collect(); + // Where rows draw, apart from what they hold: a patch writing values lays nothing out again. + let laid = stamp_of((pyramids, &chosen, &pinned, rows_of(source))); + let held = stamp_of((source.0.version, frames, reads_of(source, ask))); + if laid == self.laid { + // Once the camera rests, rows laid out of drawing order are laid out again in it. + self.quiet = self.quiet.saturating_add(1); + if held == self.held && (self.settled() || self.quiet < SETTLE) { + return None; + } + } else { + self.quiet = 0; + } + let afresh = self.quiet >= SETTLE && !self.settled(); + let relaid = laid != self.laid || afresh; + (self.laid, self.held) = (laid, held); + if !relaid { + return Some(self.rewrite(source, ask)); + } + let serving: FxHashMap> = serving.into_iter().collect(); + Some(self.build(source, ask, &serving, &chosen, &pinned, afresh)) + } + + /// The dataset drawn when only what its rows hold changed: every row stays where it is drawn, and + /// each field writes only the rows whose values changed. + fn rewrite(&mut self, source: &Data, ask: &Ask<'_>) -> Data { + let (rows, versions) = (std::mem::take(&mut self.rows), std::mem::take(&mut self.versions)); + for name in rows.keys() { + if let Some(gathered) = self.tables.get_mut(name) { + gathered.writes = Some(Vec::new()); + } + } + let tables: Vec
= + source.tables().map(|table| self.drawn(source, table, ask, &rows, &versions)).collect(); + (self.rows, self.versions) = (rows, versions); + source.drawn(tables) + } + + /// The dataset drawn: every table's rows drawn, pinned rows kept, the ends of edges drawn carried + /// along, each table's rows laid out, afresh where `afresh` says so, and gathered. + fn build( + &mut self, + source: &Data, + ask: &Ask<'_>, + serving: &FxHashMap>, + chosen: &[(Name, Choice)], + pinned: &[&Row], + afresh: bool, + ) -> Data { + let mut wanted: FxHashMap> = chosen + .iter() + .filter_map(|(name, choice)| { + let len = source.table(name).map_or(0, Table::len) as u32; + Some((name.clone(), choice.rows(serving.get(name).map(Arc::as_ref), len)?)) + }) + .collect(); + // Rows pinned, and the rows the edges drawn end at, draw whatever their tiles. + let mut drawn: FxHashMap = wanted + .iter() + .map(|(name, list)| (name.clone(), Bitset::of(list, source.table(name).map_or(0, Table::len)))) + .collect(); + for row in pinned { + let (Some(list), Some(table)) = (wanted.get_mut(&row.table), source.table(&row.table)) else { continue }; + if let Some(r) = table.row(row.id.as_ref()) + && drawn.get_mut(&row.table).is_some_and(|set| set.insert(r as u32)) + { + list.push(r as u32); + } + } + let mut carried: Vec<(Name, Vec)> = Vec::new(); + for table in source.tables() { + // Only the ends of edges and faces drawn are carried. + let Some(Place::Ends(ends)) = ask.plans.get(&(source.name().clone(), table.name.clone())).map(|p| &p.place) + else { + continue; + }; + for (name, field) in &table.fields { + let Field::Reference(reference) = field else { continue }; + if !wanted.contains_key(&reference.to) || !ends.contains(name) { + continue; + } + let targets = self.targets(&table.name, name, field); + let ends: Vec = match wanted.get(&table.name) { + Some(list) => list.iter().map(|&r| targets[r as usize]).collect(), + None => targets.to_vec(), + }; + carried.push((reference.to.clone(), ends)); + } + } + for (to, ends) in carried { + let (Some(list), Some(set)) = (wanted.get_mut(&to), drawn.get_mut(&to)) else { continue }; + for t in ends { + if t != UNWIRED && set.insert(t) { + list.push(t); + } + } + } + // Each table drawn in part: its rows laid out, and the versions it holds while they do. + let mut rows: FxHashMap> = FxHashMap::default(); + let mut versions: FxHashMap = FxHashMap::default(); + for (name, list) in &wanted { + let gathered = self.tables.entry(name.clone()).or_default(); + let len = source.table(name).map_or(0, Table::len); + let writes = gathered.slots.lay(list, len, afresh); + let laid: Arc<[u32]> = match (&writes, &gathered.rows) { + (Some(writes), Some(before)) if writes.is_empty() => before.clone(), + _ => gathered.slots.rows.as_slice().into(), + }; + // Rows written in place keep the order the table's rows are drawn in, as every row still + // drawn keeps its place; rows laid out afresh draw in another. + let held = match (&writes, gathered.versions) { + (Some(writes), Some(held)) if writes.is_empty() => held, + (Some(_), Some((order, _))) => (order, Version::next()), + _ => { + let v = Version::next(); + (v, v) + } + }; + gathered.versions = Some(held); + versions.insert(name.clone(), held); + if writes.is_none() { + gathered.ids = None; + gathered.fields.clear(); + gathered.references.clear(); + } + gathered.writes = writes.map(|w| { + w.iter().map(|&(at, r)| (at as usize, if r == HOLE { crate::data::HOLE } else { r as usize })).collect() + }); + gathered.rows = Some(laid.clone()); + rows.insert(name.clone(), laid); + } + let mut tables = Vec::with_capacity(source.tables().count()); + for table in source.tables() { + tables.push(self.drawn(source, table, ask, &rows, &versions)); + } + (self.rows, self.versions) = (rows, versions); + source.drawn(tables) + } + + /// Every row's target by reference field `name` of table `table`, `field`, as of its version. + fn targets(&mut self, table: &Name, name: &Name, field: &Field) -> Arc<[u32]> { + let Field::Reference(reference) = field else { return Arc::from([]) }; + let gathered = self.tables.entry(table.clone()).or_default(); + if let Some((version, targets)) = gathered.targets.get(name) + && *version == reference.version + { + return targets.clone(); + } + let targets: Arc<[u32]> = reference.targets().into(); + gathered.targets.insert(name.clone(), (reference.version, targets.clone())); + targets + } + + /// Table `table` as it is, its references naming the rows drawn of the tables drawn in part, each + /// holding `versions` while they do: resolved again only when the reference or where the rows it + /// names are drawn changed. + fn remapped(&mut self, table: &Table, versions: &FxHashMap) -> Table { + let mut out = table.clone(); + for (name, field) in &table.fields { + let Field::Reference(reference) = field else { continue }; + let Some(&(order, structure)) = versions.get(&reference.to) else { continue }; + let whole = stamp_of((reference.version, order, structure)); + let kept = self.tables.get(&table.name).and_then(|g| g.references.get(name)); + if let Some((_, _, field)) = kept.filter(|(_, w, _)| *w == whole) { + out.insert(name.clone(), field.clone()); + continue; + } + let targets = self.targets(&table.name, name, field); + let map = &self.tables[&reference.to].slots.at; + let mapped: Vec = targets.iter().map(|&t| remap(map, t)).collect(); + let kept = self.tables.get(&table.name).and_then(|g| g.references.get(name)).map(|(_, _, f)| f.clone()); + let kept = kept.as_ref().and_then(|f| if let Field::Reference(r) = f { Some(r) } else { None }); + let remapped = reference.resolved_to(reference.ids.clone(), &mapped, order, structure, kept); + let field = Field::Reference(remapped); + let gathered = self.tables.entry(table.name.clone()).or_default(); + gathered.references.insert(name.clone(), (stamp_of(reference.version), whole, field.clone())); + out.insert(name.clone(), field); + } + out + } + + /// Table `table` as drawn: as it is, its references naming the rows drawn; or its rows drawn + /// in part, with the fields marks read. Rows written in place write the ids and fields kept, + /// touching only their pages, and so do rows whose values changed; rows laid out afresh gather + /// them again. What nothing changed under is kept as it is. + fn drawn( + &mut self, + source: &Data, + table: &Table, + ask: &Ask<'_>, + rows: &FxHashMap>, + versions: &FxHashMap, + ) -> Table { + // A table no mark draws stays as it is: only joins read it, by id. + let planned = ask.plans.contains_key(&(source.name().clone(), table.name.clone())); + let remaps = table.fields.iter().any(|(_, f)| matches!(f, Field::Reference(r) if rows.contains_key(&r.to))); + let Some(list) = rows.get(&table.name) else { + return if remaps && planned { self.remapped(table, versions) } else { table.clone() }; + }; + let reads = ask.plans.get(&(source.name().clone(), table.name.clone())).and_then(|p| p.reads.as_ref()); + // The source row of each row drawn, picked only where something gathers afresh. + let picks = std::cell::OnceCell::new(); + let picked = || { + picks.get_or_init(|| { + list.iter().map(|&r| if r == HOLE { crate::data::HOLE } else { r as usize }).collect::>() + }) + }; + let (order, structure) = versions[&table.name]; + let gathered = self.tables.get_mut(&table.name).expect("made with its rows"); + let writes = gathered.writes.take(); + let len = list.len(); + let ids = match (&gathered.ids, writes.as_deref()) { + (Some(ids), Some([])) => ids.clone(), + (Some(ids), Some(writes)) => ids.write(len, writes, &table.ids).expect("ids of one kind"), + _ => table.ids.gather(picked()), + }; + gathered.ids = Some(ids.clone()); + let mut out = + Table { name: table.name.clone(), ids, index: Arc::default(), fields: Vec::new(), structure, order }; + // Fields not read now miss the rows written: gathered again once read. + if writes.as_ref().is_some_and(|w| !w.is_empty()) { + gathered.fields.retain(|name, _| reads.is_none_or(|r| r.contains(name))); + } + let frames = |samples: &crate::data::Samples| samples.frame_at(ask.at); + for (name, field) in &table.fields { + let read = reads.is_none_or(|r| r.contains(name)); + let gathered = self.tables.get_mut(&table.name).expect("made with its rows"); + let kept = gathered.fields.get(name); + let (stamp, made) = match field { + Field::Values(column, version) if read => { + let stamp = stamp_of(version); + let made = match (kept, writes.as_deref()) { + (Some(kept), Some([])) if kept.stamp == stamp => kept.drawn.clone(), + // The rows laid out in place, and the rows whose values changed since the field + // kept was gathered, wherever they are drawn; a field now of another kind + // gathers afresh. + ( + Some(Kept { stamp: was, source: Field::Values(before, _), drawn: Field::Values(drawn, _) }), + Some(laid), + ) if before.kind() == column.kind() => { + // What the pages remember was written, else what differs: a row written + // the value it held is written again, cheaper than comparing every row. + let changed = if *was == stamp { + Vec::new() + } else { + column.rows_since(before).unwrap_or_else(|| column.differing(before)) + }; + let at = &gathered.slots.at; + let mut written: Vec<(usize, usize)> = changed + .into_iter() + .filter_map(|r| at.get(r).filter(|&&a| a != UNWIRED).map(|&a| (a as usize, r))) + .collect(); + written.extend_from_slice(laid); + written.sort_unstable_by_key(|w| w.0); + written.dedup_by_key(|w| w.0); + Field::Values(drawn.write(len, &written, column).expect("one storage"), Version::next()) + } + _ => Field::Values(column.gather(picked()), Version::next()), + }; + (stamp, made) + } + Field::Sampled(samples, version) if read => { + let frame = frames(samples); + let stamp = stamp_of((version, frame)); + let made = match (kept, writes.as_deref()) { + (Some(kept), Some([])) if kept.stamp == stamp => kept.drawn.clone(), + _ => { + let span = frame.map_or(0..0, |f| f..f + 2); + Field::Sampled(samples.gather_frames(picked(), span), Version::next()) + } + }; + (stamp, made) + } + Field::Reference(reference) => { + // Where the rows it names are drawn: as laid out where drawn in part, else as they are. + let held = versions.get(&reference.to).copied(); + let named = held.unwrap_or_else(|| { + source.table(&reference.to).map_or((order, structure), |t| (t.order, t.structure)) + }); + let resolved = + self.reference(&table.name, name, field, list, writes.as_deref(), (held.is_some(), named)); + out.insert(name.clone(), resolved); + continue; + } + _ => continue, + }; + let gathered = self.tables.get_mut(&table.name).expect("made with its rows"); + gathered.fields.insert(name.clone(), Kept { stamp, source: field.clone(), drawn: made.clone() }); + out.insert(name.clone(), made); + } + out + } + + /// Reference field `name` of table `table`, `field`, for the rows `list` drawn, resolved to where + /// the rows it names are drawn: `named` says whether those are drawn in part, and the versions they + /// hold. Kept as it is where no row was written here, the reference is the same, and the rows it + /// names hold; else its ids are written where rows were written in place. + fn reference( + &mut self, + table: &Name, + name: &Name, + field: &Field, + list: &[u32], + writes: Option<&[(usize, usize)]>, + (in_part, (order, structure)): (bool, (Version, Version)), + ) -> Field { + let Field::Reference(reference) = field else { return field.clone() }; + let stamp = stamp_of(reference.version); + let whole = stamp_of((reference.version, order, structure)); + let gathered = self.tables.entry(table.clone()).or_default(); + if let Some((_, _, field)) = gathered.references.get(name).filter(|(_, w, _)| *w == whole) + && writes.is_some_and(<[_]>::is_empty) + { + return field.clone(); + } + let targets = self.targets(table, name, field); + let gathered = self.tables.entry(table.clone()).or_default(); + let kept = gathered.references.get(name).filter(|(s, _, _)| *s == stamp).map(|(_, _, f)| f.clone()); + let kept = kept.as_ref().and_then(|f| if let Field::Reference(r) = f { Some(r) } else { None }); + let len = list.len(); + let ids = match (kept, writes) { + (Some(kept), Some(writes)) => kept.ids.write(len, writes, &reference.ids).expect("ids of one kind"), + (Some(kept), None) if kept.ids.len() == len => kept.ids.clone(), + _ => { + let picked: Vec = + list.iter().map(|&r| if r == HOLE { crate::data::HOLE } else { r as usize }).collect(); + reference.ids.gather(&picked) + } + }; + let target = self.tables.get(&reference.to).filter(|_| in_part); + let mapped: Vec = list + .iter() + .map(|&r| match (r, target) { + (HOLE, _) => UNWIRED, + (r, Some(target)) => remap(&target.slots.at, targets[r as usize]), + (r, None) => targets[r as usize], + }) + .collect(); + let resolved = Field::Reference(reference.resolved_to(ids, &mapped, order, structure, kept)); + let gathered = self.tables.entry(table.clone()).or_default(); + gathered.references.insert(name.clone(), (stamp, whole, resolved.clone())); + resolved + } +} + +/// Rows, a bit each: which rows of a table are drawn. +struct Bitset(Vec); + +impl Bitset { + /// The rows of `list`, of a table of `len` rows. + fn of<'a>(list: impl IntoIterator, len: usize) -> Bitset { + let mut set = Bitset(vec![0; len.div_ceil(64)]); + for &r in list { + set.insert(r); + } + set + } + + /// Whether row `r` is there. + fn contains(&self, r: u32) -> bool { + self.0.get(r as usize / 64).is_some_and(|word| word >> (r % 64) & 1 == 1) + } + + /// Adds row `r`; whether it was not there before. + fn insert(&mut self, r: u32) -> bool { + let Some(word) = self.0.get_mut(r as usize / 64) else { return false }; + let bit = 1 << (r % 64); + let new = *word & bit == 0; + *word |= bit; + new + } +} + +/// What a table drawn in part draws of its pyramid. +#[derive(Clone, Debug, PartialEq, Hash)] +enum Choice { + /// Every row as it is, until its pyramid lands. + AsIs, + /// Every row a step apart, until its pyramid lands. + Sample(u32), + /// The rows of these tiles. + Tiles(Wanted), + /// The last rows of its one tile: those that matter most. + Last(u32), +} + +impl Choice { + /// The rows it draws of a table of `len` rows, by `placed`, its pyramid, in drawing order: finest + /// tiles first, so what matters more draws on top. `None` for a table drawn as it is. + fn rows(&self, placed: Option<&Placed>, len: u32) -> Option> { + Some(match (self, placed) { + (Choice::AsIs, _) => return None, + (Choice::Tiles(wanted), Some(placed)) => { + let pyramid = &placed.pyramid; + let mut tiles = wanted.tiles.clone(); + tiles.sort_by_key(|&(t, _)| std::cmp::Reverse((pyramid.tiles[t as usize].key.z, u32::MAX - t))); + let mut list = Vec::new(); + for (t, finest) in tiles { + let range = pyramid.tiles[t as usize].rows.clone(); + let rows = &pyramid.order[range.start as usize..range.end as usize]; + // A coarser tile draws only its rows reaching where the finest cover. + match wanted.cover.filter(|_| !finest && !pyramid.anchors.is_empty()) { + Some(cover) => list.extend(rows.iter().copied().filter(|&r| { + let extent = pyramid.extents.get(r as usize).copied().unwrap_or(0); + reaches(&cover, pyramid.anchors[r as usize], extent) + })), + None => list.extend_from_slice(rows), + } + } + list + } + (Choice::Last(n), Some(placed)) => { + let order = &placed.pyramid.order; + order[order.len() - *n as usize..].to_vec() + } + (Choice::Sample(step), _) => (0..len).step_by(*step as usize).collect(), + (_, None) => Vec::new(), + }) + } +} + +/// A row drawn that no source row fills: a hole a row no longer drawn left. +const HOLE: u32 = u32::MAX; +/// Updates without change after which rows laid out of drawing order are laid out again in order. +const SETTLE: u32 = 8; + +/// Where a table drawn in part draws each row: a row still drawn keeps its place while the camera +/// moves, so only arriving rows are gathered and evaluated. A row no longer drawn leaves a hole, which +/// a row arriving later takes, the first hole first, else a row past the last. The rows are laid out +/// afresh, in drawing order, when holes pass a quarter of them, and once the camera rests while they +/// lie out of that order. +#[derive(Default)] +struct Slots { + /// Each row drawn: its source row, or a [`HOLE`]. + rows: Vec, + /// Where each source row is drawn, `UNWIRED` where it is not. + at: Vec, + /// Holes, by row. + holes: Vec, + /// Whether the rows lie in drawing order with no hole, as laying out afresh lays them. + ordered: bool, +} + +impl Slots { + /// Lays out `wanted`, rows of a table of `len` rows, in drawing order: each still drawn keeps its + /// place, each no longer drawn leaves a hole, and each arriving takes the first hole, else a row + /// past the last. Every row is laid out afresh where `afresh` says so or holes would pass a quarter + /// of the rows. The rows written, `(row, source row or HOLE)` by row; `None` where every row was + /// laid out afresh. + fn lay(&mut self, wanted: &[u32], len: usize, afresh: bool) -> Option> { + self.at.resize(len, UNWIRED); + if afresh || self.rows.is_empty() { + return self.afresh(wanted); + } + let keep = Bitset::of(wanted, len); + let mut writes: Vec<(u32, u32)> = Vec::new(); + let mut freed: Vec = Vec::new(); + for (i, slot) in self.rows.iter_mut().enumerate() { + if *slot != HOLE && !keep.contains(*slot) { + if let Some(at) = self.at.get_mut(*slot as usize) { + *at = UNWIRED; + } + *slot = HOLE; + freed.push(i as u32); + writes.push((i as u32, HOLE)); + } + } + if !freed.is_empty() { + self.holes.extend(freed); + self.holes.sort_unstable(); + } + let mut taken = 0; + for &source in wanted { + if self.at.get(source as usize).is_none_or(|&at| at != UNWIRED) { + continue; + } + let row = if let Some(&hole) = self.holes.get(taken) { + taken += 1; + hole + } else { + self.rows.push(HOLE); + self.rows.len() as u32 - 1 + }; + self.rows[row as usize] = source; + self.at[source as usize] = row; + writes.push((row, source)); + } + self.holes.drain(..taken); + if 4 * self.holes.len() > self.rows.len() { + return self.afresh(wanted); + } + // A row left and taken again writes what takes it. + writes.sort_by_key(|w| w.0); + writes.dedup_by(|later, earlier| { + let same = later.0 == earlier.0; + if same { + earlier.1 = later.1; + } + same + }); + self.ordered = self.holes.is_empty() && self.rows == wanted; + Some(writes) + } + + /// Lays every row out afresh, in drawing order, with no hole. + fn afresh(&mut self, wanted: &[u32]) -> Option> { + for &old in self.rows.iter().filter(|&&r| r != HOLE) { + if let Some(at) = self.at.get_mut(old as usize) { + *at = UNWIRED; + } + } + for (row, &source) in wanted.iter().enumerate() { + if let Some(at) = self.at.get_mut(source as usize) { + *at = row as u32; + } + } + self.rows = wanted.to_vec(); + self.holes.clear(); + self.ordered = true; + None + } +} + +/// The row `t` is drawn at, by `map`. +fn remap(map: &[u32], t: u32) -> u32 { + map.get(t as usize).copied().unwrap_or(UNWIRED) +} + +/// The tables of `source` a pyramid places, each with its plan: every table drawn in part, and every +/// table the ends of one drawn through tiles name, which only anchors them. +fn placed<'a>(source: &'a Data, ask: &'a Ask<'_>) -> Vec<(&'a Table, &'a Planned)> { + let plan = |table: &Table| ask.plans.get(&(source.name().clone(), table.name.clone())); + let mut out: Vec<(&Table, &Planned)> = Vec::new(); + for table in source.tables() { + let Some(planned) = plan(table) else { continue }; + let named = source.tables().any(|other| { + plan(other).is_some_and(|p| matches!(p.draw, Draw::Tiles { .. }) && ends_of(other, p) == Some(&table.name)) + }); + if !planned.as_is() || named { + out.push((table, planned)); + } + } + // Tables an edge table's ends name come before it. + out.sort_by_key(|(_, p)| matches!(p.place, Place::Ends(_))); + out +} + +/// The table the ends of `table` name, as `planned` places it. +fn ends_of<'t>(table: &'t Table, planned: &Planned) -> Option<&'t Name> { + let Place::Ends(fields) = &planned.place else { return None }; + match table.field_named(fields.first()?)? { + Field::Reference(reference) => Some(&reference.to), + _ => None, + } +} + +/// The stamp of everything a dataset's pyramids are placed from. +fn stamp(source: &Data, ask: &Ask<'_>, placed: &[(&Table, &Planned)]) -> u64 { + let rows: Vec<_> = placed.iter().map(|(t, _)| (t.name.clone(), t.structure, t.order)).collect(); + let mut inputs = Vec::new(); + for (table, planned) in placed { + let mut fields = Vec::new(); + if let Some(priority) = &planned.priority { + fields_of(priority, &mut fields); + } + match &planned.place { + Place::Points(xy) => xy.iter().for_each(|e| fields_of(e, &mut fields)), + Place::Geometry(field) => fields.push(field.clone()), + Place::Ends(ends) => fields.extend(ends.iter().cloned()), + Place::Nowhere => {} + } + let versions: Vec<_> = fields.iter().map(|f| table.field_named(f).map(Field::version)).collect(); + let tiles = matches!(planned.draw, Draw::Tiles { .. }); + inputs.push((format!("{:?}{:?}", planned.priority, planned.place), versions, tiles, planned.as_is())); + } + stamp_of((source.name(), rows, inputs, ask.earth)) +} + +/// The fields `expr` reads of its mark's own table. +fn fields_of(expr: &Expr, out: &mut Vec) { + match &*expr.0 { + Node::Field(f) if f.of.is_none() => out.push(f.name.clone()), + Node::Unary(_, a) | Node::Is(a, _) => fields_of(a, out), + Node::Binary(_, a, b) => { + fields_of(a, out); + fields_of(b, out); + } + Node::When(c, a, b) => { + fields_of(c, out); + fields_of(a, out); + fields_of(b, out); + } + Node::Scale { input, .. } | Node::Colormap { input, .. } => fields_of(input, out), + _ => {} + } +} + +/// The frame shown of each sampled field marks read of a table drawn in part. +fn sampled_frames(source: &Data, ask: &Ask<'_>) -> Vec> { + let mut frames = Vec::new(); + for table in source.tables() { + let Some(planned) = ask.plans.get(&(source.name().clone(), table.name.clone())) else { continue }; + if planned.as_is() { + continue; + } + for (name, field) in &table.fields { + if let Field::Sampled(samples, _) = field + && planned.reads.as_ref().is_none_or(|r| r.contains(name)) + { + frames.push(samples.frame_at(ask.at)); + } + } + } + frames +} + +/// What decides which of `source`'s rows draw and where, beside the tiles and the rows pinned: each +/// table's rows and their order, and the rows its references name. +fn rows_of(source: &Data) -> Vec<(Version, Version, Vec)> { + source + .tables() + .map(|table| { + let references = table.fields.iter().filter(|(_, f)| matches!(f, Field::Reference(_))); + (table.structure, table.order, references.map(|(_, f)| f.version()).collect()) + }) + .collect() +} + +/// The fields read of each table drawn in part, in a stable order; `None` for every field. +fn reads_of(source: &Data, ask: &Ask<'_>) -> Vec>> { + source + .tables() + .filter_map(|t| ask.plans.get(&(source.name().clone(), t.name.clone()))) + .map(|p| { + p.reads.as_ref().map(|reads| { + let mut reads: Vec = reads.iter().cloned().collect(); + reads.sort(); + reads + }) + }) + .collect() +} + +/// The box every placed row of `places` lies in, west, south, east, north; inverted when none is. +fn bounds_of(places: &Places) -> [f64; 4] { + let mut b = [f64::INFINITY, f64::INFINITY, f64::NEG_INFINITY, f64::NEG_INFINITY]; + let mut take = |r: [f64; 4]| { + if r.iter().all(|v| v.is_finite()) { + b = [b[0].min(r[0]), b[1].min(r[1]), b[2].max(r[2]), b[3].max(r[3])]; + } + }; + match places { + Places::None => {} + Places::Points(points) => points.iter().for_each(|p| take([p[0], p[1], p[0], p[1]].map(f64::from))), + Places::Boxes(boxes) => boxes.iter().for_each(|r| take(r.map(f64::from))), + } + b +} + +/// Where `table`'s rows lie, as `place` puts them. +fn locate(table: &Table, place: &Place, all: &[Data]) -> Places { + match place { + Place::Points([x, y]) => { + let rows = Rows::new(table, all); + let (xs, ys) = (rows.numbers(x, |v| v as f32), rows.numbers(y, |v| v as f32)); + Places::Points(xs.into_iter().zip(ys).map(|(x, y)| [x, y]).collect()) + } + Place::Geometry(field) => { + let Some(Field::Values(column, _)) = table.field_named(field) else { return Places::None }; + let mut boxes = Vec::with_capacity(table.len()); + for page in column.pages() { + let geometry = page.values.geometry(); + for i in 0..page.values.len() { + let mut b = [f64::INFINITY, f64::INFINITY, f64::NEG_INFINITY, f64::NEG_INFINITY]; + if let Some(g) = geometry.filter(|_| page.values.is_valid(i)) { + for p in g.row_coords(i) { + if p[0].is_finite() && p[1].is_finite() { + b = [b[0].min(p[0]), b[1].min(p[1]), b[2].max(p[0]), b[3].max(p[1])]; + } + } + } + boxes.push(b); + } + } + Places::Boxes(boxes.into_iter().map(|b: [f64; 4]| b.map(|v| v as f32)).collect()) + } + Place::Ends(_) | Place::Nowhere => Places::None, + } +} + +/// What to ask pyramid jobs for `placed`, in the square they tile, and each table's bounds. +fn leveling(ask: &Ask<'_>, placed: &[(&Table, &Planned)]) -> (Leveling, FxHashMap) { + let names: Vec = placed.iter().map(|(t, _)| t.name.clone()).collect(); + let mut tables: Vec = placed + .iter() + .map(|(table, planned)| { + // Tables drawn through tiles are placed; one only an edge table's ends name anchors them. + let anchors = matches!(planned.draw, Draw::Tiles { .. }) || planned.as_is(); + let places = if anchors { locate(table, &planned.place, ask.sources) } else { Places::None }; + Placing { rows: table.len() as u32, answered: !planned.as_is(), places, ..Placing::default() } + }) + .collect(); + let mut bounds: FxHashMap = FxHashMap::default(); + let mut all = [f64::INFINITY, f64::INFINITY, f64::NEG_INFINITY, f64::NEG_INFINITY]; + for (name, placing) in names.iter().zip(&tables) { + let b = bounds_of(&placing.places); + if b[0] <= b[2] { + all = [all[0].min(b[0]), all[1].min(b[1]), all[2].max(b[2]), all[3].max(b[3])]; + bounds.insert(name.clone(), b); + } + } + let domain = if ask.earth { Domain::Earth } else { Domain::plane(all) }; + for (i, (table, planned)) in placed.iter().enumerate() { + let placing = &mut tables[i]; + if let (Place::Ends(fields), Some(to)) = (&planned.place, ends_of(table, planned)) + && let Some(target) = names.iter().position(|n| n == to) + && !placed[target].1.place.eq(&Place::Nowhere) + { + let ends: Option>> = fields + .iter() + .map(|f| match table.field_named(f) { + Some(Field::Reference(r)) if r.to == *to => Some(r.targets().into()), + _ => None, + }) + .collect(); + placing.ends = ends.map(|ends| (target as u32, ends)); + } + placing.leveled = matches!(planned.draw, Draw::Tiles { .. }) + && (!matches!(placing.places, Places::None) || placing.ends.is_some()); + if let Some(priority) = &planned.priority { + placing.priority = Rows::new(table, ask.sources).numbers(priority, |p| p as f32).into(); + } + } + (Leveling { domain, tables }, bounds) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn rows_still_drawn_keep_their_places_and_arriving_ones_fill_holes() { + let mut slots = Slots::default(); + let first: Vec = (0..20).collect(); + assert_eq!(slots.lay(&first, 100, false), None, "laid out afresh"); + assert!(slots.ordered); + // Rows 4..8 go: their places are holes, every other row stays. + let kept: Vec = (0..4).chain(8..20).collect(); + let writes = slots.lay(&kept, 100, false).expect("in place"); + assert_eq!(writes, (4..8).map(|r| (r, HOLE)).collect::>()); + assert_eq!((slots.rows[3], slots.rows[8], slots.at[9]), (3, 8, 9)); + assert!(!slots.ordered, "holes lie among the rows"); + // Rows 50..55 arrive: four take the holes, the fifth goes past the last row. + let more: Vec = kept.iter().copied().chain(50..55).collect(); + let writes = slots.lay(&more, 100, false).expect("in place"); + assert_eq!(writes, [(4, 50), (5, 51), (6, 52), (7, 53), (20, 54)]); + assert_eq!(slots.lay(&more, 100, false), Some(vec![]), "nothing changed, nothing written"); + // A row leaving and another arriving in one go: the place left is taken at once. + let swapped: Vec = more.iter().copied().filter(|&r| r != 10).chain([60]).collect(); + assert_eq!(slots.lay(&swapped, 100, false), Some(vec![(10, 60)])); + // Holes past a quarter of the rows lay every row out afresh, in order. + assert_eq!(slots.lay(&[60, 61], 100, false), None); + assert_eq!((slots.rows.as_slice(), slots.ordered, slots.at[10]), (&[60, 61][..], true, UNWIRED)); + assert_eq!(slots.lay(&[60, 61], 100, true), None, "and so does asking for it"); + } +} diff --git a/crates/latkit/src/derive/tiles/frames.rs b/crates/latkit/src/derive/tiles/frames.rs new file mode 100644 index 00000000..46dcc9d7 --- /dev/null +++ b/crates/latkit/src/derive/tiles/frames.rs @@ -0,0 +1,242 @@ +//! Time tiles: sampled fields' histories fetched in spans as a view asks for them, from the files +//! [`Data::to_tiles`](crate::Data::to_tiles) writes. Every field wants its coarsest spans, which stand +//! in for any span still loading; a line tracing it wants the spans of the level of detail its plot +//! window draws at, middle first; a mark showing it at the view's coordinate wants the frames about +//! that coordinate. A span drawn puts its entries in the dataset; one no longer drawn lets them go. + +use std::ops::Range; +use std::sync::Arc; + +use rustc_hash::{FxHashMap, FxHashSet}; + +use super::super::Jobs; +use super::super::tiling::{Decoding, Requested, Source, Tiling}; +use super::Reading; +use crate::data::{ + Data, Field, Listed, MAX_LEVEL, Manifest, Name, Op, Patch, Run, Samples, bucket_frames, detail, sides, +}; +use crate::host::Request; +use crate::tiles::Span; +use crate::{Error, Pending}; + +/// Spans a line wants at most, middle first: those its plot window draws need far fewer. +const MAX_SPANS: usize = 64; + +/// Sampled fields fetched in spans, drawn as a dataset the view owns. +pub(crate) struct Frames { + manifest: Manifest, + /// Where each span lies, resolved against the manifest's URL. + url: String, + /// The dataset without its sampled fields' entries, until it lands. + base: Option>>, + /// Per field listed, its spans. + fields: Vec, + failed: bool, +} + +/// One field's spans: fetched and decoded, and those drawn with the runs each put in. +#[derive(Default)] +struct Spans { + tiling: Tiling, + drawn: FxHashMap>, +} + +impl Frames { + /// The fields `manifest`, found at `url`, lists; their dataset is fetched at once. + pub(crate) fn open(url: &str, manifest: Manifest, jobs: &Jobs<'_>) -> Frames { + let base = jobs.fetch(&Request::new(crate::url::resolve(url, &manifest.data))); + Frames { + url: crate::url::resolve(url, &manifest.url), + base: Some(base), + fields: manifest.fields.iter().map(|_| Spans::default()).collect(), + manifest, + failed: false, + } + } + + /// Spans drawn. + pub(crate) fn drawn(&self) -> usize { + self.fields.iter().map(|f| f.drawn.len()).sum() + } + + /// Fetches and decodes under way. + pub(crate) fn under_way(&self) -> usize { + usize::from(self.base.is_some()) + self.fields.iter().map(|f| f.tiling.under_way()).sum::() + } + + /// Brings `data`, dataset `name`, up to what `reading` reads of it: whether it changed, whether a + /// span stands in, and a failure to tell. + pub(crate) fn update( + &mut self, + name: &Name, + data: &mut Data, + reading: &Reading, + jobs: &Jobs<'_>, + ) -> (bool, bool, Option) { + let mut changed = false; + if let Some(pending) = &self.base { + let Some(landed) = pending.take() else { return (false, true, None) }; + self.base = None; + match landed.and_then(|bytes| Data::from_bytes(&bytes)) { + Ok(base) => { + *data = base.renamed(name.clone()); + changed = true; + } + Err(error) => { + self.failed = true; + return (false, false, Some(error)); + } + } + } + if self.failed { + return (false, false, None); + } + let (mut standing_in, mut failure) = (false, None); + for (k, listed) in self.manifest.fields.iter().enumerate() { + let reads = reading.reads(name, &listed.table, &listed.field); + let spans = &mut self.fields[k]; + // Spans drawn may tell more finely where the window lies, which may want finer spans: ask + // again until what is wanted settles, so what stands in is never taken for what draws. + let (mut asked, mut standing) = (Vec::new(), false); + for _ in 0..=MAX_LEVEL { + let wanted = + wanted(&listed.frames, sampled(data, listed), reads, reading, self.manifest.chunk, listed.levels); + if wanted == asked { + break; + } + let drawn = spans.tiling.update(&wanted, 0, &mut At { url: &self.url, field: k }, jobs); + standing = drawn.standing_in; + failure = failure.or(drawn.failure); + changed |= spans.draw(&drawn.keys, &listed.table, &listed.field, data); + asked = wanted; + } + standing_in |= standing; + } + (changed, standing_in, failure) + } +} + +impl Spans { + /// Makes `data`'s field `field` of `table` hold the entries of spans `drawn` and of no other: + /// whether it changed. + fn draw(&mut self, drawn: &[Span], table: &Name, field: &Name, data: &mut Data) -> bool { + let gone: Vec = self.drawn.keys().filter(|s| !drawn.contains(s)).copied().collect(); + let arrived: Vec<(Span, &Patch)> = drawn + .iter() + .filter(|s| !self.drawn.contains_key(s)) + .filter_map(|s| Some((*s, self.tiling.decoded(s, 0)?))) + .collect(); + if gone.is_empty() && arrived.is_empty() { + return false; + } + let mut put: Vec<(Span, Vec)> = Vec::new(); + let drawn_runs = &mut self.drawn; + let changed = data.sampled(table, field, |samples| { + for span in &gone { + for run in drawn_runs.remove(span).unwrap_or_default() { + samples.remove(&run); + } + } + for (span, tile) in &arrived { + put.push((*span, held(tile, table, field, samples))); + } + true + }); + if changed { + self.drawn.extend(put); + } + changed + } +} + +/// Puts the runs of field `field` of `table` that `tile` holds in `samples`: those it put. +fn held(tile: &Patch, table: &Name, field: &Name, samples: &mut Samples) -> Vec { + let mut runs = Vec::new(); + for op in &tile.ops { + let Op::Frames { table: t, field: f, run, at, values } = op else { continue }; + if t != table || f != field { + continue; + } + let per_row = run.len() * sides(run.level); + let rows = values.len().checked_div(per_row).unwrap_or(0); + if samples.insert(run, at, values, rows).is_ok() { + runs.push(run.clone()); + } + } + runs +} + +/// The samples `data` holds of the field `listed` names. +fn sampled<'a>(data: &'a Data, listed: &Listed) -> Option<&'a Samples> { + match data.table(&listed.table)?.field_named(&listed.field)? { + Field::Sampled(samples, _) => Some(samples), + _ => None, + } +} + +/// The spans of a field reading `frames` a view wants, nearest first: those of its coarsest level +/// holding any entry always; where a mark shows it, `(_, true)`, the frames about the coordinate shown; +/// where a line traces it, `(true, _)`, those of the level of detail the plot window draws at, middle +/// first. Where the window lies among the frames, what is held tells, as finely as it is held. +fn wanted( + frames: &Range, + samples: Option<&Samples>, + (traced, shown): (bool, bool), + reading: &Reading, + chunk: u32, + levels: u32, +) -> Vec { + // The entries of each level a history of `frames` holds: whole buckets only. + let chunk = u64::from(chunk); + let entries = |level: u32| frames.start >> (3 * level)..frames.end >> (3 * level); + // The spans of `level` holding its entries over frames `window`. + let spans = |level: u32, window: &Range| { + let (held, span) = (entries(level), bucket_frames(level)); + let first = (window.start / span).max(held.start); + let end = window.end.div_ceil(span).min(held.end); + (first / chunk..end.div_ceil(chunk)).map(move |index| Span { level: level as u8, index }) + }; + let top = (0..=levels).rev().find(|&level| !entries(level).is_empty()).unwrap_or(0); + let mut wanted: Vec = spans(top, frames).take(MAX_SPANS).collect(); + let held = samples.filter(|s| !s.is_empty()); + if shown && let Some(samples) = held { + let frame = samples.bound(reading.at, true).saturating_sub(1); + wanted.extend(spans(0, &(frame..frame.saturating_add(2)))); + } + if traced { + let window = match (held, reading.across) { + (Some(samples), Some(across)) => samples.across(across), + _ => frames.clone(), + }; + let level = detail(window.end - window.start, reading.columns).min(top); + let (held, span) = (entries(level), bucket_frames(level)); + let first = (window.start / span).max(held.start) / chunk; + let end = window.end.div_ceil(span).min(held.end).div_ceil(chunk); + // Choose nearest spans before allocating: an absolute-index range may be enormous and sparse. + let count = end.saturating_sub(first); + let middle = first + count.saturating_sub(1) / 2; + wanted.extend((0..count.min(MAX_SPANS as u64)).map(|offset| { + let index = if offset % 2 == 0 { middle - offset / 2 } else { middle + offset.div_ceil(2) }; + Span { level: level as u8, index } + })); + } + let mut seen = FxHashSet::default(); + wanted.retain(|span| seen.insert(*span)); + wanted +} + +/// Where a field's spans lie: the field's place in the manifest, in the spans' URL template. +struct At<'a> { + url: &'a str, + field: usize, +} + +impl Source for At<'_> { + fn request(&mut self, span: Span, _: &Jobs<'_>) -> Requested { + Requested::Fetch(Request::new(Manifest::span(self.url, self.field, u32::from(span.level), span.index))) + } + + fn decode(&self, _: Span, bytes: &Arc>, _: &Jobs<'_>) -> Decoding { + Decoding::Now(Patch::from_bytes(bytes).unwrap_or_default()) + } +} diff --git a/crates/latkit/src/derive/tiles/mod.rs b/crates/latkit/src/derive/tiles/mod.rs new file mode 100644 index 00000000..f6b11f7b --- /dev/null +++ b/crates/latkit/src/derive/tiles/mod.rs @@ -0,0 +1,263 @@ +//! Tiles: what a view fetches in pieces as it asks for them, kept as datasets the view owns, which +//! marks draw like any other. A source's first bytes say what it holds: a manifest of time tiles, +//! whose spans of sampled fields the plot window and the shown coordinate ask for; or a PMTiles +//! archive, a TileJSON document, or a URL template, which hold vector tiles the camera asks for (the +//! `geo` part). + +mod frames; +mod vector; + +use super::sight::Sight; +use super::{Input, Jobs}; +use crate::data::{Data, Manifest, Name}; +use crate::host::Request; +use crate::{Error, Pending, Tiles}; + +/// What a view reads of sampled fields: the plot window lines trace across and the pixel columns it +/// spans, the coordinate fields are shown at, and each field marks read, by dataset, table, and +/// name, with whether a line traces it. +#[derive(Default)] +pub(crate) struct Reading { + pub(crate) across: Option<[f64; 2]>, + pub(crate) columns: u32, + pub(crate) at: f64, + pub(crate) fields: Vec<(Name, Name, Name, bool)>, +} + +impl Reading { + /// Whether a line traces field `field` of `table` in dataset `data`, and whether a mark shows it + /// at the coordinate. + fn reads(&self, data: &str, table: &str, field: &str) -> (bool, bool) { + let mut reads = (false, false); + for (d, t, f, traced) in &self.fields { + if d == data && t == table && f == field { + if *traced { + reads.0 = true; + } else { + reads.1 = true; + } + } + } + reads + } +} + +/// What a source holds, once its first bytes said. +enum Holds { + Frames(Box), + Vector(Box), +} + +impl Holds { + /// Pieces drawn. + fn drawn(&self) -> usize { + match self { + Holds::Frames(frames) => frames.drawn(), + Holds::Vector(vector) => vector.drawn(), + } + } + + /// Fetches and decodes under way. + fn under_way(&self) -> usize { + match self { + Holds::Frames(frames) => frames.under_way(), + Holds::Vector(vector) => vector.under_way(), + } + } + + /// Brings `data`, dataset `name`, up to what the view asks: whether it changed, whether a piece + /// stands in, and a failure to tell. + fn update( + &mut self, + input: &Input<'_>, + name: &Name, + data: &mut Data, + asked: &Asked<'_>, + jobs: &Jobs<'_>, + ) -> (bool, bool, Option) { + match self { + Holds::Frames(frames) => frames.update(name, data, asked.reading, jobs), + Holds::Vector(vector) => vector.update(input, name, data, asked.sight, jobs), + } + } +} + +/// What the view asks of its tiles: the tiles the camera shows, on the earth, and what it reads of +/// sampled fields. +pub(crate) struct Asked<'a> { + pub(crate) sight: Option<&'a Sight<'a>>, + pub(crate) reading: &'a Reading, +} + +/// Where a set's pieces come from, as its source opens. +enum Source { + Unopened, + /// The URL's first bytes, which say what it holds. + Opening(Pending>), + Open(Holds), + Failed, +} + +/// A source's pieces: where they come from, and the dataset they make. +struct TileSet { + tiles: Tiles, + source: Source, + data: Data, + /// Whether the dataset changed since it was last taken. + changed: bool, + /// Whether a failure was told: a source that went away tells it once. + told: bool, + /// Whether a piece the view wanted at the last update drew an ancestor, or nothing, instead. + standing_in: bool, +} + +impl TileSet { + fn new(tiles: Tiles) -> TileSet { + TileSet { + data: Data::new(tiles.name.clone()), + tiles, + source: Source::Unopened, + changed: false, + told: false, + standing_in: false, + } + } +} + +/// Every source of tiles a view was given. +#[derive(Default)] +pub(crate) struct TileSets { + sets: Vec, + /// Datasets the last update changed, for the view to take. + changed: Vec, + errors: Vec, +} + +impl TileSets { + /// Fetches tiles from `tiles` as the view asks; tiles of the same name replace these. + pub(crate) fn set(&mut self, tiles: Tiles) { + if self.sets.iter().any(|s| s.tiles == tiles) { + return; + } + self.sets.retain(|s| s.tiles.name != tiles.name); + self.sets.push(TileSet::new(tiles)); + } + + /// Whether every piece the view wants draws itself: none stands in by an ancestor, or by nothing + /// while its source opens. A piece that could not be fetched draws nothing, and is final. + pub(crate) fn complete(&self) -> bool { + self.sets.iter().all(|s| !matches!(s.source, Source::Unopened | Source::Opening(_)) && !s.standing_in) + } + + /// The pieces every source draws, and those being fetched or decoded. + pub(crate) fn counts(&self) -> [u64; 2] { + let mut counts = [0, 0]; + for set in &self.sets { + if let Source::Open(holds) = &set.source { + counts[0] += holds.drawn() as u64; + counts[1] += holds.under_way() as u64; + } + } + counts + } + + /// Whether the view owns dataset `name`: pieces fetched as the view asks, drawn as they are. + pub(crate) fn owns(&self, name: &str) -> bool { + self.sets.iter().any(|s| *s.tiles.name == *name) + } + + /// Stops fetching the pieces drawn as dataset `name`. + pub(crate) fn remove(&mut self, name: &str) { + self.sets.retain(|s| s.tiles.name != name); + } + + /// The datasets the last update changed. + pub(crate) fn take_changed(&mut self) -> Vec { + std::mem::take(&mut self.changed) + } + + /// Failures since last asked. + pub(crate) fn take_errors(&mut self) -> Vec { + std::mem::take(&mut self.errors) + } + + /// Brings every source up to what the view asks and the scene draws. + pub(crate) fn update(&mut self, input: &Input<'_>, asked: &Asked<'_>, jobs: &Jobs<'_>) { + for set in &mut self.sets { + if let Some(error) = set.update(input, asked, jobs) + && !set.told + { + set.told = true; + self.errors.push(Error::Io(format!("tiles {}: {error}", set.tiles.name).into())); + } + if std::mem::take(&mut set.changed) { + self.changed.push(set.data.clone()); + } + } + } +} + +impl TileSet { + /// Brings the pieces up to what the view asks; a failure to tell, if any. + fn update(&mut self, input: &Input<'_>, asked: &Asked<'_>, jobs: &Jobs<'_>) -> Option { + self.standing_in = false; + let failure = self.open(jobs); + let Source::Open(holds) = &mut self.source else { return failure }; + let (changed, standing_in, failed) = holds.update(input, &self.tiles.name, &mut self.data, asked, jobs); + self.changed |= changed; + self.standing_in = standing_in; + failure.or(failed) + } + + /// Opens the source as far as what landed allows; a failure to tell, if any. + fn open(&mut self, jobs: &Jobs<'_>) -> Option { + let url = self.tiles.url.clone(); + if matches!(self.source, Source::Unopened) { + if url.contains("{z}") { + return self.vector(|| Ok(vector::Vector::template(&url))); + } + // An archive is read in ranges, from its header; a document whole. + let archive = url.split(['?', '#']).next().is_some_and(|path| path.ends_with(".pmtiles")); + let request = if archive { + Request::range(url.clone(), 0..crate::tiles::ARCHIVE_FIRST) + } else { + Request::new(url.clone()) + }; + self.source = Source::Opening(jobs.fetch(&request)); + } + let Source::Opening(pending) = &self.source else { return None }; + let bytes = match pending.take()? { + Ok(bytes) => bytes, + Err(error) => { + self.source = Source::Failed; + return Some(error); + } + }; + match Manifest::from_bytes(&bytes) { + Some(Ok(manifest)) => { + self.source = Source::Open(Holds::Frames(Box::new(frames::Frames::open(&url, manifest, jobs)))); + return None; + } + Some(Err(error)) => { + self.source = Source::Failed; + return Some(error); + } + None => {} + } + self.vector(|| vector::Vector::open(&url, &bytes, jobs)) + } + + /// Opens the source as vector tiles `make` makes. + fn vector(&mut self, make: impl FnOnce() -> Result) -> Option { + match make() { + Ok(vector) => { + self.source = Source::Open(Holds::Vector(Box::new(vector))); + None + } + Err(reason) => { + self.source = Source::Failed; + Some(Error::Io(reason.into())) + } + } + } +} diff --git a/crates/latkit/src/derive/tiles/vector.rs b/crates/latkit/src/derive/tiles/vector.rs new file mode 100644 index 00000000..7ceb0169 --- /dev/null +++ b/crates/latkit/src/derive/tiles/vector.rs @@ -0,0 +1,387 @@ +//! Vector tiles: the tiles the camera asks for, fetched from a PMTiles archive or a URL +//! template, given or from a TileJSON document, decoded in jobs, and patched into the dataset the view +//! owns. The camera chooses the tiles that draw no larger than their own size where they lie nearest +//! its focus, nearest first. Tiles decode only the layers marks draw, and again when the scene draws +//! others. + +use std::sync::Arc; + +use rustc_hash::{FxHashMap, FxHashSet}; + +use super::super::sight::{Sight, TILE_PX, meets}; +use super::super::tiling::{Decoding, Requested, Source, Tiling}; +use super::super::{Input, Jobs, stamp_of}; +use crate::data::{Data, Field, Id, Name, Op, Patch, Table, Values}; +use crate::geo::mvt::Kind as Geometry; +use crate::geo::pmtiles::{self, Directory, Entry, Header}; +use crate::geo::tiles::{Decoded, Template}; +use crate::host::{Job, Request}; +use crate::tiles::TileKey; +use crate::{Error, Kind, Mark, Pending, Scene}; + +/// Tiles drawn at once at most: past it, tiles stop splitting. +const MAX_TILES: usize = 256; + +/// The tiles to draw within `zooms` and `bounds`: those meeting what the camera shows, each split +/// while it draws larger than its size, nearest the view's middle first. +fn wanted(sight: &Sight<'_>, zooms: [u8; 2], bounds: [f64; 4]) -> Vec { + let limit = TILE_PX * 1.25; + let region = sight.region(); + let focus = sight.focus(); + let mut out: Vec<(TileKey, f64)> = Vec::new(); + let mut queue = vec![TileKey { z: 0, x: 0, y: 0 }]; + while !queue.is_empty() { + let mut next = Vec::new(); + for (k, &key) in queue.iter().enumerate() { + let b = key.bounds(); + if b[0] > bounds[2] || b[2] < bounds[0] || b[1] > bounds[3] || b[3] < bounds[1] || !meets(®ion, b) { + continue; + } + let (size, distance) = sight.measure(&focus, b); + let room = out.len() + next.len() + (queue.len() - k) * 4 < MAX_TILES; + if key.z < zooms[1] && (key.z < zooms[0] || size > limit) && room { + next.extend(key.children()); + } else if key.z >= zooms[0] { + out.push((key, distance)); + } + } + queue = next; + } + out.sort_by(|a, b| a.1.total_cmp(&b.1)); + out.into_iter().map(|(key, _)| key).collect() +} + +/// Where vector tiles come from once their source opens. +enum Opened { + /// An archive whose root directory lies past the first bytes. + Root(Header, Pending>), + Template(Template), + Archive(Header, Directory), + Failed, +} + +/// An archive's or a template's tiles, as a tiling fetches and decodes them. +struct Tiles { + url: Arc, + opened: Opened, + /// Leaf directories, and those being fetched. + leaves: FxHashMap<(u64, u64), Directory>, + leaf_fetches: FxHashMap<(u64, u64), Pending>>, + /// The tables marks draw from the tiles, which decoding writes. + tables: Vec, +} + +/// Vector tiles drawn as a dataset the view owns. +pub(crate) struct Vector { + tiles: Tiles, + tiling: Tiling, + /// The tiles whose rows the dataset holds, with the rows of each table. + drawn: FxHashMap)>>, +} + +impl Vector { + /// The tiles a URL template names, `{z}`, `{x}`, and `{y}` in it. + pub(crate) fn template(url: &Arc) -> Vector { + Vector::opened(url, Opened::Template(Template::of(url))) + } + + /// The tiles whose source's first `bytes` are a PMTiles archive's or a TileJSON document's; the + /// archive's root directory is fetched when it lies past them. + pub(crate) fn open(url: &Arc, bytes: &[u8], jobs: &Jobs<'_>) -> Result { + if !pmtiles::is_archive(bytes) { + return Template::tilejson(bytes, url).map(|template| Vector::opened(url, Opened::Template(template))); + } + let header = pmtiles::header(bytes)?; + if !header.vector { + return Err(format!("{url} holds image tiles; only vector tiles draw")); + } + let (offset, length) = header.root; + let opened = match bytes.get(offset as usize..(offset + length) as usize) { + Some(root) => archive(header, root).ok_or_else(|| corrupt(url))?, + None => Opened::Root(header, jobs.fetch(&Request::range(url.clone(), offset..offset + length))), + }; + Ok(Vector::opened(url, opened)) + } + + fn opened(url: &Arc, opened: Opened) -> Vector { + let tiles = Tiles { + url: url.clone(), + opened, + leaves: FxHashMap::default(), + leaf_fetches: FxHashMap::default(), + tables: Vec::new(), + }; + Vector { tiles, tiling: Tiling::default(), drawn: FxHashMap::default() } + } + + /// Whether the source is still opening, its root directory not landed. + pub(crate) fn opening(&self) -> bool { + matches!(self.tiles.opened, Opened::Root(..)) + } + + /// Fetches and decodes under way. + pub(crate) fn under_way(&self) -> usize { + self.tiling.under_way() + } + + /// Tiles drawn. + pub(crate) fn drawn(&self) -> usize { + self.drawn.len() + } + + /// Brings `data` up to what `sight` shows and the scene draws of dataset `name`: whether it + /// changed, whether a tile stands in, and a failure to tell. + pub(crate) fn update( + &mut self, + input: &Input<'_>, + name: &Name, + data: &mut Data, + sight: Option<&Sight<'_>>, + jobs: &Jobs<'_>, + ) -> (bool, bool, Option) { + let tables = decoded_tables(input.scene, name); + if tables.is_empty() { + return (false, false, None); + } + let mut failure = self.tiles.open_root(); + failure = failure.or_else(|| self.tiles.land_leaves()); + let Some((zooms, bounds)) = self.tiles.zooms() else { return (false, self.opening(), failure) }; + let stamp = stamp_of(&tables); + self.tiles.tables = tables; + let wanted = sight.map(|s| wanted(s, zooms, bounds)).unwrap_or_default(); + let drawn = self.tiling.update(&wanted, stamp, &mut self.tiles, jobs); + let changed = self.draw(&drawn.keys, stamp, data); + (changed, drawn.standing_in, failure.or(drawn.failure)) + } + + /// Makes `data` hold the rows of `drawn` and no other tile's; whether it changed. + fn draw(&mut self, drawn: &[TileKey], stamp: u64, data: &mut Data) -> bool { + let keep: FxHashSet = drawn.iter().copied().collect(); + let mut patch = Patch::new(); + // Tiles no longer drawn go, and so do those decoded for other tables, which come back + // decoded again. + let gone: Vec = self + .drawn + .keys() + .filter(|k| !keep.contains(k) || self.tiling.decoded(k, stamp).is_none()) + .copied() + .collect(); + for key in &gone { + for (table, ids) in self.drawn.remove(key).unwrap_or_default() { + if data.table(&table).is_some() { + patch = patch.remove(table, ids); + } + } + } + for &key in drawn { + if self.drawn.contains_key(&key) { + continue; + } + let Some(tile) = self.tiling.decoded(&key, stamp) else { continue }; + let mut rows = Vec::new(); + for op in &tile.ops { + if let Op::Set(table) = op { + rows.push((table.name.clone(), table.ids().collect())); + patch = patch.set(harmonized(table, data)); + } + } + self.drawn.insert(key, rows); + } + if patch.is_empty() { + return false; + } + let mut next = data.clone(); + if next.apply(patch).is_ok() { + *data = next; + return true; + } + false + } +} + +impl Tiles { + /// The zooms and bounds of an open source. + fn zooms(&self) -> Option<([u8; 2], [f64; 4])> { + match &self.opened { + Opened::Template(t) => Some(([t.min_zoom, t.max_zoom], t.bounds)), + Opened::Archive(h, _) => Some(([h.min_zoom, h.max_zoom], h.bounds)), + Opened::Root(..) | Opened::Failed => None, + } + } + + /// Opens the archive once its root directory landed; a failure to tell, if any. + fn open_root(&mut self) -> Option { + let Opened::Root(header, pending) = &self.opened else { return None }; + let header = *header; + let landed = pending.take()?; + let opened = landed + .map_err(|error| error.to_string()) + .and_then(|bytes| archive(header, &bytes).ok_or_else(|| corrupt(&self.url))); + match opened { + Ok(opened) => { + self.opened = opened; + None + } + Err(reason) => { + self.opened = Opened::Failed; + Some(Error::Io(reason.into())) + } + } + } + + /// Takes leaf directories that landed; a failure to tell, if any. + fn land_leaves(&mut self) -> Option { + let mut failure = None; + let landed: Vec<_> = + self.leaf_fetches.iter().filter_map(|(at, pending)| pending.take().map(|r| (*at, r.ok()))).collect(); + for (at, bytes) in landed { + self.leaf_fetches.remove(&at); + let gzip = matches!(self.opened, Opened::Archive(h, _) if h.gzip_directories); + match bytes.and_then(|b| inflate(&b, gzip)).and_then(|b| Directory::decode(&b)) { + Some(leaf) => { + self.leaves.insert(at, leaf); + } + None => failure = Some(Error::Io("a tile directory could not be read".into())), + } + } + failure + } +} + +impl Source for Tiles { + fn request(&mut self, key: TileKey, jobs: &Jobs<'_>) -> Requested { + match &self.opened { + Opened::Template(template) => Requested::Fetch(Request::new(template.url_of(key))), + Opened::Archive(header, root) => { + let id = pmtiles::tile_id(key); + let mut directory = root; + for _ in 0..pmtiles::DEPTH { + match directory.find(id) { + Some(Entry::Leaf(offset, length)) => { + let at = (header.leaves + offset, length); + let Some(leaf) = self.leaves.get(&at) else { + let url = self.url.clone(); + self.leaf_fetches + .entry(at) + .or_insert_with(|| jobs.fetch(&Request::range(url, at.0..at.0 + at.1))); + return Requested::Wait; + }; + directory = leaf; + } + Some(Entry::Tile(offset, length)) => { + let start = header.data + offset; + return Requested::Fetch(Request::range(self.url.clone(), start..start + length)); + } + None => break, + } + } + // The archive has no such tile: it draws nothing. + Requested::Missing + } + Opened::Root(..) | Opened::Failed => Requested::Wait, + } + } + + fn decode(&self, key: TileKey, bytes: &Arc>, jobs: &Jobs<'_>) -> Decoding { + Decoding::Job(jobs.spawn(Job::tile(key, &self.tables, bytes))) + } +} + +/// The archive at `header` with root directory `bytes`, or `None` where it is corrupt. +fn archive(header: Header, bytes: &[u8]) -> Option { + let root = inflate(bytes, header.gzip_directories).and_then(|b| Directory::decode(&b))?; + Some(Opened::Archive(header, root)) +} + +fn corrupt(url: &str) -> String { + format!("the archive at {url} has a corrupt directory") +} + +/// The tables marks draw from dataset `name`: a table named after a layer holds the kind of feature +/// its marks draw, polygons first, then lines, then points; one named `layer:kind` holds that kind. +fn decoded_tables(scene: &Scene, name: &Name) -> Vec { + let mut tables: Vec = Vec::new(); + for mark in &scene.marks { + let style = mark.style(); + if style.data != *name { + continue; + } + let drawn = match mark { + Mark::Areas(_) => Geometry::Polygons, + Mark::Lines(_) => Geometry::Lines, + Mark::Vertices(_) => Geometry::Points, + Mark::Edges(_) | Mark::Faces(_) => continue, + }; + let table = style.table.clone(); + let (layer, kind) = match table.split_once(':') { + Some((layer, "polygons")) => (layer.to_owned(), Geometry::Polygons), + Some((layer, "lines")) => (layer.to_owned(), Geometry::Lines), + Some((layer, "points")) => (layer.to_owned(), Geometry::Points), + _ => (table.to_string(), drawn), + }; + let rank = |k: Geometry| match k { + Geometry::Polygons => 0, + Geometry::Lines => 1, + Geometry::Points => 2, + }; + match tables.iter_mut().find(|d| d.table == table) { + Some(d) if rank(kind) < rank(d.kind) => d.kind = kind, + Some(_) => {} + None => tables.push(Decoded { layer, kind, table }), + } + } + tables.sort_by(|a, b| a.table.cmp(&b.table)); + tables +} + +/// `table`'s fields made to hold what `data`'s table of its name holds where they differ: a field a +/// tile reads as numbers but the dataset holds as texts is written as text, and so on. +fn harmonized(table: &Table, data: &Data) -> Table { + let Some(existing) = data.table(&table.name) else { return table.clone() }; + let mut out = table.clone(); + for (name, field) in &table.fields { + let (Some(want), Field::Values(column, _)) = (existing.kind(name), field) else { continue }; + if column.kind() == want { + continue; + } + let values: Vec> = (0..column.len()).map(|r| column.get(r)).collect(); + let converted: Option = match want { + Kind::Text => Some(values.iter().map(|v| v.as_ref().map(text_of)).collect::>>().into()), + Kind::Number => Some(values.iter().map(|v| v.as_ref().and_then(number_of)).collect::>().into()), + Kind::Bool => { + Some(values.iter().map(|v| v.as_ref().and_then(number_of).map(|n| n != 0.0)).collect::>().into()) + } + _ => None, + }; + if let Some(values) = converted { + out = out.field(name.clone(), values); + } + } + out +} + +fn text_of(value: &crate::Value) -> String { + match value { + crate::Value::Text(t) => t.to_string(), + crate::Value::Number(n) => n.to_string(), + crate::Value::Bool(b) => b.to_string(), + other => format!("{other:?}"), + } +} + +fn number_of(value: &crate::Value) -> Option { + match value { + crate::Value::Number(n) => Some(*n), + crate::Value::Bool(b) => Some(f64::from(u8::from(*b))), + crate::Value::Text(t) => t.parse().ok(), + _ => None, + } +} + +/// `bytes` inflated when `gzip`. +fn inflate(bytes: &[u8], gzip: bool) -> Option> { + if !gzip { + return Some(bytes.to_vec()); + } + crate::geo::gunzipped(bytes).ok().map(std::borrow::Cow::into_owned) +} diff --git a/crates/latkit/src/derive/tiling.rs b/crates/latkit/src/derive/tiling.rs new file mode 100644 index 00000000..3f0ebb94 --- /dev/null +++ b/crates/latkit/src/derive/tiling.rs @@ -0,0 +1,228 @@ +//! Tilings: what a source holds, fetched in pieces by key as a view asks for them, decoded into +//! patches, and held under a budget of bytes, the least recently drawn going first. A key wanted draws +//! once it is decoded; until then its nearest decoded ancestor stands in, and what is missing is +//! fetched, nearest first. Tiles of the earth and spans of a sampled field's history share it. + +use std::sync::Arc; + +use rustc_hash::FxHashMap; + +use super::Jobs; +use crate::data::Patch; +use crate::host::Request; +use crate::tiles::{Key, ancestry}; +use crate::{Error, Pending}; + +/// Fetches, and decodes, a tiling has under way at once. +const REQUESTS: usize = 8; +/// Bytes of fetched pieces a tiling keeps, past which the least recently drawn go. +const KEPT_BYTES: usize = 64 << 20; + +/// How a source fetches a piece. +pub(crate) enum Requested { + /// The bytes `request` answers. + Fetch(Request), + /// Not yet: the source first fetches what finds the piece, as an archive its directories. + Wait, + /// Nowhere: the source holds no such piece, which draws nothing. + Missing, +} + +/// What a piece's bytes become, the patch it draws: at once, or the answer of a job. +pub(crate) enum Decoding { + Now(Patch), + Job(Pending>), +} + +/// Where a tiling's pieces come from, and what they become. +pub(crate) trait Source { + /// How to fetch `key`. + fn request(&mut self, key: K, jobs: &Jobs<'_>) -> Requested; + + /// What `key`'s fetched `bytes`, never empty, decode into. + fn decode(&self, key: K, bytes: &Arc>, jobs: &Jobs<'_>) -> Decoding; +} + +/// What an update draws: each wanted key decoded, else its nearest decoded ancestor, each once; and +/// whether any key stands in, by an ancestor or by nothing. +pub(crate) struct Drawn { + pub(crate) keys: Vec, + pub(crate) standing_in: bool, + /// A failure to tell: a piece that could not be fetched. + pub(crate) failure: Option, +} + +/// A tiling's pieces: their fetched bytes, and the patches they decoded into for a stamp of what +/// decoding reads. +pub(crate) struct Tiling { + /// Fetched bytes, as fetched, and when each last drew; empty where the source holds no piece. + held: FxHashMap>, u64)>, + fetching: FxHashMap>>, + /// Decodes under way and done, each for the stamp it was asked for. + decoding: FxHashMap>)>, + decoded: FxHashMap, + /// Counts updates, for drawn pieces to note when they last drew. + tick: u64, +} + +impl Default for Tiling { + fn default() -> Tiling { + Tiling { + held: FxHashMap::default(), + fetching: FxHashMap::default(), + decoding: FxHashMap::default(), + decoded: FxHashMap::default(), + tick: 0, + } + } +} + +impl Tiling { + /// Brings the pieces up to `wanted`, nearest first, decoding for `stamp`: what draws. + pub(crate) fn update( + &mut self, + wanted: &[K], + stamp: u64, + source: &mut impl Source, + jobs: &Jobs<'_>, + ) -> Drawn { + self.tick += 1; + let failure = self.land(stamp); + // Keys not decoded yet decode once held, and so do the held ancestors of those still + // loading, to stand in for them; the rest fetch. A piece decoded at once draws at once. + let mut decode: Vec = Vec::new(); + for &key in wanted { + if self.ready(&key, stamp) { + continue; + } + let held_up = ancestry(key).find(|k| self.held.contains_key(k)); + if let Some(k) = held_up + && !self.ready(&k, stamp) + && !decode.contains(&k) + { + decode.push(k); + } + if !self.held.contains_key(&key) && !decode.contains(&key) { + self.fetch(key, source, jobs); + } + } + for key in decode { + self.decode(key, stamp, source, jobs); + } + let mut drawn: Vec = Vec::new(); + let mut standing_in = false; + for &key in wanted { + let stands = ancestry(key).find(|k| self.ready(k, stamp)); + if let Some(stand) = stands + && !drawn.contains(&stand) + { + drawn.push(stand); + } + standing_in |= stands != Some(key); + } + let tick = self.tick; + for key in &drawn { + if let Some((_, used)) = self.held.get_mut(key) { + *used = tick; + } + } + self.evict(&drawn, wanted); + Drawn { keys: drawn, standing_in, failure } + } + + /// The patch `key` decoded into for `stamp`, once it did. + pub(crate) fn decoded(&self, key: &K, stamp: u64) -> Option<&Patch> { + self.decoded.get(key).filter(|(s, _)| *s == stamp).map(|(_, patch)| patch) + } + + /// Fetches and decodes under way. + pub(crate) fn under_way(&self) -> usize { + self.fetching.len() + self.decoding.len() + } + + /// Whether `key` is decoded for `stamp`. + fn ready(&self, key: &K, stamp: u64) -> bool { + self.decoded.get(key).is_some_and(|(s, _)| *s == stamp) + } + + /// Takes fetches and decodes that landed; a failure to tell, if any. + fn land(&mut self, stamp: u64) -> Option { + let mut failure = None; + let fetched: Vec<_> = self.fetching.iter().filter_map(|(key, p)| p.take().map(|r| (*key, r))).collect(); + for (key, result) in fetched { + self.fetching.remove(&key); + let bytes = result.unwrap_or_else(|error| { + failure.get_or_insert(error); + Vec::new() + }); + self.held.insert(key, (Arc::new(bytes), self.tick)); + } + let decoded: Vec<_> = + self.decoding.iter().filter_map(|(key, (s, p))| p.take().map(|r| (*key, *s, r))).collect(); + for (key, s, result) in decoded { + self.decoding.remove(&key); + let patch = result.ok().and_then(|bytes| Patch::from_bytes(&bytes).ok()).unwrap_or_default(); + if s == stamp { + self.decoded.insert(key, (s, patch)); + } + } + failure + } + + /// Starts fetching `key`, within the requests under way at once. + fn fetch(&mut self, key: K, source: &mut impl Source, jobs: &Jobs<'_>) { + if self.fetching.contains_key(&key) || self.fetching.len() >= REQUESTS { + return; + } + match source.request(key, jobs) { + Requested::Fetch(request) => { + self.fetching.insert(key, jobs.fetch(&request)); + } + Requested::Wait => {} + Requested::Missing => { + self.held.insert(key, (Arc::new(Vec::new()), self.tick)); + } + } + } + + /// Starts decoding `key` for `stamp`, within the decodes under way at once. + fn decode(&mut self, key: K, stamp: u64, source: &impl Source, jobs: &Jobs<'_>) { + if self.decoding.get(&key).is_some_and(|(s, _)| *s == stamp) || self.decoding.len() >= REQUESTS { + return; + } + let Some((bytes, _)) = self.held.get(&key) else { return }; + if bytes.is_empty() { + self.decoded.insert(key, (stamp, Patch::new())); + return; + } + match source.decode(key, bytes, jobs) { + Decoding::Now(patch) => { + self.decoded.insert(key, (stamp, patch)); + } + Decoding::Job(pending) => { + self.decoding.insert(key, (stamp, pending)); + } + } + } + + /// Lets go of the least recently drawn pieces' bytes past the budget, and of decodes no longer + /// drawn, wanted, or covering a wanted key. + fn evict(&mut self, drawn: &[K], wanted: &[K]) { + let kept = |k: &K| drawn.contains(k) || wanted.contains(k); + let mut bytes: usize = self.held.values().map(|(b, _)| b.len()).sum(); + if bytes > KEPT_BYTES { + let mut old: Vec<(u64, K)> = + self.held.iter().filter(|(k, _)| !kept(k)).map(|(k, (_, used))| (*used, *k)).collect(); + old.sort_unstable(); + for (_, key) in old { + if bytes <= KEPT_BYTES { + break; + } + if let Some((b, _)) = self.held.remove(&key) { + bytes -= b.len(); + } + } + } + self.decoded.retain(|k, _| kept(k) || wanted.iter().any(|w| ancestry(*w).skip(1).any(|a| a == *k))); + } +} diff --git a/crates/latkit/src/error.rs b/crates/latkit/src/error.rs new file mode 100644 index 00000000..0e3b4d3b --- /dev/null +++ b/crates/latkit/src/error.rs @@ -0,0 +1,175 @@ +use std::borrow::Cow; +use std::fmt; + +use crate::Name; + +/// Everything that can go wrong in latkit. +#[derive(Clone, Debug, PartialEq, thiserror::Error)] +#[non_exhaustive] +pub enum Error { + /// An input does not fit what it describes; `path` names the part, such as `marks[2].vertices.color`. + #[error("{path}: {reason}")] + Invalid { + /// Where in the input the problem is. + path: Path, + /// What is wrong there. + reason: Cow<'static, str>, + }, + /// The platform or device cannot do what was asked. + #[error("unsupported: {0}")] + Unsupported(Cow<'static, str>), + /// A budget or device limit would be exceeded. + #[error("over limit: {0}")] + Limit(Cow<'static, str>), + /// Reading or writing external bytes failed: a fetch, a file, a worker, an encoder. + #[error("io: {0}")] + Io(Cow<'static, str>), + /// The operation did not complete before its deadline. + #[error("operation timed out")] + Timeout, + /// The GPU device was lost; create a new `Gpu`. + #[error("GPU device lost")] + DeviceLost, + /// The owner of pending work was destroyed before it could answer. + #[error("operation cancelled")] + Cancelled, +} + +/// A `Result` whose error is [`Error`]. +pub type Result = std::result::Result; + +impl Error { + /// An [`Error::Invalid`] at the root of the input. + pub fn invalid(reason: impl Into>) -> Error { + Error::Invalid { path: Path::default(), reason: reason.into() } + } + + /// A short, stable name for the kind of error: `invalid`, `unsupported`, `limit`, `io`, + /// `device-lost`, `cancelled`, or `timeout`. + pub fn code(&self) -> &'static str { + match self { + Error::Invalid { .. } => "invalid", + Error::Unsupported(_) => "unsupported", + Error::Limit(_) => "limit", + Error::Io(_) => "io", + Error::DeviceLost => "device-lost", + Error::Cancelled => "cancelled", + Error::Timeout => "timeout", + } + } + + /// Prefixes the path of an [`Error::Invalid`] with `step`; other errors pass through. + #[must_use] + pub fn at(self, step: impl Into) -> Error { + match self { + Error::Invalid { mut path, reason } => { + path.0.insert(0, step.into()); + Error::Invalid { path, reason } + } + other => other, + } + } +} + +/// The error as `{ code, message, path? }`: the shape the npm package's `LatkitError` takes. +impl serde::Serialize for Error { + fn serialize(&self, serializer: S) -> Result { + use serde::ser::SerializeMap; + let mut map = serializer.serialize_map(None)?; + map.serialize_entry("code", self.code())?; + map.serialize_entry("message", &self.to_string())?; + if let Error::Invalid { path, .. } = self { + map.serialize_entry("path", &path.to_string())?; + } + map.end() + } +} + +/// The error as it serializes: a failure, as plain data. +impl schemars::JsonSchema for Error { + fn schema_name() -> Cow<'static, str> { + "Failure".into() + } + + fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema { + schemars::json_schema!({ + "description": "What failed: its `code`, the message, and for invalid input the `path` to the part, such as `marks[2].vertices.color`.", + "type": "object", + "properties": { + "code": { "enum": ["invalid", "unsupported", "limit", "io", "device-lost", "cancelled", "timeout"] }, + "message": { "type": "string" }, + "path": { "type": "string" }, + }, + "required": ["code", "message"], + }) + } +} + +/// Where in an input an [`Error::Invalid`] occurred. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct Path(pub Vec); + +/// One step of a [`Path`]: a named part or an index. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Step { + /// A named part, such as a table, field, or option. + Name(Name), + /// An index into a list. + Index(usize), +} + +impl From<&str> for Step { + fn from(name: &str) -> Step { + Step::Name(name.into()) + } +} + +impl From<&Name> for Step { + fn from(name: &Name) -> Step { + Step::Name(name.clone()) + } +} + +impl From for Step { + fn from(name: Name) -> Step { + Step::Name(name) + } +} + +impl From for Step { + fn from(index: usize) -> Step { + Step::Index(index) + } +} + +impl fmt::Display for Path { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.0.is_empty() { + return f.write_str("input"); + } + for (i, step) in self.0.iter().enumerate() { + match step { + Step::Name(name) if i == 0 => write!(f, "{name}")?, + Step::Name(name) => write!(f, ".{name}")?, + Step::Index(index) => write!(f, "[{index}]")?, + } + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn paths_read_like_access_expressions() { + let error = Error::invalid("not a number").at("color").at(2).at("marks"); + assert_eq!(error.to_string(), "marks[2].color: not a number"); + } + + #[test] + fn only_invalid_errors_take_steps() { + assert_eq!(Error::DeviceLost.at("marks"), Error::DeviceLost); + } +} diff --git a/crates/latkit/src/expr/color.rs b/crates/latkit/src/expr/color.rs new file mode 100644 index 00000000..9c821f19 --- /dev/null +++ b/crates/latkit/src/expr/color.rs @@ -0,0 +1,293 @@ +use std::fmt; + +/// An sRGB color with straight alpha, each channel in `0..=1`, as in CSS. +#[derive(Clone, Copy, PartialEq, Debug)] +pub struct Color { + /// Red. + pub r: f32, + /// Green. + pub g: f32, + /// Blue. + pub b: f32, + /// Opacity. + pub a: f32, +} + +impl Color { + /// Opaque white. + pub const WHITE: Color = Color::rgba(1.0, 1.0, 1.0, 1.0); + /// Opaque black. + pub const BLACK: Color = Color::rgba(0.0, 0.0, 0.0, 1.0); + /// Fully transparent. + pub const TRANSPARENT: Color = Color::rgba(0.0, 0.0, 0.0, 0.0); + + /// A color from channels in `0..=1`. + pub const fn rgba(r: f32, g: f32, b: f32, a: f32) -> Color { + Color { r, g, b, a } + } + + /// An opaque color from channels in `0..=1`. + pub const fn rgb(r: f32, g: f32, b: f32) -> Color { + Color { r, g, b, a: 1.0 } + } + + /// A color from `#rgb`, `#rgba`, `#rrggbb`, or `#rrggbbaa`. + pub fn hex(hex: &str) -> Option { + let digits = hex.strip_prefix('#')?; + if !digits.is_ascii() { + return None; + } + let nibble = |i: usize| u8::from_str_radix(&digits[i..=i], 16).ok(); + let byte = |i: usize| u8::from_str_radix(&digits[i..i + 2], 16).ok(); + let [r, g, b, a] = match digits.len() { + 3 | 4 => { + let channel = |i: usize| nibble(i).map(|v| v * 17); + [channel(0)?, channel(1)?, channel(2)?, if digits.len() == 4 { channel(3)? } else { 255 }] + } + 6 | 8 => [byte(0)?, byte(2)?, byte(4)?, if digits.len() == 8 { byte(6)? } else { 255 }], + _ => return None, + }; + Some(Color::from_bytes([r, g, b, a])) + } + + /// A color from CSS: hex, `rgb(…)`, `rgba(…)`, or a named color. + pub fn css(css: &str) -> Option { + let css = css.trim(); + if css.starts_with('#') { + return Color::hex(css); + } + let lower = css.to_ascii_lowercase(); + if let Some(args) = lower.strip_prefix("rgba(").or_else(|| lower.strip_prefix("rgb(")) { + let parts: Vec<&str> = args.strip_suffix(')')?.split([',', '/', ' ']).filter(|p| !p.is_empty()).collect(); + if !(3..=4).contains(&parts.len()) { + return None; + } + let channel = |p: &str| match p.strip_suffix('%') { + Some(percent) => percent.parse::().ok().map(|v| v / 100.0), + None => p.parse::().ok().map(|v| v / 255.0), + }; + let alpha = |p: &str| match p.strip_suffix('%') { + Some(percent) => percent.parse::().ok().map(|v| v / 100.0), + None => p.parse::().ok(), + }; + let a = parts.get(3).map_or(Some(1.0), |p| alpha(p))?; + return Some(Color::rgba(channel(parts[0])?, channel(parts[1])?, channel(parts[2])?, a).clamped()); + } + if lower == "transparent" { + return Some(Color::TRANSPARENT); + } + let i = NAMED.binary_search_by(|(name, _)| name.cmp(&lower.as_str())).ok()?; + let [r, g, b] = NAMED[i].1.to_be_bytes()[1..].try_into().ok()?; + Some(Color::from_bytes([r, g, b, 255])) + } + + /// The same color at opacity `a`. + #[must_use] + pub fn alpha(self, a: f32) -> Color { + Color { a, ..self } + } + + pub(crate) fn from_bytes(bytes: [u8; 4]) -> Color { + let [red, green, blue, alpha] = bytes.map(|byte| f32::from(byte) / 255.0); + Color::rgba(red, green, blue, alpha) + } + + /// Red, green, blue, and alpha as bytes. + pub fn to_rgba8(self) -> [u8; 4] { + let q = |v: f32| (v.clamp(0.0, 1.0) * 255.0).round() as u8; + [q(self.r), q(self.g), q(self.b), q(self.a)] + } + + /// Packed as WGSL's `pack4x8unorm`: red in the low byte. + pub(crate) fn packed(self) -> u32 { + u32::from_le_bytes(self.to_rgba8()) + } + + pub(crate) fn to_array(self) -> [f32; 4] { + [self.r, self.g, self.b, self.a] + } + + fn clamped(self) -> Color { + let c = |v: f32| v.clamp(0.0, 1.0); + Color::rgba(c(self.r), c(self.g), c(self.b), c(self.a)) + } +} + +impl fmt::Display for Color { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let [red, green, blue, alpha] = self.to_rgba8(); + write!(f, "#{red:02x}{green:02x}{blue:02x}")?; + if alpha == 255 { Ok(()) } else { write!(f, "{alpha:02x}") } + } +} + +/// CSS named colors, sorted by name. +#[allow(clippy::unreadable_literal)] +static NAMED: &[(&str, u32)] = &[ + ("aliceblue", 0xf0f8ff), + ("antiquewhite", 0xfaebd7), + ("aqua", 0x00ffff), + ("aquamarine", 0x7fffd4), + ("azure", 0xf0ffff), + ("beige", 0xf5f5dc), + ("bisque", 0xffe4c4), + ("black", 0x000000), + ("blanchedalmond", 0xffebcd), + ("blue", 0x0000ff), + ("blueviolet", 0x8a2be2), + ("brown", 0xa52a2a), + ("burlywood", 0xdeb887), + ("cadetblue", 0x5f9ea0), + ("chartreuse", 0x7fff00), + ("chocolate", 0xd2691e), + ("coral", 0xff7f50), + ("cornflowerblue", 0x6495ed), + ("cornsilk", 0xfff8dc), + ("crimson", 0xdc143c), + ("cyan", 0x00ffff), + ("darkblue", 0x00008b), + ("darkcyan", 0x008b8b), + ("darkgoldenrod", 0xb8860b), + ("darkgray", 0xa9a9a9), + ("darkgreen", 0x006400), + ("darkgrey", 0xa9a9a9), + ("darkkhaki", 0xbdb76b), + ("darkmagenta", 0x8b008b), + ("darkolivegreen", 0x556b2f), + ("darkorange", 0xff8c00), + ("darkorchid", 0x9932cc), + ("darkred", 0x8b0000), + ("darksalmon", 0xe9967a), + ("darkseagreen", 0x8fbc8f), + ("darkslateblue", 0x483d8b), + ("darkslategray", 0x2f4f4f), + ("darkslategrey", 0x2f4f4f), + ("darkturquoise", 0x00ced1), + ("darkviolet", 0x9400d3), + ("deeppink", 0xff1493), + ("deepskyblue", 0x00bfff), + ("dimgray", 0x696969), + ("dimgrey", 0x696969), + ("dodgerblue", 0x1e90ff), + ("firebrick", 0xb22222), + ("floralwhite", 0xfffaf0), + ("forestgreen", 0x228b22), + ("fuchsia", 0xff00ff), + ("gainsboro", 0xdcdcdc), + ("ghostwhite", 0xf8f8ff), + ("gold", 0xffd700), + ("goldenrod", 0xdaa520), + ("gray", 0x808080), + ("green", 0x008000), + ("greenyellow", 0xadff2f), + ("grey", 0x808080), + ("honeydew", 0xf0fff0), + ("hotpink", 0xff69b4), + ("indianred", 0xcd5c5c), + ("indigo", 0x4b0082), + ("ivory", 0xfffff0), + ("khaki", 0xf0e68c), + ("lavender", 0xe6e6fa), + ("lavenderblush", 0xfff0f5), + ("lawngreen", 0x7cfc00), + ("lemonchiffon", 0xfffacd), + ("lightblue", 0xadd8e6), + ("lightcoral", 0xf08080), + ("lightcyan", 0xe0ffff), + ("lightgoldenrodyellow", 0xfafad2), + ("lightgray", 0xd3d3d3), + ("lightgreen", 0x90ee90), + ("lightgrey", 0xd3d3d3), + ("lightpink", 0xffb6c1), + ("lightsalmon", 0xffa07a), + ("lightseagreen", 0x20b2aa), + ("lightskyblue", 0x87cefa), + ("lightslategray", 0x778899), + ("lightslategrey", 0x778899), + ("lightsteelblue", 0xb0c4de), + ("lightyellow", 0xffffe0), + ("lime", 0x00ff00), + ("limegreen", 0x32cd32), + ("linen", 0xfaf0e6), + ("magenta", 0xff00ff), + ("maroon", 0x800000), + ("mediumaquamarine", 0x66cdaa), + ("mediumblue", 0x0000cd), + ("mediumorchid", 0xba55d3), + ("mediumpurple", 0x9370db), + ("mediumseagreen", 0x3cb371), + ("mediumslateblue", 0x7b68ee), + ("mediumspringgreen", 0x00fa9a), + ("mediumturquoise", 0x48d1cc), + ("mediumvioletred", 0xc71585), + ("midnightblue", 0x191970), + ("mintcream", 0xf5fffa), + ("mistyrose", 0xffe4e1), + ("moccasin", 0xffe4b5), + ("navajowhite", 0xffdead), + ("navy", 0x000080), + ("oldlace", 0xfdf5e6), + ("olive", 0x808000), + ("olivedrab", 0x6b8e23), + ("orange", 0xffa500), + ("orangered", 0xff4500), + ("orchid", 0xda70d6), + ("palegoldenrod", 0xeee8aa), + ("palegreen", 0x98fb98), + ("paleturquoise", 0xafeeee), + ("palevioletred", 0xdb7093), + ("papayawhip", 0xffefd5), + ("peachpuff", 0xffdab9), + ("peru", 0xcd853f), + ("pink", 0xffc0cb), + ("plum", 0xdda0dd), + ("powderblue", 0xb0e0e6), + ("purple", 0x800080), + ("rebeccapurple", 0x663399), + ("red", 0xff0000), + ("rosybrown", 0xbc8f8f), + ("royalblue", 0x4169e1), + ("saddlebrown", 0x8b4513), + ("salmon", 0xfa8072), + ("sandybrown", 0xf4a460), + ("seagreen", 0x2e8b57), + ("seashell", 0xfff5ee), + ("sienna", 0xa0522d), + ("silver", 0xc0c0c0), + ("skyblue", 0x87ceeb), + ("slateblue", 0x6a5acd), + ("slategray", 0x708090), + ("slategrey", 0x708090), + ("snow", 0xfffafa), + ("springgreen", 0x00ff7f), + ("steelblue", 0x4682b4), + ("tan", 0xd2b48c), + ("teal", 0x008080), + ("thistle", 0xd8bfd8), + ("tomato", 0xff6347), + ("turquoise", 0x40e0d0), + ("violet", 0xee82ee), + ("wheat", 0xf5deb3), + ("white", 0xffffff), + ("whitesmoke", 0xf5f5f5), + ("yellow", 0xffff00), + ("yellowgreen", 0x9acd32), +]; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parses_css() { + assert_eq!(Color::hex("#ff8000"), Some(Color::from_bytes([255, 128, 0, 255]))); + assert_eq!(Color::hex("#f80c"), Some(Color::from_bytes([255, 136, 0, 204]))); + assert_eq!(Color::css("rgb(255, 0, 0)"), Some(Color::rgb(1.0, 0.0, 0.0))); + assert_eq!(Color::css("rgba(0 0 255 / 50%)"), Some(Color::rgba(0.0, 0.0, 1.0, 0.5))); + assert_eq!(Color::css("RebeccaPurple"), Color::hex("#663399")); + assert_eq!(Color::css("nope"), None); + assert!(NAMED.windows(2).all(|w| w[0].0 < w[1].0), "sorted for binary search"); + assert_eq!(Color::hex("#336699").unwrap().to_string(), "#336699"); + assert_eq!(Color::hex("#336699").unwrap().packed(), 0xff99_6633); + } +} diff --git a/crates/latkit/src/expr/colormap.rs b/crates/latkit/src/expr/colormap.rs new file mode 100644 index 00000000..f860b514 --- /dev/null +++ b/crates/latkit/src/expr/colormap.rs @@ -0,0 +1,301 @@ +use std::borrow::Cow; +use std::sync::Arc; + +use super::Color; +use super::ramp::{self, Spread}; +#[cfg(feature = "gpu")] +use crate::gpu::shaders as wgsl; +use crate::{Error, Result}; + +/// Colors for a range of values: one of the catalog's, or one of your own. +/// +/// Sequential and diverging maps clamp, cyclic maps wrap, and categorical maps bin values by their +/// integer part: category `i` takes color `i`, and may be named with [`Colormap::categories`]. +#[derive(Clone, PartialEq, Debug)] +pub struct Colormap(Map); + +#[derive(Clone, PartialEq, Debug)] +enum Map { + Catalog(u8), + Custom(Arc), +} + +#[derive(PartialEq, Debug)] +struct Custom { + kind: ColormapKind, + count: u32, + texels: [[u8; 4]; 256], + categories: Vec>, +} + +/// How a colormap spans values. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +#[serde(rename_all = "lowercase")] +pub enum ColormapKind { + /// Low to high. + Sequential, + /// Below and above a middle. + Diverging, + /// Around a circle: values wrap. + Cyclic, + /// Distinct colors for distinct integers. + Categorical, +} + +impl ColormapKind { + fn spread(self) -> Spread { + match self { + ColormapKind::Sequential | ColormapKind::Diverging => Spread::Continuous, + ColormapKind::Cyclic => Spread::Cyclic, + ColormapKind::Categorical => Spread::Categorical, + } + } + + /// The code shaders read it by. + #[cfg(feature = "gpu")] + pub(crate) fn code(self) -> u32 { + match self { + ColormapKind::Sequential => wgsl::COLORMAP_SEQUENTIAL, + ColormapKind::Diverging => wgsl::COLORMAP_DIVERGING, + ColormapKind::Cyclic => wgsl::COLORMAP_CYCLIC, + ColormapKind::Categorical => wgsl::COLORMAP_CATEGORICAL, + } + } +} + +/// A colormap's color, at a place from 0 to 1 or evenly between its neighbors: from a [`Color`] or +/// a `(place, Color)` pair. +#[derive(Clone, Copy, PartialEq, Debug)] +pub struct Stop { + at: Option, + color: Color, +} + +impl From for Stop { + fn from(color: Color) -> Stop { + Stop { at: None, color } + } +} + +impl From<&Color> for Stop { + fn from(color: &Color) -> Stop { + Stop::from(*color) + } +} + +impl From<(f32, Color)> for Stop { + fn from((at, color): (f32, Color)) -> Stop { + Stop { at: Some(at), color } + } +} + +struct Entry { + name: &'static str, + label: &'static str, + kind: ColormapKind, + count: u32, + texels: [[u8; 4]; 256], +} + +include!(concat!(env!("OUT_DIR"), "/colormaps.rs")); + +/// The catalog's names, in order. +pub(crate) fn catalog() -> impl Iterator { + CATALOG.iter().map(|e| e.name) +} + +impl Colormap { + /// The catalog colormap named `name`, such as `"viridis"`. + pub fn named(name: &str) -> Option { + CATALOG.iter().position(|e| e.name == name).map(|i| Colormap(Map::Catalog(i as u8))) + } + + /// A colormap through `stops`, colors or `(place, color)` pairs: blended in OKLab, so lightness + /// runs evenly, a color without a place evenly between its neighbors as in a CSS gradient; or + /// for a categorical map, one color per category. Fails without a stop, for places outside + /// `0..=1` or out of order, and for a categorical map's places or more than 256 categories. + pub fn new>(kind: ColormapKind, stops: impl IntoIterator) -> Result { + let stops: Vec<(Option, [f32; 4])> = + stops.into_iter().map(Into::into).map(|s: Stop| (s.at, s.color.to_array())).collect(); + let places = || stops.iter().filter_map(|s| s.0); + let wrong: Option> = match kind { + _ if stops.is_empty() => Some("a colormap needs a color".into()), + ColormapKind::Categorical if places().next().is_some() => Some("a category's color has no place".into()), + ColormapKind::Categorical if stops.len() > 256 => { + Some(format!("a categorical map has at most 256 colors, not {}", stops.len()).into()) + } + _ if places().any(|p| !(0.0..=1.0).contains(&p)) => Some("a color's place is from 0 to 1".into()), + _ if !places().is_sorted() => Some("colors' places ascend".into()), + _ => None, + }; + if let Some(reason) = wrong { + return Err(Error::invalid(reason)); + } + let texels = ramp::texels(kind.spread(), &stops); + Ok(Colormap(Map::Custom(Arc::new(Custom { kind, count: stops.len() as u32, texels, categories: Vec::new() })))) + } + + /// The same categorical map with its categories named in order, from category 0: what its legend + /// lists. Panics for a continuous map. + #[must_use] + pub fn categories>>(&self, names: impl IntoIterator) -> Colormap { + assert_eq!(self.kind(), ColormapKind::Categorical, "only a categorical map has categories"); + let categories = names.into_iter().map(Into::into).collect(); + Colormap(Map::Custom(Arc::new(Custom { + kind: self.kind(), + count: self.count(), + texels: *self.texels(), + categories, + }))) + } + + /// The names of the categories, from category 0; none unless named. + pub(crate) fn named_categories(&self) -> &[Arc] { + match &self.0 { + Map::Catalog(_) => &[], + Map::Custom(c) => &c.categories, + } + } + + /// How the colormap spans values. + pub fn kind(&self) -> ColormapKind { + match &self.0 { + Map::Catalog(i) => CATALOG[*i as usize].kind, + Map::Custom(c) => c.kind, + } + } + + /// The catalog name, or `None` for a colormap of your own. + pub fn name(&self) -> Option<&'static str> { + match &self.0 { + Map::Catalog(i) => Some(CATALOG[*i as usize].name), + Map::Custom(_) => None, + } + } + + /// A readable title, such as `"Red / Blue"`. + pub fn label(&self) -> &str { + match &self.0 { + Map::Catalog(i) => CATALOG[*i as usize].label, + Map::Custom(_) => "Custom", + } + } + + /// The same colors in reverse order. + #[must_use] + pub fn reversed(&self) -> Colormap { + let mut texels = *self.texels(); + match self.kind() { + ColormapKind::Categorical => texels[..self.count() as usize].reverse(), + _ => texels.reverse(), + } + if self.kind() == ColormapKind::Categorical { + let n = self.count() as usize; + for i in n..256 { + texels[i] = texels[i % n]; + } + } + let categories = self.named_categories().to_vec(); + Colormap(Map::Custom(Arc::new(Custom { kind: self.kind(), count: self.count(), texels, categories }))) + } + + /// The color at `t` in `0..=1`: clamped, wrapped for cyclic maps, binned for categorical maps. + pub fn sample(&self, t: f32) -> Color { + let texels = self.texels(); + if self.kind() == ColormapKind::Categorical { + return Color::from_bytes(texels[(t.abs().floor() as usize) % self.count() as usize]); + } + let t = if self.kind() == ColormapKind::Cyclic { t - t.floor() } else { t.clamp(0.0, 1.0) }; + let at = t * 255.0; + let (left, weight) = (at.floor() as usize, at - at.floor()); + let (from, to) = (texels[left], texels[(left + 1).min(255)]); + let [red, green, blue, alpha] = + std::array::from_fn(|c| (f32::from(from[c]) * (1.0 - weight) + f32::from(to[c]) * weight) / 255.0); + Color::rgba(red, green, blue, alpha) + } + + /// How many colors it was made from: a categorical map's categories. + pub fn count(&self) -> u32 { + match &self.0 { + Map::Catalog(i) => CATALOG[*i as usize].count, + Map::Custom(c) => c.count, + } + } + + pub(crate) fn texels(&self) -> &[[u8; 4]; 256] { + match &self.0 { + Map::Catalog(i) => &CATALOG[*i as usize].texels, + Map::Custom(c) => &c.texels, + } + } + + /// Identifies the colormap's colors, for sharing one texture layer. + pub(crate) fn key(&self) -> ColormapKey { + use std::hash::{Hash, Hasher}; + match &self.0 { + Map::Catalog(i) => ColormapKey::Catalog(*i), + Map::Custom(c) => { + let mut hasher = rustc_hash::FxHasher::default(); + (c.kind, c.count, &c.texels).hash(&mut hasher); + ColormapKey::Custom(hasher.finish()) + } + } + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub(crate) enum ColormapKey { + Catalog(u8), + Custom(u64), +} + +impl From<&Colormap> for Colormap { + fn from(colormap: &Colormap) -> Colormap { + colormap.clone() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn catalog_maps_sample() { + assert_eq!(Colormap::named("viridis"), Some(Colormap::VIRIDIS)); + assert_eq!(Colormap::VIRIDIS.kind(), ColormapKind::Sequential); + assert_eq!(Colormap::PHASE.kind(), ColormapKind::Cyclic); + assert_eq!(Colormap::NAMES.len(), 46); + let start = Colormap::VIRIDIS.sample(0.0).to_rgba8(); + assert_eq!(start, [0x44, 0x01, 0x54, 255]); + assert_eq!(Colormap::TAB10.sample(11.0), Colormap::TAB10.sample(1.0)); + assert_eq!(Colormap::GRAYS.sample(1.0).to_rgba8(), [255, 255, 255, 255]); + } + + #[test] + fn custom_maps_blend_and_reverse() { + let map = Colormap::new(ColormapKind::Sequential, [Color::BLACK, Color::WHITE]).unwrap(); + // Blended in OKLab: half lightness, a darker byte than sRGB's middle. + assert!((95..105).contains(&map.sample(0.5).to_rgba8()[0])); + assert_eq!(map.reversed().sample(0.0).to_rgba8(), [255, 255, 255, 255]); + let placed = Colormap::new(ColormapKind::Sequential, [(0.0, Color::BLACK), (0.5, Color::WHITE)]).unwrap(); + assert_eq!(placed.sample(0.75).to_rgba8(), [255, 255, 255, 255]); + let categories = + Colormap::new(ColormapKind::Categorical, [Color::BLACK, Color::WHITE, Color::TRANSPARENT]).unwrap(); + assert_eq!(categories.reversed().sample(0.0), Color::TRANSPARENT); + let named = Colormap::TAB10.categories(["a", "b"]); + assert_eq!(named.sample(1.0), Colormap::TAB10.sample(1.0)); + assert_eq!(named.reversed().named_categories(), named.named_categories()); + assert_eq!(&*named.named_categories()[1], "b"); + assert_eq!(named.key(), Colormap::TAB10.categories(["c"]).key()); + } + + #[test] + fn wrong_stops_fail() { + let wrong = |kind, stops: &[(f32, Color)]| Colormap::new(kind, stops.iter().copied()).unwrap_err().to_string(); + assert!(Colormap::new(ColormapKind::Sequential, [Color::BLACK; 0]).is_err()); + assert!(wrong(ColormapKind::Sequential, &[(0.5, Color::BLACK), (0.2, Color::WHITE)]).contains("ascend")); + assert!(wrong(ColormapKind::Cyclic, &[(1.5, Color::BLACK)]).contains("0 to 1")); + assert!(wrong(ColormapKind::Categorical, &[(0.0, Color::BLACK)]).contains("no place")); + assert!(Colormap::new(ColormapKind::Categorical, [Color::BLACK; 257]).is_err()); + } +} diff --git a/crates/latkit/src/expr/compile.rs b/crates/latkit/src/expr/compile.rs new file mode 100644 index 00000000..3a772533 --- /dev/null +++ b/crates/latkit/src/expr/compile.rs @@ -0,0 +1,761 @@ +//! Expressions to bytecode: each channel of a mark is a range of ops that ends in a store. +//! +//! Compilation type-checks against the data's fields and records what each channel depends on, so +//! the view evaluates a channel only when one of its inputs changes. + +use std::ops::BitOr; +use std::sync::Arc; + +use super::{Binary, Colormap, ColormapKind, Domain, Expr, FieldRef, Node, State, Unary}; +use crate::gpu::shaders as wgsl; +use crate::{Error, Kind, Name, Result}; + +/// What a channel reads, so the view knows when to evaluate it again. +#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, Debug)] +pub(crate) struct Deps(u8); + +impl Deps { + pub(crate) const DATA: Deps = Deps(1); + pub(crate) const SAMPLES: Deps = Deps(2); + pub(crate) const TIME: Deps = Deps(4); + pub(crate) const POINTER: Deps = Deps(8); + pub(crate) const FOCUS: Deps = Deps(16); + pub(crate) const DOMAIN: Deps = Deps(32); + pub(crate) const CAMERA: Deps = Deps(64); + + pub(crate) fn intersects(self, other: Deps) -> bool { + self.0 & other.0 != 0 + } +} + +impl BitOr for Deps { + type Output = Deps; + + fn bitor(self, other: Deps) -> Deps { + Deps(self.0 | other.0) + } +} + +impl std::ops::BitOrAssign for Deps { + fn bitor_assign(&mut self, other: Deps) { + self.0 |= other.0; + } +} + +/// Which words of a column's pages a program reads. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub(crate) enum Words { + /// Numbers as `f32`, booleans as 0 or 1. + Values, + /// Text as dictionary codes. + Codes, + /// Reference rows as `u32`, `NONE` where unwired. + Bits, + /// A point's x. + X, + /// A point's y. + Y, + /// A geometry's points per row: a page's row count, each row's first point and the end, then + /// every point's x and y; parts are broken by a missing point. + Path, +} + +/// A column a program reads: of the mark's own table, of another dataset's table joined by row id, +/// or of the table the view derives beside the mark's own, row for row. +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub(crate) struct ColumnUse { + pub(crate) of: Option<(Name, Name)>, + pub(crate) derived: bool, + pub(crate) name: Name, + pub(crate) words: Words, + pub(crate) sampled: bool, + pub(crate) step: bool, + /// Also read the part `f32` drops of an `f64`, for positions. + pub(crate) low: bool, + /// Read every frame in view, as a line tracing the field does. + pub(crate) trace: bool, +} + +impl ColumnUse { + /// The mark's own field `name`, read as `words`. + fn own(name: impl Into, words: Words) -> ColumnUse { + ColumnUse { + of: None, + derived: false, + name: name.into(), + words, + sampled: false, + step: false, + low: false, + trace: false, + } + } + + /// The derived field `name`, read as `words`. + fn derived(name: impl Into, words: Words) -> ColumnUse { + ColumnUse { derived: true, ..ColumnUse::own(name, words) } + } +} + +/// A constant holding a text's dictionary code in a column; the view writes it. +#[derive(Clone, PartialEq, Debug)] +pub(crate) struct TextUse { + pub(crate) constant: u32, + pub(crate) column: u32, + pub(crate) text: Arc, +} + +/// A mark's compiled channels and what they read. +#[derive(Clone, Default, PartialEq, Debug)] +pub(crate) struct Program { + pub(crate) code: Vec<[u32; 4]>, + pub(crate) constants: Vec, + /// Op ranges of every channel, then of every reduction. + pub(crate) ranges: Vec<[u32; 2]>, + pub(crate) channels: Vec, + /// What each fitted domain's input reads. + pub(crate) domains: Vec, + pub(crate) columns: Vec, + pub(crate) texts: Vec, + /// Colormap ops, whose layer the view writes. + pub(crate) colormaps: Vec<(u32, Colormap)>, + /// Tables that ends point at, by end index. + pub(crate) ends: Vec, + /// State words stored in position units. + pub(crate) units: u32, +} + +/// What a channel or a fitted domain reads: kinds of input, and which of the program's columns. +#[derive(Clone, Copy, Default, PartialEq, Eq, Debug)] +pub(crate) struct Reads { + pub(crate) deps: Deps, + /// Bit `i` for column `i`; the last bit stands for every column past it. + pub(crate) columns: u64, +} + +impl Reads { + pub(crate) fn column(index: usize) -> u64 { + 1 << index.min(63) + } +} + +#[derive(Clone, PartialEq, Debug)] +pub(crate) struct Channel { + pub(crate) name: Name, + pub(crate) reads: Reads, +} + +impl Program { + /// What all channels read together. + pub(crate) fn reads(&self) -> Deps { + self.channels.iter().fold(Deps::default(), |all, c| all | c.reads.deps) + } +} + +/// Where a channel stores its value. +#[derive(Clone, Copy, Debug)] +pub(crate) enum Store { + Number { word: u32, fallback: Option }, + Size { word: u32, units: bool, fallback: Option }, + Color { word: u32, fallback: u32 }, + Flag { word: u32, bit: u32 }, +} + +/// The fields a mark's expressions can read. +pub(crate) trait Fields { + /// The kind of `name` in the mark's table, or in `of`'s table. + fn kind(&self, of: Option<&(Name, Name)>, name: &str) -> Option; + /// The table a reference field of the mark's table names. + fn target(&self, name: &str) -> Option; +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +enum Ty { + Number, + Bool, + Color, + Text, +} + +const NONE: u32 = wgsl::NONE; + +pub(crate) struct Compiler<'a> { + fields: &'a dyn Fields, + program: Program, + depth: u32, + deps: Deps, + columns_read: u64, + /// Code of each fitted domain's reduction, placed after the channels by `finish`. + reductions: Vec>, + reducing: bool, +} + +fn invalid(reason: impl Into>) -> Error { + Error::invalid(reason) +} + +impl<'a> Compiler<'a> { + pub(crate) fn new(fields: &'a dyn Fields) -> Compiler<'a> { + Compiler { + fields, + program: Program::default(), + depth: 0, + deps: Deps::default(), + columns_read: 0, + reductions: Vec::new(), + reducing: false, + } + } + + /// The kind of field `name` of the mark's table. + pub(crate) fn kind(&self, name: &str) -> Option { + self.fields.kind(None, name) + } + + /// Compiles `expr` into channel `name`, stored by `store`. + pub(crate) fn channel(&mut self, name: &str, expr: &Expr, store: Store) -> Result<()> { + let start = self.begin(); + self.store(expr, store).map_err(|e| e.at(name))?; + self.close(name, start); + Ok(()) + } + + /// Compiles a position channel. Plain number fields and point fields keep full precision. + pub(crate) fn position(&mut self, x: &Expr, y: &Expr, word: u32) -> Result<()> { + let start = self.begin(); + if let (Some(cx), Some(cy)) = (self.plain(x), self.plain(y)) { + self.deps |= Deps::DATA; + self.op(wgsl::OP_POSITION, word, cx, cy, 0, 0)?; + } else { + self.coordinate(x).map_err(|e| e.at("x"))?; + self.coordinate(y).map_err(|e| e.at("y"))?; + self.op(wgsl::OP_STORE_POSITION, word, 0, 0, 2, 0)?; + } + self.close("position", start); + Ok(()) + } + + /// Compiles a position channel reading the place the view derives for each row, at full + /// precision. + pub(crate) fn derived_position(&mut self, word: u32) -> Result<()> { + let start = self.begin(); + let [x, y] = + ["x", "y"].map(|name| self.column(ColumnUse { low: true, ..ColumnUse::derived(name, Words::Values) })); + self.deps |= Deps::DATA; + self.op(wgsl::OP_POSITION, word, x, y, 0, 0)?; + self.close("position", start); + Ok(()) + } + + /// Compiles channel `name` storing the number the view derives as field `field`. + pub(crate) fn derived(&mut self, name: &str, field: &str, store: Store) -> Result<()> { + let start = self.begin(); + let column = self.column(ColumnUse::derived(field, Words::Values)); + self.deps |= Deps::DATA; + self.op(wgsl::OP_FIELD, column, 0, 0, 0, 1)?; + self.store_op(store)?; + self.close(name, start); + Ok(()) + } + + /// The program column of the derived number field `field`, which shaders read directly. + pub(crate) fn derived_number(&mut self, field: &str) -> u32 { + self.column(ColumnUse::derived(field, Words::Values)) + } + + /// The program column of the derived geometry field `field`, read as points per row. + pub(crate) fn derived_path(&mut self, field: &str) -> u32 { + self.column(ColumnUse::derived(field, Words::Path)) + } + + /// The program column of the mark's geometry field `field`, read as points per row. + pub(crate) fn path(&mut self, field: &str) -> u32 { + self.column(ColumnUse::own(field, Words::Path)) + } + + /// The program column of the mark's reference field `name`, read as the rows it names. + pub(crate) fn bits(&mut self, name: &str) -> Result { + if self.fields.kind(None, name) != Some(Kind::Reference) { + return Err(invalid("not a reference field")); + } + Ok(self.column(ColumnUse::own(name, Words::Bits))) + } + + /// Refuses `expr` for option `name` when it reads anything but static fields: the CPU works it + /// out from the data alone, as it does a row's priority. + pub(crate) fn check_data(&self, name: &str, expr: &Expr) -> Result<()> { + match self.unstructural(expr) { + Some(reason) => Err(invalid(format!("{name} reads data only, not {reason}")).at(name)), + None => Ok(()), + } + } + + /// Refuses `exprs` for option `name` when they read anything but static fields: where a + /// diagram's rows stand and how large they are is its structure, made from the data alone. + pub(crate) fn check_structure<'e>(&self, name: &str, exprs: impl IntoIterator) -> Result<()> { + for expr in exprs { + if let Some(reason) = self.unstructural(expr) { + return Err(invalid(format!("a diagram's {name} reads data only, not {reason}")).at(name)); + } + } + Ok(()) + } + + /// What `expr` reads that structure cannot: view state or a sampled field. + fn unstructural(&self, expr: &Expr) -> Option<&'static str> { + match &*expr.0 { + Node::State(State::Selected | State::Hovered) => Some("selection or hover"), + Node::State(State::Pointer) => Some("the pointer"), + Node::State(State::Elapsed) => Some("time"), + Node::State(State::Zoom) => Some("the zoom"), + Node::Field(f) if self.fields.kind(f.of.as_ref(), &f.name) == Some(Kind::Sampled) => { + Some("a sampled field") + } + Node::Unary(_, a) | Node::Is(a, _) | Node::Contains(a, _) => self.unstructural(a), + Node::Binary(_, a, b) => self.unstructural(a).or_else(|| self.unstructural(b)), + Node::When(c, a, b) => { + self.unstructural(c).or_else(|| self.unstructural(a)).or_else(|| self.unstructural(b)) + } + Node::Scale { input, .. } | Node::Colormap { input, .. } => self.unstructural(input), + _ => None, + } + } + + /// Compiles end `index` of an edge: the vertex the reference field `name` names. + pub(crate) fn end(&mut self, name: &str, word: u32) -> Result<()> { + let start = self.begin(); + if self.fields.kind(None, name) != Some(Kind::Reference) { + return Err(invalid("not a reference field").at(name)); + } + let target = self.fields.target(name).ok_or_else(|| invalid("not a reference field").at(name))?; + let column = self.column(ColumnUse::own(name, Words::Bits)); + let index = self.program.ends.len() as u32; + self.program.ends.push(target); + self.deps |= Deps::DATA; + self.op(wgsl::OP_STORE_END, word, column, index, 0, 0)?; + self.close(name, start); + Ok(()) + } + + /// Compiles an end storing each row's own vertex slot at `word`: the vertex mark drawing the + /// mark's own table, row for row, as a pole stands on. + pub(crate) fn own_end(&mut self, table: &Name, word: u32) -> Result<()> { + let start = self.begin(); + let index = self.program.ends.len() as u32; + self.program.ends.push(table.clone()); + self.op(wgsl::OP_STORE_END, word, wgsl::NONE, index, 0, 0)?; + self.close("poles", start); + Ok(()) + } + + /// Compiles channel `name` storing the code of text field `expr` at `word`, and returns the + /// program column whose dictionary names the codes. + pub(crate) fn text(&mut self, name: &str, expr: &Expr, word: u32) -> Result { + let Node::Field(f) = &*expr.0 else { return Err(invalid("a label's text is a text field").at(name)) }; + if self.fields.kind(f.of.as_ref(), &f.name) != Some(Kind::Text) { + return Err(invalid("not a text field").at(&f.name).at(name)); + } + let start = self.begin(); + let column = self.field_column(f, Words::Codes, false); + self.op(wgsl::OP_FIELD, column, 0, 0, 0, 1)?; + self.op(wgsl::OP_STORE_CODE, word, 0, 0, 1, 0)?; + self.close(name, start); + Ok(column) + } + + /// The column of sampled field `name` that a line traces over the axis. + pub(crate) fn trace(&mut self, name: &str) -> Result { + if self.fields.kind(None, name) != Some(Kind::Sampled) { + return Err(invalid("not a sampled field").at(name)); + } + let use_ = ColumnUse { sampled: true, trace: true, ..ColumnUse::own(name, Words::Values) }; + self.deps |= Deps::SAMPLES; + Ok(self.column(use_)) + } + + /// The program: channel ranges, then a range per fitted domain's reduction. + pub(crate) fn finish(mut self) -> Program { + for code in std::mem::take(&mut self.reductions) { + let start = self.program.code.len() as u32; + self.program.code.extend(code); + self.program.ranges.push([start, self.program.code.len() as u32]); + } + self.program + } + + fn begin(&mut self) -> u32 { + self.depth = 0; + self.deps = Deps::default(); + self.columns_read = 0; + self.program.code.len() as u32 + } + + fn close(&mut self, name: &str, start: u32) { + self.program.ranges.push([start, self.program.code.len() as u32]); + let reads = Reads { deps: self.deps, columns: self.columns_read }; + self.program.channels.push(Channel { name: name.into(), reads }); + } + + /// Compiles channel `name` storing the theme's value in `slot`, for an option left unset. + pub(crate) fn theme(&mut self, name: &str, slot: u32, store: Store) -> Result<()> { + let start = self.begin(); + self.op(wgsl::OP_THEME, slot, 0, 0, 0, 1)?; + self.store_op(store)?; + self.close(name, start); + Ok(()) + } + + fn store(&mut self, expr: &Expr, store: Store) -> Result<()> { + let want = match store { + Store::Number { .. } | Store::Size { .. } => Ty::Number, + Store::Color { .. } => Ty::Color, + Store::Flag { .. } => Ty::Bool, + }; + self.expect(expr, want)?; + self.store_op(store) + } + + fn store_op(&mut self, store: Store) -> Result<()> { + let slot = |s: Option| s.unwrap_or(NONE); + match store { + Store::Number { word, fallback } => self.op(wgsl::OP_STORE, word, slot(fallback), 0, 1, 0), + Store::Size { word, units, fallback } => { + self.program.units |= u32::from(units) << word; + self.op(wgsl::OP_STORE, word, slot(fallback), 0, 1, 0) + } + Store::Color { word, fallback } => self.op(wgsl::OP_STORE_COLOR, word, fallback, 0, 1, 0), + Store::Flag { word, bit } => self.op(wgsl::OP_STORE_FLAG, word, bit, 0, 1, 0), + } + } + + /// The column of a plain number field or point component, with its low part. + fn plain(&mut self, e: &Expr) -> Option { + let Node::Field(f) = &*e.0 else { return None }; + if f.of.is_some() || f.step { + return None; + } + let words = match (self.fields.kind(None, &f.name)?, f.component) { + (Kind::Number, None) => Words::Values, + (Kind::Point, Some(0)) => Words::X, + (Kind::Point, Some(1)) => Words::Y, + _ => return None, + }; + Some(self.column(ColumnUse { low: true, ..ColumnUse::own(f.name.clone(), words) })) + } + + fn coordinate(&mut self, e: &Expr) -> Result<()> { + if mentions_pointer(e) { + return Err(invalid("pointer() cannot place a position")); + } + self.expect(e, Ty::Number) + } + + fn expect(&mut self, e: &Expr, want: Ty) -> Result<()> { + if let Node::Missing = &*e.0 { + let word = match want { + Ty::Color => wgsl::MISSING_COLOR, + Ty::Bool => 0, + Ty::Number | Ty::Text => wgsl::MISSING, + }; + self.constant(word, want)?; + return Ok(()); + } + match (self.emit(e)?, want) { + (got, want) if got == want => Ok(()), + (Ty::Bool, Ty::Number) => Ok(()), + (got, want) => Err(invalid(format!("expected {}, found {}", ty_name(want), ty_name(got)))), + } + } + + fn emit(&mut self, e: &Expr) -> Result { + match &*e.0 { + Node::Number(v) => self.constant((*v as f32).to_bits(), Ty::Number), + Node::Bool(b) => self.constant(f32::from(u8::from(*b)).to_bits(), Ty::Bool), + Node::Color(c) => self.constant(c.packed(), Ty::Color), + Node::Missing => self.push(wgsl::OP_MISSING, 0, Ty::Number), + Node::Field(f) => self.field(f), + Node::State(State::Selected) => self.state(wgsl::OP_SELECTED, Deps::FOCUS, Ty::Bool), + Node::State(State::Hovered) => self.state(wgsl::OP_HOVERED, Deps::FOCUS, Ty::Bool), + Node::State(State::Pointer) => self.state(wgsl::OP_POINTER, Deps::POINTER, Ty::Number), + Node::State(State::Elapsed) => self.state(wgsl::OP_ELAPSED, Deps::TIME, Ty::Number), + Node::State(State::Zoom) => self.state(wgsl::OP_ZOOM, Deps::CAMERA, Ty::Number), + Node::Unary(op, a) => { + let ty = match (op, self.emit(a)?) { + (Unary::Not, Ty::Bool) => Ty::Bool, + (Unary::Not, t) => return Err(invalid(format!("not of {}", ty_name(t)))), + (_, Ty::Number | Ty::Bool) => Ty::Number, + (op, t) => return Err(invalid(format!("{op:?} of {}", ty_name(t)).to_lowercase())), + }; + self.op(unary_code(*op), 0, 0, 0, 1, 1)?; + Ok(ty) + } + Node::Binary(op, a, b) => self.binary(*op, a, b), + Node::When(c, a, b) => { + self.expect(c, Ty::Bool).map_err(|e| e.at("when"))?; + // A missing value takes the other branch's type, so it goes last: a missing first + // branch swaps the branches and negates the condition. + let (a, b) = match (&*a.0, &*b.0) { + (Node::Missing, Node::Missing) => (a, b), + (Node::Missing, _) => { + self.op(unary_code(Unary::Not), 0, 0, 0, 1, 1)?; + (b, a) + } + _ => (a, b), + }; + let ta = self.emit(a)?; + if let Node::Missing = &*b.0 { + self.expect(b, ta)?; + self.op(wgsl::OP_SELECT, 0, 0, 0, 3, 1)?; + return Ok(ta); + } + let ty = match (ta, self.emit(b)?) { + (a, b) if a == b => a, + (Ty::Bool, Ty::Number) | (Ty::Number, Ty::Bool) => Ty::Number, + (a, b) => return Err(invalid(format!("when chooses between {} and {}", ty_name(a), ty_name(b)))), + }; + self.op(wgsl::OP_SELECT, 0, 0, 0, 3, 1)?; + Ok(ty) + } + Node::Contains(..) => Err(invalid("contains reads texts, which only a query holds")), + Node::Is(a, text) => { + let Node::Field(f) = &*a.0 else { return Err(invalid("is compares a text field")) }; + if self.fields.kind(f.of.as_ref(), &f.name) != Some(Kind::Text) { + return Err(invalid("is compares a text field").at(&f.name)); + } + let column = self.field_column(f, Words::Codes, false); + self.op(wgsl::OP_FIELD, column, 0, 0, 0, 1)?; + let constant = self.program.constants.len() as u32; + self.program.constants.push(NONE); + self.program.texts.push(TextUse { constant, column, text: text.clone() }); + self.op(wgsl::OP_CONST, constant, 0, 0, 0, 1)?; + self.op(wgsl::OP_EQ, 0, 0, 0, 2, 1)?; + Ok(Ty::Bool) + } + Node::Scale { input, domain, range } => { + self.expect(input, Ty::Number)?; + let d = self.domain(input, *domain)?; + let r = self.program.constants.len() as u32; + self.program.constants.extend([(range[0] as f32).to_bits(), (range[1] as f32).to_bits()]); + self.op(wgsl::OP_SCALE, d, r, 0, 1, 1)?; + Ok(Ty::Number) + } + Node::Colormap { input, colormap, domain } => { + self.expect(input, Ty::Number)?; + // A categorical map bins values by their integer part, so it has nothing to fit. + let domain = match domain { + Domain::Fit if colormap.kind() == ColormapKind::Categorical => { + Domain::Fixed([0.0, f64::from(colormap.count())]) + } + _ => *domain, + }; + let d = self.domain(input, domain)?; + let at = self.program.code.len() as u32; + self.program.colormaps.push((at, colormap.clone())); + self.op(wgsl::OP_COLORMAP, colormap.kind().code() << 16, d, colormap.count(), 1, 1)?; + Ok(Ty::Color) + } + } + } + + fn field(&mut self, f: &FieldRef) -> Result { + let kind = self.fields.kind(f.of.as_ref(), &f.name).ok_or_else(|| match &f.of { + Some((data, table)) => invalid(format!("no field {} in {data}.{table}", f.name)), + None => invalid(format!("no field {}", f.name)), + })?; + let (words, ty, sampled) = match (kind, f.component) { + (Kind::Number, None) => (Words::Values, Ty::Number, false), + (Kind::Bool, None) => (Words::Values, Ty::Bool, false), + (Kind::Text, None) => (Words::Codes, Ty::Text, false), + (Kind::Sampled, None) => (Words::Values, Ty::Number, true), + (Kind::Point, Some(0)) => (Words::X, Ty::Number, false), + (Kind::Point, Some(1)) => (Words::Y, Ty::Number, false), + (Kind::Reference, _) => return Err(invalid("a reference names rows; read it as an end").at(&f.name)), + _ => return Err(invalid("not a number, boolean, or text field").at(&f.name)), + }; + let column = self.field_column(f, words, sampled); + self.deps |= if sampled { Deps::SAMPLES } else { Deps::DATA }; + self.op(wgsl::OP_FIELD, column, 0, 0, 0, 1)?; + Ok(ty) + } + + fn field_column(&mut self, f: &FieldRef, words: Words, sampled: bool) -> u32 { + self.deps |= if sampled { Deps::SAMPLES } else { Deps::DATA }; + let step = f.step && sampled; + self.column(ColumnUse { of: f.of.clone(), sampled, step, ..ColumnUse::own(f.name.clone(), words) }) + } + + fn column(&mut self, use_: ColumnUse) -> u32 { + let columns = &mut self.program.columns; + let i = columns.iter().position(|c| c == &use_).unwrap_or_else(|| { + columns.push(use_); + columns.len() - 1 + }); + self.columns_read |= Reads::column(i); + i as u32 + } + + fn binary(&mut self, op: Binary, a: &Expr, b: &Expr) -> Result { + let (ta, tb) = (self.emit(a)?, self.emit(b)?); + let numbers = matches!(ta, Ty::Number | Ty::Bool) && matches!(tb, Ty::Number | Ty::Bool); + let bools = ta == Ty::Bool && tb == Ty::Bool; + let ty = match op { + Binary::Add + | Binary::Sub + | Binary::Mul + | Binary::Div + | Binary::Rem + | Binary::Pow + | Binary::Min + | Binary::Max + if numbers => + { + Ty::Number + } + Binary::Lt | Binary::Le | Binary::Gt | Binary::Ge | Binary::Eq | Binary::Ne if numbers => Ty::Bool, + Binary::Eq | Binary::Ne if ta == Ty::Color && tb == Ty::Color => Ty::Bool, + Binary::And | Binary::Or if bools => Ty::Bool, + _ => { + let hint = if ta == Ty::Text || tb == Ty::Text { "; compare text with is" } else { "" }; + let reason = format!("{} of {} and {}{hint}", binary_name(op), ty_name(ta), ty_name(tb)); + return Err(invalid(reason)); + } + }; + self.op(binary_code(op), 0, 0, 0, 2, 1)?; + Ok(ty) + } + + /// A domain record in the constants; a fitted one adds a reduction of its input. + fn domain(&mut self, input: &Expr, domain: Domain) -> Result { + let at = self.program.constants.len() as u32; + match domain { + Domain::Fixed([a, b]) => { + self.program.constants.extend([0, (a as f32).to_bits(), (b as f32).to_bits(), 0]); + } + Domain::Fit => { + if self.reducing { + return Err(invalid("a fitted domain's input cannot fit another domain; set one with domain")); + } + let index = self.program.domains.len() as u32; + self.program.domains.push(Reads::default()); + self.program.constants.extend([1, 0, 0, index]); + // Compile the input again as a reduction; `finish` places it after the channels. + let saved = (std::mem::take(&mut self.program.code), self.depth, self.deps, self.columns_read); + self.depth = 0; + self.deps = Deps::default(); + self.columns_read = 0; + self.reducing = true; + let result = self.expect(input, Ty::Number).and_then(|()| self.op(wgsl::OP_REDUCE, index, 0, 0, 1, 0)); + self.reducing = false; + let reduction = std::mem::replace(&mut self.program.code, saved.0); + let reads = Reads { deps: self.deps, columns: self.columns_read }; + self.depth = saved.1; + self.deps = saved.2 | Deps::DOMAIN; + self.columns_read = saved.3 | reads.columns; + result?; + self.program.domains[index as usize] = reads; + self.reductions.push(reduction); + } + } + Ok(at) + } + + fn state(&mut self, code: u32, deps: Deps, ty: Ty) -> Result { + self.deps |= deps; + self.push(code, 0, ty) + } + + fn push(&mut self, code: u32, a: u32, ty: Ty) -> Result { + self.op(code, a, 0, 0, 0, 1)?; + Ok(ty) + } + + fn constant(&mut self, word: u32, ty: Ty) -> Result { + let constants = &mut self.program.constants; + let i = constants.iter().position(|&c| c == word).unwrap_or_else(|| { + constants.push(word); + constants.len() - 1 + }); + self.push(wgsl::OP_CONST, i as u32, ty) + } + + fn op(&mut self, code: u32, a: u32, b: u32, c: u32, pops: u32, pushes: u32) -> Result<()> { + self.depth = self.depth - pops + pushes; + if self.depth > wgsl::STACK { + return Err(invalid("expression too deep")); + } + self.program.code.push([code, a, b, c]); + Ok(()) + } +} + +fn mentions_pointer(e: &Expr) -> bool { + match &*e.0 { + Node::State(State::Pointer) => true, + Node::Unary(_, a) | Node::Is(a, _) | Node::Contains(a, _) => mentions_pointer(a), + Node::Binary(_, a, b) => mentions_pointer(a) || mentions_pointer(b), + Node::When(c, a, b) => mentions_pointer(c) || mentions_pointer(a) || mentions_pointer(b), + Node::Scale { input, .. } | Node::Colormap { input, .. } => mentions_pointer(input), + _ => false, + } +} + +fn unary_code(op: Unary) -> u32 { + match op { + Unary::Neg => wgsl::OP_NEG, + Unary::Not => wgsl::OP_NOT, + Unary::Abs => wgsl::OP_ABS, + Unary::Sqrt => wgsl::OP_SQRT, + Unary::Sin => wgsl::OP_SIN, + Unary::Cos => wgsl::OP_COS, + Unary::Floor => wgsl::OP_FLOOR, + Unary::Ln => wgsl::OP_LOG, + Unary::Exp => wgsl::OP_EXP, + } +} + +fn binary_code(op: Binary) -> u32 { + match op { + Binary::Add => wgsl::OP_ADD, + Binary::Sub => wgsl::OP_SUB, + Binary::Mul => wgsl::OP_MUL, + Binary::Div => wgsl::OP_DIV, + Binary::Rem => wgsl::OP_MOD, + Binary::Pow => wgsl::OP_POW, + Binary::Min => wgsl::OP_MIN, + Binary::Max => wgsl::OP_MAX, + Binary::Lt => wgsl::OP_LT, + Binary::Le => wgsl::OP_LE, + Binary::Gt => wgsl::OP_GT, + Binary::Ge => wgsl::OP_GE, + Binary::Eq => wgsl::OP_EQ, + Binary::Ne => wgsl::OP_NE, + Binary::And => wgsl::OP_AND, + Binary::Or => wgsl::OP_OR, + } +} + +fn binary_name(op: Binary) -> &'static str { + match op { + Binary::Add => "sum", + Binary::Sub => "difference", + Binary::Mul => "product", + Binary::Div => "quotient", + Binary::Rem => "remainder", + Binary::Pow => "power", + Binary::Min => "min", + Binary::Max => "max", + Binary::Lt | Binary::Le | Binary::Gt | Binary::Ge => "comparison", + Binary::Eq | Binary::Ne => "equality", + Binary::And => "and", + Binary::Or => "or", + } +} + +fn ty_name(ty: Ty) -> &'static str { + match ty { + Ty::Number => "a number", + Ty::Bool => "a boolean", + Ty::Color => "a color", + Ty::Text => "a text", + } +} diff --git a/crates/latkit/src/expr/cpu.rs b/crates/latkit/src/expr/cpu.rs new file mode 100644 index 00000000..d057b0da --- /dev/null +++ b/crates/latkit/src/expr/cpu.rs @@ -0,0 +1,225 @@ +//! The expression machine on the CPU, for what a diagram's sheet reads (where rows stand, how large +//! they are, and the texts its blocks fit) and what a query keeps, sorts, and selects. The GPU runs +//! the same expressions for everything drawn; here they read fields, sampled ones at a coordinate. + +use std::cell::RefCell; +use std::sync::Arc; + +use rustc_hash::FxHashMap; + +use super::{Binary, Domain, Expr, FieldRef, Node, Unary}; +use crate::Kind; +use crate::data::{Data, Field, Geometry, Table, Value}; + +/// The rows an expression reads: a table, and every dataset its joins may name. +pub(crate) struct Rows<'a> { + pub(crate) table: &'a Table, + pub(crate) all: &'a [Data], + /// The axis coordinate sampled fields are read at: their last frame by default. + at: f64, + /// Fitted domains already reduced, by the input they reduce. + fitted: RefCell>, +} + +impl<'a> Rows<'a> { + pub(crate) fn new(table: &'a Table, all: &'a [Data]) -> Rows<'a> { + Rows { table, all, at: f64::INFINITY, fitted: RefCell::default() } + } + + /// The rows with sampled fields read at axis coordinate `at`. + pub(crate) fn at(mut self, at: f64) -> Rows<'a> { + self.at = at; + self + } + + /// `expr` for `row` as a number; `None` where it reads missing, or holds no number. + pub(crate) fn number(&self, expr: &Expr, row: usize) -> Option { + let v = self.eval(expr, row); + v.is_finite().then_some(v) + } + + /// `expr` for every row, NaN where it reads missing, each made into a `T` by `make`: a plain + /// field read page by page, anything else row by row. + pub(crate) fn numbers(&self, expr: &Expr, mut make: impl FnMut(f64) -> T) -> Vec { + let n = self.table.len(); + let mut out = Vec::with_capacity(n); + match &*expr.0 { + Node::Number(v) => { + out.resize_with(n, || make(*v)); + return out; + } + Node::Field(f) if f.of.is_none() => { + if let Some(Field::Values(column, _)) = self.table.field_named(&f.name) { + let pages = column.pages().iter().map(|p| &p.values); + match (column.kind(), f.component) { + (Kind::Number | Kind::Bool, None) => { + pages.for_each(|v| v.each_number(|x| out.push(make(x.unwrap_or(f64::NAN))))); + return out; + } + (Kind::Point, Some(k)) => { + let k = usize::from(k.min(1)); + for v in pages { + let coords = v.geometry().map_or(&[][..], Geometry::coords); + out.extend( + (0..v.len()).map(|i| make(if v.is_valid(i) { coords[i][k] } else { f64::NAN })), + ); + } + return out; + } + _ => {} + } + } + } + _ => {} + } + out.extend((0..n).map(|row| make(self.eval(expr, row)))); + out + } + + /// The text field `expr` names, for `row`. + pub(crate) fn text(&self, expr: &Expr, row: usize) -> Option> { + let Node::Field(f) = &*expr.0 else { return None }; + match self.value(f, row)? { + Value::Text(text) => Some(text), + _ => None, + } + } + + /// Field `f`'s value for `row`: of the table, or of a joined one by the row's id. + fn value(&self, f: &FieldRef, row: usize) -> Option { + let value = match &f.of { + None => self.table.value(row, &f.name, self.at)?, + Some((data, table)) => { + let other = self.all.iter().find(|d| d.name() == data)?.table(table)?; + let key = self.table.ids.key(row)?; + other.value(other.row(key)?, &f.name, self.at)? + } + }; + Some(match (value, f.component) { + (Value::Point(p), Some(k)) => Value::Number(p[usize::from(k.min(1))]), + (value, _) => value, + }) + } + + /// `expr` as the GPU computes it, NaN standing for missing. + fn eval(&self, expr: &Expr, row: usize) -> f64 { + match &*expr.0 { + Node::Number(v) => *v, + Node::Bool(b) => f64::from(u8::from(*b)), + Node::Field(f) => match self.value(f, row) { + Some(Value::Number(n)) => n, + Some(Value::Bool(b)) => f64::from(u8::from(b)), + _ => f64::NAN, + }, + Node::Unary(op, a) => unary(*op, self.eval(a, row)), + Node::Binary(op, a, b) => binary(*op, self.eval(a, row), self.eval(b, row)), + Node::When(c, a, b) => { + if self.eval(c, row) > 0.5 { + self.eval(a, row) + } else { + self.eval(b, row) + } + } + Node::Is(a, text) => { + let Node::Field(f) = &*a.0 else { return f64::NAN }; + f64::from(u8::from(matches!(self.value(f, row), Some(Value::Text(t)) if *t == **text))) + } + Node::Contains(a, text) => { + let Node::Field(f) = &*a.0 else { return f64::NAN }; + let held = |t: &str| t.to_lowercase().contains(&text.to_lowercase()); + f64::from(u8::from(matches!(self.value(f, row), Some(Value::Text(t)) if held(&t)))) + } + Node::Scale { input, domain, range } => { + let x = self.eval(input, row); + if !x.is_finite() { + return x; + } + let [lo, hi] = match domain { + Domain::Fixed(d) => *d, + Domain::Fit => self.fit(input), + }; + let span = hi - lo; + let t = if span == 0.0 { 0.5 } else { (x - lo) / span }; + range[0] + (range[1] - range[0]) * t.clamp(0.0, 1.0) + } + Node::Color(_) | Node::Missing | Node::State(_) | Node::Colormap { .. } => f64::NAN, + } + } + + /// The extent of `input` over every row, as a fitted domain reduces it. + fn fit(&self, input: &Expr) -> [f64; 2] { + let key = Arc::as_ptr(&input.0); + if let Some(&extent) = self.fitted.borrow().get(&key) { + return extent; + } + let mut extent = [f64::INFINITY, f64::NEG_INFINITY]; + for row in 0..self.table.len() { + let x = self.eval(input, row); + if x.is_finite() { + extent = [extent[0].min(x), extent[1].max(x)]; + } + } + if extent[0] > extent[1] { + extent = [0.0, 1.0]; + } + self.fitted.borrow_mut().insert(key, extent); + extent + } +} + +fn unary(op: Unary, a: f64) -> f64 { + match op { + Unary::Neg => -a, + Unary::Not => f64::from(u8::from(a <= 0.5)), + Unary::Abs => a.abs(), + Unary::Sqrt => a.sqrt(), + Unary::Sin => a.sin(), + Unary::Cos => a.cos(), + Unary::Floor => a.floor(), + Unary::Ln => a.ln(), + Unary::Exp => a.exp(), + } +} + +fn binary(op: Binary, a: f64, b: f64) -> f64 { + let truth = |v: bool| f64::from(u8::from(v)); + match op { + Binary::Add => a + b, + Binary::Sub => a - b, + Binary::Mul => a * b, + Binary::Div => a / b, + Binary::Rem => a - b * (a / b).floor(), + Binary::Pow => a.powf(b), + Binary::Min => a.min(b), + Binary::Max => a.max(b), + Binary::Lt => truth(a < b), + Binary::Le => truth(a <= b), + Binary::Gt => truth(a > b), + Binary::Ge => truth(a >= b), + Binary::Eq => truth(a == b), + Binary::Ne => truth(a != b), + Binary::And => truth(a > 0.5 && b > 0.5), + Binary::Or => truth(a > 0.5 || b > 0.5), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Ids, Table, field, when}; + + #[test] + fn numbers_follow_the_gpu() { + let table = Table::new("T", Ids::count(3)) + .field("w", vec![Some(10.0), None, Some(30.0)]) + .field("on", vec![true, false, true]); + let rows = Rows::new(&table, &[]); + let size = field("w") * 2.0 + 4.0; + assert_eq!(rows.number(&size, 0), Some(24.0)); + assert_eq!(rows.number(&size, 1), None, "missing stays missing"); + let pick = when(field("on")).then(1.0).otherwise(2.0); + assert_eq!((0..3).map(|r| rows.number(&pick, r)).collect::>(), [Some(1.0), Some(2.0), Some(1.0)]); + let scaled: Expr = field("w").scale(0.0..=1.0).into(); + assert_eq!(rows.number(&scaled, 2), Some(1.0), "a fitted domain spans the values"); + } +} diff --git a/crates/latkit/src/expr/form.rs b/crates/latkit/src/expr/form.rs new file mode 100644 index 00000000..f56eb1e9 --- /dev/null +++ b/crates/latkit/src/expr/form.rs @@ -0,0 +1,497 @@ +//! Expressions, sizes, colors, and colormaps as JSON. A number or boolean is a constant, a string a +//! field (or a hex color when it starts with `#`), and an object one node, named by its key: +//! +//! | Form | Builder | +//! | ---------------------------------------------------------- | ------------------------------- | +//! | `{ "field": "x", "of": ["data", "Table"], "step": true }` | `field("x").of(..).step()` | +//! | `{ "color": "#ffb000" }` | a color | +//! | `{ "state": "selected" }` | `selected()`, `hovered()`, … | +//! | `{ "missing": true }` | `Expr::missing()` | +//! | `{ "op": "add", "args": [a, b] }` | `a + b`, `a.min(b)`, `!a`, … | +//! | `{ "when": [[c, v], …], "otherwise": e }` | `when(c).then(v)…otherwise(e)` | +//! | `{ "is": [a, "text"] }`, `{ "contains": [a, "text"] }` | `a.is("text")`, `a.contains(..)` | +//! | `{ "scale": [0, 1], "value": a, "domain": [lo, hi] }` | `a.scale(..).domain(..)` | +//! | `{ "colormap": "viridis", "value": a, "domain": [lo, hi] }` | `a.colormap(..).domain(..)` | +//! | `{ "units": a, "atLeast": 2, "atMost": 20 }` (sizes only) | `units(a).at_least(..)` | +//! +//! Each object is its kind's form exactly: a key another kind has is refused. A map is a catalog name +//! or `{ "kind": "sequential", "colors": ["black", [0.2, "red"], "white"] }`, a color placed as a +//! `[place, color]` pair, and `categories` naming a categorical map's colors. + +use std::borrow::Cow; + +use schemars::{JsonSchema, Schema, SchemaGenerator, json_schema}; +use serde::Deserialize; +use serde::de::{self, DeserializeOwned, Deserializer}; +use serde_json::{Map, Value}; + +use super::{Binary, Color, Colormap, ColormapKind, Expr, Node, Size, State, Stop, Unary, node}; +use crate::Name; + +/// The key naming each kind of expression object. +const KINDS: &[&str] = &["field", "color", "state", "missing", "op", "when", "is", "contains", "scale", "colormap"]; + +/// `T` read from JSON `value`, or why not. +fn read(value: Value) -> Result { + serde_json::from_value(value).map_err(|e| e.to_string()) +} + +impl<'de> Deserialize<'de> for Expr { + fn deserialize>(deserializer: D) -> Result { + Expr::from_value(Value::deserialize(deserializer)?).map_err(de::Error::custom) + } +} + +impl Expr { + /// The expression JSON `value` writes. + pub(crate) fn from_value(value: Value) -> Result { + match value { + Value::Number(n) => n.as_f64().map(Expr::from).ok_or_else(|| "a number within range".to_owned()), + Value::Bool(b) => Ok(b.into()), + Value::String(text) if text.starts_with('#') => { + Color::hex(&text).map(Expr::from).ok_or_else(|| format!("not a hex color: {text:?}")) + } + Value::String(name) => Ok(super::field(name)), + Value::Object(map) => object(map), + Value::Null | Value::Array(_) => { + Err("an expression is a number, a boolean, a field's name, or an expression object".to_owned()) + } + } + } +} + +/// The expression an object writes, read by the form of the kind its key names. +fn object(map: Map) -> Result { + let Some(&kind) = KINDS.iter().find(|&&k| map.contains_key(k)) else { + return Err(format!("an expression object has one of {}", KINDS.join(", "))); + }; + let op = map.get("op").and_then(Value::as_str).map(str::to_owned); + let value = Value::Object(map); + Ok(match kind { + "field" => { + let FieldNode { field, of, step } = read(value)?; + let expr = super::field(field); + let expr = match of { + Some((data, table)) => expr.of(data, table), + None => expr, + }; + if step { expr.step() } else { expr } + } + "color" => read::(value)?.color.into(), + "state" => node(Node::State(read::(value)?.state)), + "missing" => { + if !read::(value)?.missing { + return Err("missing is true".to_owned()); + } + Expr::missing() + } + "op" if op.as_deref().is_some_and(|op| named::(op).is_ok()) => { + let UnaryNode { op, args: [a] } = read(value)?; + node(Node::Unary(op, a)) + } + "op" => { + let BinaryNode { op, args: [a, b] } = read(value)?; + node(Node::Binary(op, a, b)) + } + "when" => { + let WhenNode { when, otherwise } = read(value)?; + when.into_iter().rev().fold(otherwise, |rest, (c, v)| node(Node::When(c, v, rest))) + } + "is" => { + let IsNode { is: (a, text) } = read(value)?; + a.is(&text) + } + "contains" => { + let ContainsNode { contains: (a, text) } = read(value)?; + a.contains(&text) + } + "scale" => { + let ScaleNode { scale: [lo, hi], value, domain } = read(value)?; + domained(value.scale(lo..=hi), domain) + } + _ => { + let ColormapNode { colormap, value, domain } = read(value)?; + domained(value.colormap(colormap), domain) + } + }) +} + +/// `mapped` with `domain` when given, else fitting the values shown. +fn domained(mapped: super::Mapped, domain: Option<[f64; 2]>) -> Expr { + match domain { + Some([lo, hi]) => mapped.domain(lo..=hi).into(), + None => mapped.into(), + } +} + +/// `name` read as one of the names `T` deserializes from. +fn named(name: &str) -> Result { + read(Value::String(name.to_owned())) +} + +/// A field of each row: of the mark's own table, or of another dataset's table joined by row id. +#[derive(Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] +struct FieldNode { + field: Name, + /// The dataset and table the field is read from, joined by row id. + #[serde(default)] + #[schemars(extend("tsType" = "[data: string, table: string]"))] + of: Option<(Name, Name)>, + /// Reads a sampled field at its last frame without interpolating. + #[serde(default)] + step: bool, +} + +#[derive(Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] +struct ColorNode { + color: Color, +} + +/// What the view knows of each row. +#[derive(Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] +struct StateNode { + state: State, +} + +/// A missing value: options that read one take the theme's. +#[derive(Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] +struct MissingNode { + #[schemars(extend("const" = true))] + missing: bool, +} + +#[derive(Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] +struct UnaryNode { + op: Unary, + args: [Expr; 1], +} + +#[derive(Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] +struct BinaryNode { + op: Binary, + args: [Expr; 2], +} + +/// The value of the first case whose condition holds, else `otherwise`. +#[derive(Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] +struct WhenNode { + #[schemars(extend("tsType" = "[condition: ExprInput, value: ExprInput][]"))] + when: Vec<(Expr, Expr)>, + otherwise: Expr, +} + +/// Whether a text field equals the text. +#[derive(Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] +struct IsNode { + #[schemars(extend("tsType" = "[field: ExprInput, text: string]"))] + is: (Expr, String), +} + +/// Whether a text field holds the text, ignoring case: read by queries, which hold texts. +#[derive(Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] +struct ContainsNode { + #[schemars(extend("tsType" = "[field: ExprInput, text: string]"))] + contains: (Expr, String), +} + +/// `value` mapped linearly onto the range `scale`, clamped: from its `domain`, else from the extent of +/// the values shown. +#[derive(Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] +struct ScaleNode { + #[schemars(extend("tsType" = "[low: number, high: number]"))] + scale: [f64; 2], + value: Expr, + #[serde(default)] + #[schemars(extend("tsType" = "[low: number, high: number]"))] + domain: Option<[f64; 2]>, +} + +/// `value` through `colormap`: from its `domain`, else from the extent of the values shown. +#[derive(Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] +struct ColormapNode { + colormap: Colormap, + value: Expr, + #[serde(default)] + #[schemars(extend("tsType" = "[low: number, high: number]"))] + domain: Option<[f64; 2]>, +} + +/// A size in position units, so it scales as the view zooms, kept within CSS pixels when given. +#[derive(Deserialize, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[allow(clippy::struct_field_names, reason = "its JSON is `{units, atLeast, atMost}`")] +struct Units { + units: Expr, + /// CSS pixels it keeps at least, however far the view zooms out. + #[serde(default)] + #[schemars(range(min = 0))] + at_least: Option, + /// CSS pixels it keeps at most, however far the view zooms in. + #[serde(default)] + #[schemars(range(min = 0))] + at_most: Option, +} + +/// An expression is its JSON, `ExprNode`; TypeScript also takes the builders that write it. +impl JsonSchema for Expr { + fn schema_name() -> Cow<'static, str> { + "Expr".into() + } + + fn json_schema(generator: &mut SchemaGenerator) -> Schema { + let mut schema = generator.subschema_for::(); + schema.insert("tsType".into(), "ExprInput".into()); + schema + } +} + +/// The JSON an expression is written as. +struct ExprNode; + +impl JsonSchema for ExprNode { + fn schema_name() -> Cow<'static, str> { + "ExprNode".into() + } + + fn json_schema(generator: &mut SchemaGenerator) -> Schema { + let forms = [ + generator.subschema_for::(), + generator.subschema_for::(), + generator.subschema_for::(), + generator.subschema_for::(), + generator.subschema_for::(), + generator.subschema_for::(), + generator.subschema_for::(), + generator.subschema_for::(), + generator.subschema_for::(), + generator.subschema_for::(), + generator.subschema_for::(), + ]; + let mut any = vec![ + json_schema!({ "type": "number" }), + json_schema!({ "type": "boolean" }), + json_schema!({ "type": "string", "description": "A field's name, or a hex color when it starts with `#`." }), + ]; + any.extend(forms); + json_schema!({ + "description": "A value for every row of a mark: a constant, a field, view state, or arithmetic of them.", + "anyOf": any, + }) + } +} + +impl<'de> Deserialize<'de> for Size { + fn deserialize>(deserializer: D) -> Result { + let value = Value::deserialize(deserializer)?; + if !value.as_object().is_some_and(|map| map.contains_key("units")) { + return Expr::from_value(value).map(Size::from).map_err(de::Error::custom); + } + let Units { units, at_least, at_most } = read(value).map_err(de::Error::custom)?; + Ok(Size { expr: units, units: true, px: [at_least.unwrap_or(0.0).max(0.0), at_most.unwrap_or(f32::INFINITY)] }) + } +} + +impl JsonSchema for Size { + fn schema_name() -> Cow<'static, str> { + "Size".into() + } + + fn json_schema(generator: &mut SchemaGenerator) -> Schema { + let expr = generator.subschema_for::(); + let units = generator.subschema_for::(); + json_schema!({ + "description": "A size: CSS pixels, or position units with `units`.", + "anyOf": [expr, units], + }) + } +} + +impl<'de> Deserialize<'de> for Color { + fn deserialize>(deserializer: D) -> Result { + let css = String::deserialize(deserializer)?; + Color::css(&css).ok_or_else(|| de::Error::custom(format!("not a CSS color: {css:?}"))) + } +} + +/// A color writes as CSS `rgba(…)`, read back exactly: whole channels as bytes, alpha as it is. +impl serde::Serialize for Color { + fn serialize(&self, serializer: S) -> Result { + let channel = |v: f32| { + let byte = v * 255.0; + if (byte - byte.round()).abs() < 1e-3 { byte.round() } else { byte } + }; + let [r, g, b] = [self.r, self.g, self.b].map(channel); + serializer.serialize_str(&format!("rgba({r}, {g}, {b}, {})", self.a)) + } +} + +impl JsonSchema for Color { + fn schema_name() -> Cow<'static, str> { + "Color".into() + } + + fn inline_schema() -> bool { + true + } + + fn json_schema(_: &mut SchemaGenerator) -> Schema { + json_schema!({ + "description": "A CSS color, such as `#ffb000` or `rebeccapurple`.", + "tsType": "Color", + "type": "string", + }) + } +} + +/// Your own colormap: its kind, its colors, and for a categorical map its categories' names. +#[derive(Deserialize, JsonSchema)] +#[serde(deny_unknown_fields)] +struct CustomColormap { + kind: ColormapKind, + /// Colors blended in OKLab, each at its `[place, color]` from 0 to 1 or evenly between its + /// neighbors, as in a CSS gradient; a categorical map's, one per category. + colors: Vec, + /// The categories' names, in order, for a legend: a categorical map's alone. + #[serde(default)] + categories: Vec, +} + +impl<'de> Deserialize<'de> for Colormap { + fn deserialize>(deserializer: D) -> Result { + let value = Value::deserialize(deserializer)?; + if let Value::String(name) = &value { + return Colormap::named(name).ok_or_else(|| de::Error::custom(format!("no colormap named {name:?}"))); + } + let CustomColormap { kind, colors, categories } = read(value).map_err(de::Error::custom)?; + if kind != ColormapKind::Categorical && !categories.is_empty() { + return Err(de::Error::custom("only a categorical map has categories")); + } + let map = Colormap::new(kind, colors).map_err(|e| match e { + crate::Error::Invalid { reason, .. } => de::Error::custom(reason), + e => de::Error::custom(e), + })?; + Ok(if categories.is_empty() { map } else { map.categories(categories) }) + } +} + +impl JsonSchema for Colormap { + fn schema_name() -> Cow<'static, str> { + "Colormap".into() + } + + fn json_schema(generator: &mut SchemaGenerator) -> Schema { + let names: Vec<&str> = super::colormap::catalog().collect(); + generator.definitions_mut().insert( + "ColormapName".into(), + serde_json::json!({ "description": "A colormap of the catalog.", "type": "string", "enum": names }), + ); + let colors = generator.subschema_for::(); + json_schema!({ + "description": "Colors for a range of values: a catalog name, or your own colors.", + "anyOf": [{ "$ref": "#/$defs/ColormapName" }, colors], + }) + } +} + +impl<'de> Deserialize<'de> for Stop { + fn deserialize>(deserializer: D) -> Result { + #[derive(Deserialize)] + #[serde(untagged)] + enum Form { + Color(Color), + Placed(f32, Color), + } + Ok(match Form::deserialize(deserializer)? { + Form::Color(color) => color.into(), + Form::Placed(at, color) => (at, color).into(), + }) + } +} + +impl JsonSchema for Stop { + fn schema_name() -> Cow<'static, str> { + "Stop".into() + } + + fn inline_schema() -> bool { + true + } + + fn json_schema(generator: &mut SchemaGenerator) -> Schema { + let color = generator.subschema_for::(); + json_schema!({ + "anyOf": [ + color, + { + "type": "array", + "prefixItems": [{ "type": "number", "minimum": 0, "maximum": 1 }, color], + "minItems": 2, + "maxItems": 2, + }, + ], + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{field, selected, when}; + + fn parse(json: &str) -> Expr { + serde_json::from_str(json).expect("an expression") + } + + #[test] + fn forms_match_builders() { + assert_eq!(parse("\"vm\""), field("vm")); + assert_eq!(parse("2.5"), Expr::from(2.5)); + assert_eq!(parse(r#"{"op": "add", "args": ["a", 1]}"#), field("a") + 1.0); + assert_eq!(parse(r#"{"op": "not", "args": ["on"]}"#), !field("on")); + assert_eq!( + parse(r##"{"when": [[{"state": "selected"}, {"color": "#ff0000"}]], "otherwise": "c"}"##), + when(selected()).then(Color::rgb(1.0, 0.0, 0.0)).otherwise(field("c")) + ); + assert_eq!( + parse(r#"{"colormap": "balance", "value": "vm", "domain": [0.9, 1.1]}"#), + field("vm").colormap(Colormap::BALANCE).domain(0.9..=1.1).into() + ); + assert_eq!(parse(r#"{"scale": [2, 8], "value": "kv"}"#), field("kv").scale(2.0..=8.0).into()); + assert_eq!(parse(r#"{"contains": ["name", "lake"]}"#), field("name").contains("lake")); + let size: Size = serde_json::from_str(r#"{"units": 3}"#).expect("a size"); + assert_eq!(size, crate::units(3.0)); + let size: Size = serde_json::from_str(r#"{"units": 3, "atLeast": 2, "atMost": 20}"#).expect("a size"); + assert_eq!(size, crate::units(3.0).at_least(2.0).at_most(20.0)); + let map: Colormap = + serde_json::from_str(r#"{"kind": "sequential", "colors": ["black", [0.25, "red"], "white"]}"#) + .expect("a map"); + let stops = [Stop::from(Color::BLACK), (0.25, Color::rgb(1.0, 0.0, 0.0)).into(), Color::WHITE.into()]; + assert_eq!(map, Colormap::new(ColormapKind::Sequential, stops).unwrap()); + } + + #[test] + fn errors_name_what_is_wrong() { + let error = serde_json::from_str::(r#"{"field": "a", "color": "red"}"#).expect_err("two kinds"); + assert!(error.to_string().contains("color"), "{error}"); + let error = serde_json::from_str::(r#"{"field": "a", "map": "viridis"}"#).expect_err("a stray key"); + assert!(error.to_string().contains("map"), "{error}"); + let error = serde_json::from_str::(r#"{"op": "frob", "args": []}"#).expect_err("unknown op"); + assert!(error.to_string().contains("frob"), "{error}"); + let error = serde_json::from_str::(r#"{"op": "add", "args": ["a"]}"#).expect_err("two arguments"); + assert!(error.to_string().contains('2'), "{error}"); + let error = serde_json::from_str::(r#"{"kind": "cyclic", "colors": [[0.5, "red"], [0.2, "blue"]]}"#) + .expect_err("descending places"); + assert!(error.to_string().contains("ascend"), "{error}"); + } +} diff --git a/crates/latkit/src/expr/mod.rs b/crates/latkit/src/expr/mod.rs new file mode 100644 index 00000000..6fc49a38 --- /dev/null +++ b/crates/latkit/src/expr/mod.rs @@ -0,0 +1,580 @@ +//! Per-row values: expressions over fields and view state, compiled to bytecode the GPU runs. + +mod color; +mod colormap; +#[cfg(feature = "gpu")] +pub(crate) mod compile; +pub(crate) mod cpu; +mod form; +mod ramp; + +use std::ops::{Add, BitAnd, BitOr, Div, Mul, Neg, Not, RangeInclusive, Rem, Sub}; +use std::sync::Arc; + +pub use color::Color; +#[cfg(feature = "gpu")] +pub(crate) use colormap::ColormapKey; +pub use colormap::{Colormap, ColormapKind, Stop}; + +use crate::Name; + +/// A value for every row of a mark: a constant, a field, view state, or arithmetic of them. +/// +/// A `&str` converts to the field of that name, so options read fields by name: +/// +/// ``` +/// # use latkit::{field, when, selected, Colormap, Color}; +/// let color = field("vm").colormap(Colormap::BALANCE).domain(0.95..=1.05); +/// let radius = 4.0 + field("load") / 100.0; +/// let status = when(selected()).then(Color::hex("#ffb000").unwrap()).otherwise(color); +/// let high_voltage = field("kv").ge(230.0) & field("kind").is("substation"); +/// ``` +/// +/// Expressions compile to bytecode; changing one never compiles a shader. +#[derive(Clone, PartialEq, Debug)] +pub struct Expr(pub(crate) Arc); + +#[derive(PartialEq, Debug)] +pub(crate) enum Node { + Number(f64), + Bool(bool), + Color(Color), + Missing, + Field(FieldRef), + State(State), + Unary(Unary, Expr), + Binary(Binary, Expr, Expr), + When(Expr, Expr, Expr), + Is(Expr, Arc), + Contains(Expr, Arc), + Scale { input: Expr, domain: Domain, range: [f64; 2] }, + Colormap { input: Expr, colormap: Colormap, domain: Domain }, +} + +/// A field read: of the mark's own table, or of another dataset's table joined by row id. +#[derive(Clone, PartialEq, Debug)] +pub(crate) struct FieldRef { + pub(crate) name: Name, + pub(crate) of: Option<(Name, Name)>, + pub(crate) step: bool, + /// For a point geometry: 0 for x, 1 for y. + pub(crate) component: Option, +} + +/// What the view knows of each row. +#[derive(Clone, Copy, PartialEq, Eq, Debug, serde::Deserialize, schemars::JsonSchema)] +#[serde(rename_all = "lowercase")] +pub(crate) enum State { + Selected, + Hovered, + Pointer, + Elapsed, + Zoom, +} + +/// An operation of one value. +#[derive(Clone, Copy, PartialEq, Eq, Debug, serde::Deserialize, schemars::JsonSchema)] +#[serde(rename_all = "lowercase")] +pub(crate) enum Unary { + Neg, + Not, + Abs, + Sqrt, + Sin, + Cos, + Floor, + Ln, + Exp, +} + +/// An operation of two values. +#[derive(Clone, Copy, PartialEq, Eq, Debug, serde::Deserialize, schemars::JsonSchema)] +#[serde(rename_all = "lowercase")] +pub(crate) enum Binary { + Add, + Sub, + Mul, + Div, + Rem, + Pow, + Min, + Max, + Lt, + Le, + Gt, + Ge, + Eq, + Ne, + And, + Or, +} + +#[derive(Clone, Copy, PartialEq, Debug)] +pub(crate) enum Domain { + /// The extent of the values shown, reduced on the GPU. + Fit, + Fixed([f64; 2]), +} + +pub(crate) fn node(node: Node) -> Expr { + Expr(Arc::new(node)) +} + +/// The field `name` of each row. +pub fn field(name: impl Into) -> Expr { + node(Node::Field(FieldRef { name: name.into(), of: None, step: false, component: None })) +} + +/// Starts a conditional: `when(c).then(a).when(d).then(b).otherwise(e)`. +pub fn when(condition: impl Into) -> When { + When { cases: Vec::new(), condition: condition.into() } +} + +/// Whether the row is selected. +pub fn selected() -> Expr { + node(Node::State(State::Selected)) +} + +/// Whether the pointer is over the row. +pub fn hovered() -> Expr { + node(Node::State(State::Hovered)) +} + +/// CSS pixels from a vertex to the pointer; for vertices only, and not in their position. +pub fn pointer() -> Expr { + node(Node::State(State::Pointer)) +} + +/// Seconds since the view was created; a mark that reads it redraws every frame. +pub fn elapsed() -> Expr { + node(Node::State(State::Elapsed)) +} + +/// The camera's zoom: the web mercator level on the earth, log₂ CSS pixels per unit elsewhere. Options +/// that read it change with the view, as levels of detail do. +pub fn zoom() -> Expr { + node(Node::State(State::Zoom)) +} + +/// A size measured in position units, so it scales as the view zooms; [`Size::at_least`] and +/// [`Size::at_most`] keep it within CSS pixels. +pub fn units(size: impl Into) -> Size { + Size { expr: size.into(), units: true, px: Size::ANY } +} + +macro_rules! unary { + ($($(#[$doc:meta])* $name:ident => $op:ident),* $(,)?) => {$( + $(#[$doc])* + #[must_use] + pub fn $name(self) -> Expr { + node(Node::Unary(Unary::$op, self)) + } + )*}; +} + +macro_rules! binary { + ($($(#[$doc:meta])* $name:ident => $op:ident),* $(,)?) => {$( + $(#[$doc])* + #[must_use] + pub fn $name(self, other: impl Into) -> Expr { + node(Node::Binary(Binary::$op, self, other.into())) + } + )*}; +} + +impl Expr { + /// A missing value: options that read one take the theme's value. + pub fn missing() -> Expr { + node(Node::Missing) + } + + unary!( + /// The absolute value. + abs => Abs, + /// The square root. + sqrt => Sqrt, + /// The sine of radians. + sin => Sin, + /// The cosine of radians. + cos => Cos, + /// The largest integer at most the value. + floor => Floor, + /// The natural logarithm. + ln => Ln, + /// `e` raised to the value. + exp => Exp, + ); + + binary!( + /// The smaller value. + min => Min, + /// The larger value. + max => Max, + /// The value raised to `other`. + pow => Pow, + /// Whether the value is less than `other`. + lt => Lt, + /// Whether the value is at most `other`. + le => Le, + /// Whether the value is greater than `other`. + gt => Gt, + /// Whether the value is at least `other`. + ge => Ge, + /// Whether the value equals `other`. + eq => Eq, + /// Whether the value differs from `other`. + ne => Ne, + ); + + /// The value clamped to `low..=high`. + #[must_use] + pub fn clamp(self, low: impl Into, high: impl Into) -> Expr { + self.max(low).min(high) + } + + /// 0 below `from`, 1 above `to`, and a smooth step between. + #[must_use] + pub fn smoothstep(self, from: impl Into, to: impl Into) -> Expr { + let (from, to) = (from.into(), to.into()); + let t = ((self - from.clone()) / (to - from)).clamp(0.0, 1.0); + t.clone() * t.clone() * (3.0 - 2.0 * t) + } + + /// Whether a text field equals `text`. + #[must_use] + pub fn is(self, text: &str) -> Expr { + node(Node::Is(self, text.into())) + } + + /// Whether a text field holds `text`, ignoring case. Only a [`Query`](crate::Query) reads it, as + /// the GPU holds no texts. + #[must_use] + pub fn contains(self, text: &str) -> Expr { + node(Node::Contains(self, text.into())) + } + + /// Reads this expression's fields from `table` of dataset `data`, joined by row id. + #[must_use] + pub fn of(self, data: impl Into, table: impl Into) -> Expr { + let of = (data.into(), table.into()); + self.map_fields(&|f| FieldRef { of: Some(of.clone()), ..f.clone() }) + } + + /// Reads sampled fields at the last frame at or before the shown coordinate, without + /// interpolating to the next. + #[must_use] + pub fn step(self) -> Expr { + self.map_fields(&|f| FieldRef { step: true, ..f.clone() }) + } + + /// The value through `colormap`; the domain fits the values shown unless set by + /// [`Mapped::domain`]. + pub fn colormap(self, colormap: impl Into) -> Mapped { + Mapped(node(Node::Colormap { input: self, colormap: colormap.into(), domain: Domain::Fit })) + } + + /// The value mapped linearly onto `range`, clamped; the domain fits the values shown unless set + /// by [`Mapped::domain`]. + pub fn scale(self, range: RangeInclusive) -> Mapped { + let range = [*range.start(), *range.end()]; + Mapped(node(Node::Scale { input: self, domain: Domain::Fit, range })) + } + + pub(crate) fn component(name: impl Into, component: u8) -> Expr { + node(Node::Field(FieldRef { name: name.into(), of: None, step: false, component: Some(component) })) + } + + fn map_fields(&self, f: &impl Fn(&FieldRef) -> FieldRef) -> Expr { + match &*self.0 { + Node::Field(field) => node(Node::Field(f(field))), + Node::Unary(op, a) => node(Node::Unary(*op, a.map_fields(f))), + Node::Binary(op, a, b) => node(Node::Binary(*op, a.map_fields(f), b.map_fields(f))), + Node::When(c, a, b) => node(Node::When(c.map_fields(f), a.map_fields(f), b.map_fields(f))), + Node::Is(a, text) => node(Node::Is(a.map_fields(f), text.clone())), + Node::Contains(a, text) => node(Node::Contains(a.map_fields(f), text.clone())), + Node::Scale { input, domain, range } => { + node(Node::Scale { input: input.map_fields(f), domain: *domain, range: *range }) + } + Node::Colormap { input, colormap, domain } => { + node(Node::Colormap { input: input.map_fields(f), colormap: colormap.clone(), domain: *domain }) + } + Node::Number(_) | Node::Bool(_) | Node::Color(_) | Node::Missing | Node::State(_) => self.clone(), + } + } + + /// Calls `f` with every field the expression reads. + pub(crate) fn for_each_field<'e>(&'e self, f: &mut impl FnMut(&'e FieldRef)) { + match &*self.0 { + Node::Field(field) => f(field), + Node::Unary(_, a) + | Node::Is(a, _) + | Node::Contains(a, _) + | Node::Scale { input: a, .. } + | Node::Colormap { input: a, .. } => a.for_each_field(f), + Node::Binary(_, a, b) => { + a.for_each_field(f); + b.for_each_field(f); + } + Node::When(c, a, b) => { + c.for_each_field(f); + a.for_each_field(f); + b.for_each_field(f); + } + Node::Number(_) | Node::Bool(_) | Node::Color(_) | Node::Missing | Node::State(_) => {} + } + } + + /// Whether a domain fits the values of every row: each row's value then reads them all. + pub(crate) fn fits(&self) -> bool { + match &*self.0 { + Node::Scale { domain: Domain::Fit, .. } | Node::Colormap { domain: Domain::Fit, .. } => true, + Node::Unary(_, a) + | Node::Is(a, _) + | Node::Contains(a, _) + | Node::Scale { input: a, .. } + | Node::Colormap { input: a, .. } => a.fits(), + Node::Binary(_, a, b) => a.fits() || b.fits(), + Node::When(c, a, b) => c.fits() || a.fits() || b.fits(), + Node::Number(_) | Node::Bool(_) | Node::Color(_) | Node::Missing | Node::Field(_) | Node::State(_) => false, + } + } + + /// The field's name, when the expression is a field of its own table read as it is. + pub(crate) fn field_name(&self) -> Option<&Name> { + match &*self.0 { + Node::Field(f) if f.of.is_none() && f.component.is_none() => Some(&f.name), + _ => None, + } + } + + /// The first colormap a color maps through, and its domain when set: what a legend shows. A + /// conditional's general case, its `otherwise`, comes before the cases it makes exceptions for. + pub(crate) fn colormap_of(&self) -> Option<(&Colormap, Option<[f64; 2]>)> { + match &*self.0 { + Node::Colormap { colormap, domain, .. } => { + Some((colormap, if let Domain::Fixed(domain) = domain { Some(*domain) } else { None })) + } + Node::Unary(_, a) | Node::Is(a, _) | Node::Contains(a, _) => a.colormap_of(), + Node::Binary(_, a, b) => a.colormap_of().or_else(|| b.colormap_of()), + Node::When(c, a, b) => b.colormap_of().or_else(|| a.colormap_of()).or_else(|| c.colormap_of()), + Node::Scale { input, .. } => input.colormap_of(), + Node::Number(_) | Node::Bool(_) | Node::Color(_) | Node::Missing | Node::Field(_) | Node::State(_) => None, + } + } +} + +/// A value mapped through a colormap or onto a range, whose domain can be set. +#[derive(Clone, PartialEq, Debug)] +pub struct Mapped(Expr); + +impl Mapped { + /// The input values that map to the ends of the range or colormap. + #[must_use] + pub fn domain(self, domain: RangeInclusive) -> Mapped { + let fixed = Domain::Fixed([*domain.start(), *domain.end()]); + Mapped(match &*self.0.0 { + Node::Colormap { input, colormap, .. } => { + node(Node::Colormap { input: input.clone(), colormap: colormap.clone(), domain: fixed }) + } + Node::Scale { input, range, .. } => { + node(Node::Scale { input: input.clone(), domain: fixed, range: *range }) + } + _ => unreachable!("a mapped value is a colormap or a scale"), + }) + } +} + +impl From for Expr { + fn from(mapped: Mapped) -> Expr { + mapped.0 + } +} + +/// The open cases of a [`when`]. +pub struct When { + cases: Vec<(Expr, Expr)>, + condition: Expr, +} + +/// The cases of a [`when`], waiting for another case or the value otherwise. +pub struct Then { + cases: Vec<(Expr, Expr)>, +} + +impl When { + /// The value where the condition holds. + pub fn then(mut self, value: impl Into) -> Then { + self.cases.push((self.condition, value.into())); + Then { cases: self.cases } + } +} + +impl Then { + /// Another case, tried when the earlier ones do not hold. + pub fn when(self, condition: impl Into) -> When { + When { cases: self.cases, condition: condition.into() } + } + + /// The value where no case holds. + pub fn otherwise(self, value: impl Into) -> Expr { + self.cases.into_iter().rev().fold(value.into(), |otherwise, (c, v)| node(Node::When(c, v, otherwise))) + } +} + +/// A size: CSS pixels, or position units with [`units`], kept within a range of CSS pixels. +#[derive(Clone, PartialEq, Debug)] +pub struct Size { + pub(crate) expr: Expr, + pub(crate) units: bool, + /// The CSS pixels it keeps within, at any zoom. + pub(crate) px: [f32; 2], +} + +impl Size { + /// Any number of CSS pixels. + pub(crate) const ANY: [f32; 2] = [0.0, f32::INFINITY]; + + /// Keeps at least `px` CSS pixels however far the view zooms out: `units(field("r")).at_least(2.0)` + /// grows with the map and never vanishes. A marker keeps its proportions, its larger side held. + #[must_use] + pub fn at_least(mut self, px: f32) -> Size { + self.px[0] = px.max(0.0); + self + } + + /// Keeps at most `px` CSS pixels however far the view zooms in. + #[must_use] + pub fn at_most(mut self, px: f32) -> Size { + self.px[1] = px.max(0.0); + self + } +} + +impl> From for Size { + fn from(value: T) -> Size { + Size { expr: value.into(), units: false, px: Size::ANY } + } +} + +impl From<&str> for Expr { + fn from(name: &str) -> Expr { + field(name) + } +} + +impl From for Expr { + fn from(name: String) -> Expr { + field(name) + } +} + +impl From<&Name> for Expr { + fn from(name: &Name) -> Expr { + field(name) + } +} + +impl From for Expr { + fn from(value: f64) -> Expr { + node(Node::Number(value)) + } +} + +impl From for Expr { + fn from(value: f32) -> Expr { + node(Node::Number(f64::from(value))) + } +} + +impl From for Expr { + fn from(value: i32) -> Expr { + node(Node::Number(f64::from(value))) + } +} + +impl From for Expr { + fn from(value: bool) -> Expr { + node(Node::Bool(value)) + } +} + +impl From for Expr { + fn from(value: Color) -> Expr { + node(Node::Color(value)) + } +} + +impl From<&Expr> for Expr { + fn from(value: &Expr) -> Expr { + value.clone() + } +} + +macro_rules! operators { + ($($trait:ident $method:ident $op:ident),*) => {$( + impl> $trait for Expr { + type Output = Expr; + + fn $method(self, other: R) -> Expr { + node(Node::Binary(Binary::$op, self, other.into())) + } + } + + impl $trait for f64 { + type Output = Expr; + + fn $method(self, other: Expr) -> Expr { + node(Node::Binary(Binary::$op, Expr::from(self), other)) + } + } + )*}; +} + +operators!(Add add Add, Sub sub Sub, Mul mul Mul, Div div Div, Rem rem Rem, BitAnd bitand And, BitOr bitor Or); + +impl Neg for Expr { + type Output = Expr; + + fn neg(self) -> Expr { + node(Node::Unary(Unary::Neg, self)) + } +} + +impl Not for Expr { + type Output = Expr; + + fn not(self) -> Expr { + node(Node::Unary(Unary::Not, self)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn when_folds_right_to_left() { + let e = when(selected()).then(1.0).when(hovered()).then(2.0).otherwise(3.0); + let Node::When(c, a, rest) = &*e.0 else { panic!("a when") }; + assert_eq!(c, &selected()); + assert_eq!(a, &Expr::from(1.0)); + assert!(matches!(&*rest.0, Node::When(..))); + } + + #[test] + fn domain_applies_to_the_mapping_whatever_the_order() { + let a: Expr = field("vm").colormap(Colormap::BALANCE).domain(0.9..=1.1).into(); + let Node::Colormap { domain, .. } = &*a.0 else { panic!("a colormap") }; + assert_eq!(*domain, Domain::Fixed([0.9, 1.1])); + } + + #[test] + fn of_reaches_every_field() { + let e = (field("a") + field("b")).of("weather", "Station"); + let Node::Binary(_, a, b) = &*e.0 else { panic!("a sum") }; + for side in [a, b] { + let Node::Field(f) = &*side.0 else { panic!("a field") }; + assert_eq!(f.of, Some(("weather".into(), "Station".into()))); + } + } +} diff --git a/crates/latkit/src/expr/ramp.rs b/crates/latkit/src/expr/ramp.rs new file mode 100644 index 00000000..c416be0f --- /dev/null +++ b/crates/latkit/src/expr/ramp.rs @@ -0,0 +1,142 @@ +//! A colormap's 256 texels from its stops, made one way for the catalog the build bakes and for the +//! maps made at run time: blended in OKLab, so lightness runs evenly; wrapping when cyclic; a stop a +//! texel in turn when categorical. Free of the crate, so the build script includes it as it is. + +/// How a ramp spans its stops. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub(crate) enum Spread { + /// From the first stop to the last. + Continuous, + /// Around a circle: past the last stop, back to the first. + Cyclic, + /// A stop's color for each texel in turn. + Categorical, +} + +/// The 256 texels through `stops`, each a place from 0 to 1, ascending, and a straight sRGB color +/// from 0 to 1. A stop without a place sits evenly between its neighbors' places, as in a CSS +/// gradient: the first at 0, the last at 1, or a turn after the first when cyclic. A categorical +/// ramp's texel `i` takes stop `i` modulo their count. +pub(crate) fn texels(spread: Spread, stops: &[(Option, [f32; 4])]) -> [[u8; 4]; 256] { + assert!(!stops.is_empty(), "a ramp has a stop"); + if spread == Spread::Categorical || stops.len() == 1 { + return std::array::from_fn(|t| bytes(stops[t % stops.len()].1)); + } + let cyclic = spread == Spread::Cyclic; + let places = places(stops.iter().map(|s| s.0), cyclic); + let lab: Vec<(f32, [f32; 4])> = places.into_iter().zip(stops.iter().map(|s| oklab(s.1))).collect(); + std::array::from_fn(|t| { + let x = if cyclic { t as f32 / 256.0 } else { t as f32 / 255.0 }; + bytes(srgb(blend(&lab, x, cyclic))) + }) +} + +/// Each stop's place, filled in evenly between those given. +fn places(given: impl Iterator>, cyclic: bool) -> Vec { + let mut at: Vec> = given.collect(); + let n = at.len(); + let first = *at[0].get_or_insert(0.0); + if cyclic { + at.push(Some(first + 1.0)); + } else { + at[n - 1].get_or_insert(1.0); + } + let known: Vec<(usize, f32)> = at.iter().enumerate().filter_map(|(i, p)| Some((i, (*p)?))).collect(); + let mut places = vec![0.0; at.len()]; + for pair in known.windows(2) { + let ((i, from), (j, to)) = (pair[0], pair[1]); + for (k, place) in places.iter_mut().enumerate().take(j + 1).skip(i) { + *place = from + (to - from) * (k - i) as f32 / (j - i) as f32; + } + } + places.truncate(n); + places +} + +/// The OKLab color at `x` between the stops around it. +fn blend(stops: &[(f32, [f32; 4])], x: f32, cyclic: bool) -> [f32; 4] { + let n = stops.len(); + let (first, last) = (stops[0], stops[n - 1]); + let (a, b) = match stops.partition_point(|s| s.0 <= x) { + // Before the first stop: from the last a turn back, when cyclic. + 0 if cyclic => ((last.0 - 1.0, last.1), first), + 0 => (first, first), + // Past the last stop: on to the first a turn on, when cyclic. + i if i == n && cyclic => (last, (first.0 + 1.0, first.1)), + i if i == n => (last, last), + i => (stops[i - 1], stops[i]), + }; + let w = if b.0 > a.0 { ((x - a.0) / (b.0 - a.0)).clamp(0.0, 1.0) } else { 0.0 }; + std::array::from_fn(|c| a.1[c] + (b.1[c] - a.1[c]) * w) +} + +fn bytes(color: [f32; 4]) -> [u8; 4] { + color.map(|c| (c.clamp(0.0, 1.0) * 255.0).round() as u8) +} + +fn linear(c: f32) -> f32 { + if c <= 0.04045 { c / 12.92 } else { ((c + 0.055) / 1.055).powf(2.4) } +} + +fn gamma(c: f32) -> f32 { + if c <= 0.003_130_8 { c * 12.92 } else { 1.055 * c.max(0.0).powf(1.0 / 2.4) - 0.055 } +} + +/// A straight sRGB color in OKLab, its alpha kept. +fn oklab([r, g, b, a]: [f32; 4]) -> [f32; 4] { + let [r, g, b] = [r, g, b].map(linear); + let l = (0.412_221_47 * r + 0.536_332_55 * g + 0.051_445_995 * b).cbrt(); + let m = (0.211_903_5 * r + 0.680_699_5 * g + 0.107_396_96 * b).cbrt(); + let s = (0.088_302_46 * r + 0.281_718_85 * g + 0.629_978_7 * b).cbrt(); + [ + 0.210_454_26 * l + 0.793_617_8 * m - 0.004_072_047 * s, + 1.977_998_5 * l - 2.428_592_2 * m + 0.450_593_7 * s, + 0.025_904_037 * l + 0.782_771_77 * m - 0.808_675_77 * s, + a, + ] +} + +/// An OKLab color in straight sRGB, its alpha kept. +fn srgb([l, a, b, alpha]: [f32; 4]) -> [f32; 4] { + let l_ = (l + 0.396_337_78 * a + 0.215_803_76 * b).powi(3); + let m_ = (l - 0.105_561_346 * a - 0.063_854_17 * b).powi(3); + let s_ = (l - 0.089_484_18 * a - 1.291_485_5 * b).powi(3); + let [r, g, b] = [ + 4.076_741_7 * l_ - 3.307_711_6 * m_ + 0.230_969_94 * s_, + -1.268_438 * l_ + 2.609_757_4 * m_ - 0.341_319_38 * s_, + -0.004_196_086_3 * l_ - 0.703_418_6 * m_ + 1.707_614_7 * s_, + ] + .map(gamma); + [r, g, b, alpha] +} + +#[cfg(test)] +mod tests { + use super::*; + + const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0]; + const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0]; + + #[test] + fn stops_land_on_their_texels_and_blend_in_oklab() { + let ramp = texels(Spread::Continuous, &[(None, BLACK), (None, WHITE)]); + assert_eq!((ramp[0], ramp[255]), ([0, 0, 0, 255], [255, 255, 255, 255])); + // OKLab's half lightness is a darker byte than sRGB's middle: about 100, not 128. + assert!((95..105).contains(&ramp[128][0]), "{:?}", ramp[128]); + let red = [1.0, 0.0, 0.0, 1.0]; + let placed = texels(Spread::Continuous, &[(None, BLACK), (Some(64.0 / 255.0), red), (None, WHITE)]); + assert_eq!(placed[64], [255, 0, 0, 255], "a placed stop lands on its texel"); + assert_eq!(placed[0], [0, 0, 0, 255]); + } + + #[test] + fn cyclic_ramps_wrap_and_categories_repeat() { + let cyclic = texels(Spread::Cyclic, &[(None, BLACK), (None, WHITE)]); + assert_eq!((cyclic[0], cyclic[128]), ([0, 0, 0, 255], [255, 255, 255, 255])); + assert!(cyclic[255][0] < 20, "a cyclic ramp returns to its first stop: {:?}", cyclic[255]); + assert_eq!(places([None, Some(0.5), None, None].into_iter(), false), [0.0, 0.5, 0.75, 1.0]); + assert_eq!(places([None, None].into_iter(), true), [0.0, 0.5]); + let categories = texels(Spread::Categorical, &[(None, BLACK), (None, WHITE)]); + assert_eq!(categories[..3], [[0, 0, 0, 255], [255, 255, 255, 255], [0, 0, 0, 255]]); + } +} diff --git a/crates/latkit/src/geo/earcut.rs b/crates/latkit/src/geo/earcut.rs new file mode 100644 index 00000000..a0f3707d --- /dev/null +++ b/crates/latkit/src/geo/earcut.rs @@ -0,0 +1,749 @@ +//! Ear clipping: a polygon with holes cut into triangles, after Mapbox's earcut 3.2. Holes join the +//! outer ring through bridges; ears are clipped from a doubly linked ring, found by z-order hashing +//! on large polygons; where none clips, the ring is filtered while that removes points, cured once +//! of local self-intersections, then split in two. + +/// No node. +const NIL: u32 = u32::MAX; + +#[derive(Clone, Copy)] +struct Node { + /// The vertex index. + i: u32, + x: f64, + y: f64, + prev: u32, + next: u32, + /// Z-order of the vertex, and its neighbors in z-order. + z: u32, + prev_z: u32, + next_z: u32, + /// Whether the vertex is a lone hole point, which may stay in the ring. + steiner: bool, +} + +struct Rings<'a> { + nodes: Vec, + points: &'a [[f64; 2]], + triangles: Vec<[u32; 3]>, + /// Whether the last filter removed a point. + filtered: bool, +} + +/// The triangles of the polygon whose points are `points`: the outer ring first, then each hole from +/// where `holes` starts it. Each triangle is three indices into `points`. +pub(crate) fn earcut(points: &[[f64; 2]], holes: &[usize]) -> Vec<[u32; 3]> { + let nodes = Vec::with_capacity(points.len() * 3 / 2); + let mut rings = Rings { nodes, points, triangles: Vec::new(), filtered: false }; + let outer_end = holes.first().copied().unwrap_or(points.len()); + let mut outer = rings.linked(0, outer_end, true); + if outer == NIL || rings.n(outer).next == rings.n(outer).prev { + return rings.triangles; + } + if !holes.is_empty() { + outer = rings.eliminate_holes(holes, outer); + } + // Large polygons find ears through z-order hashing. + let (mut min, mut size) = ([0.0; 2], 0.0); + if points.len() > 80 { + let mut max = [f64::NEG_INFINITY; 2]; + min = [f64::INFINITY; 2]; + for p in &points[..outer_end] { + for k in 0..2 { + min[k] = min[k].min(p[k]); + max[k] = max[k].max(p[k]); + } + } + let span = (max[0] - min[0]).max(max[1] - min[1]); + size = if span > 0.0 { 32767.0 / span } else { 0.0 }; + } + rings.clip(outer, min, size); + rings.triangles +} + +impl Rings<'_> { + fn n(&self, i: u32) -> &Node { + &self.nodes[i as usize] + } + + fn m(&mut self, i: u32) -> &mut Node { + &mut self.nodes[i as usize] + } + + fn xy(&self, i: u32) -> (f64, f64) { + let n = self.n(i); + (n.x, n.y) + } + + /// A circular list of points `start..end`, wound as `clockwise` asks. + fn linked(&mut self, start: usize, end: usize, clockwise: bool) -> u32 { + let mut last = NIL; + if clockwise == (signed_area(&self.points[start..end]) > 0.0) { + for i in start..end { + last = self.insert(i as u32, last); + } + } else { + for i in (start..end).rev() { + last = self.insert(i as u32, last); + } + } + if last != NIL && self.equals(last, self.n(last).next) { + let next = self.n(last).next; + self.remove(last); + last = next; + } + last + } + + fn insert(&mut self, i: u32, last: u32) -> u32 { + let [x, y] = self.points[i as usize]; + let p = self.nodes.len() as u32; + let mut node = Node { i, x, y, prev: p, next: p, z: 0, prev_z: NIL, next_z: NIL, steiner: false }; + if last == NIL { + self.nodes.push(node); + } else { + let after = self.n(last).next; + node.next = after; + node.prev = last; + self.nodes.push(node); + self.m(after).prev = p; + self.m(last).next = p; + } + p + } + + fn remove(&mut self, p: u32) { + let Node { prev, next, prev_z, next_z, .. } = *self.n(p); + self.m(next).prev = prev; + self.m(prev).next = next; + if prev_z != NIL { + self.m(prev_z).next_z = next_z; + } + if next_z != NIL { + self.m(next_z).prev_z = prev_z; + } + } + + fn equals(&self, a: u32, b: u32) -> bool { + self.xy(a) == self.xy(b) + } + + /// Twice the signed area of the triangle `p q r`: negative turning one way. + fn area(&self, p: u32, q: u32, r: u32) -> f64 { + let ((px, py), (qx, qy), (rx, ry)) = (self.xy(p), self.xy(q), self.xy(r)); + (qy - py) * (rx - qx) - (qx - px) * (ry - qy) + } + + /// Removes repeated points and straight runs: around the whole ring from `start` until none is + /// left when `end` is `NIL`; else from `start` to `end`, healing the cut between them. Answers a + /// point still in the ring. + fn filter(&mut self, start: u32, end: u32) -> u32 { + if start == NIL { + return start; + } + let whole = end == NIL || end == start; + let mut end = if end == NIL { start } else { end }; + let mut p = start; + loop { + let mut again = false; + let (prev, next) = (self.n(p).prev, self.n(p).next); + if p != next && !self.n(p).steiner && (self.equals(p, next) || self.area(prev, p, next) == 0.0) { + if whole || p == end { + end = prev; + } + self.filtered = true; + self.remove(p); + p = prev; + again = true; + } else if whole || p != end { + p = next; + again = !whole; + } + if !again && p == end { + return end; + } + } + } + + /// Clips ears from the ring at `ear`. Where none clips, filters while that removes points, cures + /// local self-intersections once, then splits the ring in two. + fn clip(&mut self, mut ear: u32, min: [f64; 2], size: f64) { + if ear == NIL { + return; + } + if size > 0.0 { + self.index(ear, min, size); + } + let (mut stop, mut cured) = (ear, false); + while self.n(ear).prev != self.n(ear).next { + let (prev, next) = (self.n(ear).prev, self.n(ear).next); + let is_ear = if size > 0.0 { self.is_ear_hashed(ear, min, size) } else { self.is_ear(ear) }; + if is_ear { + self.triangles.push([self.n(prev).i, self.n(ear).i, self.n(next).i]); + self.remove(ear); + ear = next; + stop = next; + continue; + } + ear = next; + if ear == stop { + self.filtered = false; + ear = self.filter(ear, NIL); + if self.filtered { + stop = ear; + continue; + } + if !cured { + ear = self.cure(ear); + stop = ear; + cured = true; + continue; + } + self.split(ear, min, size); + break; + } + } + } + + fn is_ear(&self, ear: u32) -> bool { + let (a, b, c) = (self.n(ear).prev, ear, self.n(ear).next); + if self.area(a, b, c) >= 0.0 { + return false; + } + let ((ax, ay), (bx, by), (cx, cy)) = (self.xy(a), self.xy(b), self.xy(c)); + let (x0, y0, x1, y1) = (ax.min(bx).min(cx), ay.min(by).min(cy), ax.max(bx).max(cx), ay.max(by).max(cy)); + let mut p = self.n(c).next; + while p != a { + let n = self.n(p); + if n.x >= x0 + && n.x <= x1 + && n.y >= y0 + && n.y <= y1 + && inside_except_first([ax, ay], [bx, by], [cx, cy], [n.x, n.y]) + && self.area(n.prev, p, n.next) >= 0.0 + { + return false; + } + p = n.next; + } + true + } + + fn is_ear_hashed(&self, ear: u32, min: [f64; 2], size: f64) -> bool { + let (a, b, c) = (self.n(ear).prev, ear, self.n(ear).next); + if self.area(a, b, c) >= 0.0 { + return false; + } + let ((ax, ay), (bx, by), (cx, cy)) = (self.xy(a), self.xy(b), self.xy(c)); + let (x0, y0, x1, y1) = (ax.min(bx).min(cx), ay.min(by).min(cy), ax.max(bx).max(cx), ay.max(by).max(cy)); + let (low, high) = (z_order(x0, y0, min, size), z_order(x1, y1, min, size)); + let blocks = |p: u32| { + let n = self.n(p); + n.x >= x0 + && n.x <= x1 + && n.y >= y0 + && n.y <= y1 + && p != a + && p != c + && inside_except_first([ax, ay], [bx, by], [cx, cy], [n.x, n.y]) + && self.area(n.prev, p, n.next) >= 0.0 + }; + let (mut p, mut n) = (self.n(ear).prev_z, self.n(ear).next_z); + while p != NIL && self.n(p).z >= low && n != NIL && self.n(n).z <= high { + if blocks(p) { + return false; + } + p = self.n(p).prev_z; + if blocks(n) { + return false; + } + n = self.n(n).next_z; + } + while p != NIL && self.n(p).z >= low { + if blocks(p) { + return false; + } + p = self.n(p).prev_z; + } + while n != NIL && self.n(n).z <= high { + if blocks(n) { + return false; + } + n = self.n(n).next_z; + } + true + } + + /// Clips the triangles of local self-intersections, returning the ring left. + fn cure(&mut self, start: u32) -> u32 { + let (mut p, mut start, mut cured) = (start, start, false); + loop { + let a = self.n(p).prev; + let next = self.n(p).next; + let b = self.n(next).next; + if self.crosses(a, p, next, b) && self.locally_inside(a, b) && self.locally_inside(b, a) { + self.triangles.push([self.n(a).i, self.n(p).i, self.n(b).i]); + self.remove(p); + self.remove(next); + p = b; + start = b; + cured = true; + } + p = self.n(p).next; + if p == start { + break; + } + } + if cured { self.filter(p, NIL) } else { p } + } + + /// Splits the ring in two along a valid diagonal, and clips each. + fn split(&mut self, start: u32, min: [f64; 2], size: f64) { + let mut a = start; + loop { + let mut b = self.n(self.n(a).next).next; + while b != self.n(a).prev { + if self.n(a).i != self.n(b).i && self.valid_diagonal(a, b) { + let c = self.split_polygon(a, b); + let a = self.filter(a, self.n(a).next); + let c = self.filter(c, self.n(c).next); + self.clip(a, min, size); + self.clip(c, min, size); + return; + } + b = self.n(b).next; + } + a = self.n(a).next; + if a == start { + break; + } + } + } + + /// Joins every hole to the outer ring, leftmost first. + fn eliminate_holes(&mut self, holes: &[usize], mut outer: u32) -> u32 { + let mut queue = Vec::with_capacity(holes.len()); + for (k, &start) in holes.iter().enumerate() { + let end = holes.get(k + 1).copied().unwrap_or(self.points.len()); + if end <= start { + continue; + } + let list = self.linked(start, end, false); + if list == NIL { + continue; + } + if list == self.n(list).next { + self.m(list).steiner = true; + } + queue.push(self.leftmost(list)); + } + // Holes whose leftmost points meet go around that point, so each bridges to where they meet. + let slope = |p: u32| { + let (n, next) = (self.n(p), self.n(self.n(p).next)); + (next.y - n.y) / (next.x - n.x) + }; + queue.sort_by(|&a, &b| { + let (na, nb) = (self.n(a), self.n(b)); + na.x.total_cmp(&nb.x).then(na.y.total_cmp(&nb.y)).then_with(|| slope(a).total_cmp(&slope(b))) + }); + for hole in queue { + outer = self.eliminate_hole(hole, outer); + } + // Points made collinear or repeated across the merged ring go before clipping. + self.filter(outer, NIL) + } + + fn eliminate_hole(&mut self, hole: u32, outer: u32) -> u32 { + let Some(bridge) = self.hole_bridge(hole, outer) else { return outer }; + let reverse = self.split_polygon(bridge, hole); + self.filter(reverse, self.n(reverse).next); + self.filter(bridge, self.n(bridge).next) + } + + /// The outer ring's point a hole joins it at: seen from the hole's leftmost point, nothing between. + fn hole_bridge(&self, hole: u32, outer: u32) -> Option { + let (hx, hy) = self.xy(hole); + let mut qx = f64::NEG_INFINITY; + let mut m = NIL; + let mut p = outer; + // A hole touching the outer ring at a point joins it there. + if self.equals(hole, p) { + return Some(p); + } + loop { + let (px, py) = self.xy(p); + let next = self.n(p).next; + let (nx, ny) = self.xy(next); + if self.equals(hole, next) { + return Some(next); + } + if hy <= py && hy >= ny && ny != py { + let x = px + (hy - py) * (nx - px) / (ny - py); + if x <= hx && x > qx { + qx = x; + m = if px < nx { p } else { next }; + if x == hx { + return Some(m); + } + } + } + p = next; + if p == outer { + break; + } + } + if m == NIL { + return None; + } + let stop = m; + let (mx, my) = self.xy(m); + let mut tan_min = f64::INFINITY; + p = m; + loop { + let (px, py) = self.xy(p); + let (ax, cx) = if hy < my { (hx, qx) } else { (qx, hx) }; + if hx >= px && px >= mx && hx != px && inside_triangle([ax, hy], [mx, my], [cx, hy], [px, py]) { + let tan = (hy - py).abs() / (hx - px); + let (bx, _) = self.xy(m); + // The hole's point on `p`'s level edge, a T touch: a bridge along that edge is valid, + // though not locally inside. + let (nx, ny) = self.xy(self.n(p).next); + let along = py == hy && ny == hy && nx > hx; + if (self.locally_inside(p, hole) || along) + && (tan < tan_min || (tan == tan_min && (px > bx || (px == bx && self.sector_contains(m, p))))) + { + m = p; + tan_min = tan; + } + } + p = self.n(p).next; + if p == stop { + break; + } + } + Some(m) + } + + fn sector_contains(&self, m: u32, p: u32) -> bool { + self.area(self.n(m).prev, m, self.n(p).prev) < 0.0 && self.area(self.n(p).next, m, self.n(m).next) < 0.0 + } + + fn leftmost(&self, start: u32) -> u32 { + let (mut p, mut left) = (start, start); + loop { + let (n, l) = (self.n(p), self.n(left)); + if n.x < l.x || (n.x == l.x && n.y < l.y) { + left = p; + } + p = n.next; + if p == start { + break; + } + } + left + } + + /// Links the ring in z-order, sorted. + fn index(&mut self, start: u32, min: [f64; 2], size: f64) { + let mut p = start; + loop { + let n = *self.n(p); + self.m(p).z = z_order(n.x, n.y, min, size); + self.m(p).prev_z = n.prev; + self.m(p).next_z = n.next; + p = n.next; + if p == start { + break; + } + } + let last = self.n(p).prev_z; + self.m(last).next_z = NIL; + self.m(p).prev_z = NIL; + self.sort(p); + } + + /// Merge-sorts the z-order list from `list`. + fn sort(&mut self, mut list: u32) { + let mut in_size = 1; + loop { + let mut p = list; + list = NIL; + let mut tail = NIL; + let mut merges = 0; + while p != NIL { + merges += 1; + let mut q = p; + let mut p_size = 0; + for _ in 0..in_size { + p_size += 1; + q = self.n(q).next_z; + if q == NIL { + break; + } + } + let mut q_size = in_size; + while p_size > 0 || (q_size > 0 && q != NIL) { + let e; + if p_size != 0 && (q_size == 0 || q == NIL || self.n(p).z <= self.n(q).z) { + e = p; + p = self.n(p).next_z; + p_size -= 1; + } else { + e = q; + q = self.n(q).next_z; + q_size -= 1; + } + if tail == NIL { + list = e; + } else { + self.m(tail).next_z = e; + } + self.m(e).prev_z = tail; + tail = e; + } + p = q; + } + if tail != NIL { + self.m(tail).next_z = NIL; + } + in_size *= 2; + if merges <= 1 { + break; + } + } + } + + /// Whether diagonal `a b` lies inside the polygon: locally visible from both ends, crossing no + /// edge, its middle inside, and making no opposite-facing sectors; or of no length between two + /// convex corners. + fn valid_diagonal(&self, a: u32, b: u32) -> bool { + let (na, nb) = (self.n(a), self.n(b)); + let zero_length = + self.equals(a, b) && self.area(na.prev, a, na.next) > 0.0 && self.area(nb.prev, b, nb.next) > 0.0; + self.n(na.next).i != nb.i + && (zero_length + || (self.locally_inside(a, b) + && self.locally_inside(b, a) + && (self.area(na.prev, a, nb.prev) != 0.0 || self.area(a, nb.prev, b) != 0.0))) + && !self.intersects_polygon(a, b) + && (zero_length || self.middle_inside(a, b)) + } + + /// Whether segments `p1 q1` and `p2 q2` cross, not counting a touch. + fn crosses(&self, p1: u32, q1: u32, p2: u32, q2: u32) -> bool { + let (o1, o2) = (sign(self.area(p1, q1, p2)), sign(self.area(p1, q1, q2))); + let (o3, o4) = (sign(self.area(p2, q2, p1)), sign(self.area(p2, q2, q1))); + o1 * o2 < 0 && o3 * o4 < 0 + } + + /// Whether segments `p1 q1` and `p2 q2` meet, touches included. + fn intersects(&self, p1: u32, q1: u32, p2: u32, q2: u32) -> bool { + let o1 = sign(self.area(p1, q1, p2)); + let o2 = sign(self.area(p1, q1, q2)); + let o3 = sign(self.area(p2, q2, p1)); + let o4 = sign(self.area(p2, q2, q1)); + self.crosses(p1, q1, p2, q2) + || (o1 == 0 && self.on_segment(p1, p2, q1)) + || (o2 == 0 && self.on_segment(p1, q2, q1)) + || (o3 == 0 && self.on_segment(p2, p1, q2)) + || (o4 == 0 && self.on_segment(p2, q1, q2)) + } + + /// Whether `q` lies within the box of segment `p r`, on which it lies. + fn on_segment(&self, p: u32, q: u32, r: u32) -> bool { + let ((px, py), (qx, qy), (rx, ry)) = (self.xy(p), self.xy(q), self.xy(r)); + qx <= px.max(rx) && qx >= px.min(rx) && qy <= py.max(ry) && qy >= py.min(ry) + } + + /// Whether diagonal `a b` meets an edge of the ring, other than those at its ends. + fn intersects_polygon(&self, a: u32, b: u32) -> bool { + let (ia, ib) = (self.n(a).i, self.n(b).i); + let ((ax, ay), (bx, by)) = (self.xy(a), self.xy(b)); + let (x0, x1, y0, y1) = (ax.min(bx), ax.max(bx), ay.min(by), ay.max(by)); + let mut p = a; + loop { + let next = self.n(p).next; + let ((px, py), (nx, ny)) = (self.xy(p), self.xy(next)); + // An edge beside the diagonal's box cannot meet it. + let apart = (px > x1 && nx > x1) || (px < x0 && nx < x0) || (py > y1 && ny > y1) || (py < y0 && ny < y0); + let (ip, inext) = (self.n(p).i, self.n(next).i); + if !apart && ip != ia && inext != ia && ip != ib && inext != ib && self.intersects(p, next, a, b) { + return true; + } + p = next; + if p == a { + return false; + } + } + } + + fn locally_inside(&self, a: u32, b: u32) -> bool { + let n = self.n(a); + if self.area(n.prev, a, n.next) < 0.0 { + self.area(a, b, n.next) >= 0.0 && self.area(a, n.prev, b) >= 0.0 + } else { + self.area(a, b, n.prev) < 0.0 || self.area(a, n.next, b) < 0.0 + } + } + + fn middle_inside(&self, a: u32, b: u32) -> bool { + let ((ax, ay), (bx, by)) = (self.xy(a), self.xy(b)); + let (px, py) = (f64::midpoint(ax, bx), f64::midpoint(ay, by)); + let mut inside = false; + let mut p = a; + loop { + let (x, y) = self.xy(p); + let next = self.n(p).next; + let (nx, ny) = self.xy(next); + if ((y > py) != (ny > py)) && ny != y && px < (nx - x) * (py - y) / (ny - y) + x { + inside = !inside; + } + p = next; + if p == a { + return inside; + } + } + } + + /// Splits the ring along the diagonal `a b` into two; returns the new copy of `b`. + fn split_polygon(&mut self, a: u32, b: u32) -> u32 { + let (na, nb) = (*self.n(a), *self.n(b)); + let a2 = self.nodes.len() as u32; + let b2 = a2 + 1; + let fresh = |n: Node| Node { prev: NIL, next: NIL, z: 0, prev_z: NIL, next_z: NIL, steiner: false, ..n }; + self.nodes.push(fresh(na)); + self.nodes.push(fresh(nb)); + let (an, bp) = (na.next, nb.prev); + self.m(a).next = b; + self.m(b).prev = a; + self.m(a2).next = an; + self.m(an).prev = a2; + self.m(b2).next = a2; + self.m(a2).prev = b2; + self.m(bp).next = b2; + self.m(b2).prev = bp; + b2 + } +} + +/// Twice the signed area of a ring, by the shoelace sum as earcut takes it. +fn signed_area(points: &[[f64; 2]]) -> f64 { + let Some(&last) = points.last() else { return 0.0 }; + let mut sum = 0.0; + let mut j = last; + for &p in points { + sum += (j[0] - p[0]) * (p[1] + j[1]); + j = p; + } + sum +} + +/// The z-order of point `(x, y)` in a box from `min` scaled by `size` to 15 bits a side. +fn z_order(x: f64, y: f64, min: [f64; 2], size: f64) -> u32 { + let spread = |v: f64| { + let mut v = (v * size) as u32 & 0x7fff; + v = (v | (v << 8)) & 0x00ff_00ff; + v = (v | (v << 4)) & 0x0f0f_0f0f; + v = (v | (v << 2)) & 0x3333_3333; + (v | (v << 1)) & 0x5555_5555 + }; + spread(x - min[0]) | (spread(y - min[1]) << 1) +} + +fn inside_triangle(a: [f64; 2], b: [f64; 2], c: [f64; 2], p: [f64; 2]) -> bool { + (c[0] - p[0]) * (a[1] - p[1]) >= (a[0] - p[0]) * (c[1] - p[1]) + && (a[0] - p[0]) * (b[1] - p[1]) >= (b[0] - p[0]) * (a[1] - p[1]) + && (b[0] - p[0]) * (c[1] - p[1]) >= (c[0] - p[0]) * (b[1] - p[1]) +} + +/// Whether `p` lies in the triangle, other than at its first corner: a point where a bridge doubled +/// that corner blocks no ear. +fn inside_except_first(a: [f64; 2], b: [f64; 2], c: [f64; 2], p: [f64; 2]) -> bool { + a != p && inside_triangle(a, b, c, p) +} + +fn sign(v: f64) -> i8 { + if v > 0.0 { + 1 + } else if v < 0.0 { + -1 + } else { + 0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Twice the area the triangles cover. + fn covered(points: &[[f64; 2]], triangles: &[[u32; 3]]) -> f64 { + triangles + .iter() + .map(|t| { + let [a, b, c] = t.map(|i| points[i as usize]); + ((b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1])).abs() + }) + .sum() + } + + #[test] + fn a_square_is_two_triangles() { + let square = [[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]]; + let triangles = earcut(&square, &[]); + assert_eq!(triangles.len(), 2); + assert!((covered(&square, &triangles) - 2.0).abs() < 1e-12); + } + + #[test] + fn holes_are_left_out() { + let mut points = vec![[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0]]; + points.extend([[2.0, 2.0], [2.0, 4.0], [4.0, 4.0], [4.0, 2.0]]); + points.extend([[6.0, 6.0], [6.0, 8.0], [8.0, 8.0], [8.0, 6.0]]); + let triangles = earcut(&points, &[4, 8]); + assert!((covered(&points, &triangles) - 2.0 * (100.0 - 8.0)).abs() < 1e-9, "{triangles:?}"); + } + + #[test] + fn holes_touching_the_ring_or_each_other_are_left_out() { + /// Holes, where each starts, and the area left. + type Case<'a> = (&'a [[f64; 2]], &'a [usize], f64); + let outer = [[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0]]; + let cases: [Case<'_>; 3] = [ + // A hole touching the outer ring at its corner. + (&[[0.0, 0.0], [3.0, 1.0], [1.0, 3.0]], &[4], 96.0), + // One touching its edge. + (&[[0.0, 5.0], [3.0, 4.0], [3.0, 6.0]], &[4], 97.0), + // Two meeting at their leftmost point. + (&[[5.0, 5.0], [7.0, 4.0], [7.0, 6.0], [5.0, 5.0], [7.0, 7.0], [6.0, 9.0]], &[4, 7], 95.0), + ]; + for (holes, starts, area) in cases { + let points = [&outer[..], holes].concat(); + let triangles = earcut(&points, starts); + assert!((covered(&points, &triangles) - 2.0 * area).abs() < 1e-9, "{holes:?}: {triangles:?}"); + } + } + + #[test] + fn large_rings_hash_their_ears() { + // A star of 200 points: concave everywhere, so ear finding matters. + let points: Vec<[f64; 2]> = (0..200) + .map(|k| { + let a = f64::from(k) / 200.0 * std::f64::consts::TAU; + let r = if k % 2 == 0 { 10.0 } else { 4.0 }; + [r * a.cos(), r * a.sin()] + }) + .collect(); + let triangles = earcut(&points, &[]); + assert_eq!(triangles.len(), 198); + let area = signed_area(&points).abs(); + assert!((covered(&points, &triangles) - area).abs() < 1e-6 * area); + } + + #[test] + fn degenerate_rings_answer_nothing() { + let none: Vec<[u32; 3]> = Vec::new(); + assert_eq!(earcut(&[[0.0, 0.0], [1.0, 1.0]], &[]), none); + assert_eq!(earcut(&[[0.0, 0.0], [1.0, 0.0], [2.0, 0.0]], &[]), none, "collinear"); + } +} diff --git a/crates/latkit/src/geo/geojson.rs b/crates/latkit/src/geo/geojson.rs new file mode 100644 index 00000000..11fa1b04 --- /dev/null +++ b/crates/latkit/src/geo/geojson.rs @@ -0,0 +1,379 @@ +//! GeoJSON as data: a feature collection's features become rows of three tables by what their +//! geometry is, `points`, `lines`, and `polygons`, each with its geometry as field `geometry` and its +//! properties as fields. + +use std::fmt; + +use serde::Deserialize; +use serde::de::{self, IgnoredAny, SeqAccess, Visitor}; +use serde_json::{Map, Value as Json}; + +use crate::data::{Data, Ids, Name, Patch, Table, Values}; +use crate::{Error, Result}; + +type Point = [f64; 2]; + +/// The features of GeoJSON `bytes`, gzip-compressed or not, as dataset `name`: a feature collection, +/// one feature, or a bare geometry. +/// +/// Points become rows of table `points`, a point field `geometry`; line strings rows of `lines`, a +/// field of parts; polygons rows of `polygons`, a field of polygons. A multi-point is a row per point, +/// and a geometry collection a row per member. Properties become fields: numbers, booleans, and texts, +/// any other value written as its JSON. Rows take their features' ids where every row of a table has +/// one and no two share it, and are numbered in order otherwise. +pub(crate) fn geojson(name: impl Into, bytes: &[u8]) -> Result { + let bytes = super::gunzipped(bytes)?; + let top: Top = serde_json::from_slice(&bytes).map_err(|e| Error::invalid(format!("not GeoJSON: {e}")))?; + let mut tables = [Rows::default(), Rows::default(), Rows::default()]; + let mut add = |feature: Feature| { + if let Some(geometry) = feature.geometry { + let properties = feature.properties.unwrap_or_default(); + geometry.into_rows(feature.id.as_ref(), &properties, &mut tables); + } + }; + match top.kind.as_str() { + "FeatureCollection" => top.features.unwrap_or_default().into_iter().for_each(&mut add), + "Feature" => add(Feature { id: top.id, geometry: top.geometry, properties: top.properties }), + _ => add(Feature { + id: None, + geometry: Some(Geometry { kind: top.kind, coordinates: top.coordinates, geometries: top.geometries }), + properties: None, + }), + } + let mut patch = Patch::new(); + for (rows, name) in tables.into_iter().zip(["points", "lines", "polygons"]) { + if let Some(table) = rows.table(name) { + patch = patch.replace(table); + } + } + let mut data = Data::new(name); + data.apply(patch)?; + Ok(data) +} + +/// The top of a document: a collection, a feature, or a geometry, as one struct of each's members. +#[derive(Deserialize)] +struct Top { + #[serde(rename = "type")] + kind: String, + features: Option>, + id: Option, + geometry: Option, + properties: Option>, + coordinates: Option, + geometries: Option>, +} + +#[derive(Deserialize)] +struct Feature { + id: Option, + geometry: Option, + properties: Option>, +} + +#[derive(Deserialize)] +struct Geometry { + #[serde(rename = "type")] + kind: String, + coordinates: Option, + geometries: Option>, +} + +/// Which table a geometry's rows go to. +const POINTS: usize = 0; +const LINES: usize = 1; +const POLYGONS: usize = 2; + +impl Geometry { + /// Adds this geometry's rows, with the feature's id and properties, to the table of each kind. + fn into_rows(self, id: Option<&Json>, properties: &Map, tables: &mut [Rows; 3]) { + let coordinates = self.coordinates.unwrap_or(Coordinates::Empty); + match (self.kind.as_str(), coordinates) { + ("Point", Coordinates::Position(p)) => tables[POINTS].push(id, properties, Shape::Point(p)), + ("MultiPoint", Coordinates::Line(points)) => { + for p in points { + tables[POINTS].push(id, properties, Shape::Point(p)); + } + } + ("LineString", Coordinates::Line(line)) => tables[LINES].push(id, properties, Shape::Parts(vec![line])), + ("MultiLineString", Coordinates::Rings(lines)) => tables[LINES].push(id, properties, Shape::Parts(lines)), + ("Polygon", Coordinates::Rings(rings)) => { + tables[POLYGONS].push(id, properties, Shape::Polygons(vec![rings])); + } + ("MultiPolygon", Coordinates::Polygons(polygons)) => { + tables[POLYGONS].push(id, properties, Shape::Polygons(polygons)); + } + ("GeometryCollection", _) => { + for member in self.geometries.unwrap_or_default() { + member.into_rows(id, properties, tables); + } + } + // A geometry without coordinates, or of a type GeoJSON does not have, adds no row. + _ => {} + } + } +} + +enum Shape { + Point(Point), + Parts(Vec>), + Polygons(Vec>>), +} + +/// One table's rows as they are read: each row's id, its properties, and its shape. +#[derive(Default)] +struct Rows { + ids: Vec>, + properties: Vec>, + shapes: Vec, +} + +impl Rows { + fn push(&mut self, id: Option<&Json>, properties: &Map, shape: Shape) { + self.ids.push(id.cloned()); + self.properties.push(properties.clone()); + self.shapes.push(shape); + } + + /// The rows as table `name`, or `None` without any. + fn table(self, name: &str) -> Option
{ + if self.shapes.is_empty() { + return None; + } + let count = self.shapes.len(); + let mut table = Table::new(name, ids(&self.ids).unwrap_or_else(|| Ids::count(count as u32))); + let geometry: Values = match &self.shapes[0] { + Shape::Point(_) => self + .shapes + .iter() + .map(|s| if let Shape::Point(p) = s { *p } else { [f64::NAN; 2] }) + .collect::>() + .into(), + Shape::Parts(_) => self + .shapes + .into_iter() + .map(|s| if let Shape::Parts(parts) = s { parts } else { Vec::new() }) + .collect::>() + .into(), + Shape::Polygons(_) => self + .shapes + .into_iter() + .map(|s| if let Shape::Polygons(polygons) = s { polygons } else { Vec::new() }) + .collect::>() + .into(), + }; + table = table.field("geometry", geometry); + let mut keys: Vec<&String> = Vec::new(); + for properties in &self.properties { + for key in properties.keys() { + if !keys.contains(&key) { + keys.push(key); + } + } + } + for key in keys { + // A property named like the geometry would replace it. + if key == "geometry" { + continue; + } + let values: Vec> = + self.properties.iter().map(|p| p.get(key.as_str()).filter(|v| !v.is_null())).collect(); + table = table.field(key.as_str(), property(&values)); + } + Some(table) + } +} + +/// The rows' ids: every one present, of one kind, and distinct; else `None`. +fn ids(ids: &[Option]) -> Option { + let mut seen = std::collections::HashSet::with_capacity(ids.len()); + if ids.iter().all(|id| id.as_ref().and_then(Json::as_u64).is_some_and(|n| seen.insert(n.to_string()))) { + return Some(Ids::from( + ids.iter().map(|id| id.as_ref().and_then(Json::as_u64).unwrap_or(0)).collect::>(), + )); + } + seen.clear(); + if ids.iter().all(|id| id.as_ref().and_then(Json::as_str).is_some_and(|t| seen.insert(t.to_owned()))) { + let texts: Vec<&str> = ids.iter().map(|id| id.as_ref().and_then(Json::as_str).unwrap_or("")).collect(); + return Some(Ids::from(texts)); + } + None +} + +/// A property's values as a field: numbers where every value present is one, booleans likewise, and +/// texts otherwise, any value not a text written as its JSON. +fn property(values: &[Option<&Json>]) -> Values { + let present = || values.iter().flatten(); + if present().all(|v| v.is_number()) { + return values.iter().map(|v| v.and_then(Json::as_f64)).collect::>().into(); + } + if present().all(|v| v.is_boolean()) { + return values.iter().map(|v| v.and_then(Json::as_bool)).collect::>().into(); + } + let texts: Vec> = values + .iter() + .map(|v| { + v.map(|v| match v { + Json::String(text) => text.clone(), + other => other.to_string(), + }) + }) + .collect(); + texts.into() +} + +/// Coordinates of any depth: a position, a list of them, lists of those, or polygons. Positions read +/// their longitude and latitude and skip any altitude. +enum Coordinates { + Number(f64), + Position(Point), + Line(Vec), + Rings(Vec>), + Polygons(Vec>>), + Empty, +} + +impl<'de> Deserialize<'de> for Coordinates { + fn deserialize>(deserializer: D) -> std::result::Result { + deserializer.deserialize_any(Depth) + } +} + +/// Reads coordinates of any depth: the first element of each array says how deep the rest are. +struct Depth; + +impl<'de> Visitor<'de> for Depth { + type Value = Coordinates; + + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("GeoJSON coordinates") + } + + fn visit_f64(self, v: f64) -> std::result::Result { + Ok(Coordinates::Number(v)) + } + + fn visit_i64(self, v: i64) -> std::result::Result { + Ok(Coordinates::Number(v as f64)) + } + + fn visit_u64(self, v: u64) -> std::result::Result { + Ok(Coordinates::Number(v as f64)) + } + + fn visit_seq>(self, mut seq: A) -> std::result::Result { + Ok(match seq.next_element::()? { + None => Coordinates::Empty, + Some(Coordinates::Number(x)) => { + let y = seq.next_element::()?.unwrap_or(f64::NAN); + while seq.next_element::()?.is_some() {} + Coordinates::Position([x, y]) + } + Some(Coordinates::Position(p)) => { + let mut line = vec![p]; + while let Some(Position(p)) = seq.next_element()? { + line.push(p); + } + Coordinates::Line(line) + } + Some(Coordinates::Line(first)) => { + let mut rings = vec![first]; + while let Some(ring) = seq.next_element::>()? { + rings.push(ring.into_iter().map(|p| p.0).collect()); + } + Coordinates::Rings(rings) + } + Some(Coordinates::Rings(first)) => { + let mut polygons = vec![first]; + while let Some(polygon) = seq.next_element::>>()? { + polygons.push(polygon.into_iter().map(|r| r.into_iter().map(|p| p.0).collect()).collect()); + } + Coordinates::Polygons(polygons) + } + Some(Coordinates::Polygons(_) | Coordinates::Empty) => { + while seq.next_element::()?.is_some() {} + Coordinates::Empty + } + }) + } +} + +/// One position: longitude and latitude, any altitude skipped. +struct Position(Point); + +impl<'de> Deserialize<'de> for Position { + fn deserialize>(deserializer: D) -> std::result::Result { + struct Numbers; + impl<'de> Visitor<'de> for Numbers { + type Value = Position; + + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("a position") + } + + fn visit_seq>(self, mut seq: A) -> std::result::Result { + let x = seq.next_element::()?.unwrap_or(f64::NAN); + let y = seq.next_element::()?.unwrap_or(f64::NAN); + while seq.next_element::()?.is_some() {} + Ok(Position([x, y])) + } + } + deserializer.deserialize_seq(Numbers) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Kind, Value}; + + const COLLECTION: &str = r#"{ + "type": "FeatureCollection", + "features": [ + {"type": "Feature", "id": 7, "properties": {"name": "Austin", "pop": 974447, "capital": true}, + "geometry": {"type": "Point", "coordinates": [-97.74, 30.27, 149.0]}}, + {"type": "Feature", "id": 9, "properties": {"name": "Dallas", "pop": null, "tags": ["big"]}, + "geometry": {"type": "Point", "coordinates": [-96.8, 32.78]}}, + {"type": "Feature", "properties": {"river": "Colorado"}, + "geometry": {"type": "LineString", "coordinates": [[-98.0, 30.0], [-97.0, 29.0]]}}, + {"type": "Feature", "properties": {"county": "Travis"}, + "geometry": {"type": "MultiPolygon", "coordinates": [[[[0, 0], [1, 0], [1, 1], [0, 0]]], + [[[2, 2], [3, 2], [3, 3], [2, 2]]]]}} + ] + }"#; + + #[test] + fn features_become_rows_of_tables_by_kind() { + let data = geojson("texas", COLLECTION.as_bytes()).expect("valid"); + let points = data.table("points").expect("points"); + assert_eq!(points.len(), 2); + assert_eq!(points.get(7_u64, "geometry"), Some(Value::Point([-97.74, 30.27])), "altitude skipped"); + assert_eq!(points.get(7_u64, "pop"), Some(Value::Number(974_447.0))); + assert_eq!(points.get(9_u64, "pop"), None, "null is missing"); + assert_eq!(points.get(7_u64, "capital"), Some(Value::Bool(true))); + assert_eq!(points.get(9_u64, "tags"), Some(Value::Text("[\"big\"]".into())), "other values as JSON"); + assert_eq!(data.table("lines").map(|t| t.kind("geometry")), Some(Some(Kind::Parts))); + let polygons = data.table("polygons").expect("polygons"); + assert_eq!(polygons.kind("geometry"), Some(Kind::Polygons)); + let Some(Value::Polygons(shapes)) = polygons.get(0_u64, "geometry") else { panic!("polygons") }; + assert_eq!(shapes.len(), 2, "a multipolygon is one row"); + assert_eq!(polygons.get(0_u64, "county"), Some(Value::Text("Travis".into()))); + } + + #[test] + fn gzip_compressed_bytes_read_alike() { + use std::io::Write; + let mut encoder = flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::fast()); + encoder.write_all(COLLECTION.as_bytes()).expect("written"); + let data = geojson("texas", &encoder.finish().expect("finished")).expect("valid"); + assert_eq!(data.table("points").map(Table::len), Some(2)); + } + + #[test] + fn bare_geometries_and_bad_documents() { + let data = geojson("g", br#"{"type": "Polygon", "coordinates": [[[0, 0], [1, 0], [0, 1], [0, 0]]]}"#) + .expect("a geometry"); + assert_eq!(data.table("polygons").map(Table::len), Some(1)); + assert!(geojson("g", b"{\"type\": \"FeatureCollection\"").is_err(), "cut short"); + } +} diff --git a/crates/latkit/src/geo/mod.rs b/crates/latkit/src/geo/mod.rs new file mode 100644 index 00000000..b335c69e --- /dev/null +++ b/crates/latkit/src/geo/mod.rs @@ -0,0 +1,33 @@ +//! Geography: GeoJSON and vector tiles as data, and what shapes become to draw: an +//! area's triangles, and lines bent along the globe. + +#[cfg(feature = "gpu")] +mod earcut; +mod geojson; +#[cfg(feature = "gpu")] +pub(crate) mod mvt; +#[cfg(feature = "gpu")] +pub(crate) mod pmtiles; +#[cfg(feature = "gpu")] +pub(crate) mod shapes; +#[cfg(feature = "gpu")] +pub(crate) mod tiles; + +use std::borrow::Cow; +use std::io::Read; + +pub(crate) use geojson::geojson; + +use crate::{Error, Result}; + +/// `bytes` inflated where they are gzip-compressed, else as they are. +pub(crate) fn gunzipped(bytes: &[u8]) -> Result> { + if !bytes.starts_with(&[0x1f, 0x8b]) { + return Ok(Cow::Borrowed(bytes)); + } + let mut out = Vec::with_capacity(bytes.len() * 4); + flate2::read::MultiGzDecoder::new(bytes) + .read_to_end(&mut out) + .map_err(|e| Error::invalid(format!("the gzip-compressed bytes are corrupt: {e}")))?; + Ok(Cow::Owned(out)) +} diff --git a/crates/latkit/src/geo/mvt.rs b/crates/latkit/src/geo/mvt.rs new file mode 100644 index 00000000..81f0d699 --- /dev/null +++ b/crates/latkit/src/geo/mvt.rs @@ -0,0 +1,715 @@ +//! Mapbox vector tiles: a tile's layers, their features' geometry in longitude and latitude, clipped +//! to the tile so neighbors never overlap, and their properties. + +use crate::tiles::TileKey; + +type Point = [f64; 2]; + +/// What a feature's geometry is. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub(crate) enum Kind { + Points, + Lines, + Polygons, +} + +/// A property value as a tile holds it. +#[derive(Clone, PartialEq, Debug)] +pub(crate) enum Property { + Text(String), + Number(f64), + Bool(bool), +} + +/// A feature's geometry, in degrees. +#[derive(Clone, PartialEq, Debug)] +pub(crate) enum Shape { + Points(Vec), + Lines(Vec>), + Polygons(Vec>>), +} + +impl Shape { + pub(crate) fn kind(&self) -> Kind { + match self { + Shape::Points(_) => Kind::Points, + Shape::Lines(_) => Kind::Lines, + Shape::Polygons(_) => Kind::Polygons, + } + } +} + +/// One feature: its place among its layer's features, its shape, and its properties by key. +#[derive(Clone, Debug)] +pub(crate) struct Feature { + pub(crate) shape: Shape, + pub(crate) properties: Vec<(u32, Property)>, +} + +/// One layer: its name, its keys, and its features. +#[derive(Clone, Debug, Default)] +pub(crate) struct Layer { + pub(crate) name: String, + pub(crate) keys: Vec, + pub(crate) features: Vec, +} + +/// The layers of tile `key`'s `bytes`; a feature's geometry clipped to the tile, and one left with +/// nothing inside it dropped. Bytes that are no tile answer `None`. +pub(crate) fn decode(bytes: &[u8], key: TileKey) -> Option> { + let mut layers = Vec::new(); + let mut tile = Reader::new(bytes); + while !tile.done() { + let (field, wire) = tile.tag()?; + if field == 3 && wire == LENGTH { + layers.push(layer(tile.bytes()?, key)?); + } else { + tile.skip(wire)?; + } + } + Some(layers) +} + +fn layer(bytes: &[u8], key: TileKey) -> Option { + let mut out = Layer::default(); + let mut values = Vec::new(); + let mut raw = Vec::new(); + let mut extent = 4096_u32; + let mut reader = Reader::new(bytes); + while !reader.done() { + let (field, wire) = reader.tag()?; + match (field, wire) { + (1, LENGTH) => out.name = String::from_utf8_lossy(reader.bytes()?).into_owned(), + (2, LENGTH) => raw.push(reader.bytes()?), + (3, LENGTH) => out.keys.push(String::from_utf8_lossy(reader.bytes()?).into_owned()), + (4, LENGTH) => values.push(value(reader.bytes()?)?), + (5, VARINT) => extent = reader.varint()? as u32, + _ => reader.skip(wire)?, + } + } + let frame = Frame::new(key, f64::from(extent.max(1))); + out.features = raw.into_iter().filter_map(|bytes| feature(bytes, &values, &frame)).collect(); + Some(out) +} + +fn value(bytes: &[u8]) -> Option { + let mut reader = Reader::new(bytes); + let mut out = Property::Bool(false); + while !reader.done() { + let (field, wire) = reader.tag()?; + out = match (field, wire) { + (1, LENGTH) => Property::Text(String::from_utf8_lossy(reader.bytes()?).into_owned()), + (2, FIXED32) => Property::Number(f64::from(f32::from_le_bytes(reader.take()?))), + (3, FIXED64) => Property::Number(f64::from_le_bytes(reader.take()?)), + (4, VARINT) => Property::Number(reader.varint()? as i64 as f64), + (5, VARINT) => Property::Number(reader.varint()? as f64), + (6, VARINT) => Property::Number(zigzag(reader.varint()?) as f64), + (7, VARINT) => Property::Bool(reader.varint()? != 0), + _ => { + reader.skip(wire)?; + continue; + } + }; + } + Some(out) +} + +/// A feature: `None` when nothing of it lies in the tile, or its bytes are no feature, which drops +/// it alone. +fn feature(bytes: &[u8], values: &[Property], frame: &Frame) -> Option { + let mut reader = Reader::new(bytes); + let (mut tags, mut geometry, mut kind) = (Vec::new(), Vec::new(), 0); + while !reader.done() { + let (field, wire) = reader.tag()?; + match (field, wire) { + (2, LENGTH) => packed(reader.bytes()?, &mut tags)?, + (2, VARINT) => tags.push(reader.varint()? as u32), + (3, VARINT) => kind = reader.varint()?, + (4, LENGTH) => packed(reader.bytes()?, &mut geometry)?, + (4, VARINT) => geometry.push(reader.varint()? as u32), + _ => reader.skip(wire)?, + } + } + let shape = match kind { + 1 => frame.points(&geometry), + 2 => frame.lines(&geometry), + 3 => frame.polygons(&geometry), + _ => None, + }; + let shape = shape?; + let properties = tags + .as_chunks::<2>() + .0 + .iter() + .filter_map(|&[key, value]| Some((key, values.get(value as usize)?.clone()))) + .collect(); + Some(Feature { shape, properties }) +} + +/// A tile's frame: where its coordinates lie on the earth. +struct Frame { + key: TileKey, + extent: f64, +} + +impl Frame { + fn new(key: TileKey, extent: f64) -> Frame { + Frame { key, extent } + } + + /// The longitude and latitude of tile coordinates `p`. + fn degrees(&self, p: [f64; 2]) -> Point { + let n = f64::from(1_u32 << self.key.z.min(31)); + let x = (f64::from(self.key.x) + p[0] / self.extent) / n; + let y = (f64::from(self.key.y) + p[1] / self.extent) / n; + let lat = (std::f64::consts::PI * (1.0 - 2.0 * y)).sinh().atan().to_degrees(); + [x * 360.0 - 180.0, lat] + } + + /// The tile's points, those outside it dropped. + fn points(&self, geometry: &[u32]) -> Option { + let inside = |p: &[f64; 2]| p.iter().all(|&v| v >= 0.0 && v < self.extent); + let points: Vec = + paths(geometry).into_iter().flatten().filter(inside).map(|p| self.degrees(p)).collect(); + (!points.is_empty()).then_some(Shape::Points(points)) + } + + /// The tile's lines, cut where they leave it. + fn lines(&self, geometry: &[u32]) -> Option { + let mut parts: Vec> = Vec::new(); + for path in paths(geometry) { + for part in clip_line(&path, self.extent) { + if part.len() >= 2 { + parts.push(part.into_iter().map(|p| self.degrees(p)).collect()); + } + } + } + (!parts.is_empty()).then_some(Shape::Lines(parts)) + } + + /// The tile's polygons: each exterior ring, by its positive area, with the holes after it, + /// clipped to the tile as a whole. + fn polygons(&self, geometry: &[u32]) -> Option { + let mut groups: Vec>> = Vec::new(); + for ring in paths(geometry) { + let area = surveyor(&ring); + if area > 0.0 { + groups.push(vec![ring]); + } else if let Some(group) = groups.last_mut().filter(|_| area < 0.0) { + group.push(ring); + } + } + let polygons: Vec>> = groups + .iter() + .flat_map(|group| clip_polygon(group, self.extent)) + .map(|polygon| { + let closed = |ring: Vec<[f64; 2]>| { + let mut ring: Vec = ring.into_iter().map(|p| self.degrees(p)).collect(); + ring.push(ring[0]); + ring + }; + polygon.into_iter().map(closed).collect() + }) + .collect(); + (!polygons.is_empty()).then_some(Shape::Polygons(polygons)) + } +} + +/// A polygon, its exterior then its holes, clipped to the square `0..extent` as a whole: a ring +/// wholly inside it stays; the runs of the rest inside it join along its edge, where the polygon's +/// inside lies, into exteriors; and each hole inside goes to the exterior around it. Clipping each +/// ring alone would leave a hole crossing the edge running along its exterior there, which no +/// triangulation reads right. +fn clip_polygon(rings: &[Vec<[f64; 2]>], extent: f64) -> Vec>> { + let inside = |p: &[f64; 2]| p.iter().all(|&v| (0.0..=extent).contains(&v)); + let (mut exteriors, mut holes, mut runs) = (Vec::new(), Vec::new(), Vec::new()); + // Whether the square lies within the polygon, as the rings that miss it say. + let mut covered = false; + for (k, ring) in rings.iter().enumerate().filter(|(_, r)| r.len() >= 3) { + if ring.iter().all(inside) { + if k == 0 { + exteriors.push(ring.clone()); + } else { + holes.push(ring.clone()); + } + continue; + } + let crossing = runs_inside(ring, extent); + // A ring missing the square holds all of it or none: the exterior first, then a hole within. + if crossing.is_empty() && contains(ring, [extent / 2.0; 2]) { + covered = k == 0; + } + runs.extend(crossing); + } + if !runs.is_empty() { + exteriors.extend(join(&runs, extent)); + } else if covered { + exteriors.push(vec![[0.0, 0.0], [extent, 0.0], [extent, extent], [0.0, extent]]); + } + let mut polygons: Vec>> = exteriors.into_iter().map(|e| vec![e]).collect(); + for hole in holes { + let within = |p: &&[f64; 2]| p.iter().all(|&v| v > 0.0 && v < extent); + let Some(&point) = hole.iter().find(within) else { continue }; + let around = match polygons.len() { + 1 => polygons.first_mut(), + _ => polygons.iter_mut().find(|p| contains(&p[0], point)), + }; + if let Some(polygon) = around { + polygon.push(hole); + } + } + polygons +} + +/// The runs of closed `ring`, which has a point outside the square `0..extent`, inside it: each from +/// where it enters to where it leaves, on the edge. A run lying along the edge alone bounds nothing, +/// and drops. +fn runs_inside(ring: &[[f64; 2]], extent: f64) -> Vec> { + let outside = |p: &[f64; 2]| p.iter().any(|&v| !(0.0..=extent).contains(&v)); + let Some(start) = ring.iter().position(outside) else { return Vec::new() }; + let on_edge = |p: &[f64; 2]| p.iter().any(|&v| v.abs() <= extent * 1e-9 || (v - extent).abs() <= extent * 1e-9); + let n = ring.len(); + let (mut runs, mut run) = (Vec::new(), Vec::new()); + for k in 0..n { + let (a, b) = (ring[(start + k) % n], ring[(start + k + 1) % n]); + let Some((p, q)) = clip_segment(a, b, extent) else { continue }; + if run.is_empty() { + run.push(onto_edge(p, extent)); + } + if q == b { + run.push(q); + continue; + } + // The segment leaves the square: the run ends. + run.push(onto_edge(q, extent)); + if run.len() >= 2 && !run.iter().all(on_edge) { + runs.push(std::mem::take(&mut run)); + } + run.clear(); + } + runs +} + +/// `p`, near the square's edge, moved onto it. +fn onto_edge(p: [f64; 2], extent: f64) -> [f64; 2] { + let gaps = [p[1].abs(), (p[0] - extent).abs(), (p[1] - extent).abs(), p[0].abs()]; + let edge = (0..4).min_by(|&a, &b| gaps[a].total_cmp(&gaps[b])).unwrap_or(0); + let p = p.map(|v| v.clamp(0.0, extent)); + match edge { + 0 => [p[0], 0.0], + 1 => [extent, p[1]], + 2 => [p[0], extent], + _ => [0.0, p[1]], + } +} + +/// How far along the square's edge `p` lies, from the corner at 0 the way an exterior winds: along +/// y = 0, then x = extent, y = extent, and x = 0. +fn along(p: [f64; 2], extent: f64) -> f64 { + let gaps = [p[1].abs(), (p[0] - extent).abs(), (p[1] - extent).abs(), p[0].abs()]; + match (0..4).min_by(|&a, &b| gaps[a].total_cmp(&gaps[b])).unwrap_or(0) { + 0 => p[0], + 1 => extent + p[1], + 2 => 3.0 * extent - p[0], + _ => 4.0 * extent - p[1], + } +} + +/// The exteriors `runs` make: from where each leaves the square, along its edge the way the +/// polygon's inside lies to where the next enters, past the corners between, until the first again. +fn join(runs: &[Vec<[f64; 2]>], extent: f64) -> Vec> { + let around = 4.0 * extent; + let entries: Vec = runs.iter().map(|r| along(r[0], extent)).collect(); + let ahead = |from: f64, to: f64| (to - from).rem_euclid(around); + let corner = |k: i64| match k.rem_euclid(4) { + 0 => [0.0, 0.0], + 1 => [extent, 0.0], + 2 => [extent, extent], + _ => [0.0, extent], + }; + let mut used = vec![false; runs.len()]; + let mut rings = Vec::new(); + for first in 0..runs.len() { + if used[first] { + continue; + } + let (mut ring, mut run) = (Vec::new(), first); + loop { + used[run] = true; + ring.extend_from_slice(&runs[run]); + let exit = along(runs[run][runs[run].len() - 1], extent); + let next = (0..runs.len()) + .filter(|&k| !used[k] || k == first) + .min_by(|&a, &b| ahead(exit, entries[a]).total_cmp(&ahead(exit, entries[b]))) + .unwrap_or(first); + let to = exit + ahead(exit, entries[next]); + let first_corner = (exit / extent).floor() as i64 + 1; + for k in first_corner.. { + if k as f64 * extent >= to { + break; + } + ring.push(corner(k)); + } + if next == first { + break; + } + run = next; + } + if ring.len() >= 3 { + rings.push(ring); + } + } + rings +} + +/// Whether closed `ring` holds `p`, by the crossings of a ray from it. +fn contains(ring: &[[f64; 2]], p: [f64; 2]) -> bool { + let mut inside = false; + let mut a = ring[ring.len() - 1]; + for &b in ring { + if (a[1] > p[1]) != (b[1] > p[1]) && p[0] < a[0] + (p[1] - a[1]) * (b[0] - a[0]) / (b[1] - a[1]) { + inside = !inside; + } + a = b; + } + inside +} + +/// The paths a geometry's commands draw, in tile coordinates: each move starts one, a close returns +/// to its start (left implicit). +fn paths(geometry: &[u32]) -> Vec> { + let mut paths: Vec> = Vec::new(); + let (mut x, mut y) = (0_i64, 0_i64); + let mut i = 0; + while i < geometry.len() { + let command = geometry[i]; + let (id, count) = (command & 7, (command >> 3) as usize); + i += 1; + match id { + 1 | 2 => { + for k in 0..count { + let (Some(&dx), Some(&dy)) = (geometry.get(i), geometry.get(i + 1)) else { return paths }; + i += 2; + x += zigzag(u64::from(dx)); + y += zigzag(u64::from(dy)); + if id == 1 && (k == 0 || paths.is_empty()) { + paths.push(Vec::new()); + } + if let Some(path) = paths.last_mut() { + path.push([x as f64, y as f64]); + } + // A move with several points is several points, each its own path. + if id == 1 && count > 1 && k + 1 < count { + paths.push(Vec::new()); + } + } + } + 7 => {} + _ => return paths, + } + } + paths.retain(|p| !p.is_empty()); + paths +} + +/// Twice a ring's area by the surveyor's formula in tile coordinates, y down: positive for an +/// exterior ring. +fn surveyor(ring: &[[f64; 2]]) -> f64 { + let Some(&last) = ring.last() else { return 0.0 }; + let mut sum = 0.0; + let mut a = last; + for &b in ring { + sum += a[0] * b[1] - b[0] * a[1]; + a = b; + } + sum +} + +/// `line` cut to the square `0..extent`: the runs of it inside. +fn clip_line(line: &[[f64; 2]], extent: f64) -> Vec> { + let mut parts: Vec> = Vec::new(); + let mut current: Vec<[f64; 2]> = Vec::new(); + for w in line.windows(2) { + let Some((a, b)) = clip_segment(w[0], w[1], extent) else { + if current.len() >= 2 { + parts.push(std::mem::take(&mut current)); + } + current.clear(); + continue; + }; + if current.last() != Some(&a) { + if current.len() >= 2 { + parts.push(std::mem::take(&mut current)); + } + current.clear(); + current.push(a); + } + current.push(b); + // The segment left the tile: what follows starts a new run. + if b != w[1] { + parts.push(std::mem::take(&mut current)); + } + } + if current.len() >= 2 { + parts.push(current); + } + parts +} + +/// Segment `a b` clipped to the square `0..extent`, by Liang and Barsky. +fn clip_segment(a: [f64; 2], b: [f64; 2], extent: f64) -> Option<([f64; 2], [f64; 2])> { + let (dx, dy) = (b[0] - a[0], b[1] - a[1]); + let (mut t0, mut t1) = (0.0_f64, 1.0_f64); + for (p, q) in [(-dx, a[0]), (dx, extent - a[0]), (-dy, a[1]), (dy, extent - a[1])] { + if p == 0.0 { + if q < 0.0 { + return None; + } + } else { + let t = q / p; + if p < 0.0 { + t0 = t0.max(t); + } else { + t1 = t1.min(t); + } + } + } + if t0 > t1 { + return None; + } + let at = |t: f64| { + if t == 0.0 { + a + } else if t == 1.0 { + b + } else { + [a[0] + dx * t, a[1] + dy * t] + } + }; + Some((at(t0), at(t1))) +} + +fn zigzag(n: u64) -> i64 { + ((n >> 1) as i64) ^ -((n & 1) as i64) +} + +fn packed(bytes: &[u8], out: &mut Vec) -> Option<()> { + let mut reader = Reader::new(bytes); + while !reader.done() { + out.push(reader.varint()? as u32); + } + Some(()) +} + +const VARINT: u8 = 0; +const FIXED64: u8 = 1; +const LENGTH: u8 = 2; +const FIXED32: u8 = 5; + +/// Protocol buffer fields, read in order; `None` past the end or on a malformed field. +struct Reader<'a> { + bytes: &'a [u8], +} + +impl<'a> Reader<'a> { + fn new(bytes: &'a [u8]) -> Reader<'a> { + Reader { bytes } + } + + fn done(&self) -> bool { + self.bytes.is_empty() + } + + fn varint(&mut self) -> Option { + let mut value = 0_u64; + for shift in (0..64).step_by(7) { + let (&byte, rest) = self.bytes.split_first()?; + self.bytes = rest; + value |= u64::from(byte & 0x7f) << shift; + if byte < 0x80 { + return Some(value); + } + } + None + } + + /// The next field's number and wire type. + fn tag(&mut self) -> Option<(u32, u8)> { + let tag = self.varint()?; + Some(((tag >> 3) as u32, (tag & 7) as u8)) + } + + fn bytes(&mut self) -> Option<&'a [u8]> { + let len = usize::try_from(self.varint()?).ok()?; + let (head, rest) = self.bytes.split_at_checked(len)?; + self.bytes = rest; + Some(head) + } + + fn take(&mut self) -> Option<[u8; N]> { + let (head, rest) = self.bytes.split_first_chunk::()?; + self.bytes = rest; + Some(*head) + } + + fn skip(&mut self, wire: u8) -> Option<()> { + match wire { + VARINT => self.varint().map(drop), + FIXED64 => self.take::<8>().map(drop), + LENGTH => self.bytes().map(drop), + FIXED32 => self.take::<4>().map(drop), + _ => None, + } + } +} + +#[cfg(test)] +pub(crate) mod tests { + use super::*; + + /// Protocol buffer fields, written. + #[derive(Default)] + pub(crate) struct Writer(pub(crate) Vec); + + impl Writer { + pub(crate) fn varint(&mut self, mut v: u64) { + while v >= 0x80 { + self.0.push((v as u8) | 0x80); + v >>= 7; + } + self.0.push(v as u8); + } + + pub(crate) fn tag(&mut self, field: u32, wire: u8) { + self.varint(u64::from(field << 3) | u64::from(wire)); + } + + pub(crate) fn bytes(&mut self, field: u32, bytes: &[u8]) { + self.tag(field, LENGTH); + self.varint(bytes.len() as u64); + self.0.extend_from_slice(bytes); + } + + pub(crate) fn packed(&mut self, field: u32, values: &[u32]) { + let mut inner = Writer::default(); + for &v in values { + inner.varint(u64::from(v)); + } + self.bytes(field, &inner.0); + } + } + + pub(crate) fn zig(v: i64) -> u32 { + ((v << 1) ^ (v >> 63)) as u32 + } + + /// A tile of one layer `name` holding one feature of `kind` drawn by `geometry`, with property + /// `name` set to `value`. + pub(crate) fn tile(layer: &str, kind: u64, geometry: &[u32], value: &str) -> Vec { + let mut feature = Writer::default(); + feature.packed(2, &[0, 0]); + feature.tag(3, VARINT); + feature.varint(kind); + feature.packed(4, geometry); + let mut text = Writer::default(); + text.bytes(1, value.as_bytes()); + let mut l = Writer::default(); + l.tag(15, VARINT); + l.varint(2); + l.bytes(1, layer.as_bytes()); + l.bytes(2, &feature.0); + l.bytes(3, b"name"); + l.bytes(4, &text.0); + l.tag(5, VARINT); + l.varint(4096); + let mut t = Writer::default(); + t.bytes(3, &l.0); + t.0 + } + + /// A square's commands, from `(x, y)` of `side`, clockwise in tile coordinates. + pub(crate) fn square(x: i64, y: i64, side: i64) -> Vec { + vec![9, zig(x), zig(y), 26, zig(side), 0, 0, zig(side), zig(-side), 0, 15] + } + + #[test] + fn a_polygon_decodes_to_degrees() { + let key = TileKey { z: 0, x: 0, y: 0 }; + let layers = decode(&tile("water", 3, &square(1024, 1024, 2048), "lake"), key).expect("a tile"); + assert_eq!(layers.len(), 1); + assert_eq!(layers[0].name, "water"); + let feature = &layers[0].features[0]; + let Shape::Polygons(polygons) = &feature.shape else { panic!("polygons") }; + let ring = &polygons[0][0]; + assert_eq!(ring.len(), 5, "closed"); + assert!((ring[0][0] + 90.0).abs() < 1e-9, "a quarter in: {:?}", ring[0]); + assert!(ring[0][1] > 60.0 && ring[0][1] < 70.0, "mercator latitude: {:?}", ring[0]); + assert_eq!(feature.properties, vec![(0, Property::Text("lake".into()))]); + } + + #[test] + fn a_polygon_clips_as_a_whole() { + let square = |x: f64, y: f64, side: f64, exterior: bool| { + let ring = vec![[x, y], [x + side, y], [x + side, y + side], [x, y + side]]; + if exterior { ring } else { ring.into_iter().rev().collect() } + }; + // A sea over the tile and its buffer, with islands across its left edge, across its corner, + // inside it, and outside it. + let rings = [ + square(-64.0, -64.0, 4224.0, true), + square(-200.0, 1800.0, 500.0, false), + square(3900.0, -100.0, 400.0, false), + square(1000.0, 1000.0, 200.0, false), + square(5000.0, 5000.0, 100.0, false), + ]; + let polygons = clip_polygon(&rings, 4096.0); + assert_eq!(polygons.len(), 1); + assert_eq!(polygons[0].len(), 2, "islands across the edge notch the sea; the one inside stays a hole"); + let points: Vec<[f64; 2]> = polygons[0].concat(); + let triangles = super::super::earcut::earcut(&points, &[polygons[0][0].len()]); + let area: f64 = triangles + .iter() + .map(|t| { + let [a, b, c] = t.map(|i| points[i as usize]); + ((b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1])).abs() / 2.0 + }) + .sum(); + let sea = 4096.0 * 4096.0 - 300.0 * 500.0 - 196.0 * 300.0 - 200.0 * 200.0; + assert!((area - sea).abs() < 1e-6, "{area} drawn of {sea}"); + // A sea the tile lies wholly in is the tile; one beside it is nothing. + assert_eq!(clip_polygon(&[square(-100.0, -100.0, 5000.0, true)], 4096.0)[0][0].len(), 4); + assert_eq!(clip_polygon(&[square(5000.0, 0.0, 100.0, true)], 4096.0).len(), 0); + } + + #[test] + fn shapes_are_clipped_to_the_tile() { + let key = TileKey { z: 1, x: 1, y: 0 }; + // A square reaching past the tile's left edge: clipped there. + let layers = decode(&tile("land", 3, &square(-512, 1024, 1024), "x"), key).expect("a tile"); + let Shape::Polygons(polygons) = &layers[0].features[0].shape else { panic!("polygons") }; + assert!(polygons[0][0].iter().all(|p| p[0] >= -1e-9), "west of 0 is clipped: {:?}", polygons[0][0]); + // A line wholly outside draws nothing. + let outside = vec![9, zig(-100), zig(10), 10, zig(-50), 0]; + let layers = decode(&tile("road", 2, &outside, "y"), key).expect("a tile"); + assert!(layers[0].features.is_empty()); + } + + #[test] + fn a_polygon_wholly_outside_leaves_nothing() { + let key = TileKey { z: 1, x: 1, y: 0 }; + // Commands move relative to where the last ring ended, (-3000, 600): the second starts at (100, 100). + let mut geometry = square(-3000, 100, 500); + geometry.extend(square(3100, -500, 500)); + let layers = decode(&tile("land", 3, &geometry, "x"), key).expect("a tile"); + let Shape::Polygons(polygons) = &layers[0].features[0].shape else { panic!("polygons") }; + assert_eq!(polygons.len(), 1, "only the one inside: {polygons:?}"); + assert!(polygons.iter().flatten().all(|ring| ring.len() >= 4)); + } + + #[test] + fn lines_are_cut_where_they_leave() { + let parts = clip_line(&[[-10.0, 5.0], [10.0, 5.0], [10.0, -10.0], [20.0, 5.0]], 100.0); + assert_eq!(parts.len(), 2, "{parts:?}"); + assert_eq!(parts[0][0], [0.0, 5.0]); + } +} diff --git a/crates/latkit/src/geo/pmtiles.rs b/crates/latkit/src/geo/pmtiles.rs new file mode 100644 index 00000000..1eeebf0f --- /dev/null +++ b/crates/latkit/src/geo/pmtiles.rs @@ -0,0 +1,190 @@ +//! PMTiles archives, version 3: a header, directories of tile entries along the Hilbert curve, and +//! the tiles, each found by range requests. + +use crate::tiles::TileKey; + +/// Bytes a header takes. +pub(crate) const HEADER: usize = 127; +const MAGIC: &[u8] = b"PMTiles"; +/// How deep directories nest at most. +pub(crate) const DEPTH: usize = 4; + +/// What an archive's header says. +#[derive(Clone, Copy, PartialEq, Debug)] +pub(crate) struct Header { + pub(crate) root: (u64, u64), + pub(crate) metadata: (u64, u64), + pub(crate) leaves: u64, + pub(crate) data: u64, + /// Whether directories, and tiles, are gzip-compressed. + pub(crate) gzip_directories: bool, + pub(crate) gzip_tiles: bool, + pub(crate) vector: bool, + pub(crate) min_zoom: u8, + pub(crate) max_zoom: u8, + /// West, south, east, north. + pub(crate) bounds: [f64; 4], +} + +/// Whether `bytes` begin a PMTiles archive. +pub(crate) fn is_archive(bytes: &[u8]) -> bool { + bytes.starts_with(MAGIC) +} + +/// The header at the start of `bytes`: a version 3 archive's, with compression read or none. +pub(crate) fn header(bytes: &[u8]) -> Result { + if !is_archive(bytes) || bytes.len() < HEADER { + return Err("these bytes are not a PMTiles archive".into()); + } + if bytes[7] != 3 { + return Err(format!("PMTiles version {} is not read; version 3 is", bytes[7])); + } + let u64_at = |at: usize| u64::from_le_bytes(bytes[at..at + 8].try_into().expect("eight bytes")); + let degrees = |at: usize| f64::from(i32::from_le_bytes(bytes[at..at + 4].try_into().expect("four bytes"))) / 1e7; + let compression = |code: u8, what: &str| match code { + 0 | 1 => Ok(false), + 2 => Ok(true), + other => Err(format!("the archive's {what} use compression {other}; only gzip is read")), + }; + Ok(Header { + root: (u64_at(8), u64_at(16)), + metadata: (u64_at(24), u64_at(32)), + leaves: u64_at(40), + data: u64_at(56), + gzip_directories: compression(bytes[97], "directories")?, + gzip_tiles: compression(bytes[98], "tiles")?, + vector: bytes[99] == 1 || bytes[99] == 0, + min_zoom: bytes[100], + max_zoom: bytes[101], + bounds: [degrees(102), degrees(106), degrees(110), degrees(114)], + }) +} + +/// A directory's entries, sorted by tile id: each one's id, run length (0 for a leaf directory), +/// offset, and length. +#[derive(Clone, Default, Debug)] +pub(crate) struct Directory { + ids: Vec, + runs: Vec, + offsets: Vec, + lengths: Vec, +} + +/// Where a directory sends a tile. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub(crate) enum Entry { + /// The tile's bytes: offset from the data section, and length. + Tile(u64, u64), + /// A leaf directory: offset from the leaf section, and length. + Leaf(u64, u64), +} + +impl Directory { + /// The directory in `bytes`, decompressed. + pub(crate) fn decode(bytes: &[u8]) -> Option { + let mut at = 0; + let mut next = || -> Option { + let mut value = 0_u64; + for shift in (0..64).step_by(7) { + let byte = *bytes.get(at)?; + at += 1; + value |= u64::from(byte & 0x7f) << shift; + if byte < 0x80 { + return Some(value); + } + } + None + }; + let count = usize::try_from(next()?).ok()?; + if count > bytes.len() { + return None; + } + let mut id = 0; + let ids: Vec = (0..count) + .map(|_| { + next().map(|d| { + id += d; + id + }) + }) + .collect::>()?; + let runs: Vec = (0..count).map(|_| next().map(|v| v as u32)).collect::>()?; + let lengths: Vec = (0..count).map(|_| next().map(|v| v as u32)).collect::>()?; + let mut offsets: Vec = Vec::with_capacity(count); + for i in 0..count { + let value = next()?; + let offset = match (value, i) { + (0, 0) => return None, + (0, _) => offsets[i - 1] + u64::from(lengths[i - 1]), + (v, _) => v - 1, + }; + offsets.push(offset); + } + Some(Directory { ids, runs, offsets, lengths }) + } + + /// Where the entry holding tile id `id` sends it, if any does. + pub(crate) fn find(&self, id: u64) -> Option { + let i = match self.ids.binary_search(&id) { + Ok(i) => i, + Err(0) => return None, + Err(i) => i - 1, + }; + let (offset, length) = (self.offsets[i], u64::from(self.lengths[i])); + match self.runs[i] { + 0 => Some(Entry::Leaf(offset, length)), + run if id - self.ids[i] < u64::from(run) => Some(Entry::Tile(offset, length)), + _ => None, + } + } +} + +/// Tile `key`'s id along the Hilbert curve, counting every tile of the zooms before it. +pub(crate) fn tile_id(key: TileKey) -> u64 { + let z = u32::from(key.z); + let before: u64 = (0..z).map(|k| 1_u64 << (2 * k)).sum(); + let n = 1_u64 << z; + let (mut x, mut y) = (u64::from(key.x), u64::from(key.y)); + let mut index = 0; + let mut s = n / 2; + while s > 0 { + let rx = u64::from(x & s != 0); + let ry = u64::from(y & s != 0); + index += s * s * ((3 * rx) ^ ry); + if ry == 0 { + if rx == 1 { + x = n - 1 - x; + y = n - 1 - y; + } + std::mem::swap(&mut x, &mut y); + } + s /= 2; + } + before + index +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn tile_ids_follow_the_hilbert_curve() { + assert_eq!(tile_id(TileKey { z: 0, x: 0, y: 0 }), 0); + // Zoom 1 goes around its four tiles from the top left, down, then right. + let ids: Vec = [(0, 0), (0, 1), (1, 1), (1, 0)].map(|(x, y)| tile_id(TileKey { z: 1, x, y })).to_vec(); + assert_eq!(ids, vec![1, 2, 3, 4]); + assert_eq!(tile_id(TileKey { z: 2, x: 0, y: 0 }), 5); + } + + #[test] + fn directories_find_tiles_and_leaves() { + // Entries: ids 0 (a run of 2 tiles), 5 (a leaf); offsets written as offset + 1, then 0 for + // "right after the one before". + let bytes = [2, 0, 5, 2, 0, 10, 20, 1, 0]; + let directory = Directory::decode(&bytes).expect("a directory"); + assert_eq!(directory.find(0), Some(Entry::Tile(0, 10))); + assert_eq!(directory.find(1), Some(Entry::Tile(0, 10)), "inside the run"); + assert_eq!(directory.find(2), None, "past the run"); + assert_eq!(directory.find(7), Some(Entry::Leaf(10, 20))); + } +} diff --git a/crates/latkit/src/geo/shapes.rs b/crates/latkit/src/geo/shapes.rs new file mode 100644 index 00000000..ffade701 --- /dev/null +++ b/crates/latkit/src/geo/shapes.rs @@ -0,0 +1,412 @@ +//! What geometry becomes to draw: an area's triangles with the point its label hangs from, and on the +//! earth a path that bends with the globe. On the earth, longitudes unwrap across the antimeridian so +//! nothing streaks across the map, and nothing spans more than [`EARTH_STEP`] degrees: triangles +//! split along a grid of that pitch, paths gain points. + +use std::collections::BinaryHeap; + +use super::earcut::earcut; + +type Point = [f64; 2]; + +/// Degrees an earth triangle spans a side at most, and an earth path's segment: a chord this long +/// sags under a two-thousandth of the globe's radius. +pub(crate) const EARTH_STEP: f64 = 2.0; + +/// The triangles of `polygons`, each its outer ring then its holes, as a point list: the point its +/// label hangs from first, then three points per triangle. Without triangles, no points at all. +pub(crate) fn triangles(polygons: &[Vec>], earth: bool) -> Vec { + let mut out = vec![[f64::NAN; 2]]; + let mut largest: Option<(f64, Vec>)> = None; + for polygon in polygons { + let rings: Vec> = if earth { unwrapped(polygon) } else { polygon.clone() }; + let Some(outer) = rings.first().filter(|r| r.len() >= 3) else { continue }; + let area = ring_area(outer).abs(); + let mut points: Vec = Vec::with_capacity(rings.iter().map(Vec::len).sum()); + let mut holes = Vec::with_capacity(rings.len().saturating_sub(1)); + for (k, ring) in rings.iter().enumerate() { + if k > 0 { + if ring.len() < 3 { + continue; + } + holes.push(points.len()); + } + points.extend(ring.iter().copied().filter(|p| p[0].is_finite() && p[1].is_finite())); + } + for t in earcut(&points, &holes) { + let corners = t.map(|i| points[i as usize]); + if earth { split(corners, &mut out) } else { out.extend(corners) } + } + if largest.as_ref().is_none_or(|(a, _)| area > *a) { + largest = Some((area, rings)); + } + } + if out.len() == 1 { + return Vec::new(); + } + if let Some((_, rings)) = largest { + out[0] = label_point(&rings); + } + out +} + +/// `parts` as an earth path draws them: longitudes unwrapped across the antimeridian, and a point +/// every [`EARTH_STEP`] degrees along longer segments. `None` when nothing changes. +pub(crate) fn earth_parts(parts: &[Vec]) -> Option>> { + let changes = parts.iter().any(|part| { + part.windows(2).any(|w| (w[1][0] - w[0][0]).abs() > EARTH_STEP || (w[1][1] - w[0][1]).abs() > EARTH_STEP) + }); + changes.then(|| parts.iter().map(|part| densified(&unwrap(part))).collect()) +} + +/// `polygon`'s rings with longitudes unwrapped: each ring continuous, and every ring on the side of +/// the antimeridian the outer ring starts on. +fn unwrapped(polygon: &[Vec]) -> Vec> { + let first = polygon.first().and_then(|r| r.first()).map_or(0.0, |p| p[0]); + polygon + .iter() + .map(|ring| { + let mut ring = unwrap(ring); + if let Some(start) = ring.first().map(|p| p[0]) { + let shift = 360.0 * turns(first - start); + if shift != 0.0 { + for p in &mut ring { + p[0] += shift; + } + } + } + ring + }) + .collect() +} + +/// `line` with each longitude moved by whole turns to within 180 degrees of the one before. +fn unwrap(line: &[Point]) -> Vec { + let mut out: Vec = Vec::with_capacity(line.len()); + for &p in line { + let mut p = p; + if let Some(prev) = out.last() { + p[0] += 360.0 * turns(prev[0] - p[0]); + } + out.push(p); + } + out +} + +/// The whole turns that bring a step of `degrees` within half a turn. A step of exactly half a turn +/// stays: a tile half the world wide has edges that long, and which way round they run is theirs. +fn turns(degrees: f64) -> f64 { + degrees.signum() * ((degrees.abs() - 180.0) / 360.0).ceil().max(0.0) +} + +/// `line` with points every [`EARTH_STEP`] degrees along its longer segments, straight in longitude +/// and latitude. +fn densified(line: &[Point]) -> Vec { + let mut out: Vec = Vec::with_capacity(line.len()); + for (k, &p) in line.iter().enumerate() { + if k > 0 { + let a = line[k - 1]; + let steps = ((p[0] - a[0]).abs().max((p[1] - a[1]).abs()) / EARTH_STEP).ceil() as usize; + for s in 1..steps { + let t = s as f64 / steps as f64; + out.push([a[0] + (p[0] - a[0]) * t, a[1] + (p[1] - a[1]) * t]); + } + } + out.push(p); + } + out +} + +/// Triangle `t` cut along the grid of [`EARTH_STEP`] degrees into the pieces each cell holds, each +/// fanned into triangles. A crossing is worked out from its edge's ends in one order, so triangles +/// sharing an edge share its crossings and no crack opens. +fn split(t: [Point; 3], out: &mut Vec) { + let cell = |v: f64| (v / EARTH_STEP).floor(); + let lo = [0, 1].map(|k| cell(t[0][k].min(t[1][k]).min(t[2][k]))); + let hi = [0, 1].map(|k| cell(t[0][k].max(t[1][k]).max(t[2][k]))); + if lo == hi || !lo.iter().chain(&hi).all(|v| v.is_finite()) { + out.extend(t); + return; + } + let mut piece: Vec = Vec::with_capacity(9); + let mut next: Vec = Vec::with_capacity(9); + let mut x = lo[0]; + while x <= hi[0] { + let mut y = lo[1]; + while y <= hi[1] { + piece.clear(); + piece.extend(t); + for (axis, at, keep_above) in [ + (0, x * EARTH_STEP, true), + (0, (x + 1.0) * EARTH_STEP, false), + (1, y * EARTH_STEP, true), + (1, (y + 1.0) * EARTH_STEP, false), + ] { + clip(&piece, axis, at, keep_above, &mut next); + std::mem::swap(&mut piece, &mut next); + if piece.len() < 3 { + break; + } + } + for k in 1..piece.len().saturating_sub(1) { + out.extend([piece[0], piece[k], piece[k + 1]]); + } + y += 1.0; + } + x += 1.0; + } +} + +/// The part of convex polygon `piece` on one side of the line where coordinate `axis` is `at`: at or +/// above it when `keep_above`, else at or below it. +fn clip(piece: &[Point], axis: usize, at: f64, keep_above: bool, out: &mut Vec) { + out.clear(); + let inside = |p: &Point| if keep_above { p[axis] >= at } else { p[axis] <= at }; + for (k, &p) in piece.iter().enumerate() { + let q = piece[(k + 1) % piece.len()]; + let (p_in, q_in) = (inside(&p), inside(&q)); + if p_in { + out.push(p); + } + if p_in != q_in { + out.push(crossing(p, q, axis, at)); + } + } +} + +/// Where segment `p q` crosses the line where coordinate `axis` is `at`, worked out from its ends in +/// one order whichever way the segment runs. +fn crossing(p: Point, q: Point, axis: usize, at: f64) -> Point { + let (a, b) = if (p[0], p[1]) <= (q[0], q[1]) { (p, q) } else { (q, p) }; + let t = (at - a[axis]) / (b[axis] - a[axis]); + let other = 1 - axis; + let mut out = [0.0; 2]; + out[axis] = at; + out[other] = a[other] + (b[other] - a[other]) * t; + out +} + +/// Twice the signed area of a ring. +fn ring_area(ring: &[Point]) -> f64 { + let Some(&last) = ring.last() else { return 0.0 }; + let mut sum = 0.0; + let mut j = last; + for &p in ring { + sum += (j[0] - p[0]) * (p[1] + j[1]); + j = p; + } + sum +} + +/// The point a polygon's label hangs from: the point inside it farthest from its edges, found to a +/// fiftieth of its size, as polylabel finds it. +fn label_point(rings: &[Vec]) -> Point { + let Some(outer) = rings.first() else { return [f64::NAN; 2] }; + let (mut lo, mut hi) = ([f64::INFINITY; 2], [f64::NEG_INFINITY; 2]); + for p in outer { + for k in 0..2 { + lo[k] = lo[k].min(p[k]); + hi[k] = hi[k].max(p[k]); + } + } + let (short, long) = ((hi[0] - lo[0]).min(hi[1] - lo[1]), (hi[0] - lo[0]).max(hi[1] - lo[1])); + if short.is_nan() || short <= 0.0 { + return [lo[0].midpoint(hi[0]), lo[1].midpoint(hi[1])]; + } + // Cells start square, at most sixteen along the longer side. + let size = short.max(long / 16.0); + let precision = long / 50.0; + let probe = |center: Point, half: f64| Cell::new(center, half, signed_distance(center, rings)); + let mut queue = BinaryHeap::new(); + let mut h = size / 2.0; + let mut x = lo[0]; + while x < hi[0] { + let mut y = lo[1]; + while y < hi[1] { + queue.push(probe([x + h, y + h], h)); + y += size; + } + x += size; + } + let mut best = probe(centroid(outer), 0.0); + let middle = probe([lo[0].midpoint(hi[0]), lo[1].midpoint(hi[1])], 0.0); + if middle.distance > best.distance { + best = middle; + } + // Each cell probed costs a pass over the rings; cap them so a huge polygon stays bounded. + let mut probes = 0; + while let Some(cell) = queue.pop() { + if cell.distance > best.distance { + best = cell; + } + if cell.max - best.distance <= precision || probes > 4096 { + continue; + } + h = cell.half / 2.0; + for [dx, dy] in [[-1.0, -1.0], [1.0, -1.0], [-1.0, 1.0], [1.0, 1.0]] { + queue.push(probe([cell.center[0] + dx * h, cell.center[1] + dy * h], h)); + probes += 1; + } + } + best.center +} + +/// A square cell of polylabel's search: its center, half its side, the distance from its center to +/// the polygon's edges (negative outside), and the most any point of it could reach. +#[derive(Clone, Copy)] +struct Cell { + center: Point, + half: f64, + distance: f64, + max: f64, +} + +impl Cell { + fn new(center: Point, half: f64, distance: f64) -> Cell { + Cell { center, half, distance, max: distance + half * std::f64::consts::SQRT_2 } + } +} + +impl PartialEq for Cell { + fn eq(&self, other: &Cell) -> bool { + self.max == other.max + } +} + +impl Eq for Cell {} + +impl PartialOrd for Cell { + fn partial_cmp(&self, other: &Cell) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Cell { + fn cmp(&self, other: &Cell) -> std::cmp::Ordering { + self.max.total_cmp(&other.max) + } +} + +/// The distance from `p` to the nearest edge of `rings`: positive inside, negative outside. +fn signed_distance(p: Point, rings: &[Vec]) -> f64 { + let mut inside = false; + let mut nearest = f64::INFINITY; + for ring in rings { + let Some(&last) = ring.last() else { continue }; + let mut a = last; + for &b in ring { + if (a[1] > p[1]) != (b[1] > p[1]) && p[0] < (b[0] - a[0]) * (p[1] - a[1]) / (b[1] - a[1]) + a[0] { + inside = !inside; + } + nearest = nearest.min(segment_distance_squared(p, a, b)); + a = b; + } + } + let distance = nearest.sqrt(); + if inside { distance } else { -distance } +} + +fn segment_distance_squared(p: Point, a: Point, b: Point) -> f64 { + let (dx, dy) = (b[0] - a[0], b[1] - a[1]); + let length = dx * dx + dy * dy; + let t = if length > 0.0 { (((p[0] - a[0]) * dx + (p[1] - a[1]) * dy) / length).clamp(0.0, 1.0) } else { 0.0 }; + let (x, y) = (a[0] + dx * t - p[0], a[1] + dy * t - p[1]); + x * x + y * y +} + +/// A ring's centroid, or its first point when it has no area. +fn centroid(ring: &[Point]) -> Point { + let (mut area, mut x, mut y) = (0.0, 0.0, 0.0); + let Some(&last) = ring.last() else { return [f64::NAN; 2] }; + let mut a = last; + for &b in ring { + let f = a[0] * b[1] - b[0] * a[1]; + x += (a[0] + b[0]) * f; + y += (a[1] + b[1]) * f; + area += f * 3.0; + a = b; + } + if area == 0.0 { ring[0] } else { [x / area, y / area] } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn square(x: f64, y: f64, side: f64) -> Vec { + vec![[x, y], [x + side, y], [x + side, y + side], [x, y + side], [x, y]] + } + + /// The area the triangles of a point list cover. + fn covered(points: &[Point]) -> f64 { + points[1..] + .chunks(3) + .map(|t| { + ((t[1][0] - t[0][0]) * (t[2][1] - t[0][1]) - (t[2][0] - t[0][0]) * (t[1][1] - t[0][1])).abs() / 2.0 + }) + .sum() + } + + #[test] + fn a_square_triangulates_with_its_label_in_the_middle() { + let points = triangles(&[vec![square(0.0, 0.0, 10.0)]], false); + assert_eq!(points.len(), 1 + 6); + assert!((covered(&points) - 100.0).abs() < 1e-9); + let [x, y] = points[0]; + assert!((x - 5.0).abs() < 0.3 && (y - 5.0).abs() < 0.3, "{:?}", points[0]); + } + + #[test] + fn a_half_world_tile_stays_where_it_lies_from_any_corner() { + // A tile at zoom 1 is half the world wide: its edges run exactly 180 degrees. + let corners = [[0.0, 0.0], [180.0, 0.0], [180.0, 80.0], [0.0, 80.0]]; + for start in 0..4 { + let mut ring: Vec = (0..4).map(|k| corners[(start + k) % 4]).collect(); + ring.push(ring[0]); + let points = triangles(&[vec![ring]], true); + assert!((covered(&points) - 180.0 * 80.0).abs() < 1e-6, "from corner {start}"); + assert!(points[1..].iter().all(|p| (0.0..=180.0).contains(&p[0])), "from corner {start}"); + } + } + + #[test] + fn a_hole_moves_the_label_off_it() { + let polygon = vec![square(0.0, 0.0, 10.0), square(3.0, 3.0, 4.0)]; + let points = triangles(&[polygon], false); + assert!((covered(&points) - 84.0).abs() < 1e-9); + let [x, y] = points[0]; + assert!(!(3.0..=7.0).contains(&x) || !(3.0..=7.0).contains(&y), "{:?}", points[0]); + } + + #[test] + fn earth_triangles_split_along_the_grid_without_losing_area() { + let points = triangles(&[vec![square(0.5, 0.5, 9.0)]], true); + assert!((covered(&points) - 81.0).abs() < 1e-6, "{}", covered(&points)); + for t in points[1..].chunks(3) { + for k in 0..2 { + let (lo, hi) = ( + t.iter().map(|p| p[k]).fold(f64::INFINITY, f64::min), + t.iter().map(|p| p[k]).fold(f64::NEG_INFINITY, f64::max), + ); + assert!(hi - lo <= EARTH_STEP + 1e-9, "a piece spans {lo}..{hi}"); + } + } + } + + #[test] + fn rings_across_the_antimeridian_stay_whole() { + let ring = vec![[179.0, 0.0], [-179.0, 0.0], [-179.0, 1.0], [179.0, 1.0], [179.0, 0.0]]; + let points = triangles(&[vec![ring]], true); + assert!((covered(&points) - 2.0).abs() < 1e-9, "{}", covered(&points)); + assert!(points[1..].iter().all(|p| p[0] >= 179.0 && p[0] <= 181.0), "unwrapped east: {points:?}"); + } + + #[test] + fn earth_parts_bend_and_unwrap() { + assert!(earth_parts(&[vec![[0.0, 0.0], [1.0, 1.0]]]).is_none(), "short segments stay"); + let parts = earth_parts(&[vec![[170.0, 10.0], [-170.0, 10.0]]]).expect("crosses"); + assert_eq!(parts[0].first(), Some(&[170.0, 10.0])); + assert_eq!(parts[0].last(), Some(&[190.0, 10.0])); + assert!(parts[0].windows(2).all(|w| (w[1][0] - w[0][0]).abs() <= EARTH_STEP + 1e-9)); + } +} diff --git a/crates/latkit/src/geo/tiles.rs b/crates/latkit/src/geo/tiles.rs new file mode 100644 index 00000000..44d1716d --- /dev/null +++ b/crates/latkit/src/geo/tiles.rs @@ -0,0 +1,211 @@ +//! Vector tiles as data: where tiles come from, and a tile decoded into the rows of the tables marks +//! draw from it. + +use super::mvt::{self, Kind, Property, Shape}; +use crate::data::{Ids, Name, Patch, Table, Values}; +use crate::tiles::TileKey; + +/// Tiles fetched from a URL template, from a TileJSON document or given as one. +#[derive(Clone, PartialEq, Debug)] +pub(crate) struct Template { + pub(crate) url: String, + pub(crate) min_zoom: u8, + pub(crate) max_zoom: u8, + /// West, south, east, north. + pub(crate) bounds: [f64; 4], + /// Whether rows count from the south, as TMS has them. + pub(crate) tms: bool, +} + +/// The whole earth web mercator reaches. +pub(crate) const WORLD: [f64; 4] = [-180.0, -85.051_128_78, 180.0, 85.051_128_78]; + +impl Template { + /// The template `url`, its zooms and bounds as most sources serve them. + pub(crate) fn of(url: &str) -> Template { + Template { url: url.to_owned(), min_zoom: 0, max_zoom: 14, bounds: WORLD, tms: false } + } + + /// The TileJSON document `bytes`, found at `base`. + pub(crate) fn tilejson(bytes: &[u8], base: &str) -> Result { + let json: serde_json::Value = + serde_json::from_slice(bytes).map_err(|e| format!("{base} is not TileJSON: {e}"))?; + let template = json["tiles"][0].as_str().ok_or_else(|| format!("the TileJSON at {base} names no tiles"))?; + if let Some(format) = json["format"].as_str() + && ["png", "jpg", "jpeg", "webp", "avif"].contains(&format) + { + return Err(format!("the TileJSON at {base} names image tiles; only vector tiles draw")); + } + let zoom = |key: &str, or: u8| json[key].as_u64().map_or(or, |z| z.min(24) as u8); + let bounds = json["bounds"] + .as_array() + .filter(|b| b.len() == 4) + .and_then(|b| Some([b[0].as_f64()?, b[1].as_f64()?, b[2].as_f64()?, b[3].as_f64()?])) + .unwrap_or(WORLD); + Ok(Template { + url: crate::url::resolve(base, template), + min_zoom: zoom("minzoom", 0), + max_zoom: zoom("maxzoom", 14), + bounds, + tms: json["scheme"].as_str() == Some("tms"), + }) + } + + /// The URL of tile `key`. + pub(crate) fn url_of(&self, key: TileKey) -> String { + let y = if self.tms { (1_u32 << key.z) - 1 - key.y } else { key.y }; + self.url.replace("{z}", &key.z.to_string()).replace("{x}", &key.x.to_string()).replace("{y}", &y.to_string()) + } +} + +/// A table a tile decodes into: its layer's features of one kind, as table `table`. +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub(crate) struct Decoded { + pub(crate) layer: String, + pub(crate) kind: Kind, + pub(crate) table: Name, +} + +/// Features a tile's table numbers at most; ids beyond its place in the tile never collide. +pub(crate) const FEATURES: u64 = 1 << 20; + +/// Tile `key`'s rows as a patch of every table of `tables`: each feature of the table's layer and +/// kind a row (a multi-point a row per point), its geometry field `geometry` and its properties +/// fields. A row's id is the tile's place along the Hilbert curve times [`FEATURES`], plus its own +/// place among the table's rows. `None` when the bytes are no tile. +pub(crate) fn decode(bytes: &[u8], key: TileKey, tables: &[Decoded]) -> Option { + let bytes = super::gunzipped(bytes).ok()?; + let layers = mvt::decode(&bytes, key)?; + let first = super::pmtiles::tile_id(key) * FEATURES; + let mut patch = Patch::new(); + for decoded in tables { + let Some(layer) = layers.iter().find(|l| l.name == decoded.layer) else { continue }; + let mut shapes: Vec = Vec::new(); + let mut properties: Vec<&[(u32, Property)]> = Vec::new(); + for feature in layer.features.iter().filter(|f| f.shape.kind() == decoded.kind) { + match &feature.shape { + Shape::Points(points) => { + for &p in points { + shapes.push(Shape::Points(vec![p])); + properties.push(&feature.properties); + } + } + shape => { + shapes.push(shape.clone()); + properties.push(&feature.properties); + } + } + } + let count = shapes.len().min(FEATURES as usize); + if count == 0 { + continue; + } + let ids: Vec = (0..count as u64).map(|k| first + k).collect(); + let geometry: Values = match decoded.kind { + Kind::Points => shapes[..count] + .iter() + .map(|s| if let Shape::Points(p) = s { p[0] } else { [f64::NAN; 2] }) + .collect::>() + .into(), + Kind::Lines => shapes + .into_iter() + .take(count) + .map(|s| if let Shape::Lines(parts) = s { parts } else { Vec::new() }) + .collect::>() + .into(), + Kind::Polygons => shapes + .into_iter() + .take(count) + .map(|s| if let Shape::Polygons(polygons) = s { polygons } else { Vec::new() }) + .collect::>() + .into(), + }; + let mut table = Table::new(decoded.table.clone(), Ids::from(ids)).field("geometry", geometry); + for (k, key) in layer.keys.iter().enumerate() { + if key == "geometry" { + continue; + } + let values: Vec> = properties[..count] + .iter() + .map(|props| props.iter().find(|(i, _)| *i as usize == k).map(|(_, v)| v)) + .collect(); + if values.iter().any(Option::is_some) { + table = table.field(key.as_str(), field(&values)); + } + } + patch = patch.set(table); + } + Some(patch) +} + +/// A property's values as a field: numbers where every value present is one, booleans likewise, +/// texts otherwise. +fn field(values: &[Option<&Property>]) -> Values { + let present = || values.iter().flatten(); + if present().all(|v| matches!(v, Property::Number(_))) { + return values + .iter() + .map(|v| v.and_then(|v| if let Property::Number(n) = v { Some(*n) } else { None })) + .collect::>() + .into(); + } + if present().all(|v| matches!(v, Property::Bool(_))) { + return values + .iter() + .map(|v| v.and_then(|v| if let Property::Bool(b) = v { Some(*b) } else { None })) + .collect::>() + .into(); + } + values.iter().map(|v| v.map(text)).collect::>>().into() +} + +/// A property written as text. +pub(crate) fn text(property: &Property) -> String { + match property { + Property::Text(t) => t.clone(), + Property::Number(n) => n.to_string(), + Property::Bool(b) => b.to_string(), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::geo::mvt::tests::{square, tile}; + use crate::{Data, Value}; + + #[test] + fn a_tile_decodes_into_its_tables_rows() { + let key = TileKey { z: 3, x: 2, y: 3 }; + let bytes = tile("water", 3, &square(100, 100, 1000), "bay"); + let tables = [Decoded { layer: "water".into(), kind: Kind::Polygons, table: "water".into() }]; + let patch = decode(&bytes, key, &tables).expect("a tile"); + let mut data = Data::new("base"); + data.apply(patch).expect("valid"); + let water = data.table("water").expect("the table"); + assert_eq!(water.len(), 1); + let id = crate::geo::pmtiles::tile_id(key) * FEATURES; + assert_eq!(water.get(id, "name"), Some(Value::Text("bay".into())), "stable ids"); + assert!(matches!(water.get(id, "geometry"), Some(Value::Polygons(_)))); + let other = [Decoded { layer: "water".into(), kind: Kind::Lines, table: "water".into() }]; + assert!(decode(&bytes, key, &other).expect("a tile").is_empty(), "no lines in it"); + } + + #[test] + fn templates_fill_and_resolve() { + let json = br#"{"tiles": ["/planet/{z}/{x}/{y}.pbf"], "minzoom": 0, "maxzoom": 14, "scheme": "xyz"}"#; + let template = Template::tilejson(json, "https://tiles.example/planet").expect("TileJSON"); + assert_eq!(template.url_of(TileKey { z: 2, x: 1, y: 3 }), "https://tiles.example/planet/2/1/3.pbf"); + let tms = Template { tms: true, ..Template::of("{z}/{x}/{y}") }; + assert_eq!(tms.url_of(TileKey { z: 1, x: 0, y: 0 }), "1/0/1"); + } + + #[test] + fn tile_bounds_meet_their_parents() { + let key = TileKey { z: 1, x: 1, y: 0 }; + let [w, s, e, n] = key.bounds(); + assert_eq!([w, s, e], [0.0, 0.0, 180.0]); + assert!((n - 85.051_128_78).abs() < 1e-6); + assert_eq!(key.children()[3].ancestor(1), key); + } +} diff --git a/crates/latkit/src/gpu/arena.rs b/crates/latkit/src/gpu/arena.rs new file mode 100644 index 00000000..09ba3206 --- /dev/null +++ b/crates/latkit/src/gpu/arena.rs @@ -0,0 +1,517 @@ +//! Data pages on the GPU: one pool of 64 Ki-word chunks in one storage buffer, which doubles as it +//! fills, up to the budget. A chunk is carved into blocks of one power-of-two size, and no page is +//! larger than a chunk: a geometry's points split into pieces of a chunk each. So the room any page +//! leaves serves any other: a chunk whose blocks all come back is carved again for another size. +//! +//! A page is identified by its id, the words of it a program reads, and its piece. Page tables pin +//! the pages they reference, so a page in use is never evicted; unpinned pages stay cached, the least +//! recently used going first when a page needs their room. Uploads stream within a per-frame byte +//! budget. A page that finds no room waits until pins let room go: views plan what they draw to fit +//! the pool, so none waits long. + +use std::collections::hash_map::Entry; +use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque}; + +use rustc_hash::FxBuildHasher; + +use crate::data::{AxisPage, FramePage, PageId, Value, Values}; +use crate::expr::compile::Words; +use crate::gpu::shaders::{MISSING, NONE, POINT_BITS}; +use crate::gpu::work::Queue; + +/// Words in a chunk: the largest block, and the largest page. +pub(crate) const CHUNK_WORDS: u32 = 1 << 16; +/// Bytes in a chunk. +pub(crate) const CHUNK_BYTES: u64 = CHUNK_WORDS as u64 * 4; +const MIN_CLASS_BITS: u32 = 6; +const CLASSES: usize = (16 - MIN_CLASS_BITS + 1) as usize; +const INITIAL_CHUNKS: u32 = 16; +/// Points in a piece of a geometry's points: a chunk of x and y words. +pub(crate) const PIECE_POINTS: usize = 1 << POINT_BITS; + +/// A page as a program reads it. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub(crate) struct PageKey { + pub(crate) page: PageId, + pub(crate) words: Words, + /// The part `f32` drops of an `f64`, rather than the value. + pub(crate) low: bool, + /// Which piece of the page: a geometry's first points, then its points a chunk at a time; 0 + /// for every other page, which is one piece. + pub(crate) piece: u32, +} + +impl PageKey { + /// The one piece of a page that is not a geometry's. + pub(crate) fn of(page: PageId, words: Words, low: bool) -> PageKey { + PageKey { page, words, low, piece: 0 } + } +} + +/// What to upload for a page. +pub(crate) enum Content { + /// Static values, converted to words for `words`. + Values { values: Values, words: Words, low: bool }, + /// A page of samples; one an append opened grows, and only its new tail uploads. + Frames(FramePage), + /// A page of where a level's entries draw along the axis; it grows like a page of samples. + Axis(AxisPage), + /// Words computed on the CPU: text codes, join rows, a geometry's pieces. + Computed(Vec), +} + +impl Content { + /// Words in the page. + fn len(&self) -> u32 { + let len = match self { + Content::Values { values, .. } => values.len(), + Content::Frames(page) => page.read(<[f32]>::len), + Content::Axis(page) => page.words_len(), + Content::Computed(words) => words.len(), + }; + debug_assert!(len <= CHUNK_WORDS as usize, "no page is larger than a chunk"); + len as u32 + } + + /// The page's words from word `from` on: a growing page uploads only its new tail. + fn words(&self, from: usize) -> Vec { + match self { + Content::Values { values, words, low } => page_words(values, *words, *low).split_off(from), + Content::Frames(page) => { + page.read(|values| values[from.min(values.len())..].iter().map(|v| v.to_bits()).collect()) + } + Content::Axis(page) => page.words(from), + Content::Computed(words) => words[from.min(words.len())..].to_vec(), + } + } + + /// The class of the block it takes: a growing page takes a whole chunk to grow into. + fn class(&self, words: u32) -> usize { + match self { + Content::Frames(page) if page.grows() => CLASSES - 1, + Content::Axis(page) if page.grows() => CLASSES - 1, + _ => class_of(words), + } + } +} + +/// The class of a block holding `words`: the power of two at least that large. +fn class_of(words: u32) -> usize { + let bits = words.max(1).next_power_of_two().trailing_zeros().max(MIN_CLASS_BITS); + (bits - MIN_CLASS_BITS) as usize +} + +fn class_words(class: usize) -> u32 { + 1 << (class as u32 + MIN_CLASS_BITS) +} + +/// Blocks of `class` in a chunk. +fn slots(class: usize) -> u32 { + CHUNK_WORDS / class_words(class) +} + +/// What a page uploads as `words` reads it: numbers as `f32`, the low part of `f64`s, point +/// components, or reference rows as `u32`. Missing values are `MISSING`, or `NONE` for rows. +pub(crate) fn page_words(values: &Values, words: Words, low: bool) -> Vec { + let n = values.len(); + let word = |x: f64| { + let hi = x as f32; + if low { (x - f64::from(hi)) as f32 } else { hi }.to_bits() + }; + match words { + Words::Values => values.map_numbers(|x| x.map_or(MISSING, word)), + Words::Bits => values.map_numbers(|x| x.map_or(NONE, |x| x as u32)), + Words::X | Words::Y => { + let component = usize::from(words == Words::Y); + let coords = values.geometry().map(crate::data::Geometry::coords); + (0..n) + .map(|i| match coords { + Some(coords) if values.is_valid(i) && coords[i][component].is_finite() => { + word(coords[i][component]) + } + _ => MISSING, + }) + .collect() + } + Words::Path => unreachable!("a geometry uploads in pieces"), + Words::Codes => unreachable!("text codes upload as words"), + } +} + +/// Points a geometry page's rows take as shaders read them: every coordinate, and a break between a +/// row's parts or rings. +pub(crate) fn path_points(values: &Values) -> usize { + let Some(geometry) = values.geometry() else { return 0 }; + (0..values.len()).filter(|&row| values.is_valid(row)).map(|row| geometry.row_points(row)).sum() +} + +/// A geometry page's pieces, as `lib/read.wesl` reads them: each row's first point, then its points +/// a chunk at a time, every point an x and a y word. A row's parts, or its polygons' rings, are +/// broken by a missing point. +pub(crate) fn path_pieces(values: &Values) -> Vec> { + let mut firsts = Vec::with_capacity(values.len()); + let mut pieces: Vec> = vec![Vec::new()]; + let mut points = 0_u32; + let push = |point: [u32; 2], pieces: &mut Vec>, points: &mut u32| { + if pieces.last().is_some_and(|p| p.len() == 2 * PIECE_POINTS) { + pieces.push(Vec::with_capacity(2 * PIECE_POINTS)); + } + pieces.last_mut().expect("a piece").extend(point); + *points += 1; + }; + let bits = |p: &[f64; 2]| p.map(|v| (v as f32).to_bits()); + for row in 0..values.len() { + firsts.push(points); + let parts: Vec> = match values.get(row) { + Some(Value::Point(p)) => vec![vec![p]], + Some(Value::Path(path)) => vec![path], + Some(Value::Parts(parts)) => parts, + Some(Value::Polygons(polygons)) => polygons.into_iter().flatten().collect(), + _ => Vec::new(), + }; + for (k, part) in parts.iter().enumerate() { + if k > 0 { + push([MISSING, MISSING], &mut pieces, &mut points); + } + for p in part { + push(bits(p), &mut pieces, &mut points); + } + } + } + if pieces.last().is_some_and(Vec::is_empty) { + pieces.pop(); + } + std::iter::once(firsts).chain(pieces).collect() +} + +struct Block { + /// Offset in words, or `NONE` until allocated. + offset: u32, + class: usize, + /// Words uploaded so far. + written: u32, + pins: u32, + /// When it was last unpinned, its place in the LRU. + tick: u64, +} + +/// A chunk of the pool: free, or carved into blocks of one class with a bit for each that is free; +/// the class is the one whose chunks list it. +#[derive(Clone, Copy)] +struct Chunk { + live: u32, + free: [u64; 16], +} + +impl Chunk { + const FREE: Chunk = Chunk { live: 0, free: [0; 16] }; + + /// Takes a free block, returning its slot. + fn take(&mut self) -> u32 { + let word = self.free.iter().position(|&w| w != 0).expect("a chunk listed with room has a free block"); + let bit = self.free[word].trailing_zeros(); + self.free[word] &= !(1 << bit); + self.live += 1; + word as u32 * 64 + bit + } +} + +pub(crate) struct Arena { + buffer: wgpu::Buffer, + chunks: Vec, + /// The most chunks the pool grows to. + limit: u32, + /// Changes whenever the buffer is replaced, so views rebind it. + pub(crate) generation: u64, + /// Free chunks, and each class's chunks with a free block, lowest first so blocks gather low. + free: BTreeSet, + partial: [BTreeSet; CLASSES], + blocks: HashMap, + /// Unpinned, allocated blocks by when they were unpinned. + unpinned: BTreeMap, + tick: u64, + uploads: VecDeque, + contents: HashMap, + /// Bytes of allocated blocks. + resident: u64, + /// Whether the page at the front of the queue found no room, the last time it tried. + starved: bool, +} + +impl Arena { + /// A pool that grows to at most `bytes`, within what the device binds. + pub(crate) fn new(device: &wgpu::Device, bytes: u64) -> Arena { + let limit = limit_of(device, bytes); + let chunks = INITIAL_CHUNKS.min(limit); + Arena { + buffer: create(device, chunks), + chunks: vec![Chunk::FREE; chunks as usize], + limit, + generation: 0, + free: (0..chunks).collect(), + partial: Default::default(), + blocks: HashMap::default(), + unpinned: BTreeMap::new(), + tick: 0, + uploads: VecDeque::new(), + contents: HashMap::default(), + resident: 0, + starved: false, + } + } + + pub(crate) fn buffer(&self) -> &wgpu::Buffer { + &self.buffer + } + + /// Lets the pool grow to at most `bytes` from now on; it never shrinks. + pub(crate) fn set_limit(&mut self, device: &wgpu::Device, bytes: u64) { + self.limit = limit_of(device, bytes).max(self.chunks.len() as u32); + } + + /// The block holding at least `need` words of `key`, or `None` while it uploads. + pub(crate) fn get(&mut self, key: PageKey, need: u32, content: impl FnOnce() -> Content) -> Option { + if let Some(offset) = self.offset(key, need) { + return Some(offset); + } + if let Entry::Vacant(entry) = self.contents.entry(key) { + entry.insert(content()); + self.uploads.push_back(key); + } + None + } + + /// The block holding at least `need` words of `key`, if one does. + pub(crate) fn offset(&self, key: PageKey, need: u32) -> Option { + self.blocks.get(&key).filter(|b| b.offset != NONE && b.written >= need).map(|b| b.offset) + } + + /// Keeps `key` resident while pinned; pins nest. + pub(crate) fn pin(&mut self, key: PageKey) { + let block = self.blocks.entry(key).or_insert(Block { offset: NONE, class: 0, written: 0, pins: 0, tick: 0 }); + if block.pins == 0 && block.offset != NONE { + self.unpinned.remove(&block.tick); + } + block.pins += 1; + } + + pub(crate) fn unpin(&mut self, key: PageKey) { + let Some(block) = self.blocks.get_mut(&key) else { return }; + block.pins -= 1; + if block.pins > 0 { + return; + } + if block.offset == NONE { + self.blocks.remove(&key); + self.contents.remove(&key); + return; + } + self.tick += 1; + block.tick = self.tick; + self.unpinned.insert(self.tick, key); + // Room let go may be what a waiting page needs. + self.starved = false; + } + + /// Whether uploads are waiting that can make progress. + pub(crate) fn uploading(&self) -> bool { + !self.uploads.is_empty() && !self.starved + } + + /// Bytes waiting to upload. + pub(crate) fn pending(&self) -> u64 { + self.contents.values().map(|c| u64::from(c.len()) * 4).sum() + } + + /// Bytes of resident blocks. + pub(crate) fn resident(&self) -> u64 { + self.resident + } + + /// Bytes the pool may grow to. + pub(crate) fn capacity(&self) -> u64 { + u64::from(self.limit) * CHUNK_BYTES + } + + /// Uploads queued pages, at least one and at most `budget` bytes; returns the bytes uploaded. + /// + /// A page that finds no room stays queued at the front, and later pages wait behind it, so the + /// pages of one table upload in order; it tries again once a pin lets room go. + pub(crate) fn pump(&mut self, device: &wgpu::Device, queue: &Queue, budget: u64) -> u64 { + let mut bytes = 0; + while !self.starved + && (bytes == 0 || bytes < budget) + && let Some(key) = self.uploads.pop_front() + { + let Some(content) = self.contents.remove(&key) else { continue }; + let resident = self.blocks.get(&key).filter(|b| b.offset != NONE).map(|b| (b.offset, b.class, b.written)); + let len = content.len(); + let (offset, written) = match resident { + Some((offset, class, written)) if class_words(class) >= len => (offset, written), + _ => { + let Some(offset) = self.place(device, queue, key, content.class(len)) else { + self.contents.insert(key, content); + self.uploads.push_front(key); + self.starved = true; + break; + }; + (offset, 0) + } + }; + let tail = content.words(written as usize); + if !tail.is_empty() { + queue.upload(&self.buffer, u64::from(offset + written) * 4, bytemuck::cast_slice(&tail)); + bytes += tail.len() as u64 * 4; + } + self.blocks.get_mut(&key).expect("placed").written = written + tail.len() as u32; + } + bytes + } + + /// Allocates a block of `class` for `key`, releasing a smaller one it had. + fn place(&mut self, device: &wgpu::Device, queue: &Queue, key: PageKey, class: usize) -> Option { + let offset = self.allocate(device, queue, class, key)?; + if let Some(old) = self.blocks.get(&key).filter(|b| b.offset != NONE) { + let (old_offset, old_class) = (old.offset, old.class); + self.release(old_offset, old_class); + } + let block = self.blocks.entry(key).or_insert(Block { offset: NONE, class, written: 0, pins: 0, tick: 0 }); + let pinned = block.pins > 0; + block.offset = offset; + block.class = class; + block.written = 0; + self.resident += u64::from(class_words(class)) * 4; + if !pinned { + self.tick += 1; + block.tick = self.tick; + self.unpinned.insert(self.tick, key); + } + Some(offset) + } + + fn release(&mut self, offset: u32, class: usize) { + let k = offset / CHUNK_WORDS; + let slot = (offset % CHUNK_WORDS) / class_words(class); + let chunk = &mut self.chunks[k as usize]; + chunk.free[slot as usize / 64] |= 1 << (slot % 64); + chunk.live -= 1; + if chunk.live == 0 { + *chunk = Chunk::FREE; + self.partial[class].remove(&k); + self.free.insert(k); + } else { + self.partial[class].insert(k); + } + self.resident -= u64::from(class_words(class)) * 4; + } + + /// A block of `class`: a free one of its size, a free chunk carved, the pool grown, or room the + /// least recently used unpinned blocks leave, whatever their size; `None` when every block left + /// is pinned. `keep` is the page it is for, which is never evicted for itself. + fn allocate(&mut self, device: &wgpu::Device, queue: &Queue, class: usize, keep: PageKey) -> Option { + loop { + if let Some(&k) = self.partial[class].first() { + let chunk = &mut self.chunks[k as usize]; + let slot = chunk.take(); + if chunk.live == slots(class) { + self.partial[class].remove(&k); + } + return Some(k * CHUNK_WORDS + slot * class_words(class)); + } + if let Some(k) = self.free.pop_first() { + let slots = slots(class); + let mut free = [0_u64; 16]; + for (w, word) in free.iter_mut().enumerate() { + let bits = slots.saturating_sub(w as u32 * 64).min(64); + *word = if bits == 64 { u64::MAX } else { (1 << bits) - 1 }; + } + self.chunks[k as usize] = Chunk { live: 0, free }; + self.partial[class].insert(k); + continue; + } + if self.grow(device, queue) { + continue; + } + let (&tick, &key) = self.unpinned.iter().find(|&(_, k)| *k != keep)?; + self.unpinned.remove(&tick); + let block = self.blocks.remove(&key).expect("listed"); + self.release(block.offset, block.class); + } + } + + /// Doubles the buffer up to the limit, copying what it holds. + fn grow(&mut self, device: &wgpu::Device, queue: &Queue) -> bool { + let before = self.chunks.len() as u32; + let chunks = (before * 2).min(self.limit); + if chunks <= before { + return false; + } + let buffer = create(device, chunks); + let mut encoder = + device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("latkit arena") }); + encoder.copy_buffer_to_buffer(&self.buffer, 0, &buffer, 0, self.buffer.size()); + queue.submit([encoder.finish()]); + self.buffer = buffer; + self.chunks.resize(chunks as usize, Chunk::FREE); + self.free.extend(before..chunks); + self.generation += 1; + true + } +} + +/// Chunks a pool of at most `bytes` holds, within what the device binds: at least the first ones. +fn limit_of(device: &wgpu::Device, bytes: u64) -> u32 { + let limits = device.limits(); + let bytes = bytes.min(limits.max_storage_buffer_binding_size).min(limits.max_buffer_size); + ((bytes / CHUNK_BYTES).min(u64::from(u32::MAX / CHUNK_WORDS)) as u32).max(INITIAL_CHUNKS) +} + +fn create(device: &wgpu::Device, chunks: u32) -> wgpu::Buffer { + device.create_buffer(&wgpu::BufferDescriptor { + label: Some("latkit pages"), + size: u64::from(chunks) * CHUNK_BYTES, + usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::COPY_SRC, + mapped_at_creation: false, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn classes_round_up_to_powers_of_two() { + assert_eq!(class_of(1), 0); + assert_eq!(class_words(class_of(64)), 64); + assert_eq!(class_words(class_of(65)), 128); + assert_eq!(class_words(class_of(65536)), 65536); + assert_eq!(CLASSES, 11); + assert_eq!(slots(0), 1024); + assert_eq!(slots(CLASSES - 1), 1); + } + + #[test] + fn page_words_split_doubles() { + let values = Values::from(vec![Some(1.0_f64 + 1e-9), None]); + let hi = page_words(&values, Words::Values, false); + let lo = page_words(&values, Words::Values, true); + assert_eq!(hi[1], MISSING); + let back = f64::from(f32::from_bits(hi[0])) + f64::from(f32::from_bits(lo[0])); + assert!((back - (1.0 + 1e-9)).abs() < 1e-15); + } + + #[test] + fn geometry_pieces_hold_a_chunk_of_points_each() { + let long: Vec<[f64; 2]> = (0..PIECE_POINTS + 10).map(|i| [i as f64, 0.0]).collect(); + let parts = vec![vec![[0.0, 0.0], [1.0, 1.0]], vec![[2.0, 2.0]]]; + let values = Values::from(vec![vec![long.clone()], Vec::new(), parts]); + let pieces = path_pieces(&values); + assert_eq!(pieces[0], vec![0, (PIECE_POINTS + 10) as u32, (PIECE_POINTS + 10) as u32], "first points"); + assert_eq!(pieces.len(), 3, "the first points, then two pieces of points"); + assert_eq!(pieces[1].len(), 2 * PIECE_POINTS); + // The last row's two parts are broken by a missing point. + assert_eq!(pieces[2].len(), 2 * (10 + 2 + 1 + 1)); + assert_eq!(path_points(&values), PIECE_POINTS + 10 + 4); + assert!(pieces.iter().all(|p| p.len() <= CHUNK_WORDS as usize)); + } +} diff --git a/crates/latkit/src/gpu/atlas.rs b/crates/latkit/src/gpu/atlas.rs new file mode 100644 index 00000000..71bb27c7 --- /dev/null +++ b/crates/latkit/src/gpu/atlas.rs @@ -0,0 +1,446 @@ +//! Text on the GPU: runs set once by the host at `TEXT_BASE`, turned into distance fields reaching +//! `TEXT_SPREAD` texels past the text's edge, and packed on shelves of one texture. A distance field +//! draws crisp at any size and gives halos for free, so a run is set once whatever size it shows at. +//! The host sets coverage; the GPU makes the fields of every run set in a frame at once, before the +//! frame draws (`compute/fields.wesl`). When no shelf has room, the shelf used least recently is +//! cleared for the new run; only when none fits does the packing start over. A run counts as used +//! when it is set and whenever labels in view show it, so what the view shows stays. Views follow +//! evictions to drop what they pointed at. + +use std::collections::HashMap; +use std::sync::Arc; + +use crate::gpu::pipelines::Pipelines; +use crate::gpu::shaders::{FIELD_AT, FIELD_COLUMNS, FIELD_COVERAGE, FIELD_HEIGHT, FIELD_ROW, FIELD_WIDTH, FIELD_WORDS}; +use crate::gpu::shaders::{Shader, TEXT_BASE, TEXT_SPREAD}; +use crate::gpu::work::{Count, Counters, Queue}; +use crate::host::{Host, Raster, TextRun}; + +/// Texels across the atlas: room for about 1,400 labels of ten characters at the base size. +const SIZE: u32 = 4096; +/// Texels between runs, so filtering never reads a neighbor. +const GAP: u32 = 1; +/// Texels of field around a run's coverage. +const PAD: u32 = TEXT_SPREAD as u32; +/// Runs whose fields one dispatch makes at most: one workgroup layer each. +const RUNS: usize = 65_535; + +/// Where a run lies in the atlas. +#[derive(Clone, Copy, PartialEq, Debug)] +pub(crate) struct Glyphs { + /// Left, top, right, and bottom, texels, reaching `TEXT_SPREAD` past the text on every side. + pub(crate) rect: [u32; 4], + /// Texels from the top of the rectangle to the baseline. + pub(crate) baseline: f32, +} + +impl Glyphs { + /// The rectangle as the two corner words shaders read: 16 bits of x, then 16 of y. + pub(crate) fn corners(&self) -> [u32; 2] { + let [l, t, r, b] = self.rect; + [l | t << 16, r | b << 16] + } +} + +/// A run table entry for `run` before it is set: the estimate flag, then the corner a rectangle of +/// its size by a rough measure would reach from the atlas's own corner, so its label can be placed +/// while only labels that show have their texts set. +pub(crate) fn estimate(run: &TextRun) -> [u32; 2] { + let size = run.size_px as f32; + let width = run.text.chars().count() as f32 * 0.58 * size; + let (width, lines) = match run.max_width.map(|w| w as f32) { + Some(wrap) if width > wrap => (wrap, (width / wrap).ceil()), + _ => (width, 1.0), + }; + // The host pads each run a little, and the field reaches past it. + let pad = 2.0 * (2.0 + PAD as f32); + let w = ((width + pad).ceil() as u32).min(0xffff); + let h = ((lines * 1.25 * size + pad).ceil() as u32).min(0xffff); + [crate::gpu::shaders::TEXT_ESTIMATE, w | h << 16] +} + +/// The run the atlas sets for `text` shown at `size`, wrapping at `max_width`, both length units: set +/// at the base size, wrapping where `max_width` falls at it. A sheet measures the same run it draws. +pub(crate) fn run(text: Arc, font: Arc, size: f32, max_width: Option) -> TextRun { + let wrap = max_width.map(|w| (w * TEXT_BASE / size.max(1e-3)).round().max(1.0) as u32); + TextRun { text, font, size_px: TEXT_BASE as u32, max_width: wrap } +} + +struct Shelf { + top: u32, + height: u32, + used: u32, + /// When a run on it was last asked for. + tick: u64, +} + +/// A run set whose field waits to be made: its coverage, and the shelf and corner its field fills. +struct Waiting { + raster: Raster, + shelf: usize, + corner: [u32; 2], +} + +pub(crate) struct Atlas { + pub(crate) errors: Vec, + texture: wgpu::Texture, + pub(crate) view: wgpu::TextureView, + shelves: Vec, + /// Every run asked for, and its shelf; `None` when the host could not set it. + runs: HashMap>, + /// Runs set whose fields the next frame makes. + waiting: Vec, + /// What making fields works in, and its bind group. + work: Option<(wgpu::Buffer, wgpu::BindGroup)>, + /// Counts the frames runs are asked for in. + clock: u64, + /// Changes whenever runs are evicted, so what pointed at them looks again. + pub(crate) evictions: u64, + /// What counts the texts the host is asked to set. + counters: Arc, +} + +impl Atlas { + pub(crate) fn new(device: &wgpu::Device, counters: Arc) -> Atlas { + let texture = device.create_texture(&wgpu::TextureDescriptor { + label: Some("latkit text"), + size: wgpu::Extent3d { width: SIZE, height: SIZE, depth_or_array_layers: 1 }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::R8Unorm, + usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST | wgpu::TextureUsages::COPY_SRC, + view_formats: &[], + }); + let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); + Atlas { + errors: Vec::new(), + texture, + view, + shelves: Vec::new(), + runs: HashMap::new(), + waiting: Vec::new(), + work: None, + clock: 0, + evictions: 0, + counters, + } + } + + /// Starts a frame: runs asked for from now on count as used in it. + pub(crate) fn tick(&mut self) { + self.clock += 1; + } + + /// Where `run` lies, set by `host` the first time it is asked for; its field is made before the + /// frame draws. + pub(crate) fn text(&mut self, host: Option<&dyn Host>, run: &TextRun) -> Option { + if let Some(found) = self.runs.get(run) { + let (glyphs, shelf) = (*found)?; + self.shelves[shelf].tick = self.clock; + return Some(glyphs); + } + let host = host?; + self.counters.add(Count::Texts, 1); + let raster = match host.rasterize(run) { + Ok(raster) => raster, + Err(error) => { + self.errors.push(error); + return None; + } + }; + let placed = self.hold(raster); + if placed.is_some() { + self.runs.insert(run.clone(), placed); + } + placed.map(|(glyphs, _)| glyphs) + } + + /// Places `raster`'s field, which waits to be made: where it lies, and its shelf. + fn hold(&mut self, raster: Raster) -> Option<(Glyphs, usize)> { + let [w, h] = raster.size; + let (width, height) = (w.saturating_add(2 * PAD), h.saturating_add(2 * PAD)); + if w == 0 || h == 0 || width > SIZE || height > SIZE { + self.errors.push(crate::Error::Limit("text raster does not fit the atlas".into())); + return None; + } + if raster.coverage.len() != w as usize * h as usize { + self.errors.push(crate::Error::invalid("text raster coverage does not match its size")); + return None; + } + let (shelf, [left, top]) = self.place(width, height); + let glyphs = Glyphs { rect: [left, top, left + width, top + height], baseline: raster.baseline + PAD as f32 }; + self.waiting.push(Waiting { raster, shelf, corner: [left, top] }); + Some((glyphs, shelf)) + } + + /// Counts `run` as used now: labels in view show it. + pub(crate) fn touch(&mut self, run: &TextRun) { + if let Some(Some((_, shelf))) = self.runs.get(run) { + self.shelves[*shelf].tick = self.clock; + } + } + + /// Whether `glyphs` still lie where they were for `run`. + pub(crate) fn holds(&self, run: &TextRun, glyphs: Glyphs) -> bool { + matches!(self.runs.get(run), Some(Some((g, _))) if *g == glyphs) + } + + /// Makes the fields of the runs set since last time, recorded into `encoder` before what draws + /// them: their coverage goes up, each column and then each row takes its least squared distances + /// within the spread, and each field copies into its place. + pub(crate) fn lay( + &mut self, + device: &wgpu::Device, + queue: &Queue, + encoder: &mut wgpu::CommandEncoder, + pipelines: &mut Pipelines, + ) { + if self.waiting.is_empty() { + return; + } + let rest = self.waiting.split_off(self.waiting.len().min(RUNS)); + let laid = std::mem::replace(&mut self.waiting, rest); + let size = |w: &Waiting| w.raster.size.map(|n| n + 2 * PAD); + // The runs and their coverage go up; their columns and fields follow. A field starts where a + // copy out of it may, and its rows are as far apart as copies need. + let mut runs = vec![[0_u32; FIELD_WORDS as usize]; laid.len()]; + let mut coverage = Vec::new(); + let mut at = laid.len() as u32 * FIELD_WORDS; + for (w, run) in laid.iter().zip(&mut runs) { + run[FIELD_COVERAGE as usize] = at + (coverage.len() / 4) as u32; + [run[FIELD_WIDTH as usize], run[FIELD_HEIGHT as usize]] = w.raster.size; + coverage.extend_from_slice(&w.raster.coverage); + coverage.resize(coverage.len().next_multiple_of(4), 0); + } + at += (coverage.len() / 4) as u32; + for (w, run) in laid.iter().zip(&mut runs) { + let [width, height] = size(w); + run[FIELD_COLUMNS as usize] = at; + at += width * height; + } + for (w, run) in laid.iter().zip(&mut runs) { + let [width, height] = size(w); + at = at.next_multiple_of(COPY_ALIGN / 4); + run[FIELD_AT as usize] = at; + run[FIELD_ROW as usize] = width.next_multiple_of(wgpu::COPY_BYTES_PER_ROW_ALIGNMENT) / 4; + at += run[FIELD_ROW as usize] * height; + } + let (buffer, group) = self.fit_work(device, pipelines, u64::from(at) * 4); + let mut upload: Vec = bytemuck::cast_slice(&runs).to_vec(); + upload.extend_from_slice(&coverage); + queue.write_buffer_in(device, encoder, &buffer, 0, &upload); + let most = laid.iter().map(size).fold([0, 0], |m, s| [m[0].max(s[0]), m[1].max(s[1])]); + { + let mut pass = encoder.begin_compute_pass(&wgpu::ComputePassDescriptor { + label: Some("latkit fields"), + timestamp_writes: None, + }); + pass.set_bind_group(0, &pipelines.empty, &[]); + pass.set_bind_group(1, &pipelines.empty, &[]); + pass.set_bind_group(2, &group, &[]); + pass.set_pipeline(&pipelines.compute(device, Shader::Fields, "columns")); + pass.dispatch_workgroups(most[0].div_ceil(16), most[1].div_ceil(16), laid.len() as u32); + pass.set_pipeline(&pipelines.compute(device, Shader::Fields, "rows")); + pass.dispatch_workgroups(most[0].div_ceil(4).div_ceil(16), most[1].div_ceil(16), laid.len() as u32); + } + for (w, run) in laid.iter().zip(&runs) { + let [width, height] = size(w); + encoder.copy_buffer_to_texture( + wgpu::TexelCopyBufferInfo { + buffer: &buffer, + layout: wgpu::TexelCopyBufferLayout { + offset: u64::from(run[FIELD_AT as usize]) * 4, + bytes_per_row: Some(run[FIELD_ROW as usize] * 4), + rows_per_image: Some(height), + }, + }, + wgpu::TexelCopyTextureInfo { + texture: &self.texture, + mip_level: 0, + origin: wgpu::Origin3d { x: w.corner[0], y: w.corner[1], z: 0 }, + aspect: wgpu::TextureAspect::All, + }, + wgpu::Extent3d { width, height, depth_or_array_layers: 1 }, + ); + } + } + + /// The buffer making fields works in, holding at least `bytes`, and its bind group. + fn fit_work( + &mut self, + device: &wgpu::Device, + pipelines: &mut Pipelines, + bytes: u64, + ) -> (wgpu::Buffer, wgpu::BindGroup) { + if let Some((buffer, group)) = self.work.as_ref().filter(|(buffer, _)| buffer.size() >= bytes) { + return (buffer.clone(), group.clone()); + } + let buffer = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("latkit fields"), + size: (bytes + bytes / 2).next_multiple_of(256), + usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_SRC | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + let group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("latkit fields"), + layout: &pipelines.pass_layout(device, Shader::Fields), + entries: &[wgpu::BindGroupEntry { binding: 0, resource: buffer.as_entire_binding() }], + }); + self.work = Some((buffer.clone(), group.clone())); + (buffer, group) + } + + /// The shelf and top left of room for `width` by `height` texels. + fn place(&mut self, width: u32, height: u32) -> (usize, [u32; 2]) { + let fits = |s: &Shelf| s.height >= height && s.height <= height + height / 2 + 4; + let at = self.shelves.iter().position(|s| fits(s) && s.used + width <= SIZE); + let at = at.or_else(|| { + let top = self.shelves.last().map_or(0, |s| s.top + s.height + GAP); + (top + height <= SIZE).then(|| { + self.shelves.push(Shelf { top, height, used: 0, tick: self.clock }); + self.shelves.len() - 1 + }) + }); + let at = at.or_else(|| { + // Clear the shelf of this height used least recently, if not in this frame. + let clock = self.clock; + let oldest = (0..self.shelves.len()) + .filter(|&i| fits(&self.shelves[i]) && self.shelves[i].tick < clock) + .min_by_key(|&i| self.shelves[i].tick)?; + self.runs.retain(|_, placed| !matches!(placed, Some((_, shelf)) if *shelf == oldest)); + self.waiting.retain(|w| w.shelf != oldest); + self.shelves[oldest].used = 0; + self.evictions += 1; + Some(oldest) + }); + let at = at.unwrap_or_else(|| { + // Nothing fits: start over. + self.runs.clear(); + self.waiting.clear(); + self.shelves.clear(); + self.evictions += 1; + self.shelves.push(Shelf { top: 0, height, used: 0, tick: self.clock }); + 0 + }); + let shelf = &mut self.shelves[at]; + let corner = [shelf.used, shelf.top]; + shelf.used += width + GAP; + shelf.tick = self.clock; + (at, corner) + } +} + +/// Bytes a copy out of a buffer into a texture may start at a multiple of, on every backend. +const COPY_ALIGN: u32 = 512; + +#[cfg(test)] +mod tests { + use super::*; + + /// The field of `width` by `height` coverage bytes as it is defined, texel by texel: the least + /// squared distance to a texel inside and outside over every texel within reach. + fn exact(coverage: &[u8], width: usize, height: usize) -> Vec { + let pad = i64::from(PAD); + let (w, h) = (width as i64 + 2 * pad, height as i64 + 2 * pad); + let own = |x: i64, y: i64| { + let (cx, cy) = (x - pad, y - pad); + let a = if (0..width as i64).contains(&cx) && (0..height as i64).contains(&cy) { + f64::from(coverage[(cy * width as i64 + cx) as usize]) / 255.0 + } else { + 0.0 + }; + let d = 0.5 - a; + if a >= 1.0 { + (0.0, f64::INFINITY) + } else if a <= 0.0 { + (f64::INFINITY, 0.0) + } else { + (if d > 0.0 { d * d } else { 0.0 }, if d < 0.0 { d * d } else { 0.0 }) + } + }; + let mut field = Vec::new(); + for y in 0..h { + for x in 0..w { + let (mut inside, mut outside) = (f64::INFINITY, f64::INFINITY); + for qy in (y - pad).max(0)..=(y + pad).min(h - 1) { + for qx in (x - pad).max(0)..=(x + pad).min(w - 1) { + let (i, o) = own(qx, qy); + let r = ((qx - x).pow(2) + (qy - y).pow(2)) as f64; + (inside, outside) = (inside.min(i + r), outside.min(o + r)); + } + } + let d = outside.sqrt() - inside.sqrt(); + field.push(((0.5 + d / (2.0 * f64::from(TEXT_SPREAD))).clamp(0.0, 1.0) * 255.0).round() as u8); + } + } + field + } + + #[test] + fn fields_made_on_the_gpu_are_the_exact_field() { + let gpu = match pollster::block_on(crate::Gpu::new()) { + Ok(gpu) => gpu, + Err(error) if std::env::var_os("LATKIT_REQUIRE_GPU").is_some() => panic!("GPU required: {error}"), + Err(_) => return, + }; + // A soft disc, a hairline of half coverage, a faint speck, and an odd width. + let (width, height) = (41, 26); + let mut coverage = vec![0_u8; width * height]; + for y in 0..height { + for x in 0..width { + let edge = ((x as f64 - 12.0).hypot(y as f64 - 13.0) - 8.0).clamp(-1.0, 1.0); + coverage[y * width + x] = ((0.5 - edge / 2.0) * 255.0).round() as u8; + } + } + for y in 3..23 { + coverage[y * width + 30] = 128; + } + coverage[5 * width + 37] = 40; + let mut inner = gpu.0.lock(); + let raster = Raster { size: [width as u32, height as u32], coverage: coverage.clone(), baseline: 20.0 }; + let (glyphs, _) = inner.atlas.hold(raster).expect("placed"); + let (device, queue) = (&gpu.0.device, &gpu.0.queue); + let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor::default()); + let crate::gpu::Inner { atlas, pipelines, .. } = &mut *inner; + atlas.lay(device, queue, &mut encoder, pipelines); + // Another view can lay a smaller batch into the same scratch buffer before submission. + // Its upload must not replace the first batch's inputs before that batch has executed. + atlas.hold(Raster { size: [9, 7], coverage: vec![255; 63], baseline: 5.0 }).expect("second batch"); + atlas.lay(device, queue, &mut encoder, pipelines); + let [l, t, r, b] = glyphs.rect; + let (w, h) = (r - l, b - t); + let row = w.next_multiple_of(wgpu::COPY_BYTES_PER_ROW_ALIGNMENT); + let readback = device.create_buffer(&wgpu::BufferDescriptor { + label: None, + size: u64::from(row * h), + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ, + mapped_at_creation: false, + }); + encoder.copy_texture_to_buffer( + wgpu::TexelCopyTextureInfo { + texture: &atlas.texture, + mip_level: 0, + origin: wgpu::Origin3d { x: l, y: t, z: 0 }, + aspect: wgpu::TextureAspect::All, + }, + wgpu::TexelCopyBufferInfo { + buffer: &readback, + layout: wgpu::TexelCopyBufferLayout { offset: 0, bytes_per_row: Some(row), rows_per_image: Some(h) }, + }, + wgpu::Extent3d { width: w, height: h, depth_or_array_layers: 1 }, + ); + queue.submit([encoder.finish()]); + let slice = readback.slice(..); + slice.map_async(wgpu::MapMode::Read, |result| result.expect("mapped")); + let wait = wgpu::PollType::Wait { submission_index: None, timeout: Some(std::time::Duration::from_secs(10)) }; + device.poll(wait).expect("the GPU finishes"); + let texels = slice.get_mapped_range().expect("mapped"); + let made: Vec = texels.chunks(row as usize).flat_map(|line| &line[..w as usize]).copied().collect(); + let want = exact(&coverage, width, height); + let off = made.iter().zip(&want).filter(|(a, b)| a.abs_diff(**b) > 1).count(); + assert_eq!(off, 0, "every texel within a step of the exact field"); + let deepest = made.iter().max().copied().unwrap_or(0); + assert!(made.contains(&0) && deepest > 224, "the field runs from nothing outside to deep inside: {deepest}"); + } +} diff --git a/crates/latkit/src/gpu/colormaps.rs b/crates/latkit/src/gpu/colormaps.rs new file mode 100644 index 00000000..cd78b52a --- /dev/null +++ b/crates/latkit/src/gpu/colormaps.rs @@ -0,0 +1,84 @@ +//! Colormaps on the GPU: one 256-texel layer per colormap a program uses, in one texture array. + +use std::collections::HashMap; + +use crate::expr::{Colormap, ColormapKey}; +use crate::gpu::work::Queue; +use crate::{Error, Result}; + +const INITIAL_LAYERS: u32 = 16; + +pub(crate) struct Colormaps { + texture: wgpu::Texture, + pub(crate) view: wgpu::TextureView, + layers: HashMap, + capacity: u32, + /// Changes whenever the texture is replaced, so views rebind it. + pub(crate) generation: u64, +} + +fn create(device: &wgpu::Device, layers: u32) -> (wgpu::Texture, wgpu::TextureView) { + let texture = device.create_texture(&wgpu::TextureDescriptor { + label: Some("latkit colormaps"), + size: wgpu::Extent3d { width: 256, height: 1, depth_or_array_layers: layers }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8Unorm, + usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST | wgpu::TextureUsages::COPY_SRC, + view_formats: &[], + }); + let view = texture.create_view(&wgpu::TextureViewDescriptor { + dimension: Some(wgpu::TextureViewDimension::D2Array), + ..Default::default() + }); + (texture, view) +} + +impl Colormaps { + pub(crate) fn new(device: &wgpu::Device) -> Colormaps { + let (texture, view) = create(device, INITIAL_LAYERS); + Colormaps { texture, view, layers: HashMap::new(), capacity: INITIAL_LAYERS, generation: 0 } + } + + /// The layer holding `colormap`, uploading it the first time. + pub(crate) fn layer(&mut self, device: &wgpu::Device, queue: &Queue, colormap: &Colormap) -> Result { + let key = colormap.key(); + if let Some(&layer) = self.layers.get(&key) { + return Ok(layer); + } + let layer = self.layers.len() as u32; + if layer >= self.capacity { + let capacity = (self.capacity * 2).min(device.limits().max_texture_array_layers); + if layer >= capacity { + return Err(Error::Limit(format!("more than {capacity} distinct colormaps").into())); + } + let (texture, view) = create(device, capacity); + let mut encoder = + device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("latkit colormaps") }); + encoder.copy_texture_to_texture( + self.texture.as_image_copy(), + texture.as_image_copy(), + wgpu::Extent3d { width: 256, height: 1, depth_or_array_layers: self.capacity }, + ); + queue.submit([encoder.finish()]); + self.texture = texture; + self.view = view; + self.capacity = capacity; + self.generation += 1; + } + queue.write_texture( + wgpu::TexelCopyTextureInfo { + texture: &self.texture, + mip_level: 0, + origin: wgpu::Origin3d { x: 0, y: 0, z: layer }, + aspect: wgpu::TextureAspect::All, + }, + bytemuck::cast_slice(colormap.texels()), + wgpu::TexelCopyBufferLayout { offset: 0, bytes_per_row: Some(256 * 4), rows_per_image: Some(1) }, + wgpu::Extent3d { width: 256, height: 1, depth_or_array_layers: 1 }, + ); + self.layers.insert(key, layer); + Ok(layer) + } +} diff --git a/crates/latkit/src/gpu/dictionary.rs b/crates/latkit/src/gpu/dictionary.rs new file mode 100644 index 00000000..f029d56f --- /dev/null +++ b/crates/latkit/src/gpu/dictionary.rs @@ -0,0 +1,125 @@ +//! Text on the GPU: each text field's distinct texts get codes in the order they are first seen. +//! Codes only ever grow, so a page's codes never change and upload once. A page is coded once; one +//! written over a page coded takes its codes and codes only the rows written. + +use std::collections::HashMap; +use std::sync::Arc; + +use rustc_hash::FxBuildHasher; + +use crate::Name; +use crate::data::{Page, PageId, Values}; +use crate::gpu::shaders::MISSING; + +/// Pages a dictionary keeps the codes of: past them, it forgets them all. +const PAGES: usize = 256; + +#[derive(Default)] +pub(crate) struct Dictionaries { + fields: HashMap<(Name, Name, Name), Dictionary, FxBuildHasher>, +} + +#[derive(Default)] +pub(crate) struct Dictionary { + codes: HashMap, u32, FxBuildHasher>, + /// Each code's text. + texts: Vec>, + /// The codes of pages coded, by page. + pages: HashMap, FxBuildHasher>, +} + +impl Dictionaries { + /// The dictionary of field `field` of `table` in dataset `data`. + pub(crate) fn field(&mut self, data: &Name, table: &Name, field: &Name) -> &mut Dictionary { + self.fields.entry((data.clone(), table.clone(), field.clone())).or_default() + } +} + +impl Dictionary { + /// The codes of `page`, its texts added: `f32` words, `MISSING` where missing. A page coded + /// before costs nothing; one written over a page coded costs the rows written. + pub(crate) fn codes(&mut self, page: &Page) -> Arc<[u32]> { + if let Some(codes) = self.pages.get(&page.id) { + return codes.clone(); + } + let len = page.values.len(); + // The nearest page it was written over whose codes are kept, and the rows written since. + let mut reused = None; + let mut at = page.written.as_deref(); + while let Some(written) = at { + if let Some(codes) = self.pages.get(&written.from).filter(|codes| codes.len() == len) { + reused = page.rows_since(written.from).map(|rows| (written.from, codes.clone(), rows)); + break; + } + at = written.before.as_deref(); + } + let codes: Arc<[u32]> = match reused { + Some((from, before, rows)) => { + // The page written over is usually written over no more. + self.pages.remove(&from); + let mut codes = before.to_vec(); + for row in rows { + codes[row as usize] = self.code(&page.values, row as usize); + } + codes.into() + } + None => (0..len).map(|i| self.code(&page.values, i)).collect(), + }; + if self.pages.len() >= PAGES { + self.pages.clear(); + } + self.pages.insert(page.id, codes.clone()); + codes + } + + /// The code of value `i` of `values` as an `f32` word, its text added when it is new. + fn code(&mut self, values: &Values, i: usize) -> u32 { + let Some(text) = values.text().filter(|_| values.is_valid(i)) else { return MISSING }; + let t = text.get(i); + let code = if let Some(&code) = self.codes.get(t) { + code + } else { + let code = self.codes.len() as u32; + let text: Arc = t.into(); + self.codes.insert(text.clone(), code); + self.texts.push(text); + code + }; + (code as f32).to_bits() + } + + /// Codes given so far. + pub(crate) fn len(&self) -> usize { + self.texts.len() + } + + /// The text of `code`. + pub(crate) fn text(&self, code: u32) -> Option<&Arc> { + self.texts.get(code as usize) + } + + /// The code of `text` as an `f32` word; one no text has when it was never seen. + pub(crate) fn code_of(&self, text: &str) -> u32 { + self.codes.get(text).map_or(f32::NAN.to_bits(), |&code| (code as f32).to_bits()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::data::Column; + + #[test] + fn a_page_written_over_one_coded_codes_only_its_rows() { + let column = Column::new(&Values::from(vec!["a", "b", "c"])); + let mut dictionary = Dictionary::default(); + let first = dictionary.codes(&column.pages()[0]); + let written = column.write(3, &[(1, 0)], &Column::new(&Values::from(vec!["d"]))).expect("texts"); + let second = dictionary.codes(&written.pages()[0]); + let text = |word: u32| dictionary.text(f32::from_bits(word) as u32).map(ToString::to_string); + assert_eq!((second[0], second[2]), (first[0], first[2]), "rows not written keep their codes"); + assert_eq!(text(second[1]).as_deref(), Some("d")); + assert_eq!(dictionary.len(), 4); + assert!(Arc::ptr_eq(&dictionary.codes(&written.pages()[0]), &second), "a page is coded once"); + } +} diff --git a/crates/latkit/src/gpu/icons.rs b/crates/latkit/src/gpu/icons.rs new file mode 100644 index 00000000..b6b907c3 --- /dev/null +++ b/crates/latkit/src/gpu/icons.rs @@ -0,0 +1,118 @@ +//! Icons on the GPU: every image an icon marker shows, as a layer of one texture array of a common +//! size, scaled to fit. Markers name their images; the same image shares its layer. + +use std::collections::HashMap; +use std::sync::Arc; + +use crate::gpu::work::Queue; + +/// Texels across an icon layer. +const SIZE: u32 = 64; + +pub(crate) struct Icons { + texture: wgpu::Texture, + pub(crate) view: wgpu::TextureView, + /// Each image's layer, by the address of its pixels. + layers: HashMap, u32)>, + capacity: u32, + /// Changes whenever the texture is replaced, so views rebind it. + pub(crate) generation: u64, +} + +fn create(device: &wgpu::Device, layers: u32) -> (wgpu::Texture, wgpu::TextureView) { + let texture = device.create_texture(&wgpu::TextureDescriptor { + label: Some("latkit icons"), + size: wgpu::Extent3d { width: SIZE, height: SIZE, depth_or_array_layers: layers }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8Unorm, + usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST | wgpu::TextureUsages::COPY_SRC, + view_formats: &[], + }); + let view = texture.create_view(&wgpu::TextureViewDescriptor { + dimension: Some(wgpu::TextureViewDimension::D2Array), + ..Default::default() + }); + (texture, view) +} + +impl Icons { + pub(crate) fn new(device: &wgpu::Device) -> Icons { + let (texture, view) = create(device, 1); + Icons { texture, view, layers: HashMap::new(), capacity: 1, generation: 0 } + } + + /// The layer of each of `images`, uploading the ones not yet on the GPU. + pub(crate) fn layers(&mut self, device: &wgpu::Device, queue: &Queue, images: &[crate::Image]) -> Vec { + let needed = self.layers.len() as u32 + images.len() as u32; + if needed > self.capacity { + let capacity = needed.next_power_of_two().min(device.limits().max_texture_array_layers); + let (texture, view) = create(device, capacity); + let mut encoder = + device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("latkit icons") }); + encoder.copy_texture_to_texture( + self.texture.as_image_copy(), + texture.as_image_copy(), + wgpu::Extent3d { width: SIZE, height: SIZE, depth_or_array_layers: self.capacity }, + ); + queue.submit([encoder.finish()]); + self.texture = texture; + self.view = view; + self.capacity = capacity; + self.generation += 1; + } + images + .iter() + .map(|image| { + let key = image.rgba.as_ptr() as usize; + if let Some((_, layer)) = self.layers.get(&key) { + return *layer; + } + let layer = (self.layers.len() as u32).min(self.capacity - 1); + let texels = fit(image); + queue.write_texture( + wgpu::TexelCopyTextureInfo { + texture: &self.texture, + mip_level: 0, + origin: wgpu::Origin3d { x: 0, y: 0, z: layer }, + aspect: wgpu::TextureAspect::All, + }, + &texels, + wgpu::TexelCopyBufferLayout { + offset: 0, + bytes_per_row: Some(SIZE * 4), + rows_per_image: Some(SIZE), + }, + wgpu::Extent3d { width: SIZE, height: SIZE, depth_or_array_layers: 1 }, + ); + self.layers.insert(key, (image.rgba.clone(), layer)); + layer + }) + .collect() + } +} + +/// `image` scaled to `SIZE` square by its nearest texels, centered with its aspect kept. +fn fit(image: &crate::Image) -> Vec { + let [w, h] = image.size.map(|v| v.max(1)); + let scale = f64::from(w.max(h)) / f64::from(SIZE); + let (fw, fh) = (f64::from(w) / scale, f64::from(h) / scale); + let (x0, y0) = ((f64::from(SIZE) - fw) / 2.0, (f64::from(SIZE) - fh) / 2.0); + let mut out = vec![0_u8; (SIZE * SIZE * 4) as usize]; + for y in 0..SIZE { + for x in 0..SIZE { + let u = (f64::from(x) + 0.5 - x0) * scale; + let v = (f64::from(y) + 0.5 - y0) * scale; + if u < 0.0 || v < 0.0 || u >= f64::from(w) || v >= f64::from(h) { + continue; + } + let from = ((v as u32 * w + u as u32) * 4) as usize; + let to = ((y * SIZE + x) * 4) as usize; + if let Some(texel) = image.rgba.get(from..from + 4) { + out[to..to + 4].copy_from_slice(texel); + } + } + } + out +} diff --git a/crates/latkit/src/gpu/mod.rs b/crates/latkit/src/gpu/mod.rs new file mode 100644 index 00000000..40429190 --- /dev/null +++ b/crates/latkit/src/gpu/mod.rs @@ -0,0 +1,367 @@ +//! The GPU: one device shared by every view, with the page arena, pipelines, colormaps, and text +//! dictionaries every view draws from. + +pub(crate) mod arena; +pub(crate) mod atlas; +pub(crate) mod colormaps; +pub(crate) mod dictionary; +pub(crate) mod icons; +pub(crate) mod pipelines; +pub(crate) mod readback; +pub(crate) mod shaders; +pub(crate) mod work; + +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::{Arc, Mutex, MutexGuard, PoisonError}; + +use arena::Arena; +use atlas::Atlas; +use colormaps::Colormaps; +use dictionary::Dictionaries; +use icons::Icons; +use pipelines::Pipelines; +use readback::Readbacks; +use work::{Counters, Queue, Work}; + +use crate::host::Host; +use crate::{Error, Result}; + +/// The format views draw canvases and shots in, so both share one set of pipelines: every WebGPU +/// canvas takes it. +pub(crate) const FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Bgra8Unorm; + +/// The GPU device that views draw with. Cheap to clone; views of one `Gpu` share uploaded data. +#[derive(Clone)] +pub struct Gpu(pub(crate) Arc); + +/// Receives events from an application-owned wgpu device without taking over its callbacks. +#[derive(Clone)] +pub struct DeviceEvents { + lost: Arc, + errors: Arc>>, +} + +impl DeviceEvents { + /// Reports device loss to every view sharing this GPU. + pub fn lost(&self) { + self.lost.store(true, Ordering::Release); + } + + /// Reports an uncaptured device error to latkit's views. + pub fn error(&self, error: &wgpu::Error) { + self.errors + .lock() + .unwrap_or_else(PoisonError::into_inner) + .push(Error::Unsupported(format!("the GPU refused: {error}").into())); + } +} + +pub(crate) struct Shared { + /// The instance and adapter `Gpu::new` created the device from, for surfaces. + pub(crate) instance: Option, + pub(crate) adapter: Option, + pub(crate) device: wgpu::Device, + /// The queue, counting what is written through it. + pub(crate) queue: Queue, + /// What the GPU did, counted: views count the rows they evaluate and the jobs they hand out + /// through it, and [`Gpu::work`] reads it. + pub(crate) counters: Arc, + pub(crate) sampler: wgpu::Sampler, + pub(crate) lost: Arc, + /// Errors the device reported outside any scope, for views to tell. + pub(crate) errors: Arc>>, + inner: Mutex, +} + +pub(crate) struct Inner { + pub(crate) arena: Arena, + pub(crate) pipelines: Pipelines, + pub(crate) colormaps: Colormaps, + pub(crate) dictionaries: Dictionaries, + pub(crate) atlas: Atlas, + pub(crate) icons: Icons, + pub(crate) readbacks: Readbacks, + pub(crate) host: Option>, + pub(crate) budget: Budget, + /// What each view plans within: its share of the budget. + pub(crate) ledger: Ledger, +} + +/// The share of the budget the views of a GPU plan what they draw within, between them; the rest holds +/// pages a new version uploads while the one it replaces is still drawn, and pages cached. +const PLANNED: f64 = 0.5; + +/// What each view of a GPU plans what it draws within: shares of one part of the budget, granted +/// max-min fair, so views together never plan past it however many there are. Pages several views +/// draw are on the GPU once, so they count once, split between those views. +#[derive(Default)] +pub(crate) struct Ledger { + /// What each view would draw whole, by view. + asks: rustc_hash::FxHashMap, +} + +/// What a view would draw whole: bytes of its own, and the pages it reads that any view drawing the +/// same data shares. +#[derive(Clone, Default, PartialEq, Debug)] +pub(crate) struct Ask { + /// Bytes no other view holds: its marks' state, focus, labels, traces, and derived columns. + pub(crate) own: f64, + /// Each piece any view drawing it shares, by what it holds, and its bytes. + pub(crate) shared: Vec<(u64, f64)>, +} + +impl Ledger { + /// Records what view `view` would draw whole, `whole` bytes as it counts them, and grants it its + /// share of what `budget` plans, as a part of `whole`. Each view asks its own bytes and a split of + /// each piece it shares between the views drawing it; each gets all it asks while an even split + /// of what is left covers it, else that split, views asking less having what they ask first. + pub(crate) fn grant(&mut self, view: u64, whole: f64, ask: Ask, budget: u64) -> f64 { + self.asks.insert(view, ask); + let mut sharing: rustc_hash::FxHashMap = rustc_hash::FxHashMap::default(); + for ask in self.asks.values() { + for (piece, _) in &ask.shared { + *sharing.entry(*piece).or_default() += 1.0; + } + } + let split = |ask: &Ask| ask.own + ask.shared.iter().map(|(piece, bytes)| bytes / sharing[piece]).sum::(); + let mine = split(&self.asks[&view]); + let mut asks: Vec = self.asks.values().map(split).collect(); + asks.sort_by(f64::total_cmp); + let mut left = budget as f64 * PLANNED; + for (i, &each) in asks.iter().enumerate() { + let even = left / (asks.len() - i) as f64; + if each > even { + return if mine > even { whole * even / mine } else { whole }; + } + left -= each; + } + whole + } + + /// Forgets view `view`, which no longer draws. + pub(crate) fn leave(&mut self, view: u64) { + self.asks.remove(&view); + } +} + +/// How much GPU memory latkit uses. +#[derive(Clone, Copy, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub struct Budget { + /// Bytes the data every view of the `Gpu` draws may take on the GPU: its pages, and each view's + /// rows. A view draws a table too large for its share through the tiles the camera asks for, so + /// what it draws always fits; pages no view draws stay cached in the room left, the least + /// recently drawn going first. By default half the device's largest storage buffer. The pool of + /// pages grows as data needs it, and never shrinks: set the budget before data draws. + pub bytes: u64, + /// Bytes uploaded per frame at most; larger data streams in over frames. + pub upload_per_frame: u64, +} + +impl Budget { + /// Half the largest storage buffer `device` binds, and 32 MiB uploaded per frame. + fn of(device: &wgpu::Device) -> Budget { + let limits = device.limits(); + let largest = limits.max_storage_buffer_binding_size.min(limits.max_buffer_size); + Budget { bytes: largest / 2, upload_per_frame: 32 << 20 } + } +} + +impl Gpu { + /// Creates a device on the best adapter: WebGPU in browsers, Vulkan, Metal, or DX12 natively. + pub async fn new() -> Result { + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { + backends: wgpu::Backends::PRIMARY | wgpu::Backends::BROWSER_WEBGPU, + ..wgpu::InstanceDescriptor::new_without_display_handle() + }); + let adapter = instance + .request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::HighPerformance, + ..Default::default() + }) + .await + .map_err(|e| Error::Unsupported(format!("no GPU adapter: {e}").into()))?; + let supported = adapter.limits(); + let limits = wgpu::Limits { + max_storage_buffer_binding_size: supported.max_storage_buffer_binding_size, + max_buffer_size: supported.max_buffer_size, + max_storage_buffers_per_shader_stage: supported.max_storage_buffers_per_shader_stage, + ..wgpu::Limits::default() + }; + // Timestamps, where the adapter writes them, measure what each frame costs the GPU. + let features = adapter.features() & wgpu::Features::TIMESTAMP_QUERY; + let (device, queue) = adapter + .request_device(&wgpu::DeviceDescriptor { + label: Some("latkit"), + required_features: features, + required_limits: limits, + ..Default::default() + }) + .await + .map_err(|e| Error::Unsupported(format!("no GPU device: {e}").into()))?; + Ok(Gpu::create(Some(instance), Some(adapter), device, queue)) + } + + /// Draws with an application-owned device and queue without replacing their callbacks. + /// Forward device loss and uncaptured errors through [`Gpu::device_events`]. Clone this + /// `Gpu` to share its caches and budget between views. + pub fn from_wgpu(device: wgpu::Device, queue: wgpu::Queue) -> Result { + if !wgpu::Limits::default().check_limits(&device.limits()) { + return Err(Error::Unsupported("the device does not meet WebGPU's default limits".into())); + } + Ok(Gpu::create(None, None, device, queue)) + } + + /// A lightweight sink for the application's existing device callbacks; it does not own the GPU. + pub fn device_events(&self) -> DeviceEvents { + DeviceEvents { lost: self.0.lost.clone(), errors: self.0.errors.clone() } + } + + fn create( + instance: Option, + adapter: Option, + device: wgpu::Device, + queue: wgpu::Queue, + ) -> Gpu { + let lost = Arc::new(AtomicBool::new(false)); + let errors: Arc>> = Arc::default(); + if instance.is_some() { + let events = DeviceEvents { lost: lost.clone(), errors: errors.clone() }; + let loss = events.clone(); + device.set_device_lost_callback(move |_, _| loss.lost()); + device.on_uncaptured_error(Arc::new(move |error| events.error(&error))); + } + let sampler = device.create_sampler(&wgpu::SamplerDescriptor { + label: Some("latkit ramp"), + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::MipmapFilterMode::Linear, + ..Default::default() + }); + let budget = Budget::of(&device); + let counters = Arc::new(Counters::default()); + let inner = Inner { + arena: Arena::new(&device, budget.bytes), + pipelines: Pipelines::new(&device, counters.clone()), + colormaps: Colormaps::new(&device), + dictionaries: Dictionaries::default(), + atlas: Atlas::new(&device, counters.clone()), + icons: Icons::new(&device), + readbacks: Readbacks::counted(counters.clone()), + host: None, + budget, + ledger: Ledger::default(), + }; + let queue = Queue::new(queue, counters.clone()); + #[cfg_attr( + target_arch = "wasm32", + allow(clippy::arc_with_non_send_sync, reason = "WebGPU objects stay on the one thread a page has") + )] + let shared = Arc::new(Shared { + instance, + adapter, + device, + queue, + counters, + sampler, + lost, + errors, + inner: Mutex::new(inner), + }); + Gpu(shared) + } + + /// What this GPU did since it was made, counted exactly. It repeats wherever the budget, the + /// device's limits, and the frames drawn do, so tests and benchmarks hold it to what it was. + /// Subtract two for what happened between. + pub fn work(&self) -> Work { + self.0.counters.work() + } + + /// The device. + pub fn device(&self) -> &wgpu::Device { + &self.0.device + } + + /// The queue. + pub fn queue(&self) -> &wgpu::Queue { + &self.0.queue + } + + /// The instance a `Gpu` from [`Gpu::new`] was created with, for creating surfaces it can draw to. + pub fn instance(&self) -> Option<&wgpu::Instance> { + self.0.instance.as_ref() + } + + /// The adapter a `Gpu` from [`Gpu::new`] was created on, for a surface's capabilities. + pub fn adapter(&self) -> Option<&wgpu::Adapter> { + self.0.adapter.as_ref() + } + + /// Sets how much GPU memory latkit uses; bytes past what the device binds are not used. + pub fn set_budget(&self, budget: Budget) { + let mut inner = self.0.lock(); + inner.arena.set_limit(&self.0.device, budget.bytes); + inner.budget = budget; + } + + /// How much GPU memory latkit uses. + pub fn budget(&self) -> Budget { + self.0.lock().budget + } + + /// Gives views the platform's services: setting text, and doing jobs off the frame. + pub fn set_host(&self, host: impl Host) { + self.0.lock().host = Some(Arc::new(host)); + } + + /// Whether the device was lost; drawing then does nothing, and a new `Gpu` is needed. + pub fn lost(&self) -> bool { + self.0.lost.load(Ordering::Acquire) + } +} + +impl Shared { + pub(crate) fn lock(&self) -> MutexGuard<'_, Inner> { + self.inner.lock().unwrap_or_else(PoisonError::into_inner) + } +} + +impl std::fmt::Debug for Gpu { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Gpu").field("budget", &self.budget()).field("lost", &self.lost()).finish() + } +} + +#[cfg(test)] +mod tests { + use super::{Ask, Ledger}; + + fn own(bytes: f64) -> Ask { + Ask { own: bytes, shared: Vec::new() } + } + + #[test] + fn views_share_the_planned_budget_max_min_fair() { + let mut ledger = Ledger::default(); + let grant = |ledger: &mut Ledger, view, bytes| ledger.grant(view, bytes, own(bytes), 1000); + assert_eq!(grant(&mut ledger, 1, 100.0), 100.0, "a view asking less than half the budget has all it asks"); + assert_eq!(grant(&mut ledger, 2, 900.0), 400.0, "the next has what is left"); + assert_eq!(grant(&mut ledger, 3, 900.0), 200.0, "two large views split what the small one leaves"); + ledger.leave(2); + assert_eq!(grant(&mut ledger, 3, 900.0), 400.0, "a view that leaves gives its share back"); + } + + #[test] + fn pages_views_share_count_once() { + let mut ledger = Ledger::default(); + // Eight views of one dataset: 300 bytes of shared pages each reads, and 20 of its own. + let ask = Ask { own: 20.0, shared: vec![(7, 300.0)] }; + let shares: Vec = (0..8).map(|view| ledger.grant(view, 320.0, ask.clone(), 1000)).collect(); + assert_eq!(shares[7], 320.0, "300 + 8 × 20 fits the 500 planned: every view draws whole"); + // Two views of other data each, too large together: each has the same part of what it asks. + let mut ledger = Ledger::default(); + ledger.grant(1, 400.0, Ask { own: 0.0, shared: vec![(1, 400.0)] }, 1000); + assert_eq!(ledger.grant(2, 400.0, Ask { own: 0.0, shared: vec![(2, 400.0)] }, 1000), 250.0); + } +} diff --git a/crates/latkit/src/gpu/pipelines.rs b/crates/latkit/src/gpu/pipelines.rs new file mode 100644 index 00000000..036dacf2 --- /dev/null +++ b/crates/latkit/src/gpu/pipelines.rs @@ -0,0 +1,592 @@ +//! Pipelines, kept by [`Variant`]. A view asks for every pipeline its scene can use the first time +//! it draws into a target, and a shot for what it composes with, all at once ([`Pipelines::ask`]): +//! in a browser each then compiles off the GPU's thread, side by side with the rest, and what uses it +//! waits until it landed, so no frame waits on a compile. Making it afterwards finds it compiled. +//! Natively a pipeline is made in process where first used, which costs as little. Every pipeline +//! shares the view and mark group layouts; each shader's pass group comes from its WGSL. + +use std::collections::HashMap; +use std::future::Future; +use std::pin::Pin; +use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; +use std::sync::{Arc, Mutex, PoisonError}; +use std::task::{Context, Poll, Waker}; + +use super::shaders::{Binding, MARK_GROUP, PATH_ENDS, Shader, VIEW_GROUP}; +use super::work::{Count, Counters}; +use crate::Error; +use crate::view::DEPTH; + +/// A check of a custom marker's shader, resolving to its error if it has one: sent between threads +/// natively, kept on the page's one thread in browsers. +#[cfg(not(target_arch = "wasm32"))] +type Check = Pin> + Send>>; +#[cfg(target_arch = "wasm32")] +type Check = Pin>>>; + +/// A custom marker's pipeline, compiled from its source the first time a view draws it. +struct Custom { + pipeline: wgpu::RenderPipeline, + check: Option, + failed: bool, +} + +/// One pipeline: a shader's entry point made for one primitive's geometry (its `PROBED`) and one +/// kind of path (its `PATH`), and for a render shader, the format and samples per pixel it draws into. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub(crate) struct Variant { + shader: Shader, + entry: &'static str, + primitive: u32, + path: u32, + target: Option<(wgpu::TextureFormat, u32)>, +} + +impl Variant { + /// `shader` drawing into `format` with `samples` per pixel. + pub(crate) fn draw(shader: Shader, format: wgpu::TextureFormat, samples: u32) -> Variant { + Variant { shader, entry: "vertex", primitive: 0, path: PATH_ENDS, target: Some((format, samples)) } + } + + /// `shader`'s compute entry point `entry`. + pub(crate) fn compute(shader: Shader, entry: &'static str) -> Variant { + Variant { shader, entry, primitive: 0, path: PATH_ENDS, target: None } + } + + /// The probe program made for marks of `primitive` (a `POINTS`, `STROKES`, or `TRIANGLES` code), + /// which answers every question a step at a time. + pub(crate) fn probe(shader: Shader, primitive: u32) -> Variant { + Variant { shader, entry: "answer", primitive, path: PATH_ENDS, target: None } + } + + /// The variant whose strokes read `path`, one of the `PATH_` codes. + #[must_use] + pub(crate) fn path(mut self, path: u32) -> Variant { + self.path = path; + self + } + + /// The pipeline constants its shader declares, set. + fn constants(&self) -> Vec<(&'static str, f64)> { + let value = |name: &str| match name { + "PROBED" => self.primitive, + "PATH" => self.path, + other => unreachable!("no value for the pipeline constant {other}"), + }; + self.shader.source().overrides.iter().map(|&name| (name, f64::from(value(name)))).collect() + } +} + +/// A pipeline asked for ahead: a variant of one of latkit's shaders, or of a custom marker's, whose +/// WGSL follows its shader's. +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub(crate) enum Asked { + Shader(Variant), + Custom(Arc, Variant), +} + +impl Asked { + /// Bytes of WGSL it compiles from: the more, the longer it takes. + pub(crate) fn size(&self) -> usize { + match self { + Asked::Shader(variant) => variant.shader.source().size(), + Asked::Custom(source, variant) => variant.shader.source().size() + source.len(), + } + } +} + +/// A pipeline asked for ahead: whether it compiled then, off the GPU's thread, whether that landed, +/// and what waits for it to. +#[derive(Default)] +struct Ahead { + compiled: AtomicBool, + landed: AtomicBool, + waiting: Mutex>, +} + +impl Ahead { + fn landed(&self) -> bool { + self.landed.load(Ordering::Acquire) + } + + /// Waits for it: `waker` wakes as it lands. + fn wait(&self, waker: &Waker) { + self.waiting.lock().unwrap_or_else(PoisonError::into_inner).push(waker.clone()); + } + + /// Lands it, counted by `landed`, and wakes what waits. + fn land(&self, landed: &AtomicU64) { + self.landed.store(true, Ordering::Release); + landed.fetch_add(1, Ordering::AcqRel); + for waker in self.waiting.lock().unwrap_or_else(PoisonError::into_inner).drain(..) { + waker.wake(); + } + } +} + +pub(crate) struct Pipelines { + pub(crate) view_layout: wgpu::BindGroupLayout, + pub(crate) mark_layout: wgpu::BindGroupLayout, + /// What a shader reading neither shared group binds in their place. + pub(crate) empty: wgpu::BindGroup, + empty_layout: wgpu::BindGroupLayout, + pass_layouts: HashMap, wgpu::BindGroupLayout>, + modules: HashMap, + render: HashMap, + compute: HashMap, + custom: HashMap<(Arc, Variant), Custom>, + /// What views and shots asked for ahead, each with its compile. + asked: HashMap>, + /// How many compiles asked for ahead landed, and in a browser how many are under way. + landed: Arc, + #[cfg(all(feature = "web", target_arch = "wasm32"))] + compiling: Arc, + /// What counts the pipelines compiled. + counters: Arc, +} + +/// Shaders that draw into the shadow map, custom markers' included. +const CASTERS: [Shader; 5] = + [Shader::PointsCast, Shader::StrokesCast, Shader::TrianglesCast, Shader::Shade, Shader::PointsCustomCast]; +/// The probe a frame of `samples` per pixel reads its depth with. +pub(crate) fn probe(samples: u32) -> Shader { + if samples > 1 { Shader::ProbeMultisampled } else { Shader::Probe } +} + +/// How a render shader's vertices assemble. +fn topology(shader: Shader) -> wgpu::PrimitiveTopology { + // Custom markers draw as points do. + match shader { + Shader::Backdrop | Shader::Triangles | Shader::TrianglesCast | Shader::Shade => { + wgpu::PrimitiveTopology::TriangleList + } + _ => wgpu::PrimitiveTopology::TriangleStrip, + } +} + +/// Whether a shader draws into the shadow map, which has no depth. +fn casts(shader: Shader) -> bool { + CASTERS.contains(&shader) +} + +/// How a render shader meets depth, which is reversed: the backdrop writes the globe's, triangles +/// write theirs, the overlay and labels ignore it, and every other mark draws where nothing nearer +/// was drawn. +fn depth(shader: Shader) -> Option { + if casts(shader) { + return None; + } + let compare = match shader { + Shader::Backdrop | Shader::Overlay | Shader::Glyphs => wgpu::CompareFunction::Always, + _ => wgpu::CompareFunction::GreaterEqual, + }; + Some(wgpu::DepthStencilState { + format: DEPTH, + depth_write_enabled: Some(matches!(shader, Shader::Triangles | Shader::Backdrop)), + depth_compare: Some(compare), + stencil: wgpu::StencilState::default(), + bias: wgpu::DepthBiasState::default(), + }) +} + +/// How a shader's fragments blend: premultiplied over what is drawn; casters keep the least of each +/// channel; map levels replace. +fn blend(shader: Shader) -> Option { + let component = |src, dst, operation| wgpu::BlendComponent { src_factor: src, dst_factor: dst, operation }; + match shader { + Shader::Shade => None, + Shader::PointsCast | Shader::StrokesCast | Shader::TrianglesCast | Shader::PointsCustomCast => { + let least = component(wgpu::BlendFactor::One, wgpu::BlendFactor::One, wgpu::BlendOperation::Min); + Some(wgpu::BlendState { color: least, alpha: least }) + } + _ => { + let over = + component(wgpu::BlendFactor::One, wgpu::BlendFactor::OneMinusSrcAlpha, wgpu::BlendOperation::Add); + Some(wgpu::BlendState { color: over, alpha: over }) + } + } +} + +fn layout(device: &wgpu::Device, label: &str, bindings: &[Binding]) -> wgpu::BindGroupLayout { + let entries: Vec<_> = bindings.iter().map(Binding::layout_entry).collect(); + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some(label), entries: &entries }) +} + +impl Pipelines { + pub(crate) fn new(device: &wgpu::Device, counters: Arc) -> Pipelines { + let empty_layout = layout(device, "latkit empty", &[]); + let empty = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("latkit empty"), + layout: &empty_layout, + entries: &[], + }); + Pipelines { + view_layout: layout(device, "latkit view", VIEW_GROUP), + mark_layout: layout(device, "latkit mark", MARK_GROUP), + empty, + empty_layout, + pass_layouts: HashMap::new(), + modules: HashMap::new(), + render: HashMap::new(), + compute: HashMap::new(), + custom: HashMap::new(), + asked: HashMap::new(), + landed: Arc::default(), + #[cfg(all(feature = "web", target_arch = "wasm32"))] + compiling: Arc::default(), + counters, + } + } + + /// Asks for each of `needs` not yet asked for: in a browser it compiles now, off the GPU's thread + /// and side by side with the rest, and `waker` wakes as each lands. A view asks for everything its + /// scene can use at once, so nothing it does later compiles where it is used. + pub(crate) fn ask(&mut self, device: &wgpu::Device, needs: &[Asked], waker: &Waker) { + for need in needs { + if let Some(ahead) = self.asked.get(need) { + if !ahead.landed() { + ahead.wait(waker); + } + continue; + } + let ahead = Arc::new(Ahead::default()); + self.asked.insert(need.clone(), ahead.clone()); + if !self.compile_ahead(device, need, &ahead, waker) { + ahead.land(&self.landed); + } + } + } + + /// Makes the shader modules `needs` compile from, ahead of asking for them: a browser reads a + /// module's WGSL on its GPU thread as it is made, so what a view asks for later is read before + /// it draws anything. + pub(crate) fn read(&mut self, device: &wgpu::Device, needs: &[Asked]) { + for need in needs { + if let Asked::Shader(variant) = need { + self.module(device, variant.shader); + } + } + } + + /// Whether every one of `needs`, asked for, has landed: what uses them can be made without a + /// compile. + pub(crate) fn ready(&self, needs: &[Asked]) -> bool { + needs.iter().all(|need| self.asked.get(need).is_some_and(|ahead| ahead.landed())) + } + + /// How many compiles asked for ahead have landed so far: what waits on one sees it change. + pub(crate) fn landed(&self) -> u64 { + self.landed.load(Ordering::Acquire) + } + + /// Compiles asked for ahead still under way. + #[cfg(all(feature = "web", target_arch = "wasm32"))] + pub(crate) fn compiling(&self) -> u64 { + self.compiling.load(Ordering::Acquire) + } + + /// Starts compiling `need` off the GPU's thread, where a browser can, with `waker` waiting for it: + /// whether it did. + #[cfg_attr( + not(all(target_arch = "wasm32", feature = "web")), + expect(clippy::unused_self, reason = "only a browser's device compiles ahead") + )] + fn compile_ahead(&mut self, device: &wgpu::Device, need: &Asked, ahead: &Arc, waker: &Waker) -> bool { + #[cfg(all(target_arch = "wasm32", feature = "web"))] + { + let Some(promise) = compiled::capture(device, || self.create(device, need)) else { return false }; + self.counters.add(Count::Pipelines, 1); + ahead.compiled.store(true, Ordering::Release); + ahead.wait(waker); + let (ahead, landed, compiling) = (ahead.clone(), self.landed.clone(), self.compiling.clone()); + compiling.fetch_add(1, Ordering::AcqRel); + wasm_bindgen_futures::spawn_local(async move { + // A descriptor the browser refuses lands too: making it then tells why, as it did. + let _ = wasm_bindgen_futures::JsFuture::from(promise).await; + compiling.fetch_sub(1, Ordering::AcqRel); + ahead.land(&landed); + }); + true + } + #[cfg(not(all(target_arch = "wasm32", feature = "web")))] + { + let _ = (device, need, ahead, waker); + false + } + } + + /// Makes `need` through wgpu, neither kept nor counted: what compiling it ahead captures. A + /// custom marker's WGSL fails in its own scope, so only making it for real tells why. + #[cfg(all(target_arch = "wasm32", feature = "web"))] + fn create(&mut self, device: &wgpu::Device, need: &Asked) { + match need { + Asked::Shader(variant) if variant.target.is_some() => { + let module = self.module(device, variant.shader); + drop(self.pipeline(device, *variant, &module)); + } + Asked::Shader(variant) => drop(self.compute_made(device, *variant)), + Asked::Custom(source, variant) => { + let scope = device.push_error_scope(wgpu::ErrorFilter::Validation); + let module = custom_module(device, source, variant.shader); + drop(self.pipeline(device, *variant, &module)); + drop(scope.pop()); + } + } + } + + /// Counts a pipeline made for `need`: compiled now unless it compiled when asked for, and late + /// unless it was asked for at all. + fn count(&self, need: &Asked) { + let ahead = self.asked.get(need); + if !ahead.is_some_and(|ahead| ahead.compiled.load(Ordering::Acquire)) { + self.counters.add(Count::Pipelines, 1); + } + if ahead.is_none() { + self.counters.add(Count::Late, 1); + } + } + + /// The layout of `shader`'s pass group; shaders with the same bindings share one. + pub(crate) fn pass_layout(&mut self, device: &wgpu::Device, shader: Shader) -> wgpu::BindGroupLayout { + let entries: Vec<_> = shader.source().pass.iter().map(Binding::layout_entry).collect(); + self.pass_layouts + .entry(entries) + .or_insert_with_key(|entries| { + device + .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: Some("latkit pass"), entries }) + }) + .clone() + } + + fn module(&mut self, device: &wgpu::Device, shader: Shader) -> wgpu::ShaderModule { + self.modules + .entry(shader) + .or_insert_with(|| { + let source = shader.source(); + device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some(source.label), + source: wgpu::ShaderSource::Wgsl(source.wgsl().into()), + }) + }) + .clone() + } + + /// The layout of `shader`'s pipelines: the view and mark groups, empty where it reads neither, then + /// its pass group. + fn pipeline_layout(&mut self, device: &wgpu::Device, shader: Shader) -> wgpu::PipelineLayout { + let pass = (!shader.source().pass.is_empty()).then(|| self.pass_layout(device, shader)); + let mut groups = if shader.source().shared { + vec![Some(&self.view_layout), Some(&self.mark_layout)] + } else { + vec![Some(&self.empty_layout), Some(&self.empty_layout)] + }; + if let Some(pass) = &pass { + groups.push(Some(pass)); + } + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some(shader.source().label), + bind_group_layouts: &groups, + immediate_size: 0, + }) + } + + /// The pipeline drawing a custom marker of `source` with `shader` (one of the custom variants), + /// or `None` once its WGSL failed to compile. + pub(crate) fn custom( + &mut self, + device: &wgpu::Device, + source: &str, + shader: Shader, + format: wgpu::TextureFormat, + samples: u32, + ) -> Option { + let key = (Arc::::from(source), Variant::draw(shader, format, samples)); + if let Some(custom) = self.custom.get(&key) { + return (!custom.failed).then(|| custom.pipeline.clone()); + } + self.count(&Asked::Custom(key.0.clone(), key.1)); + let scope = device.push_error_scope(wgpu::ErrorFilter::Validation); + let module = custom_module(device, source, shader); + let pipeline = self.pipeline(device, key.1, &module); + let check: Check = Box::pin(scope.pop()); + let custom = Custom { pipeline: pipeline.clone(), check: Some(check), failed: false }; + self.custom.insert(key, custom); + Some(pipeline) + } + + /// Errors custom markers' shaders turned out to have since last asked. + pub(crate) fn custom_errors(&mut self) -> Vec { + let mut context = Context::from_waker(Waker::noop()); + let mut errors = Vec::new(); + for custom in self.custom.values_mut() { + let Some(check) = &mut custom.check else { continue }; + if let Poll::Ready(error) = check.as_mut().poll(&mut context) { + custom.check = None; + if let Some(error) = error { + custom.failed = true; + errors.push(Error::invalid(format!("the custom marker does not compile: {error}")).at("marker")); + } + } + } + errors + } + + /// The pipeline drawing `shader` into `format` with `samples` per pixel. + pub(crate) fn render( + &mut self, + device: &wgpu::Device, + shader: Shader, + format: wgpu::TextureFormat, + samples: u32, + ) -> wgpu::RenderPipeline { + self.render_pipeline(device, Variant::draw(shader, format, samples)) + } + + /// The render pipeline `variant` names. + pub(crate) fn render_pipeline(&mut self, device: &wgpu::Device, variant: Variant) -> wgpu::RenderPipeline { + if let Some(pipeline) = self.render.get(&variant) { + return pipeline.clone(); + } + self.count(&Asked::Shader(variant)); + let module = self.module(device, variant.shader); + let pipeline = self.pipeline(device, variant, &module); + self.render.insert(variant, pipeline.clone()); + pipeline + } + + fn pipeline( + &mut self, + device: &wgpu::Device, + variant: Variant, + module: &wgpu::ShaderModule, + ) -> wgpu::RenderPipeline { + let shader = variant.shader; + let (format, samples) = variant.target.expect("a render variant"); + let layout = self.pipeline_layout(device, shader); + let constants = variant.constants(); + let options = || wgpu::PipelineCompilationOptions { constants: &constants, ..Default::default() }; + device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some(shader.source().label), + layout: Some(&layout), + vertex: wgpu::VertexState { + module, + entry_point: Some("vertex"), + compilation_options: options(), + buffers: &[], + }, + primitive: wgpu::PrimitiveState { topology: topology(shader), ..Default::default() }, + depth_stencil: depth(shader), + multisample: wgpu::MultisampleState { count: samples, ..Default::default() }, + fragment: Some(wgpu::FragmentState { + module, + entry_point: Some("fragment"), + compilation_options: options(), + targets: &[Some(wgpu::ColorTargetState { + format, + blend: blend(shader), + write_mask: wgpu::ColorWrites::ALL, + })], + }), + multiview_mask: None, + cache: None, + }) + } + + /// The compute pipeline of `shader`'s entry point `entry`. + pub(crate) fn compute( + &mut self, + device: &wgpu::Device, + shader: Shader, + entry: &'static str, + ) -> wgpu::ComputePipeline { + self.compute_pipeline(device, Variant::compute(shader, entry)) + } + + /// The compute pipeline `variant` names. + pub(crate) fn compute_pipeline(&mut self, device: &wgpu::Device, variant: Variant) -> wgpu::ComputePipeline { + if let Some(pipeline) = self.compute.get(&variant) { + return pipeline.clone(); + } + self.count(&Asked::Shader(variant)); + let pipeline = self.compute_made(device, variant); + self.compute.insert(variant, pipeline.clone()); + pipeline + } + + fn compute_made(&mut self, device: &wgpu::Device, variant: Variant) -> wgpu::ComputePipeline { + let module = self.module(device, variant.shader); + let layout = self.pipeline_layout(device, variant.shader); + let constants = variant.constants(); + device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { + label: Some(variant.entry), + layout: Some(&layout), + module: &module, + entry_point: Some(variant.entry), + compilation_options: wgpu::PipelineCompilationOptions { constants: &constants, ..Default::default() }, + cache: None, + }) + } +} + +/// The module of a custom marker of `source` drawn with `shader`: its shader's WGSL, then the marker's. +fn custom_module(device: &wgpu::Device, source: &str, shader: Shader) -> wgpu::ShaderModule { + device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("latkit custom marker"), + source: wgpu::ShaderSource::Wgsl(format!("{}\n{source}", shader.source().wgsl()).into()), + }) +} + +/// Compiling ahead in a browser. A browser compiles a pipeline made through `createRenderPipeline` +/// on the GPU's thread, holding back every frame and readback behind it, but one made through its +/// async twin on worker threads, side by side with others; Chrome keeps what it compiled by +/// descriptor, so making the same descriptor later finds it compiled. +#[cfg(all(target_arch = "wasm32", feature = "web"))] +mod compiled { + use std::cell::RefCell; + use std::rc::Rc; + + use wasm_bindgen::closure::Closure; + use wasm_bindgen::{JsCast, JsValue}; + + /// The device's pipeline makers, each with its async twin. + const MAKERS: [(&str, &str); 2] = [ + ("createRenderPipeline", "createRenderPipelineAsync"), + ("createComputePipeline", "createComputePipelineAsync"), + ]; + + /// The browser compiling, off its GPU's thread, the pipeline `make` makes through wgpu: while it + /// runs, the device's makers are their async twins, handed the very descriptor wgpu builds, so + /// what compiles is what wgpu makes later, by construction. `None` where the device is no + /// browser's, or `make` made nothing. + pub(super) fn capture(device: &wgpu::Device, make: impl FnOnce()) -> Option { + let raw: &JsValue = device.as_webgpu()?.as_ref(); + let twins: Vec = MAKERS + .iter() + .map(|(_, twin)| js_sys::Reflect::get(raw, &JsValue::from_str(twin)).ok()?.dyn_into().ok()) + .collect::>()?; + let caught: Rc>> = Rc::default(); + let shims: Vec JsValue>> = twins + .into_iter() + .map(|twin| { + let (device, caught) = (raw.clone(), caught.clone()); + Closure::new(move |descriptor: JsValue| { + let promise = twin.call1(&device, &descriptor).unwrap_or(JsValue::UNDEFINED); + *caught.borrow_mut() = promise.clone().dyn_into().ok(); + promise + }) + }) + .collect(); + let swapped = MAKERS + .iter() + .zip(&shims) + .all(|((maker, _), shim)| js_sys::Reflect::set(raw, &JsValue::from_str(maker), shim.as_ref()).is_ok()); + if swapped { + make(); + } + for (maker, _) in MAKERS { + let _ = js_sys::Reflect::delete_property(raw.unchecked_ref::(), &JsValue::from_str(maker)); + } + drop(shims); + caught.take() + } +} diff --git a/crates/latkit/src/gpu/readback.rs b/crates/latkit/src/gpu/readback.rs new file mode 100644 index 00000000..1b353e96 --- /dev/null +++ b/crates/latkit/src/gpu/readback.rs @@ -0,0 +1,132 @@ +//! Bytes read back from the GPU: copied in a frame's encoder and mapped when the caller submits it, +//! so reading never stalls a frame and never submits on its own; once mapped, it wakes what waits on +//! it. Map buffers come from a pool and go back to it once read, so hovering allocates nothing. + +use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::{Arc, Mutex, PoisonError}; +use std::task::Waker; + +use super::work::{Count, Counters}; +use crate::{Error, Result}; + +/// Map buffers no readback holds, by size, what counts the readbacks made from them, and how many +/// are still mapping. Every pool says whether it counts, so none stops counting by default. +#[derive(Clone)] +pub(crate) struct Readbacks { + free: Arc>>, + counters: Option>, + mapping: Arc, +} + +impl Readbacks { + /// A pool whose readbacks `counters` counts: the `Gpu`'s. + pub(crate) fn counted(counters: Arc) -> Readbacks { + Readbacks { free: Arc::default(), counters: Some(counters), mapping: Arc::default() } + } + + /// A pool whose readbacks count as no work: the frame timer's, which only some devices have. + pub(crate) fn uncounted() -> Readbacks { + Readbacks { free: Arc::default(), counters: None, mapping: Arc::default() } + } + + /// Readbacks of this pool the GPU has yet to map. + #[cfg(all(feature = "web", target_arch = "wasm32"))] + pub(crate) fn mapping(&self) -> u64 { + self.mapping.load(Ordering::Acquire) + } + + fn take(&self, device: &wgpu::Device, size: u64) -> wgpu::Buffer { + if let Some(counters) = &self.counters { + counters.add(Count::Readbacks, 1); + } + let class = size.max(256).next_power_of_two(); + let mut free = self.free.lock().unwrap_or_else(PoisonError::into_inner); + if let Some(i) = free.iter().position(|b| b.size() == class) { + return free.swap_remove(i); + } + device.create_buffer(&wgpu::BufferDescriptor { + label: Some("latkit readback"), + size: class, + usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }) + } +} + +/// Where a readback's map stands. +#[derive(Clone, Copy, PartialEq, Eq)] +enum Mapping { + Waiting, + Ready, + Failed, + Read, +} + +pub(crate) struct Readback { + buffer: Option, + size: u64, + pool: Readbacks, + mapping: Arc>, +} + +impl Readback { + /// Copies `size` bytes of `source` from `offset`, to read once `encoder` is submitted; `waker` + /// wakes once they can be read. + pub(crate) fn new( + pool: &Readbacks, + device: &wgpu::Device, + encoder: &mut wgpu::CommandEncoder, + source: &wgpu::Buffer, + offset: u64, + size: u64, + waker: &Waker, + ) -> Readback { + let buffer = pool.take(device, size); + encoder.copy_buffer_to_buffer(source, offset, &buffer, 0, size); + let mapping = Arc::new(Mutex::new(Mapping::Waiting)); + let done = mapping.clone(); + let waker = waker.clone(); + let pending = pool.mapping.clone(); + pending.fetch_add(1, Ordering::AcqRel); + encoder.map_buffer_on_submit(&buffer, wgpu::MapMode::Read, ..size, move |result| { + *done.lock().unwrap_or_else(PoisonError::into_inner) = + if result.is_ok() { Mapping::Ready } else { Mapping::Failed }; + pending.fetch_sub(1, Ordering::AcqRel); + waker.wake(); + }); + Readback { buffer: Some(buffer), size, pool: pool.clone(), mapping } + } + + /// The bytes once mapped, or `None` while the GPU has not finished or they were taken. + pub(crate) fn take(&self) -> Option>> { + let mut mapping = self.mapping.lock().unwrap_or_else(PoisonError::into_inner); + let buffer = self.buffer.as_ref()?; + match *mapping { + Mapping::Waiting | Mapping::Read => None, + Mapping::Failed => Some(Err(Error::DeviceLost)), + Mapping::Ready => { + let bytes = match buffer.get_mapped_range(..self.size) { + Ok(view) => view.to_vec(), + Err(_) => return Some(Err(Error::DeviceLost)), + }; + buffer.unmap(); + *mapping = Mapping::Read; + Some(Ok(bytes)) + } + } + } +} + +impl Drop for Readback { + fn drop(&mut self) { + let Some(buffer) = self.buffer.take() else { return }; + // A buffer still mapping cannot go back yet; it is dropped instead. + let mapping = *self.mapping.lock().unwrap_or_else(PoisonError::into_inner); + if mapping == Mapping::Ready { + buffer.unmap(); + } + if matches!(mapping, Mapping::Ready | Mapping::Read) { + self.pool.free.lock().unwrap_or_else(PoisonError::into_inner).push(buffer); + } + } +} diff --git a/crates/latkit/src/gpu/shaders.rs b/crates/latkit/src/gpu/shaders.rs new file mode 100644 index 00000000..58495b6a --- /dev/null +++ b/crates/latkit/src/gpu/shaders.rs @@ -0,0 +1,118 @@ +//! The GPU contract generated from the WESL shaders by `build/shaders.rs`: constants, `#[repr(C)]` +//! mirrors of shared structs, bind group layouts, and each shader's text. + +#![allow(clippy::unreadable_literal)] + +/// How a binding is read. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub(crate) enum Kind { + Uniform, + Storage { read_only: bool }, + Texture { array: bool, filterable: bool }, + Depth { multisampled: bool }, + Sampler, +} + +/// One binding of a bind group layout. +#[derive(Clone, Copy, Debug)] +pub(crate) struct Binding { + pub(crate) slot: u32, + pub(crate) kind: Kind, + pub(crate) stages: u32, + pub(crate) dynamic: bool, +} + +const VERTEX: u32 = 1; +const FRAGMENT: u32 = 2; +const COMPUTE: u32 = 4; + +impl ShaderSource { + /// The shader's WGSL: its declarations, each stored once for every shader, joined in order. + pub(crate) fn wgsl(&self) -> String { + let mut out = String::new(); + for (i, &piece) in self.pieces.iter().enumerate() { + if i > 0 { + out.push_str("\n\n"); + } + let (start, end) = PIECES[piece as usize]; + out.push_str(&WGSL[start as usize..end as usize]); + } + out + } + + /// Bytes of its WGSL: what a browser compiles for each of its pipelines, and so about how long + /// one takes. + pub(crate) fn size(&self) -> usize { + self.pieces + .iter() + .map(|&piece| { + let (start, end) = PIECES[piece as usize]; + (end - start) as usize + }) + .sum() + } +} + +/// Every distinct top-level declaration of every linked shader, each once; [`PIECES`] says where each +/// lies. +static WGSL: &str = include_str!(concat!(env!("OUT_DIR"), "/shaders.wgsl")); + +/// One linked shader: its declarations, entry points, and the bindings of its pass group. +pub(crate) struct ShaderSource { + pub(crate) label: &'static str, + /// Its declarations, as indices into [`PIECES`], in order. + pieces: &'static [u16], + pub(crate) pass: &'static [Binding], + /// The pipeline constants it declares. + pub(crate) overrides: &'static [&'static str], + /// Whether it reads the view and mark groups; one that does not binds its pass group alone. + pub(crate) shared: bool, +} + +impl Binding { + pub(crate) fn layout_entry(&self) -> wgpu::BindGroupLayoutEntry { + let mut visibility = wgpu::ShaderStages::NONE; + for (bit, stage) in [ + (VERTEX, wgpu::ShaderStages::VERTEX), + (FRAGMENT, wgpu::ShaderStages::FRAGMENT), + (COMPUTE, wgpu::ShaderStages::COMPUTE), + ] { + if self.stages & bit != 0 { + visibility |= stage; + } + } + let ty = match self.kind { + Kind::Uniform => wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: self.dynamic, + min_binding_size: None, + }, + Kind::Storage { read_only } => wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only }, + has_dynamic_offset: self.dynamic, + min_binding_size: None, + }, + Kind::Texture { array, filterable } => wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable }, + view_dimension: if array { + wgpu::TextureViewDimension::D2Array + } else { + wgpu::TextureViewDimension::D2 + }, + multisampled: false, + }, + Kind::Depth { multisampled } => wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Depth, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled, + }, + Kind::Sampler => wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + }; + wgpu::BindGroupLayoutEntry { binding: self.slot, visibility, ty, count: None } + } +} + +include!(concat!(env!("OUT_DIR"), "/shaders.rs")); + +// A block of rows the GPU evaluates is a page of every column. +const _: () = assert!(BLOCK_ROWS as usize == crate::data::PAGE_ROWS && 1 << PAGE_BITS == BLOCK_ROWS); diff --git a/crates/latkit/src/gpu/work.rs b/crates/latkit/src/gpu/work.rs new file mode 100644 index 00000000..e14cee58 --- /dev/null +++ b/crates/latkit/src/gpu/work.rs @@ -0,0 +1,143 @@ +//! What a `Gpu` did, counted exactly. Unlike time, it repeats from run to run and machine to machine +//! wherever the budget, the device's limits, and the frames drawn do, so the benchmark gates it and +//! tests assert it. Every write to the GPU goes through [`Queue`], which counts it; clippy refuses the +//! raw queue's writes anywhere else. Whatever else counts holds the counters itself: the pipelines, +//! the readback pool, the atlas, and each frame's jobs and evaluations through the `Gpu`. + +use std::ops::{Deref, Sub}; +use std::sync::Arc; +use std::sync::atomic::{AtomicU64, Ordering::Relaxed}; + +/// [`Work`], the [`Count`] naming each of its fields, and the [`Counters`] keeping them, from one list. +macro_rules! work { + ($($(#[$doc:meta])* $field:ident: $count:ident,)*) => { + /// What a [`Gpu`](crate::Gpu) did since it was made; subtract two for what happened between. + #[derive(Clone, Copy, Default, PartialEq, Eq, Debug, serde::Serialize, schemars::JsonSchema)] + pub struct Work { + $($(#[$doc])* pub $field: u64,)* + } + + /// A kind of work a `Gpu` counts. + #[derive(Clone, Copy)] + pub(crate) enum Count { + $($count,)* + } + + /// The counts, shared by every view of a `Gpu`, from any thread. + #[derive(Default)] + pub(crate) struct Counters { + $($field: AtomicU64,)* + } + + impl Counters { + pub(crate) fn add(&self, count: Count, n: u64) { + let counter = match count { + $(Count::$count => &self.$field,)* + }; + counter.fetch_add(n, Relaxed); + } + + pub(crate) fn work(&self) -> Work { + Work { $($field: self.$field.load(Relaxed),)* } + } + } + + impl Sub for Work { + type Output = Work; + + fn sub(self, before: Work) -> Work { + Work { $($field: self.$field.saturating_sub(before.$field),)* } + } + } + }; +} + +work! { + /// Bytes of data pages uploaded. + uploaded: Uploaded, + /// Bytes written besides pages: uniforms, programs, label runs, the selection, textures. + written: Written, + /// Rows whose channels the GPU evaluated. + evaluated: Evaluated, + /// Reads back from the GPU: probes, queries, fits, label placements, segment counts, pictures; + /// not the frame timer's, which only some devices have. + readbacks: Readbacks, + /// Jobs handed out: layouts, routes, lanes, triangulations, pyramids, tiles; to the host's + /// workers, or done at once without a host. + jobs: Jobs, + /// Label texts the host was asked to set. + texts: Texts, + /// Pipelines compiled: in a browser, each as a view or a shot asks for it ahead, off the GPU's + /// thread; natively, where it is first made. + pipelines: Pipelines, + /// Pipelines made without being asked for ahead, each compiled where it is first used: in a + /// browser on the GPU's thread, holding frames back. None, unless a scene uses what it did not + /// ask for. + late: Late, +} + +/// The device's queue, counting what is written through it; everything else it does as the queue. +pub(crate) struct Queue { + raw: wgpu::Queue, + counters: Arc, +} + +impl Queue { + pub(crate) fn new(raw: wgpu::Queue, counters: Arc) -> Queue { + Queue { raw, counters } + } + + /// Writes `bytes` into `buffer` at `offset`, counted as written. + #[expect(clippy::disallowed_methods, reason = "the counted write")] + pub(crate) fn write_buffer(&self, buffer: &wgpu::Buffer, offset: u64, bytes: &[u8]) { + self.counters.add(Count::Written, bytes.len() as u64); + self.raw.write_buffer(buffer, offset, bytes); + } + + /// Writes in command order, so a reused scratch buffer keeps earlier passes' inputs intact. + pub(crate) fn write_buffer_in( + &self, + device: &wgpu::Device, + encoder: &mut wgpu::CommandEncoder, + buffer: &wgpu::Buffer, + offset: u64, + bytes: &[u8], + ) { + use wgpu::util::DeviceExt; + self.counters.add(Count::Written, bytes.len() as u64); + let upload = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("latkit ordered upload"), + contents: bytes, + usage: wgpu::BufferUsages::COPY_SRC, + }); + encoder.copy_buffer_to_buffer(&upload, 0, buffer, offset, bytes.len() as u64); + } + + /// Writes a data page's words into `buffer` at `offset`, counted as uploaded. + #[expect(clippy::disallowed_methods, reason = "the counted upload")] + pub(crate) fn upload(&self, buffer: &wgpu::Buffer, offset: u64, bytes: &[u8]) { + self.counters.add(Count::Uploaded, bytes.len() as u64); + self.raw.write_buffer(buffer, offset, bytes); + } + + /// Writes texels, counted as written. + #[expect(clippy::disallowed_methods, reason = "the counted write")] + pub(crate) fn write_texture( + &self, + texture: wgpu::TexelCopyTextureInfo<'_>, + bytes: &[u8], + layout: wgpu::TexelCopyBufferLayout, + size: wgpu::Extent3d, + ) { + self.counters.add(Count::Written, bytes.len() as u64); + self.raw.write_texture(texture, bytes, layout, size); + } +} + +impl Deref for Queue { + type Target = wgpu::Queue; + + fn deref(&self) -> &wgpu::Queue { + &self.raw + } +} diff --git a/crates/latkit/src/host/browser.rs b/crates/latkit/src/host/browser.rs new file mode 100644 index 00000000..d0c04fcd --- /dev/null +++ b/crates/latkit/src/host/browser.rs @@ -0,0 +1,281 @@ +use std::cell::RefCell; + +use wasm_bindgen::{JsCast, JsValue}; +use web_sys::{OffscreenCanvas, OffscreenCanvasRenderingContext2d}; + +use super::{Encoder, Unit}; +use super::{Host, Job, Raster, Request, TextRun}; +use crate::Encoding; +use crate::{Error, Pending}; + +/// The browser: text set with a 2D canvas in the page's fonts, jobs done by the page's workers once +/// [`set_jobs`](Browser::set_jobs) names them, else at once, bytes fetched with `fetch`, and video +/// encoded by WebCodecs once [`set_encoder`](Browser::set_encoder) names how. +#[derive(Clone, Copy, Debug, Default)] +pub struct Browser; + +thread_local! { + static CANVAS: RefCell> = const { RefCell::new(None) }; + static JOBS: RefCell> = const { RefCell::new(None) }; + static ENCODERS: RefCell> = const { RefCell::new(None) }; +} + +impl Browser { + /// Has views' jobs done by `run`, which takes a job's bytes as a `Uint8Array` and returns a + /// promise of its answer's: a pool of workers, each holding the page's compiled module. + pub fn set_jobs(run: js_sys::Function) { + JOBS.with(|jobs| *jobs.borrow_mut() = Some(run)); + } + + /// Has videos encoded by what `create` makes of `(width, height, fps, bitrate)`: an object whose + /// `close()` releases resources; `encode(nv12, time, key)` and `finish()` return promises of the units finished since, each + /// `[time, key, bytes]`, in order. The npm package makes one with WebCodecs. + pub fn set_encoder(create: js_sys::Function) { + ENCODERS.with(|encoders| *encoders.borrow_mut() = Some(create)); + } +} + +/// An encoder the page made: its `encode` and `finish` answer promises of units. +struct Script(JsValue); + +impl Script { + /// Calls method `name` with `args`, resolving to the units its promise answers. + fn call(&self, name: &str, args: &js_sys::Array) -> Pending> { + let promise = js_sys::Reflect::get(&self.0, &name.into()) + .and_then(JsCast::dyn_into::) + .and_then(|f| f.apply(&self.0, args)) + .map(|answer| js_sys::Promise::resolve(&answer)); + let promise = match promise { + Ok(promise) => promise, + Err(error) => return Pending::ready(Err(Error::Unsupported(format!("the encoder: {error:?}").into()))), + }; + let (pending, resolver) = Pending::new(); + wasm_bindgen_futures::spawn_local(async move { + let answer = wasm_bindgen_futures::JsFuture::from(promise).await; + resolver.resolve( + answer + .map_err(|error| Error::Unsupported(format!("the encoder failed: {error:?}").into())) + .and_then(units), + ); + }); + pending + } +} + +/// The units an encoder answered: `[time, key, bytes]` each. +fn units(answer: JsValue) -> crate::Result> { + let units: js_sys::Array = + answer.dyn_into().map_err(|_| Error::Unsupported("the encoder answered no units".into()))?; + units + .iter() + .map(|unit| { + let unit: js_sys::Array = + unit.dyn_into().map_err(|_| Error::Unsupported("a unit is [time, key, bytes]".into()))?; + let time = unit.get(0).as_f64().ok_or_else(|| Error::Unsupported("a unit's time".into()))?; + let bytes = js_sys::Uint8Array::new(&unit.get(2)); + Ok(Unit { time: time as u64, key: unit.get(1).is_truthy(), annex_b: bytes.to_vec() }) + }) + .collect() +} + +impl Drop for Script { + fn drop(&mut self) { + if let Ok(close) = js_sys::Reflect::get(&self.0, &"close".into()).and_then(JsCast::dyn_into::) + { + let _ = close.call0(&self.0); + } + } +} + +impl Encoder for Script { + fn encode(&mut self, nv12: Vec, time: u64, key: bool) -> Pending> { + let bytes = js_sys::Uint8Array::from(&nv12[..]); + self.call("encode", &js_sys::Array::of3(&bytes, &(time as f64).into(), &key.into())) + } + + fn finish(&mut self) -> Pending> { + self.call("finish", &js_sys::Array::new()) + } +} + +/// Pixels of room around each run, so antialiasing and overhangs are kept. +const PAD: f64 = 2.0; + +/// `text` broken at spaces into lines no wider than `max_width`, each with its width. +fn lines( + context: &OffscreenCanvasRenderingContext2d, + text: &str, + max_width: Option, +) -> Option> { + let width = |s: &str| context.measure_text(s).ok().map(|m| m.width()); + let Some(max_width) = max_width else { return Some(vec![(text.to_owned(), width(text)?)]) }; + let mut lines: Vec<(String, f64)> = Vec::new(); + for word in text.split(' ') { + if let Some((line, w)) = lines.last_mut() { + let joined = format!("{line} {word}"); + let joined_width = width(&joined)?; + if joined_width <= max_width { + *line = joined; + *w = joined_width; + continue; + } + } + lines.push((word.to_owned(), width(word)?)); + } + Some(lines) +} + +/// The page's 2D context for setting and measuring text, made on first use. +fn with_context(f: impl FnOnce(&OffscreenCanvas, &OffscreenCanvasRenderingContext2d) -> Option) -> Option { + CANVAS.with(|cell| { + let mut cell = cell.borrow_mut(); + if cell.is_none() { + let canvas = OffscreenCanvas::new(256, 64).ok()?; + // Each run is read back once it is set. + let options = js_sys::Object::new(); + js_sys::Reflect::set(&options, &"willReadFrequently".into(), &true.into()).ok()?; + let context = canvas.get_context_with_context_options("2d", &options).ok()??; + let context = context.dyn_into::().ok()?; + *cell = Some((canvas, context)); + } + let (canvas, context) = cell.as_ref()?; + f(canvas, context) + }) +} + +/// A run laid out: its lines, each with its width, and its ascent and line height. +struct Layout { + lines: Vec<(String, f64)>, + ascent: f64, + line_height: f64, +} + +impl Layout { + /// `run` laid out in `context`, set to its font. + fn of(context: &OffscreenCanvasRenderingContext2d, run: &TextRun) -> Option { + context.set_font(&format!("{}px {}", run.size_px, run.font)); + let lines = lines(context, &run.text, run.max_width.map(f64::from))?; + let metrics = context.measure_text(&run.text).ok()?; + let ascent = metrics.font_bounding_box_ascent(); + Some(Layout { lines, ascent, line_height: ascent + metrics.font_bounding_box_descent() }) + } + + /// Its width and height, with room around it. + fn size(&self) -> [f64; 2] { + let widest = self.lines.iter().map(|(_, w)| *w).fold(0.0, f64::max); + [widest + 2.0 * PAD, self.line_height * self.lines.len() as f64 + 2.0 * PAD] + } +} + +impl Host for Browser { + fn measure(&self, run: &TextRun) -> crate::Result<[f32; 2]> { + with_context(|_, context| Some(Layout::of(context, run)?.size().map(|v| v as f32))) + .ok_or_else(|| Error::Unsupported("browser text measurement failed".into())) + } + + fn spawn(&self, job: Job) -> Pending> { + let Some(run) = JOBS.with(|jobs| jobs.borrow().clone()) else { return Pending::ready(Ok(job.run())) }; + let bytes = js_sys::Uint8Array::from(&job.into_bytes()[..]); + let promise = match run.call1(&JsValue::NULL, &bytes).map(js_sys::Promise::from) { + Ok(promise) => promise, + Err(error) => return Pending::ready(Err(Error::Unsupported(format!("jobs: {error:?}").into()))), + }; + let (pending, resolver) = Pending::new(); + wasm_bindgen_futures::spawn_local(async move { + let answer = wasm_bindgen_futures::JsFuture::from(promise).await; + resolver.resolve( + answer + .map(|bytes| js_sys::Uint8Array::new(&bytes).to_vec()) + .map_err(|error| Error::Unsupported(format!("a job failed: {error:?}").into())), + ); + }); + pending + } + + fn fetch(&self, request: &Request) -> Pending> { + let (pending, resolver) = Pending::new(); + let request = request.clone(); + wasm_bindgen_futures::spawn_local(async move { + resolver.resolve(fetched(&request).await); + }); + pending + } + + fn rasterize(&self, run: &TextRun) -> crate::Result { + with_context(|canvas, context| { + let layout = Layout::of(context, run)?; + let size = layout.size().map(|v| v.ceil() as u32); + if canvas.width() < size[0] || canvas.height() < size[1] { + canvas.set_width(canvas.width().max(size[0].next_power_of_two())); + canvas.set_height(canvas.height().max(size[1].next_power_of_two())); + } + // Resizing resets the context. + context.set_font(&format!("{}px {}", run.size_px, run.font)); + context.set_text_baseline("alphabetic"); + context.set_fill_style_str("#fff"); + context.clear_rect(0.0, 0.0, f64::from(size[0]), f64::from(size[1])); + for (i, (line, _)) in layout.lines.iter().enumerate() { + context.fill_text(line, PAD, PAD + layout.ascent + layout.line_height * i as f64).ok()?; + } + let rgba = context.get_image_data(0.0, 0.0, f64::from(size[0]), f64::from(size[1])).ok()?.data(); + let coverage = rgba.0.as_chunks::<4>().0.iter().map(|p| p[3]).collect(); + Some(Raster { size, coverage, baseline: (PAD + layout.ascent) as f32 }) + }) + .ok_or_else(|| Error::Unsupported("browser text rasterization failed".into())) + } + + fn encoder(&self, encoding: &Encoding) -> crate::Result> { + let unsupported = + || Error::Unsupported("videos in a browser encode with WebCodecs, which the page did not give".into()); + let create = ENCODERS.with(|encoders| encoders.borrow().clone()).ok_or_else(unsupported)?; + let [width, height] = encoding.size; + let args = js_sys::Array::of4( + &width.into(), + &height.into(), + &encoding.fps.into(), + &f64::from(encoding.bitrate).into(), + ); + let encoder = create + .apply(&JsValue::NULL, &args) + .map_err(|error| Error::Unsupported(format!("no encoder for {width}×{height}: {error:?}").into()))?; + Ok(Box::new(Script(encoder))) + } +} + +/// The bytes `request` asks for: none where there is nothing at its URL, and only the range asked for +/// where a server sends every byte. +async fn fetched(request: &Request) -> crate::Result> { + let failed = |what: &str| Error::Io(format!("{} could not be read: {what}", request.url).into()); + let init = web_sys::RequestInit::new(); + let headers = web_sys::Headers::new().map_err(|e| failed(&format!("{e:?}")))?; + if let Some(range) = &request.range { + let value = format!("bytes={}-{}", range.start, range.end.saturating_sub(1)); + headers.set("Range", &value).map_err(|e| failed(&format!("{e:?}")))?; + } + init.set_headers(&headers); + let fetch = web_sys::Request::new_with_str_and_init(&request.url, &init).map_err(|e| failed(&format!("{e:?}")))?; + // The page's fetch, or a worker's. + let global = js_sys::global(); + let promise = match (global.dyn_ref::(), global.dyn_ref::()) { + (Some(window), _) => window.fetch_with_request(&fetch), + (None, Some(worker)) => worker.fetch_with_request(&fetch), + (None, None) => return Err(failed("no fetch here")), + }; + let response = wasm_bindgen_futures::JsFuture::from(promise).await.map_err(|e| failed(&format!("{e:?}")))?; + let response: web_sys::Response = response.dyn_into().map_err(|_| failed("not a response"))?; + match response.status() { + 200 | 206 => {} + 204 | 404 => return Ok(Vec::new()), + status => return Err(failed(&format!("status {status}"))), + } + let body = response.array_buffer().map_err(|e| failed(&format!("{e:?}")))?; + let body = wasm_bindgen_futures::JsFuture::from(body).await.map_err(|e| failed(&format!("{e:?}")))?; + let mut bytes = js_sys::Uint8Array::new(&body).to_vec(); + if response.status() == 200 + && let Some(range) = &request.range + { + let end = (range.end as usize).min(bytes.len()); + bytes = bytes.get(range.start as usize..end).map(<[u8]>::to_vec).unwrap_or_default(); + } + Ok(bytes) +} diff --git a/crates/latkit/src/host/job.rs b/crates/latkit/src/host/job.rs new file mode 100644 index 00000000..e34c7fb4 --- /dev/null +++ b/crates/latkit/src/host/job.rs @@ -0,0 +1,708 @@ +//! Jobs: work too large for the frame (laying out in ranks or by stress, routing wires, cutting areas +//! into triangles, grouping a large table's rows into tiles, writing a picture as a file), handed to the +//! host to do off the frame. A job is bytes in and bytes out, so a thread, or a worker holding its own +//! copy of latkit, can do it with nothing shared. A view's job answers with a [`Patch`]: the rows it +//! worked out, by id, with their places, the paths their wires run along, or their shapes; an image +//! job answers with the file. + +use std::sync::Arc; + +use crate::Side; +use crate::data::{Field, GeometryBuilder, Id, Name, Op, Patch, Table, Value, Values, Version}; +use crate::derive::pyramid::{Leveling, Places, Placing}; +use crate::derive::sight::Domain; +use crate::geo::mvt::Kind as Geometry; +use crate::geo::shapes::{earth_parts, triangles}; +use crate::geo::tiles::{Decoded, decode}; +use crate::layout::route::{Net, Terminal, route}; +use crate::layout::{layered::layered, levels::Graph, stress::stress}; +use crate::tiles::TileKey; +use crate::{Direction, Layered, Layout}; + +/// Work latkit hands its [`Host`](super::Host) to do off the frame: bytes in, bytes out. +/// +/// A host that does jobs elsewhere sends [`into_bytes`](Job::into_bytes) there, and answers with +/// what [`run`](Job::run) makes of [`from_bytes`](Job::from_bytes) of them. +#[derive(Clone, PartialEq, Eq)] +pub struct Job(Vec); + +/// What a job does, its first word. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +enum Kind { + Layered = 1, + Stress = 2, + Routes = 3, + Shapes = 4, + Tile = 5, + GeoJson = 6, + Lanes = 7, + Pyramid = 8, + Image = 9, +} + +/// What a shapes job works out of each row's geometry. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub(crate) enum Shaping { + /// An area's triangles, the point its label hangs from first; on the earth, unwrapped and split + /// along its grid. + Triangles { earth: bool }, + /// An earth line's path: unwrapped, and bent with the globe; cheap enough that no job makes it. + Path, +} + +impl Shaping { + fn code(self) -> u32 { + match self { + Shaping::Triangles { earth: false } => 0, + Shaping::Triangles { earth: true } => 1, + Shaping::Path => 2, + } + } + + fn from_code(code: u32) -> Option { + match code { + 0 => Some(Shaping::Triangles { earth: false }), + 1 => Some(Shaping::Triangles { earth: true }), + 2 => Some(Shaping::Path), + _ => None, + } + } + + /// The depth of the shapes made from geometry of `depth`. + pub(crate) fn depth(self, depth: u8) -> u8 { + match self { + Shaping::Triangles { .. } => 1, + Shaping::Path => depth, + } + } + + /// The shape of `value`, or `None` where it stays as it is: a path that needs no bending. + pub(crate) fn shape(self, value: &Value) -> Option { + match (self, value) { + (Shaping::Triangles { earth }, Value::Polygons(polygons)) => Some(Value::Path(triangles(polygons, earth))), + (Shaping::Triangles { earth }, Value::Parts(rings)) => { + Some(Value::Path(triangles(std::slice::from_ref(rings), earth))) + } + (Shaping::Triangles { .. }, _) => Some(Value::Path(Vec::new())), + (Shaping::Path, Value::Path(path)) => { + earth_parts(std::slice::from_ref(path)).and_then(|mut parts| parts.pop()).map(Value::Path) + } + (Shaping::Path, Value::Parts(parts)) => earth_parts(parts).map(Value::Parts), + (Shaping::Path, Value::Polygons(polygons)) => { + let shaped: Vec>>> = polygons.iter().map(|rings| earth_parts(rings)).collect(); + shaped.iter().any(Option::is_some).then(|| { + Value::Polygons( + shaped + .into_iter() + .zip(polygons) + .map(|(shaped, rings)| shaped.unwrap_or_else(|| rings.clone())) + .collect(), + ) + }) + } + (Shaping::Path, _) => None, + } + } +} + +/// A row a job answers for: its table and id. +pub(crate) type Key = (Name, Id); + +/// Vertices to place: each one's size, its center when it has one, its group and how far a group's +/// box reaches past its members (left, bottom, right, top), links between them, and the key of +/// each vertex the answer places; vertices without a key are only placed around. Plane units, y up. +pub(crate) struct Placement<'a> { + pub(crate) sizes: &'a [[f64; 2]], + pub(crate) pinned: &'a [Option<[f64; 2]>], + pub(crate) groups: &'a [Option], + pub(crate) pads: &'a [[f64; 4]], + pub(crate) links: &'a [[u32; 2]], + pub(crate) keys: &'a [Option], +} + +/// Wires to route: around `obstacles` and among `groups`, each net's terminals with the key of the row +/// it draws, runs beside `fixed` wires already routed, tracks `spacing` apart. Plane units, y up. +pub(crate) struct Wiring<'a> { + pub(crate) obstacles: &'a [[f64; 4]], + pub(crate) groups: &'a [[f64; 4]], + pub(crate) nets: &'a [Net], + pub(crate) keys: &'a [Key], + pub(crate) fixed: &'a [Vec<[f64; 2]>], + pub(crate) spacing: f64, +} + +impl Job { + /// A job from its bytes. + pub fn from_bytes(bytes: Vec) -> Job { + Job(bytes) + } + + /// The job as bytes. + pub fn into_bytes(self) -> Vec { + self.0 + } + + /// Does the job, answering with a patch's bytes. Bytes that are no job answer nothing. + pub fn run(self) -> Vec { + let mut input = Reader::new(&self.0); + let kind = input.u32(); + if kind == Some(Kind::Image as u32) { + return run_image(&mut input).unwrap_or_default(); + } + let answer = match kind { + Some(k) if k == Kind::Layered as u32 || k == Kind::Stress as u32 => run_layout(k, &mut input), + Some(k) if k == Kind::Routes as u32 => run_routes(&mut input), + Some(k) if k == Kind::Shapes as u32 => run_shapes(&mut input), + Some(k) if k == Kind::Tile as u32 => run_tile(&mut input), + Some(k) if k == Kind::GeoJson as u32 => run_geojson(&mut input), + Some(k) if k == Kind::Lanes as u32 => run_lanes(&mut input), + Some(k) if k == Kind::Pyramid as u32 => run_pyramid(&mut input), + _ => None, + }; + answer.map(|patch| patch.to_bytes()).unwrap_or_default() + } + + /// Placing `placement` by `layout`, which is layered or stress; it answers each keyed vertex's + /// center as fields `x` and `y`, y up. + pub(crate) fn layout(layout: &Layout, placement: &Placement<'_>) -> Job { + let mut out = match *layout { + Layout::Stress(stress) => { + let mut out = Writer::new(Kind::Stress); + out.f64(stress.gap); + out + } + Layout::Layered(layered) => { + let mut out = Writer::new(Kind::Layered); + out.u32(match layered.flow { + Direction::Right => 0, + Direction::Left => 1, + Direction::Down => 2, + Direction::Up => 3, + }); + out.f64(layered.gap); + out.f64(layered.rank_gap); + out + } + Layout::None => unreachable!("a sheet asks for a layout only when its scene has one"), + }; + out.u32(placement.sizes.len() as u32); + for v in 0..placement.sizes.len() { + out.f64s(&placement.sizes[v]); + out.u32(u32::from(placement.pinned[v].is_some())); + out.f64s(&placement.pinned[v].unwrap_or_default()); + out.u32(placement.groups[v].unwrap_or(u32::MAX)); + out.f64s(&placement.pads[v]); + out.u32(u32::from(placement.keys[v].is_some())); + if let Some(key) = &placement.keys[v] { + out.key(key); + } + } + out.u32(placement.links.len() as u32); + for link in placement.links { + out.u32(link[0]); + out.u32(link[1]); + } + Job(out.0) + } + + /// Working out `shaping` for every row of `rows`, whose field `geometry` holds each row's + /// geometry; it answers each row's shape as field `shape`. + pub(crate) fn shapes(shaping: Shaping, rows: Table) -> Job { + let mut out = Writer::new(Kind::Shapes); + out.u32(shaping.code()); + out.0.extend(Patch::new().set(rows).to_bytes()); + Job(out.0) + } + + /// Decoding tile `key` from `bytes`, gzip-compressed or not, into the rows of `tables`; it answers + /// those rows. + pub(crate) fn tile(key: TileKey, tables: &[Decoded], bytes: &[u8]) -> Job { + let mut out = Writer::new(Kind::Tile); + out.u32(u32::from(key.z)); + out.u32(key.x); + out.u32(key.y); + out.u32(tables.len() as u32); + for decoded in tables { + out.text(&decoded.layer); + out.u32(match decoded.kind { + Geometry::Points => 0, + Geometry::Lines => 1, + Geometry::Polygons => 2, + }); + out.text(&decoded.table); + } + out.0.extend_from_slice(bytes); + Job(out.0) + } + + /// The job writing `image` as a file of `format`, which it answers with; nothing where it + /// cannot be written. + pub fn encode(image: &crate::Image, format: crate::ImageFormat) -> Job { + let mut out = Writer::new(Kind::Image); + out.u32(match format { + crate::ImageFormat::Png => 0, + crate::ImageFormat::Jpeg { quality } => 0x100 | u32::from(quality), + crate::ImageFormat::WebP => 1, + }); + out.u32(image.size[0]); + out.u32(image.size[1]); + out.0.extend_from_slice(&image.rgba); + Job(out.0) + } + + /// Reading GeoJSON `bytes` as dataset `name`, as [`Data::read`](crate::Data::read) does; it + /// answers the patch that builds the dataset, or nothing when the bytes are no GeoJSON. + pub fn geojson(name: &str, bytes: &[u8]) -> Job { + let mut out = Writer::new(Kind::GeoJson); + out.text(name); + out.0.extend_from_slice(bytes); + Job(out.0) + } + + /// Finding every edge row's lane among the rows joining the same two vertices, from each row's two + /// ends; it answers a table of every row's lane as field `lane`, without rows when none share. + pub(crate) fn lanes(from: &[u32], to: &[u32]) -> Job { + let mut out = Writer::new(Kind::Lanes); + out.u32(from.len() as u32); + out.words(from); + out.words(to); + Job(out.0) + } + + /// Grouping `leveling`'s tables into tiles; it answers each table's pyramid, as + /// [`Pyramid::read`](crate::derive::pyramid::Pyramid::read) reads it. + pub(crate) fn pyramid(leveling: &Leveling) -> Job { + let mut out = Writer::new(Kind::Pyramid); + match leveling.domain { + Domain::Earth => out.f64s(&[0.0, 0.0, 0.0, 0.0]), + Domain::Plane { min, size } => out.f64s(&[1.0, min[0], min[1], size]), + } + out.u32(leveling.tables.len() as u32); + for table in &leveling.tables { + let places = match &table.places { + Places::None => 0, + Places::Points(_) => 1, + Places::Boxes(_) => 2, + }; + let flags = u32::from(table.leveled) + | u32::from(table.answered) << 1 + | places << 2 + | u32::from(!table.priority.is_empty()) << 4 + | u32::from(table.ends.is_some()) << 5; + out.u32(table.rows); + out.u32(flags); + match &table.places { + Places::None => {} + Places::Points(points) => out.words(bytemuck::cast_slice(&points[..])), + Places::Boxes(boxes) => out.words(bytemuck::cast_slice(&boxes[..])), + } + out.words(bytemuck::cast_slice(&table.priority)); + if let Some((target, ends)) = &table.ends { + out.u32(*target); + out.u32(ends.len() as u32); + for end in ends { + out.words(end); + } + } + } + Job(out.0) + } + + /// Routing `wiring`; it answers each keyed row's wire as field `route`, its polylines. + pub(crate) fn routes(wiring: &Wiring<'_>) -> Job { + let mut out = Writer::new(Kind::Routes); + out.f64(wiring.spacing); + for boxes in [wiring.obstacles, wiring.groups] { + out.u32(boxes.len() as u32); + for b in boxes { + out.f64s(b); + } + } + out.u32(wiring.fixed.len() as u32); + for line in wiring.fixed { + out.u32(line.len() as u32); + for point in line { + out.f64s(point); + } + } + out.u32(wiring.nets.len() as u32); + for (net, key) in wiring.nets.iter().zip(wiring.keys) { + out.key(key); + out.u32(net.terminals.len() as u32); + for terminal in &net.terminals { + out.f64s(&terminal.at); + out.u32(terminal.side.map_or(u32::MAX, Side::code)); + out.u32(terminal.owner.unwrap_or(u32::MAX)); + } + } + Job(out.0) + } +} + +impl std::fmt::Debug for Job { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("Job").field(&self.0.len()).finish() + } +} + +/// A patch writing `values` for `keys`, one table at a time in the order the keys name them. +fn keyed(keys: &[Key], values: Vec, write: impl Fn(Table, Vec) -> Table) -> Patch { + let mut tables: Vec<(Name, Vec, Vec)> = Vec::new(); + for ((table, id), value) in keys.iter().zip(values) { + match tables.iter_mut().find(|(name, ..)| name == table) { + Some((_, ids, values)) => { + ids.push(id.clone()); + values.push(value); + } + None => tables.push((table.clone(), vec![id.clone()], vec![value])), + } + } + tables.into_iter().fold(Patch::new(), |patch, (name, ids, values)| patch.set(write(Table::new(name, ids), values))) +} + +fn run_layout(kind: u32, input: &mut Reader<'_>) -> Option { + let options = if kind == Kind::Stress as u32 { + Layout::Stress(crate::Stress { gap: input.f64()? }) + } else { + let flow = match input.u32()? { + 0 => Direction::Right, + 1 => Direction::Left, + 2 => Direction::Down, + _ => Direction::Up, + }; + Layout::Layered(Layered { flow, gap: input.f64()?, rank_gap: input.f64()? }) + }; + let count = input.u32()? as usize; + let (mut sizes, mut pinned, mut groups, mut pads, mut keys) = + (Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new()); + for _ in 0..count { + sizes.push([input.f64()?, input.f64()?]); + let pin = input.u32()? != 0; + let at = [input.f64()?, input.f64()?]; + pinned.push(pin.then_some(at)); + groups.push(Some(input.u32()?).filter(|&g| (g as usize) < count)); + pads.push([input.f64()?, input.f64()?, input.f64()?, input.f64()?]); + let keyed = input.u32()? != 0; + keys.push(if keyed { Some(input.key()?) } else { None }); + } + let links = input.u32()?; + let links = (0..links).map(|_| Some([input.u32()?, input.u32()?])).collect::>>()?; + if links.iter().flatten().any(|&v| v as usize >= count) { + return None; + } + let graph = Graph { sizes: &sizes, links: &links, pinned: &pinned, groups: &groups, pads: &pads }; + let centers = match options { + Layout::Stress(s) => stress(&graph, s.gap), + Layout::Layered(l) => layered(&graph, &l), + Layout::None => return None, + }; + let placed: Vec<(Key, [f64; 2])> = + keys.into_iter().zip(centers).filter_map(|(key, center)| Some((key?, center))).collect(); + let (keys, centers): (Vec, Vec<[f64; 2]>) = placed.into_iter().unzip(); + Some(keyed(&keys, centers, |table, centers| { + let (x, y): (Vec, Vec) = centers.into_iter().map(|c| (c[0], c[1])).unzip(); + table.field("x", x).field("y", y) + })) +} + +fn run_routes(input: &mut Reader<'_>) -> Option { + let spacing = input.f64()?; + let mut boxes = || { + let count = input.u32()?; + (0..count).map(|_| Some([input.f64()?, input.f64()?, input.f64()?, input.f64()?])).collect::>>() + }; + let (obstacles, groups) = (boxes()?, boxes()?); + let count = input.u32()?; + let fixed = (0..count) + .map(|_| { + let points = input.u32()?; + (0..points).map(|_| Some([input.f64()?, input.f64()?])).collect::>>() + }) + .collect::>>()?; + let count = input.u32()?; + let (mut nets, mut keys) = (Vec::new(), Vec::new()); + for _ in 0..count { + keys.push(input.key()?); + let terminals = input.u32()?; + let terminals = (0..terminals) + .map(|_| { + let at = [input.f64()?, input.f64()?]; + let side = Side::from_code(input.u32()?); + let owner = Some(input.u32()?).filter(|&o| (o as usize) < obstacles.len()); + Some(Terminal { at, side, owner }) + }) + .collect::>>()?; + nets.push(Net { terminals }); + } + let routes = route(&obstacles, &groups, &nets, &fixed, spacing); + Some(keyed(&keys, routes, |table, routes| table.field("route", routes))) +} + +fn run_shapes(input: &mut Reader<'_>) -> Option { + let shaping = Shaping::from_code(input.u32()?)?; + let Op::Set(rows) = Patch::from_bytes(input.rest()).ok()?.ops.into_iter().next()? else { return None }; + let Some(Field::Values(column, _)) = rows.field_named("geometry") else { return None }; + let depth = column.kind().depth()?; + let mut shapes = GeometryBuilder::new(shaping.depth(depth)); + for row in 0..rows.len() { + match column.get(row) { + Some(value) => { + let shaped = shaping.shape(&value); + shapes.push_value(shaped.as_ref().unwrap_or(&value)); + } + None => shapes.push_empty(), + } + } + let shapes = Values::of_geometry(shapes.finish()); + let mut answer = rows.clone(); + answer.fields.clear(); + answer.insert("shape".into(), Field::Values(crate::data::Column::new(&shapes), Version::next())); + Some(Patch::new().set(answer)) +} + +fn run_tile(input: &mut Reader<'_>) -> Option { + let key = TileKey { z: u8::try_from(input.u32()?).ok()?, x: input.u32()?, y: input.u32()? }; + let count = input.u32()?; + let tables = (0..count) + .map(|_| { + let layer = input.text()?; + let kind = match input.u32()? { + 0 => Geometry::Points, + 1 => Geometry::Lines, + _ => Geometry::Polygons, + }; + Some(Decoded { layer, kind, table: input.text()?.into() }) + }) + .collect::>>()?; + decode(input.rest(), key, &tables) +} + +fn run_image(input: &mut Reader<'_>) -> Option> { + let format = match input.u32()? { + 0 => crate::ImageFormat::Png, + 1 => crate::ImageFormat::WebP, + jpeg => crate::ImageFormat::Jpeg { quality: (jpeg & 0xff) as u8 }, + }; + let size = [input.u32()?, input.u32()?]; + crate::Image::new(size, input.rest()).ok()?.encode(format).ok() +} + +fn run_geojson(input: &mut Reader<'_>) -> Option { + let name = input.text()?; + crate::geo::geojson(name, input.rest()).ok().map(|data| data.to_patch()) +} + +fn run_pyramid(input: &mut Reader<'_>) -> Option { + let domain = match [input.f64()?, input.f64()?, input.f64()?, input.f64()?] { + [0.0, ..] => Domain::Earth, + [_, x, y, size] => Domain::Plane { min: [x, y], size }, + }; + let count = input.u32()?; + let mut tables = Vec::with_capacity(count as usize); + for _ in 0..count { + let rows = input.u32()?; + let flags = input.u32()?; + let n = rows as usize; + let has = |bit: u32| flags & 1 << bit != 0; + let places = match flags >> 2 & 3 { + 1 => Places::Points(input.words(2 * n)?.as_chunks::<2>().0.iter().map(|w| w.map(f32::from_bits)).collect()), + 2 => Places::Boxes(input.words(4 * n)?.as_chunks::<4>().0.iter().map(|w| w.map(f32::from_bits)).collect()), + _ => Places::None, + }; + let priority = if has(4) { input.words(n)?.into_iter().map(f32::from_bits).collect() } else { Arc::from([]) }; + let ends = if has(5) { + let target = input.u32()?; + let count = input.u32()?; + Some((target, (0..count).map(|_| input.words(n).map(Arc::from)).collect::>>()?)) + } else { + None + }; + tables.push(Placing { rows, leveled: has(0), answered: has(1), places, priority, ends }); + } + Some(crate::derive::pyramid::answer(&Leveling { domain, tables })) +} + +fn run_lanes(input: &mut Reader<'_>) -> Option { + let rows = input.u32()? as usize; + let (from, to) = (input.words(rows)?, input.words(rows)?); + Some(crate::derive::lanes_answer(&from, &to)) +} + +/// Little-endian words, floats, and keys, written. +struct Writer(Vec); + +impl Writer { + fn new(kind: Kind) -> Writer { + let mut out = Writer(Vec::new()); + out.u32(kind as u32); + out + } + + fn u32(&mut self, v: u32) { + self.0.extend(v.to_le_bytes()); + } + + fn f64(&mut self, v: f64) { + self.0.extend(v.to_le_bytes()); + } + + /// Words, copied whole where the machine is little-endian too. + fn words(&mut self, words: &[u32]) { + if cfg!(target_endian = "little") { + self.0.extend_from_slice(bytemuck::cast_slice(words)); + } else { + self.0.extend(words.iter().flat_map(|w| w.to_le_bytes())); + } + } + + fn f64s(&mut self, vs: &[f64]) { + for &v in vs { + self.f64(v); + } + } + + fn text(&mut self, text: &str) { + self.u32(text.len() as u32); + self.0.extend(text.as_bytes()); + } + + /// A key: 1 then a numbered id, or 2 then a texted one; the table's name after. + fn key(&mut self, (table, id): &Key) { + match id { + Id::Number(n) => { + self.u32(1); + self.0.extend(n.to_le_bytes()); + } + Id::Text(t) => { + self.u32(2); + self.text(t); + } + } + self.text(table); + } +} + +/// Little-endian words, floats, and keys, read; `None` past the end. +struct Reader<'a> { + bytes: &'a [u8], +} + +impl<'a> Reader<'a> { + fn new(bytes: &'a [u8]) -> Reader<'a> { + Reader { bytes } + } + + /// Every byte not read yet. + fn rest(&mut self) -> &'a [u8] { + std::mem::take(&mut self.bytes) + } + + fn take(&mut self) -> Option<[u8; N]> { + let (head, rest) = self.bytes.split_first_chunk::()?; + self.bytes = rest; + Some(*head) + } + + fn u32(&mut self) -> Option { + self.take().map(u32::from_le_bytes) + } + + fn f64(&mut self) -> Option { + self.take().map(f64::from_le_bytes) + } + + /// `n` words. + fn words(&mut self, n: usize) -> Option> { + let (head, rest) = self.bytes.split_at_checked(n.checked_mul(4)?)?; + self.bytes = rest; + Some(head.as_chunks::<4>().0.iter().map(|&w| u32::from_le_bytes(w)).collect()) + } + + fn text(&mut self) -> Option { + let len = self.u32()? as usize; + let (head, rest) = self.bytes.split_at_checked(len)?; + self.bytes = rest; + String::from_utf8(head.to_vec()).ok() + } + + /// A key as [`Writer::key`] wrote it. + fn key(&mut self) -> Option { + let id = match self.u32()? { + 1 => Id::Number(u64::from_le_bytes(self.take()?)), + 2 => Id::from(self.text()?), + _ => return None, + }; + Some((self.text()?.into(), id)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::data::Value; + + fn key(table: &str, id: u64) -> Key { + (table.into(), Id::Number(id)) + } + + /// Field `field` of `table`'s row `id` in the answer. + fn answered(answer: &[u8], table: &str, id: u64, field: &str) -> Option { + let mut data = crate::Data::new("d"); + data.apply(Patch::from_bytes(answer).ok()?).ok()?; + data.get(&crate::Row::new("d", table, id), field) + } + + #[test] + fn layout_jobs_answer_the_rows_they_place() { + let sizes = [[10.0, 10.0]; 3]; + let pinned = [None, Some([5.0, 5.0]), None]; + let keys = [Some(key("V", 7)), None, Some(key("V", 9))]; + let placement = Placement { + sizes: &sizes, + pinned: &pinned, + groups: &[None; 3], + pads: &[[0.0; 4]; 3], + links: &[[0, 1], [1, 2]], + keys: &keys, + }; + let answer = Job::from_bytes(Job::layout(&Layout::Layered(Layered::default()), &placement).into_bytes()).run(); + let ranked = layered( + &Graph { + sizes: &sizes, + links: &[[0, 1], [1, 2]], + pinned: &pinned, + groups: &[None; 3], + pads: &[[0.0; 4]; 3], + }, + &Layered::default(), + ); + assert_eq!(answered(&answer, "V", 9, "x"), Some(Value::Number(ranked[2][0]))); + assert_eq!(answered(&answer, "V", 7, "y"), Some(Value::Number(ranked[0][1]))); + let stress = Job::layout(&Layout::Stress(crate::Stress::default()), &placement).run(); + assert!(matches!(answered(&stress, "V", 7, "x"), Some(Value::Number(_))), "stress answers alike"); + } + + #[test] + fn route_jobs_answer_routed_wires() { + let obstacles = [[0.0, 0.0, 10.0, 10.0], [40.0, 0.0, 50.0, 10.0]]; + let terminal = |x: f64, side, owner| Terminal { at: [x, 5.0], side: Some(side), owner: Some(owner) }; + let nets = [Net { terminals: vec![terminal(10.0, Side::Right, 0), terminal(40.0, Side::Left, 1)] }]; + let wiring = Wiring { + obstacles: &obstacles, + groups: &[], + nets: &nets, + keys: &[key("Wire", 3)], + fixed: &[], + spacing: 2.0, + }; + let answer = Job::routes(&wiring).run(); + let want = route(&obstacles, &[], &nets, &[], 2.0).swap_remove(0); + assert_eq!(answered(&answer, "Wire", 3, "route"), Some(Value::Parts(want))); + } + + #[test] + fn bytes_that_are_no_job_answer_nothing() { + assert_eq!(Job::from_bytes(vec![1, 0, 0, 0, 9]).run(), Vec::::new()); + assert_eq!(Job::from_bytes(Vec::new()).run(), Vec::::new()); + } +} diff --git a/crates/latkit/src/host/mod.rs b/crates/latkit/src/host/mod.rs new file mode 100644 index 00000000..80422815 --- /dev/null +++ b/crates/latkit/src/host/mod.rs @@ -0,0 +1,109 @@ +//! What the platform does for latkit: set and measure text in its fonts, do jobs off the frame, fetch +//! bytes (tiles, and the files JSON documents name), and encode video with its [`Encoder`]. A +//! [`Gpu`](crate::Gpu) is given its host with [`Gpu::set_host`](crate::Gpu::set_host); without one, +//! views draw no text, do their jobs at once, fetch nothing, and encode no video. A browser's host is +//! `Browser`, built with the `web` feature for `wasm32`. Natively, the `native` feature supplies +//! `Native`: lazy fonts, a worker pool doing jobs and reading files, and Media Foundation's H.264 on +//! Windows, without a window or network client. + +#[cfg(all(feature = "web", target_arch = "wasm32"))] +mod browser; +mod job; +#[cfg(all(feature = "native", not(target_arch = "wasm32")))] +mod native; + +use std::sync::Arc; + +#[cfg(all(feature = "web", target_arch = "wasm32"))] +pub use browser::Browser; +pub use job::Job; +pub(crate) use job::Placement; +pub(crate) use job::Wiring; +pub(crate) use job::{Key, Shaping}; +#[cfg(all(feature = "native", not(target_arch = "wasm32")))] +pub use native::Native; + +use crate::Encoding; +pub use crate::resource::Request; +use crate::{Error, Pending, Result}; + +/// Ticks of a second an encoder's times count. +pub const TIMESCALE: u32 = 90_000; + +/// A platform's H.264 encoder: NV12 pictures (BT.709, limited range) in, Annex B units out, no +/// B-frames, so every platform's encoder fits and the muxer never reorders. +pub trait Encoder { + /// Encodes one NV12 picture at `time` ticks, a keyframe when `key`; resolves, once it has room + /// for another picture, to the units it finished since the last call, in order. + fn encode(&mut self, nv12: Vec, time: u64, key: bool) -> Pending>; + + /// Resolves to the units it still holds once every picture given is encoded. + fn finish(&mut self) -> Pending>; +} + +/// One encoded access unit of H.264: Annex B bytes, at `time` ticks of [`TIMESCALE`], decode order +/// equal to display order. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Unit { + /// Ticks at which this frame shows. + pub time: u64, + /// Whether it is a keyframe, which carries its parameter sets in band. + pub key: bool, + /// Its NAL units, each after a start code. + pub annex_b: Vec, +} + +/// The platform services a view uses. +pub trait Host: Send + Sync + 'static { + /// Sets `run` as coverage, reporting unavailable fonts or failed rasterization. + fn rasterize(&self, run: &TextRun) -> Result; + + /// The width and height `run` takes once set, in pixels; by default what setting it takes. + fn measure(&self, run: &TextRun) -> Result<[f32; 2]> { + self.rasterize(run).map(|raster| raster.size.map(|v| v as f32)) + } + + /// Does `job` off the frame, resolving to what [`Job::run`] answers; by default at once, on the + /// calling thread. + fn spawn(&self, job: Job) -> Pending> { + Pending::ready(Ok(job.run())) + } + + /// Fetches `request`, resolving to its bytes; to no bytes where there is nothing at its URL, and + /// to an error where it cannot be read. By default a host fetches nothing. + fn fetch(&self, request: &Request) -> Pending> { + let _ = request; + Pending::ready(Err(Error::Unsupported("this host does not fetch".into()))) + } + + /// An H.264 encoder for pictures as `encoding` says, hardware where the platform has one: what an + /// [`Mp4`](crate::Mp4) encodes with. By default a host encodes no video. + fn encoder(&self, encoding: &Encoding) -> crate::Result> { + let _ = encoding; + Err(Error::Unsupported("this host encodes no video".into())) + } +} + +/// A line of text to set. +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub struct TextRun { + /// The text. + pub text: Arc, + /// A CSS font family list. + pub font: Arc, + /// The size in pixels. + pub size_px: u32, + /// Pixels a line runs to before it wraps at a space; `None` keeps one line. + pub max_width: Option, +} + +/// Text set as coverage: one byte per pixel, rows top to bottom. +#[derive(Clone, PartialEq, Debug)] +pub struct Raster { + /// Width and height in pixels. + pub size: [u32; 2], + /// `size[0] * size[1]` coverage bytes. + pub coverage: Vec, + /// Pixels from the top to the baseline. + pub baseline: f32, +} diff --git a/crates/latkit/src/host/native.rs b/crates/latkit/src/host/native.rs new file mode 100644 index 00000000..52e14b92 --- /dev/null +++ b/crates/latkit/src/host/native.rs @@ -0,0 +1,391 @@ +//! Native text, a small, lazily started worker pool, local files, and the platform's H.264 encoder. +//! No window or async runtime is needed. + +#[cfg(windows)] +#[allow(unsafe_code, reason = "Media Foundation is COM: the FFI stays in this module, behind Encoder")] +mod media_foundation; + +use std::io::{Read, Seek, SeekFrom}; +use std::panic::{AssertUnwindSafe, catch_unwind}; +use std::sync::{Arc, Mutex, OnceLock, mpsc}; + +use cosmic_text::{Attrs, Buffer, Color, Family, FontSystem, Metrics, Shaping, SwashCache, Wrap, fontdb}; + +use super::Encoder; +use super::{Host, Job, Raster, Request, TextRun}; +use crate::Encoding; +use crate::{Error, Pending, Resolver, Result}; + +/// Native platform services: shaped text, background jobs, local files, and video. A handle: clones +/// share its fonts and workers. System fonts are discovered only on the first text request; +/// [`from_fonts`](Self::from_fonts) uses only the supplied font bytes. A pool of at most four +/// workers starts on the first job or fetch; a fetch reads a file path, or a `file://` URL, on it. +/// Video encodes with Media Foundation on Windows, hardware where the machine has it; elsewhere this +/// host encodes none. +#[derive(Clone, Default)] +pub struct Native(Arc); + +#[derive(Default)] +struct Services { + text: Mutex>, + workers: OnceLock>, +} + +impl Native { + /// A host that discovers system fonts lazily. Constructing it does no I/O and starts no threads. + pub fn new() -> Self { + Self::default() + } + + /// A host using only these TTF/OTF/TTC bytes, in order; the first family is the generic fallback. + /// No system fonts are discovered. Each item must contain at least one usable face. + pub fn from_fonts(fonts: impl IntoIterator>) -> Result { + let mut db = fontdb::Database::new(); + for (i, font) in fonts.into_iter().enumerate() { + let before = db.faces().count(); + db.load_font_data(font); + if db.faces().count() == before { + return Err(Error::invalid("no usable font faces").at(i).at("fonts")); + } + } + let family = db + .faces() + .next() + .and_then(|face| face.families.first()) + .map(|(name, _)| name.clone()) + .ok_or_else(|| Error::invalid("supply at least one font").at("fonts"))?; + db.set_sans_serif_family(family.clone()); + db.set_serif_family(family.clone()); + db.set_monospace_family(family); + let fonts = FontSystem::new_with_locale_and_db("en-US".into(), db); + let text = Mutex::new(Some(Text { fonts, cache: SwashCache::new() })); + Ok(Self(Arc::new(Services { text, workers: OnceLock::new() }))) + } + + fn with_text(&self, f: impl FnOnce(&mut Text) -> Result) -> Result { + let mut text = self.0.text.lock().map_err(|_| Error::Io("native text service failed".into()))?; + let text = text.get_or_insert_with(Text::system); + if text.fonts.db().faces().next().is_none() { + return Err(Error::Unsupported("no fonts available; supply font bytes with Native::from_fonts".into())); + } + f(text) + } + + /// Does `work` on a worker, resolving to what it answers. + fn work(&self, work: impl FnOnce() -> Result> + Send + 'static) -> Pending> { + let workers = match self.0.workers.get_or_init(Workers::new) { + Ok(workers) => workers, + Err(error) => return Pending::ready(Err(error.clone())), + }; + let (pending, resolver) = Pending::new(); + if let Err(error) = workers.0.send((Box::new(work), resolver)) { + error.0.1.resolve(Err(Error::Io("native workers stopped".into()))); + } + pending + } +} + +impl Host for Native { + fn rasterize(&self, run: &TextRun) -> Result { + self.with_text(|text| { + let (mut buffer, bounds, baseline) = text.layout(run)?; + let size = [(bounds[2] - bounds[0]) as u32, (bounds[3] - bounds[1]) as u32]; + let mut coverage = vec![0; size[0] as usize * size[1] as usize]; + buffer.draw(&mut text.fonts, &mut text.cache, Color::rgb(255, 255, 255), |x, y, w, h, color| { + for row in y..y + h as i32 { + for col in x..x + w as i32 { + let at = (row - bounds[1]) as usize * size[0] as usize + (col - bounds[0]) as usize; + let alpha = u32::from(color.a()); + let old = u32::from(coverage[at]); + coverage[at] = (alpha + (old * (255 - alpha) + 127) / 255) as u8; + } + } + }); + Ok(Raster { size, coverage, baseline: baseline - bounds[1] as f32 }) + }) + } + + fn measure(&self, run: &TextRun) -> Result<[f32; 2]> { + self.with_text(|text| { + let (_, bounds, _) = text.layout(run)?; + Ok([(bounds[2] - bounds[0]) as f32, (bounds[3] - bounds[1]) as f32]) + }) + } + + fn spawn(&self, job: Job) -> Pending> { + self.work(move || Ok(job.run())) + } + + fn fetch(&self, request: &Request) -> Pending> { + let request = request.clone(); + self.work(move || read(&request)) + } + + fn encoder(&self, encoding: &Encoding) -> Result> { + #[cfg(windows)] + return media_foundation::encoder(encoding); + #[cfg(not(windows))] + { + let _ = encoding; + Err(Error::Unsupported( + "native H.264 encoding is Windows' (Media Foundation); this platform has none".into(), + )) + } + } +} + +/// The bytes `request` names of a local file: none where there is no file. +fn read(request: &Request) -> Result> { + let url = &*request.url; + let path = if url.starts_with("file:") { + url::Url::parse(url) + .ok() + .and_then(|url| url.to_file_path().ok()) + .ok_or_else(|| Error::invalid(format!("invalid file URL: {url}")))? + } else { + if url.contains("://") { + return Err(Error::Unsupported(format!("the native host reads files, not {url}").into())); + } + std::path::PathBuf::from(url) + }; + let failed = |e: std::io::Error| Error::Io(format!("{}: {e}", path.display()).into()); + let mut file = match std::fs::File::open(&path) { + Ok(file) => file, + Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(Vec::new()), + Err(e) => return Err(failed(e)), + }; + let mut bytes = Vec::new(); + match &request.range { + None => { + file.read_to_end(&mut bytes).map_err(failed)?; + } + Some(range) => { + file.seek(SeekFrom::Start(range.start)).map_err(failed)?; + file.take(range.end.saturating_sub(range.start)).read_to_end(&mut bytes).map_err(failed)?; + } + } + Ok(bytes) +} + +struct Text { + fonts: FontSystem, + cache: SwashCache, +} + +impl Text { + fn system() -> Self { + // Keep fontdb's platform/fontconfig generic families. FontSystem::new replaces them with + // fixed Linux family names, which may be absent on Windows and macOS. + let mut db = fontdb::Database::new(); + db.load_system_fonts(); + installed_generics(&mut db); + Self { fonts: FontSystem::new_with_locale_and_db("en-US".into(), db), cache: SwashCache::new() } + } + + fn layout(&mut self, run: &TextRun) -> Result<(Buffer, [i32; 4], f32)> { + if run.size_px == 0 || run.size_px > 4096 || run.max_width == Some(0) { + return Err(Error::invalid("text size must be 1..=4096 pixels and wrap width must be positive")); + } + // Resolve the CSS family list in order, including generic families. Cosmic supplies glyph + // fallback within the chosen database, including shaping for complex scripts. + let family = run + .font + .split(',') + .map(|name| name.trim().trim_matches(['\'', '"'])) + .map(|name| match name { + "serif" => Family::Serif, + "monospace" => Family::Monospace, + "sans-serif" | "system-ui" => Family::SansSerif, + _ => Family::Name(name), + }) + .find(|family| { + self.fonts.db().query(&fontdb::Query { families: &[*family], ..Default::default() }).is_some() + }) + .unwrap_or(Family::SansSerif); + let size = run.size_px as f32; + let mut buffer = Buffer::new(&mut self.fonts, Metrics::new(size, size * 1.25)); + buffer.set_size(run.max_width.map(|width| width as f32), None); + buffer.set_wrap(if run.max_width.is_some() { Wrap::Word } else { Wrap::None }); + buffer.set_text(&run.text, &Attrs::new().family(family), Shaping::Advanced, None); + buffer.shape_until_scroll(&mut self.fonts, false); + let baseline = buffer.layout_runs().next().map_or(size, |line| line.line_y); + let mut bounds = [0, 0, 1, (size * 1.25).ceil() as i32]; + for line in buffer.layout_runs() { + bounds[2] = bounds[2].max(line.line_w.ceil() as i32); + bounds[3] = bounds[3].max((line.line_top + line.line_height).ceil() as i32); + if line.glyphs.iter().any(|glyph| glyph.glyph_id == 0) { + return Err(Error::Unsupported( + "available fonts do not cover this text; supply a fallback font".into(), + )); + } + } + buffer.draw(&mut self.fonts, &mut self.cache, Color::rgb(255, 255, 255), |x, y, w, h, _| { + bounds[0] = bounds[0].min(x); + bounds[1] = bounds[1].min(y); + bounds[2] = bounds[2].max(x + w as i32); + bounds[3] = bounds[3].max(y + h as i32); + }); + bounds[0] -= 2; + bounds[1] -= 2; + bounds[2] += 2; + bounds[3] += 2; + if bounds[2] - bounds[0] > 4096 || bounds[3] - bounds[1] > 4096 { + return Err(Error::Limit("text raster exceeds 4096 pixels on one axis".into())); + } + Ok((buffer, bounds, baseline)) + } +} + +/// Points each generic family at an installed one. fontdb names a generic after fontconfig's last +/// alias for it, installed or not: stock Ubuntu's last `sans-serif` alias prefers `FreeSans`, which +/// it does not ship. A generic naming nothing installed takes the first installed of its common +/// families, else any installed family. +fn installed_generics(db: &mut fontdb::Database) { + fn has(db: &fontdb::Database, family: Family<'_>) -> bool { + db.query(&fontdb::Query { families: &[family], ..Default::default() }).is_some() + } + type Set = fn(&mut fontdb::Database, String); + let generics: [(Family<'_>, &[&str], Set); 3] = [ + ( + Family::SansSerif, + &["DejaVu Sans", "Noto Sans", "Liberation Sans", "Arial", "Helvetica"], + fontdb::Database::set_sans_serif_family::, + ), + ( + Family::Serif, + &["DejaVu Serif", "Noto Serif", "Liberation Serif", "Times New Roman", "Times"], + fontdb::Database::set_serif_family::, + ), + ( + Family::Monospace, + &["DejaVu Sans Mono", "Noto Sans Mono", "Liberation Mono", "Courier New", "Menlo"], + fontdb::Database::set_monospace_family::, + ), + ]; + let any = db.faces().find_map(|face| face.families.first()).map(|(name, _)| name.clone()); + for (generic, common, set) in generics { + if has(db, generic) { + continue; + } + let name = common.iter().find(|name| has(db, Family::Name(name))).map(ToString::to_string); + if let Some(name) = name.or_else(|| any.clone()) { + set(db, name); + } + } +} + +type Task = (Box Result> + Send>, Resolver>); +struct Workers(mpsc::Sender); + +impl Workers { + fn new() -> Result { + let (sender, receiver) = mpsc::channel::(); + let receiver = Arc::new(Mutex::new(receiver)); + let count = std::thread::available_parallelism().map_or(1, |n| n.get().saturating_sub(1).clamp(1, 4)); + for i in 0..count { + let receiver = receiver.clone(); + std::thread::Builder::new() + .name(format!("latkit-{i}")) + .spawn(move || { + loop { + let task = receiver.lock().expect("worker queue").recv(); + let Ok((work, resolver)) = task else { break }; + if resolver.is_cancelled() { + continue; + } + let result = catch_unwind(AssertUnwindSafe(work)) + .unwrap_or_else(|_| Err(Error::Io("native work panicked".into()))); + resolver.resolve(result); + } + }) + .map_err(|error| Error::Io(format!("cannot start native worker: {error}").into()))?; + } + Ok(Self(sender)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn font_bytes() -> Vec { + let fonts = Text::system().fonts; + let id = fonts + .db() + .query(&fontdb::Query { families: &[Family::SansSerif], ..Default::default() }) + .expect("native text tests require a system sans-serif font"); + fonts.db().with_face_data(id, |bytes, _| bytes.to_vec()).expect("font bytes") + } + + #[test] + fn generic_families_name_installed_fonts() { + let mut db = fontdb::Database::new(); + db.load_system_fonts(); + db.set_sans_serif_family("Not Installed Sans"); + db.set_monospace_family("Not Installed Mono"); + installed_generics(&mut db); + for generic in [Family::SansSerif, Family::Monospace] { + assert!(db.query(&fontdb::Query { families: &[generic], ..Default::default() }).is_some()); + } + } + + #[test] + fn services_are_lazy_and_explicit_fonts_are_validated() { + let native = Native::new(); + assert!(native.0.text.lock().unwrap().is_none()); + assert!(native.0.workers.get().is_none()); + assert!(Native::from_fonts([]).is_err()); + assert!(Native::from_fonts([b"not a font".to_vec()]).is_err()); + } + + #[test] + fn shaped_text_measures_wraps_and_reuses_the_glyph_cache() { + let host = Native::from_fonts([font_bytes()]).unwrap(); + let mut run = TextRun { + text: "Hello world office".into(), + font: "Missing Font, sans-serif".into(), + size_px: 32, + max_width: None, + }; + let raster = host.rasterize(&run).unwrap(); + assert!(raster.coverage.iter().any(|&alpha| alpha > 0)); + assert!(raster.coverage.contains(&0)); + assert_eq!(host.measure(&run).unwrap(), raster.size.map(|n| n as f32)); + assert_eq!(host.rasterize(&run).unwrap(), raster); + assert!(raster.baseline > 0.0 && raster.baseline < raster.size[1] as f32); + run.max_width = Some(130); + let wrapped = host.rasterize(&run).unwrap(); + assert!(wrapped.size[1] > raster.size[1]); + assert!(wrapped.size[0] < raster.size[0]); + } + + #[test] + fn fetches_read_local_files_and_their_ranges() { + let dir = std::env::temp_dir().join(format!("latkit-fetch-{}", std::process::id())); + std::fs::create_dir_all(&dir).unwrap(); + let path = dir.join("bytes.bin"); + std::fs::write(&path, b"0123456789").unwrap(); + let host = Native::new(); + let fetch = |request: Request| pollster::block_on(host.fetch(&request)); + let url = path.to_string_lossy().into_owned(); + assert_eq!(fetch(Request::new(url.as_str())).unwrap(), b"0123456789"); + assert_eq!(fetch(Request::range(format!("file://{url}"), 3..6)).unwrap(), b"345"); + assert_eq!(fetch(Request::range(url.as_str(), 8..20)).unwrap(), b"89", "a range past the end"); + assert_eq!(fetch(Request::new(dir.join("none").to_string_lossy().into_owned())).unwrap(), b""); + assert!(fetch(Request::new("https://example.com/tiles")).is_err()); + std::fs::remove_dir_all(dir).unwrap(); + } + + #[test] + fn background_jobs_complete_without_a_runtime_or_font_discovery() { + let host = Native::new(); + let image = crate::Image::new([1, 1], vec![255, 0, 0, 128]).unwrap(); + let jobs: Vec<_> = (0..12).map(|_| host.spawn(Job::encode(&image, crate::ImageFormat::Png))).collect(); + for job in jobs { + assert_eq!(crate::Image::from_png(&pollster::block_on(job).unwrap()).unwrap(), image); + } + assert!(host.0.text.lock().unwrap().is_none()); + let clone = host.clone(); + assert!(Arc::ptr_eq(&clone.0, &host.0), "clones share the workers and fonts"); + } +} diff --git a/crates/latkit/src/host/native/media_foundation.rs b/crates/latkit/src/host/native/media_foundation.rs new file mode 100644 index 00000000..58cce9a6 --- /dev/null +++ b/crates/latkit/src/host/native/media_foundation.rs @@ -0,0 +1,716 @@ +//! H.264 through Windows Media Foundation: the platform's encoder transform, hardware where the +//! machine has one and the software encoder otherwise, on a thread of its own so encoding overlaps +//! drawing. NV12 pictures in, Annex B units out, no B-frames, keyframes where asked. + +use std::collections::VecDeque; +use std::mem::ManuallyDrop; +use std::sync::mpsc::{self, Receiver, Sender}; +use std::time::{Duration, Instant}; + +use windows::Win32::Media::MediaFoundation::{ + CODECAPI_AVEncCommonMeanBitRate, CODECAPI_AVEncCommonRateControlMode, CODECAPI_AVEncMPVDefaultBPictureCount, + CODECAPI_AVEncMPVGOPSize, CODECAPI_AVEncVideoForceKeyFrame, CODECAPI_AVLowLatencyMode, ICodecAPI, IMFActivate, + IMFAsyncCallback, IMFMediaEventGenerator, IMFMediaType, IMFSample, IMFTransform, METransformDrainComplete, + METransformHaveOutput, METransformNeedInput, MF_E_INVALIDMEDIATYPE, MF_E_NOTACCEPTING, + MF_E_TRANSFORM_NEED_MORE_INPUT, MF_E_TRANSFORM_STREAM_CHANGE, MF_LOW_LATENCY, MF_MT_AVG_BITRATE, + MF_MT_DEFAULT_STRIDE, MF_MT_FRAME_RATE, MF_MT_FRAME_SIZE, MF_MT_INTERLACE_MODE, MF_MT_MAJOR_TYPE, + MF_MT_MPEG_SEQUENCE_HEADER, MF_MT_MPEG2_PROFILE, MF_MT_PIXEL_ASPECT_RATIO, MF_MT_SUBTYPE, MF_MT_TRANSFER_FUNCTION, + MF_MT_VIDEO_NOMINAL_RANGE, MF_MT_VIDEO_PRIMARIES, MF_MT_YUV_MATRIX, MF_TRANSFORM_ASYNC, MF_TRANSFORM_ASYNC_UNLOCK, + MF_VERSION, MFCreateMediaType, MFCreateMemoryBuffer, MFCreateSample, MFMediaType_Video, MFNominalRange_16_235, + MFSTARTUP_FULL, MFShutdown, MFStartup, MFT_CATEGORY_VIDEO_ENCODER, MFT_ENUM_FLAG, MFT_ENUM_FLAG_HARDWARE, + MFT_ENUM_FLAG_SORTANDFILTER, MFT_ENUM_FLAG_SYNCMFT, MFT_MESSAGE_COMMAND_DRAIN, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, + MFT_MESSAGE_NOTIFY_END_OF_STREAM, MFT_MESSAGE_NOTIFY_END_STREAMING, MFT_MESSAGE_NOTIFY_START_OF_STREAM, + MFT_OUTPUT_DATA_BUFFER, MFT_OUTPUT_STREAM_PROVIDES_SAMPLES, MFT_REGISTER_TYPE_INFO, MFTEnumEx, MFVideoFormat_H264, + MFVideoFormat_NV12, MFVideoInterlace_Progressive, MFVideoPrimaries_BT709, MFVideoTransFunc_709, + MFVideoTransferMatrix_BT709, eAVEncCommonRateControlMode_UnconstrainedVBR, eAVEncH264VProfile_High, +}; +use windows::Win32::System::Com::{COINIT_MULTITHREADED, CoInitializeEx, CoTaskMemFree, CoUninitialize}; +use windows::Win32::System::Variant::VARIANT; +use windows::core::Interface; + +use crate::host::{Encoder, TIMESCALE, Unit}; +use crate::video::nals; +use crate::{Encoding, Error, Pending, Resolver, Result}; +use tell::Tell; + +/// The longest the transform may take to start, to want a picture, or to drain. +const STALL: Duration = Duration::from_secs(20); +/// Seconds between the keyframes the encoder places itself; the video asks for its own besides. +const KEYFRAMES: f64 = 2.0; +/// 100-nanosecond ticks a second, Media Foundation's clock. +const HNS: u64 = 10_000_000; + +/// An encoder on a thread of its own, where Media Foundation lives. +struct MediaFoundation { + work: Option>, +} + +/// What the encoder's thread is handed: a picture, with what tells the encoder it has room for +/// another; or the end. +enum Work { + Picture { nv12: Vec, time: u64, key: bool, room: Resolver> }, + Finish(Resolver>), +} + +/// An encoder for pictures as `encoding` says: the machine's hardware encoder where one starts, else +/// Windows' software encoder. +pub(super) fn encoder(encoding: &Encoding) -> Result> { + open(*encoding, &[hardware(), software()]).map(|e| Box::new(e) as Box) +} + +fn hardware() -> MFT_ENUM_FLAG { + MFT_ENUM_FLAG_HARDWARE | MFT_ENUM_FLAG_SORTANDFILTER +} + +fn software() -> MFT_ENUM_FLAG { + MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_SORTANDFILTER +} + +/// An encoder from the first transform of `kinds`, in order, that starts. +fn open(encoding: Encoding, kinds: &[MFT_ENUM_FLAG]) -> Result { + let (started, ready) = mpsc::channel(); + let (work, pictures) = mpsc::channel(); + let kinds = kinds.to_vec(); + std::thread::Builder::new() + .name("latkit encoder".into()) + .spawn(move || run(encoding, &kinds, &started, &pictures)) + .map_err(|e| Error::Io(format!("the encoder's thread did not start: {e}").into()))?; + match ready.recv_timeout(STALL) { + Ok(Ok(())) => Ok(MediaFoundation { work: Some(work) }), + Ok(Err(error)) => Err(error), + Err(_) => Err(Error::Timeout), + } +} + +fn stopped() -> Error { + Error::Unsupported("the Media Foundation encoder stopped".into()) +} + +impl Encoder for MediaFoundation { + fn encode(&mut self, nv12: Vec, time: u64, key: bool) -> Pending> { + let (pending, room) = Pending::new(); + match &self.work { + Some(work) if work.send(Work::Picture { nv12, time, key, room }).is_ok() => pending, + _ => Pending::ready(Err(stopped())), + } + } + + fn finish(&mut self) -> Pending> { + let (pending, resolver) = Pending::new(); + match self.work.take() { + Some(work) if work.send(Work::Finish(resolver)).is_ok() => pending, + _ => Pending::ready(Err(stopped())), + } + } +} + +/// The encoder's thread: starts Media Foundation and the transform, then encodes what it is handed +/// until it finishes or the encoder is dropped. Taking a picture tells there is room for another, +/// with the units finished before it; after an error, every picture is answered with it. +fn run(encoding: Encoding, kinds: &[MFT_ENUM_FLAG], started: &Sender>, work: &Receiver) { + let session = match Session::new() { + Ok(session) => session, + Err(error) => { + let _ = started.send(Err(error)); + return; + } + }; + let mut transform = match Transform::first(&encoding, kinds) { + Ok(transform) => transform, + Err(error) => { + let _ = started.send(Err(error)); + return; + } + }; + let _ = started.send(Ok(())); + let mut finished = Vec::new(); + let mut failure: Option = None; + for item in work { + match item { + Work::Picture { nv12, time, key, room } => { + if let Some(error) = &failure { + room.resolve(Err(error.clone())); + continue; + } + room.resolve(Ok(std::mem::take(&mut finished))); + match transform.encode(&nv12, time, key) { + Ok(units) => finished.extend(units), + Err(error) => failure = Some(error), + } + } + Work::Finish(resolver) => { + let result = match failure.take() { + Some(error) => Err(error), + None => transform.finish().map(|units| { + finished.extend(units); + std::mem::take(&mut finished) + }), + }; + resolver.resolve(result); + break; + } + } + } + drop(transform); + drop(session); +} + +/// A failed Media Foundation call, named. +fn failed(call: &str, error: &windows::core::Error) -> Error { + Error::Unsupported(format!("the Media Foundation encoder's {call}: {error}").into()) +} + +/// COM and Media Foundation, started on this thread and shut down with it. +struct Session { + media: bool, +} + +impl Session { + fn new() -> Result { + // SAFETY: initialized on this thread, uninitialized on it when the session drops. + unsafe { CoInitializeEx(None, COINIT_MULTITHREADED).ok().map_err(|e| failed("CoInitializeEx", &e))? }; + let mut session = Session { media: false }; + // SAFETY: paired with MFShutdown when the session drops, on this thread. + unsafe { MFStartup(MF_VERSION, MFSTARTUP_FULL).map_err(|e| failed("MFStartup", &e))? }; + session.media = true; + Ok(session) + } +} + +impl Drop for Session { + fn drop(&mut self) { + // SAFETY: every transform, sample, and buffer of this thread was released before. + unsafe { + if self.media { + let _ = MFShutdown(); + } + CoUninitialize(); + } + } +} + +/// One H.264 encoder transform, streaming. +struct Transform { + activate: IMFActivate, + mft: IMFTransform, + codec: Option, + /// An asynchronous transform's events: hardware encoders are asynchronous. + events: Option, + /// Inputs an asynchronous transform asked for and was not given. + wanted: u32, + input: u32, + output: u32, + /// Whether the transform makes its output samples; else, how large a buffer it takes. + provides: bool, + output_size: u32, + /// The times of the pictures given and not yet encoded, in order: no B-frames reorder them. + times: VecDeque, + /// The SPS and PPS, Annex B, for keyframes that leave them out. + header: Vec, + /// Parameter sets the transform gave as units of their own, for the next picture. + prefix: Vec, + encoding: Encoding, +} + +impl Transform { + /// The first transform of `kinds` that starts for `encoding`. + fn first(encoding: &Encoding, kinds: &[MFT_ENUM_FLAG]) -> Result { + let mut last = Error::Unsupported("this machine has no H.264 encoder".into()); + for &kind in kinds { + for activate in activates(kind)? { + match Transform::new(activate, encoding) { + Ok(transform) => return Ok(transform), + Err(error) => last = error, + } + } + } + Err(last) + } + + fn new(activate: IMFActivate, encoding: &Encoding) -> Result { + let [width, height] = encoding.size; + let [num, den] = encoding.rate(); + // SAFETY: owned COM handles; every pointer argument borrows a value that outlives its call. + unsafe { + let mft: IMFTransform = activate.ActivateObject().map_err(|e| failed("ActivateObject", &e))?; + let mut transform = Transform { + activate, + codec: mft.cast::().ok(), + events: None, + wanted: 0, + input: 0, + output: 0, + provides: false, + output_size: 0, + times: VecDeque::new(), + header: Vec::new(), + prefix: Vec::new(), + encoding: *encoding, + mft, + }; + if let Ok(attributes) = transform.mft.GetAttributes() { + if attributes.GetUINT32(&MF_TRANSFORM_ASYNC).unwrap_or(0) != 0 { + attributes.SetUINT32(&MF_TRANSFORM_ASYNC_UNLOCK, 1).map_err(|e| failed("SetUINT32", &e))?; + transform.events = Some(Events::new(transform.mft.cast().map_err(|e| failed("cast", &e))?)); + } + let _ = attributes.SetUINT32(&MF_LOW_LATENCY, 1); + } + let (mut inputs, mut outputs) = ([0_u32], [0_u32]); + if transform.mft.GetStreamIDs(&mut inputs, &mut outputs).is_ok() { + (transform.input, transform.output) = (inputs[0], outputs[0]); + } + if let Some(codec) = &transform.codec { + // What an encoder cannot set it does without: these only shape its output. + let gop = (encoding.fps * KEYFRAMES).round().max(1.0) as u32; + let rate = eAVEncCommonRateControlMode_UnconstrainedVBR.0 as u32; + for (api, value) in [ + (&CODECAPI_AVEncCommonRateControlMode, VARIANT::from(rate)), + (&CODECAPI_AVEncCommonMeanBitRate, VARIANT::from(encoding.bitrate)), + (&CODECAPI_AVEncMPVDefaultBPictureCount, VARIANT::from(0_u32)), + (&CODECAPI_AVEncMPVGOPSize, VARIANT::from(gop)), + (&CODECAPI_AVLowLatencyMode, VARIANT::from(true)), + ] { + let _ = codec.SetValue(api, &raw const value); + } + } + let output = MFCreateMediaType().map_err(|e| failed("MFCreateMediaType", &e))?; + output.SetGUID(&MF_MT_MAJOR_TYPE, &MFMediaType_Video).map_err(|e| failed("SetGUID", &e))?; + output.SetGUID(&MF_MT_SUBTYPE, &MFVideoFormat_H264).map_err(|e| failed("SetGUID", &e))?; + output.SetUINT32(&MF_MT_AVG_BITRATE, encoding.bitrate).map_err(|e| failed("SetUINT32", &e))?; + output + .SetUINT32(&MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_High.0 as u32) + .map_err(|e| failed("SetUINT32", &e))?; + picture(&output, width, height, num, den)?; + transform.mft.SetOutputType(transform.output, &output, 0).map_err(|e| { + if e.code() == MF_E_INVALIDMEDIATYPE { + Error::Unsupported( + format!("this H.264 encoder takes no {width}×{height} pictures at {num}/{den} fps").into(), + ) + } else { + failed("SetOutputType", &e) + } + })?; + let input = transform.input_type(width, height, num, den)?; + transform.mft.SetInputType(transform.input, &input, 0).map_err(|e| failed("SetInputType", &e))?; + transform.output_info()?; + transform.header = header(&transform.mft, transform.output); + transform + .mft + .ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0) + .map_err(|e| failed("ProcessMessage", &e))?; + transform + .mft + .ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0) + .map_err(|e| failed("ProcessMessage", &e))?; + Ok(transform) + } + } + + /// The NV12 input type: the transform's own where it offers one, else a type of ours. + fn input_type(&self, width: u32, height: u32, num: u32, den: u32) -> Result { + // SAFETY: owned COM handles only. + unsafe { + let offered = (0..64) + .map_while(|i| self.mft.GetInputAvailableType(self.input, i).ok()) + .find(|t| t.GetGUID(&MF_MT_SUBTYPE).is_ok_and(|s| s == MFVideoFormat_NV12)); + let input = if let Some(input) = offered { + input + } else { + let input = MFCreateMediaType().map_err(|e| failed("MFCreateMediaType", &e))?; + input.SetGUID(&MF_MT_MAJOR_TYPE, &MFMediaType_Video).map_err(|e| failed("SetGUID", &e))?; + input.SetGUID(&MF_MT_SUBTYPE, &MFVideoFormat_NV12).map_err(|e| failed("SetGUID", &e))?; + input + }; + input.SetUINT32(&MF_MT_DEFAULT_STRIDE, width).map_err(|e| failed("SetUINT32", &e))?; + picture(&input, width, height, num, den)?; + Ok(input) + } + } + + /// Whether the transform makes its own output samples, and how large ours must be otherwise. + fn output_info(&mut self) -> Result<()> { + // SAFETY: owned COM handles only. + let info = + unsafe { self.mft.GetOutputStreamInfo(self.output) }.map_err(|e| failed("GetOutputStreamInfo", &e))?; + self.provides = info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES.0 as u32 != 0; + let [width, height] = self.encoding.size; + self.output_size = info.cbSize.max(width * height * 3 / 2); + Ok(()) + } + + /// Encodes one NV12 picture at `time` ticks, a keyframe when `key`: the units the transform + /// finished meanwhile. + fn encode(&mut self, nv12: &[u8], time: u64, key: bool) -> Result> { + let sample = self.sample(nv12, time)?; + if key && let Some(codec) = &self.codec { + let force = VARIANT::from(1_u32); + // SAFETY: a value borrowed for the call. + let _ = unsafe { codec.SetValue(&CODECAPI_AVEncVideoForceKeyFrame, &raw const force) }; + } + self.times.push_back(time); + let mut units = Vec::new(); + if self.events.is_some() { + while self.wanted == 0 { + self.event(true, &mut units)?; + } + self.wanted -= 1; + self.input(&sample)?; + // Whatever it told meanwhile: outputs ready, and inputs wanted. + while self.event(false, &mut units)? {} + } else { + let started = Instant::now(); + loop { + // SAFETY: an owned sample, borrowed for the call. + match unsafe { self.mft.ProcessInput(self.input, &sample, 0) } { + Ok(()) => break, + Err(e) if e.code() == MF_E_NOTACCEPTING && started.elapsed() < STALL => self.drain(&mut units)?, + Err(e) => return Err(failed("ProcessInput", &e)), + } + } + self.drain(&mut units)?; + } + Ok(units) + } + + /// The units the transform still holds once every picture given is encoded. + fn finish(&mut self) -> Result> { + let mut units = Vec::new(); + // SAFETY: plain messages to an owned transform. + unsafe { + self.mft.ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0).map_err(|e| failed("ProcessMessage", &e))?; + self.mft.ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, 0).map_err(|e| failed("ProcessMessage", &e))?; + } + if self.events.is_some() { + loop { + match self.events.as_mut().expect("an asynchronous transform").next(true)? { + Some(kind) if kind == METransformHaveOutput.0 as u32 => self.drain_one(&mut units)?, + Some(kind) if kind == METransformDrainComplete.0 as u32 => break, + _ => {} + } + } + } else { + self.drain(&mut units)?; + } + // SAFETY: a plain message to an owned transform. + let _ = unsafe { self.mft.ProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 0) }; + Ok(units) + } + + /// Gives a synchronous transform `sample`, or an asynchronous one that asked for it. + fn input(&self, sample: &IMFSample) -> Result<()> { + // SAFETY: an owned sample, borrowed for the call. + unsafe { self.mft.ProcessInput(self.input, sample, 0) }.map_err(|e| failed("ProcessInput", &e)) + } + + /// Handles the asynchronous transform's next event, waiting for it, up to the stall, when `wait`: + /// an input wanted is counted, an output ready is taken into `units`. Whether there was one. + fn event(&mut self, wait: bool, units: &mut Vec) -> Result { + let events = self.events.as_mut().expect("an asynchronous transform"); + match events.next(wait)? { + Some(kind) if kind == METransformNeedInput.0 as u32 => self.wanted += 1, + Some(kind) if kind == METransformHaveOutput.0 as u32 => self.drain_one(units)?, + Some(_) => {} + None => return Ok(false), + } + Ok(true) + } + + /// Takes every output a synchronous transform has ready into `units`. + fn drain(&mut self, units: &mut Vec) -> Result<()> { + while self.output(units)? {} + Ok(()) + } + + /// Takes the output an asynchronous transform said it has. + fn drain_one(&mut self, units: &mut Vec) -> Result<()> { + self.output(units).map(|_| ()) + } + + /// Takes one output into `units`: whether there was one, rather than a want of input. + fn output(&mut self, units: &mut Vec) -> Result { + for _ in 0..4 { + let sample = if self.provides { None } else { Some(empty(self.output_size)?) }; + let mut buffer = MFT_OUTPUT_DATA_BUFFER { + dwStreamID: self.output, + pSample: ManuallyDrop::new(sample), + dwStatus: 0, + pEvents: ManuallyDrop::new(None), + }; + let mut status = 0; + // SAFETY: the buffer's sample and events are taken back below, whatever the result. + let result = unsafe { self.mft.ProcessOutput(0, std::slice::from_mut(&mut buffer), &raw mut status) }; + let sample = unsafe { ManuallyDrop::take(&mut buffer.pSample) }; + drop(unsafe { ManuallyDrop::take(&mut buffer.pEvents) }); + match result { + Ok(()) => {} + Err(e) if e.code() == MF_E_TRANSFORM_NEED_MORE_INPUT => return Ok(false), + Err(e) if e.code() == MF_E_TRANSFORM_STREAM_CHANGE => { + // SAFETY: owned COM handles. + unsafe { + let changed = self + .mft + .GetOutputAvailableType(self.output, 0) + .map_err(|e| failed("GetOutputAvailableType", &e))?; + self.mft.SetOutputType(self.output, &changed, 0).map_err(|e| failed("SetOutputType", &e))?; + self.output_info()?; + } + // An asynchronous transform says when the output is ready in its new type. + if self.events.is_some() { + return Ok(true); + } + continue; + } + Err(e) => return Err(failed("ProcessOutput", &e)), + } + let Some(sample) = sample else { return Err(Error::Io("the encoder gave no sample".into())) }; + let bytes = bytes(&sample)?; + let types: Vec = nals(&bytes).map(|nal| nal[0] & 0x1f).collect(); + if !types.iter().any(|t| (1..=5).contains(t)) { + // Parameter sets alone: they lead the next picture. + self.prefix.extend_from_slice(&bytes); + return Ok(true); + } + let key = types.contains(&5); + let mut annex_b = std::mem::take(&mut self.prefix); + if key && !types.contains(&7) && !annex_b.windows(4).any(|w| w == [0, 0, 1, 0x67]) { + annex_b.extend_from_slice(&self.header); + } + annex_b.extend_from_slice(&bytes); + let time = self.times.pop_front().ok_or_else(|| Error::Io("the encoder gave more than given".into()))?; + units.push(Unit { time, key, annex_b }); + return Ok(true); + } + Err(Error::Io("the encoder kept changing its output".into())) + } + + /// A sample of NV12 `bytes` showing at `time` ticks for a frame's duration. + fn sample(&self, bytes: &[u8], time: u64) -> Result { + let length = u32::try_from(bytes.len()).map_err(|_| Error::invalid("the picture is too large to encode"))?; + let sample = empty(length)?; + // SAFETY: the buffer holds `length` bytes; the mapped slice never outlives its lock. + unsafe { + let buffer = sample.GetBufferByIndex(0).map_err(|e| failed("GetBufferByIndex", &e))?; + let mut address = std::ptr::null_mut(); + buffer.Lock(&raw mut address, None, None).map_err(|e| failed("Lock", &e))?; + std::ptr::copy_nonoverlapping(bytes.as_ptr(), address, bytes.len()); + buffer.Unlock().map_err(|e| failed("Unlock", &e))?; + buffer.SetCurrentLength(length).map_err(|e| failed("SetCurrentLength", &e))?; + let hns = |ticks: u64| (u128::from(ticks) * u128::from(HNS) / u128::from(TIMESCALE)) as i64; + sample.SetSampleTime(hns(time)).map_err(|e| failed("SetSampleTime", &e))?; + let frame = (HNS as f64 / self.encoding.fps).round() as i64; + sample.SetSampleDuration(frame).map_err(|e| failed("SetSampleDuration", &e))?; + } + Ok(sample) + } +} + +/// A sample with one empty buffer of `length` bytes. +fn empty(length: u32) -> Result { + // SAFETY: owned COM handles. + unsafe { + let buffer = MFCreateMemoryBuffer(length).map_err(|e| failed("MFCreateMemoryBuffer", &e))?; + let sample = MFCreateSample().map_err(|e| failed("MFCreateSample", &e))?; + sample.AddBuffer(&buffer).map_err(|e| failed("AddBuffer", &e))?; + Ok(sample) + } +} + +impl Drop for Transform { + fn drop(&mut self) { + // SAFETY: an asynchronous transform is shut down through what activated it, once. + let _ = unsafe { self.activate.ShutdownObject() }; + } +} + +/// The transforms encoding NV12 into H.264 of `kind`, the best first. +fn activates(kind: MFT_ENUM_FLAG) -> Result> { + let input = MFT_REGISTER_TYPE_INFO { guidMajorType: MFMediaType_Video, guidSubtype: MFVideoFormat_NV12 }; + let output = MFT_REGISTER_TYPE_INFO { guidMajorType: MFMediaType_Video, guidSubtype: MFVideoFormat_H264 }; + let mut list: *mut Option = std::ptr::null_mut(); + let mut count = 0_u32; + // SAFETY: Media Foundation allocates the list; each item is taken from it, then it is freed. + unsafe { + MFTEnumEx( + MFT_CATEGORY_VIDEO_ENCODER, + kind, + Some(&raw const input), + Some(&raw const output), + &raw mut list, + &raw mut count, + ) + .map_err(|e| failed("MFTEnumEx", &e))?; + if list.is_null() { + return Ok(Vec::new()); + } + let items = std::slice::from_raw_parts_mut(list, count as usize); + let activates = items.iter_mut().filter_map(Option::take).collect(); + CoTaskMemFree(Some(list.cast_const().cast())); + Ok(activates) + } +} + +/// Sets what a picture is on `kind`: its size and rate, progressive, square pixels, BT.709 limited. +fn picture(kind: &IMFMediaType, width: u32, height: u32, num: u32, den: u32) -> Result<()> { + // SAFETY: owned COM handles, values borrowed for each call. + unsafe { + kind.SetUINT64(&MF_MT_FRAME_SIZE, (u64::from(width) << 32) | u64::from(height)) + .map_err(|e| failed("SetUINT64", &e))?; + kind.SetUINT64(&MF_MT_FRAME_RATE, (u64::from(num) << 32) | u64::from(den)) + .map_err(|e| failed("SetUINT64", &e))?; + kind.SetUINT32(&MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive.0 as u32) + .map_err(|e| failed("SetUINT32", &e))?; + kind.SetUINT64(&MF_MT_PIXEL_ASPECT_RATIO, (1_u64 << 32) | 1).map_err(|e| failed("SetUINT64", &e))?; + let _ = kind.SetUINT32(&MF_MT_VIDEO_PRIMARIES, MFVideoPrimaries_BT709.0 as u32); + let _ = kind.SetUINT32(&MF_MT_TRANSFER_FUNCTION, MFVideoTransFunc_709.0 as u32); + let _ = kind.SetUINT32(&MF_MT_YUV_MATRIX, MFVideoTransferMatrix_BT709.0 as u32); + let _ = kind.SetUINT32(&MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_16_235.0 as u32); + } + Ok(()) +} + +/// The SPS and PPS the transform's output type carries, Annex B; none where it carries them in band. +fn header(mft: &IMFTransform, output: u32) -> Vec { + // SAFETY: owned COM handles; the blob is copied into a buffer of its size. + unsafe { + let Ok(kind) = mft.GetOutputCurrentType(output) else { return Vec::new() }; + let Ok(size) = kind.GetBlobSize(&MF_MT_MPEG_SEQUENCE_HEADER) else { return Vec::new() }; + let mut blob = vec![0; size as usize]; + if kind.GetBlob(&MF_MT_MPEG_SEQUENCE_HEADER, &mut blob, None).is_err() || !blob.starts_with(&[0, 0]) { + return Vec::new(); + } + blob + } +} + +/// An asynchronous transform's events, told as they come to the callback each request names. +struct Events { + generator: IMFMediaEventGenerator, + callback: IMFAsyncCallback, + told: Receiver>, + /// Whether an event was asked for and not yet told. + asked: bool, +} + +impl Events { + fn new(generator: IMFMediaEventGenerator) -> Events { + let (tell, told) = mpsc::channel(); + let callback = Tell { generator: generator.clone(), tell }.into(); + Events { generator, callback, told, asked: false } + } + + /// The type of the next event: waiting for it up to the stall when `wait`, else `None` while + /// none was told. + fn next(&mut self, wait: bool) -> Result> { + if !self.asked { + // SAFETY: owned COM handles; the callback outlives the request it answers. + unsafe { self.generator.BeginGetEvent(&self.callback, None::<&windows::core::IUnknown>) } + .map_err(|e| failed("BeginGetEvent", &e))?; + self.asked = true; + } + let told = if wait { self.told.recv_timeout(STALL).ok() } else { self.told.try_recv().ok() }; + match told { + Some(kind) => { + self.asked = false; + kind.map(Some).map_err(|e| failed("EndGetEvent", &e)) + } + None if wait => Err(Error::Timeout), + None => Ok(None), + } + } +} + +/// What a transform tells its next event to: a COM object of ours, as `windows::core::implement` +/// writes one. +#[allow(clippy::ref_as_ptr, clippy::inline_always, reason = "what windows::core::implement writes")] +mod tell { + use std::sync::mpsc::Sender; + + use windows::Win32::Media::MediaFoundation::{ + IMFAsyncCallback, IMFAsyncCallback_Impl, IMFAsyncResult, IMFMediaEventGenerator, + }; + + #[windows::core::implement(IMFAsyncCallback)] + pub(super) struct Tell { + pub(super) generator: IMFMediaEventGenerator, + pub(super) tell: Sender>, + } + + impl IMFAsyncCallback_Impl for Tell_Impl { + fn GetParameters(&self, _: *mut u32, _: *mut u32) -> windows::core::Result<()> { + // E_NOTIMPL: the default work queue calls back. + Err(windows::core::Error::from_hresult(windows::core::HRESULT(0x8000_4001_u32 as i32))) + } + + fn Invoke(&self, result: windows::core::Ref) -> windows::core::Result<()> { + // SAFETY: the result of the request this callback answers. + let kind = result + .ok() + .and_then(|result| unsafe { self.generator.EndGetEvent(result) }) + .and_then(|event| unsafe { event.GetType() }); + let _ = self.tell.send(kind); + Ok(()) + } + } +} + +/// The bytes of `sample`'s buffers, in order. +fn bytes(sample: &IMFSample) -> Result> { + // SAFETY: the mapped bytes are copied out before the buffer unlocks. + unsafe { + let buffer = sample.ConvertToContiguousBuffer().map_err(|e| failed("ConvertToContiguousBuffer", &e))?; + let (mut address, mut length) = (std::ptr::null_mut(), 0_u32); + buffer.Lock(&raw mut address, None, Some(&raw mut length)).map_err(|e| failed("Lock", &e))?; + let bytes = std::slice::from_raw_parts(address, length as usize).to_vec(); + buffer.Unlock().map_err(|e| failed("Unlock", &e))?; + Ok(bytes) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + /// A gray NV12 picture of `size` with a light square that moves with `frame`. + fn picture_of(size: [u32; 2], frame: u32) -> Vec { + let [w, h] = size; + let mut nv12 = vec![128; (w * h * 3 / 2) as usize]; + for y in 0..h { + for x in 0..w { + let inside = (x + w - frame * 2 % w) % w < 16 && (8..24).contains(&y); + nv12[(y * w + x) as usize] = if inside { 220 } else { 60 }; + } + } + nv12 + } + + fn encodes_a_short_video(kinds: &[MFT_ENUM_FLAG]) { + let encoding = Encoding::new([64, 64], 30.0); + let mut encoder = match open(encoding, kinds) { + Ok(encoder) => encoder, + Err(Error::Unsupported(reason)) => return eprintln!("skipping: {reason}"), + Err(error) => panic!("{error}"), + }; + let mut units = Vec::new(); + for i in 0..12_u32 { + let time = u64::from(i) * 3000; + units.extend(pollster::block_on(encoder.encode(picture_of(encoding.size, i), time, i % 6 == 0)).unwrap()); + } + units.extend(pollster::block_on(encoder.finish()).unwrap()); + assert_eq!(units.len(), 12, "a unit for every picture"); + assert_eq!(units.iter().map(|u| u.time).collect::>(), (0..12).map(|i| i * 3000).collect::>()); + assert!(units[0].key, "the first is a keyframe"); + let first: Vec = nals(&units[0].annex_b).map(|nal| nal[0] & 0x1f).collect(); + assert!(first.contains(&7) && first.contains(&8), "the first keyframe carries its parameter sets: {first:?}"); + assert!(units[6].key, "a keyframe where asked"); + } + + #[test] + fn the_software_encoder_gives_a_unit_a_picture() { + encodes_a_short_video(&[software()]); + } + + #[test] + fn the_hardware_encoder_gives_a_unit_a_picture() { + encodes_a_short_video(&[hardware()]); + } +} diff --git a/crates/latkit/src/image.rs b/crates/latkit/src/image.rs new file mode 100644 index 00000000..36bba992 --- /dev/null +++ b/crates/latkit/src/image.rs @@ -0,0 +1,187 @@ +//! Images: RGBA texels, what an icon marker draws and what a shot reads its picture back as, written +//! as PNG, JPEG, or lossless WebP and read from PNG. + +use std::io::{Cursor, Write}; +use std::sync::Arc; + +use crate::{Error, Result}; + +/// RGBA texels, straight alpha, sRGB, rows top to bottom. +#[derive(Clone, PartialEq, Eq, Debug, serde::Deserialize, schemars::JsonSchema)] +#[serde(remote = "Self", deny_unknown_fields)] +#[schemars(rename = "Bitmap")] +pub struct Image { + /// Width and height in texels. + pub size: [u32; 2], + /// `size[0] * size[1] * 4` bytes. + pub rgba: Arc<[u8]>, +} + +/// An image reads as `{ size, rgba }`, four bytes a texel. +impl<'de> serde::Deserialize<'de> for Image { + fn deserialize>(deserializer: D) -> Result { + let Image { size, rgba } = Image::deserialize(deserializer)?; + Image::new(size, rgba).map_err(serde::de::Error::custom) + } +} + +impl Image { + /// An image of `size` texels holding `rgba`, four bytes a texel. + pub fn new(size: [u32; 2], rgba: impl Into>) -> Result { + let rgba = rgba.into(); + let expected = u64::from(size[0]).checked_mul(u64::from(size[1])).and_then(|pixels| pixels.checked_mul(4)); + if size.contains(&0) || expected != Some(rgba.len() as u64) { + return Err(Error::invalid("an image needs positive dimensions and exactly four bytes per pixel")); + } + Ok(Image { size, rgba }) + } + + /// The image written as a file of `format`. + pub fn encode(&self, format: ImageFormat) -> Result> { + let mut out = Vec::new(); + self.write(format, &mut out)?; + Ok(out) + } + + /// Writes the image as a file of `format` to a file or stream, reporting write failures. + pub fn write(&self, format: ImageFormat, mut output: impl Write) -> Result<()> { + Self::new(self.size, self.rgba.clone())?; + let [width, height] = self.size; + let failed = |error: &dyn std::fmt::Display| Error::Io(format!("cannot write {format}: {error}").into()); + match format { + ImageFormat::Png => { + let mut encoder = png::Encoder::new(output, width, height); + encoder.set_color(png::ColorType::Rgba); + encoder.set_depth(png::BitDepth::Eight); + encoder.set_source_srgb(png::SrgbRenderingIntent::Perceptual); + // A picture is written far more often than it is stored long. + encoder.set_compression(png::Compression::Fast); + let mut writer = encoder.write_header().map_err(|e| failed(&e))?; + writer.write_image_data(&self.rgba).map_err(|e| failed(&e))?; + writer.finish().map_err(|e| failed(&e)) + } + ImageFormat::Jpeg { quality } => { + if !(1..=100).contains(&quality) { + return Err(Error::invalid("a JPEG's quality runs from 1 to 100").at("quality")); + } + let side = |v: u32| u16::try_from(v).map_err(|_| failed(&"a JPEG is at most 65535 pixels a side")); + let mut bytes = Vec::new(); + jpeg_encoder::Encoder::new(&mut bytes, quality) + .encode(&self.rgba, side(width)?, side(height)?, jpeg_encoder::ColorType::Rgba) + .map_err(|e| failed(&e))?; + output.write_all(&bytes).map_err(|e| failed(&e)) + } + ImageFormat::WebP => image_webp::WebPEncoder::new(output) + .encode(&self.rgba, width, height, image_webp::ColorType::Rgba8) + .map_err(|e| failed(&e)), + } + } + + /// The image a PNG file holds, any color type and depth made eight bit RGBA. + pub fn from_png(bytes: &[u8]) -> Result { + let failed = |e: png::DecodingError| Error::invalid(format!("not a PNG image: {e}")); + let mut decoder = png::Decoder::new(Cursor::new(bytes)); + decoder.set_transformations(png::Transformations::normalize_to_color8()); + let mut reader = decoder.read_info().map_err(failed)?; + let mut buffer = vec![0; reader.output_buffer_size().ok_or_else(|| Error::invalid("a PNG too large"))?]; + let info = reader.next_frame(&mut buffer).map_err(failed)?; + let texels = (info.width * info.height) as usize; + let rgba: Vec = match info.color_type { + png::ColorType::Rgba => buffer[..texels * 4].to_vec(), + png::ColorType::Rgb => { + buffer[..texels * 3].as_chunks::<3>().0.iter().flat_map(|c| [c[0], c[1], c[2], 255]).collect() + } + png::ColorType::GrayscaleAlpha => { + buffer[..texels * 2].as_chunks::<2>().0.iter().flat_map(|c| [c[0], c[0], c[0], c[1]]).collect() + } + png::ColorType::Grayscale => buffer[..texels].iter().flat_map(|&g| [g, g, g, 255]).collect(), + png::ColorType::Indexed => return Err(Error::invalid("a PNG palette was not expanded")), + }; + Image::new([info.width, info.height], rgba) + } +} + +/// How an image is written as a file. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)] +pub enum ImageFormat { + /// PNG: lossless, alpha kept, tagged sRGB. + #[default] + Png, + /// JPEG at `quality` from 1 to 100: small, its alpha dropped. + Jpeg { + /// From 1, smallest, to 100, sharpest; 90 is good for pictures of views. + quality: u8, + }, + /// WebP, lossless: smaller than PNG, alpha kept. + WebP, +} + +impl ImageFormat { + /// The format a file's `extension` names: `png`, `jpg` or `jpeg` at quality 90, or `webp`. + pub fn of_extension(extension: &str) -> Option { + match extension.to_ascii_lowercase().as_str() { + "png" => Some(ImageFormat::Png), + "jpg" | "jpeg" => Some(ImageFormat::Jpeg { quality: 90 }), + "webp" => Some(ImageFormat::WebP), + _ => None, + } + } +} + +impl std::fmt::Display for ImageFormat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + ImageFormat::Png => "PNG", + ImageFormat::Jpeg { .. } => "JPEG", + ImageFormat::WebP => "WebP", + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn png_holds_what_it_was_given() { + let rgba: Vec = (0..3 * 2 * 4).map(|i| (i * 11) as u8).collect(); + let image = Image::new([3, 2], rgba).expect("whole"); + let back = Image::from_png(&image.encode(ImageFormat::Png).expect("written")).expect("a PNG"); + assert_eq!(back, image); + } + + #[test] + fn every_format_writes_its_file() { + let rgba: Vec = (0..16 * 8 * 4).map(|i| (i * 7) as u8).collect(); + let image = Image::new([16, 8], rgba).expect("whole"); + let jpeg = image.encode(ImageFormat::Jpeg { quality: 90 }).expect("written"); + assert_eq!(jpeg[..3], [0xff, 0xd8, 0xff], "a JPEG starts with its marker"); + let webp = image.encode(ImageFormat::WebP).expect("written"); + assert!(webp.starts_with(b"RIFF") && &webp[8..12] == b"WEBP", "a WebP is a RIFF file"); + assert_eq!(ImageFormat::of_extension("JPG"), Some(ImageFormat::Jpeg { quality: 90 })); + assert_eq!(ImageFormat::of_extension("gif"), None); + } + + #[test] + fn an_image_holds_four_bytes_a_texel() { + assert!(Image::new([2, 2], vec![0; 15]).is_err()); + assert!(Image::from_png(b"not a png").is_err()); + assert!(Image::new([0, 0], Vec::new()).is_err()); + assert!(Image::new([u32::MAX, u32::MAX], Vec::new()).is_err()); + } + + #[test] + fn writing_reports_stream_failures() { + struct Broken; + impl Write for Broken { + fn write(&mut self, _: &[u8]) -> std::io::Result { + Err(std::io::ErrorKind::BrokenPipe.into()) + } + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } + } + let image = Image::new([1, 1], vec![0; 4]).unwrap(); + assert!(image.write(ImageFormat::Png, Broken).is_err()); + } +} diff --git a/crates/latkit/src/json.rs b/crates/latkit/src/json.rs new file mode 100644 index 00000000..10013920 --- /dev/null +++ b/crates/latkit/src/json.rs @@ -0,0 +1,58 @@ +//! JSON as latkit reads it: any input from its text, an error naming the path to what it could not +//! read, such as `marks[2].vertices.color`. + +use std::fmt::Display; + +use serde::de::{Deserialize, DeserializeOwned, Deserializer}; +use serde_path_to_error::Segment; + +use crate::{Error, Path, Result, Step}; + +/// What JSON `text` holds, read as `T`: a scene, a camera, a fit, a query, rows, a budget, a shot, or +/// any type that deserializes. An error names the path to what could not be read. +/// +/// ``` +/// # #[cfg(feature = "gpu")] { +/// let scene: latkit::Scene = latkit::from_json(r#"{"space": "plane", "marks": []}"#)?; +/// let error = latkit::from_json::(r#"{"space": "plane", "marks": [{"vertices": 3}]}"#); +/// assert!(error.unwrap_err().to_string().starts_with("marks[0]")); +/// # } +/// # Ok::<(), latkit::Error>(()) +/// ``` +pub fn from_json(text: &str) -> Result { + let mut deserializer = serde_json::Deserializer::from_str(text); + let value = read(&mut deserializer)?; + deserializer.end().map_err(|e| Error::invalid(e.to_string()))?; + Ok(value) +} + +/// What `deserializer` holds, read as `T`, an error naming the path to what could not be read. +pub(crate) fn read<'de, T: Deserialize<'de>, D: Deserializer<'de>>(deserializer: D) -> Result +where + D::Error: Display, +{ + serde_path_to_error::deserialize(deserializer).map_err(|error| { + let steps = error.path().iter().filter_map(|segment| match segment { + Segment::Seq { index } => Some(Step::Index(*index)), + Segment::Map { key } => Some(Step::Name(key.as_str().into())), + Segment::Enum { variant } => Some(Step::Name(variant.as_str().into())), + Segment::Unknown => None, + }); + Error::Invalid { path: Path(steps.collect()), reason: error.into_inner().to_string().into() } + }) +} + +#[cfg(all(test, feature = "gpu"))] +mod tests { + use crate::{Scene, from_json}; + + #[test] + fn errors_name_the_path_through_presets_and_marks() { + let at = |json: &str| from_json::(json).unwrap_err().to_string(); + let grid = at(r#"{"space": {"plane": {"grid": "bogus"}}, "marks": []}"#); + assert!(grid.starts_with("space.plane.grid:"), "{grid}"); + let mark = at(r#"{"space": "plane", "marks": [{"vertices": {"of": ["d", "t"], "colour": "x"}}]}"#); + assert!(mark.starts_with("marks[0].vertices"), "{mark}"); + assert!(from_json::(r#"{"space": "plane", "marks": []} trailing"#).is_err()); + } +} diff --git a/crates/latkit/src/layout/layered.rs b/crates/latkit/src/layout/layered.rs new file mode 100644 index 00000000..2df668bb --- /dev/null +++ b/crates/latkit/src/layout/layered.rs @@ -0,0 +1,756 @@ +use rustc_hash::FxHashMap; + +use super::levels::{Graph, Level, Runs, bounds, frame, nested}; +use super::pack; +use super::rect::union; +use crate::scene::{Direction, Layered}; + +/// Width over height of the rows that parts nothing pins pack into. +const ASPECT: f64 = 16.0 / 9.0; +/// Crossing-reduction sweeps, alternately down and up the ranks. +const SWEEPS: usize = 8; + +/// Every vertex's center: pinned vertices where they are; the others in ranks along `options.flow` +/// (`Direction::Up` toward +y), `options.gap` apart within a rank and `options.rank_gap` between +/// ranks, ordered to cross few links, each pointing from one vertex to another; cycles are broken. +/// Each connected part is laid out alone, and parts nothing pins pack into rows (aspect 16:9) beside +/// the pinned ones. Across the flow, each vertex lines up with its sources; in a part nothing pins, +/// each source then settles amid the vertices it fans out to. Groups nest as [`nested`] lays them +/// out. +pub(crate) fn layered(graph: &Graph<'_>, options: &Layered) -> Vec<[f64; 2]> { + nested(graph, |level| arrange(level, options)) +} + +/// Places one level: each part that its links join laid out alone in ranks, then the parts nothing +/// pins packed in rows below the pinned ones, tallest first. +fn arrange(level: &Level, options: &Layered) -> Vec<[f64; 2]> { + let (sizes, pins) = (&level.sizes, &level.pinned); + let mut centers = vec![[0.0; 2]; sizes.len()]; + let (part, count) = parts(sizes.len(), &level.links); + let inside = Runs::new(count, (0..sizes.len()).map(|i| (part[i] as usize, i as u32))); + let joins = Runs::new(count, level.links.iter().map(|&link| (part[link[0] as usize] as usize, link))); + // Each member's place in its part, whose members run in index order. + let mut slot = vec![0_u32; sizes.len()]; + for p in 0..count { + for (s, &i) in inside.get(p).iter().enumerate() { + slot[i as usize] = s as u32; + } + } + let vertex = |i: u32| i as usize; + let flow = options.flow; + let mut anchored: Option<[f64; 4]> = None; + let mut loose: Vec<(usize, [f64; 4])> = Vec::new(); + for p in 0..count { + let part_members = inside.get(p); + let free = part_members.iter().filter(|&&i| pins[vertex(i)].is_none()).count(); + if free > 0 && part_members.len() == 1 { + centers[vertex(part_members[0])] = [0.0; 2]; + } else if free > 0 { + let extents: Vec<[f64; 2]> = part_members.iter().map(|&i| extent(flow, sizes[vertex(i)])).collect(); + let fixed: Vec> = + part_members.iter().map(|&i| pins[vertex(i)].map(|pin| to_flow(flow, pin))).collect(); + let part_links: Vec<[u32; 2]> = + joins.get(p).iter().map(|&[from, to]| [slot[from as usize], slot[to as usize]]).collect(); + let placed = ranked(&extents, &fixed, &part_links, options.gap, options.rank_gap); + for (&i, &at) in part_members.iter().zip(&placed) { + centers[vertex(i)] = from_flow(flow, at); + } + } + for &i in part_members { + if let Some(pin) = pins[vertex(i)] { + centers[vertex(i)] = pin; + } + } + let bounds = bounds(part_members.iter().map(|&i| frame(centers[vertex(i)], sizes[vertex(i)]))); + if free == part_members.len() { + loose.push((p, bounds)); + } else { + anchored = Some(anchored.map_or(bounds, |anchored| union(anchored, bounds))); + } + } + if loose.is_empty() { + return centers; + } + // Tallest first, then by first member, so like parts line up. + loose.sort_by(|a, b| (b.1[3] - b.1[1]).total_cmp(&(a.1[3] - a.1[1]))); + let boxes: Vec<[f64; 2]> = loose.iter().map(|(_, b)| [b[2] - b[0], b[3] - b[1]]).collect(); + let gap = options.rank_gap; + let span = pack::span(&boxes, gap, ASPECT).max(anchored.map_or(0.0, |anchored| anchored[2] - anchored[0])); + let origin = anchored.map_or([0.0; 2], |anchored| [anchored[0], anchored[1] - gap]); + for (&(p, bounds), corner) in loose.iter().zip(pack::rows(&boxes, gap, span)) { + let shift = [origin[0] + corner[0] - bounds[0], origin[1] + corner[1] - bounds[3]]; + for &i in inside.get(p) { + let center = &mut centers[vertex(i)]; + *center = [center[0] + shift[0], center[1] + shift[1]]; + } + } + centers +} + +/// Each of `count` vertices' part, the parts that `links` join numbered by their first vertex, and how many parts +/// there are. +fn parts(count: usize, links: &[[u32; 2]]) -> (Vec, usize) { + fn find(root: &mut [u32], mut vertex: u32) -> u32 { + while root[vertex as usize] != vertex { + root[vertex as usize] = root[root[vertex as usize] as usize]; + vertex = root[vertex as usize]; + } + vertex + } + let mut root: Vec = (0..count as u32).collect(); + for &[from, to] in links { + let (from, to) = (find(&mut root, from), find(&mut root, to)); + // The lower root wins, so a part's root is its first vertex. + if from < to { + root[to as usize] = from; + } else { + root[from as usize] = to; + } + } + let mut number = vec![u32::MAX; count]; + let mut parts = 0; + let part = (0..count as u32) + .map(|vertex| { + let first = find(&mut root, vertex) as usize; + if number[first] == u32::MAX { + number[first] = parts as u32; + parts += 1; + } + number[first] + }) + .collect(); + (part, parts) +} + +/// Plane coordinates turned so `flow` runs along the first: `[along, across]`, across running down a sideways flow and +/// rightward across an upward or downward one. +fn to_flow(flow: Direction, [x, y]: [f64; 2]) -> [f64; 2] { + match flow { + Direction::Right => [x, -y], + Direction::Left => [-x, -y], + Direction::Down => [-y, x], + Direction::Up => [y, x], + } +} + +/// Plane coordinates of flow coordinates `[along, across]`; undoes [`to_flow`]. +fn from_flow(flow: Direction, [along, across]: [f64; 2]) -> [f64; 2] { + match flow { + Direction::Right => [along, -across], + Direction::Left => [-along, -across], + Direction::Down => [across, -along], + Direction::Up => [across, along], + } +} + +/// A width and height as a length along `flow` and a span across it. +fn extent(flow: Direction, [width, height]: [f64; 2]) -> [f64; 2] { + match flow { + Direction::Right | Direction::Left => [width, height], + Direction::Down | Direction::Up => [height, width], + } +} + +/// One part's centers in flow coordinates (see [`to_flow`]). `extents` are each vertex's length along the flow and +/// span across it, `pins` the centers of those that stay, and `links` point from one vertex to another. +fn ranked( + extents: &[[f64; 2]], + pins: &[Option<[f64; 2]>], + links: &[[u32; 2]], + gap: f64, + rank_gap: f64, +) -> Vec<[f64; 2]> { + let count = extents.len(); + let rank = ranks(count, links); + let rank_count = rank.iter().max().map_or(0, |&last| last as usize + 1); + let mut layers = Runs::new(rank_count, (0..count).map(|i| (rank[i] as usize, i as u32))); + // Each link as its end in the earlier rank, then its end in the later; ranking leaves none within a rank. + let ends = |&[from, to]: &[u32; 2]| if rank[from as usize] < rank[to as usize] { [from, to] } else { [to, from] }; + let above = Runs::new(count, links.iter().map(ends).map(|[early, late]| (late as usize, early))); + let below = Runs::new(count, links.iter().map(ends).map(|[early, late]| (early as usize, late))); + let adjacent = Runs::new( + rank_count, + links + .iter() + .map(ends) + .filter(|&[early, late]| rank[late as usize] == rank[early as usize] + 1) + .map(|link| (rank[link[0] as usize] as usize, link)), + ); + reorder(&mut layers, &above, &below, &adjacent); + let mut centers = coordinates(extents, pins, &layers, &above, gap, rank_gap); + if pins.iter().all(Option::is_none) { + balance(&mut centers, extents, &layers, &below, gap); + } + centers +} + +/// Each vertex's rank: the longest path to it from a vertex nothing points to, once the links that close cycles are +/// set aside. A walk depth first from the vertices nothing points to finds those links. +fn ranks(count: usize, links: &[[u32; 2]]) -> Vec { + const NEW: u8 = 0; + const WALKING: u8 = 1; + const DONE: u8 = 2; + let mut next = Runs::new(count, links.iter().map(|&[from, to]| (from as usize, to))); + next.sort_each(); + let mut pointed = vec![false; count]; + for &[_, to] in links { + pointed[to as usize] = true; + } + let mut roots: Vec = (0..count as u32).collect(); + roots.sort_by_key(|&vertex| pointed[vertex as usize]); + // A link into a vertex still on the walk closes a cycle; every other link keeps its direction. + let mut state = vec![NEW; count]; + let mut forward: Vec<[u32; 2]> = Vec::with_capacity(links.len()); + let mut walk: Vec<(u32, usize)> = Vec::new(); + for &root in &roots { + if state[root as usize] != NEW { + continue; + } + state[root as usize] = WALKING; + walk.push((root, 0)); + while let Some(top) = walk.last_mut() { + let at = top.0; + let Some(&to) = next.get(at as usize).get(top.1) else { + state[at as usize] = DONE; + walk.pop(); + continue; + }; + top.1 += 1; + if state[to as usize] == WALKING { + continue; + } + forward.push([at, to]); + if state[to as usize] == NEW { + state[to as usize] = WALKING; + walk.push((to, 0)); + } + } + } + let after = Runs::new(count, forward.iter().map(|&[from, to]| (from as usize, to))); + let mut waiting = vec![0_u32; count]; + for &[_, to] in &forward { + waiting[to as usize] += 1; + } + let mut rank = vec![0_u32; count]; + let mut queue: Vec = roots.iter().copied().filter(|&vertex| waiting[vertex as usize] == 0).collect(); + let mut head = 0; + while let Some(&from) = queue.get(head) { + head += 1; + for &to in after.get(from as usize) { + rank[to as usize] = rank[to as usize].max(rank[from as usize] + 1); + waiting[to as usize] -= 1; + if waiting[to as usize] == 0 { + queue.push(to); + } + } + } + rank +} + +/// Orders each rank to cross few edges. Barycenter sweeps run alternately down the ranks, sorting each by where its +/// vertices' neighbors in earlier ranks sit, and up them by their neighbors in later ranks; the order that crosses the +/// fewest edges between adjacent ranks stays. +fn reorder(layers: &mut Runs, above: &Runs, below: &Runs, adjacent: &Runs<[u32; 2]>) { + let mut position = vec![0_u32; above.len()]; + for k in 0..layers.len() { + settle(layers.get(k), &mut position); + } + let mut crossings = Crossings::default(); + let mut fewest = crossings.count(layers, &position, adjacent); + let mut best = layers.items.clone(); + let mut score = vec![0.0; above.len()]; + for sweep in 0..SWEEPS { + if fewest == 0 { + break; + } + let down = sweep % 2 == 0; + let neighbors = if down { above } else { below }; + for step in 0..layers.len() { + let layer = layers.get_mut(if down { step } else { layers.len() - 1 - step }); + for &vertex in &*layer { + let near = neighbors.get(vertex as usize); + score[vertex as usize] = if near.is_empty() { + f64::from(position[vertex as usize]) + } else { + near.iter().map(|&other| f64::from(position[other as usize])).sum::() / near.len() as f64 + }; + } + layer.sort_by(|&a, &b| score[a as usize].total_cmp(&score[b as usize])); + settle(layer, &mut position); + } + let crossed = crossings.count(layers, &position, adjacent); + if crossed < fewest { + fewest = crossed; + best.clone_from(&layers.items); + } + } + layers.items = best; +} + +/// Records where each vertex of `layer` sits in it. +fn settle(layer: &[u32], position: &mut [u32]) { + for (at, &vertex) in layer.iter().enumerate() { + position[vertex as usize] = at as u32; + } +} + +/// Counts edges crossing between adjacent ranks, keeping its buffers from one count to the next. +#[derive(Default)] +struct Crossings { + /// Where each edge between two ranks starts and ends in them. + ends: Vec<(u32, u32)>, + /// A Fenwick tree of how many edges so far end at each place of the later rank. + ended: Vec, +} + +impl Crossings { + /// Edges between adjacent ranks that cross, given where each vertex sits in its rank: once sorted by where they + /// start, each edge crosses the earlier ones ending past it. + fn count(&mut self, layers: &Runs, position: &[u32], adjacent: &Runs<[u32; 2]>) -> u64 { + let mut total = 0; + for k in 1..layers.len() { + let edges = adjacent.get(k - 1); + if edges.len() < 2 { + continue; + } + self.ends.clear(); + self.ends.extend(edges.iter().map(|&[early, late]| (position[early as usize], position[late as usize]))); + self.ends.sort_unstable(); + self.ended.clear(); + self.ended.resize(layers.get(k).len() + 1, 0); + for (seen, &(_, end)) in self.ends.iter().enumerate() { + let mut at_or_before = 0; + let mut node = end as usize + 1; + while node > 0 { + at_or_before += self.ended[node] as usize; + node &= node - 1; + } + total += (seen - at_or_before) as u64; + let mut node = end as usize + 1; + while node < self.ended.len() { + self.ended[node] += 1; + node += node.isolate_lowest_one(); + } + } + } + total + } +} + +/// Each vertex's center in flow coordinates. Ranks run `rank_gap` apart along the flow, each vertex centered in its +/// rank's band; across it, each vertex sits in line with the median of its neighbors in earlier ranks unless that +/// would bring it within `gap` of the vertex before it in its rank. A rank holding pinned vertices starts where they +/// do, and vertices step past the pinned ones they would come within `gap` of. +fn coordinates( + extents: &[[f64; 2]], + pins: &[Option<[f64; 2]>], + layers: &Runs, + above: &Runs, + gap: f64, + rank_gap: f64, +) -> Vec<[f64; 2]> { + let mut centers: Vec<[f64; 2]> = pins.iter().map(|pin| pin.unwrap_or_default()).collect(); + let length_of = |vertex: u32| extents[vertex as usize][0]; + let bands: Vec = + (0..layers.len()).map(|k| layers.get(k).iter().map(|&i| length_of(i)).fold(0.0, f64::max)).collect(); + // Where a rank's pinned vertices begin along the flow. + let lead = |k: usize| { + layers.get(k).iter().filter_map(|&i| pins[i as usize].map(|pin| pin[0] - length_of(i) / 2.0)).reduce(f64::min) + }; + let first = (0..layers.len()).find_map(|k| lead(k).map(|at| (k, at))); + // Ranks before the first pinned one end where it starts. + let mut major = first.map_or(0.0, |(k, at)| at - bands[..k].iter().map(|band| band + rank_gap).sum::()); + let mut obstacles = first.map(|_| Obstacles::new(extents, pins, [gap.min(rank_gap), gap])); + let mut wanted: Vec = Vec::new(); + for (k, &band) in bands.iter().enumerate() { + if let Some(at) = lead(k) { + major = at; + } + let along = major + band / 2.0; + let mut floor: Option = None; + for &i in layers.get(k) { + let i = i as usize; + if pins[i].is_some() { + continue; + } + let [length, span] = extents[i]; + wanted.clear(); + wanted.extend(above.get(i).iter().map(|&other| centers[other as usize][1] - span / 2.0)); + let median = (!wanted.is_empty()).then(|| { + let middle = (wanted.len() - 1) / 2; + *wanted.select_nth_unstable_by(middle, f64::total_cmp).1 + }); + let mut low = match (median, floor) { + (Some(median), Some(floor)) => median.max(floor), + (Some(at), None) | (None, Some(at)) => at, + (None, None) => 0.0, + }; + let (start, end) = (along - length / 2.0, along + length / 2.0); + if let Some(obstacles) = &obstacles { + while let Some(high) = obstacles.reach([start, low, end, low + span]) { + low = high + gap; + } + } + let high = low + span; + centers[i] = [along, low + span / 2.0]; + if let Some(obstacles) = &mut obstacles { + obstacles.add([start, low, end, high]); + } + floor = Some(high + gap); + } + major += band + rank_gap; + } + centers +} + +/// Moves each vertex across the flow toward the middle of its neighbors in later ranks, the last ranks first, as far +/// as the vertices beside it in its rank allow, `gap` apart: a source settles amid the vertices it fans out to, and a +/// chain stays in line. +fn balance(centers: &mut [[f64; 2]], extents: &[[f64; 2]], layers: &Runs, below: &Runs, gap: f64) { + let mut across: Vec = Vec::new(); + let mut goals: Vec> = Vec::new(); + for k in (0..layers.len()).rev() { + let layer = layers.get(k); + goals.clear(); + for &vertex in layer { + let near = below.get(vertex as usize); + across.clear(); + across.extend(near.iter().map(|&other| centers[other as usize][1])); + across.sort_unstable_by(f64::total_cmp); + let middle = across.len() / 2; + goals.push(match across.len() { + 0 => None, + count if count % 2 == 1 => Some(across[middle]), + _ => Some(across[middle - 1].midpoint(across[middle])), + }); + } + // Toward greater across, the last vertex first, each held short of the one after it. + let mut ceiling = f64::INFINITY; + for (&vertex, goal) in layer.iter().zip(&goals).rev() { + let half = extents[vertex as usize][1] / 2.0; + let center = &mut centers[vertex as usize][1]; + if let Some(goal) = *goal + && goal > *center + { + *center = goal.min(ceiling - half).max(*center); + } + ceiling = *center - half - gap; + } + // Then toward lesser across, the first vertex first, each held short of the one before it. + let mut floor = f64::NEG_INFINITY; + for (&vertex, goal) in layer.iter().zip(&goals) { + let half = extents[vertex as usize][1] / 2.0; + let center = &mut centers[vertex as usize][1]; + if let Some(goal) = *goal + && goal < *center + { + *center = goal.max(floor + half).min(*center); + } + floor = *center + half + gap; + } + } +} + +/// Placed boxes in flow coordinates, bucketed in square cells to find those near a box quickly. +struct Obstacles { + /// A cell's side. + cell: f64, + /// The room boxes keep between them along the flow and across it. + room: [f64; 2], + /// Each box: its least along and across, then its greatest. + boxes: Vec<[f64; 4]>, + /// The boxes reaching into each cell. + cells: FxHashMap<[i64; 2], Vec>, +} + +impl Obstacles { + /// The pinned vertices' boxes, keeping `room` between boxes. Cells span a few vertices, so a box reaches few. + fn new(extents: &[[f64; 2]], pins: &[Option<[f64; 2]>], room: [f64; 2]) -> Obstacles { + let largest = extents.iter().flatten().fold(0.0, |largest: f64, &side| largest.max(side)); + let cell = (room[1] * 8.0).max(largest * 2.0); + let mut obstacles = Obstacles { + cell: if cell > 0.0 { cell } else { 1.0 }, + room, + boxes: Vec::new(), + cells: FxHashMap::default(), + }; + for (pin, &[length, span]) in pins.iter().zip(extents) { + if let Some([along, across]) = *pin { + obstacles.add([along - length / 2.0, across - span / 2.0, along + length / 2.0, across + span / 2.0]); + } + } + obstacles + } + + /// Adds a placed box. + fn add(&mut self, placed: [f64; 4]) { + let id = self.boxes.len() as u32; + self.boxes.push(placed); + for key in cells(self.cell, placed) { + self.cells.entry(key).or_default().push(id); + } + } + + /// The greatest across of the boxes that `query` comes within room of, if any. + fn reach(&self, query: [f64; 4]) -> Option { + let [along, across] = self.room; + let grown = [query[0] - along, query[1] - across, query[2] + along, query[3] + across]; + let mut reach: Option = None; + for key in cells(self.cell, grown) { + for &id in self.cells.get(&key).into_iter().flatten() { + let other = self.boxes[id as usize]; + let near = other[0] < query[2] + along + && query[0] < other[2] + along + && other[1] < query[3] + across + && query[1] < other[3] + across; + if near { + reach = Some(reach.map_or(other[3], |reach| reach.max(other[3]))); + } + } + } + reach + } +} + +/// The cells of side `cell` that `area` reaches into. +fn cells(cell: f64, area: [f64; 4]) -> impl Iterator { + let index = |at: f64| (at / cell).floor() as i64; + let (across_from, across_to) = (index(area[1]), index(area[3])); + (index(area[0])..=index(area[2])) + .flat_map(move |along| (across_from..=across_to).map(move |across| [along, across])) +} + +#[cfg(test)] +mod tests { + use super::*; + + const SIZE: [f64; 2] = [20.0, 10.0]; + + fn options(flow: Direction) -> Layered { + Layered { flow, gap: 10.0, rank_gap: 40.0 } + } + + /// A graph's columns, owned. + struct Columns { + sizes: Vec<[f64; 2]>, + edges: Vec<[u32; 2]>, + pinned: Vec>, + groups: Vec>, + pads: Vec<[f64; 4]>, + } + + impl Columns { + /// `count` vertices of [`SIZE`] joined by `edges`, none pinned or grouped; a group pads its members by + /// half a gap. + fn new(count: usize, edges: &[[u32; 2]]) -> Columns { + Columns { + sizes: vec![SIZE; count], + edges: edges.to_vec(), + pinned: vec![None; count], + groups: vec![None; count], + pads: vec![[5.0; 4]; count], + } + } + + fn layout(&self, options: &Layered) -> Vec<[f64; 2]> { + let graph = Graph { + sizes: &self.sizes, + links: &self.edges, + pinned: &self.pinned, + groups: &self.groups, + pads: &self.pads, + }; + layered(&graph, options) + } + + /// Vertex `v`'s box: a group's is its members' bounds, padded. + fn frame(&self, centers: &[[f64; 2]], v: usize, padding: f64) -> [f64; 4] { + let members: Vec = (0..self.sizes.len()).filter(|&m| self.groups[m] == Some(v as u32)).collect(); + if members.is_empty() { + return frame(centers[v], self.sizes[v]); + } + let inner = bounds(members.iter().map(|&m| self.frame(centers, m, padding))); + [inner[0] - padding, inner[1] - padding, inner[2] + padding, inner[3] + padding] + } + } + + /// Whether two boxes share more than an edge. + fn overlap(a: [f64; 4], b: [f64; 4]) -> bool { + const SLACK: f64 = 1e-6; + a[0] < b[2] - SLACK && b[0] < a[2] - SLACK && a[1] < b[3] - SLACK && b[1] < a[3] - SLACK + } + + fn near(a: f64, b: f64) -> bool { + (a - b).abs() < 1e-9 + } + + /// Edges that cross between vertices in the same two ranks of a rightward flow. + fn crossings(edges: &[[u32; 2]], centers: &[[f64; 2]]) -> usize { + let mut count = 0; + for (k, first) in edges.iter().enumerate() { + for second in &edges[k + 1..] { + let [from, to] = first.map(|vertex| centers[vertex as usize]); + let [other_from, other_to] = second.map(|vertex| centers[vertex as usize]); + let same_ranks = near(from[0], other_from[0]) && near(to[0], other_to[0]); + if same_ranks && (from[1] - other_from[1]) * (to[1] - other_to[1]) < 0.0 { + count += 1; + } + } + } + count + } + + #[test] + fn a_chain_ranks_along_the_flow_in_order() { + let graph = Columns::new(4, &[[2, 3], [0, 1], [1, 2]]); + for flow in [Direction::Right, Direction::Left, Direction::Down, Direction::Up] { + let centers = graph.layout(&options(flow)); + let (along, across, sign) = match flow { + Direction::Right => (0, 1, 1.0), + Direction::Left => (0, 1, -1.0), + Direction::Down => (1, 0, -1.0), + Direction::Up => (1, 0, 1.0), + }; + let length = SIZE[along]; + for pair in centers.windows(2) { + let step = (pair[1][along] - pair[0][along]) * sign; + assert!(near(step, length + 40.0), "{flow:?}: ranks a rank gap apart: {centers:?}"); + assert!(near(pair[1][across], pair[0][across]), "{flow:?}: in line with its source: {centers:?}"); + } + } + } + + #[test] + fn a_source_centers_on_its_fan() { + // 0 fans out to 1, 2, and 3; 3 runs on to 4. + let centers = Columns::new(5, &[[0, 1], [0, 2], [0, 3], [3, 4]]).layout(&options(Direction::Down)); + assert!(near(centers[0][0], centers[2][0]), "the source sits amid its fan: {centers:?}"); + assert!(near(centers[3][0], centers[4][0]), "a chain stays in line: {centers:?}"); + assert!(centers[1][0] < centers[2][0] && centers[2][0] < centers[3][0], "{centers:?}"); + } + + #[test] + fn pinned_vertices_stay_put() { + let mut graph = Columns::new(5, &[[0, 1], [1, 2], [1, 3], [3, 4]]); + graph.pinned[1] = Some([500.0, -300.0]); + graph.pinned[3] = Some([620.0, -260.0]); + let centers = graph.layout(&options(Direction::Right)); + assert_eq!(centers[1], [500.0, -300.0]); + assert_eq!(centers[3], [620.0, -260.0]); + assert!(centers[0][0] < centers[1][0] && centers[2][0] > centers[1][0], "{centers:?}"); + for a in 0..5 { + for b in a + 1..5 { + assert!(!overlap(frame(centers[a], SIZE), frame(centers[b], SIZE)), "{a} and {b}: {centers:?}"); + } + } + } + + #[test] + fn disconnected_parts_do_not_overlap() { + let graph = Columns::new(8, &[[0, 1], [1, 2], [3, 4], [4, 5]]); + let centers = graph.layout(&options(Direction::Right)); + for a in 0..8 { + for b in a + 1..8 { + assert!(!overlap(frame(centers[a], SIZE), frame(centers[b], SIZE)), "{a} and {b}: {centers:?}"); + } + } + let first = bounds((0..3).map(|v| frame(centers[v], SIZE))); + assert!(near(first[0], 0.0) && near(first[3], 0.0), "the first part's top left is the origin: {first:?}"); + } + + #[test] + fn a_cycle_still_lays_out() { + let graph = Columns::new(4, &[[0, 1], [1, 2], [2, 0], [2, 3]]); + let centers = graph.layout(&options(Direction::Right)); + assert!(centers.iter().flatten().all(|at| at.is_finite())); + assert!( + centers.windows(2).all(|pair| pair[1][0] > pair[0][0]), + "the cycle breaks at its back edge: {centers:?}" + ); + } + + #[test] + fn sweeps_untangle_crossings() { + // A K2,2 short of one edge in two ranks of two, and three ranks of three; both cross in index order. + let small = [[0, 3], [1, 2], [1, 3]]; + let large = [[0, 5], [1, 4], [2, 3], [2, 4], [3, 8], [4, 7], [5, 6]]; + for (count, width, edges) in [(4, 2, &small[..]), (9, 3, &large[..])] { + let in_index_order: Vec<[f64; 2]> = (0..count).map(|v| [(v / width) as f64, (v % width) as f64]).collect(); + assert!(crossings(edges, &in_index_order) > 0); + let centers = Columns::new(count, edges).layout(&options(Direction::Right)); + assert_eq!(crossings(edges, ¢ers), 0, "{centers:?}"); + } + } + + #[test] + fn groups_hold_their_members_apart_from_the_rest() { + // Group 0 holds 1 → 2 → 3 and group 6, which holds 7 → 8; 4 feeds the group and 5 drains it. + let mut graph = Columns::new(9, &[[1, 2], [2, 3], [4, 1], [3, 5], [2, 7], [7, 8]]); + graph.groups = vec![None, Some(0), Some(0), Some(0), None, None, Some(0), Some(6), Some(6)]; + let options = options(Direction::Right); + let centers = graph.layout(&options); + let padding = options.gap / 2.0; + let frame = |v: usize| graph.frame(¢ers, v, padding); + for (group, members) in [(0, &[1, 2, 3, 6][..]), (6, &[7, 8][..])] { + let outer = frame(group); + let middle = [outer[0].midpoint(outer[2]), outer[1].midpoint(outer[3])]; + assert!(near(centers[group][0], middle[0]) && near(centers[group][1], middle[1]), "{centers:?}"); + for &m in members { + let inner = frame(m); + assert!(inner[0] >= outer[0] && inner[1] >= outer[1] && inner[2] <= outer[2] && inner[3] <= outer[3]); + } + } + for (a, b) in [(0, 4), (0, 5), (4, 5), (6, 1), (6, 2), (6, 3), (1, 2), (2, 3), (1, 3), (7, 8)] { + assert!(!overlap(frame(a), frame(b)), "{a} and {b}: {centers:?}"); + } + assert!(frame(4)[2] < frame(0)[0] && frame(0)[2] < frame(5)[0], "the group ranks as one vertex: {centers:?}"); + } + + #[test] + fn a_pinned_member_holds_its_group_and_a_pinned_group_carries_its_members() { + let mut graph = Columns::new(7, &[[1, 2], [3, 0], [5, 6], [4, 5]]); + graph.groups = vec![None, Some(0), Some(0), None, None, Some(4), Some(4)]; + graph.pinned[1] = Some([300.0, 200.0]); + graph.pinned[4] = Some([-1000.0, 1000.0]); + let options = options(Direction::Right); + let centers = graph.layout(&options); + assert_eq!(centers[1], [300.0, 200.0]); + assert!(near(centers[4][0], -1000.0) && near(centers[4][1], 1000.0), "{centers:?}"); + let frame = |v: usize| graph.frame(¢ers, v, options.gap / 2.0); + let group = frame(4); + assert!(near(group[0].midpoint(group[2]), -1000.0) && near(group[1].midpoint(group[3]), 1000.0)); + assert!(!overlap(frame(3), frame(0)) && frame(3)[2] < frame(0)[0], "{centers:?}"); + } + + #[test] + fn large_graphs_lay_out_apart() { + // Fifty groups of twenty, and edges joining random vertices, many against the flow. + let count = 10_000; + let mut seed = 0x9e37_79b9_u32; + let mut random = move |below: usize| { + seed ^= seed << 13; + seed ^= seed >> 17; + seed ^= seed << 5; + seed as usize % below + }; + let mut edges: Vec<[u32; 2]> = (51..count).map(|v| [(50 + random(v - 50)) as u32, v as u32]).collect(); + edges.extend((0..count / 2).map(|_| [(50 + random(count - 50)) as u32, (50 + random(count - 50)) as u32])); + let mut graph = Columns::new(count, &edges); + for v in 50..1050 { + graph.groups[v] = Some(((v - 50) / 20) as u32); + } + let options = options(Direction::Down); + let centers = graph.layout(&options); + assert!(centers.iter().flatten().all(|at| at.is_finite())); + let mut frames: Vec<(usize, [f64; 4])> = (50..count).map(|v| (v, frame(centers[v], SIZE))).collect(); + frames.extend((0..50).map(|g| (g, graph.frame(¢ers, g, options.gap / 2.0)))); + // Ranks run down the page, so sweeping down it compares each frame with few others. + frames.sort_by(|a, b| a.1[1].total_cmp(&b.1[1])); + for (k, &(a, first)) in frames.iter().enumerate() { + for &(b, second) in frames[k + 1..].iter().take_while(|(_, second)| second[1] < first[3]) { + let held = graph.groups[a] == Some(b as u32) || graph.groups[b] == Some(a as u32); + assert!(held || !overlap(first, second), "{a} {first:?} and {b} {second:?}"); + } + } + } +} diff --git a/crates/latkit/src/layout/levels.rs b/crates/latkit/src/layout/levels.rs new file mode 100644 index 00000000..31b3e1f6 --- /dev/null +++ b/crates/latkit/src/layout/levels.rs @@ -0,0 +1,252 @@ +//! Nested graphs laid out a level at a time. A level is the vertices of the top, or the members of +//! one group. A group's members are placed first, innermost groups first; the group then stands as +//! one vertex of its box's size in the level holding it, with links between members of different +//! groups lifted to the groups they meet in. Every layout places one level at a time, so every +//! layout nests alike. + +use std::cmp::Reverse; + +/// A graph to lay out, plane units with y up: each vertex's width and height, its center when it has +/// one, the group holding it, and how far a group's box reaches past its members (left, bottom, +/// right, top); and links between vertices, from one to another where a layout reads direction. +pub(crate) struct Graph<'a> { + pub(crate) sizes: &'a [[f64; 2]], + pub(crate) links: &'a [[u32; 2]], + pub(crate) pinned: &'a [Option<[f64; 2]>], + pub(crate) groups: &'a [Option], + pub(crate) pads: &'a [[f64; 4]], +} + +/// One level to place: its vertices' sizes and pins, and the links among them, by index within it. +pub(crate) struct Level { + pub(crate) sizes: Vec<[f64; 2]>, + pub(crate) links: Vec<[u32; 2]>, + pub(crate) pinned: Vec>, +} + +/// Every vertex's center, `place` answering each level's. A group's center is the middle of its box: +/// its members' bounds grown by its pads. A pinned member holds its group where its members settled; +/// a group's own pin moves its members only when none of them is pinned. Groups out of range, of +/// themselves, or closing a cycle hold nothing. +pub(crate) fn nested(graph: &Graph<'_>, mut place: impl FnMut(&Level) -> Vec<[f64; 2]>) -> Vec<[f64; 2]> { + let count = graph.sizes.len(); + assert!( + graph.pinned.len() == count && graph.groups.len() == count && graph.pads.len() == count, + "a pin, a group, and pads for each vertex" + ); + let parent = tree(graph.groups); + let depth = depths(&parent); + // Level 0 is the top, then the groups innermost first. + let mut holds = vec![false; count]; + for &group in parent.iter().flatten() { + holds[group as usize] = true; + } + let mut groups: Vec = (0..count).filter(|&group| holds[group]).collect(); + groups.sort_by_key(|&group| Reverse(depth[group])); + let mut level = vec![0; count]; + for (k, &group) in groups.iter().enumerate() { + level[group] = k + 1; + } + let level_of = |vertex: usize| parent[vertex].map_or(0, |group| level[group as usize]); + let members = Runs::new(groups.len() + 1, (0..count).map(|vertex| (level_of(vertex), vertex as u32))); + let lifted: Vec<[u32; 2]> = graph.links.iter().filter_map(|&[from, to]| lift(from, to, &parent, &depth)).collect(); + let links = Runs::new(groups.len() + 1, lifted.iter().map(|&link| (level_of(link[0] as usize), link))); + + let mut sizes: Vec<[f64; 2]> = + graph.sizes.iter().map(|&[width, height]| [width.max(0.0), height.max(0.0)]).collect(); + let mut pins: Vec> = + graph.pinned.iter().map(|pin| pin.filter(|at| at[0].is_finite() && at[1].is_finite())).collect(); + // Centers within each vertex's level, and each group's members' middle within its own. + let mut centers = vec![[0.0; 2]; count]; + let mut middles = vec![[0.0; 2]; count]; + let mut local = vec![0_u32; count]; + let mut lay = |inside: &[u32], joins: &[[u32; 2]], sizes: &[[f64; 2]], pins: &[Option<[f64; 2]>]| { + for (i, &vertex) in inside.iter().enumerate() { + local[vertex as usize] = i as u32; + } + let level = Level { + sizes: inside.iter().map(|&vertex| sizes[vertex as usize]).collect(), + links: joins.iter().map(|&[from, to]| [local[from as usize], local[to as usize]]).collect(), + pinned: inside.iter().map(|&vertex| pins[vertex as usize]).collect(), + }; + place(&level) + }; + for (k, &group) in groups.iter().enumerate() { + let inside = members.get(k + 1); + for (&vertex, center) in inside.iter().zip(lay(inside, links.get(k + 1), &sizes, &pins)) { + centers[vertex as usize] = center; + } + let bounds = bounds(inside.iter().map(|&vertex| frame(centers[vertex as usize], sizes[vertex as usize]))); + let [left, bottom, right, top] = graph.pads[group]; + let grown = [bounds[0] - left, bounds[1] - bottom, bounds[2] + right, bounds[3] + top]; + middles[group] = [grown[0].midpoint(grown[2]), grown[1].midpoint(grown[3])]; + sizes[group] = [grown[2] - grown[0], grown[3] - grown[1]]; + if inside.iter().any(|&vertex| pins[vertex as usize].is_some()) { + pins[group] = Some(middles[group]); + } + } + let top = members.get(0); + for (&vertex, center) in top.iter().zip(lay(top, links.get(0), &sizes, &pins)) { + centers[vertex as usize] = center; + } + // Each group's members move with it, outermost first. + let mut shifts = vec![[0.0; 2]; count]; + for &group in groups.iter().rev() { + let outer = parent[group].map_or([0.0; 2], |up| shifts[up as usize]); + shifts[group] = + [centers[group][0] + outer[0] - middles[group][0], centers[group][1] + outer[1] - middles[group][1]]; + } + centers + .iter() + .zip(&parent) + .map(|(center, group)| { + let shift = group.map_or([0.0; 2], |group| shifts[group as usize]); + [center[0] + shift[0], center[1] + shift[1]] + }) + .collect() +} + +/// Each vertex's group: groups out of range or of themselves dropped, and each cycle of groups cut where a walk up it +/// closes. +fn tree(groups: &[Option]) -> Vec> { + const NEW: u8 = 0; + const WALKING: u8 = 1; + const DONE: u8 = 2; + let count = groups.len(); + let mut parent: Vec> = groups + .iter() + .enumerate() + .map(|(vertex, group)| group.filter(|&group| (group as usize) < count && group as usize != vertex)) + .collect(); + let mut state = vec![NEW; count]; + let mut walk: Vec = Vec::new(); + for start in 0..count { + let mut at = start; + loop { + if state[at] != NEW { + if state[at] == WALKING { + parent[*walk.last().expect("a walk reaches itself only after a step")] = None; + } + break; + } + state[at] = WALKING; + walk.push(at); + match parent[at] { + Some(group) => at = group as usize, + None => break, + } + } + for vertex in walk.drain(..) { + state[vertex] = DONE; + } + } + parent +} + +/// How many groups hold each vertex. +fn depths(parent: &[Option]) -> Vec { + let mut depth = vec![u32::MAX; parent.len()]; + let mut walk: Vec = Vec::new(); + for start in 0..parent.len() { + let mut at = start; + while depth[at] == u32::MAX { + walk.push(at); + match parent[at] { + Some(group) => at = group as usize, + None => break, + } + } + // The walk ends at a vertex already counted, or at the top, which it holds. + let mut next = if depth[at] == u32::MAX { 0 } else { depth[at] + 1 }; + while let Some(vertex) = walk.pop() { + depth[vertex] = next; + next += 1; + } + } + depth +} + +/// The link `from` → `to` between the outermost groups (or vertices) that hold each end and share a level; `None` for +/// a link within one of them or with an end out of range. +fn lift(from: u32, to: u32, parent: &[Option], depth: &[u32]) -> Option<[u32; 2]> { + if from as usize >= parent.len() || to as usize >= parent.len() { + return None; + } + let up = |vertex: usize| parent[vertex].expect("a held vertex has a group") as usize; + let (mut from, mut to) = (from as usize, to as usize); + while depth[from] > depth[to] { + from = up(from); + } + while depth[to] > depth[from] { + to = up(to); + } + while parent[from] != parent[to] { + (from, to) = (up(from), up(to)); + } + (from != to).then_some([from as u32, to as u32]) +} + +/// The box of a vertex centered at `center`: its least x and y, then its greatest. +pub(crate) fn frame(center: [f64; 2], size: [f64; 2]) -> [f64; 4] { + let half = [size[0] / 2.0, size[1] / 2.0]; + [center[0] - half[0], center[1] - half[1], center[0] + half[0], center[1] + half[1]] +} + +/// The box holding `boxes`; a point at the origin for none. +pub(crate) fn bounds(boxes: impl Iterator) -> [f64; 4] { + boxes.reduce(super::rect::union).unwrap_or([0.0; 4]) +} + +/// Items bucketed by key, each bucket's in the order given: bucket `k` is `items[offsets[k]..offsets[k + 1]]`. +pub(crate) struct Runs { + offsets: Vec, + /// Every bucket's items, bucket after bucket; reordered within buckets, they stay bucketed. + pub(crate) items: Vec, +} + +impl Runs { + /// `keyed` items in `buckets` buckets, each item's key below `buckets`. + pub(crate) fn new(buckets: usize, keyed: impl Iterator + Clone) -> Runs { + let mut offsets = vec![0; buckets + 1]; + for (key, _) in keyed.clone() { + offsets[key] += 1; + } + let mut total = 0; + for offset in &mut offsets { + (*offset, total) = (total, total + *offset); + } + let mut items = vec![T::default(); total]; + let mut fill = offsets.clone(); + for (key, item) in keyed { + items[fill[key]] = item; + fill[key] += 1; + } + Runs { offsets, items } + } +} + +impl Runs { + /// How many buckets. + pub(crate) fn len(&self) -> usize { + self.offsets.len() - 1 + } + + /// Bucket `k`'s items. + pub(crate) fn get(&self, k: usize) -> &[T] { + &self.items[self.offsets[k]..self.offsets[k + 1]] + } + + /// Bucket `k`'s items, to change. + pub(crate) fn get_mut(&mut self, k: usize) -> &mut [T] { + &mut self.items[self.offsets[k]..self.offsets[k + 1]] + } +} + +impl Runs { + /// Sorts the items within each bucket. + pub(crate) fn sort_each(&mut self) { + for k in 0..self.len() { + self.get_mut(k).sort_unstable(); + } + } +} diff --git a/crates/latkit/src/layout/mod.rs b/crates/latkit/src/layout/mod.rs new file mode 100644 index 00000000..94e56c18 --- /dev/null +++ b/crates/latkit/src/layout/mod.rs @@ -0,0 +1,9 @@ +//! Layouts on the CPU: layered drawing and stress over nested graphs, packing of parts, overlap +//! removal, and a diagram's orthogonal routes. Each is pure, so it runs as well in a host's job. +pub(crate) mod layered; +pub(crate) mod levels; +pub(crate) mod overlap; +pub(crate) mod pack; +pub(crate) mod rect; +pub(crate) mod route; +pub(crate) mod stress; diff --git a/crates/latkit/src/layout/overlap.rs b/crates/latkit/src/layout/overlap.rs new file mode 100644 index 00000000..d78e1f4a --- /dev/null +++ b/crates/latkit/src/layout/overlap.rs @@ -0,0 +1,144 @@ +//! Overlap removal: boxes pushed apart until no two come within a clearance of each other. + +use rustc_hash::FxHashMap; + +/// Rounds of pairwise pushing, before a sweep parts what they leave. +const ROUNDS: usize = 40; + +/// Each box's center once no two of `boxes` (center, then half width and height) come within +/// `clearance` of each other, pinned ones aside. First rounds of pushing: a pair too close parts +/// along the axis it overlaps least, each half the way, or a free box all of it when the other is +/// pinned. That moves boxes least, but a crowd jams; a sweep along x then places each box after the +/// pinned ones, in order, right of any placed box it overlaps. Pairs are found in a grid of cells as +/// wide as the widest box, so each round, and the sweep, is linear in the boxes for boxes of like +/// sizes. +pub(crate) fn separate(boxes: &[[f64; 4]], pinned: &[bool], clearance: f64) -> Vec<[f64; 2]> { + let mut centers: Vec<[f64; 2]> = boxes.iter().map(|b| [b[0], b[1]]).collect(); + let half: Vec<[f64; 2]> = boxes.iter().map(|b| [b[2], b[3]].map(|h| h.max(0.0) + clearance / 2.0)).collect(); + let grid = Grid { cell: 2.0 * half.iter().flatten().copied().fold(1e-9, f64::max) }; + // Overlaps this small are rounding, not overlap. + let slack = grid.cell * 1e-9; + let overlap = |centers: &[[f64; 2]], i: usize, j: usize| { + let over = [0, 1].map(|k| half[i][k] + half[j][k] - (centers[j][k] - centers[i][k]).abs()); + (over[0] > slack && over[1] > slack).then_some(over) + }; + let mut cells = FxHashMap::default(); + for _ in 0..ROUNDS { + grid.fill(&mut cells, ¢ers, 0..centers.len()); + let mut moved = false; + for i in 0..centers.len() { + for j in grid.near(&cells, centers[i]) { + if j <= i || (pinned[i] && pinned[j]) { + continue; + } + let Some(over) = overlap(¢ers, i, j) else { continue }; + let d = [0, 1].map(|k| centers[j][k] - centers[i][k]); + // Boxes at one point part by their order, across and along by turns. + let k = if d == [0.0; 2] { (i + j) % 2 } else { usize::from(over[1] < over[0]) }; + let sign = if d[k] == 0.0 { 1.0 } else { d[k].signum() }; + let share = if pinned[i] { + 0.0 + } else if pinned[j] { + 1.0 + } else { + 0.5 + }; + centers[i][k] -= sign * over[k] * share; + centers[j][k] += sign * over[k] * (1.0 - share); + moved = true; + } + } + if !moved { + return centers; + } + } + let mut order: Vec = (0..centers.len()).filter(|&i| !pinned[i]).collect(); + order.sort_by(|&a, &b| centers[a][0].total_cmp(¢ers[b][0]).then(a.cmp(&b))); + grid.fill(&mut cells, ¢ers, (0..centers.len()).filter(|&i| pinned[i])); + for i in order { + // Right past the placed boxes it overlaps, until it overlaps none. + while let Some(x) = grid + .near(&cells, centers[i]) + .filter_map(|j| overlap(¢ers, j, i).map(|_| centers[j][0] + half[j][0] + half[i][0])) + .reduce(f64::max) + { + centers[i][0] = x; + } + cells.entry(grid.key(centers[i])).or_default().push(i as u32); + } + centers +} + +/// Square cells of boxes' centers, wide enough that boxes that overlap stand in neighboring cells. +struct Grid { + cell: f64, +} + +impl Grid { + fn key(&self, c: [f64; 2]) -> (i64, i64) { + ((c[0] / self.cell).floor() as i64, (c[1] / self.cell).floor() as i64) + } + + /// Fills `cells` with the boxes `which`. + fn fill( + &self, + cells: &mut FxHashMap<(i64, i64), Vec>, + centers: &[[f64; 2]], + which: impl Iterator, + ) { + cells.values_mut().for_each(Vec::clear); + for i in which { + cells.entry(self.key(centers[i])).or_default().push(i as u32); + } + } + + /// The boxes in the cells around `at`. + fn near<'a>(&self, cells: &'a FxHashMap<(i64, i64), Vec>, at: [f64; 2]) -> impl Iterator + 'a { + let (x, y) = self.key(at); + [-1, 0, 1] + .into_iter() + .flat_map(move |dx| [-1, 0, 1].map(|dy| (x + dx, y + dy))) + .filter_map(|key| cells.get(&key)) + .flatten() + .map(|&j| j as usize) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn clear(boxes: &[[f64; 4]], centers: &[[f64; 2]], clearance: f64) -> bool { + (0..boxes.len()).all(|i| { + (i + 1..boxes.len()).all(|j| { + (0..2).any(|k| { + (centers[i][k] - centers[j][k]).abs() >= boxes[i][k + 2] + boxes[j][k + 2] + clearance - 1e-6 + }) + }) + }) + } + + #[test] + fn a_pair_parts_along_its_lesser_overlap() { + // Each half grows by half the clearance: 12 and 12 overlap 15 apart by 9 across, 22 along. + let boxes = [[0.0, 0.0, 10.0, 10.0], [15.0, 2.0, 10.0, 10.0]]; + let centers = separate(&boxes, &[false, false], 4.0); + assert_eq!(centers, vec![[-4.5, 0.0], [19.5, 2.0]]); + } + + #[test] + fn pinned_boxes_hold() { + let boxes = [[0.0, 0.0, 10.0, 10.0], [15.0, 0.0, 10.0, 10.0]]; + let centers = separate(&boxes, &[true, false], 0.0); + assert_eq!(centers, vec![[0.0, 0.0], [20.0, 0.0]]); + } + + #[test] + fn a_crowd_at_one_point_spreads_until_none_overlap() { + let boxes: Vec<[f64; 4]> = (0..60).map(|i| [0.0, 0.0, 5.0 + f64::from(i % 3), 4.0]).collect(); + let pinned: Vec = (0..60).map(|i| i == 7).collect(); + let centers = separate(&boxes, &pinned, 2.0); + assert!(clear(&boxes, ¢ers, 2.0), "{centers:?}"); + assert_eq!(centers[7], [0.0, 0.0], "the pinned box holds"); + } +} diff --git a/crates/latkit/src/layout/pack.rs b/crates/latkit/src/layout/pack.rs new file mode 100644 index 00000000..25cb7317 --- /dev/null +++ b/crates/latkit/src/layout/pack.rs @@ -0,0 +1,82 @@ +/// Offsets that pack boxes (each `[width, height]`) into rows `gap` apart whose width over height approaches `aspect`, +/// in the order given; the first box's top left lands at the origin. Returns each box's top-left corner (y up: top is +/// the greater y). +pub(crate) fn pack(boxes: &[[f64; 2]], gap: f64, aspect: f64) -> Vec<[f64; 2]> { + rows(boxes, gap, span(boxes, gap, aspect)) +} + +/// How wide rows of `boxes` run for the rows' width over height to approach `aspect`: as wide as a rectangle of that +/// aspect holding all the boxes and their gaps. +pub(super) fn span(boxes: &[[f64; 2]], gap: f64, aspect: f64) -> f64 { + let area: f64 = boxes.iter().map(|[width, height]| (width + gap) * (height + gap)).sum(); + (area * aspect).sqrt() +} + +/// Each box's top-left corner in rows `gap` apart, going down from the origin. A row breaks before a box that would +/// run it past `span`, so only a box wider than `span` makes a row wider. +pub(super) fn rows(boxes: &[[f64; 2]], gap: f64, span: f64) -> Vec<[f64; 2]> { + let (mut x, mut top, mut tallest) = (0.0, 0.0, 0.0_f64); + boxes + .iter() + .enumerate() + .map(|(i, &[width, height])| { + if i > 0 && x + width > span { + x = 0.0; + top -= tallest + gap; + tallest = 0.0; + } + let corner = [x, top]; + x += width + gap; + tallest = tallest.max(height); + corner + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Boxes of uneven sizes, the same each run. + fn uneven(count: usize) -> Vec<[f64; 2]> { + let mut seed = 0x2545_f491_u32; + let mut next = move || { + seed ^= seed << 13; + seed ^= seed >> 17; + seed ^= seed << 5; + f64::from(seed % 1000) / 10.0 + 1.0 + }; + (0..count).map(|_| [next(), next()]).collect() + } + + #[test] + fn boxes_do_not_overlap_and_keep_their_gap() { + let (boxes, gap) = (uneven(200), 4.0); + let corners = pack(&boxes, gap, 16.0 / 9.0); + assert_eq!(corners[0], [0.0, 0.0], "the first box's top left is the origin"); + for (i, (a, &[aw, ah])) in corners.iter().zip(&boxes).enumerate() { + for (b, &[bw, bh]) in corners.iter().zip(&boxes).skip(i + 1) { + let apart_x = a[0] + aw + gap <= b[0] || b[0] + bw + gap <= a[0]; + let apart_y = a[1] - ah - gap >= b[1] || b[1] - bh - gap >= a[1]; + assert!(apart_x || apart_y, "{a:?} {:?} and {b:?} {:?}", [aw, ah], [bw, bh]); + } + } + } + + #[test] + fn rows_approach_the_aspect() { + let squares = vec![[1.0, 1.0]; 100]; + let corners = pack(&squares, 0.0, 16.0 / 9.0); + let width = corners.iter().map(|c| c[0] + 1.0).fold(0.0, f64::max); + let height = -corners.iter().map(|c| c[1] - 1.0).fold(0.0, f64::min); + let aspect = width / height; + assert!((1.4..=2.2).contains(&aspect), "{width} by {height}"); + assert!(corners.iter().all(|c| c[1] <= 0.0), "rows go down from the origin"); + } + + #[test] + fn a_wide_box_takes_a_row_alone() { + let corners = pack(&[[1.0, 1.0], [50.0, 2.0], [1.0, 1.0]], 1.0, 1.0); + assert_eq!(corners, vec![[0.0, 0.0], [0.0, -2.0], [0.0, -5.0]]); + } +} diff --git a/crates/latkit/src/layout/rect.rs b/crates/latkit/src/layout/rect.rs new file mode 100644 index 00000000..08c31932 --- /dev/null +++ b/crates/latkit/src/layout/rect.rs @@ -0,0 +1,35 @@ +//! Boxes on the plane, least x and y then greatest, and the points they hold. + +/// A point on the plane. +pub(crate) type Point = [f64; 2]; + +/// A box: least x, least y, greatest x, greatest y. +pub(crate) type Rect = [f64; 4]; + +/// A box holding nothing, which any union replaces. +pub(crate) const EMPTY: Rect = [f64::INFINITY, f64::INFINITY, f64::NEG_INFINITY, f64::NEG_INFINITY]; + +/// The box holding `a` and `b`. +pub(crate) fn union(a: Rect, b: Rect) -> Rect { + [a[0].min(b[0]), a[1].min(b[1]), a[2].max(b[2]), a[3].max(b[3])] +} + +/// The box holding only `p`. +pub(crate) fn dot(p: Point) -> Rect { + [p[0], p[1], p[0], p[1]] +} + +/// The box `half` its width and height each way about `center`. +pub(crate) fn around(center: Point, half: Point) -> Rect { + [center[0] - half[0], center[1] - half[1], center[0] + half[0], center[1] + half[1]] +} + +/// `r` grown by `by` on every side. +pub(crate) fn grow(r: Rect, by: f64) -> Rect { + [r[0] - by, r[1] - by, r[2] + by, r[3] + by] +} + +/// Whether two boxes meet, touching included. +pub(crate) fn meets(a: &Rect, b: &Rect) -> bool { + a[0] <= b[2] && a[2] >= b[0] && a[1] <= b[3] && a[3] >= b[1] +} diff --git a/crates/latkit/src/layout/route.rs b/crates/latkit/src/layout/route.rs new file mode 100644 index 00000000..535dd718 --- /dev/null +++ b/crates/latkit/src/layout/route.rs @@ -0,0 +1,1654 @@ +//! Orthogonal routes: wires in horizontal and vertical runs around obstacles. +//! +//! Each net grows as a tree from its first terminal. Every terminal leaves its vertex along its side +//! by a stub, and each further terminal, nearest first, branches off the tree by the cheapest clear +//! elbow, or else by an A* search over a sparse visibility graph: the free stretches of the lines +//! through the nearby obstacles' corners, joined where they cross. Tracks then set apart the runs of +//! different nets that share a line. +//! +//! Sides are in plane units with y up: a top side faces +y. + +use std::cmp::Ordering; +use std::collections::BinaryHeap; + +use super::rect::{EMPTY, Point, Rect, dot, grow, meets, union}; +use crate::scene::Side; + +/// Where a wire meets a vertex: the point on its boundary, the side it leaves by (None: any), and the +/// obstacle it belongs to (an index into `obstacles`), which its own wire may touch. +#[derive(Clone, Copy, PartialEq, Debug)] +pub(crate) struct Terminal { + /// The point on the vertex's boundary. + pub(crate) at: [f64; 2], + /// The side the wire leaves by; with none, the owner's side nearest `at`, or else the way toward + /// the rest of the net. + pub(crate) side: Option, + /// The obstacle the terminal belongs to. + pub(crate) owner: Option, +} + +/// A net: every terminal it joins. Two terminals make a plain edge. +#[derive(Clone, PartialEq, Debug, Default)] +pub(crate) struct Net { + /// The terminals; the route grows from the first. + pub(crate) terminals: Vec, +} + +/// Each net's route as polylines (a tree for nets of more than two terminals, sharing junction points), +/// running in horizontal and vertical segments around `obstacles` (each `[min x, min y, max x, max y]`), +/// leaving each terminal along its side, with parallel runs of different nets `spacing` apart. Runs of +/// `fixed` polylines, wires already routed, keep their tracks, and the new runs take tracks beside +/// them. A net whose route cannot avoid the obstacles still gets an orthogonal route through them. +/// +/// Wires keep twice `spacing` from obstacles where they can. `groups` are soft: wires cross their +/// borders at a cost, so they enter and leave a group once, and keep off its borders. A net of fewer +/// than two terminals at finite points gets no polylines; obstacles with a non-finite or inverted box +/// are left out. +pub(crate) fn route( + obstacles: &[[f64; 4]], + groups: &[[f64; 4]], + nets: &[Net], + fixed: &[Vec<[f64; 2]>], + spacing: f64, +) -> Vec>> { + let mut router = Router::new(obstacles, groups, spacing); + let mut trees: Vec> = nets.iter().map(|net| router.net(net)).collect(); + let routed = trees.len(); + trees.extend(fixed.iter().filter(|line| line.len() > 1).map(|line| Some(Tree::fixed(line)))); + router.separate(&mut trees); + trees.truncate(routed); + trees.iter().map(|tree| tree.as_ref().map_or_else(Vec::new, Tree::polylines)).collect() +} + +/// Arc points a rounded bend takes between its ends. +const ARC: usize = 3; + +/// A net's polylines as drawn: each bend between perpendicular runs rounded by up to `radius`, and +/// each part ending where another starts doubled at its end, so that point draws as a junction and +/// takes no arrowhead. No point repeats anywhere else, as where two bends' arcs meet on a short run: +/// it would draw as a junction too. +pub(crate) fn finish(lines: &[Vec], radius: f64) -> Vec> { + lines + .iter() + .map(|line| { + let mut out: Vec = Vec::with_capacity(line.len() + ARC * line.len().saturating_sub(2)); + out.extend(line.first()); + for k in 1..line.len().saturating_sub(1) { + let (a, p, b) = (line[k - 1], line[k], line[k + 1]); + let (u, v) = (direction(a, p), direction(p, b)); + let r = radius.min(manhattan(a, p) / 2.0).min(manhattan(p, b) / 2.0); + if u[0] * v[0] + u[1] * v[1] != 0.0 || r <= SAME || (u == [0.0; 2]) || (v == [0.0; 2]) { + push_new(&mut out, p); + continue; + } + // A quarter circle from `p - u r` to `p + v r` about `p - u r + v r`. + let center = [p[0] - u[0] * r + v[0] * r, p[1] - u[1] * r + v[1] * r]; + for i in 0..=ARC + 1 { + let t = i as f64 / (ARC + 1) as f64 * std::f64::consts::FRAC_PI_2; + let (cos, sin) = (t.cos(), t.sin()); + let at = [center[0] - v[0] * r * cos + u[0] * r * sin, center[1] - v[1] * r * cos + u[1] * r * sin]; + push_new(&mut out, at); + } + } + if let Some(&last) = line.last().filter(|_| line.len() > 1) { + push_new(&mut out, last); + } + let end = *out.last().expect("a polyline has points"); + if lines.iter().any(|other| other.first() == Some(&end)) { + out.push(end); + } + out + }) + .collect() +} + +/// Pushes `p` onto `out` unless it is the last point there again. +fn push_new(out: &mut Vec, p: Point) { + if out.last().is_none_or(|&q| manhattan(q, p) > EPSILON) { + out.push(p); + } +} + +/// How far wires keep from obstacles, in spacings. +const CLEARANCE: f64 = 2.0; + +/// Offsets below this are rounding: a point this near a box's side is on it. +const EPSILON: f64 = 1e-6; + +/// Points nearer than this are one point. +const SAME: f64 = 1e-9; + +/// Children per index node. +const NODE: usize = 16; + +/// Attach points a branch tries, nearest first. +const ATTACHES: usize = 8; + +/// Attach points a branch searches from when no elbow is clear. +const SEARCHED: usize = 3; + +/// Crossings past which a search gives up. +const MAX_CROSSINGS: usize = 1 << 20; + +/// Steps a search takes before it gives up. +const MAX_VISITS: usize = 1 << 17; + +/// Crossings a flood from a search's goal reaches before it takes the goal for open. +const POCKET: usize = 256; + +/// Times a search widens its window over the obstacles that wall it in. +const WIDENINGS: usize = 1; + +/// What crossing a group's border costs, in clearances of length. +const CROSSING: f64 = 4.0; + +/// No joint: the root's parent, or a joint without children. +const NONE: usize = usize::MAX; + +/// No state: where a search starts. +const NOWHERE: u32 = u32::MAX; + +impl Side { + /// The unit normal out of this side. + fn normal(self) -> Point { + match self { + Side::Left => [-1.0, 0.0], + Side::Right => [1.0, 0.0], + Side::Top => [0.0, 1.0], + Side::Bottom => [0.0, -1.0], + } + } +} + +/// A terminal as routing reads it: where its wire meets the vertex, the way out, and its owner's box. +struct End { + at: Point, + normal: Point, + owner: Option, +} + +/// Plans nets among the obstacles, then sets their runs apart. +struct Router<'a> { + obstacles: Obstacles<'a>, + groups: Groups, + /// How far apart tracks run. + spacing: f64, + /// How far wires keep from obstacles where they can. + clearance: f64, + search: Search, +} + +impl<'a> Router<'a> { + /// A router among `boxes` and `groups`, tracks `spacing` apart; a negative or non-finite spacing + /// is zero. + fn new(boxes: &'a [Rect], groups: &[Rect], spacing: f64) -> Router<'a> { + let spacing = if spacing.is_finite() { spacing.max(0.0) } else { 0.0 }; + let clearance = spacing * CLEARANCE; + let groups = Groups { boxes: groups.iter().copied().filter(valid).collect(), clearance }; + Router { obstacles: Obstacles::new(boxes), groups, spacing, clearance, search: Search::new(2.0 * clearance) } + } + + /// The shortest stub, and the least a track keeps a stub's end off its terminal. + fn least(&self) -> f64 { + self.spacing / 8.0 + } + + /// A net's tree: the first terminal's stub, then each further terminal's branch, nearest first; + /// `None` for a net of fewer than two terminals at finite points. + fn net(&mut self, net: &Net) -> Option { + let terminals: Vec = + net.terminals.iter().filter(|terminal| terminal.at.iter().all(|v| v.is_finite())).copied().collect(); + let (first, rest) = terminals.split_first()?; + let root = self.end(*first, rest.first()?.at); + let mut readers: Vec = rest.iter().map(|terminal| self.end(*terminal, root.at)).collect(); + readers.sort_by(|a, b| manhattan(a.at, root.at).total_cmp(&manhattan(b.at, root.at))); + let mut tree = Tree::default(); + let origin = tree.add(root.at, NONE, Joint::Terminal); + tree.add(self.stub(&root), origin, Joint::Stub(origin)); + for reader in &readers { + let end = self.stub(reader); + let branch = self.branch(&tree, end, reader, &root); + let Attach { child, interior, .. } = branch.attach; + let mut parent = if interior { + tree.split(child, branch.points[0]) + } else if manhattan(branch.points[0], tree.points[child]) < SAME { + child + } else { + tree.parent[child] + }; + for &bend in branch.points.iter().take(branch.points.len() - 1).skip(1) { + parent = tree.add(bend, parent, Joint::Bend); + } + let stub = tree.add(end, parent, Joint::Bend); + let terminal = tree.add(reader.at, stub, Joint::Terminal); + tree.joints[stub] = Joint::Stub(terminal); + } + Some(tree) + } + + /// How routing reads a terminal. Its way out is its side; else its owner's side nearest it; else + /// the axis toward `toward`. + fn end(&self, terminal: Terminal, toward: Point) -> End { + let owner = self.obstacles.owned(terminal.owner); + let at = terminal.at; + let normal = match (terminal.side, owner) { + (Some(side), _) => side.normal(), + (None, Some(own)) => { + let offset = [at[0] - own[0].midpoint(own[2]), at[1] - own[1].midpoint(own[3])]; + outward(offset, [own[2] - own[0], own[3] - own[1]]) + } + (None, None) => outward([toward[0] - at[0], toward[1] - at[1]], [1.0, 1.0]), + }; + End { at, normal, owner } + } + + /// Where a terminal's stub ends: clear of its owner by the clearance, or halfway to an obstacle + /// in the way. + fn stub(&self, end: &End) -> Point { + let axis = usize::from(end.normal[0] == 0.0); + let sign = end.normal[axis]; + let from = end.at[axis]; + let exit = end + .owner + .map_or(0.0, |own| (((if sign > 0.0 { own[axis + 2] } else { own[axis] }) - from) * sign).max(0.0)); + let length = exit + self.clearance; + let far = from + sign * length; + let across = end.at[1 - axis]; + let (lo, hi) = (from.min(far), from.max(far)); + let region = if axis == 0 { [lo, across, hi, across] } else { [across, lo, across, hi] }; + let mut nearest = length; + self.obstacles.some(region, 0.0, |obstacle| { + let near = ((if sign > 0.0 { obstacle[axis] } else { obstacle[axis + 2] }) - from) * sign; + if near > exit + EPSILON && near < nearest { + nearest = near; + } + false + }); + let length = if nearest < length { (exit + self.least()).max(exit.midpoint(nearest)) } else { length }; + let mut point = end.at; + point[axis] = from + sign * length; + point + } + + /// The cheapest clear way from the tree to a reader's stub end `end`: an elbow from one of the + /// nearest attach points; else a search around the obstacles at less and less clearance; else a + /// plain elbow through them. + fn branch(&mut self, tree: &Tree, end: Point, reader: &End, root: &End) -> Branch { + let mut attaches = tree.attaches(end); + attaches.truncate(ATTACHES); + let into = [-reader.normal[0], -reader.normal[1]]; + let mut best = + Best { tree, into, bend: self.search.bend, groups: &self.groups, cost: f64::INFINITY, branch: None }; + let clear = Some((&self.obstacles, self.clearance - EPSILON)); + for &attach in &attaches { + let from = attach.point; + let middle = [from[0].midpoint(end[0]), from[1].midpoint(end[1])]; + best.consider(&[from, [end[0], from[1]], end], attach, clear); + best.consider(&[from, [from[0], end[1]], end], attach, clear); + best.consider(&[from, [middle[0], from[1]], [middle[0], end[1]], end], attach, clear); + best.consider(&[from, [from[0], middle[1]], [end[0], middle[1]], end], attach, clear); + } + // An elbow that keeps out of every group it need not cross is as good as any search finds. + match best.branch.take() { + Some(branch) if branch.points.windows(2).all(|w| self.groups.cost(w[0], w[1]) == 0.0) => return branch, + elbow => best.branch = elbow, + } + // The window frames the boxes a branch may have to go around: its terminal's, and the root's + // when the branch may leave the root's stub. + let searched = &attaches[..attaches.len().min(SEARCHED)]; + let from_root = searched.iter().any(|attach| attach.point == tree.points[1]); + let owners: Vec = [reader.owner, root.owner.filter(|_| from_root)].into_iter().flatten().collect(); + let from: Vec<(Point, Option)> = + searched.iter().map(|&attach| (attach.point, tree.stub_way(attach))).collect(); + let leg = Leg { from: &from, to: end, arrive: Some(reader.normal) }; + for by in [self.clearance, self.clearance / 2.0, 0.0] { + if let Some((source, path)) = self.search.path(&self.obstacles, &self.groups, &leg, &owners, by) { + best.consider(&path, attaches[source], None); + } + if let Some(branch) = best.branch.take() { + return branch; + } + } + let attach = attaches.first().copied().unwrap_or(Attach { point: tree.points[0], child: 1, interior: false }); + Branch { points: simplify(&[attach.point, [end[0], attach.point[1]], end]), attach } + } + + /// Sets apart the runs of different nets that share a line: each takes its own track, `spacing` + /// apart where the corridor between obstacles has room, ordered by where its ends turn so runs + /// nest rather than cross. A run carries its joints, so branches stay joined; terminals never + /// move, and stubs only grow. + fn separate(&self, trees: &mut [Option]) { + let tolerance = self.spacing / 16.0; + for axis in 0..2 { + let mut runs = runs(trees, axis, self.least()); + runs.sort_by(|a, b| a.line.total_cmp(&b.line).then(a.along[0].total_cmp(&b.along[0]))); + let mut first = 0; + while first < runs.len() { + let mut end = first + 1; + let mut reach = runs[first].along[1]; + while end < runs.len() && runs[end].line - runs[first].line < tolerance && runs[end].along[0] < reach { + reach = reach.max(runs[end].along[1]); + end += 1; + } + let cluster = &runs[first..end]; + first = end; + if cluster.iter().any(|run| run.net != cluster[0].net) { + self.tracks(cluster, axis, trees); + } + } + } + } + + /// Spreads a cluster of runs on one line across tracks between the nearest obstacles' sides. + fn tracks(&self, cluster: &[Run], axis: usize, trees: &mut [Option]) { + let gap = self.spacing; + let line = cluster[0].line; + let lo = cluster.iter().map(|run| run.along[0]).fold(f64::INFINITY, f64::min); + let hi = cluster.iter().map(|run| run.along[1]).fold(f64::NEG_INFINITY, f64::max); + let reach = gap * (cluster.len() + 2) as f64; + let (mut low, mut high) = (line - reach, line + reach); + let region = + if axis == 0 { [line - reach, lo, line + reach, hi] } else { [lo, line - reach, hi, line + reach] }; + self.obstacles.some(region, 0.0, |obstacle| { + if obstacle[axis + 2] <= line + EPSILON { + low = low.max(obstacle[axis + 2] + gap / 2.0); + } else if obstacle[axis] >= line - EPSILON { + high = high.min(obstacle[axis] - gap / 2.0); + } + false + }); + let mut order: Vec<&Run> = cluster.iter().collect(); + order.sort_by(|a, b| { + let (length_a, length_b) = (a.along[1] - a.along[0], b.along[1] - b.along[0]); + a.turn + .total_cmp(&b.turn) + .then_with(|| if a.turn > 0.0 { length_a.total_cmp(&length_b) } else { length_b.total_cmp(&length_a) }) + .then(a.along[0].total_cmp(&b.along[0])) + }); + let last = (order.len() - 1) as f64; + let step = gap.min((high - low).max(0.0) / last.max(1.0)); + let base = + order.iter().position(|run| run.held()).map_or(line - last * step / 2.0, |held| line - held as f64 * step); + let base = low.min(line).max(base.min(high.max(line) - last * step)); + for (rank, run) in order.iter().enumerate() { + if run.held() { + continue; + } + let at = (base + rank as f64 * step).min(run.limits[1]).max(run.limits[0]); + if let Some(tree) = &mut trees[run.net] { + for &joint in &run.joints { + tree.points[joint][axis] = at; + } + } + } + } +} + +/// The axis direction an offset from a box's middle leaves it by, measured across the box's `size`. +fn outward(offset: Point, size: Point) -> Point { + let across = |k: usize| (offset[k] / size[k].max(f64::MIN_POSITIVE)).abs(); + let away = |v: f64| if v < 0.0 { -1.0 } else { 1.0 }; + if across(0) > across(1) { [away(offset[0]), 0.0] } else { [0.0, away(offset[1])] } +} + +/// What a joint of a tree is, which says how far tracks may move it. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +enum Joint { + /// A bend or a junction, free to move. + Bend, + /// A terminal, which never moves. + Terminal, + /// A stub's outer end, whose stub from the terminal joint given only grows. + Stub(usize), +} + +/// A net while it is planned: joints, each joined to its parent by an axis-aligned segment. The +/// first joint is the root's terminal. +#[derive(Default)] +struct Tree { + points: Vec, + parent: Vec, + joints: Vec, +} + +impl Tree { + /// A wire already routed, as a chain of joints none of which moves: its runs hold their tracks. + fn fixed(line: &[Point]) -> Tree { + let mut tree = Tree::default(); + let mut parent = NONE; + for &point in line { + parent = tree.add(point, parent, Joint::Terminal); + } + tree + } + + /// Adds a joint at `point` below `parent`. + fn add(&mut self, point: Point, parent: usize, joint: Joint) -> usize { + self.points.push(point); + self.parent.push(parent); + self.joints.push(joint); + self.points.len() - 1 + } + + /// A joint at `point` on the segment from `child` to its parent. + fn split(&mut self, child: usize, point: Point) -> usize { + let joint = self.add(point, self.parent[child], Joint::Bend); + self.parent[child] = joint; + joint + } + + /// Where a branch may attach, nearest `toward` first: each joint but a terminal, and each + /// segment's nearest point to `toward`. Segments into terminals are stubs, which no branch + /// attaches inside. + fn attaches(&self, toward: Point) -> Vec { + let mut out = Vec::new(); + for child in 1..self.points.len() { + let parent = self.parent[child]; + let (upper, lower) = (self.points[parent], self.points[child]); + let (upper_held, lower_held) = + (self.joints[parent] == Joint::Terminal, self.joints[child] == Joint::Terminal); + if !upper_held { + out.push(Attach { point: upper, child, interior: false }); + } + if !lower_held { + out.push(Attach { point: lower, child, interior: false }); + } + if upper_held || lower_held { + continue; + } + let nearest = |k: usize| toward[k].max(upper[k].min(lower[k])).min(upper[k].max(lower[k])); + let point = if upper[0] == lower[0] { [upper[0], nearest(1)] } else { [nearest(0), upper[1]] }; + if manhattan(point, upper) > SAME && manhattan(point, lower) > SAME { + out.push(Attach { point, child, interior: true }); + } + } + out.sort_by(|a, b| manhattan(a.point, toward).total_cmp(&manhattan(b.point, toward))); + out + } + + /// The way from a joint `attach` is at along its stub into a terminal, which no branch leaves by. + fn stub_way(&self, attach: Attach) -> Option { + if attach.interior { + return None; + } + let parent = self.parent[attach.child]; + let joint = if manhattan(attach.point, self.points[parent]) < SAME { parent } else { attach.child }; + let up = self.parent[joint]; + (0..self.points.len()) + .find(|&k| (k == up || self.parent[k] == joint) && self.joints[k] == Joint::Terminal) + .map(|terminal| direction(attach.point, self.points[terminal])) + } + + /// Moves a path's start along the tree while its first step runs along a segment of the tree, so + /// the path attaches where it leaves the tree. Stubs, which no branch attaches inside, stop it. + fn slide(&self, path: &mut Vec, mut attach: Attach) -> Attach { + for _ in 0..self.points.len() { + let [start, next, ..] = path[..] else { break }; + let way = direction(start, next); + let along = (1..self.points.len()).find_map(|child| { + let parent = self.parent[child]; + if self.joints[parent] == Joint::Terminal || self.joints[child] == Joint::Terminal { + return None; + } + let (upper, lower) = (self.points[parent], self.points[child]); + let on = (start[0] == upper[0] && upper[0] == lower[0] && between(start[1], upper[1], lower[1])) + || (start[1] == upper[1] && upper[1] == lower[1] && between(start[0], upper[0], lower[0])); + [upper, lower].into_iter().find(|&far| on && direction(start, far) == way).map(|far| (child, far)) + }); + let Some((child, far)) = along else { break }; + let (to_next, to_far) = (manhattan(start, next), manhattan(start, far)); + if to_next < to_far - SAME { + path.remove(0); + return Attach { point: next, child, interior: true }; + } + attach = Attach { point: far, child, interior: false }; + if to_next <= to_far + SAME { + path.remove(0); + } else { + path[0] = far; + } + } + attach + } + + /// The tree as polylines, each from the root or a junction to a leaf or the next junction. + fn polylines(&self) -> Vec> { + let count = self.points.len(); + let (mut children, mut siblings) = (vec![NONE; count], vec![NONE; count]); + for joint in (1..count).rev() { + let parent = self.parent[joint]; + siblings[joint] = children[parent]; + children[parent] = joint; + } + let mut polylines = Vec::new(); + let mut stack = if count > 0 { vec![0] } else { Vec::new() }; + while let Some(start) = stack.pop() { + let mut first = children[start]; + while first != NONE { + let mut line = vec![self.points[start]]; + let mut joint = first; + loop { + line.push(self.points[joint]); + let child = children[joint]; + if child == NONE || siblings[child] != NONE { + break; + } + joint = child; + } + polylines.push(simplify(&line)); + if children[joint] != NONE { + stack.push(joint); + } + first = siblings[first]; + } + } + polylines + } +} + +/// Where a branch may attach to a tree: a point on the segment from `child` to its parent, inside +/// it or at one of its joints. +#[derive(Clone, Copy)] +struct Attach { + point: Point, + child: usize, + interior: bool, +} + +/// A branch from a tree to a terminal's stub end: its path, from where it attaches. +struct Branch { + points: Vec, + attach: Attach, +} + +/// The cheapest branch found so far. +struct Best<'t> { + tree: &'t Tree, + /// The way a branch enters the stub end: against the terminal's side. + into: Point, + /// What a bend costs, in length. + bend: f64, + groups: &'t Groups, + cost: f64, + branch: Option, +} + +impl Best<'_> { + /// Keeps the path through `points` from `attach` when it turns well, costs less than the best so + /// far, and, with `clear`, keeps out of the obstacles grown by the clearance given. + fn consider(&mut self, points: &[Point], attach: Attach, clear: Option<(&Obstacles, f64)>) { + let mut path = simplify(points); + let attach = self.tree.slide(&mut path, attach); + if !self.fits(&path, attach) { + return; + } + let mut cost = path.len().saturating_sub(2) as f64 * self.bend; + for pair in path.windows(2) { + cost += manhattan(pair[0], pair[1]) + self.groups.cost(pair[0], pair[1]); + if cost >= self.cost || clear.is_some_and(|(obstacles, by)| !obstacles.clear(pair[0], pair[1], by)) { + return; + } + } + if cost < self.cost { + self.cost = cost; + self.branch = Some(Branch { points: path, attach }); + } + } + + /// Whether a path from the tree to the stub end turns well: it never doubles back along the + /// stub, leaves a segment it attaches inside across it, and leaves a joint along none of the + /// segments already there. + fn fits(&self, path: &[Point], attach: Attach) -> bool { + let (Some(&[start, next]), Some(&[before, last])) = (path.first_chunk(), path.last_chunk()) else { + return path.len() == 1; + }; + direction(before, last) != [-self.into[0], -self.into[1]] && self.leaves_well(start, next, attach) + } + + /// Whether a path's first step, from `start` toward `next`, leaves the tree well. + fn leaves_well(&self, start: Point, next: Point, attach: Attach) -> bool { + let tree = self.tree; + let parent = tree.parent[attach.child]; + let (upper, lower) = (tree.points[parent], tree.points[attach.child]); + if attach.interior { + let along = usize::from(upper[0] == lower[0]); + return next[along] == start[along]; + } + let leaving = direction(start, next); + let joint = if manhattan(start, upper) < SAME { parent } else { attach.child }; + let up = tree.parent[joint]; + (0..tree.points.len()) + .filter(|&k| k == up || tree.parent[k] == joint) + .all(|k| direction(start, tree.points[k]) != leaving) + } +} + +/// What a search joins: the points it may leave from, each with a way it may not leave by, and the +/// point it reaches, with a way it may not arrive moving. +struct Leg<'p> { + from: &'p [(Point, Option)], + to: Point, + arrive: Option, +} + +/// How a search over one window ended. +enum Outcome { + /// The path found, from the leg's start given. + Found(usize, Vec), + /// No way inside the window, though a wider one may hold one. + Walled, + /// No way at all, or too much to look through. + Unreachable, +} + +/// What a flood from a search's goal found before the search spreads over the window. +enum Reach { + /// A start, or more than a pocket: the search is worth running. + Open, + /// A pocket without a start that reaches the window's edge: a wider window may join them. + Apart, + /// A pocket without a start, walled in inside the window. + Enclosed, +} + +/// A state waiting in a search: its estimated total cost, its cost so far, and the state, a crossing +/// and the axis of the step that reached it. +#[derive(Clone, Copy)] +struct Step { + estimate: f64, + cost: f64, + state: u32, +} + +impl Ord for Step { + // The heap pops its greatest: the least estimate, then the farthest along, then the first state. + fn cmp(&self, other: &Step) -> Ordering { + other + .estimate + .total_cmp(&self.estimate) + .then(self.cost.total_cmp(&other.cost)) + .then(other.state.cmp(&self.state)) + } +} + +impl PartialOrd for Step { + fn partial_cmp(&self, other: &Step) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialEq for Step { + fn eq(&self, other: &Step) -> bool { + self.cmp(other) == Ordering::Equal + } +} + +impl Eq for Step {} + +/// A free stretch of a line among a search's obstacles: the line's place across, and where the +/// stretch starts and ends along it. +#[derive(Clone, Copy, PartialEq)] +struct Span { + line: f64, + lo: f64, + hi: f64, +} + +/// Where a horizontal and a vertical span cross: a vertex of a search's graph. +#[derive(Clone, Copy)] +struct Crossing { + point: Point, + /// The horizontal span, then the vertical one. + spans: [u32; 2], + /// Its place in the search's columns. + place: u32, +} + +/// Searches for orthogonal paths around obstacles over a sparse visibility graph: the free spans of +/// the lines through the obstacles' corners, the path's two ends, and the window's edges, which meet +/// where they cross. Its scratch is shared by every search, grown and never shrunk. +struct Search { + /// What a bend costs, in length. + bend: f64, + /// How far a window reaches past what it frames. + margin: f64, + /// The graph's vertices: horizontal span by span, each from left to right. + crossings: Vec, + /// The crossings of each vertical span from bottom to top, span after span. + columns: Vec, + /// Where each vertical span's crossings start in `columns`, then where the last ends. + starts: Vec, + /// The cheapest cost found to each state: a crossing, and the axis of the step that reached it. + costs: Vec, + /// The state each state was reached from. + came: Vec, + heap: BinaryHeap, + /// Which crossings a flood has reached, and the order it reached them in. + seen: Vec, + queue: Vec, +} + +impl Search { + /// A search whose bends cost, and whose windows reach, `reach`. + fn new(reach: f64) -> Search { + Search { + bend: reach, + margin: reach, + crossings: Vec::new(), + columns: Vec::new(), + starts: Vec::new(), + costs: Vec::new(), + came: Vec::new(), + heap: BinaryHeap::new(), + seen: Vec::new(), + queue: Vec::new(), + } + } + + /// The cheapest orthogonal path for `leg` around the obstacles grown by `by`, from whichever start + /// is cheapest, in a window framing the leg and the boxes `around`. The window widens over + /// obstacles that wall it in. `None` when the leg's end or every start is inside an obstacle, or no + /// way is found. + fn path( + &mut self, + obstacles: &Obstacles, + groups: &Groups, + leg: &Leg, + around: &[Rect], + by: f64, + ) -> Option<(usize, Vec)> { + let frame = around.iter().fold(dot(leg.to), |frame, owner| union(frame, *owner)); + let frame = leg.from.iter().fold(frame, |frame, &(start, _)| union(frame, dot(start))); + let mut window = grow(frame, self.margin); + for _ in 0..=WIDENINGS { + let boxes = obstacles.query(grow(window, by), by); + let free = |point: Point| !boxes.iter().any(|obstacle| inside(point, obstacle)); + if !free(leg.to) || !leg.from.iter().any(|&(start, _)| free(start)) { + return None; + } + match self.graph(&boxes, groups, window, leg) { + Outcome::Found(source, path) => return Some((source, path)), + Outcome::Unreachable => return None, + Outcome::Walled => {} + } + if boxes.iter().all(|obstacle| within(obstacle, &window)) { + return None; + } + window = grow(boxes.iter().fold(window, |walls, obstacle| union(walls, *obstacle)), self.margin); + } + None + } + + /// Builds the window's visibility graph through `ends` among `boxes`, the grown obstacles that + /// meet it; false when it holds too many crossings to search. + fn build(&mut self, boxes: &[Rect], window: Rect, ends: &[Point]) -> bool { + let horizontal = spans(boxes, window, ends, 0); + let vertical = spans(boxes, window, ends, 1); + self.crossings.clear(); + for (row, span) in horizontal.iter().enumerate() { + let first = vertical.partition_point(|other| other.line < span.lo); + for (column, other) in + vertical.iter().enumerate().skip(first).take_while(|(_, other)| other.line <= span.hi) + { + if other.lo <= span.line && span.line <= other.hi { + let spans = [row as u32, column as u32]; + self.crossings.push(Crossing { point: [other.line, span.line], spans, place: 0 }); + } + } + if self.crossings.len() > MAX_CROSSINGS { + return false; + } + } + // Each vertical span's crossings, which come bottom to top as the rows do. + self.starts.clear(); + self.starts.resize(vertical.len() + 1, 0); + for crossing in &self.crossings { + self.starts[crossing.spans[1] as usize] += 1; + } + let mut total = 0; + for start in &mut self.starts { + (*start, total) = (total, total + *start); + } + let mut cursor = self.starts.clone(); + self.columns.clear(); + self.columns.resize(self.crossings.len(), 0); + for (index, crossing) in self.crossings.iter_mut().enumerate() { + let at = &mut cursor[crossing.spans[1] as usize]; + crossing.place = *at; + self.columns[*at as usize] = index as u32; + *at += 1; + } + true + } + + /// A* over the window's visibility graph for `leg` among `boxes`, the grown obstacles that meet + /// it, its steps costing their crossings of `groups`' borders: each state a crossing and the axis + /// of the step that reached it. The groups' lanes, just inside and outside their borders, are + /// lines of the graph too. + fn graph(&mut self, boxes: &[Rect], groups: &Groups, window: Rect, leg: &Leg) -> Outcome { + let groups = groups.within(window); + let mut ends: Vec = leg.from.iter().map(|&(start, _)| start).chain([leg.to]).collect(); + ends.extend(groups.lanes()); + if !self.build(boxes, window, &ends) { + return Outcome::Unreachable; + } + let find = |point: Point| self.crossings.iter().position(|crossing| crossing.point == point); + let Some(goal) = find(leg.to) else { return Outcome::Unreachable }; + let sources: Vec<(usize, Option)> = + leg.from.iter().filter_map(|&(start, banned)| find(start).map(|vertex| (vertex, banned))).collect(); + if sources.is_empty() { + return Outcome::Unreachable; + } + match self.flood(goal, &sources, window) { + Reach::Open => {} + Reach::Apart => return Outcome::Walled, + Reach::Enclosed => return Outcome::Unreachable, + } + let states = self.crossings.len() * 2; + self.costs.clear(); + self.costs.resize(states, f64::INFINITY); + self.came.clear(); + self.came.resize(states, NOWHERE); + self.heap.clear(); + for &(vertex, _) in &sources { + for axis in 0..2 { + let state = vertex * 2 + axis; + self.costs[state] = 0.0; + let estimate = self.estimate(self.crossings[vertex].point, None, leg.to); + self.heap.push(Step { estimate, cost: 0.0, state: state as u32 }); + } + } + let (mut visits, mut edge) = (0, false); + while let Some(Step { cost, state, .. }) = self.heap.pop() { + let state = state as usize; + if cost > self.costs[state] { + continue; + } + let (vertex, axis) = (state / 2, state % 2); + if vertex == goal { + let path = self.trace(state); + let source = leg.from.iter().position(|&(start, _)| start == path[0]).unwrap_or(0); + return Outcome::Found(source, path); + } + visits += 1; + if visits > MAX_VISITS { + return Outcome::Unreachable; + } + let crossing = self.crossings[vertex]; + edge |= on_edge(crossing.point, &window); + // A start's first step leaves by any way but its banned one. + let first = self.came[state] == NOWHERE; + let banned = + if first { sources.iter().find(|source| source.0 == vertex).and_then(|source| source.1) } else { None }; + for (k, next) in self.neighbors(vertex).into_iter().enumerate() { + let Some(next) = next else { continue }; + let along = k / 2; + let point = self.crossings[next].point; + let way = Some(direction(crossing.point, point)); + if (banned.is_some() && way == banned) || (next == goal && way == leg.arrive) { + continue; + } + let turn = if !first && along != axis { self.bend } else { 0.0 }; + let value = cost + manhattan(crossing.point, point) + turn + groups.cost(crossing.point, point); + let reached = next * 2 + along; + if value >= self.costs[reached] { + continue; + } + self.costs[reached] = value; + self.came[reached] = state as u32; + let estimate = value + self.estimate(point, Some(along), leg.to); + self.heap.push(Step { estimate, cost: value, state: reached as u32 }); + } + } + // A start walled in short of the window's edge stays walled in however wide the window. + if edge { Outcome::Walled } else { Outcome::Unreachable } + } + + /// The least a path can cost from `point`, reached along `axis` (`None` at a start, whose first + /// step turns for free), to `to`: its length, and a bend for the turn it still needs. + fn estimate(&self, point: Point, axis: Option, to: Point) -> f64 { + let turns = match ([point[0] != to[0], point[1] != to[1]], axis) { + ([true, true], _) | ([true, false], Some(1)) | ([false, true], Some(0)) => 1.0, + _ => 0.0, + }; + manhattan(point, to) + turns * self.bend + } + + /// The crossings next to `vertex`: left and right along its horizontal span, then down and up + /// along its vertical one. + fn neighbors(&self, vertex: usize) -> [Option; 4] { + let crossing = self.crossings[vertex]; + let row = |other: usize| self.crossings.get(other).is_some_and(|c| c.spans[0] == crossing.spans[0]); + let place = crossing.place as usize; + let column = crossing.spans[1] as usize; + let (low, high) = (self.starts[column] as usize, self.starts[column + 1] as usize); + [ + vertex.checked_sub(1).filter(|&left| row(left)), + Some(vertex + 1).filter(|&right| row(right)), + (place > low).then(|| self.columns[place - 1] as usize), + (place + 1 < high).then(|| self.columns[place + 1] as usize), + ] + } + + /// Floods the graph from `goal` for a pocket's worth of crossings, to fail fast where the goal is + /// walled in apart from every start. + fn flood(&mut self, goal: usize, sources: &[(usize, Option)], window: Rect) -> Reach { + self.seen.clear(); + self.seen.resize(self.crossings.len(), false); + self.queue.clear(); + self.queue.push(goal); + self.seen[goal] = true; + let (mut next, mut edge) = (0, false); + while let Some(&vertex) = self.queue.get(next) { + if next >= POCKET || sources.iter().any(|source| source.0 == vertex) { + return Reach::Open; + } + next += 1; + edge |= on_edge(self.crossings[vertex].point, &window); + for other in self.neighbors(vertex).into_iter().flatten() { + if !self.seen[other] { + self.seen[other] = true; + self.queue.push(other); + } + } + } + if edge { Reach::Apart } else { Reach::Enclosed } + } + + /// The path that reached state `goal`, from the start. + fn trace(&self, goal: usize) -> Vec { + let mut path = Vec::new(); + let mut state = goal; + loop { + path.push(self.crossings[state / 2].point); + match self.came[state] { + NOWHERE => break, + previous => state = previous as usize, + } + } + path.reverse(); + simplify(&path) + } +} + +/// The free spans of lines running along `along` (0: x, 1: y) within `window`, among `boxes`, the +/// grown obstacles that meet it: through each box's corners, or where its sides' lines enter the +/// window, through each of `ends`, and every span along the window's edges. Sorted by line, then +/// start. +fn spans(boxes: &[Rect], window: Rect, ends: &[Point], along: usize) -> Vec { + let held = 1 - along; + let (start, end) = (window[along], window[along + 2]); + let (low, high) = (window[held], window[held + 2]); + // A seed is a line and a point along it its span holds; NaN takes every span of the line. + let mut seeds: Vec = boxes + .iter() + .flat_map(|r| { + [[r[held], r[along]], [r[held], r[along + 2]], [r[held + 2], r[along]], [r[held + 2], r[along + 2]]] + }) + .chain(ends.iter().map(|point| [point[held], point[along]])) + .filter(|&[line, _]| (low..=high).contains(&line)) + .map(|[line, at]| [line, at.max(start).min(end)]) + .chain([[low, f64::NAN], [high, f64::NAN]]) + .collect(); + seeds.sort_by(|a, b| a[0].total_cmp(&b[0]).then(a[1].total_cmp(&b[1]))); + // A sweep across the lines: the boxes whose open stretch across holds the line, by start along. + let mut order: Vec = (0..boxes.len()).collect(); + order.sort_by(|&a, &b| boxes[a][held].total_cmp(&boxes[b][held]).then(a.cmp(&b))); + let mut order = order.into_iter().peekable(); + let mut active: Vec = Vec::new(); + let mut spans = Vec::new(); + let mut merged: Vec<[f64; 2]> = Vec::new(); + for seeds in seeds.chunk_by(|a, b| a[0] == b[0]) { + let line = seeds[0][0]; + while let Some(r) = order.next_if(|&next| boxes[next][held] + EPSILON < line).map(|next| boxes[next]) { + let at = active.partition_point(|other| other[along] <= r[along]); + active.insert(at, r); + } + active.retain(|r| line < r[held + 2] - EPSILON); + // The stretches of the line inside an obstacle, merged where they meet. + merged.clear(); + for r in &active { + match merged.last_mut() { + Some(last) if r[along] <= last[1] + EPSILON => last[1] = last[1].max(r[along + 2]), + _ => merged.push([r[along], r[along + 2]]), + } + } + for &[_, at] in seeds { + if at.is_nan() { + let mut lo = start; + for &[from, to] in &merged { + if lo > end { + break; + } + if from > lo { + spans.push(Span { line, lo, hi: from.min(end) }); + } + lo = lo.max(to); + } + if lo <= end { + spans.push(Span { line, lo, hi: end }); + } + continue; + } + let after = merged.partition_point(|stretch| stretch[0] <= at - EPSILON); + if after > 0 && merged[after - 1][1] > at + EPSILON { + continue; + } + let lo = if after > 0 { merged[after - 1][1].max(start) } else { start }; + let hi = merged.get(after).map_or(end, |stretch| stretch[0].min(end)); + spans.push(Span { line, lo: lo.min(at), hi: hi.max(at) }); + } + } + spans.sort_by(|a, b| a.line.total_cmp(&b.line).then(a.lo.total_cmp(&b.lo))); + spans.dedup(); + spans +} + +/// The groups wires route among: boxes they may cross, at a cost. +struct Groups { + boxes: Vec, + /// How far wires keep from obstacles: a border's lanes lie half of it inside and outside. + clearance: f64, +} + +impl Groups { + /// What a run from `a` to `b` costs past its length: [`CROSSING`] clearances for each border it + /// crosses, and its length again where it runs along a border, nearer than half a clearance. + fn cost(&self, a: Point, b: Point) -> f64 { + let along = usize::from(a[0] == b[0]); + let held = 1 - along; + let (lo, hi, line) = (a[along].min(b[along]), a[along].max(b[along]), a[held]); + let near = self.clearance / 2.0; + let mut cost = 0.0; + for r in &self.boxes { + if line > r[held] && line < r[held + 2] { + let crossed = [r[along], r[along + 2]].iter().filter(|&&side| side > lo && side < hi).count(); + cost += crossed as f64 * CROSSING * self.clearance; + } + for side in [r[held], r[held + 2]] { + if (line - side).abs() < near { + cost += (hi.min(r[along + 2]) - lo.max(r[along])).max(0.0); + } + } + } + cost + } + + /// The groups meeting `window`. + fn within(&self, window: Rect) -> Groups { + Groups { boxes: self.boxes.iter().copied().filter(|r| meets(r, &window)).collect(), clearance: self.clearance } + } + + /// The corners of the lanes along every group's borders, half a clearance inside and outside each: + /// points the search's lines run through. + fn lanes(&self) -> Vec { + let half = self.clearance / 2.0; + let mut out = Vec::new(); + for r in &self.boxes { + for by in [half, -half] { + let g = grow(*r, by); + if g[0] < g[2] && g[1] < g[3] { + out.extend([[g[0], g[1]], [g[2], g[1]], [g[0], g[3]], [g[2], g[3]]]); + } + } + } + out + } +} + +/// The obstacles routing avoids, with an index over them. +struct Obstacles<'a> { + boxes: &'a [Rect], + index: Index, +} + +impl<'a> Obstacles<'a> { + /// The obstacles `boxes`, indexed. + fn new(boxes: &'a [Rect]) -> Obstacles<'a> { + Obstacles { boxes, index: Index::new(boxes) } + } + + /// The box of obstacle `owner`, when there is one. + fn owned(&self, owner: Option) -> Option { + owner.and_then(|owner| self.boxes.get(owner as usize)).copied().filter(valid) + } + + /// Visits the obstacles meeting `region`, each grown by `by`, until `visit` returns true; whether + /// it did. + fn some(&self, region: Rect, by: f64, mut visit: impl FnMut(Rect) -> bool) -> bool { + self.index.some(region, &mut |item| visit(grow(self.boxes[item], by))) + } + + /// The obstacles meeting `region`, each grown by `by`. + fn query(&self, region: Rect, by: f64) -> Vec { + let mut out = Vec::new(); + self.some(region, by, |obstacle| { + out.push(obstacle); + false + }); + out + } + + /// Whether the axis-aligned segment from `a` to `b` keeps out of every obstacle grown by `by`. + fn clear(&self, a: Point, b: Point, by: f64) -> bool { + let span = grow([a[0].min(b[0]), a[1].min(b[1]), a[0].max(b[0]), a[1].max(b[1])], by); + !self.some(span, by, |obstacle| crosses(a, b, &obstacle)) + } +} + +/// A packed R-tree over the valid boxes: leaves in Z-order of their middles, [`NODE`] children a +/// node. +struct Index { + /// The box at each leaf. + items: Vec, + /// Each node's box: the leaves, then each level up to the root. + nodes: Vec, + /// Where each level's nodes start, leaves first; the last is the node count. + starts: Vec, +} + +impl Index { + /// An index over `boxes`, leaving out those that are not [`valid`]. + fn new(boxes: &[Rect]) -> Index { + let mut items: Vec = (0..boxes.len()).filter(|&item| valid(&boxes[item])).collect(); + let extent = items.iter().fold(EMPTY, |extent, &item| union(extent, boxes[item])); + let cell = + |v: f64, lo: f64, hi: f64| if hi > lo { ((v - lo) / (hi - lo) * f64::from(u16::MAX)) as u32 } else { 0 }; + items.sort_by_cached_key(|&item| { + let middle = [boxes[item][0].midpoint(boxes[item][2]), boxes[item][1].midpoint(boxes[item][3])]; + (morton(cell(middle[0], extent[0], extent[2]), cell(middle[1], extent[1], extent[3])), item) + }); + let mut nodes: Vec = items.iter().map(|&item| boxes[item]).collect(); + let mut starts = vec![0]; + let mut level = 0; + loop { + let next = nodes.len(); + starts.push(next); + for first in (level..next).step_by(NODE) { + let node = nodes[first..(first + NODE).min(next)].iter().fold(EMPTY, |node, child| union(node, *child)); + nodes.push(node); + } + if nodes.len() - next <= 1 { + break; + } + level = next; + } + starts.push(nodes.len()); + Index { items, nodes, starts } + } + + /// Visits the boxes meeting `region` until `visit` returns true; whether it did. + fn some(&self, region: Rect, visit: &mut impl FnMut(usize) -> bool) -> bool { + let top = self.starts.len() - 2; + !self.items.is_empty() + && meets(&self.nodes[self.starts[top]], ®ion) + && self.descend(top, self.starts[top], region, visit) + } + + /// [`Index::some`] below `node` of `level`. + fn descend(&self, level: usize, node: usize, region: Rect, visit: &mut impl FnMut(usize) -> bool) -> bool { + let first = self.starts[level - 1] + (node - self.starts[level]) * NODE; + let last = (first + NODE).min(self.starts[level]); + (first..last).any(|child| { + meets(&self.nodes[child], ®ion) + && if level > 1 { self.descend(level - 1, child, region, visit) } else { visit(self.items[child]) } + }) + } +} + +/// Position along a Z-order curve on a 65536² grid. +fn morton(x: u32, y: u32) -> u32 { + let spread = |v: u32| { + let v = v & 0xffff; + let v = (v | (v << 8)) & 0x00ff_00ff; + let v = (v | (v << 4)) & 0x0f0f_0f0f; + let v = (v | (v << 2)) & 0x3333_3333; + (v | (v << 1)) & 0x5555_5555 + }; + spread(x) | (spread(y) << 1) +} + +/// Whether a box is finite and not inverted. +fn valid(r: &Rect) -> bool { + r.iter().all(|v| v.is_finite()) && r[0] <= r[2] && r[1] <= r[3] +} + +/// Whether box `a` lies within box `b`. +fn within(a: &Rect, b: &Rect) -> bool { + a[0] >= b[0] && a[1] >= b[1] && a[2] <= b[2] && a[3] <= b[3] +} + +/// Whether a point is on a box's edge. +fn on_edge(p: Point, r: &Rect) -> bool { + p[0] == r[0] || p[0] == r[2] || p[1] == r[1] || p[1] == r[3] +} + +/// Whether a point is strictly inside a box. +fn inside(p: Point, r: &Rect) -> bool { + p[0] > r[0] + EPSILON && p[0] < r[2] - EPSILON && p[1] > r[1] + EPSILON && p[1] < r[3] - EPSILON +} + +/// Whether the axis-aligned segment from `a` to `b` passes through a box's interior. +fn crosses(a: Point, b: Point, r: &Rect) -> bool { + // A vertical segment holds its x and runs along y; a horizontal one holds its y. + let held = usize::from(a[0] != b[0]); + let runs = 1 - held; + a[held] > r[held] + EPSILON + && a[held] < r[held + 2] - EPSILON + && a[runs].max(b[runs]) > r[runs] + EPSILON + && a[runs].min(b[runs]) < r[runs + 2] - EPSILON +} + +/// Whether `v` lies between `a` and `b`, either way round. +fn between(v: f64, a: f64, b: f64) -> bool { + a.min(b) <= v && v <= a.max(b) +} + +/// The length of an orthogonal path between two points. +fn manhattan(a: Point, b: Point) -> f64 { + (a[0] - b[0]).abs() + (a[1] - b[1]).abs() +} + +/// −1, 0, or 1 as `v` is below, at, or above zero. +fn sign(v: f64) -> f64 { + if v > 0.0 { + 1.0 + } else if v < 0.0 { + -1.0 + } else { + 0.0 + } +} + +/// The axis signs of the way from one point to another. +fn direction(from: Point, to: Point) -> Point { + [sign(to[0] - from[0]), sign(to[1] - from[1])] +} + +/// A path's points without repeats or in-line middles. +pub(crate) fn simplify(path: &[Point]) -> Vec { + let mut out: Vec = Vec::with_capacity(path.len()); + for &p in path { + if out.last() == Some(&p) { + continue; + } + if let [.., a, b] = out[..] + && ((a[0] == b[0] && b[0] == p[0]) || (a[1] == b[1] && b[1] == p[1])) + { + out.pop(); + } + out.push(p); + } + out +} + +/// A net's chain of segments along one line, which a track moves as one. +struct Run { + net: usize, + /// The joints it carries. + joints: Vec, + /// The line's coordinate on the axis tracks move it along. + line: f64, + /// Where it starts and ends along the line. + along: [f64; 2], + /// Where its ends turn: below zero toward lower lines, above toward higher. + turn: f64, + /// The lines tracks may move it between; one line for a run holding a terminal. + limits: [f64; 2], +} + +impl Run { + /// Whether it holds a terminal, so no track moves it. + fn held(&self) -> bool { + self.limits[0] == self.limits[1] + } +} + +/// Every net's runs on lines across `axis`: maximal chains of segments along one line through +/// joints. A stub's end keeps `least` off its terminal. +fn runs(trees: &[Option], axis: usize, least: f64) -> Vec { + let mut runs = Vec::new(); + for (net, tree) in trees.iter().enumerate() { + let Some(tree) = tree else { continue }; + let count = tree.points.len(); + let line = |joint: usize| tree.points[joint][axis]; + let along = |joint: usize| tree.points[joint][1 - axis]; + let on_line = |a: usize, b: usize| line(a) == line(b) && along(a) != along(b); + let mut neighbors = vec![Vec::new(); count]; + for child in 1..count { + let parent = tree.parent[child]; + neighbors[child].push(parent); + neighbors[parent].push(child); + } + let mut component = vec![NONE; count]; + for seed in 0..count { + if component[seed] != NONE || !neighbors[seed].iter().any(|&other| on_line(seed, other)) { + continue; + } + let mut joints = Vec::new(); + let mut stack = vec![seed]; + component[seed] = seed; + while let Some(joint) = stack.pop() { + joints.push(joint); + for &other in &neighbors[joint] { + if component[other] == NONE && on_line(joint, other) { + component[other] = seed; + stack.push(other); + } + } + } + let (mut first, mut last) = (joints[0], joints[0]); + let mut limits = [f64::NEG_INFINITY, f64::INFINITY]; + for &joint in &joints { + if along(joint) < along(first) { + first = joint; + } + if along(joint) > along(last) { + last = joint; + } + match tree.joints[joint] { + Joint::Terminal => limits = [line(joint); 2], + Joint::Stub(terminal) => { + let out = sign(line(joint) - line(terminal)); + if out > 0.0 { + limits[0] = limits[0].max(line(terminal) + least); + } else if out < 0.0 { + limits[1] = limits[1].min(line(terminal) - least); + } + } + Joint::Bend => {} + } + } + let turn = |joint: usize| -> f64 { + neighbors[joint] + .iter() + .filter(|&&other| component[other] != seed) + .map(|&other| sign(line(other) - line(joint))) + .sum() + }; + let at = line(seed); + runs.push(Run { + net, + line: at, + along: [along(first), along(last)], + turn: turn(first) + turn(last), + limits: [limits[0].min(at), limits[1].max(at)], + joints, + }); + } + } + runs +} + +#[cfg(test)] +mod tests { + use super::*; + + const SPACING: f64 = 8.0; + + /// A terminal at `at` on `side` of obstacle `owner`. + fn on(at: Point, side: Side, owner: u32) -> Terminal { + Terminal { at, side: Some(side), owner: Some(owner) } + } + + /// Every segment of a net's polylines. + fn segments(wire: &[Vec]) -> Vec<[Point; 2]> { + wire.iter().flat_map(|line| line.windows(2).map(|pair| [pair[0], pair[1]])).collect() + } + + /// Whether every segment runs horizontally or vertically. + fn orthogonal(wire: &[Vec]) -> bool { + segments(wire).iter().all(|[a, b]| a[0] == b[0] || a[1] == b[1]) + } + + /// Whether no segment passes through any of `boxes`. + fn outside(wire: &[Vec], boxes: &[Rect]) -> bool { + segments(wire).iter().all(|[a, b]| boxes.iter().all(|r| !crosses(*a, *b, r))) + } + + /// The point next to the terminal at `at` on its wire: the way the wire leaves it. + fn leaving(wire: &[Vec], at: Point) -> Point { + wire.iter() + .find_map(|line| match line[..] { + [first, next, ..] if first == at => Some(next), + [.., next, last] if last == at => Some(next), + _ => None, + }) + .expect("the wire ends at the terminal") + } + + /// Whether the polylines make one tree reaching every terminal: each starts at the first terminal + /// or where another ends. + fn one_tree(wire: &[Vec], terminals: &[Terminal]) -> bool { + let mut reached = vec![terminals[0].at]; + let mut joined = vec![false; wire.len()]; + while let Some(line) = (0..wire.len()).find(|&line| !joined[line] && reached.contains(&wire[line][0])) { + joined[line] = true; + reached.extend(wire[line].last()); + } + joined.iter().all(|&joined| joined) && terminals.iter().all(|terminal| reached.contains(&terminal.at)) + } + + #[test] + fn side_by_side_boxes_join_by_a_straight_run() { + let boxes = [[0.0, 0.0, 20.0, 20.0], [100.0, 0.0, 120.0, 20.0]]; + let nets = [Net { terminals: vec![on([20.0, 10.0], Side::Right, 0), on([100.0, 10.0], Side::Left, 1)] }]; + assert_eq!(route(&boxes, &[], &nets, &[], SPACING), vec![vec![vec![[20.0, 10.0], [100.0, 10.0]]]]); + } + + #[test] + fn a_wire_bends_around_an_obstacle_between() { + let boxes = [[0.0, 0.0, 20.0, 20.0], [200.0, 0.0, 220.0, 20.0], [80.0, -30.0, 140.0, 50.0]]; + let nets = [Net { terminals: vec![on([20.0, 10.0], Side::Right, 0), on([200.0, 10.0], Side::Left, 1)] }]; + let wire = &route(&boxes, &[], &nets, &[], SPACING)[0]; + assert!(orthogonal(wire), "{wire:?}"); + assert!(segments(wire).len() > 2, "it bends: {wire:?}"); + assert!(outside(wire, &boxes), "{wire:?}"); + assert!(one_tree(wire, &nets[0].terminals), "{wire:?}"); + } + + #[test] + fn wires_go_around_groups_they_do_not_join() { + // A thin group on the straight way between two blocks: through it is shorter, around keeps out. + let boxes = [[20.0, 45.0, 40.0, 55.0], [160.0, 45.0, 180.0, 55.0]]; + let group = [90.0, 44.0, 110.0, 56.0]; + let nets = [Net { terminals: vec![on([40.0, 50.0], Side::Right, 0), on([160.0, 50.0], Side::Left, 1)] }]; + let through = &route(&boxes, &[], &nets, &[], SPACING)[0]; + assert_eq!(segments(through).len(), 1, "without the group, straight: {through:?}"); + let around = &route(&boxes, &[group], &nets, &[], SPACING)[0]; + assert!(outside(around, &[group]), "with it, around: {around:?}"); + assert!(orthogonal(around) && one_tree(around, &nets[0].terminals), "{around:?}"); + } + + #[test] + fn bends_meeting_on_a_short_run_repeat_no_point() { + // An S-bend whose middle run is shorter than two radii: the arcs of its bends meet halfway. + let wire = finish(&[vec![[0.0, 0.0], [20.0, 0.0], [20.0, 10.0], [40.0, 10.0]]], 8.0); + let line = &wire[0]; + assert!(line.windows(2).all(|w| manhattan(w[0], w[1]) > EPSILON), "no point twice: {line:?}"); + assert_eq!((line[0], line[line.len() - 1]), ([0.0, 0.0], [40.0, 10.0])); + // A part ending where another starts still doubles its end: a junction. + let tree = finish(&[vec![[0.0, 0.0], [10.0, 0.0]], vec![[10.0, 0.0], [10.0, 10.0]]], 8.0); + assert_eq!(tree[0], [[0.0, 0.0], [10.0, 0.0], [10.0, 0.0]]); + } + + #[test] + fn crossing_and_running_along_a_border_cost() { + let groups = Groups { boxes: vec![[0.0, 0.0, 100.0, 90.0]], clearance: 2.0 * SPACING }; + assert_eq!(groups.cost([-10.0, 10.0], [10.0, 10.0]), CROSSING * 2.0 * SPACING, "a crossing"); + assert_eq!(groups.cost([10.0, 10.0], [20.0, 10.0]), 0.0, "inside, away from the border"); + assert_eq!(groups.cost([10.0, 88.0], [30.0, 88.0]), 20.0, "along the border"); + } + + #[test] + fn a_wall_too_long_for_the_window_is_gone_around() { + let boxes = [ + [0.0, 0.0, 20.0, 20.0], + [200.0, 0.0, 220.0, 20.0], + [80.0, -100.0, 100.0, 120.0], + [100.0, -400.0, 120.0, 90.0], + ]; + let nets = [Net { terminals: vec![on([20.0, 10.0], Side::Right, 0), on([200.0, 10.0], Side::Left, 1)] }]; + let wire = &route(&boxes, &[], &nets, &[], SPACING)[0]; + assert!(orthogonal(wire) && outside(wire, &boxes), "{wire:?}"); + } + + #[test] + fn terminals_leave_along_their_sides() { + let boxes = [ + [0.0, 0.0, 20.0, 20.0], + [100.0, 100.0, 120.0, 120.0], + [0.0, 200.0, 20.0, 220.0], + [100.0, -100.0, 120.0, -80.0], + ]; + let nets = [ + Net { terminals: vec![on([10.0, 20.0], Side::Top, 0), on([100.0, 110.0], Side::Left, 1)] }, + Net { terminals: vec![on([10.0, 200.0], Side::Bottom, 2), on([120.0, -90.0], Side::Right, 3)] }, + ]; + let routes = route(&boxes, &[], &nets, &[], SPACING); + for (net, wire) in nets.iter().zip(&routes) { + assert!(orthogonal(wire) && outside(wire, &boxes), "{wire:?}"); + for terminal in &net.terminals { + let next = leaving(wire, terminal.at); + let out = [next[0] - terminal.at[0], next[1] - terminal.at[1]]; + let normal = terminal.side.expect("a side").normal(); + let ahead = out[0] * normal[0] + out[1] * normal[1]; + assert!(ahead > 0.0 && ahead == manhattan(next, terminal.at), "{terminal:?} leaves toward {next:?}"); + } + } + } + + #[test] + fn a_net_of_three_terminals_is_one_tree() { + let boxes = [[0.0, 0.0, 20.0, 20.0], [100.0, -60.0, 120.0, -40.0], [100.0, 60.0, 120.0, 80.0]]; + let net = Net { + terminals: vec![ + on([20.0, 10.0], Side::Right, 0), + on([100.0, -50.0], Side::Left, 1), + on([100.0, 70.0], Side::Left, 2), + ], + }; + let wire = &route(&boxes, &[], std::slice::from_ref(&net), &[], SPACING)[0]; + assert!(wire.len() >= 3, "a junction splits it: {wire:?}"); + assert!(orthogonal(wire) && outside(wire, &boxes), "{wire:?}"); + assert!(one_tree(wire, &net.terminals), "{wire:?}"); + } + + #[test] + fn parallel_runs_of_different_nets_keep_spacing_apart() { + let boxes = + [[0.0, 0.0, 20.0, 20.0], [0.0, 30.0, 20.0, 50.0], [100.0, 60.0, 120.0, 80.0], [100.0, 90.0, 120.0, 110.0]]; + let nets = [ + Net { terminals: vec![on([20.0, 10.0], Side::Right, 0), on([100.0, 70.0], Side::Left, 2)] }, + Net { terminals: vec![on([20.0, 40.0], Side::Right, 1), on([100.0, 100.0], Side::Left, 3)] }, + ]; + let routes = route(&boxes, &[], &nets, &[], SPACING); + // A segment as the axis it runs along, its line, and its extent along it. + let run = |[a, b]: [Point; 2]| { + let axis = usize::from(a[0] == b[0]); + (axis, a[1 - axis], [a[axis].min(b[axis]), a[axis].max(b[axis])]) + }; + let mut beside = 0; + for one in segments(&routes[0]).into_iter().map(run) { + for other in segments(&routes[1]).into_iter().map(run) { + let overlap = one.2[1].min(other.2[1]) - one.2[0].max(other.2[0]); + if one.0 != other.0 || overlap <= EPSILON { + continue; + } + let apart = (one.1 - other.1).abs(); + assert!(apart >= SPACING - EPSILON, "runs {apart} apart: {routes:?}"); + beside += usize::from(apart < 2.0 * SPACING); + } + } + assert!(beside > 0, "the nets run side by side: {routes:?}"); + } + + #[test] + fn an_enclosed_terminal_still_gets_an_orthogonal_route() { + let ring = [ + [80.0, 40.0, 140.0, 50.0], + [80.0, -30.0, 140.0, -20.0], + [80.0, -30.0, 90.0, 50.0], + [130.0, -30.0, 140.0, 50.0], + ]; + let mut boxes = vec![[0.0, 0.0, 20.0, 20.0], [100.0, 0.0, 120.0, 20.0]]; + boxes.extend(ring); + let nets = [Net { terminals: vec![on([20.0, 10.0], Side::Right, 0), on([100.0, 10.0], Side::Left, 1)] }]; + let wire = &route(&boxes, &[], &nets, &[], SPACING)[0]; + assert!(orthogonal(wire) && one_tree(wire, &nets[0].terminals), "{wire:?}"); + } + + #[test] + fn a_crowded_grid_routes_alike_every_time() { + let mut boxes = Vec::new(); + for row in 0..30 { + for column in 0..30 { + let (x, y) = (f64::from(column) * 60.0, f64::from(row) * 50.0); + boxes.push([x, y, x + 30.0, y + 20.0]); + } + } + let mut seed = 0x2545_f491_u32; + let mut next = move |below: u32| { + seed ^= seed << 13; + seed ^= seed >> 17; + seed ^= seed << 5; + seed % below + }; + let sides = [Side::Left, Side::Right, Side::Top, Side::Bottom]; + let nets: Vec = (0..300) + .map(|n| { + let terminals = (0..if n % 5 == 0 { 3 } else { 2 }) + .map(|_| { + let owner = next(900); + let r: Rect = boxes[owner as usize]; + let side = sides[next(4) as usize]; + let at = match side { + Side::Left => [r[0], r[1].midpoint(r[3])], + Side::Right => [r[2], r[1].midpoint(r[3])], + Side::Top => [r[0].midpoint(r[2]), r[3]], + Side::Bottom => [r[0].midpoint(r[2]), r[1]], + }; + on(at, side, owner) + }) + .collect(); + Net { terminals } + }) + .collect(); + let routes = route(&boxes, &[], &nets, &[], SPACING); + assert_eq!(routes, route(&boxes, &[], &nets, &[], SPACING), "the same input routes the same"); + for (net, wire) in nets.iter().zip(&routes) { + assert!(orthogonal(wire), "{wire:?}"); + assert!(one_tree(wire, &net.terminals), "{net:?}: {wire:?}"); + let others: Vec = (0..boxes.len()) + .filter(|&other| net.terminals.iter().all(|terminal| terminal.owner != Some(other as u32))) + .map(|other| boxes[other]) + .collect(); + assert!(outside(wire, &others), "{net:?}: {wire:?}"); + } + } + + #[test] + fn nets_without_two_terminals_get_nothing() { + let free = Terminal { at: [0.0, 0.0], side: None, owner: None }; + let nets = [ + Net::default(), + Net { terminals: vec![free] }, + Net { terminals: vec![free, Terminal { at: [f64::NAN, 0.0], ..free }] }, + ]; + assert_eq!(route(&[], &[], &nets, &[], SPACING), vec![Vec::>::new(); 3]); + } + + #[test] + fn terminals_without_sides_leave_toward_the_rest_of_the_net() { + let boxes = [[0.0, 0.0, 20.0, 20.0]]; + let nets = [Net { + terminals: vec![ + Terminal { at: [20.0, 10.0], side: None, owner: Some(0) }, + Terminal { at: [100.0, 50.0], side: None, owner: None }, + ], + }]; + let wire = &route(&boxes, &[], &nets, &[], SPACING)[0]; + assert!(orthogonal(wire) && outside(wire, &boxes), "{wire:?}"); + assert_eq!(leaving(wire, [20.0, 10.0])[1], 10.0, "it leaves by the side it is on: {wire:?}"); + } +} diff --git a/crates/latkit/src/layout/stress.rs b/crates/latkit/src/layout/stress.rs new file mode 100644 index 00000000..97d97e0e --- /dev/null +++ b/crates/latkit/src/layout/stress.rs @@ -0,0 +1,315 @@ +//! Stress majorization: vertices at graph distances, then their boxes parted. Each vertex's terms are +//! its neighbors a gap away and a few pivots at their graph distance, so a round costs O(vertices × +//! pivots). Pinned vertices hold the rest; vertices start near the pinned ones they link to, or +//! around their part's most linked vertex, and parts nothing pins pack apart. Groups nest as +//! [`nested`] lays them out: a group's members settle by stress among themselves, and the group by +//! stress among the vertices and groups beside it. + +use std::collections::VecDeque; + +use super::levels::{Graph, Level, nested}; +use super::overlap::separate; +use super::pack::pack; + +/// Jacobi rounds stress runs. +const ROUNDS: usize = 240; +/// Pivots stress measures graph distances from, and the distances it keeps in all. +const PIVOTS: usize = 32; +const DISTANCES: usize = 8_000_000; +/// The share of the gap vertices' boxes keep clear of each other. +const CLEARANCE: f64 = 0.25; + +/// Every vertex's center: neighbors `gap` apart, pinned vertices where they are, boxes a quarter of +/// the gap clear of each other; links' directions do not matter. +pub(crate) fn stress(graph: &Graph<'_>, gap: f64) -> Vec<[f64; 2]> { + nested(graph, |level| place(level, gap)) +} + +/// One level's centers. +fn place(level: &Level, gap: f64) -> Vec<[f64; 2]> { + let n = level.sizes.len(); + if n == 0 { + return Vec::new(); + } + let (offsets, targets) = neighbors(n, &level.links); + let terms = terms(n, gap, &offsets, &targets); + let mut position = start(level, gap, &offsets, &targets); + let mut next = position.clone(); + for _ in 0..ROUNDS { + for v in 0..n { + if let Some(pin) = level.pinned[v] { + next[v] = pin; + continue; + } + let here = position[v]; + let (mut sum, mut weights) = ([0.0; 2], 0.0); + for &(other, distance, weight) in &terms[v] { + let there = position[other as usize]; + let apart = [here[0] - there[0], here[1] - there[1]]; + let length = apart[0].hypot(apart[1]); + // Vertices at one point part along a direction of their own. + let toward = if length > 1e-9 { + [apart[0] / length, apart[1] / length] + } else { + let angle = v as f64; + [angle.cos(), angle.sin()] + }; + sum = [ + sum[0] + weight * (there[0] + distance * toward[0]), + sum[1] + weight * (there[1] + distance * toward[1]), + ]; + weights += weight; + } + next[v] = if weights > 0.0 { [sum[0] / weights, sum[1] / weights] } else { here }; + } + std::mem::swap(&mut position, &mut next); + } + let boxes: Vec<[f64; 4]> = + position.iter().zip(&level.sizes).map(|(p, s)| [p[0], p[1], s[0] / 2.0, s[1] / 2.0]).collect(); + let pinned: Vec = level.pinned.iter().map(Option::is_some).collect(); + separate(&boxes, &pinned, gap * CLEARANCE) +} + +/// Each vertex's terms: its neighbors one `gap` away, weighted by the inverse square, and pivots at +/// their graph distance, weighted by the vertices nearer the pivot than half that distance. +fn terms(n: usize, gap: f64, offsets: &[u32], targets: &[u32]) -> Vec> { + let degree = |v: usize| offsets[v + 1] - offsets[v]; + // Pivots far from each other: each the vertex farthest from those before, other parts first. + let count = PIVOTS.min(n).min((DISTANCES / n.max(1)).max(2)); + let mut pivots: Vec<(usize, Vec)> = Vec::with_capacity(count); + let mut nearest = vec![u32::MAX; n]; + let mut next = (0..n).max_by_key(|&v| degree(v)).unwrap_or(0); + while pivots.len() < count { + let distance = hops(next, offsets, targets); + for (near, &d) in nearest.iter_mut().zip(&distance) { + *near = (*near).min(d); + } + pivots.push((next, distance)); + let Some(far) = (0..n).max_by_key(|&v| (nearest[v], degree(v))) else { break }; + if nearest[far] == 0 { + break; + } + next = far; + } + // Each pivot's region, as the sorted distances of the vertices nearest it. + let mut regions: Vec> = vec![Vec::new(); pivots.len()]; + for v in 0..n { + let closest = pivots.iter().enumerate().map(|(p, (_, d))| (p, d[v])).filter(|&(_, d)| d != u32::MAX); + if let Some((p, d)) = closest.min_by_key(|&(_, d)| d) { + regions[p].push(d); + } + } + for region in &mut regions { + region.sort_unstable(); + } + let weight = 1.0 / (gap * gap); + (0..n) + .map(|v| { + let mut own: Vec<(u32, f64, f64)> = + targets[offsets[v] as usize..offsets[v + 1] as usize].iter().map(|&w| (w, gap, weight)).collect(); + for (p, (pivot, distance)) in pivots.iter().enumerate() { + let d = distance[v]; + if *pivot == v || d == u32::MAX || d <= 1 { + continue; + } + let held = regions[p].partition_point(|&r| 2 * r <= d).max(1) as f64; + let apart = gap * f64::from(d); + own.push((*pivot as u32, apart, held / (apart * apart))); + } + own + }) + .collect() +} + +/// Where stress starts each vertex. A part holding pinned vertices starts around their middle, each +/// free vertex a gap per hop from the nearest of them; a part nothing pins starts around its most +/// linked vertex on a golden-angle spiral, and such parts pack apart below the pinned ones. +fn start(level: &Level, gap: f64, offsets: &[u32], targets: &[u32]) -> Vec<[f64; 2]> { + let n = level.sizes.len(); + let mut start = vec![[0.0; 2]; n]; + let mut part = vec![u32::MAX; n]; + let mut parts: Vec> = Vec::new(); + let mut order: Vec = (0..n).collect(); + order.sort_by_key(|&v| (level.pinned[v].is_none(), std::cmp::Reverse(offsets[v + 1] - offsets[v]))); + for &root in &order { + if part[root] != u32::MAX { + continue; + } + let id = parts.len() as u32; + part[root] = id; + let mut inside = vec![root]; + let mut k = 0; + while k < inside.len() { + let v = inside[k]; + k += 1; + for &w in &targets[offsets[v] as usize..offsets[v + 1] as usize] { + if part[w as usize] == u32::MAX { + part[w as usize] = id; + inside.push(w as usize); + } + } + } + parts.push(inside); + } + let mut loose: Vec<(usize, [f64; 2])> = Vec::new(); + let spiral = |v: usize, hops: u32| { + let angle = v as f64 * 2.399_963_229_728_653; + let radius = gap * f64::from(hops) + gap * 0.1 * (v % 7) as f64; + [radius * angle.cos(), radius * angle.sin()] + }; + for (p, inside) in parts.iter().enumerate() { + let pins: Vec<[f64; 2]> = inside.iter().filter_map(|&v| level.pinned[v]).collect(); + // Hops from the pinned vertices, or from the part's first, most linked one. + let sources: Vec = if pins.is_empty() { + vec![inside[0]] + } else { + inside.iter().copied().filter(|&v| level.pinned[v].is_some()).collect() + }; + let mut hop = vec![u32::MAX; n]; + let mut from = vec![usize::MAX; n]; + let mut queue: VecDeque = VecDeque::new(); + for &s in &sources { + hop[s] = 0; + from[s] = s; + queue.push_back(s); + } + while let Some(v) = queue.pop_front() { + for &w in &targets[offsets[v] as usize..offsets[v + 1] as usize] { + if hop[w as usize] == u32::MAX { + hop[w as usize] = hop[v] + 1; + from[w as usize] = from[v]; + queue.push_back(w as usize); + } + } + } + if pins.is_empty() { + let mut reach: f64 = 0.0; + for &v in inside { + start[v] = spiral(v, hop[v]); + reach = reach.max(start[v][0].hypot(start[v][1])); + } + loose.push((p, [2.0 * reach + gap, 2.0 * reach + gap])); + continue; + } + for &v in inside { + start[v] = level.pinned[v].unwrap_or_else(|| { + let anchor = level.pinned[from[v]].unwrap_or(pins[0]); + let offset = spiral(v, hop[v]); + [anchor[0] + offset[0], anchor[1] + offset[1]] + }); + } + } + if loose.is_empty() { + return start; + } + // Parts nothing pins pack in rows below whatever is pinned. + let pinned: Vec<[f64; 2]> = level.pinned.iter().flatten().copied().collect(); + let below = pinned.iter().map(|p| p[1]).fold(f64::INFINITY, f64::min); + let left = pinned.iter().map(|p| p[0]).fold(f64::INFINITY, f64::min); + let origin = if pinned.is_empty() { [0.0, 0.0] } else { [left, below - 2.0 * gap] }; + let boxes: Vec<[f64; 2]> = loose.iter().map(|(_, b)| *b).collect(); + for ((p, size), corner) in loose.iter().zip(pack(&boxes, gap, 16.0 / 9.0)) { + let center = [origin[0] + corner[0] + size[0] / 2.0, origin[1] + corner[1] - size[1] / 2.0]; + for &v in &parts[*p] { + start[v] = [center[0] + start[v][0], center[1] + start[v][1]]; + } + } + start +} + +/// Each vertex's neighbors, once each. +fn neighbors(n: usize, links: &[[u32; 2]]) -> (Vec, Vec) { + let mut pairs: Vec<(u32, u32)> = links + .iter() + .filter(|[a, b]| a != b && (*a as usize) < n && (*b as usize) < n) + .flat_map(|&[a, b]| [(a, b), (b, a)]) + .collect(); + pairs.sort_unstable(); + pairs.dedup(); + let mut offsets = vec![0_u32; n + 1]; + for &(a, _) in &pairs { + offsets[a as usize + 1] += 1; + } + for i in 0..n { + offsets[i + 1] += offsets[i]; + } + (offsets, pairs.into_iter().map(|(_, b)| b).collect()) +} + +/// Hops from `from` to every vertex; `u32::MAX` where none lead. +fn hops(from: usize, offsets: &[u32], targets: &[u32]) -> Vec { + let mut distance = vec![u32::MAX; offsets.len() - 1]; + let mut queue = VecDeque::from([from]); + distance[from] = 0; + while let Some(v) = queue.pop_front() { + for &w in &targets[offsets[v] as usize..offsets[v + 1] as usize] { + if distance[w as usize] == u32::MAX { + distance[w as usize] = distance[v] + 1; + queue.push_back(w as usize); + } + } + } + distance +} + +#[cfg(test)] +mod tests { + use super::*; + + fn apart(a: [f64; 2], b: [f64; 2]) -> f64 { + (a[0] - b[0]).hypot(a[1] - b[1]) + } + + /// `sizes` laid out by stress with `links`, `pinned`, and `groups`, groups padding their members by 5. + fn laid( + sizes: &[[f64; 2]], + links: &[[u32; 2]], + pinned: &[Option<[f64; 2]>], + groups: &[Option], + gap: f64, + ) -> Vec<[f64; 2]> { + let pads = vec![[5.0; 4]; sizes.len()]; + stress(&Graph { sizes, links, pinned, groups, pads: &pads }, gap) + } + + #[test] + fn neighbors_settle_a_gap_apart_and_leaves_spread() { + // A chain 0 → 1 → 2 and a branch 1 → 3. + let p = laid(&[[4.0, 4.0]; 4], &[[0, 1], [1, 2], [1, 3]], &[None; 4], &[None; 4], 40.0); + for (a, b) in [(0, 1), (1, 2), (1, 3)] { + assert!((apart(p[a], p[b]) - 40.0).abs() < 14.0, "{a}–{b}: {p:?}"); + } + assert!(apart(p[2], p[3]) > 56.0, "leaves spread: {p:?}"); + } + + #[test] + fn pins_hold_and_boxes_part() { + let pinned = [Some([-100.0, 60.0]), None, None, None]; + let p = laid(&[[60.0, 20.0]; 4], &[[0, 1], [1, 2], [1, 3]], &pinned, &[None; 4], 10.0); + assert_eq!(p[0], [-100.0, 60.0]); + for i in 0..4 { + for j in i + 1..4 { + let (dx, dy) = ((p[i][0] - p[j][0]).abs(), (p[i][1] - p[j][1]).abs()); + assert!(dx >= 60.0 || dy >= 20.0, "{i} and {j} overlap: {p:?}"); + } + } + } + + #[test] + fn groups_hold_their_members_apart_from_each_other() { + // Groups 0 and 1 hold three linked vertices each, and link through their members. + let sizes = + [[0.0; 2], [0.0; 2], [20.0, 10.0], [20.0, 10.0], [20.0, 10.0], [20.0, 10.0], [20.0, 10.0], [20.0, 10.0]]; + let groups = [None, None, Some(0), Some(0), Some(0), Some(1), Some(1), Some(1)]; + let links = [[2, 3], [3, 4], [5, 6], [6, 7], [4, 5]]; + let p = laid(&sizes, &links, &[None; 8], &groups, 40.0); + let frame = |members: &[usize]| { + let boxes = members.iter().map(|&m| super::super::levels::frame(p[m], sizes[m])); + let b = super::super::levels::bounds(boxes); + [b[0] - 5.0, b[1] - 5.0, b[2] + 5.0, b[3] + 5.0] + }; + let (a, b) = (frame(&[2, 3, 4]), frame(&[5, 6, 7])); + let overlap = a[0] < b[2] && b[0] < a[2] && a[1] < b[3] && b[1] < a[3]; + assert!(!overlap, "the groups' boxes stand apart: {a:?} {b:?}"); + } +} diff --git a/crates/latkit/src/lib.rs b/crates/latkit/src/lib.rs new file mode 100644 index 00000000..b029e8d7 --- /dev/null +++ b/crates/latkit/src/lib.rs @@ -0,0 +1,83 @@ +//! Columnar data drawn as vertices, edges, lines, and areas on the GPU. +//! +//! A [`Data`] is a named collection of [`Table`]s, changed in place by [`Patch`]es; a clone is an +//! O(1) snapshot. A [`Scene`] describes what to draw and how it answers input: marks that name tables +//! of data, in a space, with a theme and controls. A [`View`] draws a scene into any wgpu frame, is +//! given the data by name, and turns platform [`Input`] into [`Event`]s. +//! +//! Every input is plain data that deserializes: [`from_json`] reads one from JSON text, an error +//! naming the path to what it could not read, and [`schema`] gives its JSON Schema. + +// Without `gpu`, some of the data's internals have no reader. +#[cfg_attr(not(feature = "gpu"), allow(dead_code))] +mod data; +#[cfg(feature = "gpu")] +mod derive; +mod error; +#[cfg_attr(not(feature = "gpu"), allow(dead_code))] +mod expr; +mod geo; +#[cfg(feature = "gpu")] +mod gpu; +#[cfg(feature = "gpu")] +pub mod host; +mod image; +mod json; +#[cfg(feature = "gpu")] +mod layout; +#[cfg(feature = "gpu")] +mod panels; +mod pending; +pub mod resource; +#[cfg(feature = "gpu")] +mod scene; +mod schema; +#[cfg(feature = "gpu")] +mod sheet; +#[cfg(feature = "gpu")] +mod shot; +#[cfg(feature = "gpu")] +mod tiles; +#[cfg(feature = "gpu")] +mod time; +mod url; +#[cfg(feature = "gpu")] +mod video; +#[cfg(feature = "gpu")] +mod view; +#[cfg(all(feature = "web", target_arch = "wasm32"))] +pub mod web; + +pub use data::{ + Data, DecodeLimits, Description, Envelope, FieldDescription, Id, Ids, Kind, Name, Patch, Row, Rows, Table, + TableDescription, Value, Values, +}; +pub use data::{Order, Patches, Query}; +pub use error::{Error, Path, Result, Step}; +pub use expr::{ + Color, Colormap, ColormapKind, Expr, Mapped, Size, Stop, Then, When, elapsed, field, hovered, pointer, selected, + units, when, zoom, +}; +pub use image::{Image, ImageFormat}; +pub use json::from_json; +pub use pending::{Pending, Resolver}; +pub use schema::schema; +#[cfg(feature = "gpu")] +pub use schema::schemas; +#[cfg(feature = "gpu")] +pub use { + gpu::{Budget, DeviceEvents, Gpu, work::Work}, + panels::Panels, + scene::{ + Areas, Axis, Controls, Diagram, Direction, Earth, Edges, Faces, Flow, Format, Grid, Interpolation, Label, + Layered, Layout, Lines, Mark, Marker, Motion, Plane, Plot, Port, Projection, Route, Scene, Shadow, Shape, Side, + Space, Stress, Theme, Vertices, Zoom, + }, + shot::Shot, + tiles::Tiles, + video::{Encoding, Mp4, Pixels, Sink, Video}, + view::{ + Button, Camera, Cursor, Device, End, Event, Fit, Frame, Hit, Input, Key, Modifiers, Phase, Sample, Stats, + Trigger, View, Waiting, + }, +}; diff --git a/crates/latkit/src/panels.rs b/crates/latkit/src/panels.rs new file mode 100644 index 00000000..48b8ff59 --- /dev/null +++ b/crates/latkit/src/panels.rs @@ -0,0 +1,97 @@ +//! Panels: where views draw in a target they share. A canvas showing several views and a picture or +//! video composing them lay their views out the same way. + +use crate::{Error, Result}; + +/// Where each of several views draws in a target: x, y, width, and height as fractions of it, a +/// panel per view, in order; a later panel draws over an earlier one. None given is one view filling +/// the target. +/// +/// ``` +/// use latkit::Panels; +/// let map_over_plot = Panels::from([[0.0, 0.0, 1.0, 0.8], [0.0, 0.8, 1.0, 0.2]]); +/// assert_eq!(map_over_plot.len(), 2); +/// assert_eq!(Panels::default().len(), 1); +/// ``` +#[derive(Clone, PartialEq, Debug, Default, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] +#[serde(transparent)] +pub struct Panels(Vec<[f32; 4]>); + +impl Panels { + /// How many views the panels take: one when none are given. + pub fn len(&self) -> usize { + self.0.len().max(1) + } + + /// Whether no parts were given, so one view fills the target. + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// The pixels of a target of `size` each view draws in, edges on multiples of `align`. + pub(crate) fn rects(&self, size: [u32; 2], align: [u32; 2]) -> Result> { + let whole = [[0.0, 0.0, 1.0, 1.0]]; + let parts = if self.0.is_empty() { &whole[..] } else { &self.0[..] }; + let edge = |f: f32, length: u32, align: u32| { + let units = (f64::from(f.clamp(0.0, 1.0)) * f64::from(length) / f64::from(align)).round() as u32; + (units * align).min(length) + }; + parts + .iter() + .map(|p| { + let x = [edge(p[0], size[0], align[0]), edge(p[0] + p[2], size[0], align[0])]; + let y = [edge(p[1], size[1], align[1]), edge(p[1] + p[3], size[1], align[1])]; + if x[1] <= x[0] || y[1] <= y[0] { + return Err(Error::invalid(format!("panel {p:?} covers no pixels")).at("panels")); + } + Ok(Rect { origin: [x[0], y[0]], size: [x[1] - x[0], y[1] - y[0]] }) + }) + .collect() + } +} + +impl From> for Panels { + fn from(parts: Vec<[f32; 4]>) -> Panels { + Panels(parts) + } +} + +impl From<[[f32; 4]; N]> for Panels { + fn from(parts: [[f32; 4]; N]) -> Panels { + Panels(parts.to_vec()) + } +} + +/// A view's panel of a target in pixels: its top left corner and its size. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub(crate) struct Rect { + pub(crate) origin: [u32; 2], + pub(crate) size: [u32; 2], +} + +impl Rect { + /// Whether the two share a pixel. + pub(crate) fn overlaps(self, other: Rect) -> bool { + (0..2).all(|i| { + self.origin[i] < other.origin[i] + other.size[i] && other.origin[i] < self.origin[i] + self.size[i] + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn panels_split_a_target_on_whole_blocks() { + let panels = Panels::from([[0.0, 0.0, 1.0, 0.7], [0.0, 0.7, 1.0, 0.3]]); + let rects = panels.rects([1920, 1080], [4, 2]).expect("valid"); + assert_eq!(rects, [Rect { origin: [0, 0], size: [1920, 756] }, Rect { origin: [0, 756], size: [1920, 324] }]); + assert!(!rects[0].overlaps(rects[1])); + assert_eq!( + Panels::default().rects([10, 10], [1, 1]).expect("valid"), + [Rect { origin: [0, 0], size: [10, 10] }] + ); + assert!(Panels::from([[0.5, 0.5, 0.0, 0.5]]).rects([10, 10], [1, 1]).is_err()); + } +} diff --git a/crates/latkit/src/pending.rs b/crates/latkit/src/pending.rs new file mode 100644 index 00000000..5ad3d34d --- /dev/null +++ b/crates/latkit/src/pending.rs @@ -0,0 +1,210 @@ +//! The one future latkit hands out: what a view will answer once the GPU has, and what a host's job +//! or fetch will bring. + +use std::future::Future; +use std::pin::Pin; +use std::sync::{Arc, Mutex, PoisonError}; +use std::task::{Context, Poll, Waker}; + +use crate::{Error, Result}; + +/// A value still to come: a future its [`Resolver`] resolves, from a view's frames, a host's worker, +/// or the network. A view's answers resolve to an error when the device is lost, and stay pending +/// while no frames are drawn. Destroying their owner cancels them. Await it, or [`take`](Pending::take) +/// it from a frame loop. +#[must_use = "a pending value does nothing unless awaited or taken"] +pub struct Pending(Arc>>); + +enum Slot { + Waiting { waker: Option, errors: Option>>> }, + Ready(Result), + Taken, +} + +/// What resolves a [`Pending`]: a host keeps it until its job or fetch is done. Dropping it without +/// resolving cancels the answer and wakes its waiter. +pub struct Resolver(Arc>>); + +impl Pending { + /// A pending value, and what resolves it. + pub fn new() -> (Pending, Resolver) { + let slot = Arc::new(Mutex::new(Slot::Waiting { waker: None, errors: None })); + (Pending(slot.clone()), Resolver(slot)) + } + + /// A value already here. + pub fn ready(result: Result) -> Pending { + Pending(Arc::new(Mutex::new(Slot::Ready(result)))) + } + + /// Wakes `waker` once the value is resolved: at once when it already is. + #[cfg(feature = "gpu")] + pub(crate) fn notify(&self, waker: &Waker) { + let mut slot = self.0.lock().unwrap_or_else(PoisonError::into_inner); + match &mut *slot { + Slot::Waiting { waker: waiting, .. } => *waiting = Some(waker.clone()), + Slot::Ready(_) => { + drop(slot); + waker.wake_by_ref(); + } + Slot::Taken => {} + } + } + + /// Reports a host job's failure even if its derivation keeps an earlier result. Called once + /// before handing the pending value to a derivation; superseded/dropped consumers report nothing. + #[cfg(any(feature = "gpu", test))] + pub(crate) fn report_errors(&self, errors: &Arc>>) { + let mut slot = self.0.lock().unwrap_or_else(PoisonError::into_inner); + match &mut *slot { + Slot::Waiting { errors: sink, .. } => *sink = Some(errors.clone()), + Slot::Ready(Err(error)) => errors.lock().unwrap_or_else(PoisonError::into_inner).push(error.clone()), + _ => {} + } + } + + /// The value once resolved, taking it; `None` while it waits, and after it was taken. + pub fn take(&self) -> Option> { + let mut slot = self.0.lock().unwrap_or_else(PoisonError::into_inner); + match std::mem::replace(&mut *slot, Slot::Taken) { + Slot::Ready(value) => Some(value), + waiting @ Slot::Waiting { .. } => { + *slot = waiting; + None + } + Slot::Taken => None, + } + } +} + +impl Resolver { + /// Whether the consumer dropped its pending value, so unstarted work can be skipped. + pub fn is_cancelled(&self) -> bool { + Arc::strong_count(&self.0) == 1 + } + + /// Resolves the pending value with `result`, waking whatever awaits it. + pub fn resolve(self, result: Result) { + let mut slot = self.0.lock().unwrap_or_else(PoisonError::into_inner); + if let Slot::Waiting { errors: Some(errors), .. } = &*slot + && !self.is_cancelled() + && let Err(error) = &result + { + errors.lock().unwrap_or_else(PoisonError::into_inner).push(error.clone()); + } + let previous = std::mem::replace(&mut *slot, Slot::Ready(result)); + drop(slot); + if let Slot::Waiting { waker, .. } = previous + && let Some(waker) = waker + { + waker.wake(); + } + } +} + +impl Drop for Resolver { + fn drop(&mut self) { + let waker = { + let mut slot = self.0.lock().unwrap_or_else(PoisonError::into_inner); + let Slot::Waiting { waker, errors } = &mut *slot else { return }; + if !self.is_cancelled() + && let Some(errors) = errors + { + errors.lock().unwrap_or_else(PoisonError::into_inner).push(Error::Cancelled); + } + let waker = waker.take(); + *slot = Slot::Ready(Err(Error::Cancelled)); + waker + }; + if let Some(waker) = waker { + waker.wake(); + } + } +} + +impl Future for Pending { + type Output = Result; + + fn poll(self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll> { + let mut slot = self.0.lock().unwrap_or_else(PoisonError::into_inner); + match std::mem::replace(&mut *slot, Slot::Taken) { + Slot::Ready(value) => Poll::Ready(value), + Slot::Waiting { errors, .. } => { + *slot = Slot::Waiting { waker: Some(context.waker().clone()), errors }; + Poll::Pending + } + Slot::Taken => panic!("a pending value polled after it resolved"), + } + } +} + +impl std::fmt::Debug for Pending { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("Pending") + } +} + +impl std::fmt::Debug for Resolver { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("Resolver") + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::sync::atomic::{AtomicBool, Ordering}; + use std::task::Wake; + + struct Notified(AtomicBool); + + impl Wake for Notified { + fn wake(self: Arc) { + self.0.store(true, Ordering::Relaxed); + } + } + + #[test] + fn dropping_the_resolver_cancels_and_wakes_the_waiter() { + let (mut pending, resolver) = Pending::::new(); + let notified = Arc::new(Notified(AtomicBool::new(false))); + let waker = Waker::from(notified.clone()); + assert!(Pin::new(&mut pending).poll(&mut Context::from_waker(&waker)).is_pending()); + drop(resolver); + assert!(notified.0.load(Ordering::Relaxed)); + assert_eq!(pending.take(), Some(Err(Error::Cancelled))); + } + + #[test] + fn resolving_preserves_the_answer_when_the_resolver_drops() { + let (pending, resolver) = Pending::new(); + resolver.resolve(Ok(42)); + assert_eq!(pending.take(), Some(Ok(42))); + assert_eq!(pending.take(), None); + } + + #[test] + fn job_failures_report_before_the_answer_is_consumed() { + let errors = Arc::new(Mutex::new(Vec::new())); + let (pending, resolver) = Pending::<()>::new(); + pending.report_errors(&errors); + resolver.resolve(Err(Error::DeviceLost)); + assert_eq!(pending.take(), Some(Err(Error::DeviceLost))); + assert_eq!(*errors.lock().unwrap(), vec![Error::DeviceLost]); + let ready = Pending::<()>::ready(Err(Error::Timeout)); + ready.report_errors(&errors); + assert_eq!(*errors.lock().unwrap(), vec![Error::DeviceLost, Error::Timeout]); + } + + #[test] + fn abandoned_jobs_do_not_report_failures() { + let errors = Arc::new(Mutex::new(Vec::new())); + let (pending, resolver) = Pending::<()>::new(); + pending.report_errors(&errors); + assert!(!resolver.is_cancelled()); + drop(pending); + assert!(resolver.is_cancelled()); + resolver.resolve(Err(Error::DeviceLost)); + assert_eq!(*errors.lock().unwrap(), Vec::::new()); + } +} diff --git a/crates/latkit/src/resource.rs b/crates/latkit/src/resource.rs new file mode 100644 index 00000000..8ea8f821 --- /dev/null +++ b/crates/latkit/src/resource.rs @@ -0,0 +1,38 @@ +//! Fetching bytes for CPU data loading, independent of graphics and window systems. +use crate::Pending; +use std::ops::Range; +use std::sync::Arc; + +/// A source of bytes used by JSON data documents and their binary slices. +pub trait Fetch: Send + Sync { + /// Resolves to the requested bytes, or an error. A missing resource returns empty bytes. + fn fetch(&self, request: &Request) -> Pending>; +} + +#[cfg(feature = "gpu")] +impl Fetch for T { + fn fetch(&self, request: &Request) -> Pending> { + crate::host::Host::fetch(self, request) + } +} + +/// Bytes to fetch: a URL, and the range of its bytes, or all of them. +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub struct Request { + /// The URL. + pub url: Arc, + /// Bytes `start..end`; `None` fetches every byte. + pub range: Option>, +} + +impl Request { + /// Every byte at `url`. + pub fn new(url: impl Into>) -> Request { + Request { url: url.into(), range: None } + } + + /// Bytes `range` at `url`. + pub fn range(url: impl Into>, range: Range) -> Request { + Request { url: url.into(), range: Some(range) } + } +} diff --git a/crates/latkit/src/scene/areas.rs b/crates/latkit/src/scene/areas.rs new file mode 100644 index 00000000..01ad02f2 --- /dev/null +++ b/crates/latkit/src/scene/areas.rs @@ -0,0 +1,66 @@ +use super::mark::{Context, Drawing, GEOMETRY, MarkKind, Style, mark, style_methods}; +use crate::expr::compile::{Compiler, Store}; +use crate::gpu::shaders as wgsl; +use crate::{Error, Kind, Name, Result}; + +mark!( +/// Rows drawn as the areas a polygon field holds: parcels, states, lakes, the land and water of a +/// map. The view cuts each row's polygons into triangles once, off the frame when they are large; +/// on the earth they bend with the globe and stay whole across the antimeridian. Outline areas with +/// a [`Lines`](crate::Lines) mark of the same table, which draws their rings. +/// +/// ``` +/// # use latkit::{field, Areas, Colormap}; +/// let states = Areas::of("map", "states").color(field("load").colormap(Colormap::MAKO)); +/// ``` +Areas { + /// The polygon field each row fills: one polygon's rings, or polygons. `geometry` unless set. + geometry: Option, +}); + +impl Areas { + /// Draws the rows of `table` in dataset `data`. + pub fn of(data: impl Into, table: impl Into) -> Areas { + Areas { style: Style::new(data.into(), table.into()), geometry: None } + } + + /// The polygon field each row fills: one polygon's rings, or polygons. Unless set, the field + /// `geometry`. + #[must_use] + pub fn geometry(mut self, field: impl Into) -> Areas { + self.geometry = Some(field.into()); + self + } + + /// The field each row fills. + pub(crate) fn field(&self) -> Name { + self.geometry.clone().unwrap_or_else(|| GEOMETRY.into()) + } + + pub(crate) fn compile(&self, c: &mut Compiler<'_>, _: Context<'_>) -> Result { + let field = self.field(); + match c.kind(&field) { + Some(Kind::Parts | Kind::Polygons) => {} + Some(_) => return Err(Error::invalid("not a polygon field").at(&field).at("geometry")), + None if self.geometry.is_some() => return Err(Error::invalid("no such field").at(&field).at("geometry")), + None => return Err(Error::invalid("name the polygon field each row fills").at("geometry")), + } + let color = Store::Color { word: wgsl::AREA_COLOR, fallback: wgsl::THEME_AREA }; + match &self.style.color { + Some(expr) => c.channel("color", expr, color)?, + None => c.theme("color", wgsl::THEME_AREA, color)?, + } + c.channel("visible", &self.style.visible, Store::Flag { word: wgsl::AREA_FLAGS, bit: wgsl::VISIBLE })?; + let mut drawing = Drawing::new(MarkKind::Areas, wgsl::AREA_WORDS); + drawing.geometry = c.derived_path(&triangles_of(&field)); + Ok(drawing) + } +} + +/// The derived field holding the triangles of polygon field `field`: per row the point its label +/// hangs from, then three points per triangle. +pub(crate) fn triangles_of(field: &str) -> Name { + format!("{field}.triangles").into() +} + +style_methods!(Areas); diff --git a/crates/latkit/src/scene/compile.rs b/crates/latkit/src/scene/compile.rs new file mode 100644 index 00000000..12966f07 --- /dev/null +++ b/crates/latkit/src/scene/compile.rs @@ -0,0 +1,59 @@ +//! One schema compiler for validation and interactive rendering. + +use std::sync::Arc; + +use super::mark::{Context, Drawing}; +use crate::expr::compile::{Compiler, Fields, Program}; +use crate::{Data, Error, Kind, Mark, Name, Result, Table}; + +/// A mark compiled against the schemas of its dataset and any datasets it joins. +pub(crate) struct Compiled { + pub(crate) program: Arc, + pub(crate) drawing: Drawing, + pub(crate) schemas: Vec<(Name, u64)>, +} + +/// Missing data stays pending in a live view; validation requires it before calling this. +pub(crate) fn compile(mark: &Mark, all: &[Data], context: Context<'_>) -> Result> { + let style = mark.style(); + let Some(data) = all.iter().find(|d| *d.name() == style.data) else { return Ok(None) }; + let Some(table) = data.table(&style.table) else { return Ok(None) }; + let fields = Schema { table, all }; + let mut compiler = Compiler::new(&fields); + let drawing = mark.compile(&mut compiler, context)?; + let program = compiler.finish(); + if program.channels.len() > 32 { + return Err(Error::invalid("more than 32 options read data")); + } + let mut schemas = vec![(data.name().clone(), data.schema())]; + for column in &program.columns { + if let Some((name, _)) = &column.of + && !schemas.iter().any(|(n, _)| n == name) + && let Some(other) = all.iter().find(|d| d.name() == name) + { + schemas.push((name.clone(), other.schema())); + } + } + Ok(Some(Compiled { program: Arc::new(program), drawing, schemas })) +} + +struct Schema<'a> { + table: &'a Table, + all: &'a [Data], +} + +impl Fields for Schema<'_> { + fn kind(&self, of: Option<&(Name, Name)>, name: &str) -> Option { + match of { + None => self.table.kind(name), + Some((data, table)) => self.all.iter().find(|d| d.name() == data)?.table(table)?.kind(name), + } + } + + fn target(&self, name: &str) -> Option { + match self.table.field_named(name)? { + crate::data::Field::Reference(reference) => Some(reference.to.clone()), + _ => None, + } + } +} diff --git a/crates/latkit/src/scene/controls.rs b/crates/latkit/src/scene/controls.rs new file mode 100644 index 00000000..014ef9e1 --- /dev/null +++ b/crates/latkit/src/scene/controls.rs @@ -0,0 +1,140 @@ +use std::time::Duration; + +use schemars::JsonSchema; +use serde::{Deserialize, Deserializer}; + +use super::form::{Presets, preset_or, presets, seconds}; + +/// How a view answers the pointer and keyboard, and how much it moves on its own: a preset, or options +/// over the defaults. Each mark says whether its rows pick, select, and drag; these say what the view +/// itself does. +#[derive(Clone, Copy, PartialEq, Debug, Deserialize, JsonSchema)] +#[serde(remote = "Self", default, rename_all = "camelCase", deny_unknown_fields)] +#[schemars(transform = presets::)] +pub struct Controls { + /// Dragging the background moves the camera. + pub pan: bool, + /// What zooms: the wheel and pinching, or the wheel only with Control or Meta held (as a + /// trackpad's pinch sends it), leaving the plain wheel to scroll the page; or nothing. + pub zoom: Zoom, + /// Dragging with the secondary button, or with Shift, turns and tilts a map or plane. + pub turn: bool, + /// Tab steps through the rows nearest the view's middle and arrows to the nearest row their way; + /// Enter opens the row stepped to and Space selects it. Otherwise arrows pan, `+` and `-` zoom, + /// Home fits, and Escape clears the selection. + pub keyboard: bool, + /// The row the user points at glows. It is hovered either way: events tell it, and `hovered()` + /// reads it. + pub hover: bool, + /// CSS pixels around the pointer that picks reach; touch reaches 8 more. + pub pick_radius: f32, + /// Dragging with Shift selects the rows in a box, instead of turning; a Shift click still toggles + /// its row. + pub select_box: bool, + /// Dragging from a port, from a vertex with Alt, or an edge off its end draws a connection, + /// told as [`Event::Connect`](crate::Event). + pub connect: bool, + /// Delete and Backspace tell [`Event::Delete`](crate::Event) with the selection. + pub delete: bool, + /// Clicking again where nothing moved selects the next row under the point, nearest first, so + /// rows drawn over one another can each be selected. + pub cycle: bool, + /// Seconds a touch or a pen held still asks for a menu, as the secondary button does; zero never + /// does. + #[serde(deserialize_with = "seconds")] + #[schemars(with = "f64")] + pub press: Duration, + /// How much the view moves on its own: eases, flights, coasting, orbits, label fades, comets, and + /// what reads `elapsed()`. + pub motion: Motion, +} + +/// What zooms a view. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Deserialize, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub enum Zoom { + /// The wheel, pinching, and the keys. + #[default] + Wheel, + /// Pinching and the keys, and the wheel only with Control or Meta held, as a trackpad's pinch + /// sends it: the plain wheel scrolls the page. + Modifier, + /// Nothing. + Off, +} + +/// How much a view moves on its own. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Deserialize, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub enum Motion { + /// As the platform asks: reduced where the user asked their system for less motion. + #[default] + System, + /// Every motion. + Full, + /// Only what the user moves: changes apply at once, flights jump, nothing coasts or orbits, + /// labels show without fading, and comets and what reads `elapsed()` hold still. + Reduced, +} + +impl Presets for Controls { + const NAMES: &'static [&'static str] = &["none", "inspect"]; + + fn preset(name: &str) -> Option { + match name { + "none" => Some(Controls::none()), + "inspect" => Some(Controls::inspect()), + _ => None, + } + } + + fn options<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result { + Controls::deserialize(deserializer) + } +} + +impl<'de> Deserialize<'de> for Controls { + fn deserialize>(deserializer: D) -> Result { + preset_or(deserializer) + } +} + +impl Default for Controls { + fn default() -> Controls { + Controls { + pan: true, + zoom: Zoom::Wheel, + turn: true, + keyboard: true, + hover: true, + pick_radius: 6.0, + select_box: false, + connect: false, + delete: false, + cycle: false, + press: Duration::from_millis(500), + motion: Motion::System, + } + } +} + +impl Controls { + /// A view that answers nothing: a still picture, its camera where the application puts it. + pub fn none() -> Controls { + Controls { + pan: false, + zoom: Zoom::Off, + turn: false, + keyboard: false, + hover: false, + press: Duration::ZERO, + ..Controls::default() + } + } + + /// A view to inspect rows in: they glow under the pointer, select, and step with the keys, while + /// the camera stays where the application puts it. + pub fn inspect() -> Controls { + Controls { pan: false, zoom: Zoom::Off, turn: false, ..Controls::default() } + } +} diff --git a/crates/latkit/src/scene/edges.rs b/crates/latkit/src/scene/edges.rs new file mode 100644 index 00000000..e3d03361 --- /dev/null +++ b/crates/latkit/src/scene/edges.rs @@ -0,0 +1,164 @@ +use super::Route; +use super::mark::{Context, Drawing, MarkKind, Stroke, StrokeWords, Style, mark, stroke_methods, style_methods}; +use crate::expr::compile::{Compiler, Store}; +use crate::gpu::shaders as wgsl; +use crate::{Error, Kind, Name, Result}; + +mark!( +/// Rows drawn as strokes between the vertices two reference fields name: branches, links, wires. In a +/// diagram, a row without ends is a net: it joins every vertex port whose reference field names it. +/// +/// ``` +/// # use latkit::{field, Edges}; +/// let branches = Edges::of("grid", "Branch").ends("from", "to").width(field("rating") / 100.0).flow(field("p")); +/// ``` +Edges + stroke { + /// The reference fields naming each row's two vertices. + ends: Option<(Name, Name)> as "[from: string, to: string]", + /// A path field of points each row runs through between its ends. + bends: Option, + /// How each row runs between its ends; on the earth geodesic, elsewhere straight, unless set. + /// Orthogonal routes run around blocks, bends rounded; diagrams only. + route: Option, + /// Whether each row ends in an arrowhead at its second end; a net's at each input it reaches. + arrows: bool, + /// Draws each row as a pole from its own vertex down to the ground beneath it, on a plane or the + /// earth; it has no ends. + poles: bool, + /// Draws each row as a net on a plane or the earth: it joins the vertex rows of `table` whose + /// reference field names it, as a star from their middle to each. + joins: Option<(Name, Name)> as "[table: string, reference: string]", +}); + +impl Edges { + /// Draws the rows of `table` in dataset `data`. + pub fn of(data: impl Into, table: impl Into) -> Edges { + Edges { + style: Style::new(data.into(), table.into()), + stroke: Stroke::default(), + ends: None, + bends: None, + route: None, + arrows: false, + poles: false, + joins: None, + } + } + + /// Draws each row as a net on a plane or the earth: it joins the vertex rows of `table` whose + /// reference field `reference` names it, as a star from their middle to each. In a diagram nets + /// join vertex ports instead. + #[must_use] + pub fn joins(mut self, table: impl Into, reference: impl Into) -> Edges { + self.joins = Some((table.into(), reference.into())); + self + } + + /// Draws each row as a pole: a stroke from the row's own vertex, as the vertex mark drawing the + /// table places it, down to the ground beneath it, on a plane or the earth. Dashes, comets, picks, + /// and labels run along it as along any edge. + #[must_use] + pub fn poles(mut self) -> Edges { + self.poles = true; + self + } + + /// A path field of points each row runs through between its ends. + #[must_use] + pub fn bends(mut self, field: impl Into) -> Edges { + self.bends = Some(field.into()); + self + } + + /// How each row runs between its ends; on the earth geodesic, elsewhere straight, unless set. + #[must_use] + pub fn route(mut self, route: Route) -> Edges { + self.route = Some(route); + self + } + + /// Whether each row ends in an arrowhead at its second end; a net's at each input it reaches. + #[must_use] + pub fn arrows(mut self, on: bool) -> Edges { + self.arrows = on; + self + } + + /// The reference fields naming each row's two vertices. + #[must_use] + pub fn ends(mut self, from: impl Into, to: impl Into) -> Edges { + self.ends = Some((from.into(), to.into())); + self + } + + pub(crate) fn compile(&self, c: &mut Compiler<'_>, context: Context<'_>) -> Result { + if self.joins.is_some() { + if self.ends.is_some() || self.bends.is_some() || self.poles { + return Err(Error::invalid("a net joins its members: it has no ends, bends, or poles").at("joins")); + } + } else if self.poles { + if self.ends.is_some() || self.bends.is_some() { + return Err( + Error::invalid("a pole stands on its own row's vertex: it has no ends or bends").at("poles") + ); + } + // Both ends are the row's own vertex, which lights as its pole does. + c.own_end(&self.style.table, wgsl::EDGE_FROM)?; + c.own_end(&self.style.table, wgsl::EDGE_TO)?; + } else if let Some((from, to)) = &self.ends { + c.end(from, wgsl::EDGE_FROM).map_err(|e| e.at("ends"))?; + c.end(to, wgsl::EDGE_TO).map_err(|e| e.at("ends"))?; + } else if self.bends.is_some() { + return Err(Error::invalid("bends run between ends; name them").at("bends")); + } + if let Some(bends) = &self.bends + && !matches!(c.kind(bends), Some(Kind::Path)) + { + return Err(Error::invalid("not a path field").at(bends).at("bends")); + } + let mut flags = if self.arrows { wgsl::ARROWS } else { 0 }; + let color = Store::Color { word: wgsl::EDGE_COLOR, fallback: wgsl::THEME_EDGE }; + match (&self.style.color, context.theme.edge) { + (Some(expr), _) => c.channel("color", expr, color)?, + (None, Some(_)) => c.theme("color", wgsl::THEME_EDGE, color)?, + // A diagram's wires, and nets without ends to blend, take the text color. + (None, None) if context.diagram() || self.ends.is_none() => { + c.theme( + "color", + wgsl::THEME_TEXT, + Store::Color { word: wgsl::EDGE_COLOR, fallback: wgsl::THEME_TEXT }, + )?; + } + (None, None) => flags |= wgsl::ENDS_COLOR, + } + c.channel("visible", &self.style.visible, Store::Flag { word: wgsl::EDGE_FLAGS, bit: wgsl::VISIBLE })?; + let words = StrokeWords { + width: wgsl::EDGE_WIDTH, + flow: wgsl::EDGE_FLOW, + flags: wgsl::EDGE_FLAGS, + theme_width: wgsl::THEME_EDGE_WIDTH, + }; + self.stroke.compile(c, &words, context.diagram())?; + let mut drawing = Drawing::new(MarkKind::Edges, wgsl::EDGE_WORDS); + drawing.size_px = self.stroke.px(); + drawing.flags = flags; + if self.poles { + drawing.path = wgsl::PATH_POLES; + } else if self.joins.is_some() { + // Each net's star runs along the path the view works out from its members. + drawing.path = wgsl::PATH_GEOMETRY; + drawing.geometry = c.derived_path("route"); + } else if context.diagram() { + // Every wire runs along the path its sheet worked out. + drawing.path = wgsl::PATH_GEOMETRY; + drawing.geometry = c.derived_path("route"); + } else { + drawing.geometry = self.bends.as_ref().map_or(wgsl::NONE, |bends| c.path(bends)); + drawing.lane = c.derived_number("lane"); + } + Ok(drawing) + } +} + +style_methods!(Edges); +stroke_methods!(Edges); diff --git a/crates/latkit/src/scene/faces.rs b/crates/latkit/src/scene/faces.rs new file mode 100644 index 00000000..f29f4008 --- /dev/null +++ b/crates/latkit/src/scene/faces.rs @@ -0,0 +1,56 @@ +use super::mark::{Drawing, MarkKind, Style, mark, style_methods}; +use crate::expr::compile::{Compiler, Store}; +use crate::gpu::shaders as wgsl; +use crate::{Error, Name, Result}; + +mark!( +/// Rows drawn as triangles between the vertices three reference fields name: meshes, surfaces, and +/// fields interpolated across a network. Faces are lit from the camera, so a flat mesh seen from +/// above shows its exact colors. +/// +/// ``` +/// # use latkit::Faces; +/// let surface = Faces::of("mesh", "Face").corners("a", "b", "c"); +/// ``` +Faces { + /// The reference fields naming each row's three vertices. Without a color, a face blends the + /// colors of its corners. + corners: Option<[Name; 3]> as "[a: string, b: string, c: string]", +}); + +impl Faces { + /// Draws the rows of `table` in dataset `data`. + pub fn of(data: impl Into, table: impl Into) -> Faces { + Faces { style: Style::new(data.into(), table.into()), corners: None } + } + + /// The reference fields naming each row's three vertices. Without a color, a face blends the + /// colors of its corners. + #[must_use] + pub fn corners(mut self, a: impl Into, b: impl Into, c: impl Into) -> Faces { + self.corners = Some([a.into(), b.into(), c.into()]); + self + } + + pub(crate) fn compile(&self, c: &mut Compiler<'_>) -> Result { + let Some(corners) = &self.corners else { + return Err(Error::invalid("name the reference fields of each row's three corners").at("corners")); + }; + for (corner, word) in corners.iter().zip([wgsl::FACE_A, wgsl::FACE_B, wgsl::FACE_C]) { + c.end(corner, word).map_err(|e| e.at("corners"))?; + } + let mut flags = 0; + match &self.style.color { + Some(expr) => { + c.channel("color", expr, Store::Color { word: wgsl::FACE_COLOR, fallback: wgsl::THEME_VERTEX })?; + } + None => flags |= wgsl::ENDS_COLOR, + } + c.channel("visible", &self.style.visible, Store::Flag { word: wgsl::FACE_FLAGS, bit: wgsl::VISIBLE })?; + let mut drawing = Drawing::new(MarkKind::Faces, wgsl::FACE_WORDS); + drawing.flags = flags; + Ok(drawing) + } +} + +style_methods!(Faces); diff --git a/crates/latkit/src/scene/form.rs b/crates/latkit/src/scene/form.rs new file mode 100644 index 00000000..2817f120 --- /dev/null +++ b/crates/latkit/src/scene/form.rs @@ -0,0 +1,72 @@ +//! What scenes read as JSON. Each type deserializes as itself and its schema is derived from it; a +//! type a name can stand for also reads one of its presets' names, such as `"inspect"`, `"globe"`, or +//! `"stress"`. + +use std::fmt; +use std::marker::PhantomData; +use std::time::Duration; + +use schemars::{Schema, json_schema}; +use serde::Deserialize; +use serde::de::value::MapAccessDeserializer; +use serde::de::{self, Deserializer, MapAccess, Visitor}; +use serde_json::Value; + +/// A type a name can stand for. +pub(crate) trait Presets: Sized { + /// The names, as the schema lists them. + const NAMES: &'static [&'static str]; + + /// The value `name` stands for. + fn preset(name: &str) -> Option; + + /// The value its options, written out, make: what its derive reads. + fn options<'de, D: Deserializer<'de>>(deserializer: D) -> Result; +} + +/// `T` read from one of its presets' names, or from its options, read where they are written so an +/// error names the path to the option it could not read. +pub(crate) fn preset_or<'de, D: Deserializer<'de>, T: Presets>(deserializer: D) -> Result { + struct Named(PhantomData); + + impl<'de, T: Presets> Visitor<'de> for Named { + type Value = T; + + fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "one of {}, or options", T::NAMES.join(", ")) + } + + fn visit_str(self, name: &str) -> Result { + T::preset(name) + .ok_or_else(|| E::custom(format!("unknown name {name:?}, expected one of {}", T::NAMES.join(", ")))) + } + + fn visit_map>(self, map: A) -> Result { + T::options(MapAccessDeserializer::new(map)) + } + } + + deserializer.deserialize_any(Named(PhantomData)) +} + +/// `T`'s schema as one of its presets' names or what it derived, its description kept on the whole. +pub(crate) fn presets(schema: &mut Schema) { + let mut derived = std::mem::replace(schema, json_schema!({})); + let description = derived.remove("description"); + // A variant without options that a preset names already is the preset. + for key in ["oneOf", "anyOf"] { + if let Some(variants) = derived.get_mut(key).and_then(Value::as_array_mut) { + variants.retain(|v| !v.get("const").and_then(Value::as_str).is_some_and(|name| T::NAMES.contains(&name))); + } + } + *schema = json_schema!({ "anyOf": [{ "type": "string", "enum": T::NAMES }, derived] }); + if let Some(description) = description { + schema.insert("description".into(), description); + } +} + +/// A duration read as seconds. +pub(crate) fn seconds<'de, D: Deserializer<'de>>(deserializer: D) -> Result { + let seconds = f64::deserialize(deserializer)?; + Duration::try_from_secs_f64(seconds).map_err(|_| de::Error::custom("seconds from 0, within range")) +} diff --git a/crates/latkit/src/scene/label.rs b/crates/latkit/src/scene/label.rs new file mode 100644 index 00000000..5883e387 --- /dev/null +++ b/crates/latkit/src/scene/label.rs @@ -0,0 +1,112 @@ +use std::sync::Arc; + +use schemars::JsonSchema; +use serde::Deserialize; +use serde::de::{self, Deserializer}; +use serde_json::Value; + +use crate::Expr; + +/// A row's text, placed beside, inside, or along what its mark draws, following it every frame: a +/// text field, or options. Labels that would overlap give way by priority; among equals, those +/// already shown keep their place. In a diagram a label is part of the drawing: it scales with the +/// zoom, fades out once too small to read, and shows wherever it fits its vertex. +/// +/// ``` +/// # use latkit::{field, Label, Vertices}; +/// let buses = Vertices::of("grid", "Bus").position("lon", "lat").label(Label::new("name").priority(field("kv"))); +/// ``` +#[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema)] +#[serde(remote = "Self", rename_all = "camelCase", deny_unknown_fields)] +#[schemars(transform = text_or_options)] +pub struct Label { + /// A text field. + pub(crate) text: Expr, + /// CSS pixels, or units in a diagram; the theme's font size unless set. + #[serde(default)] + pub(crate) size: Option, + /// Each row's text color; the theme's text color unless set. + #[serde(default)] + pub(crate) color: Option, + /// Where labels would overlap, the higher shows; the mark's priority unless set. + #[serde(default)] + pub(crate) priority: Option, + /// How far a line runs before it wraps: CSS pixels, or units in a diagram. + #[serde(default)] + pub(crate) max_width: Option, + /// The CSS font family list its texts are set in; the theme's font unless set. + #[serde(default)] + pub(crate) font: Option>, + /// The most labels shown at once, those of highest priority among the rows in view; where they + /// would overlap, fewer. + #[serde(default)] + pub(crate) max: Option, +} + +/// A label reads a text field as its text alone, or an object with `text` as its options. +impl<'de> Deserialize<'de> for Label { + fn deserialize>(deserializer: D) -> Result { + let value = Value::deserialize(deserializer)?; + if value.as_object().is_some_and(|map| map.contains_key("text")) { + return Label::deserialize(value).map_err(de::Error::custom); + } + Expr::from_value(value).map(Label::new).map_err(de::Error::custom) + } +} + +/// A label's schema: a text field, or its options. +fn text_or_options(schema: &mut schemars::Schema) { + let options = std::mem::replace(schema, schemars::json_schema!({})); + *schema = schemars::json_schema!({ "anyOf": [{ "$ref": "#/$defs/Expr" }, options] }); +} + +impl Label { + /// Labels each row with a text field's value. + pub fn new(text: impl Into) -> Label { + Label { text: text.into(), size: None, color: None, priority: None, max_width: None, font: None, max: None } + } + + /// Text size, CSS pixels, or units in a diagram; the theme's font size unless set. + #[must_use] + pub fn size(mut self, size: f32) -> Label { + self.size = Some(size); + self + } + + /// Each row's text color; the theme's text color unless set. + #[must_use] + pub fn color(mut self, color: impl Into) -> Label { + self.color = Some(color.into()); + self + } + + /// Each row's priority: where labels would overlap, the higher shows. The mark's priority + /// unless set. + #[must_use] + pub fn priority(mut self, priority: impl Into) -> Label { + self.priority = Some(priority.into()); + self + } + + /// How far a line of text runs before it wraps: CSS pixels, or units in a diagram. + #[must_use] + pub fn max_width(mut self, width: f32) -> Label { + self.max_width = Some(width); + self + } + + /// The CSS font family list its texts are set in; the theme's font unless set. + #[must_use] + pub fn font(mut self, font: impl Into>) -> Label { + self.font = Some(font.into()); + self + } + + /// Shows at most `max` labels at once, those of highest priority among the rows in view; where + /// they would overlap, fewer. + #[must_use] + pub fn max(mut self, max: u32) -> Label { + self.max = Some(max); + self + } +} diff --git a/crates/latkit/src/scene/layout.rs b/crates/latkit/src/scene/layout.rs new file mode 100644 index 00000000..00010459 --- /dev/null +++ b/crates/latkit/src/scene/layout.rs @@ -0,0 +1,131 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Deserializer}; + +use super::form::{Presets, preset_or, presets}; + +/// How the view places vertex rows without positions: a diagram's blocks, sized, or the points of a +/// plane or the earth, among the rows linked to them, gaps in the space's units: a name, or `{ stress +/// | layered: options }`. A place, once given, holds: rows added later are placed around the rest, +/// and [`View::arrange`](crate::View::arrange) lays every row out again. +#[derive(Clone, Copy, PartialEq, Debug, Default, Deserialize, JsonSchema)] +#[serde(remote = "Self", rename_all = "camelCase", deny_unknown_fields)] +#[schemars(transform = presets::)] +pub enum Layout { + /// Unplaced vertices are not drawn. + #[default] + None, + /// Distances on the drawing follow distances in the graph. + Stress(Stress), + /// Ranks along a direction, for flows and hierarchies. + Layered(Layered), +} + +impl Presets for Layout { + const NAMES: &'static [&'static str] = &["none", "stress", "layered"]; + + fn preset(name: &str) -> Option { + match name { + "none" => Some(Layout::None), + "stress" => Some(Layout::Stress(Stress::default())), + "layered" => Some(Layout::Layered(Layered::default())), + _ => None, + } + } + + fn options<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result { + Layout::deserialize(deserializer) + } +} + +impl<'de> Deserialize<'de> for Layout { + fn deserialize>(deserializer: D) -> Result { + preset_or(deserializer) + } +} + +/// Stress majorization: each pair of vertices pulls toward its graph distance; then their boxes +/// part, keeping a quarter of the gap clear. +#[derive(Clone, Copy, PartialEq, Debug, Deserialize, JsonSchema)] +#[serde(default, rename_all = "camelCase", deny_unknown_fields)] +pub struct Stress { + /// Units between adjacent vertices' centers. + #[schemars(range(min = 0))] + pub gap: f64, +} + +impl Default for Stress { + fn default() -> Stress { + Stress { gap: 40.0 } + } +} + +/// Layered drawing: vertices in ranks, edges pointing along `flow`, and nets from their outputs. +#[derive(Clone, Copy, PartialEq, Debug, Deserialize, JsonSchema)] +#[serde(default, rename_all = "camelCase", deny_unknown_fields)] +pub struct Layered { + /// Where edges point. + pub flow: Direction, + /// Units between vertices of a rank. + pub gap: f64, + /// Units between ranks. + pub rank_gap: f64, +} + +impl Default for Layered { + fn default() -> Layered { + Layered { flow: Direction::Right, gap: 30.0, rank_gap: 80.0 } + } +} + +/// How an edge runs between its ends. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Deserialize, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub enum Route { + /// Straight across the screen. + Straight, + /// Along the great circle, on the earth. + Geodesic, + /// In horizontal and vertical runs around vertices, leaving and entering at their sides, bends + /// rounded. Diagrams only. + Orthogonal, +} + +/// How a line runs between its samples. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Deserialize, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub enum Interpolation { + /// Straight from each sample to the next. + #[default] + Linear, + /// Each value holds from the sample before it: steps rise at their samples' ends. + StepBefore, + /// Each value holds until the next sample: steps rise at the next sample. + StepAfter, +} + +/// A direction on screen. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Deserialize, JsonSchema)] +#[serde(rename_all = "camelCase")] +pub enum Direction { + /// Toward the right. + #[default] + Right, + /// Toward the left. + Left, + /// Toward the bottom. + Down, + /// Toward the top. + Up, +} + +impl From for Layout { + fn from(stress: Stress) -> Layout { + Layout::Stress(stress) + } +} + +impl From for Layout { + fn from(layered: Layered) -> Layout { + Layout::Layered(layered) + } +} diff --git a/crates/latkit/src/scene/lines.rs b/crates/latkit/src/scene/lines.rs new file mode 100644 index 00000000..8cfe55d6 --- /dev/null +++ b/crates/latkit/src/scene/lines.rs @@ -0,0 +1,133 @@ +use super::Interpolation; +use super::mark::{ + Context, Drawing, GEOMETRY, MarkKind, Stroke, StrokeWords, Style, mark, stroke_methods, style_methods, +}; +use crate::expr::compile::{Compiler, Store}; +use crate::gpu::shaders as wgsl; +use crate::{Error, Kind, Name, Result, Space}; + +mark!( +/// Rows drawn as lines: along a path field (roads, rivers, borders) or a polygon field's rings, +/// outlining its areas; on a plot, through a sampled field's history across the data's axis, what a +/// monitor shows. On the earth paths bend with the globe and stay whole across the antimeridian. +/// +/// ``` +/// # use latkit::Lines; +/// let roads = Lines::of("city", "roads").width(2.0); +/// let height = Lines::of("body", "Body").trace("height"); +/// ``` +Lines + stroke { + /// The path or polygon field each row runs along; `geometry` unless set. Not on a plot. + geometry: Option, + /// The sampled field each row traces across the data's axis, on a plot alone. A field not recorded + /// yet draws nothing until its first frame. + trace: Option, + /// How each row runs between its samples, on a plot. + interpolation: Interpolation, +}); + +impl Lines { + /// Draws the rows of `table` in dataset `data`. + pub fn of(data: impl Into, table: impl Into) -> Lines { + Lines { + style: Style::new(data.into(), table.into()), + stroke: Stroke::default(), + geometry: None, + trace: None, + interpolation: Interpolation::Linear, + } + } + + /// The path or polygon field each row runs along; the field `geometry` unless set. Not on a plot. + #[must_use] + pub fn geometry(mut self, field: impl Into) -> Lines { + self.geometry = Some(field.into()); + self + } + + /// The sampled field each row traces across the data's axis, on a plot. Unless named, the mark + /// takes the field's name. + #[must_use] + pub fn trace(mut self, field: impl Into) -> Lines { + self.trace = Some(field.into()); + self + } + + /// How each row runs between its samples, on a plot. + #[must_use] + pub fn interpolation(mut self, interpolation: Interpolation) -> Lines { + self.interpolation = interpolation; + self + } + + /// The field each row draws from: the sampled field it traces, else its path field. + pub(crate) fn traced(&self) -> Name { + self.trace.clone().or_else(|| self.geometry.clone()).unwrap_or_else(|| GEOMETRY.into()) + } + + pub(crate) fn compile(&self, c: &mut Compiler<'_>, context: Context<'_>) -> Result { + let mut drawing = Drawing::new(MarkKind::Lines, wgsl::LINE_WORDS); + drawing.size_px = self.stroke.px(); + if matches!(context.space, Space::Plot(_)) { + if self.geometry.is_some() { + return Err(Error::invalid("a plot traces sampled fields; name one with trace").at("geometry")); + } + let Some(field) = &self.trace else { + return Err(Error::invalid("name the sampled field each row traces").at("trace")); + }; + drawing.trace = match c.kind(field) { + // Streamed data appends its first frame later; the mark compiles again then. + None => wgsl::NONE, + _ => c.trace(field).map_err(|e| e.at("trace"))?, + }; + drawing.flags = match self.interpolation { + Interpolation::Linear => 0, + Interpolation::StepBefore => wgsl::STEP_BEFORE, + Interpolation::StepAfter => wgsl::STEP_AFTER, + }; + } else { + if self.trace.is_some() { + return Err(Error::invalid("only a plot traces a sampled field; name a path with geometry").at("trace")); + } + let field = self.geometry.clone().unwrap_or_else(|| GEOMETRY.into()); + match c.kind(&field) { + Some(Kind::Path | Kind::Parts | Kind::Polygons) => {} + Some(_) => return Err(Error::invalid("not a path or polygon field").at(&field).at("geometry")), + None if self.geometry.is_some() => { + return Err(Error::invalid("no such field").at(&field).at("geometry")); + } + None => return Err(Error::invalid("name the path field each row runs along").at("geometry")), + } + drawing.path = wgsl::PATH_GEOMETRY; + // On the earth a line runs along its path as it bends with the globe. + drawing.geometry = if matches!(context.space, Space::Earth(_)) { + c.derived_path(&path_of(&field)) + } else { + c.path(&field) + }; + } + let color = Store::Color { word: wgsl::LINE_COLOR, fallback: wgsl::THEME_LINE }; + match &self.style.color { + Some(expr) => c.channel("color", expr, color)?, + None => c.theme("color", wgsl::THEME_LINE, color)?, + } + c.channel("visible", &self.style.visible, Store::Flag { word: wgsl::LINE_FLAGS, bit: wgsl::VISIBLE })?; + let words = StrokeWords { + width: wgsl::LINE_WIDTH, + flow: wgsl::LINE_FLOW, + flags: wgsl::LINE_FLAGS, + theme_width: wgsl::THEME_LINE_WIDTH, + }; + self.stroke.compile(c, &words, context.diagram())?; + Ok(drawing) + } +} + +/// The derived field holding path field `field` as an earth line draws it: unwrapped across the +/// antimeridian, with a point every few degrees along longer segments. +pub(crate) fn path_of(field: &str) -> Name { + format!("{field}.path").into() +} + +style_methods!(Lines); +stroke_methods!(Lines); diff --git a/crates/latkit/src/scene/mark.rs b/crates/latkit/src/scene/mark.rs new file mode 100644 index 00000000..8671f202 --- /dev/null +++ b/crates/latkit/src/scene/mark.rs @@ -0,0 +1,792 @@ +use std::sync::Arc; + +use super::{Areas, Edges, Faces, Label, Lines, Vertices}; +use crate::expr::compile::{Compiler, Store}; +use crate::gpu::shaders as wgsl; +use crate::{Error, Expr, Name, Result, Size, Space}; + +/// One drawn table of a scene: `{ vertices | edges | faces | lines | areas: options }` as JSON. +#[derive(Clone, PartialEq, Debug, serde::Deserialize, schemars::JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[non_exhaustive] +pub enum Mark { + /// Rows drawn as markers. + Vertices(Vertices), + /// Rows drawn as strokes between two vertices. + Edges(Edges), + /// Rows drawn as triangles between three vertices. + Faces(Faces), + /// Rows drawn as lines along their paths, or on a plot through their samples. + Lines(Lines), + /// Rows drawn as the areas their polygons cover. + Areas(Areas), +} + +impl From for Mark { + fn from(mark: Vertices) -> Mark { + Mark::Vertices(mark) + } +} + +impl From for Mark { + fn from(mark: Edges) -> Mark { + Mark::Edges(mark) + } +} + +impl From for Mark { + fn from(mark: Faces) -> Mark { + Mark::Faces(mark) + } +} + +impl From for Mark { + fn from(mark: Lines) -> Mark { + Mark::Lines(mark) + } +} + +impl From for Mark { + fn from(mark: Areas) -> Mark { + Mark::Areas(mark) + } +} + +/// The field a mark reads its shape from unless told otherwise: what geography's tables hold. +pub(crate) const GEOMETRY: &str = "geometry"; + +/// Options every mark has. +#[derive(Clone, PartialEq, Debug)] +pub(crate) struct Style { + pub(crate) data: Name, + pub(crate) table: Name, + pub(crate) color: Option, + pub(crate) visible: Expr, + /// Each row's priority, read from its data alone. + pub(crate) priority: Option, + pub(crate) name: Option, + pub(crate) interaction: Interaction, + pub(crate) label: Option