From bd9209ebb70d6dd8716c162b2ab5358e1fb9ede2 Mon Sep 17 00:00:00 2001 From: boris Date: Tue, 2 Jun 2026 12:27:54 +0200 Subject: [PATCH] Docker Image and first iteration --- .dockerignore | 10 + .env.example | 4 + .gitignore | 9 + AGENTS.md | 94 + Dockerfile | 33 + README.md | 35 + SECURITY.md | 104 + compose.yaml | 24 + frontend/package-lock.json | 2383 ++++ frontend/package.json | 29 + frontend/src/PortfolioMap.test.tsx | 68 + frontend/src/PortfolioMap.tsx | 205 + frontend/src/main.tsx | 11 + frontend/src/styles.css | 297 + frontend/src/types.ts | 23 + frontend/src/vite-env.d.ts | 2 + frontend/tsconfig.json | 20 + frontend/vite.config.ts | 27 + manage.py | 15 + portfolio/__init__.py | 1 + portfolio/asgi.py | 8 + portfolio/settings.py | 79 + portfolio/urls.py | 7 + portfolio/wsgi.py | 8 + requirements.txt | 3 + showcase/__init__.py | 1 + showcase/admin.py | 19 + showcase/apps.py | 7 + showcase/migrations/0001_initial.py | 57 + showcase/migrations/0002_seed_regions.py | 37 + showcase/migrations/__init__.py | 1 + showcase/migrations/regions.json | 1034 ++ showcase/models.py | 49 + .../static/showcase/maps/countries.topo.json | 11736 ++++++++++++++++ .../showcase/maps/subdivisions.topo.json | 10057 +++++++++++++ showcase/templates/showcase/home.html | 26 + showcase/tests/__init__.py | 1 + showcase/tests/test_views.py | 59 + showcase/urls.py | 9 + showcase/views.py | 51 + 40 files changed, 26643 insertions(+) create mode 100644 .dockerignore create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 compose.yaml create mode 100644 frontend/package-lock.json create mode 100644 frontend/package.json create mode 100644 frontend/src/PortfolioMap.test.tsx create mode 100644 frontend/src/PortfolioMap.tsx create mode 100644 frontend/src/main.tsx create mode 100644 frontend/src/styles.css create mode 100644 frontend/src/types.ts create mode 100644 frontend/src/vite-env.d.ts create mode 100644 frontend/tsconfig.json create mode 100644 frontend/vite.config.ts create mode 100755 manage.py create mode 100644 portfolio/__init__.py create mode 100644 portfolio/asgi.py create mode 100644 portfolio/settings.py create mode 100644 portfolio/urls.py create mode 100644 portfolio/wsgi.py create mode 100644 requirements.txt create mode 100644 showcase/__init__.py create mode 100644 showcase/admin.py create mode 100644 showcase/apps.py create mode 100644 showcase/migrations/0001_initial.py create mode 100644 showcase/migrations/0002_seed_regions.py create mode 100644 showcase/migrations/__init__.py create mode 100644 showcase/migrations/regions.json create mode 100644 showcase/models.py create mode 100644 showcase/static/showcase/maps/countries.topo.json create mode 100644 showcase/static/showcase/maps/subdivisions.topo.json create mode 100644 showcase/templates/showcase/home.html create mode 100644 showcase/tests/__init__.py create mode 100644 showcase/tests/test_views.py create mode 100644 showcase/urls.py create mode 100644 showcase/views.py diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ebdec6f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +.git +.env +.venv +__pycache__ +*.py[cod] +*.sqlite3 +.pytest_cache +.ruff_cache +frontend/node_modules +showcase/static/showcase/dist diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..99c4a3e --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +DJANGO_SECRET_KEY=django-insecure-local-development-only-change-me +DJANGO_DEBUG=1 +DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1 + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d76e746 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.env +.venv/ +__pycache__/ +*.py[cod] +*.sqlite3 +.pytest_cache/ +.ruff_cache/ +frontend/node_modules/ +showcase/static/showcase/dist/ diff --git a/AGENTS.md b/AGENTS.md index e69de29..e56d4a1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -0,0 +1,94 @@ +# AGENTS.md + +## Project Overview + +This repository is a foundational Dockerized Django portfolio website. Local +development currently uses SQLite and a single Docker Compose `web` service. +Do not assume a frontend stack, deployment platform, or CI provider unless the +repository explicitly defines one. + +## Working Principles + +- Prefer small, reviewable changes with a clear purpose. +- Inspect the repository before making changes. Follow existing patterns once + they exist instead of introducing parallel conventions. +- Keep local development Docker-first. Add and document Docker Compose commands + when the Compose configuration is introduced. +- Do not hard-code credentials, secret keys, hostnames, or environment-specific + configuration. +- Update `README.md`, this file, and `SECURITY.md` when implementation changes + make their instructions inaccurate. + +## Django Conventions + +- Keep environment-specific settings outside committed source code. Load + sensitive values from environment variables or a deployment secret store. +- Organize Django apps by domain responsibility. Avoid creating apps solely to + mirror technical layers. +- Use Django migrations for schema changes. Commit generated migration files + with the code that requires them. +- Review migrations before committing them. Avoid destructive schema changes + without an explicit data migration or rollout plan. +- Keep views, forms, serializers, templates, and models focused. Extract shared + behavior only when there is a concrete reuse case. +- Use Django's built-in security protections unless there is a documented + reason to override them. + +## Docker Workflow + +Docker Compose is the preferred local interface: + +```sh +docker compose up --build -d +docker compose exec web python manage.py check +docker compose exec web python manage.py migrate +docker compose exec web python manage.py test +docker compose run --rm frontend npm run test +docker compose run --rm frontend npm run build +docker compose down +``` + +Keep containers reproducible: + +- Pin runtime versions and dependency versions using the chosen package + manager's lock mechanism. +- Run application processes as a non-root user where practical. +- Do not bake secrets or local environment files into images. +- Add a `.dockerignore` when Docker files are introduced. +- Use a `.env.example` to record environment variables, and do not touch the production `.env`. +- The Web Container should be entirely self contained, without splitting the functionality into multiple containers. It should include both backend, frontend, integrated database, webserver, etc. + +## Frontend Conventions + +- Keep Django responsible for page rendering and use React only for focused + interactive islands unless the architecture is intentionally changed. +- Build frontend assets with the one-shot Docker Compose `frontend` service. +- Keep npm dependencies pinned and commit `frontend/package-lock.json`. +- Keep generated frontend bundles out of version control. The Docker image + builds its own production bundle. +- Treat committed TopoJSON map files as generated assets derived from Natural + Earth data. Regenerate them deliberately rather than editing them by hand. + +## Validation + +Before considering a change complete, run the checks supported by the current +repository. Once available, this should include: + +- Django system checks. +- The automated test suite. +- Migration consistency checks. +- Formatting, linting, and type checks selected by the project. +- A Docker image build and a basic container startup check for infrastructure + changes. + +If a check is not yet configured or cannot be run, state that clearly in the +change summary. Do not invent placeholder commands that appear executable. + +## Change Hygiene + +- Never commit `.env` files, secret values, local databases, uploaded media, + caches, or generated build output. +- Add tests for behavior changes and regression fixes once the test harness + exists. +- Keep documentation aligned with actual repository behavior. +- Avoid unrelated refactors in focused feature or bug-fix changes. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..89a5a29 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,33 @@ +FROM node:24-bookworm-slim AS frontend-deps + +WORKDIR /app/frontend + +COPY frontend/package*.json ./ +RUN npm ci + +FROM frontend-deps AS frontend-builder + +COPY frontend ./ +RUN npm run build + +FROM python:3.12-slim-bookworm + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 + +WORKDIR /app + +RUN addgroup --system django \ + && adduser --system --ingroup django django + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY --chown=django:django . . +COPY --from=frontend-builder --chown=django:django /app/showcase/static/showcase/dist ./showcase/static/showcase/dist + +USER django + +EXPOSE 8000 + +CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] diff --git a/README.md b/README.md index e69de29..1ff9660 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,35 @@ +# Portfolio + +Foundational Dockerized Django project for a portfolio website. + +## Start + +```sh +docker compose run --rm frontend npm run build +docker compose up --build -d +docker compose exec web python manage.py migrate +``` + +The development server is available at . Portfolio +entries and their map regions can be managed at . + +## Common Commands + +```sh +docker compose exec web python manage.py check +docker compose exec web python manage.py migrate +docker compose exec web python manage.py test +docker compose run --rm frontend npm run test +docker compose run --rm frontend npm run build +docker compose down +``` + +`.env.example` contains local-only development defaults. Create a separate +untracked `.env` and update `compose.yaml` before using environment-specific +values outside local development. + +## Map Data + +The React map island uses committed, optimized TopoJSON assets derived from +public-domain [Natural Earth](https://www.naturalearthdata.com/) Admin-0 and +Admin-1 data. The browser does not request a map provider or API key. diff --git a/SECURITY.md b/SECURITY.md index e69de29..4fef393 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -0,0 +1,104 @@ +# Security Policy + +## Reporting a Vulnerability + +Please report suspected vulnerabilities privately. Do not open a public issue +for an unpatched security problem. + +Send a concise report to **`security@ntbx.io`**. + +Include the affected area, reproduction steps, potential impact, and any +suggested mitigation. Avoid including secrets or personal data unless they are +required to explain the issue. No response-time or remediation-time guarantee +is currently offered. + +## Supported Versions + +This project is an initial scaffold and has no released or supported versions +yet. Define the supported release policy here before the first public +deployment. + +## Engineering Security Baseline + +The following requirements apply as the Dockerized Django application is +built. They are implementation guardrails, not claims that the corresponding +components already exist. + +### Django Settings + +- Read `SECRET_KEY`, database credentials, allowed hosts, and other + environment-specific values from environment variables or a deployment + secret store. +- Keep debug mode disabled outside local development. +- Configure allowed hosts and trusted CSRF origins explicitly for each deployed + environment. +- Enable secure cookie, HTTPS redirect, HSTS, and proxy SSL settings as + appropriate for the production hosting topology. +- Preserve Django's CSRF, escaping, password validation, and clickjacking + protections unless an exception is documented and reviewed. + +### Containers + +- Pin base image versions and rebuild images regularly for security updates. +- Run the application as a non-root user where practical. +- Keep images minimal and exclude source-control metadata, local environment + files, caches, and development-only artifacts with `.dockerignore`. +- Do not publish database or internal service ports unless a documented + environment requires it. +- Keep development conveniences separate from production configuration. + +### Secrets and Dependencies + +- Never commit secrets, API keys, private keys, production credentials, or + populated `.env` files. +- Use separate credentials for local development, tests, staging, and + production. +- Pin application dependencies with the selected package manager's lock or + constraints mechanism. +- Review dependency updates and use automated vulnerability scanning when CI is + introduced. +- Rotate any credential immediately if it is exposed, including exposure in + version-control history. + +### Authentication and Authorization + +- Prefer Django's built-in authentication and password hashing facilities. +- Protect administrative routes with strong credentials and restrict access + further at the network or identity layer where the deployment supports it. +- Enforce authorization checks server-side for every protected action. Do not + rely on hidden UI controls. +- Add rate limiting or equivalent abuse protection for authentication and + public write endpoints when those endpoints are introduced. + +### Uploads and User-Controlled Content + +- Treat filenames, metadata, form fields, URL parameters, and uploaded files as + untrusted input. +- Validate upload size and content type, generate storage-safe filenames, and + keep uploaded files outside executable application paths. +- Do not render user-controlled HTML as safe unless it has been sanitized by an + explicitly selected and tested mechanism. +- Store and serve media according to the chosen deployment platform's security + model. + +### Database and Logging + +- Use least-privilege database credentials and avoid exposing the database + directly to the public internet. +- Back up production data and test the restore procedure once a production + database exists. +- Do not log passwords, secret values, authentication tokens, or unnecessary + personal data. +- Record security-relevant failures with enough context to investigate them + without leaking sensitive information. + +### Production Deployment + +- Serve the application over HTTPS. +- Keep production debug tooling disabled. +- Apply migrations deliberately during deployment and maintain a rollback or + recovery plan for risky changes. +- Monitor application errors, suspicious authentication activity, and + dependency vulnerabilities once operational tooling is selected. +- Document the deployment-specific security configuration before the first + public release. diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..153b324 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,24 @@ +services: + frontend: + profiles: + - tools + build: + context: . + target: frontend-deps + working_dir: /app/frontend + volumes: + - ./frontend:/app/frontend + - frontend_node_modules:/app/frontend/node_modules + - ./showcase/static/showcase/dist:/app/showcase/static/showcase/dist + + web: + build: . + env_file: + - .env.example + volumes: + - .:/app + ports: + - "8000:8000" + +volumes: + frontend_node_modules: diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000..bfb5854 --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,2383 @@ +{ + "name": "xav-portfolio-map", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "xav-portfolio-map", + "version": "0.1.0", + "dependencies": { + "react": "18.3.1", + "react-dom": "18.3.1", + "react-simple-maps": "3.0.0" + }, + "devDependencies": { + "@testing-library/react": "16.3.2", + "@types/react": "18.3.30", + "@types/react-dom": "18.3.7", + "@types/react-simple-maps": "3.0.6", + "@vitejs/plugin-react": "6.0.2", + "jsdom": "29.1.1", + "typescript": "6.0.3", + "vite": "8.0.16", + "vitest": "4.1.8" + } + }, + "node_modules/@asamuzakjp/css-color": { + "version": "5.1.11", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz", + "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/generational-cache": "^1.0.1", + "@csstools/css-calc": "^3.2.0", + "@csstools/css-color-parser": "^4.1.0", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz", + "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/generational-cache": "^1.0.1", + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.2.1", + "is-potential-custom-element-name": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/generational-cache": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz", + "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bramus/specificity": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz", + "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "^3.0.0" + }, + "bin": { + "specificity": "bin/cli.js" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", + "integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@csstools/css-calc": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.2.1.tgz", + "integrity": "sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.1.1.tgz", + "integrity": "sha512-eZ5XOtyhK+mggRafYUWzA0tvaYOFgdY8AkgQiCJF9qNAePnUo/zmsqqYubBBb3sQ8uNUaSKTY9s9klfRaAXL0g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^6.0.2", + "@csstools/css-calc": "^3.2.1" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.4.tgz", + "integrity": "sha512-wgsqt92b7C7tQhIdPNxj0n9zuUbQlvAuI1exyzeNrOKOi62SD7ren8zqszmpVREjAOqg8cD2FqYhQfAuKjk4sw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@exodus/bytes": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.1.tgz", + "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.133.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", + "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz", + "integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz", + "integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz", + "integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz", + "integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz", + "integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz", + "integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz", + "integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz", + "integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz", + "integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz", + "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz", + "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz", + "integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz", + "integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz", + "integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz", + "integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/react": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", + "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/d3-color": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-2.0.6.tgz", + "integrity": "sha512-tbaFGDmJWHqnenvk3QGSvD3RVwr631BjKRD7Sc7VLRgrdX5mk5hTyoeBL6rXZaeoXzmZwIl1D2HPogEdt1rHBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-geo": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-2.0.7.tgz", + "integrity": "sha512-RIXlxPdxvX+LAZFv+t78CuYpxYag4zuw9mZc+AwfB8tZpKU90rMEn2il2ADncmeZlb7nER9dDsJpRisA3lRvjA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-interpolate": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-2.0.5.tgz", + "integrity": "sha512-UINE41RDaUMbulp+bxQMDnhOi51rh5lA2dG+dWZU0UY/IwQiG/u2x8TfnWYU9+xwGdXsJoAvrBYUEQl0r91atg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-color": "^2" + } + }, + "node_modules/@types/d3-selection": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-2.0.5.tgz", + "integrity": "sha512-71BorcY0yXl12S7lvb01JdaN9TpeUHBDb4RRhSq8U8BEkX/nIk5p7Byho+ZRTsx5nYLMpAbY3qt5EhqFzfGJlw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-zoom": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-2.0.7.tgz", + "integrity": "sha512-JWke4E8ZyrKUQ68ESTWSK16fVb0OYnaiJ+WXJRYxKLn4aXU0o4CLYxMWBEiouUfO3TTCoyroOrGPcBG6u1aAxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "^2", + "@types/d3-selection": "^2" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.30", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.30.tgz", + "integrity": "sha512-3ek6mwJL5/VBewBcY4S66cqlCtK3qi4WIq37Z0m/NHw1hjhI7274Mx1qz/+ggSzyBCOEf7eHjBN6INjPAWYfYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/react-simple-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/react-simple-maps/-/react-simple-maps-3.0.6.tgz", + "integrity": "sha512-hR01RXt6VvsE41FxDd+Bqm1PPGdKbYjCYVtCgh38YeBPt46z3SwmWPWu2L3EdCAP6bd6VYEgztucihRw1C0Klg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-geo": "^2", + "@types/d3-zoom": "^2", + "@types/geojson": "*", + "@types/react": "*" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.2.tgz", + "integrity": "sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "vite": "^8.0.0" + }, + "peerDependenciesMeta": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.8.tgz", + "integrity": "sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.8", + "@vitest/utils": "4.1.8", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.8.tgz", + "integrity": "sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.8", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.8.tgz", + "integrity": "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.8.tgz", + "integrity": "sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.8", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.8.tgz", + "integrity": "sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.8", + "@vitest/utils": "4.1.8", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.8.tgz", + "integrity": "sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.8.tgz", + "integrity": "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.8", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz", + "integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-drag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-2.0.0.tgz", + "integrity": "sha512-g9y9WbMnF5uqB9qKqwIIa/921RYWzlUDv9Jl1/yONQwxbOfszAWTCm8u7HOTgJgRDXiRZN56cHT9pd24dmXs8w==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-dispatch": "1 - 2", + "d3-selection": "2" + } + }, + "node_modules/d3-ease": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-2.0.0.tgz", + "integrity": "sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-geo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-2.0.2.tgz", + "integrity": "sha512-8pM1WGMLGFuhq9S+FpPURxic+gKzjluCD/CHTuUF3mXMeiCo0i6R0tO1s4+GArRFde96SLcW/kOFRjoAosPsFA==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "^2.5.0" + } + }, + "node_modules/d3-interpolate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz", + "integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-color": "1 - 2" + } + }, + "node_modules/d3-selection": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz", + "integrity": "sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-timer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz", + "integrity": "sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-transition": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-2.0.0.tgz", + "integrity": "sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-color": "1 - 2", + "d3-dispatch": "1 - 2", + "d3-ease": "1 - 2", + "d3-interpolate": "1 - 2", + "d3-timer": "1 - 2" + }, + "peerDependencies": { + "d3-selection": "2" + } + }, + "node_modules/d3-zoom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-2.0.0.tgz", + "integrity": "sha512-fFg7aoaEm9/jf+qfstak0IYpnesZLiMX6GZvXtUSdv8RH2o4E2qeelgdU09eKS6wGuiGMfcnMI0nTIqWzRHGpw==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-dispatch": "1 - 2", + "d3-drag": "2", + "d3-interpolate": "1 - 2", + "d3-selection": "2", + "d3-transition": "2" + } + }, + "node_modules/data-urls": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/entities": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.6.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/jsdom": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz", + "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^5.1.11", + "@asamuzakjp/dom-selector": "^7.1.1", + "@bramus/specificity": "^2.4.2", + "@csstools/css-syntax-patches-for-csstree": "^1.1.3", + "@exodus/bytes": "^1.15.0", + "css-tree": "^3.2.1", + "data-urls": "^7.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^6.0.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.3.5", + "parse5": "^8.0.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^6.0.1", + "undici": "^7.25.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^8.0.1", + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.1", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^8.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT", + "peer": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/react-simple-maps": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-simple-maps/-/react-simple-maps-3.0.0.tgz", + "integrity": "sha512-vKNFrvpPG8Vyfdjnz5Ne1N56rZlDfHXv5THNXOVZMqbX1rWZA48zQuYT03mx6PAKanqarJu/PDLgshIZAfHHqw==", + "license": "MIT", + "dependencies": { + "d3-geo": "^2.0.2", + "d3-selection": "^2.0.0", + "d3-zoom": "^2.0.0", + "topojson-client": "^3.1.0" + }, + "peerDependencies": { + "prop-types": "^15.7.2", + "react": "^16.8.0 || 17.x || 18.x", + "react-dom": "^16.8.0 || 17.x || 18.x" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rolldown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", + "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.133.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.3", + "@rolldown/binding-darwin-arm64": "1.0.3", + "@rolldown/binding-darwin-x64": "1.0.3", + "@rolldown/binding-freebsd-x64": "1.0.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", + "@rolldown/binding-linux-arm64-gnu": "1.0.3", + "@rolldown/binding-linux-arm64-musl": "1.0.3", + "@rolldown/binding-linux-ppc64-gnu": "1.0.3", + "@rolldown/binding-linux-s390x-gnu": "1.0.3", + "@rolldown/binding-linux-x64-gnu": "1.0.3", + "@rolldown/binding-linux-x64-musl": "1.0.3", + "@rolldown/binding-openharmony-arm64": "1.0.3", + "@rolldown/binding-wasm32-wasi": "1.0.3", + "@rolldown/binding-win32-arm64-msvc": "1.0.3", + "@rolldown/binding-win32-x64-msvc": "1.0.3" + } + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz", + "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.2.tgz", + "integrity": "sha512-kCwffuaH8ntKtygnWe1b4BJKWiCUH30n5KfoTr6IchcXOwR7chAOFJxFrH3vjANafUYrIA4a7SDL+nn7SiR4Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^7.4.2" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.2.tgz", + "integrity": "sha512-nwEyF4vl4RSJjwSjBUmOSxc3BFPoIFdlRthJ6e+5v9P3bHNsoD06UjuqMUspqp7vsEZ1beaHi1km+optiE17yA==", + "dev": true, + "license": "MIT" + }, + "node_modules/topojson-client": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz", + "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==", + "license": "ISC", + "dependencies": { + "commander": "2" + }, + "bin": { + "topo2geo": "bin/topo2geo", + "topomerge": "bin/topomerge", + "topoquantize": "bin/topoquantize" + } + }, + "node_modules/tough-cookie": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz", + "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.27.0.tgz", + "integrity": "sha512-+t2Z/GwkZQDtu00813aP66ygViGtPHKhhoFZpQKpKrE+9jIgES+Zw+mFNaDWOVRKiuJjuqKHzD3B1sfGg8+ZOQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/vite": { + "version": "8.0.16", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz", + "integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.15", + "rolldown": "1.0.3", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.18", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitest": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.8.tgz", + "integrity": "sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.8", + "@vitest/mocker": "4.1.8", + "@vitest/pretty-format": "4.1.8", + "@vitest/runner": "4.1.8", + "@vitest/snapshot": "4.1.8", + "@vitest/spy": "4.1.8", + "@vitest/utils": "4.1.8", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.8", + "@vitest/browser-preview": "4.1.8", + "@vitest/browser-webdriverio": "4.1.8", + "@vitest/coverage-istanbul": "4.1.8", + "@vitest/coverage-v8": "4.1.8", + "@vitest/ui": "4.1.8", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20" + } + }, + "node_modules/whatwg-mimetype": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/whatwg-url": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz", + "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.11.0", + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..cc55dd7 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,29 @@ +{ + "name": "xav-portfolio-map", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "build": "tsc --noEmit && vite build", + "test": "vitest run" + }, + "dependencies": { + "react": "18.3.1", + "react-dom": "18.3.1", + "react-simple-maps": "3.0.0" + }, + "devDependencies": { + "@testing-library/react": "16.3.2", + "@types/react": "18.3.30", + "@types/react-dom": "18.3.7", + "@types/react-simple-maps": "3.0.6", + "@vitejs/plugin-react": "6.0.2", + "jsdom": "29.1.1", + "typescript": "6.0.3", + "vite": "8.0.16", + "vitest": "4.1.8" + }, + "overrides": { + "d3-color": "3.1.0" + } +} diff --git a/frontend/src/PortfolioMap.test.tsx b/frontend/src/PortfolioMap.test.tsx new file mode 100644 index 0000000..c7ca0c2 --- /dev/null +++ b/frontend/src/PortfolioMap.test.tsx @@ -0,0 +1,68 @@ +import { fireEvent, render, screen, waitFor } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +import { PortfolioMap } from "./PortfolioMap"; + +vi.mock("react-simple-maps", () => ({ + ComposableMap: ({ children }: { children: React.ReactNode }) => {children}, + Geographies: ({ + children, + geography, + }: { + children: (value: { geographies: unknown[] }) => React.ReactNode; + geography: string; + }) => + children({ + geographies: geography.includes("subdivisions") + ? [{ rsmKey: "us-ca", properties: { code: "US-CA", name: "California" } }] + : [], + }), + Geography: (props: React.SVGProps) => , +})); + +describe("PortfolioMap", () => { + beforeEach(() => { + vi.stubGlobal( + "fetch", + vi.fn().mockResolvedValue({ + ok: true, + json: () => + Promise.resolve({ + regions: [ + { code: "USA", name: "United States of America", level: "country", parentCode: null, entries: [] }, + { code: "US-CA", name: "California", level: "subdivision", parentCode: "USA", entries: [] }, + ], + }), + }), + ); + }); + + it("selects a region and renders its empty state", async () => { + render(); + + await waitFor(() => expect(screen.getByText("California")).toBeTruthy()); + fireEvent.change(screen.getByRole("combobox"), { target: { value: "US-CA" } }); + + expect(screen.getByText("No published experience is attached to this region yet.")).toBeTruthy(); + expect(screen.queryByRole("button", { name: "View United States of America" })).toBeNull(); + }); + + it("clears a pinned region", async () => { + render(); + + await waitFor(() => expect(screen.getByText("California")).toBeTruthy()); + fireEvent.change(screen.getByRole("combobox"), { target: { value: "US-CA" } }); + fireEvent.click(screen.getByRole("button", { name: "Clear selection" })); + + expect(screen.queryByText("No published experience is attached to this region yet.")).toBeNull(); + }); + + it("selects a map region with the keyboard", async () => { + render(); + + const region = await screen.findByRole("button", { name: "California" }); + fireEvent.keyDown(region, { key: "Enter" }); + + expect(screen.getByText("No published experience is attached to this region yet.")).toBeTruthy(); + }); +}); diff --git a/frontend/src/PortfolioMap.tsx b/frontend/src/PortfolioMap.tsx new file mode 100644 index 0000000..71b83e6 --- /dev/null +++ b/frontend/src/PortfolioMap.tsx @@ -0,0 +1,205 @@ +import { useEffect, useState } from "react"; +import { + ComposableMap, + Geographies, + Geography, +} from "react-simple-maps"; + +import type { Region, RegionsResponse } from "./types"; + +const countriesUrl = "/static/showcase/maps/countries.topo.json"; +const subdivisionsUrl = "/static/showcase/maps/subdivisions.topo.json"; +const visibleCountryCodes = new Set([ + "ALB", "AND", "AUT", "BEL", "BGR", "BIH", "BLR", "CAN", "CHE", "CZE", + "DEU", "DNK", "ESP", "EST", "FIN", "FRA", "GBR", "GRC", "GRL", "HRV", + "HUN", "IRL", "ISL", "ITA", "KOS", "LTU", "LUX", "LVA", "MDA", "MEX", + "MKD", "MNE", "NLD", "NOR", "POL", "PRT", "ROU", "RUS", "SRB", "SVK", + "SVN", "SWE", "TUR", "UKR", "USA", +]); + +type GeographyShape = { + rsmKey: string; + properties: { + code: string; + name: string; + }; +}; + +function RegionLayer({ + geographyUrl, + regions, + selectedCode, + visibleCodes, + onPreview, + onSelect, +}: { + geographyUrl: string; + regions: Map; + selectedCode: string | null; + visibleCodes?: Set; + onPreview: (region: Region | null) => void; + onSelect: (region: Region) => void; +}) { + return ( + + {({ geographies }: { geographies: GeographyShape[] }) => + geographies.map((geography) => { + if (visibleCodes && !visibleCodes.has(geography.properties.code)) return null; + + const region = regions.get(geography.properties.code); + if (!region) return null; + + const active = region.entries.length > 0; + const selected = selectedCode === region.code; + return ( + onPreview(null)} + onClick={() => onSelect(region)} + onFocus={() => onPreview(region)} + onKeyDown={(event) => { + if (event.key === "Enter" || event.key === " ") { + event.preventDefault(); + onSelect(region); + } + }} + onMouseEnter={() => onPreview(region)} + onMouseLeave={() => onPreview(null)} + role="button" + tabIndex={0} + /> + ); + }) + } + + ); +} + +function DetailPanel({ + region, + onClose, +}: { + region: Region | null; + onClose: () => void; +}) { + if (!region) return null; + + return ( + + ); +} + +export function PortfolioMap() { + const [regions, setRegions] = useState([]); + const [preview, setPreview] = useState(null); + const [selected, setSelected] = useState(null); + const [error, setError] = useState(false); + + useEffect(() => { + fetch("/api/map/regions/") + .then((response) => { + if (!response.ok) throw new Error("Unable to load map data"); + return response.json() as Promise; + }) + .then((response) => setRegions(response.regions)) + .catch(() => setError(true)); + }, []); + + const regionsByCode = new Map(regions.map((region) => [region.code, region])); + const visibleRegions = regions.filter( + (region) => region.level === "subdivision" || visibleCountryCodes.has(region.code), + ); + + if (error) { + return

The portfolio map could not be loaded.

; + } + + return ( +
+
+
+
+

Interactive geography

+

Atlas

+
+ +
+
+ + + + +
+ {preview ? ( + <> + {preview.name} + {preview.entries.length} linked {preview.entries.length === 1 ? "entry" : "entries"} + + ) : ( + Hover or choose a region + )} +
+
+
+ setSelected(null)} region={selected} /> +
+ ); +} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx new file mode 100644 index 0000000..8bf9038 --- /dev/null +++ b/frontend/src/main.tsx @@ -0,0 +1,11 @@ +import { createRoot } from "react-dom/client"; + +import { PortfolioMap } from "./PortfolioMap"; +import "./styles.css"; + +const root = document.getElementById("portfolio-map-root"); + +if (root) { + createRoot(root).render(); +} + diff --git a/frontend/src/styles.css b/frontend/src/styles.css new file mode 100644 index 0000000..c7270f8 --- /dev/null +++ b/frontend/src/styles.css @@ -0,0 +1,297 @@ +:root { + color: #1e2b26; + background: #f3efe4; + font-family: Georgia, "Times New Roman", serif; +} + +* { + box-sizing: border-box; +} + +html, +body { + height: 100%; + max-width: 100vw; + overflow: hidden; + width: 100%; +} + +body { + margin: 0; + background: + radial-gradient(circle at 20% 15%, rgba(190, 209, 196, 0.55), transparent 30rem), + #f3efe4; +} + +button, +select { + font: inherit; +} + +.site-header, +.site-shell { + margin: 0 auto; + max-width: 1480px; + padding-inline: clamp(1rem, 4vw, 5rem); + width: 100%; +} + +.site-header { + align-items: center; + display: flex; + justify-content: space-between; + padding-block: 1.35rem; +} + +.site-shell { + height: calc(100dvh - 4.2rem); + overflow: hidden; + padding-bottom: 1rem; +} + +.site-shell section, +#portfolio-map-root, +.map-island, +.map-stage { + height: 100%; +} + +h2, +h3, +h4, +p { + margin-top: 0; +} + +.site-mark { + color: #1e2b26; + font-size: 1.5rem; + font-weight: 700; + letter-spacing: -0.08em; + text-decoration: none; +} + +.site-mark span { + color: #bf5b3a; +} + +.site-header nav { + display: flex; + gap: clamp(0.9rem, 3vw, 2.4rem); +} + +.site-header nav a { + color: #53645d; + font-family: "Courier New", monospace; + font-size: 0.72rem; + letter-spacing: 0.12em; + text-decoration: none; + text-transform: uppercase; +} + +.site-header nav a:hover, +.site-header nav a:focus { + color: #bf5b3a; +} + +.eyebrow, +.entry-type { + color: #bf5b3a; + font-family: "Courier New", monospace; + font-size: 0.7rem; + letter-spacing: 0.16em; + text-transform: uppercase; +} + +.map-island { + margin-top: 1rem; +} + +.map-island.has-detail { + display: grid; + gap: 1rem; + grid-template-columns: minmax(0, 1fr) minmax(17rem, 22rem); +} + +.map-stage, +.detail-panel { + background: rgba(255, 252, 243, 0.72); + border: 1px solid rgba(55, 83, 72, 0.18); +} + +.map-stage { + display: flex; + flex-direction: column; + padding: 1rem; +} + +.map-toolbar { + align-items: end; + display: flex; + justify-content: space-between; + gap: 1rem; +} + +.map-toolbar h2 { + font-size: clamp(1.8rem, 4vw, 3rem); + letter-spacing: -0.06em; +} + +select { + background: #fffaf0; + border: 1px solid #9aa99e; + color: #1e2b26; + max-width: 15rem; + padding: 0.55rem; +} + +.map-canvas { + flex: 1; + min-height: 0; + position: relative; +} + +.map-canvas svg { + display: block; + height: 100%; + width: 100%; +} + +.map-region { + cursor: pointer; + fill: #d7ddd3; + outline: none; + stroke: #fffaf0; + stroke-width: 0.5; + transition: fill 160ms ease, stroke 160ms ease; +} + +.map-region.has-entries { + fill: #91a899; +} + +.map-region:hover, +.map-region:focus, +.map-region.is-selected { + fill: #bf5b3a; + stroke: #71311f; +} + +.map-preview { + align-items: start; + background: rgba(255, 250, 240, 0.88); + bottom: 0; + display: flex; + flex-direction: column; + font-family: "Courier New", monospace; + font-size: 0.78rem; + gap: 0.2rem; + left: 0; + padding: 0.55rem 0.7rem; + position: absolute; +} + +.detail-panel { + min-height: 0; + overflow: auto; + padding: 1rem; +} + +.detail-panel h3 { + font-size: 2rem; + letter-spacing: -0.05em; +} + +.close-button { + background: transparent; + border: 1px solid #9aa99e; + color: #1e2b26; + cursor: pointer; + padding: 0.45rem 0.65rem; +} + +.close-button { + float: right; + font-size: 0.72rem; +} + +.entry-card { + border-top: 1px solid rgba(55, 83, 72, 0.18); + padding-top: 0.9rem; +} + +.entry-card a { + color: #9e452c; +} + +.empty-state, +.map-status { + color: #53645d; +} + +.sr-only { + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + +@media (max-width: 760px) { + .site-header { + max-width: none; + padding-inline: 0.75rem; + padding-block: 1rem; + position: relative; + width: 100%; + } + + .site-header nav { + display: grid; + gap: 0.45rem; + grid-template-columns: repeat(3, auto); + justify-content: end; + position: absolute; + right: 0.75rem; + top: 1.45rem; + } + + .site-header nav a { + font-size: 0.56rem; + letter-spacing: 0.04em; + } + + .site-shell { + height: calc(100dvh - 3.5rem); + padding-bottom: 0.75rem; + padding-inline: 0.75rem; + } + + .map-island { + display: block; + margin-top: 0.5rem; + } + + .map-toolbar { + align-items: stretch; + flex-direction: column; + } + + .map-canvas { + min-height: 0; + } + + .detail-panel { + background: #fffaf0; + border-radius: 1rem 1rem 0 0; + bottom: 0; + box-shadow: 0 -0.5rem 2rem rgba(30, 43, 38, 0.18); + left: 0; + max-height: 58vh; + overflow: auto; + position: fixed; + right: 0; + z-index: 10; + } +} diff --git a/frontend/src/types.ts b/frontend/src/types.ts new file mode 100644 index 0000000..5c8cc7a --- /dev/null +++ b/frontend/src/types.ts @@ -0,0 +1,23 @@ +export type PortfolioEntry = { + id: number; + type: "work" | "cv"; + title: string; + organization: string; + startDate: string | null; + endDate: string | null; + summary: string; + url: string; +}; + +export type Region = { + code: string; + name: string; + level: "country" | "subdivision"; + parentCode: string | null; + entries: PortfolioEntry[]; +}; + +export type RegionsResponse = { + regions: Region[]; +}; + diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts new file mode 100644 index 0000000..ed77210 --- /dev/null +++ b/frontend/src/vite-env.d.ts @@ -0,0 +1,2 @@ +/// + diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 0000000..8d0354b --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "noEmit": true + }, + "include": ["src", "vite.config.ts"] +} + diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts new file mode 100644 index 0000000..f849fca --- /dev/null +++ b/frontend/vite.config.ts @@ -0,0 +1,27 @@ +import react from "@vitejs/plugin-react"; +import { defineConfig } from "vitest/config"; + +export default defineConfig(({ mode }) => ({ + define: { + "process.env.NODE_ENV": JSON.stringify(mode === "test" ? "test" : "production"), + }, + plugins: [react()], + build: { + outDir: "../showcase/static/showcase/dist", + emptyOutDir: true, + lib: { + entry: "src/main.tsx", + formats: ["es"], + fileName: () => "map.js", + }, + rollupOptions: { + output: { + assetFileNames: "map.[ext]", + }, + }, + }, + test: { + environment: "jsdom", + globals: true, + }, +})); diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..2a6514a --- /dev/null +++ b/manage.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +import os +import sys + + +def main(): + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "portfolio.settings") + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) + + +if __name__ == "__main__": + main() + diff --git a/portfolio/__init__.py b/portfolio/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/portfolio/__init__.py @@ -0,0 +1 @@ + diff --git a/portfolio/asgi.py b/portfolio/asgi.py new file mode 100644 index 0000000..b888257 --- /dev/null +++ b/portfolio/asgi.py @@ -0,0 +1,8 @@ +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "portfolio.settings") + +application = get_asgi_application() + diff --git a/portfolio/settings.py b/portfolio/settings.py new file mode 100644 index 0000000..c457fe2 --- /dev/null +++ b/portfolio/settings.py @@ -0,0 +1,79 @@ +import os +from pathlib import Path + +BASE_DIR = Path(__file__).resolve().parent.parent + +SECRET_KEY = os.environ["DJANGO_SECRET_KEY"] +DEBUG = os.environ.get("DJANGO_DEBUG", "0") == "1" +ALLOWED_HOSTS = [ + host for host in os.environ.get("DJANGO_ALLOWED_HOSTS", "").split(",") if host +] + +INSTALLED_APPS = [ + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "showcase", +] + +MIDDLEWARE = [ + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", +] + +ROOT_URLCONF = "portfolio.urls" + +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ], + }, + }, +] + +WSGI_APPLICATION = "portfolio.wsgi.application" + +DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": BASE_DIR / "db.sqlite3", + } +} + +AUTH_PASSWORD_VALIDATORS = [ + { + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", + }, +] + +LANGUAGE_CODE = "en-us" +TIME_ZONE = "UTC" +USE_I18N = True +USE_TZ = True + +STATIC_URL = "static/" +DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" diff --git a/portfolio/urls.py b/portfolio/urls.py new file mode 100644 index 0000000..85641c1 --- /dev/null +++ b/portfolio/urls.py @@ -0,0 +1,7 @@ +from django.contrib import admin +from django.urls import include, path + +urlpatterns = [ + path("admin/", admin.site.urls), + path("", include("showcase.urls")), +] diff --git a/portfolio/wsgi.py b/portfolio/wsgi.py new file mode 100644 index 0000000..0bb6c45 --- /dev/null +++ b/portfolio/wsgi.py @@ -0,0 +1,8 @@ +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "portfolio.settings") + +application = get_wsgi_application() + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..5cb46df --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +asgiref==3.11.1 +Django==5.2.14 +sqlparse==0.5.5 diff --git a/showcase/__init__.py b/showcase/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/showcase/__init__.py @@ -0,0 +1 @@ + diff --git a/showcase/admin.py b/showcase/admin.py new file mode 100644 index 0000000..f543468 --- /dev/null +++ b/showcase/admin.py @@ -0,0 +1,19 @@ +from django.contrib import admin + +from .models import PortfolioEntry, Region + + +@admin.register(Region) +class RegionAdmin(admin.ModelAdmin): + list_display = ("name", "code", "level", "parent") + list_filter = ("level", "parent") + search_fields = ("name", "code") + + +@admin.register(PortfolioEntry) +class PortfolioEntryAdmin(admin.ModelAdmin): + list_display = ("title", "organization", "entry_type", "is_published", "display_order") + list_filter = ("entry_type", "is_published", "regions") + search_fields = ("title", "organization", "summary") + filter_horizontal = ("regions",) + diff --git a/showcase/apps.py b/showcase/apps.py new file mode 100644 index 0000000..3bdbcbb --- /dev/null +++ b/showcase/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig + + +class ShowcaseConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "showcase" + diff --git a/showcase/migrations/0001_initial.py b/showcase/migrations/0001_initial.py new file mode 100644 index 0000000..82c341f --- /dev/null +++ b/showcase/migrations/0001_initial.py @@ -0,0 +1,57 @@ +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="Region", + fields=[ + ("code", models.CharField(max_length=8, primary_key=True, serialize=False)), + ("name", models.CharField(max_length=120)), + ( + "level", + models.CharField( + choices=[("country", "Country"), ("subdivision", "Subdivision")], + max_length=16, + ), + ), + ( + "parent", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="subdivisions", + to="showcase.region", + ), + ), + ], + options={"ordering": ("name",)}, + ), + migrations.CreateModel( + name="PortfolioEntry", + fields=[ + ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("entry_type", models.CharField(choices=[("work", "Work"), ("cv", "CV")], max_length=8)), + ("title", models.CharField(max_length=160)), + ("organization", models.CharField(blank=True, max_length=160)), + ("start_date", models.DateField(blank=True, null=True)), + ("end_date", models.DateField(blank=True, null=True)), + ("summary", models.TextField()), + ("url", models.URLField(blank=True)), + ("is_published", models.BooleanField(default=False)), + ("display_order", models.PositiveIntegerField(default=0)), + ("regions", models.ManyToManyField(related_name="entries", to="showcase.region")), + ], + options={ + "verbose_name_plural": "portfolio entries", + "ordering": ("display_order", "-start_date", "title"), + }, + ), + ] + diff --git a/showcase/migrations/0002_seed_regions.py b/showcase/migrations/0002_seed_regions.py new file mode 100644 index 0000000..df9dfdf --- /dev/null +++ b/showcase/migrations/0002_seed_regions.py @@ -0,0 +1,37 @@ +import json +from pathlib import Path + +from django.db import migrations + + +def seed_regions(apps, schema_editor): + region_model = apps.get_model("showcase", "Region") + seed_path = Path(__file__).with_name("regions.json") + regions = json.loads(seed_path.read_text()) + + for region in regions["countries"]: + region_model.objects.update_or_create( + code=region["code"], + defaults={"name": region["name"], "level": "country", "parent": None}, + ) + + for region in regions["subdivisions"]: + region_model.objects.update_or_create( + code=region["code"], + defaults={ + "name": region["name"], + "level": "subdivision", + "parent_id": region["parentCode"], + }, + ) + + +def unseed_regions(apps, schema_editor): + apps.get_model("showcase", "Region").objects.all().delete() + + +class Migration(migrations.Migration): + dependencies = [("showcase", "0001_initial")] + + operations = [migrations.RunPython(seed_regions, unseed_regions)] + diff --git a/showcase/migrations/__init__.py b/showcase/migrations/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/showcase/migrations/__init__.py @@ -0,0 +1 @@ + diff --git a/showcase/migrations/regions.json b/showcase/migrations/regions.json new file mode 100644 index 0000000..4c7b395 --- /dev/null +++ b/showcase/migrations/regions.json @@ -0,0 +1,1034 @@ +{ + "countries": [ + { + "code": "AFG", + "name": "Afghanistan" + }, + { + "code": "ALB", + "name": "Albania" + }, + { + "code": "DZA", + "name": "Algeria" + }, + { + "code": "AGO", + "name": "Angola" + }, + { + "code": "ATA", + "name": "Antarctica" + }, + { + "code": "ARG", + "name": "Argentina" + }, + { + "code": "ARM", + "name": "Armenia" + }, + { + "code": "AUS", + "name": "Australia" + }, + { + "code": "AUT", + "name": "Austria" + }, + { + "code": "AZE", + "name": "Azerbaijan" + }, + { + "code": "BHS", + "name": "Bahamas" + }, + { + "code": "BGD", + "name": "Bangladesh" + }, + { + "code": "BLR", + "name": "Belarus" + }, + { + "code": "BEL", + "name": "Belgium" + }, + { + "code": "BLZ", + "name": "Belize" + }, + { + "code": "BEN", + "name": "Benin" + }, + { + "code": "BTN", + "name": "Bhutan" + }, + { + "code": "BOL", + "name": "Bolivia" + }, + { + "code": "BIH", + "name": "Bosnia and Herz." + }, + { + "code": "BWA", + "name": "Botswana" + }, + { + "code": "BRA", + "name": "Brazil" + }, + { + "code": "BRN", + "name": "Brunei" + }, + { + "code": "BGR", + "name": "Bulgaria" + }, + { + "code": "BFA", + "name": "Burkina Faso" + }, + { + "code": "BDI", + "name": "Burundi" + }, + { + "code": "KHM", + "name": "Cambodia" + }, + { + "code": "CMR", + "name": "Cameroon" + }, + { + "code": "CAN", + "name": "Canada" + }, + { + "code": "CAF", + "name": "Central African Rep." + }, + { + "code": "TCD", + "name": "Chad" + }, + { + "code": "CHL", + "name": "Chile" + }, + { + "code": "CHN", + "name": "China" + }, + { + "code": "COL", + "name": "Colombia" + }, + { + "code": "COG", + "name": "Congo" + }, + { + "code": "CRI", + "name": "Costa Rica" + }, + { + "code": "HRV", + "name": "Croatia" + }, + { + "code": "CUB", + "name": "Cuba" + }, + { + "code": "CYP", + "name": "Cyprus" + }, + { + "code": "CZE", + "name": "Czechia" + }, + { + "code": "CIV", + "name": "Côte d'Ivoire" + }, + { + "code": "COD", + "name": "Dem. Rep. Congo" + }, + { + "code": "DNK", + "name": "Denmark" + }, + { + "code": "DJI", + "name": "Djibouti" + }, + { + "code": "DOM", + "name": "Dominican Rep." + }, + { + "code": "ECU", + "name": "Ecuador" + }, + { + "code": "EGY", + "name": "Egypt" + }, + { + "code": "SLV", + "name": "El Salvador" + }, + { + "code": "GNQ", + "name": "Eq. Guinea" + }, + { + "code": "ERI", + "name": "Eritrea" + }, + { + "code": "EST", + "name": "Estonia" + }, + { + "code": "ETH", + "name": "Ethiopia" + }, + { + "code": "FLK", + "name": "Falkland Is." + }, + { + "code": "FJI", + "name": "Fiji" + }, + { + "code": "FIN", + "name": "Finland" + }, + { + "code": "ATF", + "name": "Fr. S. Antarctic Lands" + }, + { + "code": "FRA", + "name": "France" + }, + { + "code": "GAB", + "name": "Gabon" + }, + { + "code": "GMB", + "name": "Gambia" + }, + { + "code": "GEO", + "name": "Georgia" + }, + { + "code": "DEU", + "name": "Germany" + }, + { + "code": "GHA", + "name": "Ghana" + }, + { + "code": "GRC", + "name": "Greece" + }, + { + "code": "GRL", + "name": "Greenland" + }, + { + "code": "GTM", + "name": "Guatemala" + }, + { + "code": "GIN", + "name": "Guinea" + }, + { + "code": "GNB", + "name": "Guinea-Bissau" + }, + { + "code": "GUY", + "name": "Guyana" + }, + { + "code": "HTI", + "name": "Haiti" + }, + { + "code": "HND", + "name": "Honduras" + }, + { + "code": "HUN", + "name": "Hungary" + }, + { + "code": "ISL", + "name": "Iceland" + }, + { + "code": "IND", + "name": "India" + }, + { + "code": "IDN", + "name": "Indonesia" + }, + { + "code": "IRN", + "name": "Iran" + }, + { + "code": "IRQ", + "name": "Iraq" + }, + { + "code": "IRL", + "name": "Ireland" + }, + { + "code": "ISR", + "name": "Israel" + }, + { + "code": "ITA", + "name": "Italy" + }, + { + "code": "JAM", + "name": "Jamaica" + }, + { + "code": "JPN", + "name": "Japan" + }, + { + "code": "JOR", + "name": "Jordan" + }, + { + "code": "KAZ", + "name": "Kazakhstan" + }, + { + "code": "KEN", + "name": "Kenya" + }, + { + "code": "KOS", + "name": "Kosovo" + }, + { + "code": "KWT", + "name": "Kuwait" + }, + { + "code": "KGZ", + "name": "Kyrgyzstan" + }, + { + "code": "LAO", + "name": "Laos" + }, + { + "code": "LVA", + "name": "Latvia" + }, + { + "code": "LBN", + "name": "Lebanon" + }, + { + "code": "LSO", + "name": "Lesotho" + }, + { + "code": "LBR", + "name": "Liberia" + }, + { + "code": "LBY", + "name": "Libya" + }, + { + "code": "LTU", + "name": "Lithuania" + }, + { + "code": "LUX", + "name": "Luxembourg" + }, + { + "code": "MDG", + "name": "Madagascar" + }, + { + "code": "MWI", + "name": "Malawi" + }, + { + "code": "MYS", + "name": "Malaysia" + }, + { + "code": "MLI", + "name": "Mali" + }, + { + "code": "MRT", + "name": "Mauritania" + }, + { + "code": "MEX", + "name": "Mexico" + }, + { + "code": "MDA", + "name": "Moldova" + }, + { + "code": "MNG", + "name": "Mongolia" + }, + { + "code": "MNE", + "name": "Montenegro" + }, + { + "code": "MAR", + "name": "Morocco" + }, + { + "code": "MOZ", + "name": "Mozambique" + }, + { + "code": "MMR", + "name": "Myanmar" + }, + { + "code": "CYN", + "name": "N. Cyprus" + }, + { + "code": "NAM", + "name": "Namibia" + }, + { + "code": "NPL", + "name": "Nepal" + }, + { + "code": "NLD", + "name": "Netherlands" + }, + { + "code": "NCL", + "name": "New Caledonia" + }, + { + "code": "NZL", + "name": "New Zealand" + }, + { + "code": "NIC", + "name": "Nicaragua" + }, + { + "code": "NER", + "name": "Niger" + }, + { + "code": "NGA", + "name": "Nigeria" + }, + { + "code": "PRK", + "name": "North Korea" + }, + { + "code": "MKD", + "name": "North Macedonia" + }, + { + "code": "NOR", + "name": "Norway" + }, + { + "code": "OMN", + "name": "Oman" + }, + { + "code": "PAK", + "name": "Pakistan" + }, + { + "code": "PSX", + "name": "Palestine" + }, + { + "code": "PAN", + "name": "Panama" + }, + { + "code": "PNG", + "name": "Papua New Guinea" + }, + { + "code": "PRY", + "name": "Paraguay" + }, + { + "code": "PER", + "name": "Peru" + }, + { + "code": "PHL", + "name": "Philippines" + }, + { + "code": "POL", + "name": "Poland" + }, + { + "code": "PRT", + "name": "Portugal" + }, + { + "code": "PRI", + "name": "Puerto Rico" + }, + { + "code": "QAT", + "name": "Qatar" + }, + { + "code": "ROU", + "name": "Romania" + }, + { + "code": "RUS", + "name": "Russia" + }, + { + "code": "RWA", + "name": "Rwanda" + }, + { + "code": "SDS", + "name": "S. Sudan" + }, + { + "code": "SAU", + "name": "Saudi Arabia" + }, + { + "code": "SEN", + "name": "Senegal" + }, + { + "code": "SRB", + "name": "Serbia" + }, + { + "code": "SLE", + "name": "Sierra Leone" + }, + { + "code": "SVK", + "name": "Slovakia" + }, + { + "code": "SVN", + "name": "Slovenia" + }, + { + "code": "SLB", + "name": "Solomon Is." + }, + { + "code": "SOM", + "name": "Somalia" + }, + { + "code": "SOL", + "name": "Somaliland" + }, + { + "code": "ZAF", + "name": "South Africa" + }, + { + "code": "KOR", + "name": "South Korea" + }, + { + "code": "ESP", + "name": "Spain" + }, + { + "code": "LKA", + "name": "Sri Lanka" + }, + { + "code": "SDN", + "name": "Sudan" + }, + { + "code": "SUR", + "name": "Suriname" + }, + { + "code": "SWE", + "name": "Sweden" + }, + { + "code": "CHE", + "name": "Switzerland" + }, + { + "code": "SYR", + "name": "Syria" + }, + { + "code": "TWN", + "name": "Taiwan" + }, + { + "code": "TJK", + "name": "Tajikistan" + }, + { + "code": "TZA", + "name": "Tanzania" + }, + { + "code": "THA", + "name": "Thailand" + }, + { + "code": "TLS", + "name": "Timor-Leste" + }, + { + "code": "TGO", + "name": "Togo" + }, + { + "code": "TTO", + "name": "Trinidad and Tobago" + }, + { + "code": "TUN", + "name": "Tunisia" + }, + { + "code": "TUR", + "name": "Turkey" + }, + { + "code": "TKM", + "name": "Turkmenistan" + }, + { + "code": "UGA", + "name": "Uganda" + }, + { + "code": "UKR", + "name": "Ukraine" + }, + { + "code": "ARE", + "name": "United Arab Emirates" + }, + { + "code": "GBR", + "name": "United Kingdom" + }, + { + "code": "USA", + "name": "United States of America" + }, + { + "code": "URY", + "name": "Uruguay" + }, + { + "code": "UZB", + "name": "Uzbekistan" + }, + { + "code": "VUT", + "name": "Vanuatu" + }, + { + "code": "VEN", + "name": "Venezuela" + }, + { + "code": "VNM", + "name": "Vietnam" + }, + { + "code": "SAH", + "name": "W. Sahara" + }, + { + "code": "YEM", + "name": "Yemen" + }, + { + "code": "ZMB", + "name": "Zambia" + }, + { + "code": "ZWE", + "name": "Zimbabwe" + }, + { + "code": "SWZ", + "name": "eSwatini" + } + ], + "subdivisions": [ + { + "code": "US-AL", + "name": "Alabama", + "parentCode": "USA" + }, + { + "code": "US-AK", + "name": "Alaska", + "parentCode": "USA" + }, + { + "code": "CA-AB", + "name": "Alberta", + "parentCode": "CAN" + }, + { + "code": "US-AZ", + "name": "Arizona", + "parentCode": "USA" + }, + { + "code": "US-AR", + "name": "Arkansas", + "parentCode": "USA" + }, + { + "code": "CA-BC", + "name": "British Columbia", + "parentCode": "CAN" + }, + { + "code": "US-CA", + "name": "California", + "parentCode": "USA" + }, + { + "code": "US-CO", + "name": "Colorado", + "parentCode": "USA" + }, + { + "code": "US-CT", + "name": "Connecticut", + "parentCode": "USA" + }, + { + "code": "US-DE", + "name": "Delaware", + "parentCode": "USA" + }, + { + "code": "US-DC", + "name": "District of Columbia", + "parentCode": "USA" + }, + { + "code": "US-FL", + "name": "Florida", + "parentCode": "USA" + }, + { + "code": "US-GA", + "name": "Georgia", + "parentCode": "USA" + }, + { + "code": "US-HI", + "name": "Hawaii", + "parentCode": "USA" + }, + { + "code": "US-ID", + "name": "Idaho", + "parentCode": "USA" + }, + { + "code": "US-IL", + "name": "Illinois", + "parentCode": "USA" + }, + { + "code": "US-IN", + "name": "Indiana", + "parentCode": "USA" + }, + { + "code": "US-IA", + "name": "Iowa", + "parentCode": "USA" + }, + { + "code": "US-KS", + "name": "Kansas", + "parentCode": "USA" + }, + { + "code": "US-KY", + "name": "Kentucky", + "parentCode": "USA" + }, + { + "code": "US-LA", + "name": "Louisiana", + "parentCode": "USA" + }, + { + "code": "US-ME", + "name": "Maine", + "parentCode": "USA" + }, + { + "code": "CA-MB", + "name": "Manitoba", + "parentCode": "CAN" + }, + { + "code": "US-MD", + "name": "Maryland", + "parentCode": "USA" + }, + { + "code": "US-MA", + "name": "Massachusetts", + "parentCode": "USA" + }, + { + "code": "US-MI", + "name": "Michigan", + "parentCode": "USA" + }, + { + "code": "US-MN", + "name": "Minnesota", + "parentCode": "USA" + }, + { + "code": "US-MS", + "name": "Mississippi", + "parentCode": "USA" + }, + { + "code": "US-MO", + "name": "Missouri", + "parentCode": "USA" + }, + { + "code": "US-MT", + "name": "Montana", + "parentCode": "USA" + }, + { + "code": "US-NE", + "name": "Nebraska", + "parentCode": "USA" + }, + { + "code": "US-NV", + "name": "Nevada", + "parentCode": "USA" + }, + { + "code": "CA-NB", + "name": "New Brunswick", + "parentCode": "CAN" + }, + { + "code": "US-NH", + "name": "New Hampshire", + "parentCode": "USA" + }, + { + "code": "US-NJ", + "name": "New Jersey", + "parentCode": "USA" + }, + { + "code": "US-NM", + "name": "New Mexico", + "parentCode": "USA" + }, + { + "code": "US-NY", + "name": "New York", + "parentCode": "USA" + }, + { + "code": "CA-NL", + "name": "Newfoundland and Labrador", + "parentCode": "CAN" + }, + { + "code": "US-NC", + "name": "North Carolina", + "parentCode": "USA" + }, + { + "code": "US-ND", + "name": "North Dakota", + "parentCode": "USA" + }, + { + "code": "CA-NT", + "name": "Northwest Territories", + "parentCode": "CAN" + }, + { + "code": "CA-NS", + "name": "Nova Scotia", + "parentCode": "CAN" + }, + { + "code": "CA-NU", + "name": "Nunavut", + "parentCode": "CAN" + }, + { + "code": "US-OH", + "name": "Ohio", + "parentCode": "USA" + }, + { + "code": "US-OK", + "name": "Oklahoma", + "parentCode": "USA" + }, + { + "code": "CA-ON", + "name": "Ontario", + "parentCode": "CAN" + }, + { + "code": "US-OR", + "name": "Oregon", + "parentCode": "USA" + }, + { + "code": "US-PA", + "name": "Pennsylvania", + "parentCode": "USA" + }, + { + "code": "CA-PE", + "name": "Prince Edward Island", + "parentCode": "CAN" + }, + { + "code": "CA-QC", + "name": "Québec", + "parentCode": "CAN" + }, + { + "code": "US-RI", + "name": "Rhode Island", + "parentCode": "USA" + }, + { + "code": "CA-SK", + "name": "Saskatchewan", + "parentCode": "CAN" + }, + { + "code": "US-SC", + "name": "South Carolina", + "parentCode": "USA" + }, + { + "code": "US-SD", + "name": "South Dakota", + "parentCode": "USA" + }, + { + "code": "US-TN", + "name": "Tennessee", + "parentCode": "USA" + }, + { + "code": "US-TX", + "name": "Texas", + "parentCode": "USA" + }, + { + "code": "US-UT", + "name": "Utah", + "parentCode": "USA" + }, + { + "code": "US-VT", + "name": "Vermont", + "parentCode": "USA" + }, + { + "code": "US-VA", + "name": "Virginia", + "parentCode": "USA" + }, + { + "code": "US-WA", + "name": "Washington", + "parentCode": "USA" + }, + { + "code": "US-WV", + "name": "West Virginia", + "parentCode": "USA" + }, + { + "code": "US-WI", + "name": "Wisconsin", + "parentCode": "USA" + }, + { + "code": "US-WY", + "name": "Wyoming", + "parentCode": "USA" + }, + { + "code": "CA-YT", + "name": "Yukon", + "parentCode": "CAN" + } + ] +} diff --git a/showcase/models.py b/showcase/models.py new file mode 100644 index 0000000..6ceb0a8 --- /dev/null +++ b/showcase/models.py @@ -0,0 +1,49 @@ +from django.db import models + + +class Region(models.Model): + class Level(models.TextChoices): + COUNTRY = "country", "Country" + SUBDIVISION = "subdivision", "Subdivision" + + code = models.CharField(max_length=8, primary_key=True) + name = models.CharField(max_length=120) + level = models.CharField(max_length=16, choices=Level.choices) + parent = models.ForeignKey( + "self", + blank=True, + null=True, + on_delete=models.CASCADE, + related_name="subdivisions", + ) + + class Meta: + ordering = ("name",) + + def __str__(self): + return self.name + + +class PortfolioEntry(models.Model): + class EntryType(models.TextChoices): + WORK = "work", "Work" + CV = "cv", "CV" + + entry_type = models.CharField(max_length=8, choices=EntryType.choices) + title = models.CharField(max_length=160) + organization = models.CharField(max_length=160, blank=True) + start_date = models.DateField(blank=True, null=True) + end_date = models.DateField(blank=True, null=True) + summary = models.TextField() + url = models.URLField(blank=True) + is_published = models.BooleanField(default=False) + display_order = models.PositiveIntegerField(default=0) + regions = models.ManyToManyField(Region, related_name="entries") + + class Meta: + ordering = ("display_order", "-start_date", "title") + verbose_name_plural = "portfolio entries" + + def __str__(self): + return self.title + diff --git a/showcase/static/showcase/maps/countries.topo.json b/showcase/static/showcase/maps/countries.topo.json new file mode 100644 index 0000000..346988b --- /dev/null +++ b/showcase/static/showcase/maps/countries.topo.json @@ -0,0 +1,11736 @@ +{ + "type": "Topology", + "arcs": [ + [ + [ + 6931, + 2331 + ], + [ + 8, + -20 + ], + [ + -23, + -1 + ], + [ + 6, + 25 + ], + [ + 9, + -4 + ] + ], + [ + [ + 4140, + 2864 + ], + [ + 73, + -69 + ], + [ + 29, + -51 + ] + ], + [ + [ + 4242, + 2744 + ], + [ + 0, + -123 + ], + [ + 22, + -59 + ] + ], + [ + [ + 4264, + 2562 + ], + [ + -74, + -45 + ], + [ + -38, + 7 + ] + ], + [ + [ + 4152, + 2524 + ], + [ + -35, + 73 + ] + ], + [ + [ + 4117, + 2597 + ], + [ + -39, + 29 + ] + ], + [ + [ + 4078, + 2626 + ], + [ + -27, + 123 + ] + ], + [ + [ + 4051, + 2749 + ], + [ + 22, + 68 + ] + ], + [ + [ + 4073, + 2817 + ], + [ + -1, + 41 + ] + ], + [ + [ + 4072, + 2858 + ], + [ + 68, + 6 + ] + ], + [ + [ + 3316, + 3784 + ], + [ + -1, + -9 + ] + ], + [ + [ + 3315, + 3775 + ], + [ + 0, + -49 + ], + [ + -63, + 2 + ], + [ + 0, + -82 + ], + [ + -19, + -66 + ], + [ + -80, + -10 + ] + ], + [ + [ + 3153, + 3570 + ], + [ + 1, + 13 + ] + ], + [ + [ + 3154, + 3583 + ], + [ + 44, + 3 + ], + [ + 17, + 70 + ], + [ + 48, + 103 + ], + [ + 53, + 25 + ] + ], + [ + [ + 1106, + 4470 + ], + [ + -89, + 59 + ], + [ + -60, + 128 + ] + ], + [ + [ + 957, + 4657 + ], + [ + -95, + 160 + ], + [ + -39, + -29 + ], + [ + -68, + 46 + ], + [ + 0, + 183 + ], + [ + 0, + 119 + ] + ], + [ + [ + 755, + 5136 + ], + [ + 87, + -26 + ], + [ + 175, + 47 + ], + [ + 262, + -63 + ], + [ + 77, + -14 + ], + [ + 222, + -6 + ], + [ + 63, + 133 + ], + [ + 139, + -106 + ], + [ + 48, + 40 + ], + [ + 82, + -23 + ], + [ + -2, + -66 + ], + [ + -90, + -34 + ], + [ + -47, + -63 + ], + [ + -90, + -66 + ], + [ + -29, + -62 + ], + [ + 72, + -91 + ], + [ + 114, + -63 + ], + [ + 53, + -5 + ], + [ + 17, + -97 + ], + [ + 54, + 13 + ], + [ + -10, + 51 + ], + [ + 50, + 77 + ], + [ + -38, + 73 + ], + [ + 23, + 34 + ], + [ + -15, + 79 + ], + [ + 82, + 4 + ], + [ + 83, + -44 + ], + [ + 6, + -68 + ], + [ + 59, + -6 + ], + [ + 32, + 50 + ], + [ + 97, + -165 + ], + [ + 43, + -18 + ], + [ + 32, + -80 + ], + [ + -84, + -61 + ], + [ + -98, + -33 + ], + [ + 12, + -96 + ], + [ + 66, + -31 + ], + [ + -83, + -55 + ], + [ + -35, + 51 + ] + ], + [ + [ + 2184, + 4346 + ], + [ + -40, + 74 + ], + [ + -44, + -78 + ], + [ + -65, + -1 + ], + [ + -38, + -44 + ], + [ + -109, + -63 + ], + [ + -2, + 118 + ], + [ + -113, + 96 + ], + [ + -63, + -6 + ], + [ + -68, + 28 + ], + [ + -230, + 0 + ], + [ + -174, + 0 + ], + [ + -132, + 0 + ] + ], + [ + [ + 2407, + 4544 + ], + [ + -4, + -55 + ], + [ + 46, + -11 + ], + [ + 7, + -83 + ], + [ + -61, + 31 + ], + [ + -58, + -1 + ], + [ + 48, + 118 + ], + [ + 22, + 1 + ] + ], + [ + [ + 1959, + 5221 + ], + [ + 228, + -102 + ], + [ + 93, + -97 + ], + [ + -61, + -57 + ], + [ + -16, + -79 + ], + [ + -94, + 31 + ], + [ + -133, + 77 + ], + [ + 101, + 64 + ], + [ + -89, + 80 + ], + [ + -148, + 6 + ], + [ + -89, + 26 + ], + [ + -13, + 47 + ], + [ + 152, + 49 + ], + [ + 69, + -45 + ] + ], + [ + [ + 1131, + 5288 + ], + [ + 117, + -31 + ], + [ + -147, + -83 + ], + [ + -55, + 31 + ], + [ + 85, + 83 + ] + ], + [ + [ + 1422, + 5244 + ], + [ + 40, + -67 + ], + [ + -29, + -58 + ], + [ + -142, + -21 + ], + [ + -55, + 20 + ], + [ + -63, + 77 + ], + [ + 81, + 57 + ], + [ + 168, + -8 + ] + ], + [ + [ + 1711, + 5528 + ], + [ + 238, + 39 + ], + [ + 337, + -24 + ], + [ + -180, + -83 + ], + [ + -182, + -116 + ], + [ + -172, + 9 + ], + [ + 85, + 93 + ], + [ + -126, + 82 + ] + ], + [ + [ + 957, + 4657 + ], + [ + -68, + 106 + ], + [ + -72, + 12 + ], + [ + -40, + 34 + ], + [ + -158, + 14 + ], + [ + -120, + -59 + ], + [ + -68, + -18 + ], + [ + -162, + 126 + ], + [ + 30, + 53 + ], + [ + -69, + 81 + ], + [ + 70, + 29 + ], + [ + -17, + 47 + ], + [ + 67, + 74 + ], + [ + 103, + 33 + ], + [ + 84, + -24 + ], + [ + 218, + -29 + ] + ], + [ + [ + 2184, + 4346 + ], + [ + -57, + -47 + ], + [ + -11, + -71 + ], + [ + -64, + -27 + ], + [ + -34, + -87 + ], + [ + 0, + -77 + ], + [ + -55, + -54 + ], + [ + -57, + -101 + ], + [ + 28, + -123 + ], + [ + -21, + -54 + ], + [ + -50, + 152 + ], + [ + -105, + 12 + ], + [ + -107, + -27 + ], + [ + -52, + -67 + ], + [ + -3, + -50 + ] + ], + [ + [ + 1596, + 3725 + ], + [ + -29, + 17 + ], + [ + -37, + 97 + ], + [ + -68, + 6 + ], + [ + -40, + 70 + ], + [ + -87, + -13 + ], + [ + -73, + 38 + ], + [ + -45, + 0 + ] + ], + [ + [ + 1217, + 3940 + ], + [ + -63, + 62 + ], + [ + -65, + 145 + ], + [ + -16, + 122 + ], + [ + 13, + 89 + ], + [ + -16, + 86 + ], + [ + 36, + 26 + ] + ], + [ + [ + 5174, + 4477 + ], + [ + -42, + -71 + ], + [ + -101, + -67 + ], + [ + 6, + -83 + ] + ], + [ + [ + 5037, + 4256 + ], + [ + -117, + 31 + ], + [ + -63, + -34 + ] + ], + [ + [ + 4857, + 4253 + ], + [ + -82, + -35 + ], + [ + -35, + 82 + ], + [ + -56, + -7 + ], + [ + -68, + 67 + ], + [ + -50, + -19 + ], + [ + 1, + -118 + ] + ], + [ + [ + 4567, + 4223 + ], + [ + -67, + 15 + ] + ], + [ + [ + 4500, + 4238 + ], + [ + -32, + 72 + ], + [ + 42, + 40 + ], + [ + 0, + 51 + ], + [ + -76, + -15 + ] + ], + [ + [ + 4434, + 4386 + ], + [ + -51, + 64 + ], + [ + 21, + 67 + ], + [ + 62, + 40 + ], + [ + 96, + -35 + ], + [ + 82, + 43 + ], + [ + 28, + 66 + ], + [ + 73, + 11 + ], + [ + 75, + 33 + ], + [ + 103, + -59 + ], + [ + 41, + 20 + ], + [ + 68, + -106 + ], + [ + 65, + 6 + ], + [ + 77, + -59 + ] + ], + [ + [ + 4857, + 4253 + ], + [ + 1, + -65 + ] + ], + [ + [ + 4858, + 4188 + ], + [ + -33, + 16 + ], + [ + -29, + -115 + ] + ], + [ + [ + 4796, + 4089 + ], + [ + -25, + 7 + ] + ], + [ + [ + 4771, + 4096 + ], + [ + -125, + 130 + ], + [ + -28, + 43 + ], + [ + -51, + -46 + ] + ], + [ + [ + 6212, + 2811 + ], + [ + 70, + -41 + ], + [ + 100, + -210 + ], + [ + -36, + 8 + ], + [ + -36, + 67 + ], + [ + -25, + 14 + ], + [ + -41, + -55 + ], + [ + -31, + 7 + ] + ], + [ + [ + 6213, + 2601 + ], + [ + -1, + 210 + ] + ], + [ + [ + 6213, + 2601 + ], + [ + -46, + 58 + ], + [ + -14, + 62 + ], + [ + -115, + 82 + ], + [ + 7, + 79 + ], + [ + 31, + -13 + ], + [ + 9, + -64 + ], + [ + 76, + 34 + ], + [ + 51, + -28 + ] + ], + [ + [ + 5902, + 2608 + ], + [ + 2, + -16 + ] + ], + [ + [ + 5904, + 2592 + ], + [ + -2, + 16 + ] + ], + [ + [ + 5765, + 3027 + ], + [ + -7, + -159 + ], + [ + -30, + -91 + ], + [ + -111, + 23 + ], + [ + -22, + 79 + ], + [ + 11, + 80 + ] + ], + [ + [ + 5606, + 2959 + ], + [ + 16, + -40 + ], + [ + 80, + 21 + ], + [ + 24, + 93 + ], + [ + 39, + -6 + ] + ], + [ + [ + 5862, + 2922 + ], + [ + -53, + -20 + ], + [ + 58, + -158 + ], + [ + -55, + 56 + ], + [ + -30, + 4 + ], + [ + 25, + 108 + ], + [ + 55, + 10 + ] + ], + [ + [ + 5583, + 2688 + ], + [ + 80, + -17 + ], + [ + 16, + -45 + ], + [ + -100, + 18 + ], + [ + 4, + 44 + ] + ], + [ + [ + 5503, + 2859 + ], + [ + 34, + -63 + ], + [ + -6, + -90 + ], + [ + -21, + -1 + ], + [ + -41, + 53 + ], + [ + -77, + 195 + ], + [ + -63, + 101 + ], + [ + 41, + 9 + ], + [ + 61, + -101 + ], + [ + 20, + -1 + ], + [ + 52, + -102 + ] + ], + [ + [ + 2155, + 1202 + ], + [ + 33, + -73 + ] + ], + [ + [ + 2188, + 1129 + ], + [ + -33, + 73 + ] + ], + [ + [ + 2368, + 1923 + ], + [ + -15, + -119 + ] + ], + [ + [ + 2353, + 1804 + ], + [ + 31, + -96 + ], + [ + -47, + -59 + ], + [ + -60, + -3 + ], + [ + 4, + -60 + ], + [ + -58, + -12 + ], + [ + 15, + -59 + ], + [ + -23, + -69 + ], + [ + -2, + -71 + ], + [ + -68, + -112 + ], + [ + 11, + -51 + ] + ], + [ + [ + 2156, + 1212 + ], + [ + -64, + 10 + ], + [ + -28, + 52 + ], + [ + 35, + 155 + ], + [ + -12, + 106 + ], + [ + 20, + 180 + ], + [ + 25, + 80 + ], + [ + -14, + 91 + ], + [ + 17, + 93 + ], + [ + 27, + 50 + ], + [ + -3, + 77 + ], + [ + 26, + 57 + ] + ], + [ + [ + 2185, + 2163 + ], + [ + 16, + 29 + ], + [ + 69, + -13 + ] + ], + [ + [ + 2270, + 2179 + ], + [ + 36, + -53 + ], + [ + 59, + -41 + ], + [ + -16, + -63 + ], + [ + 41, + -14 + ], + [ + 36, + 58 + ] + ], + [ + [ + 2426, + 2066 + ], + [ + 19, + -38 + ], + [ + -77, + -105 + ] + ], + [ + [ + 2188, + 1129 + ], + [ + -79, + -5 + ], + [ + 46, + 78 + ] + ], + [ + [ + 2137, + 2329 + ], + [ + 16, + -90 + ], + [ + 32, + -76 + ] + ], + [ + [ + 2156, + 1212 + ], + [ + -77, + -39 + ], + [ + -46, + 41 + ], + [ + -13, + 180 + ], + [ + 18, + 29 + ], + [ + 30, + 277 + ], + [ + 33, + 152 + ], + [ + -1, + 114 + ], + [ + 11, + 39 + ], + [ + 16, + 201 + ], + [ + -5, + 98 + ] + ], + [ + [ + 2122, + 2304 + ], + [ + 15, + 25 + ] + ], + [ + [ + 4078, + 2626 + ], + [ + -38, + -6 + ], + [ + -12, + -120 + ], + [ + -82, + 43 + ] + ], + [ + [ + 3946, + 2543 + ], + [ + -34, + -5 + ], + [ + -8, + 122 + ], + [ + -45, + 4 + ], + [ + -37, + -29 + ], + [ + -23, + 70 + ], + [ + -77, + -7 + ] + ], + [ + [ + 3722, + 2698 + ], + [ + -3, + 10 + ] + ], + [ + [ + 3719, + 2708 + ], + [ + 16, + 32 + ] + ], + [ + [ + 3735, + 2740 + ], + [ + 31, + -6 + ], + [ + 27, + 47 + ], + [ + 30, + 89 + ], + [ + 18, + 137 + ] + ], + [ + [ + 3841, + 3007 + ], + [ + 19, + 49 + ], + [ + 57, + -32 + ], + [ + 39, + 34 + ], + [ + 57, + 5 + ] + ], + [ + [ + 4013, + 3063 + ], + [ + 46, + -21 + ], + [ + 21, + -35 + ] + ], + [ + [ + 4080, + 3007 + ], + [ + -24, + -156 + ] + ], + [ + [ + 4056, + 2851 + ], + [ + -11, + -48 + ] + ], + [ + [ + 4045, + 2803 + ], + [ + 6, + -54 + ] + ], + [ + [ + 4288, + 2840 + ], + [ + -11, + 27 + ], + [ + 0, + 117 + ], + [ + 17, + 36 + ] + ], + [ + [ + 4294, + 3020 + ], + [ + 60, + 35 + ], + [ + 54, + 97 + ] + ], + [ + [ + 4408, + 3152 + ], + [ + 23, + 46 + ], + [ + 0, + 63 + ] + ], + [ + [ + 4431, + 3261 + ], + [ + 40, + -25 + ], + [ + -30, + -123 + ], + [ + -56, + -127 + ], + [ + -67, + -82 + ], + [ + -30, + -64 + ] + ], + [ + [ + 4140, + 2864 + ], + [ + 22, + 91 + ], + [ + -20, + 76 + ] + ], + [ + [ + 4142, + 3031 + ], + [ + 25, + 40 + ] + ], + [ + [ + 4167, + 3071 + ], + [ + 16, + -34 + ], + [ + 66, + -33 + ], + [ + 45, + 16 + ] + ], + [ + [ + 4288, + 2840 + ], + [ + -25, + -29 + ], + [ + -21, + -67 + ] + ], + [ + [ + 3959, + 3159 + ], + [ + -22, + 23 + ], + [ + -11, + 71 + ] + ], + [ + [ + 3926, + 3253 + ], + [ + -16, + 58 + ], + [ + 36, + 85 + ], + [ + -1, + 128 + ] + ], + [ + [ + 3945, + 3524 + ], + [ + 22, + 78 + ] + ], + [ + [ + 3967, + 3602 + ], + [ + 78, + 0 + ], + [ + 152, + 0 + ] + ], + [ + [ + 4197, + 3602 + ], + [ + 12, + -109 + ], + [ + 18, + -20 + ] + ], + [ + [ + 4227, + 3473 + ], + [ + -30, + -34 + ], + [ + -8, + -81 + ] + ], + [ + [ + 4189, + 3358 + ], + [ + -11, + -59 + ], + [ + -32, + -63 + ], + [ + -5, + -63 + ] + ], + [ + [ + 4141, + 3173 + ], + [ + -15, + 113 + ], + [ + -36, + -76 + ], + [ + -94, + -9 + ], + [ + -37, + -42 + ] + ], + [ + [ + 3926, + 3253 + ], + [ + -36, + -54 + ], + [ + -59, + -51 + ], + [ + -52, + -15 + ] + ], + [ + [ + 3779, + 3133 + ], + [ + -25, + 68 + ], + [ + 18, + 43 + ], + [ + -8, + 64 + ] + ], + [ + [ + 3764, + 3308 + ], + [ + -18, + 48 + ], + [ + 33, + 73 + ], + [ + 12, + 121 + ], + [ + -20, + 79 + ] + ], + [ + [ + 3771, + 3629 + ], + [ + 19, + 18 + ], + [ + 155, + -123 + ] + ], + [ + [ + 2096, + 3528 + ], + [ + 0, + -54 + ] + ], + [ + [ + 2096, + 3474 + ], + [ + -19, + 13 + ], + [ + 19, + 41 + ] + ], + [ + [ + 2096, + 3528 + ], + [ + 17, + 6 + ], + [ + 48, + -41 + ], + [ + -65, + -19 + ] + ], + [ + [ + 4434, + 4386 + ], + [ + -47, + -57 + ], + [ + 37, + -90 + ] + ], + [ + [ + 4424, + 4239 + ], + [ + -42, + 1 + ] + ], + [ + [ + 4382, + 4240 + ], + [ + -19, + 21 + ], + [ + -106, + 30 + ] + ], + [ + [ + 4257, + 4291 + ], + [ + -47, + 39 + ], + [ + 13, + 79 + ] + ], + [ + [ + 4223, + 4409 + ], + [ + 36, + 80 + ], + [ + -91, + 32 + ], + [ + -31, + 56 + ], + [ + -38, + -7 + ] + ], + [ + [ + 4099, + 4570 + ], + [ + -18, + 111 + ], + [ + -52, + 19 + ] + ], + [ + [ + 4029, + 4700 + ], + [ + -17, + 42 + ] + ], + [ + [ + 4012, + 4742 + ], + [ + 13, + 65 + ] + ], + [ + [ + 4025, + 4807 + ], + [ + 2, + 33 + ] + ], + [ + [ + 4027, + 4840 + ], + [ + 59, + 59 + ], + [ + -31, + 84 + ], + [ + -18, + 132 + ] + ], + [ + [ + 4037, + 5115 + ], + [ + 48, + 16 + ] + ], + [ + [ + 4085, + 5131 + ], + [ + 105, + -16 + ], + [ + 89, + -73 + ], + [ + -122, + -29 + ], + [ + 3, + -47 + ], + [ + 174, + 53 + ], + [ + 189, + 89 + ], + [ + 70, + -12 + ], + [ + 119, + 35 + ], + [ + 125, + 112 + ], + [ + 188, + -23 + ], + [ + 17, + 43 + ], + [ + 356, + 90 + ], + [ + 105, + 40 + ], + [ + 130, + -32 + ], + [ + 56, + -100 + ], + [ + 252, + -1 + ], + [ + 29, + -51 + ], + [ + 220, + -16 + ], + [ + 12, + 44 + ], + [ + 320, + -59 + ], + [ + 76, + -51 + ], + [ + 286, + 14 + ], + [ + 83, + -29 + ], + [ + 0, + -128 + ], + [ + -12, + -64 + ], + [ + -168, + -86 + ], + [ + -139, + -15 + ], + [ + -27, + -161 + ], + [ + -103, + -123 + ], + [ + -26, + 140 + ], + [ + 56, + 86 + ], + [ + 34, + 80 + ], + [ + -66, + 29 + ], + [ + -105, + -86 + ], + [ + -176, + 9 + ], + [ + -136, + -139 + ], + [ + 92, + -17 + ], + [ + 28, + -36 + ], + [ + -25, + -149 + ], + [ + -36, + -69 + ], + [ + -64, + -93 + ], + [ + -80, + -38 + ] + ], + [ + [ + 6014, + 4252 + ], + [ + -2, + 6 + ] + ], + [ + [ + 6012, + 4258 + ], + [ + 7, + 82 + ], + [ + 40, + 6 + ], + [ + 38, + 107 + ], + [ + -79, + -22 + ], + [ + -64, + 63 + ], + [ + -33, + 98 + ], + [ + -96, + 15 + ], + [ + -5, + -42 + ], + [ + -55, + -79 + ], + [ + -23, + 12 + ] + ], + [ + [ + 5742, + 4498 + ], + [ + -45, + 12 + ], + [ + -72, + -36 + ], + [ + -73, + 37 + ], + [ + -62, + -6 + ], + [ + -93, + 63 + ], + [ + -31, + -75 + ], + [ + -98, + 35 + ], + [ + -86, + -49 + ] + ], + [ + [ + 5182, + 4479 + ], + [ + -8, + -2 + ] + ], + [ + [ + 3923, + 4641 + ], + [ + -59, + 3 + ] + ], + [ + [ + 3864, + 4644 + ], + [ + 31, + 25 + ] + ], + [ + [ + 3895, + 4669 + ], + [ + 28, + -28 + ] + ], + [ + [ + 98, + 5055 + ], + [ + 60, + -9 + ], + [ + -40, + -85 + ], + [ + -86, + 36 + ], + [ + -32, + -13 + ], + [ + 0, + 128 + ], + [ + 98, + -57 + ] + ], + [ + [ + 4131, + 4373 + ], + [ + 30, + -8 + ] + ], + [ + [ + 4161, + 4365 + ], + [ + -30, + 8 + ] + ], + [ + [ + 1970, + 3705 + ], + [ + 6, + -1 + ], + [ + 7, + -27 + ], + [ + -17, + 7 + ], + [ + 4, + 21 + ] + ], + [ + [ + 2299, + 1227 + ], + [ + 23, + 19 + ], + [ + 38, + -21 + ], + [ + -51, + -13 + ], + [ + -10, + 15 + ] + ], + [ + [ + 4037, + 5115 + ], + [ + -154, + 1 + ] + ], + [ + [ + 3883, + 5116 + ], + [ + -75, + -35 + ], + [ + -94, + -157 + ], + [ + 14, + -59 + ], + [ + -31, + -78 + ] + ], + [ + [ + 3697, + 4787 + ], + [ + -104, + -9 + ], + [ + -13, + 109 + ], + [ + 107, + 81 + ], + [ + 168, + 171 + ], + [ + 174, + 44 + ], + [ + 56, + -52 + ] + ], + [ + [ + 2578, + 5551 + ], + [ + 381, + 29 + ], + [ + 288, + -72 + ], + [ + -145, + -81 + ], + [ + 7, + -144 + ], + [ + -79, + -71 + ], + [ + 21, + -63 + ], + [ + -104, + -53 + ], + [ + -98, + -24 + ], + [ + -69, + -56 + ], + [ + -67, + -17 + ], + [ + -69, + -172 + ], + [ + -95, + 24 + ], + [ + -65, + 89 + ], + [ + -45, + 115 + ], + [ + -1, + 140 + ], + [ + -88, + 128 + ], + [ + -192, + 17 + ], + [ + -90, + 76 + ], + [ + 203, + 108 + ], + [ + 307, + 27 + ] + ], + [ + [ + 4818, + 1331 + ], + [ + 30, + -15 + ], + [ + -4, + -20 + ], + [ + -30, + -2 + ], + [ + 4, + 37 + ] + ], + [ + [ + 5902, + 2608 + ], + [ + 32, + 16 + ], + [ + 7, + -9 + ], + [ + -37, + -23 + ] + ], + [ + [ + 3800, + 1975 + ], + [ + 69, + 4 + ], + [ + 0, + 119 + ] + ], + [ + [ + 3869, + 2098 + ], + [ + 33, + -63 + ], + [ + 33, + 47 + ], + [ + 45, + -7 + ], + [ + 28, + 61 + ], + [ + 45, + 48 + ] + ], + [ + [ + 4053, + 2184 + ], + [ + 34, + -5 + ] + ], + [ + [ + 4087, + 2179 + ], + [ + 13, + -116 + ] + ], + [ + [ + 4100, + 2063 + ], + [ + -16, + 4 + ], + [ + -7, + -33 + ], + [ + 27, + 0 + ] + ], + [ + [ + 4104, + 2034 + ], + [ + 15, + 0 + ] + ], + [ + [ + 4119, + 2034 + ], + [ + -7, + -50 + ], + [ + -82, + -144 + ], + [ + -48, + -37 + ], + [ + -62, + 2 + ], + [ + -57, + -31 + ], + [ + -26, + 31 + ], + [ + -1, + 71 + ], + [ + -36, + 99 + ] + ], + [ + [ + 4044, + 1963 + ], + [ + -38, + -30 + ], + [ + 15, + -24 + ], + [ + 21, + 18 + ], + [ + 2, + 36 + ] + ], + [ + [ + 1596, + 3725 + ], + [ + -7, + -109 + ], + [ + 39, + -116 + ], + [ + 28, + -22 + ], + [ + 71, + 36 + ], + [ + 9, + 56 + ], + [ + 63, + 17 + ], + [ + -24, + -98 + ] + ], + [ + [ + 1775, + 3489 + ], + [ + -17, + -22 + ] + ], + [ + [ + 1758, + 3467 + ], + [ + -36, + 0 + ], + [ + -23, + -105 + ] + ], + [ + [ + 1699, + 3362 + ], + [ + -48, + 53 + ], + [ + -36, + -17 + ], + [ + -83, + 48 + ], + [ + -80, + 69 + ], + [ + -20, + 112 + ], + [ + -64, + 118 + ], + [ + -56, + 80 + ], + [ + -18, + 72 + ], + [ + -30, + -33 + ], + [ + 59, + -112 + ], + [ + -55, + 15 + ], + [ + -51, + 173 + ] + ], + [ + [ + 2368, + 1923 + ], + [ + 75, + -59 + ], + [ + 8, + -56 + ] + ], + [ + [ + 2451, + 1808 + ], + [ + -31, + -38 + ], + [ + -67, + 34 + ] + ], + [ + [ + 2426, + 2066 + ], + [ + -19, + 100 + ], + [ + -45, + 18 + ], + [ + -4, + 61 + ] + ], + [ + [ + 2358, + 2245 + ], + [ + 13, + 65 + ], + [ + -15, + 60 + ], + [ + -37, + 1 + ], + [ + -6, + 80 + ], + [ + -95, + 71 + ], + [ + 1, + 58 + ], + [ + -81, + -38 + ] + ], + [ + [ + 2138, + 2542 + ], + [ + -51, + 29 + ], + [ + -35, + 81 + ], + [ + 21, + 73 + ], + [ + 58, + 31 + ] + ], + [ + [ + 2131, + 2756 + ], + [ + 9, + 88 + ], + [ + -8, + 105 + ], + [ + 57, + -14 + ] + ], + [ + [ + 2189, + 2935 + ], + [ + 52, + 7 + ], + [ + -3, + 74 + ], + [ + 70, + 45 + ] + ], + [ + [ + 2308, + 3061 + ], + [ + 23, + -39 + ], + [ + 10, + -85 + ], + [ + 48, + 18 + ] + ], + [ + [ + 2389, + 2955 + ], + [ + 39, + 14 + ] + ], + [ + [ + 2428, + 2969 + ], + [ + 31, + -6 + ], + [ + 25, + 65 + ] + ], + [ + [ + 2484, + 3028 + ], + [ + 33, + -100 + ], + [ + 26, + -41 + ], + [ + 138, + -86 + ], + [ + 29, + 1 + ], + [ + 53, + -63 + ], + [ + 39, + -21 + ], + [ + 2, + -113 + ], + [ + -74, + -154 + ], + [ + 1, + -61 + ], + [ + -17, + -126 + ], + [ + -43, + -108 + ], + [ + -87, + -36 + ], + [ + -39, + -58 + ], + [ + -8, + -90 + ], + [ + -86, + -164 + ] + ], + [ + [ + 2358, + 2245 + ], + [ + -19, + 27 + ], + [ + -51, + -9 + ], + [ + -18, + -84 + ] + ], + [ + [ + 2137, + 2329 + ], + [ + 18, + 161 + ], + [ + -17, + 52 + ] + ], + [ + [ + 2122, + 2304 + ], + [ + -109, + 119 + ], + [ + -73, + 240 + ], + [ + -29, + 34 + ], + [ + 18, + 88 + ] + ], + [ + [ + 1929, + 2785 + ], + [ + 33, + -37 + ], + [ + 15, + 50 + ], + [ + 44, + 46 + ], + [ + 4, + 45 + ] + ], + [ + [ + 2025, + 2889 + ], + [ + 44, + -69 + ], + [ + 44, + 2 + ], + [ + 18, + -66 + ] + ], + [ + [ + 2025, + 2889 + ], + [ + -68, + 50 + ] + ], + [ + [ + 1957, + 2939 + ], + [ + 34, + 79 + ], + [ + -15, + 108 + ] + ], + [ + [ + 1976, + 3126 + ], + [ + 10, + 47 + ] + ], + [ + [ + 1986, + 3173 + ], + [ + 37, + 63 + ], + [ + 80, + 37 + ] + ], + [ + [ + 2103, + 3273 + ], + [ + -30, + -43 + ], + [ + 18, + -111 + ], + [ + 50, + -29 + ], + [ + 30, + -51 + ], + [ + 18, + -104 + ] + ], + [ + [ + 1976, + 3126 + ], + [ + -24, + 57 + ], + [ + -26, + -29 + ], + [ + -48, + 5 + ] + ], + [ + [ + 1878, + 3159 + ], + [ + 8, + 43 + ] + ], + [ + [ + 1886, + 3202 + ], + [ + 21, + -25 + ], + [ + 37, + 26 + ], + [ + 42, + -30 + ] + ], + [ + [ + 1878, + 3159 + ], + [ + -55, + 61 + ], + [ + 2, + 31 + ] + ], + [ + [ + 1825, + 3251 + ], + [ + 40, + -5 + ] + ], + [ + [ + 1865, + 3246 + ], + [ + 21, + -44 + ] + ], + [ + [ + 1825, + 3251 + ], + [ + -31, + 61 + ] + ], + [ + [ + 1794, + 3312 + ], + [ + 46, + 58 + ], + [ + 34, + 6 + ] + ], + [ + [ + 1874, + 3376 + ], + [ + -9, + -130 + ] + ], + [ + [ + 1794, + 3312 + ], + [ + -10, + 13 + ] + ], + [ + [ + 1784, + 3325 + ], + [ + -30, + 33 + ] + ], + [ + [ + 1754, + 3358 + ], + [ + 22, + 42 + ] + ], + [ + [ + 1776, + 3400 + ], + [ + 75, + 3 + ], + [ + 23, + -27 + ] + ], + [ + [ + 1784, + 3325 + ], + [ + -44, + 11 + ] + ], + [ + [ + 1740, + 3336 + ], + [ + 14, + 22 + ] + ], + [ + [ + 1758, + 3467 + ], + [ + 4, + -62 + ] + ], + [ + [ + 1762, + 3405 + ], + [ + 14, + -5 + ] + ], + [ + [ + 1740, + 3336 + ], + [ + -41, + 26 + ] + ], + [ + [ + 1775, + 3489 + ], + [ + -13, + -84 + ] + ], + [ + [ + 2103, + 3273 + ], + [ + 61, + -39 + ], + [ + 105, + -5 + ], + [ + 58, + -66 + ] + ], + [ + [ + 2327, + 3163 + ], + [ + -32, + -77 + ], + [ + 13, + -25 + ] + ], + [ + [ + 2327, + 3163 + ], + [ + 51, + -77 + ] + ], + [ + [ + 2378, + 3086 + ], + [ + -18, + -61 + ], + [ + 29, + -70 + ] + ], + [ + [ + 2378, + 3086 + ], + [ + 61, + -7 + ] + ], + [ + [ + 2439, + 3079 + ], + [ + -11, + -110 + ] + ], + [ + [ + 2439, + 3079 + ], + [ + 45, + -51 + ] + ], + [ + [ + 3603, + 4485 + ], + [ + 25, + -59 + ] + ], + [ + [ + 3628, + 4426 + ], + [ + -12, + -53 + ] + ], + [ + [ + 3616, + 4373 + ], + [ + 11, + -74 + ] + ], + [ + [ + 3627, + 4299 + ], + [ + -86, + -39 + ] + ], + [ + [ + 3541, + 4260 + ], + [ + -94, + 31 + ] + ], + [ + [ + 3447, + 4291 + ], + [ + 13, + 83 + ], + [ + -34, + 50 + ], + [ + 106, + 115 + ] + ], + [ + [ + 3532, + 4539 + ], + [ + 61, + -52 + ] + ], + [ + [ + 3593, + 4487 + ], + [ + 10, + -2 + ] + ], + [ + [ + 1929, + 2785 + ], + [ + -12, + 75 + ], + [ + 40, + 79 + ] + ], + [ + [ + 2201, + 3490 + ], + [ + 8, + -18 + ], + [ + -26, + -1 + ], + [ + 2, + 19 + ], + [ + 16, + 0 + ] + ], + [ + [ + 1982, + 3489 + ], + [ + 24, + -11 + ], + [ + -17, + -15 + ], + [ + -7, + 26 + ] + ], + [ + [ + 1891, + 3640 + ], + [ + 76, + -22 + ], + [ + 36, + -42 + ], + [ + -24, + -43 + ], + [ + -19, + 56 + ], + [ + -60, + 19 + ], + [ + -9, + 32 + ] + ], + [ + [ + 4053, + 2184 + ], + [ + -27, + 19 + ], + [ + -54, + 121 + ] + ], + [ + [ + 3972, + 2324 + ], + [ + 35, + -7 + ], + [ + 62, + 79 + ] + ], + [ + [ + 4069, + 2396 + ], + [ + 50, + -39 + ], + [ + -1, + -97 + ], + [ + -31, + -81 + ] + ], + [ + [ + 3869, + 2098 + ], + [ + 19, + 95 + ], + [ + 0, + 114 + ], + [ + 81, + 19 + ] + ], + [ + [ + 3969, + 2326 + ], + [ + 3, + -2 + ] + ], + [ + [ + 3800, + 1975 + ], + [ + -22, + 48 + ], + [ + -19, + 160 + ], + [ + -48, + 155 + ] + ], + [ + [ + 3711, + 2338 + ], + [ + 126, + 0 + ], + [ + 60, + -20 + ], + [ + 36, + 13 + ] + ], + [ + [ + 3933, + 2331 + ], + [ + 36, + -5 + ] + ], + [ + [ + 3160, + 3331 + ], + [ + 5, + 82 + ] + ], + [ + [ + 3165, + 3413 + ], + [ + 36, + 15 + ], + [ + 47, + -64 + ] + ], + [ + [ + 3248, + 3364 + ], + [ + 13, + -70 + ] + ], + [ + [ + 3261, + 3294 + ], + [ + -43, + 5 + ] + ], + [ + [ + 3218, + 3299 + ], + [ + -57, + -7 + ] + ], + [ + [ + 3161, + 3292 + ], + [ + -3, + 25 + ] + ], + [ + [ + 3158, + 3317 + ], + [ + 17, + -1 + ], + [ + 6, + 16 + ], + [ + -21, + -1 + ] + ], + [ + [ + 3248, + 3364 + ], + [ + 10, + 25 + ], + [ + 118, + 4 + ], + [ + -8, + 165 + ], + [ + -9, + 139 + ], + [ + 29, + 0 + ] + ], + [ + [ + 3388, + 3697 + ], + [ + 66, + -70 + ], + [ + 112, + -117 + ] + ], + [ + [ + 3566, + 3510 + ], + [ + -12, + -115 + ], + [ + -63, + -21 + ] + ], + [ + [ + 3491, + 3374 + ], + [ + -46, + -12 + ], + [ + -63, + -91 + ], + [ + -3, + -43 + ] + ], + [ + [ + 3379, + 3228 + ], + [ + -51, + -6 + ] + ], + [ + [ + 3328, + 3222 + ], + [ + -21, + 68 + ], + [ + -46, + 4 + ] + ], + [ + [ + 3315, + 3775 + ], + [ + 73, + -78 + ] + ], + [ + [ + 3165, + 3413 + ], + [ + 3, + 127 + ], + [ + -15, + 30 + ] + ], + [ + [ + 3536, + 3095 + ], + [ + -16, + -3 + ] + ], + [ + [ + 3520, + 3092 + ], + [ + -4, + 96 + ], + [ + -15, + 60 + ] + ], + [ + [ + 3501, + 3248 + ], + [ + 24, + 30 + ] + ], + [ + [ + 3525, + 3278 + ], + [ + 28, + -9 + ] + ], + [ + [ + 3553, + 3269 + ], + [ + -17, + -101 + ], + [ + 0, + -73 + ] + ], + [ + [ + 3764, + 3308 + ], + [ + -6, + -12 + ] + ], + [ + [ + 3758, + 3296 + ], + [ + -79, + 25 + ], + [ + -21, + -14 + ], + [ + -90, + 29 + ], + [ + -15, + -67 + ] + ], + [ + [ + 3525, + 3278 + ], + [ + -34, + 96 + ] + ], + [ + [ + 3566, + 3510 + ], + [ + 27, + 15 + ], + [ + 123, + 124 + ] + ], + [ + [ + 3716, + 3649 + ], + [ + 55, + -20 + ] + ], + [ + [ + 3758, + 3296 + ], + [ + -47, + -177 + ], + [ + -49, + -18 + ], + [ + -14, + -53 + ] + ], + [ + [ + 3648, + 3048 + ], + [ + -50, + -17 + ], + [ + -31, + 65 + ], + [ + -31, + -1 + ] + ], + [ + [ + 3779, + 3133 + ], + [ + -15, + -87 + ], + [ + 29, + -79 + ] + ], + [ + [ + 3793, + 2967 + ], + [ + -56, + 0 + ] + ], + [ + [ + 3737, + 2967 + ], + [ + -35, + 0 + ] + ], + [ + [ + 3702, + 2967 + ], + [ + -32, + 1 + ] + ], + [ + [ + 3670, + 2968 + ], + [ + -22, + 80 + ] + ], + [ + [ + 3520, + 3092 + ], + [ + -16, + -7 + ] + ], + [ + [ + 3504, + 3085 + ], + [ + -20, + 164 + ] + ], + [ + [ + 3484, + 3249 + ], + [ + 17, + -1 + ] + ], + [ + [ + 3504, + 3085 + ], + [ + -59, + -39 + ], + [ + -17, + 9 + ] + ], + [ + [ + 3428, + 3055 + ], + [ + -7, + 40 + ], + [ + 8, + 109 + ] + ], + [ + [ + 3429, + 3204 + ], + [ + -2, + 43 + ], + [ + 57, + 2 + ] + ], + [ + [ + 3379, + 3228 + ], + [ + 50, + -24 + ] + ], + [ + [ + 3428, + 3055 + ], + [ + -57, + 0 + ], + [ + -37, + -20 + ] + ], + [ + [ + 3334, + 3035 + ], + [ + -14, + 106 + ] + ], + [ + [ + 3320, + 3141 + ], + [ + 8, + 81 + ] + ], + [ + [ + 3320, + 3141 + ], + [ + -34, + 24 + ] + ], + [ + [ + 3286, + 3165 + ], + [ + -18, + 52 + ], + [ + -41, + -37 + ] + ], + [ + [ + 3227, + 3180 + ], + [ + -36, + 69 + ] + ], + [ + [ + 3191, + 3249 + ], + [ + 27, + 50 + ] + ], + [ + [ + 3191, + 3249 + ], + [ + -30, + 43 + ] + ], + [ + [ + 3334, + 3035 + ], + [ + -72, + 77 + ] + ], + [ + [ + 3262, + 3112 + ], + [ + 24, + 53 + ] + ], + [ + [ + 3262, + 3112 + ], + [ + -35, + 68 + ] + ], + [ + [ + 3841, + 3007 + ], + [ + -26, + 7 + ], + [ + -22, + -47 + ] + ], + [ + [ + 3959, + 3159 + ], + [ + 54, + -96 + ] + ], + [ + [ + 3735, + 2740 + ], + [ + -21, + -8 + ] + ], + [ + [ + 3714, + 2732 + ], + [ + -16, + 34 + ] + ], + [ + [ + 3698, + 2766 + ], + [ + 65, + 85 + ], + [ + -26, + 116 + ] + ], + [ + [ + 3698, + 2766 + ], + [ + -44, + 92 + ], + [ + 13, + 69 + ] + ], + [ + [ + 3667, + 2927 + ], + [ + 35, + 40 + ] + ], + [ + [ + 3667, + 2927 + ], + [ + 3, + 41 + ] + ], + [ + [ + 4117, + 2597 + ], + [ + 15, + -41 + ], + [ + -6, + -111 + ] + ], + [ + [ + 4126, + 2445 + ], + [ + -57, + -49 + ] + ], + [ + [ + 3933, + 2331 + ], + [ + -26, + 46 + ], + [ + 1, + 102 + ], + [ + 40, + 0 + ], + [ + -2, + 64 + ] + ], + [ + [ + 4152, + 2524 + ], + [ + -26, + -79 + ] + ], + [ + [ + 4264, + 2562 + ], + [ + 9, + -140 + ], + [ + -26, + -66 + ], + [ + -39, + -27 + ], + [ + -51, + -71 + ], + [ + 13, + -140 + ], + [ + -56, + -51 + ], + [ + 5, + -33 + ] + ], + [ + [ + 4104, + 2034 + ], + [ + -4, + 29 + ] + ], + [ + [ + 3711, + 2338 + ], + [ + 19, + 134 + ], + [ + 17, + 35 + ], + [ + -7, + 112 + ], + [ + -18, + 79 + ] + ], + [ + [ + 3719, + 2708 + ], + [ + -5, + 24 + ] + ], + [ + [ + 4045, + 2803 + ], + [ + 28, + 14 + ] + ], + [ + [ + 4175, + 3946 + ], + [ + -4, + -10 + ] + ], + [ + [ + 4171, + 3936 + ], + [ + -7, + 4 + ], + [ + -5, + -38 + ], + [ + 10, + 5 + ] + ], + [ + [ + 4169, + 3907 + ], + [ + -10, + -64 + ] + ], + [ + [ + 4159, + 3843 + ], + [ + -2, + 8 + ] + ], + [ + [ + 4157, + 3851 + ], + [ + -10, + 47 + ] + ], + [ + [ + 4147, + 3898 + ], + [ + 16, + 60 + ] + ], + [ + [ + 4163, + 3958 + ], + [ + 14, + 6 + ] + ], + [ + [ + 4177, + 3964 + ], + [ + -2, + -18 + ] + ], + [ + [ + 4163, + 3958 + ], + [ + 17, + 50 + ] + ], + [ + [ + 4180, + 4008 + ], + [ + -3, + -44 + ] + ], + [ + [ + 4442, + 2493 + ], + [ + 18, + -88 + ], + [ + -19, + -61 + ], + [ + -46, + -252 + ], + [ + -59, + -1 + ], + [ + -15, + 94 + ], + [ + 21, + 64 + ], + [ + -8, + 85 + ], + [ + 46, + 53 + ], + [ + 62, + 106 + ] + ], + [ + [ + 4171, + 3936 + ], + [ + -2, + -29 + ] + ], + [ + [ + 3158, + 3317 + ], + [ + 2, + 14 + ] + ], + [ + [ + 3667, + 3869 + ], + [ + -36, + 97 + ], + [ + 15, + 116 + ] + ], + [ + [ + 3646, + 4082 + ], + [ + 49, + -40 + ], + [ + -15, + -44 + ], + [ + 26, + -38 + ] + ], + [ + [ + 3706, + 3960 + ], + [ + -39, + -91 + ] + ], + [ + [ + 3316, + 3784 + ], + [ + 0, + 38 + ], + [ + 66, + 37 + ], + [ + 31, + 53 + ], + [ + 45, + 20 + ], + [ + -16, + 93 + ] + ], + [ + [ + 3442, + 4025 + ], + [ + 70, + 46 + ], + [ + 134, + 11 + ] + ], + [ + [ + 3667, + 3869 + ], + [ + 16, + -191 + ], + [ + 33, + -29 + ] + ], + [ + [ + 4175, + 3946 + ], + [ + 59, + 22 + ] + ], + [ + [ + 4234, + 3968 + ], + [ + 8, + -40 + ] + ], + [ + [ + 4242, + 3928 + ], + [ + -23, + -53 + ], + [ + -59, + -37 + ] + ], + [ + [ + 4160, + 3838 + ], + [ + -1, + 5 + ] + ], + [ + [ + 4482, + 3674 + ], + [ + 47, + -4 + ], + [ + 40, + 62 + ] + ], + [ + [ + 4569, + 3732 + ], + [ + 3, + -11 + ] + ], + [ + [ + 4572, + 3721 + ], + [ + 3, + -25 + ] + ], + [ + [ + 4575, + 3696 + ], + [ + -23, + -72 + ] + ], + [ + [ + 4552, + 3624 + ], + [ + -62, + 10 + ], + [ + -8, + 40 + ] + ], + [ + [ + 4467, + 3690 + ], + [ + 4, + 41 + ], + [ + 11, + -7 + ], + [ + -4, + -38 + ] + ], + [ + [ + 4478, + 3686 + ], + [ + -11, + 4 + ] + ], + [ + [ + 4412, + 3858 + ], + [ + 8, + -46 + ] + ], + [ + [ + 4420, + 3812 + ], + [ + -35, + 18 + ] + ], + [ + [ + 4385, + 3830 + ], + [ + 27, + 28 + ] + ], + [ + [ + 4234, + 3968 + ], + [ + 43, + 33 + ], + [ + 26, + 90 + ] + ], + [ + [ + 4303, + 4091 + ], + [ + 47, + -1 + ] + ], + [ + [ + 4350, + 4090 + ], + [ + 25, + -48 + ], + [ + -13, + -55 + ], + [ + 38, + -49 + ], + [ + 23, + -81 + ] + ], + [ + [ + 4423, + 3857 + ], + [ + -11, + 1 + ] + ], + [ + [ + 4385, + 3830 + ], + [ + -36, + 3 + ], + [ + -55, + 64 + ], + [ + -52, + 31 + ] + ], + [ + [ + 4569, + 3732 + ], + [ + 3, + -11 + ] + ], + [ + [ + 4575, + 3696 + ], + [ + 66, + -84 + ], + [ + -39, + -105 + ], + [ + -49, + -59 + ], + [ + -42, + -18 + ] + ], + [ + [ + 4511, + 3430 + ], + [ + -21, + 75 + ] + ], + [ + [ + 4490, + 3505 + ], + [ + 58, + 32 + ], + [ + 4, + 87 + ] + ], + [ + [ + 6711, + 2390 + ], + [ + -3, + 34 + ], + [ + 9, + -10 + ], + [ + 4, + -26 + ], + [ + -10, + 2 + ] + ], + [ + [ + 5469, + 3286 + ], + [ + 8, + 66 + ], + [ + 43, + 1 + ] + ], + [ + [ + 5520, + 3353 + ], + [ + 42, + -2 + ] + ], + [ + [ + 5562, + 3351 + ], + [ + 2, + -60 + ], + [ + -61, + -60 + ] + ], + [ + [ + 5503, + 3231 + ], + [ + -34, + 55 + ] + ], + [ + [ + 5469, + 3286 + ], + [ + -31, + 40 + ], + [ + -36, + -111 + ], + [ + 26, + -82 + ], + [ + 32, + -39 + ] + ], + [ + [ + 5460, + 3094 + ], + [ + -40, + 8 + ] + ], + [ + [ + 5420, + 3102 + ], + [ + -30, + 62 + ], + [ + 1, + 50 + ] + ], + [ + [ + 5391, + 3214 + ], + [ + 20, + 63 + ], + [ + -23, + 87 + ], + [ + 10, + 50 + ], + [ + -21, + 45 + ], + [ + 8, + 69 + ], + [ + 36, + 23 + ] + ], + [ + [ + 5421, + 3551 + ], + [ + 39, + -74 + ], + [ + 35, + 4 + ], + [ + 32, + -86 + ], + [ + -7, + -42 + ] + ], + [ + [ + 5421, + 3551 + ], + [ + 21, + 33 + ] + ], + [ + [ + 5442, + 3584 + ], + [ + 19, + 33 + ] + ], + [ + [ + 5461, + 3617 + ], + [ + 44, + -55 + ], + [ + 12, + -68 + ], + [ + 48, + -111 + ], + [ + -3, + -32 + ] + ], + [ + [ + 5391, + 3214 + ], + [ + 4, + 48 + ], + [ + -31, + 177 + ], + [ + -58, + -29 + ], + [ + 3, + 70 + ], + [ + -38, + 79 + ] + ], + [ + [ + 5271, + 3559 + ], + [ + 6, + 44 + ] + ], + [ + [ + 5277, + 3603 + ], + [ + 28, + 58 + ], + [ + 19, + 88 + ], + [ + 43, + 54 + ] + ], + [ + [ + 5367, + 3803 + ], + [ + 26, + -24 + ], + [ + 0, + -111 + ], + [ + 11, + -63 + ], + [ + 38, + -21 + ] + ], + [ + [ + 5461, + 3617 + ], + [ + 61, + 28 + ], + [ + 53, + -58 + ] + ], + [ + [ + 5575, + 3587 + ], + [ + -47, + -80 + ], + [ + 63, + -122 + ], + [ + 6, + -116 + ], + [ + -78, + -98 + ], + [ + -16, + 60 + ] + ], + [ + [ + 6014, + 4252 + ], + [ + -62, + -79 + ], + [ + 15, + -37 + ] + ], + [ + [ + 5967, + 4136 + ], + [ + -42, + -28 + ] + ], + [ + [ + 5925, + 4108 + ], + [ + -37, + 70 + ] + ], + [ + [ + 5888, + 4178 + ], + [ + 51, + 61 + ], + [ + 73, + 19 + ] + ], + [ + [ + 5967, + 4136 + ], + [ + 22, + -59 + ], + [ + -7, + -55 + ], + [ + -51, + -22 + ], + [ + -6, + 108 + ] + ], + [ + [ + 5742, + 4498 + ], + [ + -24, + -56 + ], + [ + 38, + -47 + ], + [ + -158, + -133 + ], + [ + -83, + -30 + ], + [ + -61, + 29 + ], + [ + -106, + 7 + ], + [ + -20, + 49 + ], + [ + -84, + 33 + ], + [ + 0, + 52 + ], + [ + -62, + 77 + ] + ], + [ + [ + 5277, + 3603 + ], + [ + -15, + 67 + ], + [ + -38, + 37 + ], + [ + -36, + -25 + ], + [ + 19, + -79 + ] + ], + [ + [ + 5207, + 3603 + ], + [ + -40, + -18 + ], + [ + -9, + -43 + ], + [ + -120, + -137 + ], + [ + -9, + -178 + ], + [ + -45, + -77 + ], + [ + -18, + 30 + ], + [ + -59, + 228 + ], + [ + -18, + 173 + ], + [ + -42, + -15 + ], + [ + -44, + 90 + ] + ], + [ + [ + 4803, + 3656 + ], + [ + 55, + 21 + ], + [ + -17, + 69 + ], + [ + 83, + 144 + ], + [ + -4, + 122 + ], + [ + 70, + 24 + ] + ], + [ + [ + 4990, + 4036 + ], + [ + 21, + -38 + ], + [ + -4, + -90 + ], + [ + 46, + -43 + ] + ], + [ + [ + 5053, + 3865 + ], + [ + -20, + -45 + ], + [ + 100, + -66 + ], + [ + 55, + -10 + ], + [ + 1, + 47 + ] + ], + [ + [ + 5189, + 3791 + ], + [ + 13, + -19 + ] + ], + [ + [ + 5202, + 3772 + ], + [ + 56, + 15 + ] + ], + [ + [ + 5258, + 3787 + ], + [ + 56, + 49 + ], + [ + 53, + -33 + ] + ], + [ + [ + 5271, + 3559 + ], + [ + -18, + 67 + ], + [ + -46, + -23 + ] + ], + [ + [ + 5202, + 3772 + ], + [ + 24, + 32 + ], + [ + 32, + -17 + ] + ], + [ + [ + 5053, + 3865 + ], + [ + 91, + -64 + ], + [ + 45, + -10 + ] + ], + [ + [ + 4803, + 3656 + ], + [ + -35, + 56 + ], + [ + -94, + -11 + ] + ], + [ + [ + 4674, + 3701 + ], + [ + 35, + 54 + ], + [ + -47, + 98 + ] + ], + [ + [ + 4662, + 3853 + ], + [ + 32, + -16 + ], + [ + 73, + 18 + ], + [ + 12, + 46 + ], + [ + 38, + 10 + ], + [ + 38, + 76 + ], + [ + 19, + 81 + ], + [ + 64, + 20 + ] + ], + [ + [ + 4938, + 4088 + ], + [ + 52, + -52 + ] + ], + [ + [ + 4796, + 4089 + ], + [ + 72, + 24 + ], + [ + 67, + -15 + ] + ], + [ + [ + 4935, + 4098 + ], + [ + 3, + -10 + ] + ], + [ + [ + 4662, + 3853 + ], + [ + -7, + 124 + ], + [ + 13, + 64 + ] + ], + [ + [ + 4668, + 4041 + ], + [ + 20, + -13 + ], + [ + 83, + 68 + ] + ], + [ + [ + 4858, + 4188 + ], + [ + 51, + -26 + ] + ], + [ + [ + 4909, + 4162 + ], + [ + 26, + -64 + ] + ], + [ + [ + 5037, + 4256 + ], + [ + -128, + -94 + ] + ], + [ + [ + 4668, + 4041 + ], + [ + -38, + 56 + ], + [ + -72, + 18 + ], + [ + -31, + -25 + ] + ], + [ + [ + 4527, + 4090 + ], + [ + -1, + 57 + ], + [ + -26, + 91 + ] + ], + [ + [ + 4350, + 4090 + ], + [ + 0, + 81 + ] + ], + [ + [ + 4350, + 4171 + ], + [ + 27, + -31 + ] + ], + [ + [ + 4377, + 4140 + ], + [ + 7, + 1 + ] + ], + [ + [ + 4384, + 4141 + ], + [ + 46, + -15 + ] + ], + [ + [ + 4430, + 4126 + ], + [ + 65, + -52 + ], + [ + 32, + 16 + ] + ], + [ + [ + 4674, + 3701 + ], + [ + -80, + 21 + ], + [ + -17, + 45 + ], + [ + -35, + -21 + ], + [ + -61, + 44 + ], + [ + -28, + 74 + ], + [ + -30, + -7 + ] + ], + [ + [ + 4180, + 4008 + ], + [ + 3, + 38 + ] + ], + [ + [ + 4183, + 4046 + ], + [ + 18, + 26 + ], + [ + 102, + 19 + ] + ], + [ + [ + 4377, + 4140 + ], + [ + -27, + 31 + ] + ], + [ + [ + 4350, + 4171 + ], + [ + -23, + 45 + ] + ], + [ + [ + 4327, + 4216 + ], + [ + 27, + 5 + ] + ], + [ + [ + 4354, + 4221 + ], + [ + 30, + -80 + ] + ], + [ + [ + 3883, + 5116 + ], + [ + 63, + -99 + ] + ], + [ + [ + 3946, + 5017 + ], + [ + -117, + -105 + ], + [ + 18, + -86 + ], + [ + -38, + -44 + ], + [ + -18, + -84 + ], + [ + -57, + -23 + ], + [ + -37, + 112 + ] + ], + [ + [ + 4099, + 4570 + ], + [ + -49, + -24 + ], + [ + -111, + 7 + ] + ], + [ + [ + 3939, + 4553 + ], + [ + -1, + 75 + ] + ], + [ + [ + 3938, + 4628 + ], + [ + 58, + 55 + ] + ], + [ + [ + 3996, + 4683 + ], + [ + 33, + 17 + ] + ], + [ + [ + 4223, + 4409 + ], + [ + -62, + -44 + ] + ], + [ + [ + 4131, + 4373 + ], + [ + -52, + 19 + ], + [ + -23, + -41 + ] + ], + [ + [ + 4056, + 4351 + ], + [ + -26, + 6 + ] + ], + [ + [ + 4030, + 4357 + ], + [ + 17, + 76 + ], + [ + -48, + 12 + ] + ], + [ + [ + 3999, + 4445 + ], + [ + -76, + -11 + ] + ], + [ + [ + 3923, + 4434 + ], + [ + -12, + 17 + ] + ], + [ + [ + 3911, + 4451 + ], + [ + 9, + 22 + ] + ], + [ + [ + 3920, + 4473 + ], + [ + 19, + 80 + ] + ], + [ + [ + 3920, + 4473 + ], + [ + -72, + 13 + ] + ], + [ + [ + 3848, + 4486 + ], + [ + -74, + 52 + ] + ], + [ + [ + 3774, + 4538 + ], + [ + -17, + 85 + ] + ], + [ + [ + 3757, + 4623 + ], + [ + 68, + 35 + ], + [ + 39, + -14 + ] + ], + [ + [ + 3923, + 4641 + ], + [ + 15, + -13 + ] + ], + [ + [ + 3812, + 4442 + ], + [ + -15, + -41 + ] + ], + [ + [ + 3797, + 4401 + ], + [ + -46, + -11 + ] + ], + [ + [ + 3751, + 4390 + ], + [ + -65, + 12 + ] + ], + [ + [ + 3686, + 4402 + ], + [ + -17, + 20 + ] + ], + [ + [ + 3669, + 4422 + ], + [ + 67, + 4 + ], + [ + 11, + 40 + ] + ], + [ + [ + 3747, + 4466 + ], + [ + 65, + -9 + ] + ], + [ + [ + 3812, + 4457 + ], + [ + 0, + -15 + ] + ], + [ + [ + 3923, + 4434 + ], + [ + -48, + -56 + ] + ], + [ + [ + 3875, + 4378 + ], + [ + -27, + -7 + ] + ], + [ + [ + 3848, + 4371 + ], + [ + -44, + 19 + ] + ], + [ + [ + 3804, + 4390 + ], + [ + -7, + 11 + ] + ], + [ + [ + 3812, + 4442 + ], + [ + 99, + 9 + ] + ], + [ + [ + 4030, + 4357 + ], + [ + -31, + 88 + ] + ], + [ + [ + 4056, + 4351 + ], + [ + -20, + -51 + ] + ], + [ + [ + 4036, + 4300 + ], + [ + -114, + 17 + ] + ], + [ + [ + 3922, + 4317 + ], + [ + -47, + 61 + ] + ], + [ + [ + 3895, + 4669 + ], + [ + -4, + 27 + ] + ], + [ + [ + 3891, + 4696 + ], + [ + 105, + -13 + ] + ], + [ + [ + 3891, + 4696 + ], + [ + 63, + 57 + ] + ], + [ + [ + 3954, + 4753 + ], + [ + 58, + -11 + ] + ], + [ + [ + 3954, + 4753 + ], + [ + -19, + 45 + ], + [ + 90, + 9 + ] + ], + [ + [ + 3774, + 4538 + ], + [ + -54, + -27 + ], + [ + 27, + -45 + ] + ], + [ + [ + 3669, + 4422 + ], + [ + -41, + 4 + ] + ], + [ + [ + 3603, + 4485 + ], + [ + -3, + 21 + ] + ], + [ + [ + 3600, + 4506 + ], + [ + 3, + 22 + ] + ], + [ + [ + 3603, + 4528 + ], + [ + 14, + 86 + ] + ], + [ + [ + 3617, + 4614 + ], + [ + 32, + 48 + ] + ], + [ + [ + 3649, + 4662 + ], + [ + 27, + 0 + ] + ], + [ + [ + 3676, + 4662 + ], + [ + 81, + -39 + ] + ], + [ + [ + 4036, + 4300 + ], + [ + -11, + -55 + ] + ], + [ + [ + 4025, + 4245 + ], + [ + -36, + -6 + ] + ], + [ + [ + 3989, + 4239 + ], + [ + -61, + -15 + ] + ], + [ + [ + 3928, + 4224 + ], + [ + -11, + 31 + ] + ], + [ + [ + 3917, + 4255 + ], + [ + 5, + 62 + ] + ], + [ + [ + 3989, + 4239 + ], + [ + -1, + -32 + ] + ], + [ + [ + 3988, + 4207 + ], + [ + -62, + -37 + ], + [ + 23, + -65 + ], + [ + -46, + -26 + ], + [ + -30, + 89 + ] + ], + [ + [ + 3873, + 4168 + ], + [ + 17, + 40 + ] + ], + [ + [ + 3890, + 4208 + ], + [ + 38, + 16 + ] + ], + [ + [ + 4183, + 4046 + ], + [ + -28, + 31 + ], + [ + -42, + -22 + ], + [ + -95, + 18 + ], + [ + -28, + 90 + ], + [ + 59, + 57 + ], + [ + 37, + -5 + ], + [ + 78, + 31 + ], + [ + 62, + -35 + ], + [ + 62, + 19 + ] + ], + [ + [ + 4288, + 4230 + ], + [ + 39, + -14 + ] + ], + [ + [ + 4025, + 4245 + ], + [ + -37, + -38 + ] + ], + [ + [ + 3873, + 4168 + ], + [ + -15, + 73 + ] + ], + [ + [ + 3858, + 4241 + ], + [ + 14, + 23 + ] + ], + [ + [ + 3872, + 4264 + ], + [ + 10, + -24 + ] + ], + [ + [ + 3882, + 4240 + ], + [ + 8, + -32 + ] + ], + [ + [ + 3848, + 4371 + ], + [ + 3, + -34 + ] + ], + [ + [ + 3851, + 4337 + ], + [ + -8, + -71 + ] + ], + [ + [ + 3843, + 4266 + ], + [ + -2, + -6 + ] + ], + [ + [ + 3841, + 4260 + ], + [ + -48, + 33 + ], + [ + -44, + 64 + ] + ], + [ + [ + 3749, + 4357 + ], + [ + 31, + -1 + ], + [ + 24, + 34 + ] + ], + [ + [ + 3686, + 4402 + ], + [ + -70, + -29 + ] + ], + [ + [ + 3593, + 4487 + ], + [ + 7, + 19 + ] + ], + [ + [ + 3532, + 4539 + ], + [ + 16, + 6 + ] + ], + [ + [ + 3548, + 4545 + ], + [ + 55, + -17 + ] + ], + [ + [ + 3548, + 4545 + ], + [ + 69, + 69 + ] + ], + [ + [ + 3309, + 4241 + ], + [ + 45, + 0 + ], + [ + -15, + -154 + ] + ], + [ + [ + 3339, + 4087 + ], + [ + -40, + 53 + ], + [ + 10, + 101 + ] + ], + [ + [ + 3309, + 4241 + ], + [ + 20, + 60 + ], + [ + 118, + -10 + ] + ], + [ + [ + 3541, + 4260 + ], + [ + -42, + -47 + ], + [ + -29, + -108 + ], + [ + -28, + -31 + ], + [ + -63, + -24 + ], + [ + -40, + 37 + ] + ], + [ + [ + 3364, + 4626 + ], + [ + -46, + -70 + ], + [ + -22, + 71 + ], + [ + 41, + 40 + ] + ], + [ + [ + 3337, + 4667 + ], + [ + 27, + -41 + ] + ], + [ + [ + 6692, + 2216 + ], + [ + -6, + -19 + ], + [ + -25, + 40 + ], + [ + 5, + 10 + ], + [ + 26, + -31 + ] + ], + [ + [ + 6573, + 2636 + ], + [ + 5, + -16 + ], + [ + -25, + 25 + ], + [ + -5, + 14 + ], + [ + 25, + -23 + ] + ], + [ + [ + 6907, + 1606 + ], + [ + -60, + 18 + ], + [ + 17, + 68 + ], + [ + 74, + -10 + ], + [ + -31, + -76 + ] + ], + [ + [ + 6767, + 1494 + ], + [ + 47, + 83 + ], + [ + 42, + -26 + ], + [ + -95, + -157 + ], + [ + -45, + 50 + ], + [ + 51, + 50 + ] + ], + [ + [ + 6342, + 1582 + ], + [ + 13, + -40 + ], + [ + -45, + -48 + ], + [ + -26, + 77 + ], + [ + 58, + 11 + ] + ], + [ + [ + 5925, + 1858 + ], + [ + -48, + -54 + ], + [ + -73, + -2 + ], + [ + -36, + -35 + ], + [ + -58, + 28 + ], + [ + 15, + 64 + ], + [ + -32, + 131 + ], + [ + -15, + 120 + ], + [ + 24, + 82 + ], + [ + 40, + 36 + ], + [ + 80, + 33 + ], + [ + 29, + 78 + ], + [ + 65, + 98 + ], + [ + 72, + -7 + ], + [ + 23, + 61 + ], + [ + 57, + 24 + ], + [ + 66, + -18 + ], + [ + -30, + -76 + ], + [ + 75, + -85 + ], + [ + 31, + 0 + ], + [ + 16, + 74 + ], + [ + 0, + 85 + ], + [ + 43, + -69 + ], + [ + 28, + -14 + ], + [ + 20, + -127 + ], + [ + 47, + -47 + ], + [ + 16, + -62 + ], + [ + 62, + -94 + ], + [ + 13, + -92 + ], + [ + -13, + -113 + ], + [ + -54, + -154 + ], + [ + -73, + -84 + ], + [ + -110, + 33 + ], + [ + -48, + 77 + ], + [ + -75, + 96 + ], + [ + -57, + 36 + ], + [ + -100, + -23 + ] + ], + [ + [ + 5066, + 3136 + ], + [ + -28, + -50 + ], + [ + -12, + 72 + ], + [ + 40, + -22 + ] + ], + [ + [ + 5888, + 4178 + ], + [ + -130, + -38 + ], + [ + 42, + -51 + ], + [ + -11, + -72 + ], + [ + 54, + -104 + ], + [ + 3, + -59 + ], + [ + -66, + -170 + ], + [ + -54, + -57 + ], + [ + -78, + -40 + ], + [ + -73, + 0 + ] + ], + [ + [ + 5840, + 3679 + ], + [ + -20, + -78 + ], + [ + -12, + 51 + ], + [ + 32, + 27 + ] + ], + [ + [ + 3751, + 4390 + ], + [ + 2, + -30 + ] + ], + [ + [ + 3753, + 4360 + ], + [ + -31, + -6 + ], + [ + 5, + -42 + ], + [ + 64, + -82 + ], + [ + -73, + 5 + ], + [ + -62, + 86 + ], + [ + -29, + -22 + ] + ], + [ + [ + 3649, + 4662 + ], + [ + -9, + 50 + ], + [ + 42, + 12 + ], + [ + -6, + -62 + ] + ], + [ + [ + 3337, + 4667 + ], + [ + 27, + -41 + ] + ], + [ + [ + 3424, + 4612 + ], + [ + -49, + 61 + ], + [ + 12, + 107 + ], + [ + 59, + -31 + ], + [ + -3, + -57 + ], + [ + 50, + -96 + ], + [ + 1, + -69 + ], + [ + -81, + -18 + ], + [ + -31, + 57 + ], + [ + 42, + 46 + ] + ], + [ + [ + 3203, + 5031 + ], + [ + 17, + -42 + ], + [ + -98, + -53 + ], + [ + -79, + 15 + ], + [ + 42, + 57 + ], + [ + 118, + 23 + ] + ], + [ + [ + 4424, + 4239 + ], + [ + 20, + -40 + ], + [ + -14, + -73 + ] + ], + [ + [ + 4354, + 4221 + ], + [ + 28, + 19 + ] + ], + [ + [ + 4288, + 4230 + ], + [ + -31, + 61 + ] + ], + [ + [ + 5929, + 3165 + ], + [ + 3, + -40 + ], + [ + -45, + -33 + ], + [ + -14, + 82 + ], + [ + 56, + -9 + ] + ], + [ + [ + 5851, + 3480 + ], + [ + -13, + -73 + ], + [ + -31, + -31 + ], + [ + 13, + 113 + ], + [ + 31, + -9 + ] + ], + [ + [ + 5606, + 2959 + ], + [ + 64, + 35 + ], + [ + 24, + 46 + ] + ], + [ + [ + 5694, + 3040 + ], + [ + 22, + -7 + ], + [ + 2, + 36 + ] + ], + [ + [ + 5718, + 3069 + ], + [ + 24, + 48 + ], + [ + 48, + -49 + ], + [ + -25, + -41 + ] + ], + [ + [ + 5460, + 3094 + ], + [ + 24, + -44 + ], + [ + 3, + -116 + ], + [ + -41, + 49 + ], + [ + -26, + 119 + ] + ], + [ + [ + 5694, + 3040 + ], + [ + 24, + 29 + ] + ], + [ + [ + 3749, + 4357 + ], + [ + 4, + 3 + ] + ], + [ + [ + 4027, + 4840 + ], + [ + -101, + -21 + ], + [ + -35, + 89 + ], + [ + 84, + 80 + ], + [ + -29, + 29 + ] + ], + [ + [ + 3812, + 4457 + ], + [ + 36, + 29 + ] + ], + [ + [ + 4227, + 3473 + ], + [ + 16, + -67 + ], + [ + 74, + -103 + ] + ], + [ + [ + 4317, + 3303 + ], + [ + -14, + -5 + ] + ], + [ + [ + 4303, + 3298 + ], + [ + -28, + 50 + ], + [ + -35, + 20 + ], + [ + -51, + -10 + ] + ], + [ + [ + 6229, + 4154 + ], + [ + -21, + -107 + ], + [ + -35, + -38 + ], + [ + -75, + -2 + ], + [ + -57, + -22 + ], + [ + -16, + -79 + ], + [ + -37, + 59 + ], + [ + 62, + 69 + ], + [ + 59, + 3 + ], + [ + 73, + 86 + ], + [ + 47, + 31 + ] + ], + [ + [ + 6282, + 4308 + ], + [ + -27, + -63 + ], + [ + -35, + 44 + ], + [ + 11, + 70 + ], + [ + 51, + -51 + ] + ], + [ + [ + 4511, + 3430 + ], + [ + -18, + -34 + ], + [ + -67, + -51 + ], + [ + -101, + -44 + ], + [ + -14, + 119 + ] + ], + [ + [ + 4311, + 3420 + ], + [ + 12, + 40 + ], + [ + 70, + -21 + ], + [ + 41, + 54 + ], + [ + 56, + 12 + ] + ], + [ + [ + 4420, + 3812 + ], + [ + 34, + -60 + ], + [ + 13, + -62 + ] + ], + [ + [ + 4478, + 3686 + ], + [ + 4, + -12 + ] + ], + [ + [ + 4311, + 3420 + ], + [ + -35, + 101 + ], + [ + -35, + 58 + ], + [ + -13, + 77 + ], + [ + -65, + 141 + ], + [ + -3, + 41 + ] + ], + [ + [ + 6967, + 170 + ], + [ + 0, + -170 + ], + [ + -6967, + 0 + ], + [ + 0, + 170 + ], + [ + 609, + -29 + ], + [ + -84, + 115 + ], + [ + 109, + 44 + ], + [ + -79, + 105 + ], + [ + 135, + 60 + ], + [ + 177, + 40 + ], + [ + 367, + 2 + ], + [ + 302, + -34 + ], + [ + 83, + 54 + ], + [ + 153, + 19 + ], + [ + 236, + -30 + ], + [ + 141, + 30 + ], + [ + 9, + 94 + ], + [ + 58, + 81 + ], + [ + 77, + -113 + ], + [ + -9, + -108 + ], + [ + -309, + -126 + ], + [ + 50, + -61 + ], + [ + 234, + -48 + ], + [ + 672, + 46 + ], + [ + -140, + 64 + ], + [ + 134, + 54 + ], + [ + 255, + 69 + ], + [ + 5, + 44 + ], + [ + 155, + 47 + ], + [ + 328, + 54 + ], + [ + 188, + 4 + ], + [ + 152, + -19 + ], + [ + 109, + 35 + ], + [ + 141, + 9 + ], + [ + 244, + 98 + ], + [ + 72, + 3 + ], + [ + 46, + -43 + ], + [ + 197, + -20 + ], + [ + -21, + -77 + ], + [ + 190, + 27 + ], + [ + 99, + 73 + ], + [ + 91, + 11 + ], + [ + 237, + -12 + ], + [ + 61, + 54 + ], + [ + 64, + -44 + ], + [ + 144, + 34 + ], + [ + 141, + -42 + ], + [ + 290, + 37 + ], + [ + 31, + -30 + ], + [ + 155, + 1 + ], + [ + 23, + -31 + ], + [ + 147, + -22 + ], + [ + 163, + -70 + ], + [ + 165, + -30 + ], + [ + -99, + -87 + ], + [ + -122, + -211 + ], + [ + 391, + -121 + ] + ], + [ + [ + 4117, + 4024 + ], + [ + 18, + 8 + ], + [ + 6, + -10 + ] + ], + [ + [ + 4141, + 4022 + ], + [ + -24, + 2 + ] + ], + [ + [ + 4141, + 4022 + ], + [ + -19, + -16 + ], + [ + -5, + 18 + ] + ], + [ + [ + 3154, + 3583 + ], + [ + 50, + 155 + ], + [ + 94, + 119 + ], + [ + 18, + 106 + ], + [ + 53, + 81 + ], + [ + 73, + -19 + ] + ], + [ + [ + 3967, + 3602 + ], + [ + 0, + 118 + ], + [ + 4, + 189 + ] + ], + [ + [ + 3971, + 3909 + ], + [ + 72, + -22 + ], + [ + 40, + 22 + ], + [ + 64, + -11 + ] + ], + [ + [ + 4157, + 3851 + ], + [ + -28, + -66 + ], + [ + 68, + -183 + ] + ], + [ + [ + 3706, + 3960 + ], + [ + 73, + -28 + ], + [ + 9, + -29 + ], + [ + 65, + -36 + ], + [ + 34, + 79 + ], + [ + 84, + -37 + ] + ], + [ + [ + 4167, + 3071 + ], + [ + -26, + 102 + ] + ], + [ + [ + 4303, + 3298 + ], + [ + 8, + -52 + ] + ], + [ + [ + 4311, + 3246 + ], + [ + 18, + -56 + ], + [ + 79, + -38 + ] + ], + [ + [ + 4317, + 3303 + ], + [ + 1, + -40 + ] + ], + [ + [ + 4318, + 3263 + ], + [ + -7, + -17 + ] + ], + [ + [ + 4318, + 3263 + ], + [ + 19, + -33 + ], + [ + 94, + 31 + ] + ], + [ + [ + 4072, + 2858 + ], + [ + -16, + -7 + ] + ], + [ + [ + 4080, + 3007 + ], + [ + 62, + 24 + ] + ], + [ + [ + 3851, + 4337 + ], + [ + 4, + -43 + ] + ], + [ + [ + 3855, + 4294 + ], + [ + -12, + -28 + ] + ], + [ + [ + 3882, + 4240 + ], + [ + 19, + 13 + ] + ], + [ + [ + 3901, + 4253 + ], + [ + 16, + 2 + ] + ], + [ + [ + 3901, + 4253 + ], + [ + -25, + 18 + ] + ], + [ + [ + 3876, + 4271 + ], + [ + -21, + 23 + ] + ], + [ + [ + 3858, + 4241 + ], + [ + -17, + 19 + ] + ], + [ + [ + 3876, + 4271 + ], + [ + -4, + -7 + ] + ], + [ + [ + 2290, + 3240 + ], + [ + 15, + 3 + ], + [ + -1, + -24 + ], + [ + -16, + -3 + ], + [ + 2, + 24 + ] + ] + ], + "transform": { + "scale": [ + 0.0516721687957514, + 0.031096713261648746 + ], + "translate": [ + -180, + -90 + ] + }, + "objects": { + "countries": { + "type": "GeometryCollection", + "geometries": [ + { + "arcs": [ + [ + 0 + ] + ], + "type": "Polygon", + "properties": { + "code": "FJI", + "name": "Fiji" + } + }, + { + "arcs": [ + [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ] + ], + "type": "Polygon", + "properties": { + "code": "TZA", + "name": "Tanzania" + } + }, + { + "arcs": [ + [ + 10, + 11, + 12, + 13 + ] + ], + "type": "Polygon", + "properties": { + "code": "SAH", + "name": "W. Sahara" + } + }, + { + "arcs": [ + [ + [ + 14, + 15, + 16, + 17 + ] + ], + [ + [ + 18 + ] + ], + [ + [ + 19 + ] + ], + [ + [ + 20 + ] + ], + [ + [ + 21 + ] + ], + [ + [ + 22 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "CAN", + "name": "Canada" + } + }, + { + "arcs": [ + [ + [ + -16, + 23 + ] + ], + [ + [ + -18, + 24, + 25, + 26 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "USA", + "name": "United States of America" + } + }, + { + "arcs": [ + [ + 27, + 28, + 29, + 30, + 31, + 32 + ] + ], + "type": "Polygon", + "properties": { + "code": "KAZ", + "name": "Kazakhstan" + } + }, + { + "arcs": [ + [ + -30, + 33, + 34, + 35, + 36 + ] + ], + "type": "Polygon", + "properties": { + "code": "UZB", + "name": "Uzbekistan" + } + }, + { + "arcs": [ + [ + 37, + 38 + ] + ], + "type": "Polygon", + "properties": { + "code": "PNG", + "name": "Papua New Guinea" + } + }, + { + "arcs": [ + [ + [ + -39, + 39 + ] + ], + [ + [ + 42, + 43 + ] + ], + [ + [ + 44 + ] + ], + [ + [ + 45 + ] + ], + [ + [ + 46 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "IDN", + "name": "Indonesia" + } + }, + { + "arcs": [ + [ + 49, + 50, + 51, + 52, + 53, + 54 + ] + ], + "type": "Polygon", + "properties": { + "code": "ARG", + "name": "Argentina" + } + }, + { + "arcs": [ + [ + [ + -49, + 55 + ] + ], + [ + [ + 56, + -52, + 57, + 58 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "CHL", + "name": "Chile" + } + }, + { + "arcs": [ + [ + -7, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68 + ] + ], + "type": "Polygon", + "properties": { + "code": "COD", + "name": "Dem. Rep. Congo" + } + }, + { + "arcs": [ + [ + 69, + 70, + 71, + 72 + ] + ], + "type": "Polygon", + "properties": { + "code": "SOM", + "name": "Somalia" + } + }, + { + "arcs": [ + [ + -2, + 73, + 74, + 75, + -70, + 76 + ] + ], + "type": "Polygon", + "properties": { + "code": "KEN", + "name": "Kenya" + } + }, + { + "arcs": [ + [ + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84 + ] + ], + "type": "Polygon", + "properties": { + "code": "SDN", + "name": "Sudan" + } + }, + { + "arcs": [ + [ + -79, + 85, + 86, + 87, + 88 + ] + ], + "type": "Polygon", + "properties": { + "code": "TCD", + "name": "Chad" + } + }, + { + "arcs": [ + [ + 89, + 90 + ] + ], + "type": "Polygon", + "properties": { + "code": "HTI", + "name": "Haiti" + } + }, + { + "arcs": [ + [ + -90, + 91 + ] + ], + "type": "Polygon", + "properties": { + "code": "DOM", + "name": "Dominican Rep." + } + }, + { + "arcs": [ + [ + [ + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + -33 + ] + ], + [ + [ + 108, + 109, + 110 + ] + ], + [ + [ + 111 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "RUS", + "name": "Russia" + } + }, + { + "arcs": [ + [ + 114 + ] + ], + "type": "Polygon", + "properties": { + "code": "BHS", + "name": "Bahamas" + } + }, + { + "arcs": [ + [ + 115 + ] + ], + "type": "Polygon", + "properties": { + "code": "FLK", + "name": "Falkland Is." + } + }, + { + "arcs": [ + [ + -103, + 116, + 117, + 118 + ] + ], + "type": "Polygon", + "properties": { + "code": "NOR", + "name": "Norway" + } + }, + { + "arcs": [ + [ + 119 + ] + ], + "type": "Polygon", + "properties": { + "code": "GRL", + "name": "Greenland" + } + }, + { + "arcs": [ + [ + 120 + ] + ], + "type": "Polygon", + "properties": { + "code": "ATF", + "name": "Fr. S. Antarctic Lands" + } + }, + { + "arcs": [ + [ + 121, + -41 + ] + ], + "type": "Polygon", + "properties": { + "code": "TLS", + "name": "Timor-Leste" + } + }, + { + "arcs": [ + [ + 122, + 123, + 124, + 125, + 126, + 127, + 128 + ], + [ + 129 + ] + ], + "type": "Polygon", + "properties": { + "code": "ZAF", + "name": "South Africa" + } + }, + { + "arcs": [ + [ + -130 + ] + ], + "type": "Polygon", + "properties": { + "code": "LSO", + "name": "Lesotho" + } + }, + { + "arcs": [ + [ + -26, + 130, + 131, + 132, + 133 + ] + ], + "type": "Polygon", + "properties": { + "code": "MEX", + "name": "Mexico" + } + }, + { + "arcs": [ + [ + 134, + 135, + -50 + ] + ], + "type": "Polygon", + "properties": { + "code": "URY", + "name": "Uruguay" + } + }, + { + "arcs": [ + [ + -135, + -55, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144 + ] + ], + "type": "Polygon", + "properties": { + "code": "BRA", + "name": "Brazil" + } + }, + { + "arcs": [ + [ + -138, + 145, + -53, + -57, + 146 + ] + ], + "type": "Polygon", + "properties": { + "code": "BOL", + "name": "Bolivia" + } + }, + { + "arcs": [ + [ + -139, + -147, + -59, + 147, + 148, + 149 + ] + ], + "type": "Polygon", + "properties": { + "code": "PER", + "name": "Peru" + } + }, + { + "arcs": [ + [ + -140, + -150, + 150, + 151, + 152, + 153, + 154 + ] + ], + "type": "Polygon", + "properties": { + "code": "COL", + "name": "Colombia" + } + }, + { + "arcs": [ + [ + -153, + 155, + 156, + 157 + ] + ], + "type": "Polygon", + "properties": { + "code": "PAN", + "name": "Panama" + } + }, + { + "arcs": [ + [ + -157, + 158, + 159, + 160 + ] + ], + "type": "Polygon", + "properties": { + "code": "CRI", + "name": "Costa Rica" + } + }, + { + "arcs": [ + [ + -160, + 161, + 162, + 163 + ] + ], + "type": "Polygon", + "properties": { + "code": "NIC", + "name": "Nicaragua" + } + }, + { + "arcs": [ + [ + -163, + 164, + 165, + 166, + 167 + ] + ], + "type": "Polygon", + "properties": { + "code": "HND", + "name": "Honduras" + } + }, + { + "arcs": [ + [ + -166, + 168, + 169 + ] + ], + "type": "Polygon", + "properties": { + "code": "SLV", + "name": "El Salvador" + } + }, + { + "arcs": [ + [ + -133, + 170, + 171, + -167, + -170, + 172 + ] + ], + "type": "Polygon", + "properties": { + "code": "GTM", + "name": "Guatemala" + } + }, + { + "arcs": [ + [ + -132, + 173, + -171 + ] + ], + "type": "Polygon", + "properties": { + "code": "BLZ", + "name": "Belize" + } + }, + { + "arcs": [ + [ + -141, + -155, + 174, + 175 + ] + ], + "type": "Polygon", + "properties": { + "code": "VEN", + "name": "Venezuela" + } + }, + { + "arcs": [ + [ + -142, + -176, + 176, + 177 + ] + ], + "type": "Polygon", + "properties": { + "code": "GUY", + "name": "Guyana" + } + }, + { + "arcs": [ + [ + -143, + -178, + 178, + 179 + ] + ], + "type": "Polygon", + "properties": { + "code": "SUR", + "name": "Suriname" + } + }, + { + "arcs": [ + [ + [ + -144, + -180, + 180 + ] + ], + [ + [ + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "FRA", + "name": "France" + } + }, + { + "arcs": [ + [ + -149, + 189, + -151 + ] + ], + "type": "Polygon", + "properties": { + "code": "ECU", + "name": "Ecuador" + } + }, + { + "arcs": [ + [ + 190 + ] + ], + "type": "Polygon", + "properties": { + "code": "PRI", + "name": "Puerto Rico" + } + }, + { + "arcs": [ + [ + 191 + ] + ], + "type": "Polygon", + "properties": { + "code": "JAM", + "name": "Jamaica" + } + }, + { + "arcs": [ + [ + 192 + ] + ], + "type": "Polygon", + "properties": { + "code": "CUB", + "name": "Cuba" + } + }, + { + "arcs": [ + [ + -125, + 193, + 194, + 195 + ] + ], + "type": "Polygon", + "properties": { + "code": "ZWE", + "name": "Zimbabwe" + } + }, + { + "arcs": [ + [ + -124, + 196, + 197, + -194 + ] + ], + "type": "Polygon", + "properties": { + "code": "BWA", + "name": "Botswana" + } + }, + { + "arcs": [ + [ + -123, + 198, + 199, + 200, + -197 + ] + ], + "type": "Polygon", + "properties": { + "code": "NAM", + "name": "Namibia" + } + }, + { + "arcs": [ + [ + 201, + 202, + 203, + 204, + 205, + 206, + 207 + ] + ], + "type": "Polygon", + "properties": { + "code": "SEN", + "name": "Senegal" + } + }, + { + "arcs": [ + [ + -204, + 208, + 209, + 210, + 211, + 212, + 213 + ] + ], + "type": "Polygon", + "properties": { + "code": "MLI", + "name": "Mali" + } + }, + { + "arcs": [ + [ + -12, + 214, + -209, + -203, + 215 + ] + ], + "type": "Polygon", + "properties": { + "code": "MRT", + "name": "Mauritania" + } + }, + { + "arcs": [ + [ + 216, + 217, + 218, + 219, + 220 + ] + ], + "type": "Polygon", + "properties": { + "code": "BEN", + "name": "Benin" + } + }, + { + "arcs": [ + [ + -88, + 221, + 222, + -220, + 223, + -211, + 224, + 225 + ] + ], + "type": "Polygon", + "properties": { + "code": "NER", + "name": "Niger" + } + }, + { + "arcs": [ + [ + -221, + -223, + 226, + 227 + ] + ], + "type": "Polygon", + "properties": { + "code": "NGA", + "name": "Nigeria" + } + }, + { + "arcs": [ + [ + -87, + 228, + 229, + 230, + 231, + 232, + -227, + -222 + ] + ], + "type": "Polygon", + "properties": { + "code": "CMR", + "name": "Cameroon" + } + }, + { + "arcs": [ + [ + -218, + 233, + 234, + 235 + ] + ], + "type": "Polygon", + "properties": { + "code": "TGO", + "name": "Togo" + } + }, + { + "arcs": [ + [ + -235, + 236, + 237, + 238 + ] + ], + "type": "Polygon", + "properties": { + "code": "GHA", + "name": "Ghana" + } + }, + { + "arcs": [ + [ + -213, + 239, + -238, + 240, + 241, + 242 + ] + ], + "type": "Polygon", + "properties": { + "code": "CIV", + "name": "Côte d'Ivoire" + } + }, + { + "arcs": [ + [ + -205, + -214, + -243, + 243, + 244, + 245, + 246 + ] + ], + "type": "Polygon", + "properties": { + "code": "GIN", + "name": "Guinea" + } + }, + { + "arcs": [ + [ + -206, + -247, + 247 + ] + ], + "type": "Polygon", + "properties": { + "code": "GNB", + "name": "Guinea-Bissau" + } + }, + { + "arcs": [ + [ + -242, + 248, + 249, + -244 + ] + ], + "type": "Polygon", + "properties": { + "code": "LBR", + "name": "Liberia" + } + }, + { + "arcs": [ + [ + -245, + -250, + 250 + ] + ], + "type": "Polygon", + "properties": { + "code": "SLE", + "name": "Sierra Leone" + } + }, + { + "arcs": [ + [ + -212, + -224, + -219, + -236, + -239, + -240 + ] + ], + "type": "Polygon", + "properties": { + "code": "BFA", + "name": "Burkina Faso" + } + }, + { + "arcs": [ + [ + -65, + 251, + -229, + -86, + -78, + 252 + ] + ], + "type": "Polygon", + "properties": { + "code": "CAF", + "name": "Central African Rep." + } + }, + { + "arcs": [ + [ + -64, + 253, + 254, + 255, + -230, + -252 + ] + ], + "type": "Polygon", + "properties": { + "code": "COG", + "name": "Congo" + } + }, + { + "arcs": [ + [ + -231, + -256, + 256, + 257 + ] + ], + "type": "Polygon", + "properties": { + "code": "GAB", + "name": "Gabon" + } + }, + { + "arcs": [ + [ + -232, + -258, + 258 + ] + ], + "type": "Polygon", + "properties": { + "code": "GNQ", + "name": "Eq. Guinea" + } + }, + { + "arcs": [ + [ + -6, + 259, + 260, + -195, + -198, + -201, + 261, + -60 + ] + ], + "type": "Polygon", + "properties": { + "code": "ZMB", + "name": "Zambia" + } + }, + { + "arcs": [ + [ + -5, + 262, + -260 + ] + ], + "type": "Polygon", + "properties": { + "code": "MWI", + "name": "Malawi" + } + }, + { + "arcs": [ + [ + -4, + 263, + -128, + 264, + -126, + -196, + -261, + -263 + ] + ], + "type": "Polygon", + "properties": { + "code": "MOZ", + "name": "Mozambique" + } + }, + { + "arcs": [ + [ + -127, + -265 + ] + ], + "type": "Polygon", + "properties": { + "code": "SWZ", + "name": "eSwatini" + } + }, + { + "arcs": [ + [ + [ + -61, + -262, + -200, + 265 + ] + ], + [ + [ + -63, + 266, + -254 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "AGO", + "name": "Angola" + } + }, + { + "arcs": [ + [ + -8, + -69, + 267 + ] + ], + "type": "Polygon", + "properties": { + "code": "BDI", + "name": "Burundi" + } + }, + { + "arcs": [ + [ + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275 + ] + ], + "type": "Polygon", + "properties": { + "code": "ISR", + "name": "Israel" + } + }, + { + "arcs": [ + [ + -275, + 276, + 277 + ] + ], + "type": "Polygon", + "properties": { + "code": "LBN", + "name": "Lebanon" + } + }, + { + "arcs": [ + [ + 278 + ] + ], + "type": "Polygon", + "properties": { + "code": "MDG", + "name": "Madagascar" + } + }, + { + "arcs": [ + [ + -270, + 279 + ] + ], + "type": "Polygon", + "properties": { + "code": "PSX", + "name": "Palestine" + } + }, + { + "arcs": [ + [ + -208, + 280 + ] + ], + "type": "Polygon", + "properties": { + "code": "GMB", + "name": "Gambia" + } + }, + { + "arcs": [ + [ + 281, + 282, + 283 + ] + ], + "type": "Polygon", + "properties": { + "code": "TUN", + "name": "Tunisia" + } + }, + { + "arcs": [ + [ + -11, + 284, + 285, + -282, + 286, + -225, + -210, + -215 + ] + ], + "type": "Polygon", + "properties": { + "code": "DZA", + "name": "Algeria" + } + }, + { + "arcs": [ + [ + -269, + 287, + 288, + 289, + 290, + -271, + -280 + ] + ], + "type": "Polygon", + "properties": { + "code": "JOR", + "name": "Jordan" + } + }, + { + "arcs": [ + [ + 291, + 292, + 293, + 294, + 295 + ] + ], + "type": "Polygon", + "properties": { + "code": "ARE", + "name": "United Arab Emirates" + } + }, + { + "arcs": [ + [ + 296, + 297 + ] + ], + "type": "Polygon", + "properties": { + "code": "QAT", + "name": "Qatar" + } + }, + { + "arcs": [ + [ + 298, + 299, + 300 + ] + ], + "type": "Polygon", + "properties": { + "code": "KWT", + "name": "Kuwait" + } + }, + { + "arcs": [ + [ + -289, + 301, + 302, + 303, + 304, + -301, + 305 + ] + ], + "type": "Polygon", + "properties": { + "code": "IRQ", + "name": "Iraq" + } + }, + { + "arcs": [ + [ + -295, + 307, + 308, + 309 + ] + ], + "type": "Polygon", + "properties": { + "code": "OMN", + "name": "Oman" + } + }, + { + "arcs": [ + [ + 310 + ] + ], + "type": "Polygon", + "properties": { + "code": "VUT", + "name": "Vanuatu" + } + }, + { + "arcs": [ + [ + 311, + 312, + 313, + 314 + ] + ], + "type": "Polygon", + "properties": { + "code": "KHM", + "name": "Cambodia" + } + }, + { + "arcs": [ + [ + -312, + 315, + 316, + 317, + 318, + 319 + ] + ], + "type": "Polygon", + "properties": { + "code": "THA", + "name": "Thailand" + } + }, + { + "arcs": [ + [ + -313, + -320, + 320, + 321, + 322 + ] + ], + "type": "Polygon", + "properties": { + "code": "LAO", + "name": "Laos" + } + }, + { + "arcs": [ + [ + -319, + 323, + 324, + 325, + 326, + -321 + ] + ], + "type": "Polygon", + "properties": { + "code": "MMR", + "name": "Myanmar" + } + }, + { + "arcs": [ + [ + -314, + -323, + 327, + 328 + ] + ], + "type": "Polygon", + "properties": { + "code": "VNM", + "name": "Vietnam" + } + }, + { + "arcs": [ + [ + -105, + 329, + 330, + 331, + 332 + ] + ], + "type": "Polygon", + "properties": { + "code": "PRK", + "name": "North Korea" + } + }, + { + "arcs": [ + [ + -331, + 333 + ] + ], + "type": "Polygon", + "properties": { + "code": "KOR", + "name": "South Korea" + } + }, + { + "arcs": [ + [ + -107, + 334 + ] + ], + "type": "Polygon", + "properties": { + "code": "MNG", + "name": "Mongolia" + } + }, + { + "arcs": [ + [ + -326, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342 + ] + ], + "type": "Polygon", + "properties": { + "code": "IND", + "name": "India" + } + }, + { + "arcs": [ + [ + -325, + 343, + -336 + ] + ], + "type": "Polygon", + "properties": { + "code": "BGD", + "name": "Bangladesh" + } + }, + { + "arcs": [ + [ + -342, + 344 + ] + ], + "type": "Polygon", + "properties": { + "code": "BTN", + "name": "Bhutan" + } + }, + { + "arcs": [ + [ + -340, + 345 + ] + ], + "type": "Polygon", + "properties": { + "code": "NPL", + "name": "Nepal" + } + }, + { + "arcs": [ + [ + -338, + 346, + 347, + 348, + 349 + ] + ], + "type": "Polygon", + "properties": { + "code": "PAK", + "name": "Pakistan" + } + }, + { + "arcs": [ + [ + -36, + 350, + 351, + -349, + 352, + 353 + ] + ], + "type": "Polygon", + "properties": { + "code": "AFG", + "name": "Afghanistan" + } + }, + { + "arcs": [ + [ + -35, + 354, + 355, + -351 + ] + ], + "type": "Polygon", + "properties": { + "code": "TJK", + "name": "Tajikistan" + } + }, + { + "arcs": [ + [ + -29, + 356, + -355, + -34 + ] + ], + "type": "Polygon", + "properties": { + "code": "KGZ", + "name": "Kyrgyzstan" + } + }, + { + "arcs": [ + [ + -31, + -37, + -354, + 357, + 358 + ] + ], + "type": "Polygon", + "properties": { + "code": "TKM", + "name": "Turkmenistan" + } + }, + { + "arcs": [ + [ + -304, + 359, + 360, + 361, + 362, + 363, + -358, + -353, + -348, + 364 + ] + ], + "type": "Polygon", + "properties": { + "code": "IRN", + "name": "Iran" + } + }, + { + "arcs": [ + [ + -276, + -278, + 365, + 366, + -302, + -288 + ] + ], + "type": "Polygon", + "properties": { + "code": "SYR", + "name": "Syria" + } + }, + { + "arcs": [ + [ + -362, + 367, + 368, + 369, + 370 + ] + ], + "type": "Polygon", + "properties": { + "code": "ARM", + "name": "Armenia" + } + }, + { + "arcs": [ + [ + -118, + 371, + 372 + ] + ], + "type": "Polygon", + "properties": { + "code": "SWE", + "name": "Sweden" + } + }, + { + "arcs": [ + [ + -98, + 373, + 374, + 375, + 376 + ] + ], + "type": "Polygon", + "properties": { + "code": "BLR", + "name": "Belarus" + } + }, + { + "arcs": [ + [ + -97, + 377, + -113, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + -374 + ] + ], + "type": "Polygon", + "properties": { + "code": "UKR", + "name": "Ukraine" + } + }, + { + "arcs": [ + [ + -375, + -385, + 385, + 386, + 387, + 388, + -109, + 389 + ] + ], + "type": "Polygon", + "properties": { + "code": "POL", + "name": "Poland" + } + }, + { + "arcs": [ + [ + 390, + 391, + 392, + 393, + 394, + 395, + 396 + ] + ], + "type": "Polygon", + "properties": { + "code": "AUT", + "name": "Austria" + } + }, + { + "arcs": [ + [ + -383, + 397, + 398, + 399, + 400, + -391, + 401 + ] + ], + "type": "Polygon", + "properties": { + "code": "HUN", + "name": "Hungary" + } + }, + { + "arcs": [ + [ + -381, + 402 + ] + ], + "type": "Polygon", + "properties": { + "code": "MDA", + "name": "Moldova" + } + }, + { + "arcs": [ + [ + -380, + 403, + 404, + 405, + -398, + -382, + -403 + ] + ], + "type": "Polygon", + "properties": { + "code": "ROU", + "name": "Romania" + } + }, + { + "arcs": [ + [ + -376, + -390, + -111, + 406, + 407 + ] + ], + "type": "Polygon", + "properties": { + "code": "LTU", + "name": "Lithuania" + } + }, + { + "arcs": [ + [ + -99, + -377, + -408, + 408, + 409 + ] + ], + "type": "Polygon", + "properties": { + "code": "LVA", + "name": "Latvia" + } + }, + { + "arcs": [ + [ + -100, + -410, + 410 + ] + ], + "type": "Polygon", + "properties": { + "code": "EST", + "name": "Estonia" + } + }, + { + "arcs": [ + [ + -388, + 411, + -395, + 412, + -182, + 413, + 414, + 415, + 416, + 417, + 418 + ] + ], + "type": "Polygon", + "properties": { + "code": "DEU", + "name": "Germany" + } + }, + { + "arcs": [ + [ + -405, + 419, + 420, + 421, + 422, + 423 + ] + ], + "type": "Polygon", + "properties": { + "code": "BGR", + "name": "Bulgaria" + } + }, + { + "arcs": [ + [ + -422, + 424, + 425, + 426, + 427 + ] + ], + "type": "Polygon", + "properties": { + "code": "GRC", + "name": "Greece" + } + }, + { + "arcs": [ + [ + [ + -303, + -367, + 428, + 429, + -369, + -360 + ] + ], + [ + [ + -421, + 430, + -425 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "TUR", + "name": "Turkey" + } + }, + { + "arcs": [ + [ + -427, + 431, + 432, + 433, + 434 + ] + ], + "type": "Polygon", + "properties": { + "code": "ALB", + "name": "Albania" + } + }, + { + "arcs": [ + [ + -400, + 435, + 436, + 437, + 438, + 439 + ] + ], + "type": "Polygon", + "properties": { + "code": "HRV", + "name": "Croatia" + } + }, + { + "arcs": [ + [ + -394, + 440, + -183, + -413 + ] + ], + "type": "Polygon", + "properties": { + "code": "CHE", + "name": "Switzerland" + } + }, + { + "arcs": [ + [ + -414, + -189, + 441 + ] + ], + "type": "Polygon", + "properties": { + "code": "LUX", + "name": "Luxembourg" + } + }, + { + "arcs": [ + [ + -415, + -442, + -188, + 442, + 443 + ] + ], + "type": "Polygon", + "properties": { + "code": "BEL", + "name": "Belgium" + } + }, + { + "arcs": [ + [ + -416, + -444, + 444 + ] + ], + "type": "Polygon", + "properties": { + "code": "NLD", + "name": "Netherlands" + } + }, + { + "arcs": [ + [ + 445, + 446 + ] + ], + "type": "Polygon", + "properties": { + "code": "PRT", + "name": "Portugal" + } + }, + { + "arcs": [ + [ + -446, + 447, + -186, + 448 + ] + ], + "type": "Polygon", + "properties": { + "code": "ESP", + "name": "Spain" + } + }, + { + "arcs": [ + [ + 449, + 450 + ] + ], + "type": "Polygon", + "properties": { + "code": "IRL", + "name": "Ireland" + } + }, + { + "arcs": [ + [ + 451 + ] + ], + "type": "Polygon", + "properties": { + "code": "NCL", + "name": "New Caledonia" + } + }, + { + "arcs": [ + [ + 452 + ] + ], + "type": "Polygon", + "properties": { + "code": "SLB", + "name": "Solomon Is." + } + }, + { + "arcs": [ + [ + [ + 453 + ] + ], + [ + [ + 454 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "NZL", + "name": "New Zealand" + } + }, + { + "arcs": [ + [ + [ + 455 + ] + ], + [ + [ + 456 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "AUS", + "name": "Australia" + } + }, + { + "arcs": [ + [ + 457 + ] + ], + "type": "Polygon", + "properties": { + "code": "LKA", + "name": "Sri Lanka" + } + }, + { + "arcs": [ + [ + -28, + -108, + -335, + -106, + -333, + 458, + -328, + -322, + -327, + -343, + -345, + -341, + -346, + -339, + -350, + -352, + -356, + -357 + ] + ], + "type": "Polygon", + "properties": { + "code": "CHN", + "name": "China" + } + }, + { + "arcs": [ + [ + 459 + ] + ], + "type": "Polygon", + "properties": { + "code": "TWN", + "name": "Taiwan" + } + }, + { + "arcs": [ + [ + -393, + 460, + 461, + -184, + -441 + ] + ], + "type": "Polygon", + "properties": { + "code": "ITA", + "name": "Italy" + } + }, + { + "arcs": [ + [ + -418, + 462 + ] + ], + "type": "Polygon", + "properties": { + "code": "DNK", + "name": "Denmark" + } + }, + { + "arcs": [ + [ + 464 + ] + ], + "type": "Polygon", + "properties": { + "code": "GBR", + "name": "United Kingdom" + } + }, + { + "arcs": [ + [ + 465 + ] + ], + "type": "Polygon", + "properties": { + "code": "ISL", + "name": "Iceland" + } + }, + { + "arcs": [ + [ + -94, + 466, + -363, + -371, + 467 + ] + ], + "type": "Polygon", + "properties": { + "code": "AZE", + "name": "Azerbaijan" + } + }, + { + "arcs": [ + [ + -95, + -468, + -370, + -430, + 468 + ] + ], + "type": "Polygon", + "properties": { + "code": "GEO", + "name": "Georgia" + } + }, + { + "arcs": [ + [ + [ + 469 + ] + ], + [ + [ + 470 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "PHL", + "name": "Philippines" + } + }, + { + "arcs": [ + [ + [ + -44, + 471, + 472, + 473 + ] + ], + [ + [ + -317, + 474 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "MYS", + "name": "Malaysia" + } + }, + { + "arcs": [ + [ + -473, + 475 + ] + ], + "type": "Polygon", + "properties": { + "code": "BRN", + "name": "Brunei" + } + }, + { + "arcs": [ + [ + -392, + -401, + -440, + 476, + -461 + ] + ], + "type": "Polygon", + "properties": { + "code": "SVN", + "name": "Slovenia" + } + }, + { + "arcs": [ + [ + -102, + 477, + -372, + -117 + ] + ], + "type": "Polygon", + "properties": { + "code": "FIN", + "name": "Finland" + } + }, + { + "arcs": [ + [ + -384, + -402, + -397, + 478, + -386 + ] + ], + "type": "Polygon", + "properties": { + "code": "SVK", + "name": "Slovakia" + } + }, + { + "arcs": [ + [ + -387, + -479, + -396, + -412 + ] + ], + "type": "Polygon", + "properties": { + "code": "CZE", + "name": "Czechia" + } + }, + { + "arcs": [ + [ + -83, + 479, + 480, + 481 + ] + ], + "type": "Polygon", + "properties": { + "code": "ERI", + "name": "Eritrea" + } + }, + { + "arcs": [ + [ + [ + 482 + ] + ], + [ + [ + 483 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "JPN", + "name": "Japan" + } + }, + { + "arcs": [ + [ + -137, + -54, + -146 + ] + ], + "type": "Polygon", + "properties": { + "code": "PRY", + "name": "Paraguay" + } + }, + { + "arcs": [ + [ + -309, + 484, + 485 + ] + ], + "type": "Polygon", + "properties": { + "code": "YEM", + "name": "Yemen" + } + }, + { + "arcs": [ + [ + -290, + -306, + -300, + 486, + -298, + 487, + -296, + -310, + -486, + 488 + ] + ], + "type": "Polygon", + "properties": { + "code": "SAU", + "name": "Saudi Arabia" + } + }, + { + "arcs": [ + [ + 489 + ] + ], + "type": "Polygon", + "properties": { + "code": "ATA", + "name": "Antarctica" + } + }, + { + "arcs": [ + [ + 490, + 491 + ] + ], + "type": "Polygon", + "properties": { + "code": "CYN", + "name": "N. Cyprus" + } + }, + { + "arcs": [ + [ + -492, + 492 + ] + ], + "type": "Polygon", + "properties": { + "code": "CYP", + "name": "Cyprus" + } + }, + { + "arcs": [ + [ + -285, + -14, + 493 + ] + ], + "type": "Polygon", + "properties": { + "code": "MAR", + "name": "Morocco" + } + }, + { + "arcs": [ + [ + -81, + 494, + 495, + -273, + 496 + ] + ], + "type": "Polygon", + "properties": { + "code": "EGY", + "name": "Egypt" + } + }, + { + "arcs": [ + [ + -80, + -89, + -226, + -287, + -284, + 497, + -495 + ] + ], + "type": "Polygon", + "properties": { + "code": "LBY", + "name": "Libya" + } + }, + { + "arcs": [ + [ + -71, + -76, + 498, + -84, + -482, + 499, + 500 + ] + ], + "type": "Polygon", + "properties": { + "code": "ETH", + "name": "Ethiopia" + } + }, + { + "arcs": [ + [ + -481, + 501, + 502, + -500 + ] + ], + "type": "Polygon", + "properties": { + "code": "DJI", + "name": "Djibouti" + } + }, + { + "arcs": [ + [ + -72, + -501, + -503, + 503 + ] + ], + "type": "Polygon", + "properties": { + "code": "SOL", + "name": "Somaliland" + } + }, + { + "arcs": [ + [ + -10, + 504, + -67, + 505, + -74 + ] + ], + "type": "Polygon", + "properties": { + "code": "UGA", + "name": "Uganda" + } + }, + { + "arcs": [ + [ + -9, + -268, + -68, + -505 + ] + ], + "type": "Polygon", + "properties": { + "code": "RWA", + "name": "Rwanda" + } + }, + { + "arcs": [ + [ + -437, + 506, + 507 + ] + ], + "type": "Polygon", + "properties": { + "code": "BIH", + "name": "Bosnia and Herz." + } + }, + { + "arcs": [ + [ + -423, + -428, + -435, + 508, + 509 + ] + ], + "type": "Polygon", + "properties": { + "code": "MKD", + "name": "North Macedonia" + } + }, + { + "arcs": [ + [ + -399, + -406, + -424, + -510, + 510, + 511, + -507, + -436 + ] + ], + "type": "Polygon", + "properties": { + "code": "SRB", + "name": "Serbia" + } + }, + { + "arcs": [ + [ + -433, + 512, + -438, + -508, + -512, + 513 + ] + ], + "type": "Polygon", + "properties": { + "code": "MNE", + "name": "Montenegro" + } + }, + { + "arcs": [ + [ + -434, + -514, + -511, + -509 + ] + ], + "type": "Polygon", + "properties": { + "code": "KOS", + "name": "Kosovo" + } + }, + { + "arcs": [ + [ + 514 + ] + ], + "type": "Polygon", + "properties": { + "code": "TTO", + "name": "Trinidad and Tobago" + } + }, + { + "arcs": [ + [ + -66, + -253, + -85, + -499, + -75, + -506 + ] + ], + "type": "Polygon", + "properties": { + "code": "SDS", + "name": "S. Sudan" + } + } + ] + } + } +} \ No newline at end of file diff --git a/showcase/static/showcase/maps/subdivisions.topo.json b/showcase/static/showcase/maps/subdivisions.topo.json new file mode 100644 index 0000000..610cdd2 --- /dev/null +++ b/showcase/static/showcase/maps/subdivisions.topo.json @@ -0,0 +1,10057 @@ +{ + "type": "Topology", + "arcs": [ + [ + [ + 6250, + 4580 + ], + [ + -226, + 0 + ], + [ + -148, + 0 + ] + ], + [ + [ + 5876, + 4580 + ], + [ + -60, + 88 + ], + [ + 6, + 63 + ], + [ + -13, + 57 + ], + [ + -38, + 30 + ], + [ + -38, + 62 + ], + [ + -35, + 26 + ], + [ + -63, + 101 + ], + [ + -24, + -8 + ], + [ + -35, + 64 + ], + [ + -25, + -2 + ], + [ + -112, + 154 + ], + [ + -42, + 9 + ], + [ + -58, + 46 + ], + [ + -10, + 51 + ], + [ + 0, + 294 + ], + [ + 0, + 235 + ], + [ + 0, + 411 + ] + ], + [ + [ + 5329, + 6261 + ], + [ + 345, + 0 + ], + [ + 231, + 0 + ], + [ + 345, + 0 + ] + ], + [ + [ + 6250, + 6261 + ], + [ + 0, + -420 + ], + [ + 0, + -421 + ], + [ + 0, + -262 + ], + [ + 0, + -210 + ], + [ + 0, + -368 + ] + ], + [ + [ + 5876, + 4580 + ], + [ + -183, + 0 + ] + ], + [ + [ + 5693, + 4580 + ], + [ + -91, + 0 + ] + ], + [ + [ + 5602, + 4580 + ], + [ + -245, + 0 + ], + [ + -285, + 0 + ] + ], + [ + [ + 5072, + 4580 + ], + [ + -24, + 0 + ] + ], + [ + [ + 5048, + 4580 + ], + [ + -3, + 0 + ] + ], + [ + [ + 5045, + 4580 + ], + [ + -23, + 71 + ], + [ + -48, + 3 + ], + [ + -26, + 48 + ], + [ + -59, + 35 + ], + [ + -25, + 60 + ], + [ + -125, + 17 + ], + [ + 1, + 43 + ], + [ + -61, + 9 + ], + [ + -60, + 43 + ], + [ + 6, + 50 + ], + [ + -42, + 48 + ], + [ + -23, + 56 + ], + [ + 23, + 107 + ], + [ + -32, + 3 + ], + [ + -19, + 56 + ], + [ + -58, + 23 + ], + [ + -25, + -22 + ], + [ + -71, + 72 + ], + [ + 26, + 63 + ], + [ + -35, + 44 + ], + [ + 50, + 113 + ], + [ + -13, + 111 + ] + ], + [ + [ + 4406, + 5633 + ], + [ + -66, + 69 + ], + [ + -103, + 69 + ], + [ + -180, + 292 + ], + [ + -104, + 89 + ], + [ + -49, + 77 + ], + [ + -78, + -28 + ], + [ + -23, + -70 + ], + [ + -79, + -38 + ], + [ + -15, + 50 + ], + [ + -134, + 118 + ] + ], + [ + [ + 3575, + 6261 + ], + [ + 263, + 0 + ], + [ + 351, + 0 + ], + [ + 350, + 0 + ], + [ + 263, + 0 + ], + [ + 176, + 0 + ] + ], + [ + [ + 4978, + 6261 + ], + [ + 351, + 0 + ] + ], + [ + [ + 4389, + 5501 + ], + [ + 16, + 42 + ], + [ + 1, + 90 + ] + ], + [ + [ + 4406, + 5633 + ], + [ + 1, + -92 + ], + [ + -18, + -40 + ] + ], + [ + [ + 4389, + 5501 + ], + [ + -34, + -39 + ] + ], + [ + [ + 4355, + 5462 + ], + [ + 34, + 39 + ] + ], + [ + [ + 4164, + 5364 + ], + [ + 88, + -22 + ], + [ + -29, + -110 + ], + [ + -68, + 7 + ], + [ + -28, + 72 + ], + [ + 37, + 53 + ] + ], + [ + [ + 4247, + 5222 + ], + [ + 2, + -67 + ], + [ + -40, + 4 + ], + [ + -17, + 54 + ], + [ + 55, + 9 + ] + ], + [ + [ + 4666, + 4831 + ], + [ + 158, + -49 + ], + [ + 78, + -136 + ], + [ + 59, + -31 + ], + [ + 46, + -98 + ], + [ + -9, + -38 + ], + [ + -101, + 40 + ], + [ + -105, + 76 + ], + [ + 0, + 28 + ], + [ + -66, + 22 + ], + [ + -12, + 70 + ], + [ + -40, + 0 + ], + [ + -106, + 112 + ], + [ + 32, + 38 + ], + [ + 66, + -34 + ] + ], + [ + [ + 8188, + 5780 + ], + [ + -159, + -166 + ], + [ + -271, + -308 + ], + [ + -141, + -141 + ], + [ + -1, + -330 + ], + [ + 1, + -198 + ] + ], + [ + [ + 7617, + 4637 + ], + [ + -1, + -58 + ], + [ + -190, + 1 + ] + ], + [ + [ + 7426, + 4580 + ], + [ + -185, + 0 + ], + [ + -196, + 0 + ] + ], + [ + [ + 7045, + 4580 + ], + [ + -22, + 391 + ], + [ + -11, + 195 + ], + [ + -15, + 261 + ], + [ + -11, + 195 + ], + [ + 0, + 280 + ], + [ + 0, + 359 + ] + ], + [ + [ + 6986, + 6261 + ], + [ + 415, + 0 + ], + [ + 251, + 0 + ] + ], + [ + [ + 7652, + 6261 + ], + [ + 5, + -168 + ], + [ + 40, + -28 + ], + [ + 93, + 6 + ], + [ + 94, + -267 + ], + [ + 105, + 36 + ], + [ + 48, + -3 + ], + [ + 74, + -37 + ], + [ + 77, + -20 + ] + ], + [ + [ + 10482, + 4124 + ], + [ + -26, + -27 + ] + ], + [ + [ + 10456, + 4097 + ], + [ + -144, + -93 + ], + [ + -91, + -24 + ], + [ + -23, + 16 + ] + ], + [ + [ + 10198, + 3996 + ], + [ + -32, + 16 + ], + [ + 3, + 50 + ], + [ + -32, + 15 + ], + [ + -2, + 211 + ], + [ + -47, + 41 + ], + [ + -68, + -9 + ] + ], + [ + [ + 10020, + 4320 + ], + [ + 62, + 45 + ], + [ + 0, + 52 + ], + [ + 71, + 11 + ], + [ + 22, + -22 + ], + [ + 61, + 25 + ] + ], + [ + [ + 10236, + 4431 + ], + [ + 79, + -17 + ], + [ + 17, + -32 + ], + [ + 40, + 17 + ], + [ + 49, + -13 + ], + [ + -20, + -54 + ], + [ + -37, + -41 + ], + [ + 38, + -33 + ], + [ + 33, + -99 + ], + [ + 47, + -35 + ] + ], + [ + [ + 11121, + 4954 + ], + [ + 0, + 85 + ], + [ + -188, + 0 + ], + [ + -299, + 0 + ], + [ + -112, + 0 + ], + [ + -38, + 80 + ], + [ + -25, + -121 + ], + [ + -78, + 65 + ], + [ + -83, + -7 + ], + [ + -60, + 94 + ], + [ + -35, + 4 + ], + [ + 12, + 88 + ], + [ + -76, + 108 + ], + [ + 13, + 72 + ], + [ + 89, + 44 + ], + [ + -7, + 80 + ], + [ + 97, + -88 + ], + [ + 123, + -3 + ], + [ + 54, + -17 + ], + [ + 22, + 85 + ], + [ + 33, + 21 + ], + [ + -50, + 85 + ], + [ + 11, + 25 + ], + [ + -51, + 56 + ], + [ + 2, + 46 + ], + [ + 33, + 81 + ], + [ + 1, + 54 + ], + [ + -58, + 90 + ], + [ + 48, + 45 + ], + [ + -41, + 62 + ], + [ + -48, + 103 + ], + [ + 19, + 117 + ] + ], + [ + [ + 10429, + 6308 + ], + [ + 99, + -149 + ], + [ + 32, + -73 + ], + [ + 55, + -58 + ], + [ + 26, + -77 + ], + [ + 38, + -17 + ], + [ + 4, + -73 + ], + [ + 48, + -57 + ], + [ + -17, + -94 + ], + [ + 39, + -80 + ], + [ + 24, + 14 + ], + [ + 83, + -107 + ], + [ + 86, + -17 + ], + [ + 20, + -47 + ], + [ + 54, + 4 + ], + [ + 73, + -45 + ], + [ + -69, + -34 + ], + [ + 68, + -29 + ], + [ + 24, + -48 + ], + [ + 63, + -12 + ], + [ + 61, + -85 + ], + [ + -3, + -138 + ], + [ + -17, + -58 + ], + [ + -99, + -74 + ] + ], + [ + [ + 11272, + 4968 + ], + [ + -38, + -96 + ], + [ + -76, + -129 + ], + [ + 86, + -16 + ], + [ + -12, + -58 + ], + [ + 80, + -42 + ], + [ + 41, + 29 + ], + [ + 57, + -8 + ], + [ + 35, + -46 + ], + [ + -25, + -50 + ], + [ + 29, + -89 + ], + [ + -15, + -47 + ], + [ + 68, + 16 + ], + [ + -20, + -57 + ], + [ + 48, + -16 + ], + [ + -38, + -132 + ], + [ + -51, + -1 + ], + [ + 4, + 43 + ], + [ + -55, + -12 + ], + [ + 28, + 77 + ], + [ + -11, + 57 + ], + [ + -41, + -45 + ], + [ + -39, + -12 + ], + [ + -42, + -73 + ], + [ + -44, + -6 + ], + [ + 55, + 89 + ], + [ + -94, + 34 + ], + [ + -68, + -15 + ], + [ + -127, + 16 + ], + [ + -72, + -17 + ], + [ + -23, + 45 + ], + [ + 60, + 71 + ], + [ + 0, + 41 + ], + [ + 64, + 145 + ], + [ + 51, + 140 + ], + [ + 66, + 124 + ], + [ + 67, + 45 + ], + [ + 52, + -5 + ] + ], + [ + [ + 10482, + 4124 + ], + [ + 68, + -39 + ], + [ + 75, + -20 + ], + [ + 49, + 37 + ], + [ + 42, + -27 + ], + [ + 19, + -69 + ], + [ + -113, + -60 + ], + [ + -115, + -55 + ], + [ + -48, + 10 + ], + [ + -9, + -38 + ], + [ + -44, + -66 + ], + [ + -81, + -47 + ], + [ + -35, + 39 + ], + [ + 2, + 84 + ], + [ + 41, + 60 + ], + [ + 69, + 55 + ], + [ + 7, + 54 + ], + [ + 47, + 55 + ] + ], + [ + [ + 10752, + 4114 + ], + [ + 27, + -32 + ], + [ + 31, + 32 + ], + [ + -3, + 40 + ], + [ + 59, + -7 + ], + [ + -48, + -77 + ], + [ + -83, + -13 + ], + [ + -19, + 57 + ], + [ + 57, + 130 + ], + [ + 50, + -4 + ], + [ + -23, + -91 + ], + [ + -48, + -35 + ] + ], + [ + [ + 4978, + 6261 + ], + [ + -72, + 101 + ], + [ + -72, + 20 + ], + [ + -139, + 1 + ], + [ + -17, + 87 + ], + [ + -85, + 52 + ], + [ + -52, + 62 + ], + [ + -65, + 8 + ], + [ + -2, + 42 + ], + [ + -75, + 134 + ], + [ + 24, + 25 + ], + [ + -75, + 71 + ], + [ + -41, + 69 + ], + [ + -134, + 58 + ], + [ + -4, + 77 + ], + [ + 37, + 48 + ], + [ + -38, + 66 + ], + [ + -90, + -10 + ], + [ + -4, + 92 + ], + [ + -39, + 67 + ], + [ + -191, + 0 + ], + [ + -29, + 113 + ], + [ + 0, + 176 + ] + ], + [ + [ + 3815, + 7620 + ], + [ + 52, + 3 + ], + [ + 17, + 60 + ], + [ + 51, + 24 + ], + [ + 182, + -5 + ], + [ + 30, + 33 + ], + [ + 83, + 16 + ], + [ + 133, + 59 + ], + [ + 140, + -65 + ], + [ + 111, + 77 + ], + [ + 58, + 3 + ], + [ + 48, + -78 + ], + [ + 51, + -40 + ], + [ + 65, + 24 + ], + [ + 54, + 56 + ], + [ + 107, + -94 + ], + [ + 54, + 66 + ], + [ + 137, + -5 + ], + [ + 78, + -32 + ] + ], + [ + [ + 5266, + 7722 + ], + [ + 1, + -239 + ], + [ + 305, + -155 + ], + [ + 283, + -143 + ], + [ + 164, + -84 + ], + [ + 169, + 0 + ], + [ + 106, + -91 + ], + [ + 50, + -19 + ], + [ + 402, + -53 + ], + [ + 241, + -31 + ], + [ + -1, + -315 + ], + [ + 0, + -331 + ] + ], + [ + [ + 6986, + 6261 + ], + [ + -276, + 0 + ], + [ + -184, + 0 + ], + [ + -276, + 0 + ] + ], + [ + [ + 6249, + 9115 + ], + [ + 1, + -55 + ] + ], + [ + [ + 6250, + 9060 + ], + [ + -290, + 13 + ], + [ + 191, + 46 + ], + [ + 98, + -4 + ] + ], + [ + [ + 6250, + 9024 + ], + [ + 0, + -24 + ] + ], + [ + [ + 6250, + 9000 + ], + [ + -18, + -62 + ], + [ + -162, + -28 + ], + [ + -111, + 29 + ], + [ + -3, + 58 + ], + [ + 294, + 27 + ] + ], + [ + [ + 5739, + 8913 + ], + [ + -62, + -115 + ], + [ + -290, + -59 + ], + [ + -50, + -56 + ], + [ + -184, + 27 + ], + [ + -79, + 30 + ], + [ + 107, + 32 + ], + [ + 232, + 132 + ], + [ + 326, + 9 + ] + ], + [ + [ + 6250, + 8635 + ], + [ + 0, + -106 + ] + ], + [ + [ + 6250, + 8529 + ], + [ + -232, + -66 + ], + [ + -92, + 2 + ], + [ + -57, + 52 + ], + [ + 232, + 61 + ], + [ + -379, + -31 + ], + [ + -172, + 47 + ], + [ + 91, + 122 + ], + [ + 95, + 56 + ], + [ + 128, + 2 + ], + [ + 138, + -38 + ], + [ + 151, + -100 + ], + [ + 97, + -1 + ] + ], + [ + [ + 6250, + 8778 + ], + [ + 0, + -36 + ] + ], + [ + [ + 6250, + 8742 + ], + [ + 0, + 36 + ] + ], + [ + [ + 5353, + 8417 + ], + [ + 163, + 23 + ], + [ + 71, + -14 + ], + [ + 156, + -85 + ], + [ + 5, + -27 + ], + [ + -323, + -115 + ], + [ + -41, + -50 + ], + [ + -71, + -23 + ], + [ + -41, + -107 + ], + [ + -238, + -59 + ], + [ + -74, + 85 + ], + [ + -161, + 70 + ], + [ + 71, + 69 + ], + [ + 14, + 74 + ], + [ + 96, + 106 + ], + [ + -83, + 89 + ], + [ + 311, + 27 + ], + [ + 145, + -63 + ] + ], + [ + [ + 6250, + 8244 + ], + [ + 0, + -289 + ], + [ + 0, + -166 + ], + [ + -413, + 0 + ], + [ + -237, + 0 + ], + [ + 19, + -54 + ] + ], + [ + [ + 5619, + 7735 + ], + [ + -26, + 69 + ], + [ + 234, + 32 + ], + [ + 180, + -13 + ], + [ + 48, + 34 + ], + [ + -151, + 37 + ], + [ + -206, + -16 + ], + [ + -147, + 7 + ], + [ + -62, + 39 + ], + [ + 41, + 41 + ], + [ + -97, + 81 + ], + [ + -7, + 46 + ], + [ + 68, + 42 + ], + [ + -15, + 42 + ], + [ + 166, + 79 + ], + [ + 178, + 49 + ], + [ + 49, + -78 + ], + [ + 124, + 19 + ], + [ + 137, + -42 + ], + [ + 98, + -8 + ], + [ + 19, + 49 + ] + ], + [ + [ + 5266, + 7722 + ], + [ + 77, + -34 + ], + [ + 162, + -46 + ], + [ + 186, + -28 + ], + [ + 40, + 18 + ], + [ + 112, + -48 + ], + [ + 42, + -40 + ], + [ + -74, + -20 + ], + [ + -34, + -69 + ], + [ + 134, + -18 + ], + [ + 115, + -2 + ], + [ + 133, + 16 + ], + [ + 87, + 29 + ], + [ + 38, + -38 + ], + [ + 95, + -22 + ], + [ + 56, + -51 + ], + [ + -43, + -29 + ], + [ + 120, + -28 + ], + [ + -102, + 194 + ], + [ + -39, + 19 + ], + [ + 34, + 51 + ], + [ + 198, + 48 + ], + [ + 68, + -71 + ], + [ + 114, + -65 + ], + [ + 66, + 13 + ], + [ + 72, + -47 + ], + [ + 104, + -18 + ], + [ + 102, + 22 + ], + [ + 120, + -17 + ], + [ + 67, + 15 + ], + [ + 89, + -32 + ], + [ + 23, + 37 + ], + [ + -114, + 32 + ], + [ + 21, + 38 + ], + [ + 87, + 21 + ], + [ + 27, + -30 + ], + [ + 87, + -15 + ], + [ + -31, + -92 + ], + [ + 54, + -55 + ], + [ + 48, + 10 + ], + [ + -36, + 73 + ], + [ + 18, + 43 + ], + [ + 66, + 8 + ], + [ + 100, + 72 + ], + [ + -3, + 53 + ], + [ + -54, + 86 + ], + [ + -170, + 64 + ], + [ + -39, + 69 + ], + [ + 13, + 145 + ], + [ + 110, + 96 + ], + [ + 83, + -21 + ], + [ + 125, + -77 + ], + [ + -3, + -62 + ], + [ + 130, + -103 + ], + [ + -109, + -71 + ], + [ + 178, + -65 + ], + [ + 32, + -65 + ], + [ + 130, + 61 + ], + [ + 94, + -69 + ], + [ + 21, + -62 + ], + [ + -49, + -18 + ], + [ + 13, + -80 + ], + [ + 86, + -89 + ], + [ + 67, + 51 + ], + [ + 54, + 85 + ], + [ + 20, + 85 + ], + [ + 80, + 68 + ], + [ + -48, + 24 + ], + [ + -11, + 94 + ], + [ + 117, + -2 + ], + [ + 149, + -22 + ], + [ + -2, + -35 + ], + [ + 121, + -52 + ], + [ + 4, + -71 + ], + [ + -117, + -32 + ], + [ + 53, + -89 + ], + [ + 65, + -62 + ], + [ + -18, + -59 + ], + [ + -108, + -74 + ], + [ + -169, + -62 + ], + [ + -89, + 55 + ], + [ + -110, + -1 + ], + [ + 55, + -78 + ], + [ + -115, + -102 + ], + [ + -63, + -1 + ], + [ + -164, + 90 + ], + [ + -16, + -24 + ], + [ + 88, + -66 + ], + [ + 179, + -23 + ], + [ + -23, + -57 + ], + [ + -76, + -98 + ], + [ + -51, + -27 + ], + [ + -137, + -4 + ], + [ + 12, + -27 + ], + [ + -121, + -45 + ], + [ + 54, + -24 + ], + [ + -12, + -62 + ], + [ + -53, + -22 + ], + [ + -84, + 3 + ], + [ + -98, + -170 + ], + [ + -59, + -60 + ], + [ + -53, + -137 + ], + [ + -12, + -64 + ] + ], + [ + [ + 6249, + 9115 + ], + [ + 1, + -55 + ] + ], + [ + [ + 6250, + 9024 + ], + [ + 0, + -24 + ] + ], + [ + [ + 6250, + 8635 + ], + [ + 0, + 107 + ] + ], + [ + [ + 6250, + 8778 + ], + [ + 126, + 17 + ], + [ + 81, + -99 + ], + [ + 125, + 18 + ], + [ + 84, + -48 + ], + [ + -35, + -84 + ], + [ + -119, + -41 + ], + [ + -154, + 21 + ], + [ + -108, + -33 + ] + ], + [ + [ + 6250, + 8244 + ], + [ + 120, + -74 + ], + [ + 45, + -114 + ], + [ + 83, + 22 + ], + [ + -36, + 39 + ], + [ + -50, + 146 + ], + [ + 48, + 34 + ], + [ + 114, + -20 + ], + [ + 98, + -63 + ], + [ + 17, + -57 + ], + [ + 81, + -149 + ], + [ + -20, + -51 + ], + [ + 135, + -91 + ], + [ + 180, + -55 + ], + [ + 20, + -66 + ], + [ + -115, + 20 + ], + [ + -41, + -45 + ], + [ + 60, + -22 + ], + [ + 11, + -59 + ], + [ + -149, + -33 + ], + [ + -143, + 42 + ], + [ + -103, + 12 + ], + [ + -47, + 43 + ], + [ + -72, + -67 + ], + [ + -139, + -37 + ], + [ + -218, + -33 + ], + [ + -167, + -8 + ], + [ + -45, + 53 + ], + [ + -7, + 55 + ], + [ + -135, + 10 + ], + [ + -125, + 25 + ], + [ + -31, + 34 + ] + ], + [ + [ + 8559, + 7065 + ], + [ + 139, + -24 + ], + [ + 125, + -71 + ], + [ + 31, + -95 + ], + [ + 82, + 11 + ], + [ + 48, + -50 + ], + [ + -68, + -46 + ], + [ + -123, + 37 + ], + [ + -8, + 34 + ], + [ + -95, + 26 + ], + [ + -21, + -44 + ], + [ + -83, + -77 + ], + [ + -80, + -26 + ], + [ + -20, + 80 + ], + [ + -136, + 2 + ], + [ + 86, + 71 + ], + [ + -11, + 65 + ], + [ + 38, + 174 + ], + [ + 67, + 14 + ], + [ + 29, + -81 + ] + ], + [ + [ + 8828, + 6712 + ], + [ + -11, + -46 + ], + [ + -83, + -67 + ], + [ + -62, + -8 + ], + [ + -19, + 48 + ], + [ + 48, + 66 + ], + [ + 127, + 7 + ] + ], + [ + [ + 9054, + 6629 + ], + [ + 20, + -59 + ], + [ + -36, + -63 + ], + [ + -51, + 38 + ], + [ + 4, + 45 + ], + [ + 63, + 39 + ] + ], + [ + [ + 9110, + 5691 + ], + [ + -22, + -59 + ], + [ + -76, + 8 + ], + [ + 37, + 47 + ], + [ + 61, + 4 + ] + ], + [ + [ + 8945, + 5153 + ], + [ + -102, + 32 + ], + [ + -1, + 35 + ], + [ + 66, + 3 + ], + [ + 37, + -70 + ] + ], + [ + [ + 9980, + 9777 + ], + [ + 434, + -22 + ], + [ + 311, + -66 + ], + [ + -72, + -61 + ], + [ + -221, + -47 + ], + [ + -83, + -69 + ], + [ + -429, + -135 + ], + [ + -115, + -97 + ], + [ + -356, + -52 + ], + [ + -92, + -64 + ], + [ + 168, + -43 + ], + [ + -132, + -109 + ], + [ + -198, + -10 + ], + [ + -6, + -65 + ], + [ + -116, + -55 + ], + [ + 97, + -28 + ], + [ + 0, + -62 + ], + [ + -221, + -60 + ], + [ + -45, + 51 + ], + [ + -250, + -9 + ], + [ + -115, + -22 + ], + [ + -408, + 28 + ], + [ + 6, + 51 + ], + [ + 102, + 43 + ], + [ + 140, + 14 + ], + [ + -112, + 80 + ], + [ + 99, + 26 + ], + [ + -49, + 43 + ], + [ + 68, + 92 + ], + [ + 230, + 30 + ], + [ + -72, + 98 + ], + [ + -122, + 35 + ], + [ + 10, + 73 + ], + [ + 238, + -14 + ], + [ + 338, + 46 + ], + [ + -308, + 28 + ], + [ + -176, + -29 + ], + [ + -332, + 43 + ], + [ + -95, + 56 + ], + [ + 89, + 56 + ], + [ + -139, + 52 + ], + [ + 360, + 47 + ], + [ + 155, + 40 + ], + [ + 218, + -31 + ], + [ + 38, + 54 + ], + [ + 206, + 52 + ], + [ + 221, + -9 + ], + [ + 160, + 25 + ], + [ + 532, + 11 + ], + [ + 44, + -15 + ] + ], + [ + [ + 7918, + 9489 + ], + [ + 114, + -82 + ], + [ + 273, + -34 + ], + [ + 49, + -109 + ], + [ + 152, + -20 + ], + [ + 19, + -49 + ], + [ + -159, + -47 + ], + [ + -163, + -108 + ], + [ + -168, + -7 + ], + [ + -190, + 37 + ], + [ + -281, + 157 + ], + [ + -96, + 110 + ], + [ + 106, + 40 + ], + [ + -47, + 45 + ], + [ + 79, + 47 + ], + [ + 312, + 20 + ] + ], + [ + [ + 6855, + 9211 + ], + [ + 352, + -111 + ], + [ + 40, + -111 + ], + [ + -130, + 5 + ], + [ + -45, + 46 + ], + [ + -153, + 27 + ], + [ + -147, + -15 + ], + [ + 75, + 76 + ], + [ + -186, + 40 + ], + [ + 14, + 45 + ], + [ + 180, + -2 + ] + ], + [ + [ + 7520, + 9092 + ], + [ + 121, + -29 + ], + [ + -18, + -54 + ], + [ + -175, + -28 + ], + [ + -117, + 95 + ], + [ + 4, + 57 + ], + [ + 185, + -41 + ] + ], + [ + [ + 7586, + 8979 + ], + [ + 201, + -8 + ], + [ + -20, + -41 + ], + [ + -227, + 2 + ], + [ + 46, + 47 + ] + ], + [ + [ + 7696, + 8844 + ], + [ + 145, + -47 + ], + [ + 130, + 12 + ], + [ + 42, + -37 + ], + [ + 144, + -21 + ], + [ + -89, + -38 + ], + [ + 189, + -83 + ], + [ + 87, + 17 + ], + [ + 109, + -18 + ], + [ + 197, + 48 + ], + [ + 164, + 2 + ], + [ + 229, + -58 + ], + [ + 14, + -87 + ], + [ + -70, + -46 + ], + [ + -141, + -16 + ], + [ + -159, + 17 + ], + [ + -82, + -12 + ], + [ + -368, + -2 + ], + [ + -131, + 8 + ], + [ + -195, + 38 + ], + [ + -43, + 84 + ], + [ + 22, + 77 + ], + [ + -83, + 77 + ], + [ + -201, + -14 + ], + [ + -126, + 67 + ], + [ + 92, + 55 + ], + [ + 124, + -23 + ] + ], + [ + [ + 7382, + 8776 + ], + [ + 27, + -139 + ], + [ + -36, + -67 + ], + [ + -224, + -17 + ], + [ + -44, + 61 + ], + [ + -168, + 17 + ], + [ + 102, + 73 + ], + [ + -65, + 45 + ], + [ + 161, + 50 + ], + [ + 247, + -23 + ] + ], + [ + [ + 6966, + 8707 + ], + [ + -101, + -38 + ], + [ + -95, + 64 + ], + [ + 163, + 15 + ], + [ + 33, + -41 + ] + ], + [ + [ + 7765, + 8557 + ], + [ + 0, + -52 + ], + [ + -106, + -7 + ], + [ + -145, + 42 + ], + [ + -27, + 27 + ], + [ + 82, + 66 + ], + [ + 115, + 10 + ], + [ + 81, + -86 + ] + ], + [ + [ + 7799, + 8424 + ], + [ + 88, + -29 + ], + [ + 172, + -16 + ], + [ + -163, + -170 + ], + [ + -112, + 7 + ], + [ + -64, + -118 + ], + [ + -107, + 0 + ], + [ + -32, + 115 + ], + [ + -8, + 140 + ], + [ + 60, + 53 + ], + [ + 166, + 18 + ] + ], + [ + [ + 7170, + 8391 + ], + [ + 78, + -33 + ], + [ + 145, + 24 + ], + [ + 54, + -33 + ], + [ + -73, + -59 + ], + [ + 68, + -99 + ], + [ + 40, + -122 + ], + [ + -188, + -82 + ], + [ + -47, + 10 + ], + [ + -131, + 120 + ], + [ + -104, + 25 + ], + [ + -91, + 72 + ], + [ + 73, + 41 + ], + [ + 52, + -47 + ], + [ + 80, + 4 + ], + [ + 19, + 53 + ], + [ + -108, + 48 + ], + [ + 49, + 57 + ], + [ + 84, + 21 + ] + ], + [ + [ + 8405, + 7943 + ], + [ + 87, + 22 + ], + [ + 79, + -10 + ], + [ + 12, + 76 + ], + [ + -115, + 61 + ], + [ + 52, + 66 + ], + [ + -28, + 54 + ], + [ + 58, + 86 + ], + [ + 217, + 60 + ], + [ + 116, + -14 + ], + [ + 104, + -136 + ], + [ + -62, + -82 + ], + [ + 179, + 10 + ], + [ + 92, + 63 + ], + [ + 102, + 5 + ], + [ + 147, + -37 + ], + [ + 36, + -58 + ], + [ + 110, + -58 + ], + [ + 191, + -31 + ], + [ + 78, + -63 + ], + [ + 21, + -56 + ], + [ + 128, + 4 + ], + [ + 167, + -111 + ], + [ + -106, + -70 + ], + [ + 160, + -37 + ], + [ + -90, + -45 + ], + [ + -26, + -75 + ], + [ + 92, + -34 + ], + [ + 74, + -56 + ], + [ + 157, + -23 + ], + [ + 48, + -71 + ], + [ + 89, + -17 + ], + [ + 60, + -50 + ], + [ + 38, + 17 + ], + [ + 62, + -56 + ], + [ + -64, + -94 + ], + [ + -61, + -61 + ], + [ + -65, + -14 + ], + [ + -4, + -65 + ], + [ + -116, + 8 + ], + [ + -68, + 90 + ], + [ + 9, + 38 + ], + [ + -108, + 41 + ], + [ + -65, + -37 + ], + [ + -99, + -15 + ], + [ + 88, + -69 + ], + [ + 41, + -60 + ], + [ + 146, + -71 + ], + [ + 24, + -95 + ], + [ + 31, + 3 + ], + [ + 15, + -116 + ], + [ + -51, + -1 + ], + [ + -18, + -83 + ], + [ + -66, + 43 + ], + [ + -60, + 12 + ], + [ + -111, + 57 + ], + [ + 15, + -54 + ], + [ + 128, + -121 + ], + [ + 3, + -67 + ], + [ + -109, + 44 + ], + [ + -152, + 38 + ], + [ + -42, + 52 + ], + [ + -64, + 3 + ], + [ + -94, + 43 + ], + [ + -201, + 211 + ], + [ + -99, + 37 + ], + [ + -51, + -32 + ], + [ + -152, + -33 + ], + [ + -99, + 19 + ], + [ + -35, + 38 + ], + [ + 7, + 49 + ], + [ + 60, + 34 + ], + [ + 11, + 45 + ], + [ + 138, + -35 + ], + [ + 209, + 49 + ], + [ + -80, + 91 + ], + [ + 113, + 85 + ], + [ + 90, + 85 + ], + [ + -102, + 155 + ], + [ + -121, + 67 + ], + [ + -25, + 42 + ], + [ + -137, + -44 + ], + [ + 57, + 95 + ], + [ + -124, + 51 + ], + [ + -170, + 142 + ], + [ + 8, + -92 + ], + [ + -67, + -13 + ], + [ + -136, + 30 + ], + [ + -96, + -38 + ], + [ + -88, + 25 + ], + [ + -70, + -6 + ], + [ + -227, + 28 + ], + [ + -28, + 39 + ], + [ + -117, + -23 + ], + [ + -88, + 41 + ], + [ + -47, + 84 + ], + [ + 140, + -19 + ], + [ + -3, + 40 + ], + [ + -111, + 12 + ], + [ + -70, + 31 + ], + [ + -17, + 70 + ], + [ + 70, + 171 + ], + [ + 142, + 100 + ], + [ + 88, + 17 + ], + [ + 165, + -21 + ], + [ + -102, + -67 + ], + [ + -50, + -59 + ], + [ + 54, + -168 + ], + [ + 94, + -64 + ], + [ + -145, + -52 + ] + ], + [ + [ + 9055, + 8347 + ], + [ + 115, + 1 + ], + [ + 99, + -25 + ], + [ + 85, + -64 + ], + [ + -10, + -40 + ], + [ + -133, + 12 + ], + [ + -153, + -22 + ], + [ + -63, + 72 + ], + [ + -59, + 24 + ], + [ + -2, + 52 + ], + [ + 121, + -10 + ] + ], + [ + [ + 6684, + 8235 + ], + [ + -151, + 85 + ], + [ + 29, + 33 + ], + [ + 101, + 11 + ], + [ + 80, + -23 + ], + [ + 6, + -40 + ], + [ + -65, + -66 + ] + ], + [ + [ + 7406, + 7734 + ], + [ + 105, + -46 + ], + [ + 57, + -93 + ], + [ + -66, + -40 + ], + [ + -99, + 11 + ], + [ + -164, + 49 + ], + [ + -28, + 26 + ], + [ + 102, + 46 + ], + [ + -9, + 32 + ], + [ + 102, + 15 + ] + ], + [ + [ + 9410, + 7532 + ], + [ + 48, + -13 + ], + [ + 3, + -107 + ], + [ + -60, + -38 + ], + [ + -113, + -3 + ], + [ + -28, + 67 + ], + [ + 52, + 80 + ], + [ + 98, + 14 + ] + ], + [ + [ + 8188, + 5780 + ], + [ + 81, + -59 + ], + [ + 47, + -62 + ], + [ + 173, + -70 + ], + [ + 57, + -48 + ], + [ + 106, + 4 + ], + [ + 123, + -25 + ], + [ + 33, + -51 + ], + [ + -19, + -70 + ], + [ + 26, + -82 + ], + [ + -11, + -131 + ], + [ + 61, + -81 + ], + [ + -6, + -21 + ], + [ + 93, + -82 + ], + [ + 26, + -65 + ], + [ + 49, + -24 + ], + [ + 29, + -39 + ] + ], + [ + [ + 9056, + 4874 + ], + [ + 1, + -360 + ], + [ + -3, + -177 + ], + [ + 17, + -58 + ], + [ + 53, + -96 + ], + [ + 101, + -32 + ], + [ + 117, + -105 + ], + [ + 47, + -12 + ], + [ + 96, + 34 + ], + [ + 43, + -12 + ], + [ + 5, + -54 + ] + ], + [ + [ + 9533, + 4002 + ], + [ + -34, + -32 + ] + ], + [ + [ + 9499, + 3970 + ], + [ + -43, + -16 + ], + [ + -118, + -128 + ], + [ + -33, + -66 + ], + [ + -175, + 0 + ], + [ + -42, + -25 + ], + [ + 13, + -101 + ], + [ + -67, + -40 + ] + ], + [ + [ + 9034, + 3594 + ], + [ + -70, + -33 + ] + ], + [ + [ + 8964, + 3561 + ], + [ + -70, + -18 + ], + [ + -106, + -81 + ], + [ + -63, + 42 + ] + ], + [ + [ + 8725, + 3504 + ], + [ + 4, + 53 + ], + [ + 49, + 50 + ], + [ + 37, + 144 + ], + [ + -38, + 272 + ], + [ + -96, + 72 + ], + [ + -35, + 40 + ], + [ + -20, + 71 + ], + [ + -34, + -14 + ], + [ + -29, + 68 + ], + [ + -322, + 214 + ], + [ + -103, + -46 + ] + ], + [ + [ + 8138, + 4428 + ], + [ + -124, + 31 + ], + [ + -62, + -22 + ], + [ + -137, + 84 + ], + [ + -65, + -13 + ], + [ + -84, + 33 + ], + [ + -22, + 86 + ], + [ + -27, + 10 + ] + ], + [ + [ + 9056, + 4881 + ], + [ + -18, + 23 + ], + [ + 18, + 65 + ] + ], + [ + [ + 9056, + 4969 + ], + [ + 0, + -88 + ] + ], + [ + [ + 10503, + 4194 + ], + [ + 62, + -7 + ], + [ + 89, + 10 + ], + [ + -65, + -74 + ], + [ + -71, + 35 + ], + [ + -15, + 36 + ] + ], + [ + [ + 10020, + 4320 + ], + [ + -17, + 26 + ], + [ + -71, + -115 + ], + [ + -26, + -123 + ], + [ + -73, + -93 + ] + ], + [ + [ + 9833, + 4015 + ], + [ + -40, + -44 + ] + ], + [ + [ + 9793, + 3971 + ], + [ + -169, + 0 + ] + ], + [ + [ + 9624, + 3971 + ], + [ + -125, + -1 + ] + ], + [ + [ + 9499, + 3970 + ], + [ + 106, + 65 + ], + [ + 37, + 89 + ], + [ + 116, + 95 + ], + [ + 59, + 19 + ], + [ + 68, + 42 + ], + [ + 141, + 190 + ], + [ + 131, + 89 + ], + [ + 128, + 54 + ], + [ + 60, + 8 + ], + [ + 63, + -11 + ], + [ + 53, + -41 + ], + [ + 1, + -57 + ], + [ + -93, + -81 + ], + [ + -61, + 26 + ], + [ + -72, + -26 + ] + ], + [ + [ + 11121, + 4954 + ], + [ + -130, + -23 + ], + [ + -61, + -78 + ], + [ + -84, + -81 + ], + [ + -111, + -8 + ], + [ + -131, + 16 + ], + [ + -199, + -4 + ], + [ + -37, + 6 + ], + [ + -112, + -16 + ], + [ + -42, + -34 + ], + [ + -39, + -98 + ], + [ + -84, + -23 + ], + [ + -60, + -56 + ], + [ + -77, + -112 + ], + [ + -12, + -41 + ], + [ + -74, + -105 + ], + [ + -52, + -53 + ], + [ + -56, + -17 + ], + [ + -102, + -73 + ], + [ + -45, + -72 + ], + [ + -52, + -36 + ], + [ + -28, + -44 + ] + ], + [ + [ + 9056, + 4874 + ], + [ + 0, + 7 + ] + ], + [ + [ + 9056, + 4969 + ], + [ + 50, + 29 + ], + [ + 45, + 79 + ], + [ + -21, + 58 + ], + [ + -48, + 225 + ], + [ + -39, + 91 + ], + [ + 70, + 28 + ], + [ + 93, + 54 + ], + [ + 52, + 49 + ], + [ + 63, + 84 + ], + [ + 12, + 92 + ], + [ + -5, + 72 + ], + [ + -54, + 128 + ], + [ + -125, + 102 + ], + [ + 8, + 33 + ], + [ + 61, + 73 + ], + [ + 3, + 45 + ], + [ + 39, + 56 + ], + [ + -52, + 114 + ], + [ + 13, + 100 + ], + [ + -37, + 102 + ], + [ + 6, + 38 + ], + [ + 64, + 33 + ], + [ + 247, + -59 + ], + [ + 98, + 41 + ], + [ + 142, + -111 + ], + [ + 61, + -87 + ], + [ + 105, + -14 + ], + [ + 59, + -58 + ], + [ + -11, + -46 + ], + [ + 7, + -160 + ], + [ + 47, + -68 + ], + [ + 44, + 2 + ], + [ + 34, + -48 + ], + [ + 70, + -58 + ], + [ + 88, + 51 + ], + [ + 92, + 86 + ], + [ + 16, + 102 + ], + [ + 47, + 72 + ], + [ + 29, + 9 + ] + ], + [ + [ + 10688, + 4595 + ], + [ + -39, + -2 + ], + [ + -124, + 49 + ], + [ + -52, + 83 + ], + [ + 117, + -37 + ], + [ + 96, + -64 + ], + [ + 2, + -29 + ] + ], + [ + [ + 7045, + 4580 + ], + [ + -246, + 0 + ] + ], + [ + [ + 6799, + 4580 + ], + [ + -186, + 0 + ], + [ + -196, + 0 + ], + [ + -167, + 0 + ] + ], + [ + [ + 3575, + 6261 + ], + [ + -3, + 52 + ], + [ + -82, + -24 + ], + [ + -95, + 18 + ], + [ + 0, + 402 + ], + [ + 0, + 267 + ], + [ + 0, + 224 + ], + [ + 0, + 223 + ], + [ + 0, + 312 + ] + ], + [ + [ + 3395, + 7735 + ], + [ + 168, + -21 + ], + [ + 97, + -55 + ], + [ + 155, + -39 + ] + ], + [ + [ + 4355, + 5462 + ], + [ + -43, + 59 + ], + [ + 12, + 89 + ], + [ + -34, + 42 + ], + [ + -51, + 22 + ], + [ + -90, + 135 + ], + [ + -60, + 20 + ], + [ + -8, + 80 + ], + [ + -47, + 79 + ], + [ + -65, + 37 + ], + [ + -49, + -30 + ], + [ + -51, + 49 + ], + [ + -67, + -51 + ], + [ + -88, + 51 + ], + [ + -75, + 78 + ], + [ + -171, + 97 + ], + [ + -58, + 4 + ], + [ + -76, + 33 + ], + [ + -118, + 20 + ], + [ + -79, + -13 + ], + [ + -101, + 49 + ], + [ + -91, + 22 + ], + [ + -90, + 80 + ], + [ + -136, + -23 + ], + [ + 14, + -104 + ], + [ + -22, + -28 + ], + [ + -92, + 2 + ], + [ + -70, + -66 + ], + [ + -36, + -1 + ], + [ + -35, + -49 + ], + [ + -71, + -8 + ], + [ + 0, + 122 + ], + [ + 26, + 33 + ], + [ + 12, + 82 + ], + [ + 81, + 43 + ], + [ + -15, + 43 + ], + [ + -104, + -60 + ], + [ + -1, + -24 + ], + [ + -125, + -134 + ], + [ + -90, + -78 + ], + [ + -4, + -37 + ], + [ + 73, + -40 + ], + [ + -63, + -56 + ], + [ + -21, + -51 + ], + [ + -70, + -22 + ], + [ + -136, + -105 + ], + [ + 1, + -34 + ], + [ + -102, + -72 + ], + [ + -77, + -30 + ], + [ + 13, + -37 + ], + [ + -115, + -59 + ], + [ + -40, + -2 + ], + [ + -105, + -60 + ], + [ + -59, + -2 + ], + [ + -31, + -38 + ], + [ + -73, + -29 + ], + [ + -9, + 35 + ], + [ + 75, + 82 + ], + [ + 86, + 46 + ], + [ + 34, + -38 + ], + [ + 50, + 83 + ], + [ + 94, + 57 + ], + [ + 89, + 93 + ], + [ + 65, + 47 + ], + [ + 8, + 125 + ], + [ + -90, + 65 + ], + [ + -53, + -58 + ], + [ + -54, + 68 + ], + [ + -64, + 21 + ], + [ + -128, + -67 + ], + [ + -7, + 149 + ], + [ + -38, + 90 + ], + [ + -90, + -51 + ], + [ + -64, + -6 + ], + [ + -69, + 76 + ], + [ + -64, + 37 + ], + [ + 51, + 53 + ], + [ + -70, + 32 + ], + [ + -48, + 107 + ], + [ + 82, + 103 + ], + [ + 72, + 113 + ], + [ + 97, + -26 + ], + [ + 127, + 62 + ], + [ + 81, + 16 + ], + [ + 30, + 40 + ], + [ + -15, + 116 + ], + [ + -23, + 53 + ], + [ + -53, + -16 + ], + [ + -96, + -68 + ], + [ + -84, + 33 + ], + [ + -109, + -20 + ], + [ + -114, + 19 + ], + [ + -117, + 128 + ], + [ + -63, + 36 + ], + [ + 315, + 137 + ], + [ + 83, + -3 + ], + [ + 7, + -69 + ], + [ + 173, + -4 + ], + [ + 24, + 30 + ], + [ + 122, + 26 + ], + [ + -58, + 38 + ], + [ + -92, + 4 + ], + [ + -10, + 54 + ], + [ + -95, + -4 + ], + [ + -66, + 26 + ], + [ + -38, + 63 + ], + [ + -207, + 125 + ], + [ + 15, + 70 + ], + [ + 176, + 8 + ], + [ + 105, + 69 + ], + [ + 19, + 57 + ], + [ + 99, + 87 + ], + [ + 81, + -4 + ], + [ + 155, + 88 + ], + [ + 121, + -5 + ], + [ + 112, + 72 + ], + [ + 149, + -34 + ], + [ + 90, + -45 + ], + [ + 88, + 20 + ], + [ + 92, + -19 + ], + [ + 27, + -54 + ], + [ + 246, + 7 + ], + [ + 144, + -43 + ], + [ + 174, + -9 + ], + [ + 57, + -23 + ], + [ + 182, + 16 + ], + [ + 167, + -70 + ], + [ + 37, + -1 + ] + ], + [ + [ + 591, + 6817 + ], + [ + 95, + 9 + ], + [ + 38, + -32 + ], + [ + 107, + -49 + ], + [ + -85, + -11 + ], + [ + -155, + 83 + ] + ], + [ + [ + 1081, + 6320 + ], + [ + 38, + -11 + ], + [ + 12, + -61 + ], + [ + -55, + -22 + ], + [ + -87, + 36 + ], + [ + 61, + 57 + ], + [ + 31, + 1 + ] + ], + [ + [ + 3977, + 5980 + ], + [ + 69, + -88 + ], + [ + 1, + -38 + ], + [ + -47, + -43 + ], + [ + -21, + 89 + ], + [ + -2, + 80 + ] + ], + [ + [ + 3881, + 5993 + ], + [ + 67, + -30 + ], + [ + -8, + -82 + ], + [ + -91, + 25 + ], + [ + -40, + 64 + ], + [ + 72, + 23 + ] + ], + [ + [ + 2300, + 5929 + ], + [ + 11, + -57 + ], + [ + -93, + -71 + ], + [ + -51, + -10 + ], + [ + -33, + 63 + ], + [ + 39, + 46 + ], + [ + 42, + -6 + ], + [ + 85, + 35 + ] + ], + [ + [ + 3951, + 5856 + ], + [ + 32, + -96 + ], + [ + -107, + 91 + ], + [ + 40, + 33 + ], + [ + 35, + -28 + ] + ], + [ + [ + 4098, + 5803 + ], + [ + 38, + -44 + ], + [ + -59, + -38 + ], + [ + -25, + 92 + ], + [ + 46, + -10 + ] + ], + [ + [ + 4080, + 5702 + ], + [ + 34, + -3 + ], + [ + 112, + -170 + ], + [ + 0, + -62 + ], + [ + -74, + 38 + ], + [ + -61, + 114 + ], + [ + 19, + 19 + ], + [ + -30, + 64 + ] + ], + [ + [ + 4318, + 5572 + ], + [ + -9, + -34 + ], + [ + -67, + -7 + ], + [ + 17, + 93 + ], + [ + 33, + 19 + ], + [ + 26, + -71 + ] + ], + [ + [ + 1326, + 5494 + ], + [ + 11, + -37 + ], + [ + -66, + -18 + ], + [ + -36, + -29 + ], + [ + -39, + 27 + ], + [ + 33, + 42 + ], + [ + 61, + 24 + ], + [ + 36, + -9 + ] + ], + [ + [ + 1037, + 5329 + ], + [ + 16, + -38 + ], + [ + -64, + -19 + ], + [ + 15, + 67 + ], + [ + 33, + -10 + ] + ], + [ + [ + 8323, + 1736 + ], + [ + -28, + -13 + ], + [ + -56, + 12 + ] + ], + [ + [ + 8239, + 1735 + ], + [ + -8, + 232 + ], + [ + 18, + 226 + ], + [ + 19, + 239 + ], + [ + -8, + 10 + ] + ], + [ + [ + 8260, + 2442 + ], + [ + 234, + 0 + ] + ], + [ + [ + 8494, + 2442 + ], + [ + 39, + -312 + ], + [ + 25, + -108 + ], + [ + -18, + -56 + ], + [ + 11, + -135 + ] + ], + [ + [ + 8551, + 1831 + ], + [ + -238, + 0 + ], + [ + 16, + -50 + ], + [ + -6, + -45 + ] + ], + [ + [ + 8119, + 2595 + ], + [ + -22, + -49 + ], + [ + -14, + -73 + ], + [ + -19, + -31 + ] + ], + [ + [ + 8064, + 2442 + ], + [ + -26, + -76 + ], + [ + -30, + -48 + ], + [ + -28, + -78 + ], + [ + 5, + -101 + ] + ], + [ + [ + 7985, + 2139 + ], + [ + -266, + 0 + ] + ], + [ + [ + 7719, + 2139 + ], + [ + 0, + 82 + ], + [ + -41, + 15 + ] + ], + [ + [ + 7678, + 2236 + ], + [ + 5, + 265 + ], + [ + -17, + 170 + ] + ], + [ + [ + 7666, + 2671 + ], + [ + 257, + 0 + ], + [ + 153, + 0 + ], + [ + 8, + -31 + ], + [ + -28, + -46 + ], + [ + 63, + 1 + ] + ], + [ + [ + 6338, + 1881 + ], + [ + -184, + 0 + ], + [ + -218, + 113 + ], + [ + -131, + 68 + ], + [ + 10, + 31 + ] + ], + [ + [ + 5815, + 2093 + ], + [ + 23, + 20 + ], + [ + -21, + 50 + ], + [ + 18, + 112 + ], + [ + 35, + 58 + ], + [ + -23, + 31 + ], + [ + -22, + 77 + ] + ], + [ + [ + 5825, + 2441 + ], + [ + -9, + 167 + ], + [ + 62, + 15 + ], + [ + 0, + 125 + ] + ], + [ + [ + 5878, + 2748 + ], + [ + 259, + 0 + ], + [ + 201, + 0 + ] + ], + [ + [ + 6338, + 2748 + ], + [ + 0, + -379 + ], + [ + 0, + -217 + ], + [ + 0, + -271 + ] + ], + [ + [ + 5815, + 2093 + ], + [ + -221, + -28 + ], + [ + -32, + 117 + ], + [ + -56, + 65 + ], + [ + -30, + 3 + ], + [ + -9, + 42 + ], + [ + -59, + 15 + ], + [ + -43, + 46 + ], + [ + -80, + 8 + ], + [ + -15, + 17 + ], + [ + 1, + 76 + ], + [ + -21, + 44 + ], + [ + -94, + 148 + ], + [ + 8, + 61 + ], + [ + -55, + 72 + ], + [ + -7, + 97 + ], + [ + -46, + 39 + ], + [ + -2, + 28 + ], + [ + -66, + 96 + ], + [ + -17, + 146 + ], + [ + -40, + 59 + ], + [ + -4, + 37 + ], + [ + 22, + 73 + ], + [ + 6, + 63 + ], + [ + -15, + 95 + ] + ], + [ + [ + 4940, + 3512 + ], + [ + 171, + 0 + ], + [ + 218, + 0 + ] + ], + [ + [ + 5329, + 3512 + ], + [ + 0, + -258 + ], + [ + 0, + -201 + ], + [ + 173, + -200 + ], + [ + 135, + -168 + ], + [ + 188, + -244 + ] + ], + [ + [ + 6338, + 2748 + ], + [ + 0, + 305 + ], + [ + 0, + 306 + ] + ], + [ + [ + 6338, + 3359 + ], + [ + 231, + 0 + ], + [ + 231, + 0 + ] + ], + [ + [ + 6800, + 3359 + ], + [ + 184, + 0 + ], + [ + 0, + -153 + ] + ], + [ + [ + 6984, + 3206 + ], + [ + 1, + -258 + ], + [ + 0, + -200 + ] + ], + [ + [ + 6985, + 2748 + ], + [ + -91, + 0 + ] + ], + [ + [ + 6894, + 2748 + ], + [ + -174, + 0 + ], + [ + -139, + 0 + ], + [ + -243, + 0 + ] + ], + [ + [ + 9767, + 3513 + ], + [ + -4, + -103 + ] + ], + [ + [ + 9763, + 3410 + ], + [ + -92, + -11 + ], + [ + -72, + -42 + ] + ], + [ + [ + 9599, + 3357 + ], + [ + 13, + 163 + ] + ], + [ + [ + 9612, + 3520 + ], + [ + 155, + -7 + ] + ], + [ + [ + 9286, + 3036 + ], + [ + -9, + 9 + ] + ], + [ + [ + 9277, + 3045 + ], + [ + 7, + 10 + ], + [ + 11, + -19 + ], + [ + -9, + 0 + ] + ], + [ + [ + 9469, + 2970 + ], + [ + -62, + 0 + ], + [ + -7, + 194 + ] + ], + [ + [ + 9400, + 3164 + ], + [ + 34, + 14 + ] + ], + [ + [ + 9434, + 3178 + ], + [ + -16, + -27 + ], + [ + 18, + -84 + ], + [ + 33, + -97 + ] + ], + [ + [ + 8551, + 1831 + ], + [ + 11, + -42 + ], + [ + 244, + -24 + ], + [ + 28, + 39 + ], + [ + 40, + -14 + ] + ], + [ + [ + 8874, + 1790 + ], + [ + 23, + -143 + ], + [ + 32, + -114 + ], + [ + 35, + -86 + ], + [ + -12, + -46 + ], + [ + 39, + -149 + ], + [ + 17, + -98 + ], + [ + -8, + -112 + ], + [ + -22, + -77 + ], + [ + -34, + -26 + ], + [ + -33, + 24 + ], + [ + -25, + 79 + ], + [ + -32, + 23 + ], + [ + -14, + 69 + ], + [ + -53, + 95 + ], + [ + -20, + 101 + ], + [ + -17, + 19 + ], + [ + 17, + 98 + ], + [ + 1, + 61 + ], + [ + -59, + 87 + ], + [ + -37, + 72 + ], + [ + -32, + 27 + ], + [ + -31, + -30 + ], + [ + -87, + -34 + ], + [ + -3, + 29 + ], + [ + -83, + 95 + ], + [ + -39, + -14 + ], + [ + -74, + -4 + ] + ], + [ + [ + 8494, + 2442 + ], + [ + 120, + -2 + ] + ], + [ + [ + 8614, + 2440 + ], + [ + 111, + 2 + ] + ], + [ + [ + 8725, + 2442 + ], + [ + -22, + -44 + ], + [ + 47, + -42 + ], + [ + 24, + -64 + ], + [ + 53, + -75 + ], + [ + 48, + -90 + ], + [ + 38, + -126 + ], + [ + 19, + -13 + ] + ], + [ + [ + 8932, + 1988 + ], + [ + -30, + -49 + ], + [ + -24, + -94 + ], + [ + -4, + -55 + ] + ], + [ + [ + 1849, + 373 + ], + [ + -29, + -21 + ], + [ + -15, + 41 + ], + [ + 29, + 18 + ], + [ + 15, + -38 + ] + ], + [ + [ + 2053, + 0 + ], + [ + -28, + 9 + ], + [ + -15, + 104 + ], + [ + 21, + 40 + ], + [ + -1, + 40 + ], + [ + 58, + -43 + ], + [ + 37, + -72 + ], + [ + -47, + -40 + ], + [ + -25, + -38 + ] + ], + [ + [ + 7959, + 3264 + ], + [ + -27, + 37 + ], + [ + -116, + -1 + ], + [ + -255, + -2 + ] + ], + [ + [ + 7561, + 3298 + ], + [ + -11, + 105 + ], + [ + -25, + 103 + ], + [ + -30, + 84 + ] + ], + [ + [ + 7495, + 3590 + ], + [ + -13, + 33 + ], + [ + 15, + 118 + ] + ], + [ + [ + 7497, + 3741 + ], + [ + 150, + 0 + ], + [ + 209, + 0 + ], + [ + 121, + 0 + ] + ], + [ + [ + 7977, + 3741 + ], + [ + 16, + -109 + ], + [ + 38, + -42 + ] + ], + [ + [ + 8031, + 3590 + ], + [ + 45, + -63 + ], + [ + -25, + -83 + ], + [ + -46, + -20 + ], + [ + -1, + -63 + ], + [ + -45, + -97 + ] + ], + [ + [ + 5693, + 4580 + ], + [ + 0, + -151 + ], + [ + 32, + -87 + ], + [ + 32, + -27 + ], + [ + 69, + -92 + ], + [ + 24, + -16 + ], + [ + -13, + -60 + ], + [ + 17, + -103 + ], + [ + 33, + 30 + ], + [ + 55, + -134 + ], + [ + 32, + -50 + ], + [ + 70, + 13 + ], + [ + 109, + -10 + ] + ], + [ + [ + 6153, + 3893 + ], + [ + 0, + -381 + ] + ], + [ + [ + 6153, + 3512 + ], + [ + -275, + 0 + ] + ], + [ + [ + 5878, + 3512 + ], + [ + -274, + 0 + ] + ], + [ + [ + 5604, + 3512 + ], + [ + -1, + 276 + ], + [ + 10, + 59 + ], + [ + -26, + 22 + ], + [ + 67, + 199 + ], + [ + -39, + 55 + ] + ], + [ + [ + 5615, + 4123 + ], + [ + -12, + 65 + ], + [ + -1, + 392 + ] + ], + [ + [ + 8031, + 3590 + ], + [ + 209, + -2 + ], + [ + 124, + -1 + ] + ], + [ + [ + 8364, + 3587 + ], + [ + -17, + -112 + ] + ], + [ + [ + 8347, + 3475 + ], + [ + -27, + 0 + ], + [ + -1, + -436 + ], + [ + -10, + -56 + ], + [ + -32, + -44 + ], + [ + -5, + -71 + ] + ], + [ + [ + 8272, + 2868 + ], + [ + -6, + -39 + ], + [ + -36, + -26 + ], + [ + 2, + -42 + ], + [ + -53, + 15 + ], + [ + -10, + -30 + ] + ], + [ + [ + 8169, + 2746 + ], + [ + -24, + 17 + ], + [ + -10, + 83 + ], + [ + -60, + 65 + ], + [ + -18, + 37 + ], + [ + 23, + 80 + ], + [ + -50, + 23 + ], + [ + -23, + 61 + ], + [ + -43, + 56 + ], + [ + -5, + 96 + ] + ], + [ + [ + 8347, + 3475 + ], + [ + 223, + 0 + ], + [ + 1, + -9 + ] + ], + [ + [ + 8571, + 3466 + ], + [ + -3, + -399 + ] + ], + [ + [ + 8568, + 3067 + ], + [ + 2, + -41 + ], + [ + -47, + -13 + ], + [ + -73, + -114 + ], + [ + -41, + -11 + ], + [ + -125, + -3 + ], + [ + -12, + -17 + ] + ], + [ + [ + 6984, + 3206 + ], + [ + 232, + 0 + ], + [ + 251, + 0 + ], + [ + 132, + 0 + ] + ], + [ + [ + 7599, + 3206 + ], + [ + 42, + -33 + ], + [ + -17, + -29 + ], + [ + 42, + -72 + ], + [ + 0, + -324 + ] + ], + [ + [ + 7666, + 2748 + ], + [ + -191, + 0 + ], + [ + -213, + 0 + ], + [ + -277, + 0 + ] + ], + [ + [ + 8568, + 3067 + ], + [ + 36, + 0 + ], + [ + 19, + -34 + ], + [ + 49, + -33 + ], + [ + 75, + 9 + ], + [ + 25, + -40 + ] + ], + [ + [ + 8772, + 2969 + ], + [ + 2, + -53 + ], + [ + 28, + -63 + ], + [ + 29, + -23 + ] + ], + [ + [ + 8831, + 2830 + ], + [ + -66, + -61 + ], + [ + -43, + -58 + ], + [ + -48, + -24 + ] + ], + [ + [ + 8674, + 2687 + ], + [ + -133, + 4 + ], + [ + -128, + 5 + ], + [ + -123, + -3 + ], + [ + -20, + -22 + ], + [ + -128, + 0 + ] + ], + [ + [ + 8142, + 2671 + ], + [ + 23, + 19 + ], + [ + 4, + 56 + ] + ], + [ + [ + 8139, + 2672 + ], + [ + -7, + -1 + ] + ], + [ + [ + 8132, + 2671 + ], + [ + 7, + 1 + ] + ], + [ + [ + 7985, + 2139 + ], + [ + 1, + -60 + ], + [ + 18, + -58 + ], + [ + -31, + -55 + ], + [ + -34, + -135 + ], + [ + 177, + 0 + ], + [ + -8, + -59 + ], + [ + 27, + -64 + ] + ], + [ + [ + 8135, + 1708 + ], + [ + -64, + 28 + ], + [ + -18, + -36 + ], + [ + 76, + -35 + ], + [ + -47, + -112 + ], + [ + -26, + 18 + ], + [ + -34, + -25 + ], + [ + -49, + 24 + ], + [ + -4, + 34 + ], + [ + -52, + 49 + ], + [ + -34, + -42 + ], + [ + -84, + 34 + ], + [ + -48, + -2 + ], + [ + -9, + 32 + ] + ], + [ + [ + 7742, + 1675 + ], + [ + 22, + 184 + ], + [ + -45, + 125 + ], + [ + 0, + 155 + ] + ], + [ + [ + 9612, + 3520 + ], + [ + 21, + 106 + ] + ], + [ + [ + 9633, + 3626 + ], + [ + 73, + -3 + ] + ], + [ + [ + 9706, + 3623 + ], + [ + 104, + -4 + ], + [ + 49, + 26 + ] + ], + [ + [ + 9859, + 3645 + ], + [ + 6, + -31 + ], + [ + -28, + -52 + ], + [ + 28, + -16 + ], + [ + 31, + -92 + ], + [ + -73, + -16 + ], + [ + -4, + 29 + ] + ], + [ + [ + 9819, + 3467 + ], + [ + -14, + 47 + ], + [ + -38, + -1 + ] + ], + [ + [ + 9277, + 3045 + ], + [ + -56, + 61 + ] + ], + [ + [ + 9221, + 3106 + ], + [ + -41, + 52 + ], + [ + -59, + -18 + ], + [ + -62, + -55 + ], + [ + 1, + 79 + ] + ], + [ + [ + 9060, + 3164 + ], + [ + 213, + 0 + ], + [ + 127, + 0 + ] + ], + [ + [ + 9469, + 2970 + ], + [ + -31, + -66 + ] + ], + [ + [ + 9438, + 2904 + ], + [ + -26, + -11 + ] + ], + [ + [ + 9412, + 2893 + ], + [ + -51, + 63 + ], + [ + 4, + 75 + ], + [ + -32, + 7 + ], + [ + 17, + -116 + ], + [ + -84, + 54 + ], + [ + 20, + 60 + ] + ], + [ + [ + 9452, + 2907 + ], + [ + -3, + -1 + ] + ], + [ + [ + 9449, + 2906 + ], + [ + 3, + 1 + ] + ], + [ + [ + 10198, + 3996 + ], + [ + 1, + -44 + ], + [ + -73, + -66 + ], + [ + -35, + 8 + ], + [ + -72, + -62 + ], + [ + -105, + -72 + ], + [ + -49, + -85 + ] + ], + [ + [ + 9865, + 3675 + ], + [ + -20, + 49 + ], + [ + -12, + 291 + ] + ], + [ + [ + 8725, + 3504 + ], + [ + -32, + -32 + ], + [ + -122, + -6 + ] + ], + [ + [ + 8364, + 3587 + ], + [ + -11, + 127 + ], + [ + 12, + 117 + ], + [ + 29, + 115 + ], + [ + 41, + 58 + ], + [ + -47, + 35 + ], + [ + -31, + 0 + ], + [ + -50, + -51 + ], + [ + -19, + 38 + ], + [ + 5, + 48 + ], + [ + -31, + 40 + ], + [ + -182, + 61 + ], + [ + -27, + 37 + ], + [ + 42, + 107 + ] + ], + [ + [ + 8095, + 4319 + ], + [ + 43, + 109 + ] + ], + [ + [ + 8095, + 4319 + ], + [ + -64, + 3 + ], + [ + -75, + -58 + ], + [ + -76, + -41 + ], + [ + 0, + -88 + ], + [ + -37, + -26 + ], + [ + -9, + -171 + ], + [ + 136, + -131 + ], + [ + 7, + -66 + ] + ], + [ + [ + 7497, + 3741 + ], + [ + 0, + 274 + ], + [ + -36, + 46 + ], + [ + 27, + 53 + ] + ], + [ + [ + 7488, + 4114 + ], + [ + -22, + 107 + ], + [ + -6, + 144 + ], + [ + -25, + 89 + ], + [ + -9, + 126 + ] + ], + [ + [ + 7666, + 2671 + ], + [ + 0, + 77 + ] + ], + [ + [ + 7599, + 3206 + ], + [ + -38, + 92 + ] + ], + [ + [ + 8142, + 2671 + ], + [ + -3, + 1 + ] + ], + [ + [ + 8132, + 2671 + ], + [ + -13, + -76 + ] + ], + [ + [ + 8239, + 1735 + ], + [ + -47, + 7 + ], + [ + -57, + -34 + ] + ], + [ + [ + 8064, + 2442 + ], + [ + 196, + 0 + ] + ], + [ + [ + 6799, + 4580 + ], + [ + 1, + -204 + ], + [ + 1, + -262 + ] + ], + [ + [ + 6801, + 4114 + ], + [ + -2, + -144 + ] + ], + [ + [ + 6799, + 3970 + ], + [ + -202, + 0 + ], + [ + -262, + 0 + ], + [ + -182, + 0 + ], + [ + 0, + -77 + ] + ], + [ + [ + 8614, + 2440 + ], + [ + 3, + 33 + ], + [ + 39, + 48 + ], + [ + 81, + 43 + ], + [ + 9, + 24 + ], + [ + 77, + 26 + ], + [ + 36, + 74 + ] + ], + [ + [ + 8859, + 2688 + ], + [ + 102, + -3 + ], + [ + 200, + -3 + ], + [ + 222, + -3 + ] + ], + [ + [ + 9383, + 2679 + ], + [ + -47, + -80 + ], + [ + 65, + -19 + ], + [ + 0, + -39 + ], + [ + -37, + -45 + ], + [ + -31, + -13 + ], + [ + -21, + -50 + ], + [ + -93, + -100 + ], + [ + -24, + -57 + ], + [ + -51, + -5 + ] + ], + [ + [ + 9144, + 2271 + ], + [ + -100, + 140 + ], + [ + -104, + 5 + ], + [ + -28, + 50 + ], + [ + -117, + 7 + ], + [ + -70, + -31 + ] + ], + [ + [ + 9391, + 2679 + ], + [ + 3, + 0 + ] + ], + [ + [ + 9394, + 2679 + ], + [ + -3, + 0 + ] + ], + [ + [ + 7488, + 4114 + ], + [ + -258, + 0 + ], + [ + -150, + 0 + ], + [ + -279, + 0 + ] + ], + [ + [ + 6800, + 3359 + ], + [ + 0, + 305 + ] + ], + [ + [ + 6800, + 3664 + ], + [ + 191, + 0 + ], + [ + 323, + 0 + ], + [ + 44, + -29 + ], + [ + 67, + 8 + ], + [ + 70, + -53 + ] + ], + [ + [ + 9865, + 3675 + ], + [ + -6, + -30 + ] + ], + [ + [ + 9706, + 3623 + ], + [ + 7, + 122 + ], + [ + 33, + 118 + ], + [ + 32, + 23 + ], + [ + 15, + 85 + ] + ], + [ + [ + 9466, + 3203 + ], + [ + 31, + 27 + ], + [ + -42, + 67 + ], + [ + 6, + 62 + ], + [ + 39, + 54 + ] + ], + [ + [ + 9500, + 3413 + ], + [ + 73, + -55 + ] + ], + [ + [ + 9573, + 3358 + ], + [ + -31, + -82 + ], + [ + 26, + -20 + ], + [ + -20, + -92 + ], + [ + -23, + -52 + ], + [ + -43, + -37 + ], + [ + -58, + 53 + ], + [ + 10, + 46 + ], + [ + 32, + 29 + ] + ], + [ + [ + 6894, + 2748 + ], + [ + 0, + -76 + ] + ], + [ + [ + 6894, + 2672 + ], + [ + -4, + -301 + ], + [ + -2, + -387 + ], + [ + -165, + 0 + ], + [ + -166, + 0 + ], + [ + 20, + -35 + ] + ], + [ + [ + 6577, + 1949 + ], + [ + -162, + 1 + ], + [ + -1, + -68 + ], + [ + -76, + -1 + ] + ], + [ + [ + 5329, + 3512 + ], + [ + 275, + 0 + ] + ], + [ + [ + 5878, + 3512 + ], + [ + 0, + -310 + ], + [ + 0, + -215 + ], + [ + 0, + -239 + ] + ], + [ + [ + 9624, + 3971 + ], + [ + 3, + -113 + ], + [ + -8, + -98 + ], + [ + 15, + -11 + ], + [ + -1, + -123 + ] + ], + [ + [ + 9599, + 3357 + ], + [ + -26, + 1 + ] + ], + [ + [ + 9500, + 3413 + ], + [ + -30, + 30 + ], + [ + -30, + 68 + ], + [ + -190, + 0 + ], + [ + -216, + 1 + ], + [ + 0, + 82 + ] + ], + [ + [ + 9702, + 3357 + ], + [ + -63, + -51 + ], + [ + -53, + -10 + ], + [ + 18, + 50 + ], + [ + 98, + 11 + ] + ], + [ + [ + 8964, + 3561 + ], + [ + 0, + -256 + ] + ], + [ + [ + 8964, + 3305 + ], + [ + -41, + -165 + ], + [ + -63, + -45 + ], + [ + -39, + -47 + ], + [ + -10, + -50 + ], + [ + -39, + -29 + ] + ], + [ + [ + 7678, + 2236 + ], + [ + -69, + 47 + ], + [ + -96, + -31 + ], + [ + -64, + 28 + ], + [ + -80, + -10 + ], + [ + -23, + 42 + ], + [ + -65, + 1 + ], + [ + -76, + 36 + ], + [ + -34, + 30 + ], + [ + -1, + 292 + ], + [ + -276, + 1 + ] + ], + [ + [ + 4940, + 3512 + ], + [ + -29, + 124 + ], + [ + 36, + 134 + ], + [ + 8, + 166 + ], + [ + 12, + 122 + ], + [ + -1, + 86 + ], + [ + 67, + 2 + ] + ], + [ + [ + 5033, + 4146 + ], + [ + 25, + -6 + ], + [ + 20, + -67 + ], + [ + 48, + -13 + ], + [ + 74, + 18 + ], + [ + 33, + -11 + ], + [ + 64, + 13 + ], + [ + 122, + 43 + ], + [ + 196, + 0 + ] + ], + [ + [ + 9466, + 3203 + ], + [ + -32, + -25 + ] + ], + [ + [ + 9060, + 3164 + ], + [ + -96, + 0 + ], + [ + 0, + 141 + ] + ], + [ + [ + 9819, + 3467 + ], + [ + -26, + -50 + ], + [ + -30, + -7 + ] + ], + [ + [ + 9144, + 2271 + ], + [ + -25, + -24 + ], + [ + -40, + -90 + ], + [ + -69, + -78 + ], + [ + -19, + -7 + ], + [ + -59, + -84 + ] + ], + [ + [ + 6800, + 3664 + ], + [ + -1, + 306 + ] + ], + [ + [ + 8674, + 2687 + ], + [ + 185, + 1 + ] + ], + [ + [ + 7742, + 1675 + ], + [ + -28, + -47 + ], + [ + -73, + -46 + ], + [ + -35, + -62 + ], + [ + -54, + -49 + ], + [ + -54, + -7 + ], + [ + -11, + -35 + ], + [ + -55, + -34 + ], + [ + -1, + -40 + ], + [ + -35, + -140 + ], + [ + 14, + -87 + ], + [ + 23, + -66 + ], + [ + -19, + -14 + ], + [ + -67, + 29 + ], + [ + -94, + 59 + ], + [ + -31, + 90 + ], + [ + -6, + 78 + ], + [ + -73, + 119 + ], + [ + -33, + 113 + ], + [ + -72, + 108 + ], + [ + -76, + 15 + ], + [ + -43, + -35 + ], + [ + -15, + -65 + ], + [ + -33, + -33 + ], + [ + -79, + 59 + ], + [ + -36, + 44 + ], + [ + -44, + 148 + ], + [ + -27, + 25 + ], + [ + -90, + 112 + ], + [ + -18, + 35 + ] + ], + [ + [ + 6153, + 3512 + ], + [ + 0, + -153 + ], + [ + 185, + 0 + ] + ], + [ + [ + 9286, + 3036 + ], + [ + -27, + -75 + ], + [ + 71, + -46 + ], + [ + 26, + -31 + ], + [ + 0, + -82 + ], + [ + -13, + -22 + ], + [ + 37, + -46 + ], + [ + 14, + -55 + ] + ], + [ + [ + 9391, + 2679 + ], + [ + -8, + 0 + ] + ], + [ + [ + 8831, + 2830 + ], + [ + 13, + -37 + ], + [ + 81, + 1 + ], + [ + 58, + 32 + ], + [ + 3, + 25 + ], + [ + 63, + 138 + ], + [ + 33, + -16 + ], + [ + 74, + 105 + ], + [ + 11, + 44 + ], + [ + 54, + -16 + ] + ], + [ + [ + 9438, + 2904 + ], + [ + -26, + -11 + ] + ], + [ + [ + 9452, + 2907 + ], + [ + -3, + -1 + ] + ], + [ + [ + 5033, + 4146 + ], + [ + -79, + 19 + ], + [ + 0, + 71 + ], + [ + -28, + 140 + ], + [ + -22, + 37 + ], + [ + -1, + 72 + ], + [ + 60, + -31 + ], + [ + 103, + -12 + ], + [ + 19, + -32 + ], + [ + 38, + 20 + ], + [ + -51, + 150 + ] + ], + [ + [ + 5048, + 4580 + ], + [ + -3, + 0 + ] + ] + ], + "transform": { + "scale": [ + 0.010860830875975714, + 0.006546578431372549 + ], + "translate": [ + -177.879034, + 19.012018 + ] + }, + "objects": { + "subdivisions": { + "type": "GeometryCollection", + "geometries": [ + { + "arcs": [ + [ + 0, + 1, + 2, + 3 + ] + ], + "type": "Polygon", + "properties": { + "code": "CA-AB", + "name": "Alberta" + } + }, + { + "arcs": [ + [ + [ + -2, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12 + ] + ], + [ + [ + 13, + 14 + ] + ], + [ + [ + 17 + ] + ], + [ + [ + 18 + ] + ], + [ + [ + 19 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "CA-BC", + "name": "British Columbia" + } + }, + { + "arcs": [ + [ + 20, + 21, + 22, + 23, + 24, + 25 + ] + ], + "type": "Polygon", + "properties": { + "code": "CA-MB", + "name": "Manitoba" + } + }, + { + "arcs": [ + [ + 26, + 27, + 28, + 29, + 30 + ] + ], + "type": "Polygon", + "properties": { + "code": "CA-NB", + "name": "New Brunswick" + } + }, + { + "arcs": [ + [ + [ + 31, + 32 + ] + ], + [ + [ + 33 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "CA-NL", + "name": "Newfoundland and Labrador" + } + }, + { + "arcs": [ + [ + [ + -27, + 34 + ] + ], + [ + [ + 35 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "CA-NS", + "name": "Nova Scotia" + } + }, + { + "arcs": [ + [ + [ + -3, + -13, + 36, + 37, + 38, + 39 + ] + ], + [ + [ + 40, + 41 + ] + ], + [ + [ + 42, + 43 + ] + ], + [ + [ + 44 + ] + ], + [ + [ + 45, + 46 + ] + ], + [ + [ + 49 + ] + ], + [ + [ + 50, + 51 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "CA-NT", + "name": "Northwest Territories" + } + }, + { + "arcs": [ + [ + [ + -25, + -39, + 52 + ] + ], + [ + [ + -46, + 55, + -48, + 56 + ] + ], + [ + [ + -51, + 57 + ] + ], + [ + [ + 58 + ] + ], + [ + [ + 59 + ] + ], + [ + [ + 60 + ] + ], + [ + [ + 61 + ] + ], + [ + [ + 62 + ] + ], + [ + [ + 63 + ] + ], + [ + [ + 64 + ] + ], + [ + [ + 65 + ] + ], + [ + [ + 66 + ] + ], + [ + [ + 67 + ] + ], + [ + [ + 68 + ] + ], + [ + [ + 69 + ] + ], + [ + [ + 70 + ] + ], + [ + [ + 71 + ] + ], + [ + [ + 72 + ] + ], + [ + [ + 73 + ] + ], + [ + [ + 74 + ] + ], + [ + [ + 75 + ] + ], + [ + [ + 76 + ] + ], + [ + [ + 77 + ] + ], + [ + [ + 78 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "CA-NU", + "name": "Nunavut" + } + }, + { + "arcs": [ + [ + [ + -21, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86 + ] + ], + [ + [ + 87, + 88 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "CA-ON", + "name": "Ontario" + } + }, + { + "arcs": [ + [ + 89 + ] + ], + "type": "Polygon", + "properties": { + "code": "CA-PE", + "name": "Prince Edward Island" + } + }, + { + "arcs": [ + [ + [ + -30, + 90, + 91, + 92, + 93, + 94 + ] + ], + [ + [ + -32, + 95, + -81, + 96, + -89, + 97 + ] + ], + [ + [ + 98 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "CA-QC", + "name": "Québec" + } + }, + { + "arcs": [ + [ + -4, + -40, + -24, + 99, + 100 + ] + ], + "type": "Polygon", + "properties": { + "code": "CA-SK", + "name": "Saskatchewan" + } + }, + { + "arcs": [ + [ + -12, + 101, + 102, + -37 + ] + ], + "type": "Polygon", + "properties": { + "code": "CA-YT", + "name": "Yukon" + } + }, + { + "arcs": [ + [ + [ + -11, + -14, + -17, + 103, + -102 + ] + ], + [ + [ + 104 + ] + ], + [ + [ + 105 + ] + ], + [ + [ + 106 + ] + ], + [ + [ + 107 + ] + ], + [ + [ + 108 + ] + ], + [ + [ + 109 + ] + ], + [ + [ + 110 + ] + ], + [ + [ + 111 + ] + ], + [ + [ + 112 + ] + ], + [ + [ + 113 + ] + ], + [ + [ + 114 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "US-AK", + "name": "Alaska" + } + }, + { + "arcs": [ + [ + 115, + 116, + 117, + 118, + 119 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-AL", + "name": "Alabama" + } + }, + { + "arcs": [ + [ + 120, + 121, + 122, + 123, + 124, + 125 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-AR", + "name": "Arkansas" + } + }, + { + "arcs": [ + [ + 126, + 127, + 128, + 129, + 130 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-AZ", + "name": "Arizona" + } + }, + { + "arcs": [ + [ + -128, + 131, + 132, + 133 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-CA", + "name": "California" + } + }, + { + "arcs": [ + [ + 134, + 135, + 136, + 137, + 138, + 139 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-CO", + "name": "Colorado" + } + }, + { + "arcs": [ + [ + 140, + 141, + 142, + 143 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-CT", + "name": "Connecticut" + } + }, + { + "arcs": [ + [ + 144, + 145 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-DC", + "name": "District of Columbia" + } + }, + { + "arcs": [ + [ + 146, + 147, + 148 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-DE", + "name": "Delaware" + } + }, + { + "arcs": [ + [ + -120, + 149, + 150 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-FL", + "name": "Florida" + } + }, + { + "arcs": [ + [ + -119, + 151, + 152, + 153, + 154, + -150 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-GA", + "name": "Georgia" + } + }, + { + "arcs": [ + [ + [ + 155 + ] + ], + [ + [ + 156 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "US-HI", + "name": "Hawaii" + } + }, + { + "arcs": [ + [ + 157, + 158, + 159, + 160, + 161, + 162 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-IA", + "name": "Iowa" + } + }, + { + "arcs": [ + [ + -6, + 163, + 164, + 165, + 166, + 167, + 168 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-ID", + "name": "Idaho" + } + }, + { + "arcs": [ + [ + -163, + 169, + 170, + 171, + 172, + 173 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-IL", + "name": "Illinois" + } + }, + { + "arcs": [ + [ + -172, + 174, + 175, + 176 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-IN", + "name": "Indiana" + } + }, + { + "arcs": [ + [ + -138, + 177, + 178, + 179 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-KS", + "name": "Kansas" + } + }, + { + "arcs": [ + [ + -173, + -177, + 180, + 181, + 182, + 183, + 184 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-KY", + "name": "Kentucky" + } + }, + { + "arcs": [ + [ + -123, + 187, + 188, + 189 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-LA", + "name": "Louisiana" + } + }, + { + "arcs": [ + [ + -144, + 190, + 191, + 192, + 193, + 194 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-MA", + "name": "Massachusetts" + } + }, + { + "arcs": [ + [ + -146, + 195, + 196, + 197, + -147, + 198, + 199, + 200 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-MD", + "name": "Maryland" + } + }, + { + "arcs": [ + [ + -29, + 203, + 204, + -91 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-ME", + "name": "Maine" + } + }, + { + "arcs": [ + [ + -86, + 205, + -175, + -171, + 206, + 207 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-MI", + "name": "Michigan" + } + }, + { + "arcs": [ + [ + -22, + -87, + -208, + 208, + -161, + 209, + 210 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-MN", + "name": "Minnesota" + } + }, + { + "arcs": [ + [ + -126, + 211, + -179, + 212, + -158, + -174, + -185, + 213, + -187, + 214 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-MO", + "name": "Missouri" + } + }, + { + "arcs": [ + [ + -117, + 215, + -188, + -122, + 216 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-MS", + "name": "Mississippi" + } + }, + { + "arcs": [ + [ + -1, + -101, + 217, + 218, + 219, + -164, + -5 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-MT", + "name": "Montana" + } + }, + { + "arcs": [ + [ + -153, + 220, + 221, + 222, + 223 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-NC", + "name": "North Carolina" + } + }, + { + "arcs": [ + [ + -23, + -211, + 226, + -218, + -100 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-ND", + "name": "North Dakota" + } + }, + { + "arcs": [ + [ + -137, + 227, + 228, + -159, + -213, + -178 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-NE", + "name": "Nebraska" + } + }, + { + "arcs": [ + [ + -92, + -205, + 229, + -193, + 230 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-NH", + "name": "New Hampshire" + } + }, + { + "arcs": [ + [ + 231, + 232, + 233 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-NJ", + "name": "New Jersey" + } + }, + { + "arcs": [ + [ + -131, + -140, + 234, + 235, + 236 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-NM", + "name": "New Mexico" + } + }, + { + "arcs": [ + [ + -129, + -134, + 237, + -167, + 238 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-NV", + "name": "Nevada" + } + }, + { + "arcs": [ + [ + [ + -83, + -94, + 239, + -191, + -143, + 240, + -233, + 241 + ] + ], + [ + [ + 242 + ] + ] + ], + "type": "MultiPolygon", + "properties": { + "code": "US-NY", + "name": "New York" + } + }, + { + "arcs": [ + [ + -85, + 243, + 244, + -181, + -176, + -206 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-OH", + "name": "Ohio" + } + }, + { + "arcs": [ + [ + -125, + 245, + -235, + -139, + -180, + -212 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-OK", + "name": "Oklahoma" + } + }, + { + "arcs": [ + [ + -133, + 246, + 247, + -168, + -238 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-OR", + "name": "Oregon" + } + }, + { + "arcs": [ + [ + -84, + -242, + -232, + 248, + -148, + -198, + 249, + -244 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-PA", + "name": "Pennsylvania" + } + }, + { + "arcs": [ + [ + -141, + -195, + 250 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-RI", + "name": "Rhode Island" + } + }, + { + "arcs": [ + [ + -154, + -224, + 251 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-SC", + "name": "South Carolina" + } + }, + { + "arcs": [ + [ + -160, + -229, + 252, + -219, + -227, + -210 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-SD", + "name": "South Dakota" + } + }, + { + "arcs": [ + [ + -118, + -217, + -121, + -215, + -186, + -214, + -184, + 253, + -221, + -152 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-TN", + "name": "Tennessee" + } + }, + { + "arcs": [ + [ + -124, + -190, + 254, + -236, + -246 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-TX", + "name": "Texas" + } + }, + { + "arcs": [ + [ + -130, + -239, + -166, + 255, + -135 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-UT", + "name": "Utah" + } + }, + { + "arcs": [ + [ + -145, + 256, + -225, + 257, + -222, + -254, + -183, + 258, + -196 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-VA", + "name": "Virginia" + } + }, + { + "arcs": [ + [ + -93, + -231, + -192, + -240 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-VT", + "name": "Vermont" + } + }, + { + "arcs": [ + [ + -7, + -169, + -248, + 261 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-WA", + "name": "Washington" + } + }, + { + "arcs": [ + [ + -162, + -209, + -207, + -170 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-WI", + "name": "Wisconsin" + } + }, + { + "arcs": [ + [ + -182, + -245, + -250, + -197, + -259 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-WV", + "name": "West Virginia" + } + }, + { + "arcs": [ + [ + -136, + -256, + -165, + -220, + -253, + -228 + ] + ], + "type": "Polygon", + "properties": { + "code": "US-WY", + "name": "Wyoming" + } + } + ] + } + } +} \ No newline at end of file diff --git a/showcase/templates/showcase/home.html b/showcase/templates/showcase/home.html new file mode 100644 index 0000000..2fb1e47 --- /dev/null +++ b/showcase/templates/showcase/home.html @@ -0,0 +1,26 @@ +{% load static %} + + + + + + Xavier Bukowski - Atlas + + + + +
+
+
+
+
+ + + diff --git a/showcase/tests/__init__.py b/showcase/tests/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/showcase/tests/__init__.py @@ -0,0 +1 @@ + diff --git a/showcase/tests/test_views.py b/showcase/tests/test_views.py new file mode 100644 index 0000000..8294f10 --- /dev/null +++ b/showcase/tests/test_views.py @@ -0,0 +1,59 @@ +from django.test import TestCase +from django.urls import reverse + +from showcase.models import PortfolioEntry, Region + + +class MapRegionsViewTests(TestCase): + def setUp(self): + self.us = Region.objects.get(code="USA") + self.california = Region.objects.get(code="US-CA") + self.canada = Region.objects.get(code="CAN") + + def regions_by_code(self): + response = self.client.get(reverse("map-regions")) + self.assertEqual(response.status_code, 200) + return {region["code"]: region for region in response.json()["regions"]} + + def test_homepage_contains_map_mount(self): + response = self.client.get(reverse("home")) + + self.assertContains(response, 'id="portfolio-map-root"') + self.assertContains(response, "showcase/dist/map.js") + + def test_api_returns_seeded_regions_with_empty_entries(self): + regions = self.regions_by_code() + + self.assertIn("USA", regions) + self.assertIn("CAN", regions) + self.assertIn("US-CA", regions) + self.assertEqual(regions["US-CA"]["parentCode"], "USA") + self.assertEqual(regions["USA"]["entries"], []) + + def test_country_aggregates_subdivision_entries_and_deduplicates(self): + entry = PortfolioEntry.objects.create( + entry_type=PortfolioEntry.EntryType.WORK, + title="West Coast delivery", + summary="Delivered a regional engagement.", + is_published=True, + ) + entry.regions.add(self.us, self.california) + + regions = self.regions_by_code() + + self.assertEqual(len(regions["USA"]["entries"]), 1) + self.assertEqual(regions["US-CA"]["entries"][0]["title"], entry.title) + + def test_api_excludes_unpublished_entries(self): + entry = PortfolioEntry.objects.create( + entry_type=PortfolioEntry.EntryType.CV, + title="Draft entry", + summary="Not visible yet.", + is_published=False, + ) + entry.regions.add(self.canada) + + regions = self.regions_by_code() + + self.assertEqual(regions["CAN"]["entries"], []) + diff --git a/showcase/urls.py b/showcase/urls.py new file mode 100644 index 0000000..2a2aa20 --- /dev/null +++ b/showcase/urls.py @@ -0,0 +1,9 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path("", views.home, name="home"), + path("api/map/regions/", views.map_regions, name="map-regions"), +] + diff --git a/showcase/views.py b/showcase/views.py new file mode 100644 index 0000000..5d75275 --- /dev/null +++ b/showcase/views.py @@ -0,0 +1,51 @@ +from django.http import JsonResponse +from django.shortcuts import render + +from .models import PortfolioEntry, Region + + +def home(request): + return render(request, "showcase/home.html") + + +def _serialize_entry(entry): + return { + "id": entry.id, + "type": entry.entry_type, + "title": entry.title, + "organization": entry.organization, + "startDate": entry.start_date.isoformat() if entry.start_date else None, + "endDate": entry.end_date.isoformat() if entry.end_date else None, + "summary": entry.summary, + "url": entry.url, + } + + +def map_regions(request): + entries = PortfolioEntry.objects.filter(is_published=True).prefetch_related("regions") + entries_by_region = {} + for entry in entries: + payload = _serialize_entry(entry) + for region in entry.regions.all(): + entries_by_region.setdefault(region.code, {})[entry.id] = payload + + regions = list(Region.objects.select_related("parent").prefetch_related("subdivisions")) + payload = [] + for region in regions: + related = dict(entries_by_region.get(region.code, {})) + if region.level == Region.Level.COUNTRY: + for subdivision in region.subdivisions.all(): + related.update(entries_by_region.get(subdivision.code, {})) + + payload.append( + { + "code": region.code, + "name": region.name, + "level": region.level, + "parentCode": region.parent_id, + "entries": list(related.values()), + } + ) + + return JsonResponse({"regions": payload}) +