diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 5863df8822d..be2ede84c1f 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -5,7 +5,6 @@ on: paths: - 'clients/**' - 'common/**' - - 'explorer-api/**' - 'gateway/**' - 'integrations/**' - 'nym-api/**' diff --git a/.github/workflows/publish-nym-binaries.yml b/.github/workflows/publish-nym-binaries.yml index 618304e9ae2..07b358c45f4 100644 --- a/.github/workflows/publish-nym-binaries.yml +++ b/.github/workflows/publish-nym-binaries.yml @@ -19,7 +19,11 @@ jobs: if: ${{ (startsWith(github.ref, 'refs/tags/nym-binaries-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }} strategy: fail-fast: false - runs-on: arc-ubuntu-22.04 + matrix: + include: + - os: arc-ubuntu-22.04 + target: x86_64-unknown-linux-gnu + runs-on: ${{ matrix.os }} outputs: release_id: ${{ steps.create-release.outputs.id }} @@ -66,7 +70,6 @@ jobs: with: name: my-artifact path: | - target/release/explorer-api target/release/nym-client target/release/nym-socks5-client target/release/nym-api @@ -82,7 +85,6 @@ jobs: if: github.event_name == 'release' with: files: | - target/release/explorer-api target/release/nym-client target/release/nym-socks5-client target/release/nym-api diff --git a/common/network-defaults/build.rs b/common/network-defaults/build.rs index aa52baa8767..64de45df773 100644 --- a/common/network-defaults/build.rs +++ b/common/network-defaults/build.rs @@ -23,7 +23,6 @@ fn main() { "REWARDING_VALIDATOR_ADDRESS", "NYM_API", "NYXD_WS", - "EXPLORER_API", "NYM_VPN_API", ]; diff --git a/common/network-defaults/src/mainnet.rs b/common/network-defaults/src/mainnet.rs index 2b54d174068..501c46651be 100644 --- a/common/network-defaults/src/mainnet.rs +++ b/common/network-defaults/src/mainnet.rs @@ -31,7 +31,6 @@ pub const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772 pub const NYXD_URL: &str = "https://rpc.nymtech.net"; pub const NYM_API: &str = "https://validator.nymtech.net/api/"; pub const NYXD_WS: &str = "wss://rpc.nymtech.net/websocket"; -pub const EXPLORER_API: &str = "https://explorer.nymtech.net/api/"; pub const NYM_VPN_API: &str = "https://nymvpn.com/api/"; // I'm making clippy mad on purpose, because that url HAS TO be updated and deployed before merging @@ -123,7 +122,6 @@ pub fn export_to_env() { set_var_to_default(var_names::NYXD, NYXD_URL); set_var_to_default(var_names::NYM_API, NYM_API); set_var_to_default(var_names::NYXD_WEBSOCKET, NYXD_WS); - set_var_to_default(var_names::EXPLORER_API, EXPLORER_API); set_var_to_default(var_names::EXIT_POLICY_URL, EXIT_POLICY_URL); set_var_to_default(var_names::NYM_VPN_API, NYM_VPN_API); } @@ -165,6 +163,5 @@ pub fn export_to_env_if_not_set() { set_var_conditionally_to_default(var_names::NYXD, NYXD_URL); set_var_conditionally_to_default(var_names::NYM_API, NYM_API); set_var_conditionally_to_default(var_names::NYXD_WEBSOCKET, NYXD_WS); - set_var_conditionally_to_default(var_names::EXPLORER_API, EXPLORER_API); set_var_conditionally_to_default(var_names::EXIT_POLICY_URL, EXIT_POLICY_URL); } diff --git a/common/network-defaults/src/network.rs b/common/network-defaults/src/network.rs index 8cebe533409..5a3e6ab7114 100644 --- a/common/network-defaults/src/network.rs +++ b/common/network-defaults/src/network.rs @@ -35,7 +35,6 @@ pub struct NymNetworkDetails { pub chain_details: ChainDetails, pub endpoints: Vec, pub contracts: NymContracts, - pub explorer_api: Option, pub nym_vpn_api_url: Option, } @@ -65,7 +64,6 @@ impl NymNetworkDetails { }, endpoints: Default::default(), contracts: Default::default(), - explorer_api: Default::default(), nym_vpn_api_url: Default::default(), } } @@ -124,7 +122,6 @@ impl NymNetworkDetails { .with_group_contract(get_optional_env(var_names::GROUP_CONTRACT_ADDRESS)) .with_multisig_contract(get_optional_env(var_names::MULTISIG_CONTRACT_ADDRESS)) .with_coconut_dkg_contract(get_optional_env(var_names::COCONUT_DKG_CONTRACT_ADDRESS)) - .with_explorer_api(get_optional_env(var_names::EXPLORER_API)) .with_nym_vpn_api_url(get_optional_env(var_names::NYM_VPN_API)) } @@ -152,7 +149,6 @@ impl NymNetworkDetails { mainnet::COCONUT_DKG_CONTRACT_ADDRESS, ), }, - explorer_api: parse_optional_str(mainnet::EXPLORER_API), nym_vpn_api_url: parse_optional_str(mainnet::NYM_VPN_API), } } @@ -193,7 +189,6 @@ impl NymNetworkDetails { set_optional_var(var_names::MULTISIG_CONTRACT_ADDRESS, self.contracts.multisig_contract_address); set_optional_var(var_names::COCONUT_DKG_CONTRACT_ADDRESS, self.contracts.coconut_dkg_contract_address); - set_optional_var(var_names::EXPLORER_API, self.explorer_api); set_optional_var(var_names::NYM_VPN_API, self.nym_vpn_api_url); } @@ -297,12 +292,6 @@ impl NymNetworkDetails { self } - #[must_use] - pub fn with_explorer_api>(mut self, endpoint: Option) -> Self { - self.explorer_api = endpoint.map(Into::into); - self - } - #[must_use] pub fn with_nym_vpn_api_url>(mut self, endpoint: Option) -> Self { self.nym_vpn_api_url = endpoint.map(Into::into); diff --git a/common/network-defaults/src/var_names.rs b/common/network-defaults/src/var_names.rs index bf92b957995..5bcebe85eb5 100644 --- a/common/network-defaults/src/var_names.rs +++ b/common/network-defaults/src/var_names.rs @@ -22,7 +22,6 @@ pub const REWARDING_VALIDATOR_ADDRESS: &str = "REWARDING_VALIDATOR_ADDRESS"; pub const NYXD: &str = "NYXD"; pub const NYM_API: &str = "NYM_API"; pub const NYXD_WEBSOCKET: &str = "NYXD_WS"; -pub const EXPLORER_API: &str = "EXPLORER_API"; pub const EXIT_POLICY_URL: &str = "EXIT_POLICY"; pub const NYM_VPN_API: &str = "NYM_VPN_API"; pub const CLIENT_STATS_COLLECTION_PROVIDER: &str = "CLIENT_STATS_COLLECTION_PROVIDER"; diff --git a/envs/canary.env b/envs/canary.env index 6bdd85494ed..f494ad32707 100644 --- a/envs/canary.env +++ b/envs/canary.env @@ -18,7 +18,6 @@ GROUP_CONTRACT_ADDRESS=n1qg5ega6dykkxc307y25pecuufrjkxkaggkkxh7nad0vhyhtuhw3sa07 MULTISIG_CONTRACT_ADDRESS=n1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqx5a364 COCONUT_DKG_CONTRACT_ADDRESS=n1aakfpghcanxtc45gpqlx8j3rq0zcpyf49qmhm9mdjrfx036h4z5sy2vfh9 -EXPLORER_API=https://canary-explorer.performance.nymte.ch/api/ NYXD=https://rpc.canary-validator.performance.nymte.ch NYM_API=https://canary-api.performance.nymte.ch/api/ NYXD_WS=wss://rpc.canary-validator.performance.nymte.ch/websocket diff --git a/envs/mainnet-local-api.env b/envs/mainnet-local-api.env index d6683c937d1..f7d1fec6d5e 100644 --- a/envs/mainnet-local-api.env +++ b/envs/mainnet-local-api.env @@ -23,5 +23,4 @@ STATISTICS_SERVICE_DOMAIN_ADDRESS="https://mainnet-stats.nymte.ch:8090" NYXD="https://rpc.nymtech.net" NYM_API="http://127.0.0.1:8000" NYXD_WS="wss://rpc.nymtech.net/websocket" -EXPLORER_API="https://explorer.nymtech.net/api/" NYM_VPN_API="https://nymvpn.com/api" diff --git a/envs/mainnet.env b/envs/mainnet.env index ad1e2cd88ee..444307f836c 100644 --- a/envs/mainnet.env +++ b/envs/mainnet.env @@ -24,5 +24,4 @@ STATISTICS_SERVICE_DOMAIN_ADDRESS=https://mainnet-stats.nymte.ch:8090 NYXD=https://rpc.nymtech.net NYM_API=https://validator.nymtech.net/api/ NYXD_WS=wss://rpc.nymtech.net/websocket -EXPLORER_API=https://explorer.nymtech.net/api/ NYM_VPN_API=https://nymvpn.com/api/ diff --git a/envs/qa.env b/envs/qa.env index 2a4fddb0a7c..1a350109e27 100644 --- a/envs/qa.env +++ b/envs/qa.env @@ -18,7 +18,6 @@ COCONUT_DKG_CONTRACT_ADDRESS=n1pk8jgr6y4c5k93gz7qf3xc0hvygmp7csk88c2tf8l39tkq683 VESTING_CONTRACT_ADDRESS=n1jlzdxnyces4hrhqz68dqk28mrw5jgwtcfq0c2funcwrmw0dx9l9s8nnnvj REWARDING_VALIDATOR_ADDRESS=n1rfvpsynktze6wvn6ldskj8xgwfzzk5v6pnff39 -EXPLORER_API=https://qa-network-explorer.qa.nymte.ch/api/ NYXD=https://rpc.qa-validator.qa.nymte.ch NYXD_WS=wss://rpc.qa-validator.qa.nymte.ch/websocket NYM_API=https://qa-nym-api.qa.nymte.ch/api/ diff --git a/envs/sandbox.env b/envs/sandbox.env index 68e51fec598..e90257f015c 100644 --- a/envs/sandbox.env +++ b/envs/sandbox.env @@ -19,7 +19,6 @@ COCONUT_DKG_CONTRACT_ADDRESS=n1v3n2ly2dp3a9ng3ff6rh26yfkn0pc5hed7w2shc5u9ca5c865 ECASH_CONTRACT_ADDRESS=n1v3vydvs2ued84yv3khqwtgldmgwn0elljsdh08dr5s2j9x4rc5fs9jlwz9 STATISTICS_SERVICE_DOMAIN_ADDRESS="http://0.0.0.0" -EXPLORER_API=https://sandbox-explorer.nymtech.net/api/ NYXD=https://rpc.sandbox.nymtech.net NYXD_WS=wss://rpc.sandbox.nymtech.net/websocket NYM_API=https://sandbox-nym-api1.nymtech.net/api/ diff --git a/explorer-nextjs/.eslintrc.json b/explorer-nextjs/.eslintrc.json deleted file mode 100644 index 957cd1545e3..00000000000 --- a/explorer-nextjs/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["next/core-web-vitals"] -} diff --git a/explorer-nextjs/.gitignore b/explorer-nextjs/.gitignore deleted file mode 100644 index fd3dbb571a1..00000000000 --- a/explorer-nextjs/.gitignore +++ /dev/null @@ -1,36 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js -.yarn/install-state.gz - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts diff --git a/explorer-nextjs/README.md b/explorer-nextjs/README.md deleted file mode 100644 index c4033664f80..00000000000 --- a/explorer-nextjs/README.md +++ /dev/null @@ -1,36 +0,0 @@ -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). - -## Getting Started - -First, run the development server: - -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/explorer-nextjs/app/App.tsx b/explorer-nextjs/app/App.tsx deleted file mode 100644 index 6763797c84e..00000000000 --- a/explorer-nextjs/app/App.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react' -import { Navbar } from './components/Nav/Navbar' -import { Providers } from './providers' - -const App = ({ children }: { children: React.ReactNode }) => ( - - {children} - -) - -export { App } diff --git a/explorer-nextjs/app/account/[id]/page.tsx b/explorer-nextjs/app/account/[id]/page.tsx deleted file mode 100644 index c0c482476cd..00000000000 --- a/explorer-nextjs/app/account/[id]/page.tsx +++ /dev/null @@ -1,407 +0,0 @@ -'use client' - -import * as React from 'react' -import {Alert, AlertTitle, Box, Button, Chip, CircularProgress, Grid, Tooltip, Typography} from '@mui/material' -import { useParams } from 'next/navigation' -import { useMainContext } from '@/app/context/main' -import { Title } from '@/app/components/Title' -import { MaterialReactTable, MRT_ColumnDef, useMaterialReactTable } from "material-react-table"; -import { useMemo } from "react"; -import { humanReadableCurrencyToString } from "@/app/utils/currency"; -import Table from '@mui/material/Table'; -import TableBody from '@mui/material/TableBody'; -import TableCell from '@mui/material/TableCell'; -import TableContainer from '@mui/material/TableContainer'; -import TableRow from '@mui/material/TableRow'; -import Paper from '@mui/material/Paper'; -import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'; -import WarningAmberIcon from '@mui/icons-material/WarningAmber'; -import { PieChart } from '@mui/x-charts/PieChart'; -import { useTheme } from "@mui/material/styles"; -import { useIsMobile } from "@/app/hooks"; -import { StyledLink } from "@/app/components"; - -const AccumulatedRewards = ({account}: { account?: any}) => { - const columns = useMemo< - MRT_ColumnDef[] - >(() => { - return [ - { - id: 'accumulated-rewards-data', - header: 'Accumulated Rewards Data', - columns: [ - { - id: 'node_id', - accessorKey: 'node_id', - header: 'Node ID', - size: 150, - Cell: ({ row }) => ( - {row.original.node_id} - ), - }, - { - id: 'node_still_fully_bonded', - accessorKey: 'node_still_fully_bonded', - header: 'Node still bonded?', - width: 150, - Cell: ({ row }) => ( - <>{row.original.node_still_fully_bonded ? : - theme.palette.warning.main }}> - - Unbonded - } - ) - }, - { - id: 'amount_staked', - accessorKey: 'amount_staked', - header: 'Amount', - width: 150, - Cell: ({ row }) => ( - <>{humanReadableCurrencyToString(row.original.amount_staked)} - ) - }, - { - id: 'rewards', - accessorKey: 'rewards', - header: 'Rewards', - width: 150, - Cell: ({ row }) => ( - {humanReadableCurrencyToString(row.original.rewards)} - ) - }, - ], - }, - ] - }, []) - - const table = useMaterialReactTable({ - columns, - data: account?.accumulated_rewards || [], - enableFullScreenToggle: false, - }) - - return (); -} - -const DelegationHistory = ({account}: { account?: any}) => { - const columns = useMemo< - MRT_ColumnDef[] - >(() => { - return [ - { - id: 'delegation-history-data', - header: 'Delegation History', - columns: [ - { - id: 'node_id', - accessorKey: 'node_id', - header: 'Node ID', - size: 150, - }, - { - id: 'delegated', - accessorKey: 'delegated', - header: 'Amount', - width: 150, - Cell: ({ row }) => ( - <>{humanReadableCurrencyToString(row.original.delegated)} - ) - }, - { - id: 'height', - accessorKey: 'height', - header: 'Delegated at height', - width: 150, - Cell: ({ row }) => ( - <>{row.original.height} - ) - }, - ], - }, - ] - }, []) - - const table = useMaterialReactTable({ - columns, - data: account?.delegations || [], - enableFullScreenToggle: false, - }) - - return (); -} - - -/** - * Shows account details - */ -const PageAccountWithState = ({ account }: { - account?: any; -}) => { - const theme = useTheme(); - const isMobile = useIsMobile(); - - const pieChartData = React.useMemo(() => { - if(!account) { - return []; - } - - const parts = []; - - const nymBalance = Number.parseFloat(account.balances.find((b: any) => b.denom === "unym")?.amount || "0") / 1e6; - - if(nymBalance > 0) { - parts.push({label: "Spendable", value: nymBalance, color: theme.palette.primary.main}); - } - - if(account.vesting_account) { - if (`${account.vesting_account.locked?.amount}` !== "0") { - const value = Number.parseFloat(account.vesting_account.locked.amount) / 1e6; - if(value > 0) { - parts.push({ - label: "Vesting locked", - value, - color: 'red' - }); - } - } - if (`${account.vesting_account.spendable?.amount}` !== "0") { - const value = Number.parseFloat(account.vesting_account.spendable.amount) / 1e6; - if(value > 0) { - parts.push({ - label: "Vesting spendable", - value, - color: theme.palette.primary.light - }); - } - } - } - - if (account.claimable_rewards &&`${account.claimable_rewards.amount}` !== "0") { - const value = Number.parseFloat(account.claimable_rewards.amount) / 1e6; - if(value > 0) { - parts.push({ - label: "Claimable delegation rewards", - value, - color: theme.palette.success.light - }); - } - } - if (account.operator_rewards && `${account.operator_rewards.amount}` !== "0") { - const value = Number.parseFloat(account.operator_rewards.amount) / 1e6; - if(value > 0) { - parts.push({ - label: "Claimable operator rewards", - value, - color: theme.palette.success.dark - }); - } - } - if (account.total_delegations && `${account.total_delegations.amount}` !== "0") { - const value = Number.parseFloat(account.total_delegations.amount) / 1e6; - if(value > 0) { - parts.push({ - label: "Total delegations", - value, - color: '#888' - }); - } - } - - return parts; - }, [account]); - - return ( - - - - </Box> - - <Box mt={4} sx={{ maxWidth: "600px" }}> - <PieChart - series={[ - { - data: pieChartData, - innerRadius: 40, - outerRadius: 80, - cy: isMobile ? 200 : undefined, - }, - ]} - height={300} - slotProps={isMobile ? { - legend: { position: { vertical: "top", horizontal: "right" } } - } : undefined} - /> - </Box> - - <Box mt={4}> - <TableContainer component={Paper} sx={{ maxWidth: "400px" }}> - <Table> - <TableBody> - <TableRow sx={{ color: theme => theme.palette.primary.main }}> - <TableCell component="th" scope="row" sx={{ color: "inherit" }}> - <strong>Spendable Balance</strong> - </TableCell> - <TableCell align="right" sx={{ color: "inherit" }}> - {account.balances.map((b: any) => (<strong key={`balance-${b.denom}`}>{humanReadableCurrencyToString(b)}<br/></strong>))} - </TableCell> - </TableRow> - <TableRow> - <TableCell component="th" scope="row"> - Total delegations - </TableCell> - <TableCell align="right"> - {humanReadableCurrencyToString(account.total_delegations)} - </TableCell> - </TableRow> - {account.claimable_rewards && <TableRow sx={{ color: theme => theme.palette.success.light }}> - <TableCell component="th" scope="row" sx={{ color: "inherit" }}> - Claimable delegation rewards - </TableCell> - <TableCell align="right" sx={{ color: "inherit" }}> - {humanReadableCurrencyToString(account.claimable_rewards)} - </TableCell> - </TableRow>} - {account.operator_rewards && `${account.operator_rewards.amount}` !== "0" && <TableRow sx={{ color: theme => theme.palette.success.light }}> - <TableCell component="th" scope="row" sx={{ color: "inherit" }}> - Claimable operator rewards - </TableCell> - <TableCell align="right" sx={{ color: "inherit" }}> - {humanReadableCurrencyToString(account.operator_rewards)} - </TableCell> - </TableRow>} - {account.vesting_account && ( - <> - <TableRow> - <TableCell component="th" scope="row" colSpan={2}> - Vesting account - </TableCell> - </TableRow> - {`${account.vesting_account.locked.amount}` !== "0" && - <TableRow> - <TableCell component="th" scope="row" sx={{ pl: 4 }}> - Locked - </TableCell> - <TableCell align="right" sx={{ color: "inherit" }}> - {humanReadableCurrencyToString(account.vesting_account.locked)} - </TableCell> - </TableRow> - } - {`${account.vesting_account.vested.amount}` !== "0" && - <TableRow> - <TableCell component="th" scope="row" sx={{ pl: 4 }}> - Vested - </TableCell> - <TableCell align="right" sx={{ color: "inherit" }}> - {humanReadableCurrencyToString(account.vesting_account.vested)} - </TableCell> - </TableRow> - } - {`${account.vesting_account.vesting.amount}` !== "0" && - <TableRow> - <TableCell component="th" scope="row" sx={{ pl: 4 }}> - Vesting - </TableCell> - <TableCell align="right" sx={{ color: "inherit" }}> - {humanReadableCurrencyToString(account.vesting_account.vesting)} - </TableCell> - </TableRow> - } - {`${account.vesting_account.spendable.amount}` !== "0" && - <TableRow> - <TableCell component="th" scope="row" sx={{ pl: 4 }}> - Spendable - </TableCell> - <TableCell align="right" sx={{ color: "inherit" }}> - {humanReadableCurrencyToString(account.vesting_account.spendable)} - </TableCell> - </TableRow> - } - </> - )} - <TableRow> - <TableCell component="th" scope="row" sx={{ color: "inherit" }}> - <h3>Total value</h3> - </TableCell> - <TableCell align="right" sx={{ color: "inherit" }}> - <h3>{humanReadableCurrencyToString(account.total_value)}</h3> - </TableCell> - </TableRow> - </TableBody> - </Table> - </TableContainer> - </Box> - <Box mt={4}> - <AccumulatedRewards account={account}/> - </Box> - <Box mt={4}> - <DelegationHistory account={account}/> - </Box> - </Box> - ) -} - -/** - * Guard component to handle loading and not found states - */ -const PageAccountDetailGuard = ({ account } : { account: string }) => { - const [accountDetails, setAccountDetails] = React.useState<any>(); - const [isLoading, setLoading] = React.useState<boolean>(true); - const [error, setError] = React.useState<string>(); - const { fetchAccountById } = useMainContext() - const { id } = useParams() - - React.useEffect(() => { - setLoading(true); - (async () => { - if(typeof(id) === "string") { - try { - const res = await fetchAccountById(account); - setAccountDetails(res); - } catch(e: any) { - setError(e.message); - } - finally { - setLoading(false); - } - } - })(); - }, [id]) - - if (isLoading) { - return <CircularProgress /> - } - - // loaded, but not found - if (error) { - return ( - <Alert severity="warning"> - <AlertTitle>Account not found</AlertTitle> - Sorry, we could not find the account <code>{id || ''}</code> - </Alert> - ) - } - - return <PageAccountWithState account={accountDetails} /> -} - -/** - * Wrapper component that adds the account details based on the `id` in the address URL - */ -const PageAccountDetail = () => { - const { id } = useParams() - - if (!id || typeof id !== 'string') { - return ( - <Alert severity="error">Oh no! Could not find that account</Alert> - ) - } - - return ( - <PageAccountDetailGuard account={id} /> - ) -} - -export default PageAccountDetail diff --git a/explorer-nextjs/app/api/constants.ts b/explorer-nextjs/app/api/constants.ts deleted file mode 100644 index 515655c1840..00000000000 --- a/explorer-nextjs/app/api/constants.ts +++ /dev/null @@ -1,39 +0,0 @@ -// master APIs -export const API_BASE_URL = process.env.NEXT_PUBLIC_EXPLORER_API_URL || 'https://explorer.nymtech.net/api/v1'; -export const NYM_API_BASE_URL = process.env.NEXT_PUBLIC_NYM_API_URL || 'https://validator.nymtech.net'; - -export const NYX_RPC_BASE_URL = process.env.NEXT_PUBLIC_NYX_RPC_BASE_URL || 'https://rpc.nymtech.net'; - -export const VALIDATOR_BASE_URL = process.env.NEXT_PUBLIC_VALIDATOR_URL || 'https://rpc.nymtech.net'; -export const BLOCK_EXPLORER_BASE_URL = process.env.NEXT_PUBLIC_BIG_DIPPER_URL || 'https://nym.explorers.guru'; - -// specific API routes -export const OVERVIEW_API = `${API_BASE_URL}/overview`; -export const MIXNODE_PING = `${API_BASE_URL}/ping`; -export const MIXNODES_API = `${API_BASE_URL}/mix-nodes`; -export const MIXNODE_API = `${API_BASE_URL}/mix-node`; -export const VALIDATORS_API = `${NYX_RPC_BASE_URL}/validators`; -export const BLOCK_API = `${NYX_RPC_BASE_URL}/block`; -export const COUNTRY_DATA_API = `${API_BASE_URL}/countries`; -export const UPTIME_STORY_API = `${NYM_API_BASE_URL}/api/v1/status/mixnode`; // add ID then '/history' to this. -export const UPTIME_STORY_API_GATEWAY = `${NYM_API_BASE_URL}/api/v1/status/gateway`; // add ID then '/history' or '/report' to this -export const SERVICE_PROVIDERS = `${API_BASE_URL}/service-providers`; -export const TEMP_UNSTABLE_NYM_NODES = `${API_BASE_URL}/tmp/unstable/nym-nodes`; -export const TEMP_UNSTABLE_ACCOUNT = `${API_BASE_URL}/tmp/unstable/account`; -export const NYM_API_NODE_UPTIME = `${NYM_API_BASE_URL}/api/v1/nym-nodes/uptime-history`; -export const NYM_API_NODE_PERFORMANCE = `${NYM_API_BASE_URL}/api/v1/nym-nodes/performance-history`; - -export const LEGACY_MIXNODES_API = `${API_BASE_URL}/tmp/unstable/legacy-mixnode-bonds`; -export const LEGACY_GATEWAYS_API = `${API_BASE_URL}/tmp/unstable/legacy-gateway-bonds`; - -// errors -export const MIXNODE_API_ERROR = "We're having trouble finding that record, please try again or Contact Us."; - -export const NYM_WEBSITE = 'https://nymtech.net'; - -export const EXPLORER_FOR_ACCOUNTS = ''; // set to empty to use this Nym Explorer and NOT an external one - -export const NYM_MIXNET_CONTRACT = - process.env.NYM_MIXNET_CONTRACT || 'n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr'; -export const COSMOS_KIT_USE_CHAIN = process.env.NEXT_PUBLIC_COSMOS_KIT_USE_CHAIN || 'sandbox'; -export const WALLET_CONNECT_PROJECT_ID = process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID || ''; diff --git a/explorer-nextjs/app/api/index.ts b/explorer-nextjs/app/api/index.ts deleted file mode 100644 index ae190de9b9d..00000000000 --- a/explorer-nextjs/app/api/index.ts +++ /dev/null @@ -1,217 +0,0 @@ -import keyBy from 'lodash/keyBy'; -import { - API_BASE_URL, - BLOCK_API, - COUNTRY_DATA_API, - UPTIME_STORY_API_GATEWAY, - MIXNODE_API, - MIXNODE_PING, - MIXNODES_API, - OVERVIEW_API, - UPTIME_STORY_API, - VALIDATORS_API, - SERVICE_PROVIDERS, - TEMP_UNSTABLE_NYM_NODES, - NYM_API_NODE_UPTIME, - NYM_API_NODE_PERFORMANCE, - TEMP_UNSTABLE_ACCOUNT, - LEGACY_MIXNODES_API, LEGACY_GATEWAYS_API, -} from './constants'; - -import { - CountryDataResponse, - DelegationsResponse, - UniqDelegationsResponse, - GatewayReportResponse, - UptimeStoryResponse, - MixNodeDescriptionResponse, - MixNodeResponse, - MixNodeResponseItem, - MixnodeStatus, - MixNodeEconomicDynamicsStatsResponse, - StatsResponse, - StatusResponse, - SummaryOverviewResponse, - ValidatorsResponse, - Environment, - GatewayBondAnnotated, - GatewayBond, - DirectoryServiceProvider, - LocatedGateway, -} from '../typeDefs/explorer-api'; - -function getFromCache(key: string) { - const ts = Number(localStorage.getItem('ts')); - const hasExpired = Date.now() - ts > 5000; - const curr = localStorage.getItem(key); - if (curr && !hasExpired) { - return JSON.parse(curr); - } - return undefined; -} - -function storeInCache(key: string, data: any) { - localStorage.setItem(key, data); - localStorage.setItem('ts', Date.now().toString()); -} - -export class Api { - static fetchOverviewSummary = async (): Promise<SummaryOverviewResponse> => { - const cache = getFromCache('overview-summary'); - if (cache) { - return cache; - } - const res = await fetch(`${OVERVIEW_API}/summary`); - const json: SummaryOverviewResponse = await res.json(); - - if (json.nymnodes?.roles) { - json.mixnodes.count += json.nymnodes.roles.mixnode; - json.gateways.count += json.nymnodes.roles.entry; - json.gateways.count += Math.max(json.nymnodes.roles.exit_ipr, json.nymnodes.roles.exit_nr); - } - - storeInCache('overview-summary', JSON.stringify(json)); - return json; - }; - - static fetchMixnodes = async (): Promise<MixNodeResponse> => { - const cachedMixnodes = getFromCache('mixnodes'); - if (cachedMixnodes) { - return cachedMixnodes; - } - - const res = await fetch(LEGACY_MIXNODES_API); - const json = await res.json(); - storeInCache('mixnodes', JSON.stringify(json)); - return json; - }; - - static fetchMixnodesActiveSetByStatus = async (status: MixnodeStatus): Promise<MixNodeResponse> => { - const cachedMixnodes = getFromCache(`mixnodes-${status}`); - if (cachedMixnodes) { - return cachedMixnodes; - } - const res = await fetch(`${MIXNODES_API}/active-set/${status}`); - const json = await res.json(); - storeInCache(`mixnodes-${status}`, JSON.stringify(json)); - return json; - }; - - static fetchMixnodeByID = async (id: string): Promise<MixNodeResponseItem | undefined> => { - const response = await fetch(`${MIXNODE_API}/${id}`); - - // when the mixnode is not found, returned undefined - if (response.status === 404) { - return undefined; - } - - return response.json(); - }; - - static fetchGateways = async (): Promise<LocatedGateway[]> => { - // const res = await fetch(GATEWAYS_API); - // const gatewaysAnnotated: GatewayBondAnnotated[] = await res.json(); - // const res2 = await fetch(GATEWAYS_EXPLORER_API); - // const locatedGateways: LocatedGateway[] = await res2.json(); - // const locatedGatewaysByOwner = keyBy(locatedGateways, 'owner'); - // return gatewaysAnnotated.map(({ gateway_bond, node_performance }) => ({ - // ...gateway_bond, - // node_performance, - // location: locatedGatewaysByOwner[gateway_bond.owner]?.location, - // })); - - const res = await fetch(LEGACY_GATEWAYS_API); - const locatedGateways: LocatedGateway[] = await res.json(); - return locatedGateways; - }; - - static fetchGatewayUptimeStoryById = async (id: string): Promise<UptimeStoryResponse> => - (await fetch(`${UPTIME_STORY_API_GATEWAY}/${id}/history`)).json(); - - static fetchGatewayReportById = async (id: string): Promise<GatewayReportResponse> => - (await fetch(`${UPTIME_STORY_API_GATEWAY}/${id}/report`)).json(); - - static fetchValidators = async (): Promise<ValidatorsResponse> => { - const res = await fetch(VALIDATORS_API); - const json = await res.json(); - return json.result; - }; - - static fetchBlock = async (): Promise<number> => { - const res = await fetch(BLOCK_API); - const json = await res.json(); - const { height } = json.result.block.header; - return height; - }; - - static fetchCountryData = async (): Promise<CountryDataResponse> => { - const result: CountryDataResponse = {}; - const res = await fetch(COUNTRY_DATA_API); - const json = await res.json(); - Object.keys(json).forEach((ISO3) => { - result[ISO3] = { ISO3, nodes: json[ISO3] }; - }); - return result; - }; - - static fetchDelegationsById = async (id: string): Promise<DelegationsResponse> => - (await fetch(`${MIXNODE_API}/${id}/delegations`)).json(); - - static fetchUniqDelegationsById = async (id: string): Promise<UniqDelegationsResponse> => - (await fetch(`${MIXNODE_API}/${id}/delegations/summed`)).json(); - - static fetchStatsById = async (id: string): Promise<StatsResponse> => - (await fetch(`${MIXNODE_API}/${id}/stats`)).json(); - - static fetchMixnodeDescriptionById = async (id: string): Promise<MixNodeDescriptionResponse> => - (await fetch(`${MIXNODE_API}/${id}/description`)).json(); - - static fetchMixnodeEconomicDynamicsStatsById = async (id: string): Promise<MixNodeEconomicDynamicsStatsResponse> => - (await fetch(`${MIXNODE_API}/${id}/economic-dynamics-stats`)).json(); - - static fetchStatusById = async (id: string): Promise<StatusResponse> => (await fetch(`${MIXNODE_PING}/${id}`)).json(); - - static fetchUptimeStoryById = async (id: string): Promise<UptimeStoryResponse> => - (await fetch(`${UPTIME_STORY_API}/${id}/history`)).json(); - - static fetchServiceProviders = async (): Promise<DirectoryServiceProvider[]> => { - const res = await fetch(SERVICE_PROVIDERS); - const json = await res.json(); - return json; - }; - - static fetchNodes = async () => { - const res = await fetch(TEMP_UNSTABLE_NYM_NODES); - const json = await res.json(); - return json; - } - - static fetchNodeById = async (id: number) => { - const res = await fetch(`${TEMP_UNSTABLE_NYM_NODES}/${id}`); - const json = await res.json(); - return json; - } - - static fetchNymNodeUptimeHistoryById = async (id: number | string) => { - const res = await fetch(`${NYM_API_NODE_UPTIME}/${id}`) - const json = await res.json(); - return json; - } - - static fetchNymNodePerformanceById = async (id: number | string) => { - const res = await fetch(`${NYM_API_NODE_PERFORMANCE}/${id}`) - const json = await res.json(); - return json; - } - - static fetchAccountById = async (id: string) => { - const res = await fetch(`${TEMP_UNSTABLE_ACCOUNT}/${id}`); - const json = await res.json(); - return json; - } -} - -export const getEnvironment = (): Environment => { - const matchEnv = (env: Environment) => API_BASE_URL?.toLocaleLowerCase().includes(env) && env; - return matchEnv('sandbox') || matchEnv('qa') || 'mainnet'; -}; diff --git a/explorer-nextjs/app/assets/world-110m.json b/explorer-nextjs/app/assets/world-110m.json deleted file mode 100644 index 5c999c82ca2..00000000000 --- a/explorer-nextjs/app/assets/world-110m.json +++ /dev/null @@ -1,39718 +0,0 @@ -{ - "type": "Topology", - "arcs": [ - [ - [ - 16814, - 15074 - ], - [ - 71, - -45 - ], - [ - 53, - 16 - ], - [ - 15, - 54 - ], - [ - 55, - 18 - ], - [ - 39, - 37 - ], - [ - 14, - 95 - ], - [ - 59, - 24 - ], - [ - 11, - 42 - ], - [ - 32, - -32 - ], - [ - 21, - -3 - ] - ], - [ - [ - 17184, - 15280 - ], - [ - 39, - -1 - ], - [ - 53, - -26 - ] - ], - [ - [ - 17276, - 15253 - ], - [ - 21, - -14 - ], - [ - 51, - 38 - ], - [ - 23, - -23 - ], - [ - 23, - 55 - ], - [ - 41, - -2 - ], - [ - 11, - 17 - ], - [ - 7, - 49 - ], - [ - 30, - 41 - ], - [ - 38, - -27 - ], - [ - -8, - -37 - ], - [ - 22, - -5 - ], - [ - -7, - -101 - ], - [ - 28, - -39 - ], - [ - 24, - 25 - ], - [ - 31, - 12 - ], - [ - 43, - 53 - ], - [ - 48, - -8 - ], - [ - 72, - -1 - ] - ], - [ - [ - 17774, - 15286 - ], - [ - 13, - -34 - ] - ], - [ - [ - 17787, - 15252 - ], - [ - -41, - -13 - ], - [ - -35, - -23 - ], - [ - -80, - -14 - ], - [ - -75, - -25 - ], - [ - -41, - -52 - ], - [ - 17, - -51 - ], - [ - 8, - -60 - ], - [ - -35, - -50 - ], - [ - 3, - -46 - ], - [ - -19, - -43 - ], - [ - -67, - 4 - ], - [ - 28, - -80 - ], - [ - -45, - -30 - ], - [ - -29, - -73 - ], - [ - 4, - -72 - ], - [ - -28, - -33 - ], - [ - -26, - 11 - ], - [ - -53, - -16 - ], - [ - -7, - -33 - ], - [ - -52, - 0 - ], - [ - -39, - -68 - ], - [ - -3, - -102 - ], - [ - -90, - -50 - ], - [ - -49, - 10 - ], - [ - -14, - -26 - ], - [ - -42, - 15 - ], - [ - -69, - -17 - ], - [ - -117, - 61 - ] - ], - [ - [ - 16791, - 14376 - ], - [ - 63, - 109 - ], - [ - -6, - 77 - ], - [ - -52, - 20 - ], - [ - -6, - 76 - ], - [ - -23, - 96 - ], - [ - 30, - 66 - ], - [ - -30, - 17 - ], - [ - 19, - 88 - ], - [ - 28, - 149 - ] - ], - [ - [ - 14166, - 8695 - ], - [ - -128, - -49 - ], - [ - -169, - 17 - ], - [ - -48, - 58 - ], - [ - -283, - -6 - ], - [ - -11, - -8 - ], - [ - -41, - 54 - ], - [ - -45, - 4 - ], - [ - -42, - -21 - ], - [ - -34, - -22 - ] - ], - [ - [ - 13365, - 8722 - ], - [ - -6, - 75 - ], - [ - 10, - 105 - ], - [ - 24, - 110 - ], - [ - 3, - 52 - ], - [ - 23, - 108 - ], - [ - 16, - 49 - ], - [ - 41, - 79 - ], - [ - 22, - 53 - ], - [ - 7, - 89 - ], - [ - -3, - 68 - ], - [ - -21, - 43 - ], - [ - -19, - 72 - ], - [ - -17, - 72 - ], - [ - 4, - 25 - ], - [ - 21, - 48 - ], - [ - -21, - 116 - ], - [ - -14, - 80 - ], - [ - -35, - 76 - ], - [ - 6, - 23 - ] - ], - [ - [ - 13406, - 10065 - ], - [ - 29, - 16 - ], - [ - 20, - -2 - ], - [ - 25, - 15 - ], - [ - 206, - -2 - ], - [ - 17, - -89 - ], - [ - 20, - -72 - ], - [ - 16, - -39 - ], - [ - 27, - -63 - ], - [ - 46, - 10 - ], - [ - 23, - 17 - ], - [ - 38, - -17 - ], - [ - 11, - 30 - ], - [ - 17, - 70 - ], - [ - 43, - 4 - ], - [ - 4, - 21 - ], - [ - 36, - 1 - ], - [ - -6, - -44 - ], - [ - 84, - 2 - ], - [ - 1, - -76 - ], - [ - 15, - -46 - ], - [ - -11, - -73 - ], - [ - 5, - -73 - ], - [ - 24, - -45 - ], - [ - -4, - -143 - ], - [ - 17, - 11 - ], - [ - 30, - -3 - ], - [ - 44, - 18 - ], - [ - 31, - -7 - ] - ], - [ - [ - 14214, - 9486 - ], - [ - 8, - -37 - ], - [ - -8, - -58 - ], - [ - 12, - -56 - ], - [ - -10, - -45 - ], - [ - 6, - -42 - ], - [ - -146, - 2 - ], - [ - -3, - -382 - ], - [ - 47, - -98 - ], - [ - 46, - -75 - ] - ], - [ - [ - 13397, - 10103 - ], - [ - -19, - 90 - ] - ], - [ - [ - 13378, - 10193 - ], - [ - 28, - 52 - ], - [ - 21, - 20 - ], - [ - 26, - -41 - ] - ], - [ - [ - 13453, - 10224 - ], - [ - -25, - -26 - ], - [ - -11, - -30 - ], - [ - -3, - -53 - ], - [ - -17, - -12 - ] - ], - [ - [ - 14013, - 15697 - ], - [ - -2, - -31 - ], - [ - -22, - -18 - ], - [ - -4, - -39 - ], - [ - -33, - -58 - ] - ], - [ - [ - 13952, - 15551 - ], - [ - -12, - 8 - ], - [ - -1, - 27 - ], - [ - -39, - 40 - ], - [ - -6, - 57 - ], - [ - 6, - 82 - ], - [ - 10, - 37 - ], - [ - -12, - 19 - ] - ], - [ - [ - 13898, - 15821 - ], - [ - -5, - 38 - ], - [ - 30, - 59 - ], - [ - 5, - -22 - ], - [ - 19, - 11 - ] - ], - [ - [ - 13947, - 15907 - ], - [ - 14, - -33 - ], - [ - 17, - -12 - ], - [ - 5, - -43 - ] - ], - [ - [ - 13983, - 15819 - ], - [ - -9, - -41 - ], - [ - 10, - -52 - ], - [ - 29, - -29 - ] - ], - [ - [ - 16143, - 13706 - ], - [ - 12, - 6 - ], - [ - 3, - -33 - ], - [ - 55, - 19 - ], - [ - 57, - -3 - ], - [ - 42, - -4 - ], - [ - 48, - 81 - ], - [ - 52, - 77 - ], - [ - 44, - 74 - ] - ], - [ - [ - 16456, - 13923 - ], - [ - 13, - -41 - ] - ], - [ - [ - 16469, - 13882 - ], - [ - 10, - -95 - ] - ], - [ - [ - 16479, - 13787 - ], - [ - -36, - 0 - ], - [ - -5, - -78 - ], - [ - 12, - -17 - ], - [ - -32, - -24 - ], - [ - 0, - -49 - ], - [ - -20, - -49 - ], - [ - -2, - -49 - ] - ], - [ - [ - 16396, - 13521 - ], - [ - -14, - -25 - ], - [ - -210, - 61 - ], - [ - -26, - 121 - ], - [ - -3, - 28 - ] - ], - [ - [ - 7880, - 4211 - ], - [ - -42, - 4 - ], - [ - -75, - 0 - ], - [ - 0, - 267 - ] - ], - [ - [ - 7763, - 4482 - ], - [ - 27, - -55 - ], - [ - 35, - -90 - ], - [ - 90, - -72 - ], - [ - 98, - -30 - ], - [ - -31, - -60 - ], - [ - -67, - -6 - ], - [ - -35, - 42 - ] - ], - [ - [ - 7767, - 4523 - ], - [ - -64, - 19 - ], - [ - -169, - 16 - ], - [ - -28, - 70 - ], - [ - 1, - 90 - ], - [ - -47, - -8 - ], - [ - -24, - 43 - ], - [ - -6, - 128 - ], - [ - 53, - 52 - ], - [ - 22, - 76 - ], - [ - -8, - 61 - ], - [ - 37, - 102 - ], - [ - 26, - 159 - ], - [ - -8, - 71 - ], - [ - 31, - 22 - ], - [ - -8, - 46 - ], - [ - -32, - 24 - ], - [ - 23, - 50 - ], - [ - -32, - 46 - ], - [ - -16, - 138 - ], - [ - 28, - 24 - ], - [ - -12, - 147 - ], - [ - 17, - 122 - ], - [ - 18, - 107 - ], - [ - 42, - 44 - ], - [ - -21, - 117 - ], - [ - 0, - 110 - ], - [ - 52, - 79 - ], - [ - -1, - 100 - ], - [ - 40, - 117 - ], - [ - 0, - 110 - ], - [ - -18, - 22 - ], - [ - -32, - 207 - ], - [ - 43, - 124 - ], - [ - -7, - 116 - ], - [ - 25, - 109 - ], - [ - 46, - 113 - ], - [ - 49, - 74 - ], - [ - -21, - 47 - ], - [ - 14, - 39 - ], - [ - -2, - 200 - ], - [ - 76, - 59 - ], - [ - 24, - 125 - ], - [ - -8, - 30 - ] - ], - [ - [ - 7870, - 8070 - ], - [ - 58, - 108 - ], - [ - 91, - -29 - ], - [ - 41, - -87 - ], - [ - 27, - 97 - ], - [ - 80, - -5 - ], - [ - 11, - -26 - ] - ], - [ - [ - 8178, - 8128 - ], - [ - 128, - -196 - ], - [ - 57, - -18 - ], - [ - 85, - -89 - ], - [ - 72, - -47 - ], - [ - 10, - -52 - ], - [ - -69, - -183 - ], - [ - 71, - -32 - ], - [ - 78, - -19 - ], - [ - 55, - 20 - ], - [ - 63, - 91 - ], - [ - 12, - 106 - ] - ], - [ - [ - 8740, - 7709 - ], - [ - 34, - 23 - ], - [ - 35, - -69 - ], - [ - -1, - -96 - ], - [ - -59, - -66 - ], - [ - -47, - -49 - ], - [ - -78, - -116 - ], - [ - -93, - -164 - ] - ], - [ - [ - 8531, - 7172 - ], - [ - -18, - -96 - ], - [ - -19, - -123 - ], - [ - 1, - -120 - ], - [ - -15, - -26 - ], - [ - -5, - -78 - ] - ], - [ - [ - 8475, - 6729 - ], - [ - -5, - -63 - ], - [ - 88, - -102 - ], - [ - -9, - -83 - ], - [ - 43, - -52 - ], - [ - -3, - -59 - ], - [ - -67, - -154 - ], - [ - -103, - -64 - ], - [ - -140, - -25 - ], - [ - -77, - 12 - ], - [ - 15, - -71 - ], - [ - -14, - -90 - ], - [ - 12, - -61 - ], - [ - -41, - -42 - ], - [ - -72, - -17 - ], - [ - -67, - 44 - ], - [ - -27, - -31 - ], - [ - 10, - -119 - ], - [ - 47, - -37 - ], - [ - 38, - 38 - ], - [ - 21, - -62 - ], - [ - -64, - -37 - ], - [ - -56, - -75 - ], - [ - -10, - -121 - ], - [ - -17, - -64 - ], - [ - -66, - 0 - ], - [ - -54, - -62 - ], - [ - -20, - -90 - ], - [ - 68, - -87 - ], - [ - 67, - -25 - ], - [ - -24, - -107 - ], - [ - -83, - -68 - ], - [ - -45, - -141 - ], - [ - -63, - -47 - ], - [ - -29, - -56 - ], - [ - 22, - -125 - ], - [ - 47, - -69 - ], - [ - -30, - 6 - ] - ], - [ - [ - 15586, - 15727 - ], - [ - 96, - 19 - ] - ], - [ - [ - 15682, - 15746 - ], - [ - 15, - -32 - ], - [ - 26, - -21 - ], - [ - -14, - -30 - ], - [ - 38, - -41 - ], - [ - -20, - -38 - ], - [ - 29, - -33 - ], - [ - 32, - -19 - ], - [ - 1, - -84 - ] - ], - [ - [ - 15789, - 15448 - ], - [ - -25, - -3 - ] - ], - [ - [ - 15764, - 15445 - ], - [ - -28, - 69 - ], - [ - 0, - 19 - ], - [ - -31, - 0 - ], - [ - -20, - 32 - ], - [ - -15, - -3 - ] - ], - [ - [ - 15670, - 15562 - ], - [ - -27, - 35 - ], - [ - -52, - 29 - ], - [ - 6, - 59 - ], - [ - -11, - 42 - ] - ], - [ - [ - 8395, - 1195 - ], - [ - -21, - -61 - ], - [ - -20, - -54 - ], - [ - -146, - 16 - ], - [ - -156, - -7 - ], - [ - -87, - 40 - ], - [ - 0, - 5 - ], - [ - -38, - 35 - ], - [ - 157, - -5 - ], - [ - 150, - -11 - ], - [ - 52, - 49 - ], - [ - 36, - 42 - ], - [ - 73, - -49 - ] - ], - [ - [ - 1449, - 1260 - ], - [ - -133, - -16 - ], - [ - -92, - 42 - ], - [ - -41, - 42 - ], - [ - -3, - 7 - ], - [ - -45, - 33 - ], - [ - 43, - 45 - ], - [ - 129, - -19 - ], - [ - 70, - -38 - ], - [ - 53, - -42 - ], - [ - 19, - -54 - ] - ], - [ - [ - 9400, - 1434 - ], - [ - 86, - -52 - ], - [ - 30, - -73 - ], - [ - 8, - -51 - ], - [ - 3, - -61 - ], - [ - -108, - -38 - ], - [ - -113, - -31 - ], - [ - -131, - -28 - ], - [ - -147, - -23 - ], - [ - -165, - 7 - ], - [ - -91, - 40 - ], - [ - 12, - 49 - ], - [ - 149, - 33 - ], - [ - 60, - 40 - ], - [ - 44, - 52 - ], - [ - 31, - 44 - ], - [ - 42, - 43 - ], - [ - 45, - 49 - ], - [ - 36, - 0 - ], - [ - 104, - 26 - ], - [ - 105, - -26 - ] - ], - [ - [ - 4098, - 1979 - ], - [ - 90, - -18 - ], - [ - 83, - 21 - ], - [ - -39, - -43 - ], - [ - -66, - -30 - ], - [ - -97, - 9 - ], - [ - -69, - 43 - ], - [ - 15, - 40 - ], - [ - 83, - -22 - ] - ], - [ - [ - 3795, - 1982 - ], - [ - 106, - -47 - ], - [ - -41, - 4 - ], - [ - -90, - 12 - ], - [ - -95, - 33 - ], - [ - 50, - 26 - ], - [ - 70, - -28 - ] - ], - [ - [ - 5648, - 2167 - ], - [ - 76, - -16 - ], - [ - 77, - 14 - ], - [ - 41, - -68 - ], - [ - -55, - 9 - ], - [ - -85, - -4 - ], - [ - -86, - 4 - ], - [ - -94, - -7 - ], - [ - -71, - 24 - ], - [ - -37, - 49 - ], - [ - 44, - 21 - ], - [ - 89, - -16 - ], - [ - 101, - -10 - ] - ], - [ - [ - 7776, - 2285 - ], - [ - 8, - -54 - ], - [ - -12, - -47 - ], - [ - -19, - -45 - ], - [ - -82, - -16 - ], - [ - -78, - -24 - ], - [ - -92, - 2 - ], - [ - 35, - 47 - ], - [ - -82, - -16 - ], - [ - -78, - -17 - ], - [ - -53, - 36 - ], - [ - -5, - 49 - ], - [ - 77, - 47 - ], - [ - 48, - 14 - ], - [ - 80, - -5 - ], - [ - 21, - 62 - ], - [ - 4, - 44 - ], - [ - -2, - 97 - ], - [ - 40, - 56 - ], - [ - 64, - 19 - ], - [ - 37, - -45 - ], - [ - 17, - -44 - ], - [ - 30, - -55 - ], - [ - 23, - -51 - ], - [ - 19, - -54 - ] - ], - [ - [ - 8462, - 3101 - ], - [ - -30, - -26 - ], - [ - -52, - 19 - ], - [ - -58, - -12 - ], - [ - -47, - -28 - ], - [ - -51, - -31 - ], - [ - -34, - -35 - ], - [ - -10, - -47 - ], - [ - 4, - -45 - ], - [ - 33, - -40 - ], - [ - -48, - -28 - ], - [ - -65, - -9 - ], - [ - -38, - -40 - ], - [ - -41, - -38 - ], - [ - -44, - -51 - ], - [ - -11, - -45 - ], - [ - 25, - -50 - ], - [ - 37, - -37 - ], - [ - 57, - -28 - ], - [ - 53, - -38 - ], - [ - 29, - -47 - ], - [ - 15, - -45 - ], - [ - 20, - -47 - ], - [ - 33, - -40 - ], - [ - 21, - -44 - ], - [ - 9, - -111 - ], - [ - 21, - -44 - ], - [ - 5, - -47 - ], - [ - 22, - -47 - ], - [ - -10, - -64 - ], - [ - -38, - -49 - ], - [ - -41, - -40 - ], - [ - -93, - -17 - ], - [ - -31, - -42 - ], - [ - -42, - -40 - ], - [ - -106, - -45 - ], - [ - -92, - -18 - ], - [ - -88, - -26 - ], - [ - -94, - -26 - ], - [ - -56, - -50 - ], - [ - -112, - -4 - ], - [ - -123, - 4 - ], - [ - -110, - -9 - ], - [ - -118, - 0 - ], - [ - 22, - -47 - ], - [ - 107, - -21 - ], - [ - 77, - -33 - ], - [ - 44, - -42 - ], - [ - -78, - -38 - ], - [ - -120, - 12 - ], - [ - -100, - -31 - ], - [ - -4, - -49 - ], - [ - -2, - -47 - ], - [ - 82, - -40 - ], - [ - 15, - -45 - ], - [ - 88, - -44 - ], - [ - 148, - -19 - ], - [ - 125, - -33 - ], - [ - 100, - -38 - ], - [ - 127, - -37 - ], - [ - 173, - -19 - ], - [ - 171, - -33 - ], - [ - 119, - -35 - ], - [ - 130, - -40 - ], - [ - 68, - -57 - ], - [ - 34, - -44 - ], - [ - 85, - 42 - ], - [ - 114, - 35 - ], - [ - 122, - 38 - ], - [ - 144, - 30 - ], - [ - 125, - 33 - ], - [ - 173, - 3 - ], - [ - 171, - -17 - ], - [ - 140, - -28 - ], - [ - 45, - 52 - ], - [ - 97, - 35 - ], - [ - 177, - 2 - ], - [ - 137, - 26 - ], - [ - 131, - 26 - ], - [ - 145, - 16 - ], - [ - 154, - 22 - ], - [ - 108, - 30 - ], - [ - -49, - 42 - ], - [ - -30, - 43 - ], - [ - 0, - 44 - ], - [ - -135, - -4 - ], - [ - -143, - -19 - ], - [ - -137, - 0 - ], - [ - -19, - 45 - ], - [ - 10, - 89 - ], - [ - 31, - 26 - ], - [ - 100, - 28 - ], - [ - 117, - 28 - ], - [ - 85, - 35 - ], - [ - 84, - 36 - ], - [ - 63, - 47 - ], - [ - 96, - 21 - ], - [ - 94, - 16 - ], - [ - 48, - 10 - ], - [ - 108, - 4 - ], - [ - 102, - 17 - ], - [ - 86, - 23 - ], - [ - 85, - 29 - ], - [ - 76, - 28 - ], - [ - 97, - 37 - ], - [ - 61, - 40 - ], - [ - 66, - 36 - ], - [ - 20, - 47 - ], - [ - -73, - 28 - ], - [ - 24, - 49 - ], - [ - 47, - 38 - ], - [ - 72, - 23 - ], - [ - 77, - 29 - ], - [ - 71, - 37 - ], - [ - 54, - 47 - ], - [ - 34, - 57 - ], - [ - 51, - 33 - ], - [ - 83, - -7 - ], - [ - 34, - -40 - ], - [ - 83, - -5 - ], - [ - 3, - 45 - ], - [ - 36, - 47 - ], - [ - 75, - -12 - ], - [ - 18, - -45 - ], - [ - 83, - -7 - ], - [ - 90, - 21 - ], - [ - 87, - 14 - ], - [ - 80, - -7 - ], - [ - 30, - -49 - ], - [ - 76, - 40 - ], - [ - 71, - 21 - ], - [ - 79, - 16 - ], - [ - 78, - 17 - ], - [ - 71, - 28 - ], - [ - 78, - 19 - ], - [ - 60, - 26 - ], - [ - 42, - 42 - ], - [ - 52, - -30 - ], - [ - 72, - 16 - ], - [ - 51, - -56 - ], - [ - 40, - -43 - ], - [ - 79, - 24 - ], - [ - 31, - 47 - ], - [ - 71, - 33 - ], - [ - 92, - -7 - ], - [ - 27, - -45 - ], - [ - 57, - 45 - ], - [ - 75, - 14 - ], - [ - 82, - 4 - ], - [ - 74, - -2 - ], - [ - 78, - -14 - ], - [ - 75, - -7 - ], - [ - 33, - -40 - ], - [ - 45, - -35 - ], - [ - 76, - 21 - ], - [ - 82, - 5 - ], - [ - 79, - 0 - ], - [ - 78, - 2 - ], - [ - 70, - 16 - ], - [ - 74, - 15 - ], - [ - 61, - 32 - ], - [ - 65, - 22 - ], - [ - 71, - 11 - ], - [ - 54, - 33 - ], - [ - 38, - 66 - ], - [ - 40, - 40 - ], - [ - 72, - -19 - ], - [ - 27, - -42 - ], - [ - 60, - -28 - ], - [ - 73, - 9 - ], - [ - 49, - -42 - ], - [ - 52, - -31 - ], - [ - 71, - 28 - ], - [ - 24, - 52 - ], - [ - 63, - 21 - ], - [ - 72, - 40 - ], - [ - 69, - 17 - ], - [ - 82, - 23 - ], - [ - 54, - 26 - ], - [ - 58, - 28 - ], - [ - 54, - 26 - ], - [ - 66, - -14 - ], - [ - 63, - 42 - ], - [ - 45, - 33 - ], - [ - 65, - -2 - ], - [ - 57, - 28 - ], - [ - 14, - 42 - ], - [ - 59, - 33 - ], - [ - 57, - 24 - ], - [ - 70, - 19 - ], - [ - 64, - 9 - ], - [ - 61, - -7 - ], - [ - 66, - -12 - ], - [ - 56, - -33 - ], - [ - 7, - -51 - ], - [ - 61, - -40 - ], - [ - 42, - -33 - ], - [ - 84, - -14 - ], - [ - 46, - -33 - ], - [ - 58, - -33 - ], - [ - 66, - -7 - ], - [ - 56, - 23 - ], - [ - 60, - 50 - ], - [ - 66, - -26 - ], - [ - 68, - -14 - ], - [ - 66, - -14 - ], - [ - 68, - -10 - ], - [ - 70, - 0 - ], - [ - 57, - -124 - ], - [ - -3, - -31 - ], - [ - -8, - -54 - ], - [ - -67, - -31 - ], - [ - -54, - -44 - ], - [ - 9, - -47 - ], - [ - 78, - 2 - ], - [ - -10, - -47 - ], - [ - -35, - -45 - ], - [ - -33, - -49 - ], - [ - 53, - -38 - ], - [ - 81, - -11 - ], - [ - 81, - 21 - ], - [ - 38, - 47 - ], - [ - 23, - 45 - ], - [ - 38, - 37 - ], - [ - 44, - 35 - ], - [ - 18, - 43 - ], - [ - 36, - 58 - ], - [ - 44, - 12 - ], - [ - 79, - 5 - ], - [ - 70, - 14 - ], - [ - 71, - 19 - ], - [ - 34, - 47 - ], - [ - 21, - 45 - ], - [ - 47, - 44 - ], - [ - 69, - 31 - ], - [ - 58, - 23 - ], - [ - 39, - 40 - ], - [ - 39, - 21 - ], - [ - 51, - 19 - ], - [ - 69, - -12 - ], - [ - 63, - 12 - ], - [ - 68, - 14 - ], - [ - 77, - -7 - ], - [ - 50, - 33 - ], - [ - 36, - 80 - ], - [ - 26, - -33 - ], - [ - 33, - -56 - ], - [ - 58, - -24 - ], - [ - 67, - -9 - ], - [ - 67, - 14 - ], - [ - 71, - -9 - ], - [ - 66, - -3 - ], - [ - 43, - 12 - ], - [ - 59, - -7 - ], - [ - 53, - -26 - ], - [ - 63, - 16 - ], - [ - 75, - 0 - ], - [ - 64, - 17 - ], - [ - 73, - -17 - ], - [ - 46, - 40 - ], - [ - 36, - 40 - ], - [ - 47, - 33 - ], - [ - 88, - 90 - ], - [ - 45, - -17 - ], - [ - 53, - -33 - ], - [ - 46, - -42 - ], - [ - 89, - -73 - ], - [ - 69, - -2 - ], - [ - 64, - 0 - ], - [ - 75, - 14 - ], - [ - 75, - 16 - ], - [ - 57, - 33 - ], - [ - 48, - 35 - ], - [ - 78, - 5 - ], - [ - 52, - 26 - ], - [ - 54, - -23 - ], - [ - 36, - -38 - ], - [ - 49, - -38 - ], - [ - 76, - 5 - ], - [ - 48, - -31 - ], - [ - 83, - -30 - ], - [ - 88, - -12 - ], - [ - 72, - 10 - ], - [ - 55, - 37 - ], - [ - 46, - 38 - ], - [ - 63, - 9 - ], - [ - 63, - -16 - ], - [ - 72, - -12 - ], - [ - 66, - 19 - ], - [ - 63, - 0 - ], - [ - 61, - -12 - ], - [ - 64, - -12 - ], - [ - 63, - 21 - ], - [ - 75, - 19 - ], - [ - 71, - 5 - ], - [ - 79, - 0 - ], - [ - 64, - 12 - ], - [ - 63, - 9 - ], - [ - 19, - 59 - ], - [ - 3, - 49 - ], - [ - 44, - -33 - ], - [ - 12, - -54 - ], - [ - 23, - -49 - ], - [ - 29, - -40 - ], - [ - 59, - -21 - ], - [ - 79, - 7 - ], - [ - 91, - 2 - ], - [ - 63, - 7 - ], - [ - 92, - 0 - ], - [ - 65, - 3 - ], - [ - 92, - -5 - ], - [ - 77, - -10 - ], - [ - 50, - -37 - ], - [ - -14, - -45 - ], - [ - 45, - -35 - ], - [ - 75, - -28 - ], - [ - 78, - -31 - ], - [ - 90, - -21 - ], - [ - 94, - -19 - ], - [ - 71, - -19 - ], - [ - 79, - -2 - ], - [ - 45, - 40 - ], - [ - 62, - -33 - ], - [ - 53, - -38 - ], - [ - 62, - -28 - ], - [ - 84, - -12 - ], - [ - 81, - -14 - ], - [ - 34, - -47 - ], - [ - 79, - -28 - ], - [ - 53, - -42 - ], - [ - 78, - -19 - ], - [ - 81, - 2 - ], - [ - 75, - -7 - ], - [ - 83, - 3 - ], - [ - 83, - -10 - ], - [ - 78, - -16 - ], - [ - 73, - -28 - ], - [ - 72, - -24 - ], - [ - 49, - -35 - ], - [ - -8, - -47 - ], - [ - -37, - -42 - ], - [ - -31, - -55 - ], - [ - -25, - -42 - ], - [ - -33, - -49 - ], - [ - -91, - -19 - ], - [ - -41, - -42 - ], - [ - -90, - -26 - ], - [ - -32, - -47 - ], - [ - -47, - -45 - ], - [ - -51, - -38 - ], - [ - -29, - -49 - ], - [ - -17, - -45 - ], - [ - -7, - -54 - ], - [ - 1, - -44 - ], - [ - 40, - -47 - ], - [ - 15, - -45 - ], - [ - 32, - -42 - ], - [ - 130, - -17 - ], - [ - 27, - -51 - ], - [ - -125, - -19 - ], - [ - -107, - -26 - ], - [ - -132, - -5 - ], - [ - -59, - -68 - ], - [ - -12, - -56 - ], - [ - -30, - -45 - ], - [ - -37, - -45 - ], - [ - 93, - -40 - ], - [ - 35, - -49 - ], - [ - 60, - -45 - ], - [ - 85, - -40 - ], - [ - 97, - -37 - ], - [ - 105, - -38 - ], - [ - 160, - -38 - ], - [ - 35, - -58 - ], - [ - 201, - -26 - ], - [ - 14, - -9 - ], - [ - 52, - -36 - ], - [ - 192, - 31 - ], - [ - 160, - -38 - ], - [ - 120, - -29 - ], - [ - 0, - -634 - ], - [ - -25095, - 0 - ], - [ - 0, - 634 - ], - [ - 4, - -1 - ], - [ - 62, - 70 - ], - [ - 125, - -38 - ], - [ - 8, - 5 - ], - [ - 74, - 38 - ], - [ - 10, - -1 - ], - [ - 8, - -1 - ], - [ - 101, - -50 - ], - [ - 88, - 50 - ], - [ - 16, - 6 - ], - [ - 204, - 22 - ], - [ - 67, - -28 - ], - [ - 33, - -15 - ], - [ - 105, - -40 - ], - [ - 198, - -30 - ], - [ - 157, - -38 - ], - [ - 269, - -28 - ], - [ - 200, - 33 - ], - [ - 297, - -24 - ], - [ - 168, - -37 - ], - [ - 184, - 35 - ], - [ - 194, - 33 - ], - [ - 15, - 56 - ], - [ - -275, - 5 - ], - [ - -225, - 28 - ], - [ - -59, - 47 - ], - [ - -187, - 26 - ], - [ - 13, - 54 - ], - [ - 25, - 50 - ], - [ - 26, - 44 - ], - [ - -13, - 50 - ], - [ - -116, - 33 - ], - [ - -54, - 42 - ], - [ - -107, - 37 - ], - [ - 169, - -7 - ], - [ - 161, - 19 - ], - [ - 101, - -40 - ], - [ - 124, - 36 - ], - [ - 115, - 44 - ], - [ - 56, - 40 - ], - [ - -25, - 50 - ], - [ - -90, - 32 - ], - [ - -102, - 36 - ], - [ - -143, - 7 - ], - [ - -126, - 16 - ], - [ - -135, - 12 - ], - [ - -45, - 45 - ], - [ - -90, - 37 - ], - [ - -55, - 43 - ], - [ - -22, - 136 - ], - [ - 34, - -12 - ], - [ - 63, - -37 - ], - [ - 115, - 11 - ], - [ - 110, - 17 - ], - [ - 58, - -52 - ], - [ - 110, - 12 - ], - [ - 93, - 26 - ], - [ - 87, - 33 - ], - [ - 80, - 39 - ], - [ - 105, - 12 - ], - [ - -3, - 45 - ], - [ - -24, - 45 - ], - [ - 20, - 42 - ], - [ - 90, - 21 - ], - [ - 41, - -40 - ], - [ - 107, - 24 - ], - [ - 80, - 30 - ], - [ - 100, - 3 - ], - [ - 94, - 11 - ], - [ - 94, - 28 - ], - [ - 75, - 26 - ], - [ - 85, - 26 - ], - [ - 55, - -7 - ], - [ - 47, - -9 - ], - [ - 104, - 16 - ], - [ - 93, - -21 - ], - [ - 95, - 2 - ], - [ - 92, - 17 - ], - [ - 94, - -12 - ], - [ - 104, - -12 - ], - [ - 97, - 5 - ], - [ - 101, - -2 - ], - [ - 104, - -3 - ], - [ - 95, - 5 - ], - [ - 71, - 35 - ], - [ - 85, - 19 - ], - [ - 87, - -26 - ], - [ - 84, - 21 - ], - [ - 75, - 43 - ], - [ - 45, - -38 - ], - [ - 24, - -42 - ], - [ - 45, - -40 - ], - [ - 73, - 35 - ], - [ - 83, - -45 - ], - [ - 94, - -14 - ], - [ - 81, - -33 - ], - [ - 98, - 7 - ], - [ - 89, - 22 - ], - [ - 105, - -5 - ], - [ - 94, - -17 - ], - [ - 96, - -21 - ], - [ - 37, - 52 - ], - [ - -46, - 40 - ], - [ - -34, - 42 - ], - [ - -90, - 10 - ], - [ - -39, - 44 - ], - [ - -15, - 45 - ], - [ - -25, - 89 - ], - [ - 53, - -16 - ], - [ - 92, - -7 - ], - [ - 90, - 7 - ], - [ - 82, - -19 - ], - [ - 71, - -35 - ], - [ - 30, - -42 - ], - [ - 94, - -8 - ], - [ - 90, - 17 - ], - [ - 96, - 23 - ], - [ - 86, - 15 - ], - [ - 71, - -29 - ], - [ - 93, - 10 - ], - [ - 60, - 91 - ], - [ - 56, - -54 - ], - [ - 80, - -21 - ], - [ - 88, - 12 - ], - [ - 57, - -47 - ], - [ - 91, - -5 - ], - [ - 85, - -14 - ], - [ - 83, - -26 - ], - [ - 55, - 45 - ], - [ - 27, - 42 - ], - [ - 70, - -47 - ], - [ - 95, - 12 - ], - [ - 71, - -26 - ], - [ - 48, - -40 - ], - [ - 93, - 12 - ], - [ - 72, - 26 - ], - [ - 71, - 30 - ], - [ - 85, - 17 - ], - [ - 98, - 14 - ], - [ - 89, - 16 - ], - [ - 68, - 26 - ], - [ - 41, - 38 - ], - [ - 17, - 52 - ], - [ - -8, - 49 - ], - [ - -22, - 47 - ], - [ - -25, - 47 - ], - [ - -22, - 47 - ], - [ - -18, - 42 - ], - [ - -4, - 47 - ], - [ - 7, - 47 - ], - [ - 33, - 45 - ], - [ - 27, - 49 - ], - [ - 11, - 47 - ], - [ - -13, - 52 - ], - [ - -9, - 47 - ], - [ - 35, - 54 - ], - [ - 38, - 35 - ], - [ - 45, - 45 - ], - [ - 48, - 38 - ], - [ - 56, - 35 - ], - [ - 27, - 52 - ], - [ - 38, - 33 - ], - [ - 44, - 30 - ], - [ - 67, - 7 - ], - [ - 43, - 38 - ], - [ - 50, - 23 - ], - [ - 57, - 14 - ], - [ - 50, - 31 - ], - [ - 40, - 38 - ], - [ - 55, - 14 - ], - [ - 41, - -31 - ], - [ - -26, - -40 - ], - [ - -71, - -35 - ] - ], - [ - [ - 17353, - 4964 - ], - [ - 45, - -38 - ], - [ - 66, - -15 - ], - [ - 2, - -23 - ], - [ - -19, - -54 - ], - [ - -107, - -8 - ], - [ - -2, - 64 - ], - [ - 10, - 49 - ], - [ - 5, - 25 - ] - ], - [ - [ - 22683, - 5903 - ], - [ - 67, - -41 - ], - [ - 38, - 16 - ], - [ - 55, - 23 - ], - [ - 41, - -8 - ], - [ - 5, - -142 - ], - [ - -23, - -41 - ], - [ - -8, - -97 - ], - [ - -24, - 33 - ], - [ - -48, - -84 - ], - [ - -15, - 7 - ], - [ - -43, - 4 - ], - [ - -43, - 102 - ], - [ - -9, - 79 - ], - [ - -40, - 105 - ], - [ - 1, - 55 - ], - [ - 46, - -11 - ] - ], - [ - [ - 22555, - 9146 - ], - [ - 25, - -94 - ], - [ - 45, - 45 - ], - [ - 23, - -51 - ], - [ - 33, - -47 - ], - [ - -7, - -53 - ], - [ - 15, - -103 - ], - [ - 11, - -59 - ], - [ - 17, - -15 - ], - [ - 19, - -103 - ], - [ - -7, - -62 - ], - [ - 23, - -81 - ], - [ - 75, - -63 - ], - [ - 50, - -57 - ], - [ - 46, - -52 - ], - [ - -9, - -29 - ], - [ - 40, - -75 - ], - [ - 27, - -130 - ], - [ - 28, - 26 - ], - [ - 28, - -52 - ], - [ - 17, - 19 - ], - [ - 12, - -128 - ], - [ - 50, - -73 - ], - [ - 32, - -46 - ], - [ - 55, - -97 - ], - [ - 19, - -97 - ], - [ - 2, - -68 - ], - [ - -5, - -74 - ], - [ - 34, - -102 - ], - [ - -4, - -106 - ], - [ - -12, - -56 - ], - [ - -19, - -107 - ], - [ - 1, - -69 - ], - [ - -14, - -86 - ], - [ - -30, - -109 - ], - [ - -52, - -59 - ], - [ - -26, - -93 - ], - [ - -23, - -59 - ], - [ - -20, - -104 - ], - [ - -27, - -59 - ], - [ - -18, - -90 - ], - [ - -9, - -83 - ], - [ - 4, - -38 - ], - [ - -40, - -41 - ], - [ - -78, - -5 - ], - [ - -65, - -49 - ], - [ - -32, - -46 - ], - [ - -42, - -52 - ], - [ - -58, - 53 - ], - [ - -42, - 21 - ], - [ - 10, - 63 - ], - [ - -38, - -23 - ], - [ - -61, - -87 - ], - [ - -60, - 33 - ], - [ - -39, - 19 - ], - [ - -40, - 8 - ], - [ - -68, - 35 - ], - [ - -45, - 74 - ], - [ - -13, - 91 - ], - [ - -16, - 61 - ], - [ - -34, - 48 - ], - [ - -67, - 15 - ], - [ - 23, - 58 - ], - [ - -17, - 89 - ], - [ - -34, - -83 - ], - [ - -62, - -22 - ], - [ - 36, - 66 - ], - [ - 11, - 70 - ], - [ - 27, - 58 - ], - [ - -6, - 89 - ], - [ - -57, - -102 - ], - [ - -43, - -41 - ], - [ - -27, - -96 - ], - [ - -54, - 50 - ], - [ - 2, - 63 - ], - [ - -44, - 87 - ], - [ - -37, - 45 - ], - [ - 14, - 28 - ], - [ - -90, - 73 - ], - [ - -49, - 3 - ], - [ - -67, - 59 - ], - [ - -125, - -12 - ], - [ - -90, - -43 - ], - [ - -79, - -40 - ], - [ - -67, - 8 - ], - [ - -74, - -61 - ], - [ - -60, - -28 - ], - [ - -14, - -63 - ], - [ - -25, - -49 - ], - [ - -60, - -2 - ], - [ - -43, - -11 - ], - [ - -62, - 22 - ], - [ - -50, - -13 - ], - [ - -48, - -6 - ], - [ - -41, - -64 - ], - [ - -21, - 6 - ], - [ - -35, - -34 - ], - [ - -33, - -38 - ], - [ - -51, - 4 - ], - [ - -47, - 0 - ], - [ - -74, - 77 - ], - [ - -37, - 23 - ], - [ - 1, - 68 - ], - [ - 35, - 17 - ], - [ - 12, - 27 - ], - [ - -3, - 43 - ], - [ - 9, - 84 - ], - [ - -8, - 71 - ], - [ - -37, - 121 - ], - [ - -11, - 68 - ], - [ - 3, - 69 - ], - [ - -28, - 78 - ], - [ - -2, - 35 - ], - [ - -31, - 48 - ], - [ - -8, - 94 - ], - [ - -40, - 95 - ], - [ - -10, - 51 - ], - [ - 31, - -52 - ], - [ - -24, - 111 - ], - [ - 35, - -34 - ], - [ - 20, - -47 - ], - [ - -1, - 62 - ], - [ - -34, - 94 - ], - [ - -7, - 38 - ], - [ - -16, - 36 - ], - [ - 8, - 69 - ], - [ - 14, - 30 - ], - [ - 9, - 60 - ], - [ - -7, - 70 - ], - [ - 29, - 86 - ], - [ - 5, - -91 - ], - [ - 29, - 82 - ], - [ - 57, - 40 - ], - [ - 34, - 52 - ], - [ - 53, - 44 - ], - [ - 32, - 9 - ], - [ - 19, - -15 - ], - [ - 55, - 45 - ], - [ - 42, - 13 - ], - [ - 11, - 27 - ], - [ - 18, - 10 - ], - [ - 39, - -2 - ], - [ - 73, - 35 - ], - [ - 38, - 53 - ], - [ - 18, - 64 - ], - [ - 41, - 61 - ], - [ - 3, - 48 - ], - [ - 2, - 65 - ], - [ - 49, - 102 - ], - [ - 29, - -103 - ], - [ - 30, - 23 - ], - [ - -25, - 57 - ], - [ - 22, - 58 - ], - [ - 30, - -26 - ], - [ - 9, - 92 - ], - [ - 38, - 59 - ], - [ - 17, - 47 - ], - [ - 35, - 20 - ], - [ - 1, - 34 - ], - [ - 30, - -14 - ], - [ - 2, - 30 - ], - [ - 30, - 17 - ], - [ - 34, - 16 - ], - [ - 52, - -55 - ], - [ - 38, - -71 - ], - [ - 44, - 0 - ], - [ - 44, - -12 - ], - [ - -15, - 66 - ], - [ - 34, - 96 - ], - [ - 31, - 32 - ], - [ - -11, - 30 - ], - [ - 31, - 68 - ], - [ - 42, - 43 - ], - [ - 36, - -15 - ], - [ - 58, - 23 - ], - [ - -1, - 61 - ], - [ - -51, - 40 - ], - [ - 37, - 17 - ], - [ - 46, - -30 - ], - [ - 37, - -49 - ], - [ - 59, - -31 - ], - [ - 20, - 13 - ], - [ - 43, - -37 - ], - [ - 41, - 34 - ], - [ - 26, - -10 - ], - [ - 16, - 23 - ], - [ - 32, - -60 - ], - [ - -18, - -64 - ], - [ - -27, - -48 - ], - [ - -24, - -4 - ], - [ - 8, - -48 - ], - [ - -20, - -60 - ], - [ - -25, - -59 - ], - [ - 5, - -34 - ], - [ - 55, - -66 - ], - [ - 54, - -39 - ], - [ - 36, - -41 - ], - [ - 50, - -71 - ], - [ - 20, - 0 - ], - [ - 37, - -31 - ], - [ - 10, - -37 - ], - [ - 67, - -41 - ], - [ - 46, - 41 - ], - [ - 13, - 65 - ], - [ - 14, - 53 - ], - [ - 9, - 66 - ], - [ - 21, - 95 - ], - [ - -9, - 58 - ], - [ - 5, - 35 - ], - [ - -8, - 69 - ], - [ - 9, - 90 - ], - [ - 13, - 25 - ], - [ - -11, - 40 - ], - [ - 17, - 63 - ], - [ - 13, - 66 - ], - [ - 2, - 34 - ], - [ - 26, - 45 - ], - [ - 20, - -58 - ], - [ - 5, - -76 - ], - [ - 17, - -14 - ], - [ - 3, - -51 - ], - [ - 25, - -61 - ], - [ - 5, - -67 - ], - [ - -2, - -44 - ] - ], - [ - [ - 13731, - 16571 - ], - [ - -5, - -50 - ], - [ - -39, - 0 - ], - [ - 13, - -26 - ], - [ - -23, - -77 - ] - ], - [ - [ - 13677, - 16418 - ], - [ - -13, - -20 - ], - [ - -61, - -3 - ], - [ - -35, - -27 - ], - [ - -58, - 9 - ] - ], - [ - [ - 13510, - 16377 - ], - [ - -100, - 31 - ], - [ - -15, - 42 - ], - [ - -69, - -21 - ], - [ - -8, - -23 - ], - [ - -43, - 17 - ] - ], - [ - [ - 13275, - 16423 - ], - [ - -35, - 3 - ], - [ - -32, - 22 - ], - [ - 11, - 29 - ], - [ - -3, - 22 - ] - ], - [ - [ - 13216, - 16499 - ], - [ - 21, - 6 - ], - [ - 36, - -33 - ], - [ - 10, - 32 - ], - [ - 61, - -5 - ], - [ - 50, - 21 - ], - [ - 33, - -4 - ], - [ - 22, - -24 - ], - [ - 7, - 20 - ], - [ - -10, - 78 - ], - [ - 25, - 16 - ], - [ - 24, - 55 - ] - ], - [ - [ - 13495, - 16661 - ], - [ - 52, - -39 - ], - [ - 39, - 49 - ], - [ - 25, - 9 - ], - [ - 54, - -36 - ], - [ - 33, - 6 - ], - [ - 32, - -23 - ] - ], - [ - [ - 13730, - 16627 - ], - [ - -6, - -15 - ], - [ - 7, - -41 - ] - ], - [ - [ - 15682, - 15746 - ], - [ - 18, - 19 - ], - [ - 51, - -34 - ], - [ - 38, - -7 - ], - [ - 10, - 14 - ], - [ - -35, - 65 - ], - [ - 18, - 16 - ] - ], - [ - [ - 15782, - 15819 - ], - [ - 20, - -4 - ], - [ - 48, - -73 - ], - [ - 31, - -8 - ], - [ - 12, - 31 - ], - [ - 41, - 48 - ] - ], - [ - [ - 15934, - 15813 - ], - [ - 37, - -63 - ], - [ - 35, - -85 - ], - [ - 33, - -6 - ], - [ - 21, - -32 - ], - [ - -57, - -10 - ], - [ - -12, - -93 - ], - [ - -12, - -42 - ], - [ - -26, - -28 - ], - [ - 2, - -60 - ] - ], - [ - [ - 15955, - 15394 - ], - [ - -17, - -6 - ], - [ - -44, - 63 - ], - [ - 24, - 60 - ], - [ - -20, - 35 - ], - [ - -26, - -9 - ], - [ - -83, - -89 - ] - ], - [ - [ - 15764, - 15445 - ], - [ - -48, - 16 - ], - [ - -35, - 55 - ], - [ - -11, - 46 - ] - ], - [ - [ - 14593, - 10257 - ], - [ - -5, - 145 - ], - [ - -17, - 55 - ] - ], - [ - [ - 14571, - 10457 - ], - [ - 42, - -10 - ], - [ - 21, - 68 - ], - [ - 37, - -7 - ] - ], - [ - [ - 14671, - 10508 - ], - [ - 5, - -48 - ], - [ - 15, - -27 - ], - [ - 0, - -39 - ], - [ - -17, - -25 - ], - [ - -27, - -62 - ], - [ - -25, - -44 - ], - [ - -29, - -6 - ] - ], - [ - [ - 12977, - 16892 - ], - [ - -8, - -81 - ] - ], - [ - [ - 12969, - 16811 - ], - [ - -18, - -5 - ], - [ - -8, - -67 - ] - ], - [ - [ - 12943, - 16739 - ], - [ - -61, - 55 - ], - [ - -36, - -9 - ], - [ - -48, - 56 - ], - [ - -33, - 48 - ], - [ - -32, - 2 - ], - [ - -10, - 42 - ] - ], - [ - [ - 12723, - 16933 - ], - [ - 56, - 24 - ] - ], - [ - [ - 12779, - 16957 - ], - [ - 51, - -9 - ], - [ - 64, - 25 - ], - [ - 44, - -53 - ], - [ - 39, - -28 - ] - ], - [ - [ - 12735, - 11548 - ], - [ - -57, - -14 - ] - ], - [ - [ - 12678, - 11534 - ], - [ - -18, - 83 - ], - [ - 4, - 275 - ], - [ - -15, - 25 - ], - [ - -2, - 59 - ], - [ - -24, - 42 - ], - [ - -22, - 35 - ], - [ - 9, - 64 - ] - ], - [ - [ - 12610, - 12117 - ], - [ - 24, - 13 - ], - [ - 14, - 53 - ], - [ - 34, - 11 - ], - [ - 16, - 36 - ] - ], - [ - [ - 12698, - 12230 - ], - [ - 23, - 35 - ], - [ - 25, - 0 - ], - [ - 53, - -69 - ] - ], - [ - [ - 12799, - 12196 - ], - [ - -2, - -40 - ], - [ - 15, - -71 - ], - [ - -14, - -48 - ], - [ - 8, - -33 - ], - [ - -34, - -74 - ], - [ - -21, - -37 - ], - [ - -14, - -75 - ], - [ - 2, - -77 - ], - [ - -4, - -193 - ] - ], - [ - [ - 12610, - 12117 - ], - [ - -61, - 2 - ] - ], - [ - [ - 12549, - 12119 - ], - [ - -32, - 10 - ], - [ - -23, - -20 - ], - [ - -30, - 9 - ], - [ - -121, - -6 - ], - [ - -2, - -68 - ], - [ - 9, - -90 - ] - ], - [ - [ - 12350, - 11954 - ], - [ - -47, - 31 - ], - [ - -33, - -5 - ], - [ - -24, - -30 - ], - [ - -32, - 26 - ], - [ - -12, - 39 - ], - [ - -31, - 26 - ] - ], - [ - [ - 12171, - 12041 - ], - [ - -5, - 70 - ], - [ - 19, - 51 - ], - [ - -1, - 40 - ], - [ - 55, - 100 - ], - [ - 10, - 82 - ], - [ - 19, - 29 - ], - [ - 34, - -16 - ], - [ - 29, - 25 - ], - [ - 10, - 31 - ], - [ - 54, - 53 - ], - [ - 13, - 38 - ], - [ - 65, - 50 - ], - [ - 39, - 17 - ], - [ - 17, - -23 - ], - [ - 45, - 0 - ] - ], - [ - [ - 12574, - 12588 - ], - [ - -6, - -58 - ], - [ - 9, - -55 - ], - [ - 40, - -78 - ], - [ - 2, - -58 - ], - [ - 80, - -27 - ], - [ - -1, - -82 - ] - ], - [ - [ - 19008, - 13441 - ], - [ - -2, - -86 - ], - [ - -24, - 19 - ], - [ - 4, - -97 - ] - ], - [ - [ - 18986, - 13277 - ], - [ - -20, - 63 - ], - [ - -4, - 61 - ], - [ - -13, - 57 - ], - [ - -29, - 70 - ], - [ - -64, - 5 - ], - [ - 6, - -49 - ], - [ - -22, - -67 - ], - [ - -29, - 24 - ], - [ - -11, - -22 - ], - [ - -19, - 13 - ], - [ - -27, - 11 - ] - ], - [ - [ - 18754, - 13443 - ], - [ - -11, - 99 - ], - [ - -24, - 90 - ], - [ - 12, - 72 - ], - [ - -43, - 33 - ], - [ - 15, - 43 - ], - [ - 44, - 45 - ], - [ - -51, - 64 - ], - [ - 25, - 81 - ], - [ - 55, - -52 - ], - [ - 34, - -6 - ], - [ - 6, - -83 - ], - [ - 66, - -17 - ], - [ - 65, - 2 - ], - [ - 40, - -20 - ], - [ - -32, - -102 - ], - [ - -31, - -7 - ], - [ - -22, - -68 - ], - [ - 38, - -62 - ], - [ - 12, - 76 - ], - [ - 19, - 1 - ], - [ - 37, - -191 - ] - ], - [ - [ - 14127, - 16104 - ], - [ - 20, - -49 - ], - [ - 27, - 8 - ], - [ - 54, - -18 - ], - [ - 102, - -7 - ], - [ - 34, - 31 - ], - [ - 83, - 28 - ], - [ - 50, - -44 - ], - [ - 41, - -12 - ] - ], - [ - [ - 14538, - 16041 - ], - [ - -36, - -50 - ], - [ - -25, - -86 - ], - [ - 22, - -68 - ] - ], - [ - [ - 14499, - 15837 - ], - [ - -60, - 16 - ], - [ - -71, - -38 - ] - ], - [ - [ - 14368, - 15815 - ], - [ - -1, - -60 - ], - [ - -63, - -11 - ], - [ - -49, - 42 - ], - [ - -56, - -33 - ], - [ - -52, - 3 - ] - ], - [ - [ - 14147, - 15756 - ], - [ - -4, - 80 - ], - [ - -35, - 38 - ] - ], - [ - [ - 14108, - 15874 - ], - [ - 11, - 17 - ], - [ - -7, - 15 - ], - [ - 11, - 38 - ], - [ - 27, - 37 - ], - [ - -34, - 52 - ], - [ - -6, - 44 - ], - [ - 17, - 27 - ] - ], - [ - [ - 7143, - 13648 - ], - [ - -17, - -6 - ], - [ - -18, - 69 - ], - [ - -26, - 35 - ], - [ - 15, - 76 - ], - [ - 21, - -5 - ], - [ - 24, - -100 - ], - [ - 1, - -69 - ] - ], - [ - [ - 7123, - 13986 - ], - [ - -76, - -19 - ], - [ - -5, - 44 - ], - [ - 33, - 10 - ], - [ - 46, - -4 - ], - [ - 2, - -31 - ] - ], - [ - [ - 7180, - 13987 - ], - [ - -12, - -85 - ], - [ - -13, - 15 - ], - [ - 1, - 63 - ], - [ - -31, - 47 - ], - [ - 0, - 14 - ], - [ - 55, - -54 - ] - ], - [ - [ - 13887, - 16019 - ], - [ - -13, - -11 - ], - [ - -23, - -28 - ], - [ - -10, - -66 - ] - ], - [ - [ - 13841, - 15914 - ], - [ - -61, - 45 - ], - [ - -27, - 50 - ], - [ - -26, - 27 - ], - [ - -32, - 45 - ], - [ - -15, - 37 - ], - [ - -35, - 56 - ], - [ - 15, - 50 - ], - [ - 25, - -28 - ], - [ - 15, - 25 - ], - [ - 33, - 3 - ], - [ - 60, - -20 - ], - [ - 48, - 2 - ], - [ - 31, - -27 - ] - ], - [ - [ - 13872, - 16179 - ], - [ - 26, - 0 - ], - [ - -18, - -52 - ], - [ - 34, - -47 - ], - [ - -10, - -56 - ], - [ - -17, - -5 - ] - ], - [ - [ - 14185, - 17265 - ], - [ - 67, - -1 - ], - [ - 76, - 45 - ], - [ - 16, - 68 - ], - [ - 57, - 39 - ], - [ - -7, - 53 - ] - ], - [ - [ - 14394, - 17469 - ], - [ - 43, - 20 - ], - [ - 75, - 47 - ] - ], - [ - [ - 14512, - 17536 - ], - [ - 73, - -30 - ], - [ - 10, - -30 - ], - [ - 37, - 14 - ], - [ - 68, - -28 - ], - [ - 6, - -57 - ], - [ - -14, - -32 - ], - [ - 43, - -79 - ], - [ - 29, - -22 - ], - [ - -5, - -21 - ], - [ - 47, - -21 - ], - [ - 21, - -32 - ], - [ - -28, - -27 - ], - [ - -56, - 5 - ], - [ - -13, - -12 - ], - [ - 16, - -39 - ], - [ - 17, - -77 - ] - ], - [ - [ - 14763, - 17048 - ], - [ - -60, - -7 - ], - [ - -21, - -27 - ], - [ - -5, - -60 - ], - [ - -27, - 12 - ], - [ - -63, - -6 - ], - [ - -18, - 28 - ], - [ - -27, - -21 - ], - [ - -26, - 17 - ], - [ - -55, - 3 - ], - [ - -78, - 28 - ], - [ - -70, - 10 - ], - [ - -54, - -3 - ], - [ - -38, - -32 - ], - [ - -33, - -5 - ] - ], - [ - [ - 14188, - 16985 - ], - [ - -2, - 53 - ], - [ - -21, - 56 - ], - [ - 42, - 24 - ], - [ - 0, - 48 - ], - [ - -19, - 46 - ], - [ - -3, - 53 - ] - ], - [ - [ - 6333, - 12934 - ], - [ - 0, - 17 - ], - [ - 8, - 6 - ], - [ - 13, - -14 - ], - [ - 25, - 72 - ], - [ - 13, - 2 - ] - ], - [ - [ - 6392, - 13017 - ], - [ - 1, - -18 - ], - [ - 13, - -1 - ], - [ - -1, - -32 - ], - [ - -12, - -52 - ], - [ - 6, - -19 - ], - [ - -7, - -43 - ], - [ - 4, - -11 - ], - [ - -8, - -61 - ], - [ - -13, - -31 - ], - [ - -13, - -4 - ], - [ - -14, - -42 - ] - ], - [ - [ - 6348, - 12703 - ], - [ - -21, - 0 - ], - [ - 6, - 136 - ], - [ - 0, - 95 - ] - ], - [ - [ - 7870, - 8070 - ], - [ - -51, - -17 - ], - [ - -27, - 166 - ], - [ - -37, - 134 - ], - [ - 22, - 116 - ], - [ - -37, - 51 - ], - [ - -9, - 87 - ], - [ - -35, - 81 - ] - ], - [ - [ - 7696, - 8688 - ], - [ - 44, - 130 - ], - [ - -30, - 100 - ], - [ - 16, - 41 - ], - [ - -12, - 44 - ], - [ - 27, - 60 - ], - [ - 2, - 102 - ], - [ - 3, - 85 - ], - [ - 15, - 40 - ], - [ - -60, - 193 - ] - ], - [ - [ - 7701, - 9483 - ], - [ - 52, - -10 - ], - [ - 35, - 3 - ], - [ - 16, - 36 - ], - [ - 61, - 49 - ], - [ - 37, - 45 - ], - [ - 91, - 20 - ], - [ - -8, - -90 - ], - [ - 9, - -46 - ], - [ - -6, - -80 - ], - [ - 76, - -108 - ], - [ - 78, - -20 - ], - [ - 28, - -44 - ], - [ - 47, - -24 - ], - [ - 29, - -35 - ], - [ - 43, - 1 - ], - [ - 41, - -35 - ], - [ - 3, - -70 - ], - [ - 14, - -35 - ], - [ - 0, - -52 - ], - [ - -20, - -2 - ], - [ - 27, - -139 - ], - [ - 134, - -5 - ], - [ - -11, - -70 - ], - [ - 8, - -47 - ], - [ - 38, - -34 - ], - [ - 16, - -74 - ], - [ - -12, - -95 - ], - [ - -19, - -52 - ], - [ - 7, - -69 - ], - [ - -22, - -24 - ] - ], - [ - [ - 8493, - 8377 - ], - [ - -1, - 37 - ], - [ - -65, - 61 - ], - [ - -65, - 2 - ], - [ - -122, - -35 - ], - [ - -33, - -106 - ], - [ - -2, - -64 - ], - [ - -27, - -144 - ] - ], - [ - [ - 8740, - 7709 - ], - [ - 13, - 70 - ], - [ - 10, - 70 - ], - [ - 0, - 66 - ], - [ - -25, - 22 - ], - [ - -26, - -19 - ], - [ - -26, - 5 - ], - [ - -9, - 46 - ], - [ - -6, - 110 - ], - [ - -13, - 36 - ], - [ - -47, - 33 - ], - [ - -29, - -24 - ], - [ - -73, - 23 - ], - [ - 4, - 163 - ], - [ - -20, - 67 - ] - ], - [ - [ - 7701, - 9483 - ], - [ - -40, - -20 - ], - [ - -31, - 13 - ], - [ - 4, - 183 - ], - [ - -57, - -71 - ], - [ - -61, - 3 - ], - [ - -27, - 64 - ], - [ - -46, - 7 - ], - [ - 15, - 52 - ], - [ - -39, - 73 - ], - [ - -29, - 108 - ], - [ - 18, - 22 - ], - [ - 0, - 50 - ], - [ - 42, - 35 - ], - [ - -7, - 65 - ], - [ - 18, - 41 - ], - [ - 5, - 56 - ], - [ - 80, - 82 - ], - [ - 57, - 23 - ], - [ - 10, - 18 - ], - [ - 62, - -5 - ] - ], - [ - [ - 7675, - 10282 - ], - [ - 32, - 328 - ], - [ - 1, - 53 - ], - [ - -11, - 68 - ], - [ - -31, - 44 - ], - [ - 1, - 87 - ], - [ - 39, - 20 - ], - [ - 14, - -13 - ], - [ - 2, - 46 - ], - [ - -40, - 13 - ], - [ - -1, - 75 - ], - [ - 135, - -3 - ], - [ - 24, - 42 - ], - [ - 19, - -38 - ], - [ - 14, - -71 - ], - [ - 13, - 15 - ] - ], - [ - [ - 7886, - 10948 - ], - [ - 38, - -64 - ], - [ - 54, - 8 - ], - [ - 14, - 37 - ], - [ - 52, - 28 - ], - [ - 28, - 19 - ], - [ - 8, - 51 - ], - [ - 50, - 34 - ], - [ - -4, - 25 - ], - [ - -59, - 11 - ], - [ - -9, - 75 - ], - [ - 2, - 81 - ], - [ - -31, - 31 - ], - [ - 13, - 11 - ], - [ - 52, - -15 - ], - [ - 55, - -30 - ], - [ - 21, - 28 - ], - [ - 50, - 19 - ], - [ - 78, - 44 - ], - [ - 25, - 46 - ], - [ - -9, - 34 - ] - ], - [ - [ - 8314, - 11421 - ], - [ - 36, - 5 - ], - [ - 16, - -27 - ], - [ - -9, - -53 - ], - [ - 24, - -18 - ], - [ - 16, - -56 - ], - [ - -19, - -42 - ], - [ - -11, - -102 - ], - [ - 18, - -61 - ], - [ - 5, - -55 - ], - [ - 43, - -57 - ], - [ - 34, - -6 - ], - [ - 7, - 24 - ], - [ - 23, - 5 - ], - [ - 31, - 21 - ], - [ - 23, - 32 - ], - [ - 38, - -10 - ], - [ - 17, - 4 - ] - ], - [ - [ - 8606, - 11025 - ], - [ - 38, - -10 - ], - [ - 6, - 25 - ], - [ - -11, - 24 - ], - [ - 7, - 34 - ], - [ - 28, - -10 - ], - [ - 33, - 12 - ], - [ - 40, - -25 - ] - ], - [ - [ - 8747, - 11075 - ], - [ - 30, - -25 - ], - [ - 22, - 32 - ], - [ - 15, - -5 - ], - [ - 10, - -33 - ], - [ - 33, - 8 - ], - [ - 27, - 46 - ], - [ - 21, - 88 - ], - [ - 42, - 110 - ] - ], - [ - [ - 8947, - 11296 - ], - [ - 23, - 5 - ], - [ - 18, - -66 - ], - [ - 39, - -210 - ], - [ - 37, - -19 - ], - [ - 2, - -83 - ], - [ - -53, - -99 - ], - [ - 22, - -36 - ], - [ - 123, - -19 - ], - [ - 3, - -120 - ], - [ - 53, - 78 - ], - [ - 87, - -43 - ], - [ - 116, - -73 - ], - [ - 34, - -70 - ], - [ - -11, - -67 - ], - [ - 81, - 37 - ], - [ - 136, - -63 - ], - [ - 104, - 5 - ], - [ - 103, - -100 - ], - [ - 89, - -134 - ], - [ - 53, - -35 - ], - [ - 60, - -5 - ], - [ - 25, - -37 - ], - [ - 24, - -153 - ], - [ - 12, - -73 - ], - [ - -28, - -198 - ], - [ - -36, - -78 - ], - [ - -98, - -167 - ], - [ - -44, - -136 - ], - [ - -52, - -104 - ], - [ - -17, - -2 - ], - [ - -20, - -89 - ], - [ - 5, - -224 - ], - [ - -19, - -185 - ], - [ - -8, - -79 - ], - [ - -22, - -48 - ], - [ - -12, - -160 - ], - [ - -71, - -157 - ], - [ - -12, - -124 - ], - [ - -56, - -52 - ], - [ - -16, - -71 - ], - [ - -76, - 0 - ], - [ - -110, - -46 - ], - [ - -49, - -54 - ], - [ - -78, - -35 - ], - [ - -82, - -95 - ], - [ - -59, - -119 - ], - [ - -10, - -90 - ], - [ - 11, - -66 - ], - [ - -13, - -121 - ], - [ - -15, - -59 - ], - [ - -49, - -66 - ], - [ - -77, - -211 - ], - [ - -62, - -95 - ], - [ - -47, - -56 - ], - [ - -32, - -114 - ], - [ - -46, - -69 - ] - ], - [ - [ - 8827, - 6746 - ], - [ - -19, - 68 - ], - [ - 30, - 57 - ], - [ - -40, - 82 - ], - [ - -55, - 66 - ], - [ - -71, - 77 - ], - [ - -26, - -4 - ], - [ - -70, - 93 - ], - [ - -45, - -13 - ] - ], - [ - [ - 20508, - 11340 - ], - [ - 28, - 45 - ], - [ - 59, - 66 - ] - ], - [ - [ - 20595, - 11451 - ], - [ - -3, - -59 - ], - [ - -4, - -77 - ], - [ - -33, - 4 - ], - [ - -15, - -41 - ], - [ - -32, - 62 - ] - ], - [ - [ - 18940, - 14129 - ], - [ - 28, - -38 - ], - [ - -5, - -74 - ], - [ - -57, - -4 - ], - [ - -59, - 8 - ], - [ - -44, - -18 - ], - [ - -63, - 45 - ], - [ - -1, - 24 - ] - ], - [ - [ - 18739, - 14072 - ], - [ - 46, - 89 - ], - [ - 37, - 31 - ], - [ - 50, - -28 - ], - [ - 37, - -3 - ], - [ - 31, - -32 - ] - ], - [ - [ - 14599, - 8147 - ], - [ - -98, - -88 - ], - [ - -63, - -90 - ], - [ - -23, - -80 - ], - [ - -21, - -45 - ], - [ - -38, - -10 - ], - [ - -12, - -57 - ], - [ - -7, - -37 - ], - [ - -45, - -28 - ], - [ - -57, - 6 - ], - [ - -33, - 33 - ], - [ - -29, - 15 - ], - [ - -34, - -28 - ], - [ - -18, - -58 - ], - [ - -33, - -36 - ], - [ - -34, - -53 - ], - [ - -50, - -12 - ], - [ - -16, - 42 - ], - [ - 7, - 73 - ], - [ - -42, - 114 - ], - [ - -19, - 18 - ] - ], - [ - [ - 13934, - 7826 - ], - [ - 0, - 350 - ], - [ - 69, - 4 - ], - [ - 2, - 427 - ], - [ - 52, - 4 - ], - [ - 108, - 42 - ], - [ - 26, - -49 - ], - [ - 45, - 47 - ], - [ - 21, - 0 - ], - [ - 39, - 27 - ] - ], - [ - [ - 14296, - 8678 - ], - [ - 13, - -9 - ] - ], - [ - [ - 14309, - 8669 - ], - [ - 26, - -96 - ], - [ - 14, - -21 - ], - [ - 22, - -69 - ], - [ - 79, - -132 - ], - [ - 30, - -13 - ], - [ - 0, - -42 - ], - [ - 21, - -76 - ], - [ - 54, - -19 - ], - [ - 44, - -54 - ] - ], - [ - [ - 13613, - 11688 - ], - [ - 57, - 9 - ], - [ - 13, - 30 - ], - [ - 12, - -2 - ], - [ - 17, - -27 - ], - [ - 88, - 46 - ], - [ - 29, - 47 - ], - [ - 37, - 42 - ], - [ - -7, - 42 - ], - [ - 20, - 11 - ], - [ - 67, - -8 - ], - [ - 65, - 56 - ], - [ - 51, - 131 - ], - [ - 35, - 48 - ], - [ - 44, - 21 - ] - ], - [ - [ - 14141, - 12134 - ], - [ - 8, - -51 - ], - [ - 40, - -75 - ], - [ - 1, - -49 - ], - [ - -12, - -50 - ], - [ - 5, - -38 - ], - [ - 24, - -34 - ], - [ - 53, - -53 - ] - ], - [ - [ - 14260, - 11784 - ], - [ - 38, - -48 - ], - [ - 1, - -39 - ], - [ - 47, - -63 - ], - [ - 29, - -51 - ], - [ - 17, - -72 - ], - [ - 53, - -48 - ], - [ - 11, - -38 - ] - ], - [ - [ - 14456, - 11425 - ], - [ - -23, - -13 - ], - [ - -45, - 3 - ], - [ - -52, - 13 - ], - [ - -26, - -11 - ], - [ - -11, - -29 - ], - [ - -22, - -3 - ], - [ - -28, - 25 - ], - [ - -77, - -60 - ], - [ - -32, - 12 - ], - [ - -10, - -9 - ], - [ - -21, - -72 - ], - [ - -52, - 23 - ], - [ - -51, - 12 - ], - [ - -44, - 44 - ], - [ - -57, - 41 - ], - [ - -38, - -39 - ], - [ - -27, - -61 - ], - [ - -6, - -83 - ] - ], - [ - [ - 13834, - 11218 - ], - [ - -45, - 6 - ], - [ - -47, - 20 - ], - [ - -42, - -63 - ], - [ - -36, - -112 - ] - ], - [ - [ - 13664, - 11069 - ], - [ - -8, - 35 - ], - [ - -3, - 55 - ], - [ - -32, - 38 - ], - [ - -25, - 62 - ], - [ - -6, - 43 - ], - [ - -33, - 63 - ], - [ - 5, - 36 - ], - [ - -7, - 50 - ], - [ - 6, - 93 - ], - [ - 17, - 22 - ], - [ - 35, - 122 - ] - ], - [ - [ - 8110, - 16382 - ], - [ - 50, - -16 - ], - [ - 65, - 3 - ], - [ - -35, - -49 - ], - [ - -25, - -8 - ], - [ - -89, - 51 - ], - [ - -17, - 40 - ], - [ - 26, - 37 - ], - [ - 25, - -58 - ] - ], - [ - [ - 8239, - 16688 - ], - [ - -34, - -2 - ], - [ - -90, - 38 - ], - [ - -65, - 56 - ], - [ - 24, - 10 - ], - [ - 92, - -30 - ], - [ - 71, - -50 - ], - [ - 2, - -22 - ] - ], - [ - [ - 3938, - 16617 - ], - [ - -35, - -17 - ], - [ - -115, - 55 - ], - [ - -21, - 42 - ], - [ - -62, - 42 - ], - [ - -13, - 34 - ], - [ - -71, - 22 - ], - [ - -27, - 65 - ], - [ - 6, - 28 - ], - [ - 73, - -26 - ], - [ - 43, - -18 - ], - [ - 65, - -13 - ], - [ - 24, - -41 - ], - [ - 34, - -57 - ], - [ - 70, - -50 - ], - [ - 29, - -66 - ] - ], - [ - [ - 8634, - 16878 - ], - [ - -46, - -105 - ], - [ - 46, - 41 - ], - [ - 47, - -26 - ], - [ - -25, - -42 - ], - [ - 62, - -33 - ], - [ - 32, - 29 - ], - [ - 70, - -36 - ], - [ - -22, - -88 - ], - [ - 49, - 20 - ], - [ - 9, - -63 - ], - [ - 21, - -75 - ], - [ - -29, - -106 - ], - [ - -31, - -4 - ], - [ - -46, - 23 - ], - [ - 15, - 98 - ], - [ - -20, - 15 - ], - [ - -80, - -104 - ], - [ - -42, - 4 - ], - [ - 49, - 56 - ], - [ - -67, - 30 - ], - [ - -75, - -8 - ], - [ - -135, - 4 - ], - [ - -11, - 36 - ], - [ - 44, - 42 - ], - [ - -30, - 32 - ], - [ - 58, - 73 - ], - [ - 72, - 191 - ], - [ - 43, - 68 - ], - [ - 61, - 41 - ], - [ - 32, - -5 - ], - [ - -13, - -32 - ], - [ - -38, - -76 - ] - ], - [ - [ - 3264, - 17296 - ], - [ - 33, - -16 - ], - [ - 66, - 10 - ], - [ - -20, - -136 - ], - [ - 60, - -97 - ], - [ - -28, - 0 - ], - [ - -42, - 55 - ], - [ - -25, - 56 - ], - [ - -36, - 37 - ], - [ - -12, - 53 - ], - [ - 4, - 38 - ] - ], - [ - [ - 7022, - 18254 - ], - [ - -27, - -63 - ], - [ - -31, - 10 - ], - [ - -18, - 36 - ], - [ - 3, - 9 - ], - [ - 27, - 36 - ], - [ - 28, - -3 - ], - [ - 18, - -25 - ] - ], - [ - [ - 6839, - 18321 - ], - [ - -82, - -67 - ], - [ - -49, - 3 - ], - [ - -16, - 33 - ], - [ - 52, - 55 - ], - [ - 96, - -1 - ], - [ - -1, - -23 - ] - ], - [ - [ - 6611, - 18674 - ], - [ - 13, - -53 - ], - [ - 36, - 19 - ], - [ - 40, - -32 - ], - [ - 77, - -41 - ], - [ - 79, - -37 - ], - [ - 7, - -57 - ], - [ - 51, - 9 - ], - [ - 50, - -40 - ], - [ - -62, - -37 - ], - [ - -109, - 28 - ], - [ - -39, - 54 - ], - [ - -69, - -63 - ], - [ - -99, - -62 - ], - [ - -24, - 70 - ], - [ - -95, - -12 - ], - [ - 61, - 59 - ], - [ - 9, - 95 - ], - [ - 24, - 110 - ], - [ - 50, - -10 - ] - ], - [ - [ - 7259, - 18853 - ], - [ - -78, - -6 - ], - [ - -18, - 59 - ], - [ - 30, - 67 - ], - [ - 64, - 17 - ], - [ - 54, - -34 - ], - [ - 1, - -51 - ], - [ - -8, - -17 - ], - [ - -45, - -35 - ] - ], - [ - [ - 5880, - 19088 - ], - [ - -43, - -42 - ], - [ - -94, - 36 - ], - [ - -57, - -13 - ], - [ - -95, - 54 - ], - [ - 61, - 37 - ], - [ - 49, - 52 - ], - [ - 74, - -34 - ], - [ - 42, - -21 - ], - [ - 21, - -23 - ], - [ - 42, - -46 - ] - ], - [ - [ - 3985, - 16676 - ], - [ - -10, - 0 - ], - [ - -135, - 118 - ], - [ - -50, - 52 - ], - [ - -126, - 49 - ], - [ - -39, - 106 - ], - [ - 10, - 74 - ], - [ - -89, - 51 - ], - [ - -12, - 97 - ], - [ - -84, - 87 - ], - [ - -2, - 62 - ] - ], - [ - [ - 3448, - 17372 - ], - [ - 39, - 58 - ], - [ - -2, - 75 - ], - [ - -119, - 77 - ], - [ - -71, - 137 - ], - [ - -43, - 86 - ], - [ - -64, - 54 - ], - [ - -47, - 49 - ], - [ - -37, - 62 - ], - [ - -70, - -39 - ], - [ - -68, - -67 - ], - [ - -62, - 79 - ], - [ - -49, - 52 - ], - [ - -68, - 34 - ], - [ - -68, - 3 - ], - [ - 0, - 683 - ], - [ - 1, - 445 - ] - ], - [ - [ - 2720, - 19160 - ], - [ - 130, - -28 - ], - [ - 109, - -58 - ], - [ - 73, - -11 - ], - [ - 61, - 50 - ], - [ - 85, - 37 - ], - [ - 103, - -14 - ], - [ - 105, - 52 - ], - [ - 114, - 30 - ], - [ - 48, - -49 - ], - [ - 52, - 28 - ], - [ - 15, - 56 - ], - [ - 48, - -13 - ], - [ - 118, - -107 - ], - [ - 93, - 81 - ], - [ - 9, - -91 - ], - [ - 86, - 20 - ], - [ - 26, - 35 - ], - [ - 85, - -7 - ], - [ - 106, - -51 - ], - [ - 164, - -44 - ], - [ - 96, - -20 - ], - [ - 68, - 8 - ], - [ - 94, - -61 - ], - [ - -98, - -60 - ], - [ - 126, - -25 - ], - [ - 188, - 14 - ], - [ - 59, - 21 - ], - [ - 75, - -72 - ], - [ - 75, - 61 - ], - [ - -71, - 50 - ], - [ - 45, - 42 - ], - [ - 85, - 5 - ], - [ - 56, - 12 - ], - [ - 56, - -29 - ], - [ - 70, - -65 - ], - [ - 78, - 10 - ], - [ - 123, - -54 - ], - [ - 109, - 19 - ], - [ - 101, - -3 - ], - [ - -8, - 75 - ], - [ - 62, - 20 - ], - [ - 108, - -40 - ], - [ - 0, - -114 - ], - [ - 44, - 96 - ], - [ - 56, - -3 - ], - [ - 32, - 120 - ], - [ - -75, - 74 - ], - [ - -81, - 49 - ], - [ - 5, - 132 - ], - [ - 83, - 87 - ], - [ - 92, - -19 - ], - [ - 70, - -53 - ], - [ - 95, - -135 - ], - [ - -62, - -59 - ], - [ - 130, - -24 - ], - [ - -1, - -123 - ], - [ - 93, - 94 - ], - [ - 84, - -77 - ], - [ - -21, - -89 - ], - [ - 67, - -81 - ], - [ - 73, - 87 - ], - [ - 51, - 103 - ], - [ - 4, - 132 - ], - [ - 99, - -9 - ], - [ - 103, - -18 - ], - [ - 94, - -60 - ], - [ - 4, - -59 - ], - [ - -52, - -64 - ], - [ - 49, - -64 - ], - [ - -9, - -59 - ], - [ - -136, - -83 - ], - [ - -97, - -19 - ], - [ - -72, - 36 - ], - [ - -21, - -60 - ], - [ - -67, - -101 - ], - [ - -21, - -53 - ], - [ - -80, - -81 - ], - [ - -100, - -8 - ], - [ - -55, - -51 - ], - [ - -5, - -78 - ], - [ - -81, - -15 - ], - [ - -85, - -97 - ], - [ - -76, - -135 - ], - [ - -27, - -94 - ], - [ - -4, - -140 - ], - [ - 103, - -20 - ], - [ - 31, - -112 - ], - [ - 33, - -91 - ], - [ - 97, - 24 - ], - [ - 130, - -52 - ], - [ - 69, - -46 - ], - [ - 50, - -57 - ], - [ - 88, - -33 - ], - [ - 73, - -50 - ], - [ - 116, - -7 - ], - [ - 75, - -12 - ], - [ - -11, - -104 - ], - [ - 22, - -120 - ], - [ - 50, - -134 - ], - [ - 104, - -114 - ], - [ - 54, - 39 - ], - [ - 37, - 123 - ], - [ - -36, - 189 - ], - [ - -49, - 64 - ], - [ - 111, - 56 - ], - [ - 79, - 84 - ], - [ - 39, - 84 - ], - [ - -6, - 80 - ], - [ - -47, - 102 - ], - [ - -85, - 90 - ], - [ - 82, - 126 - ], - [ - -30, - 108 - ], - [ - -23, - 188 - ], - [ - 48, - 27 - ], - [ - 120, - -32 - ], - [ - 72, - -12 - ], - [ - 57, - 32 - ], - [ - 65, - -41 - ], - [ - 86, - -70 - ], - [ - 21, - -46 - ], - [ - 124, - -9 - ], - [ - -2, - -101 - ], - [ - 24, - -152 - ], - [ - 63, - -19 - ], - [ - 51, - -70 - ], - [ - 101, - 66 - ], - [ - 66, - 133 - ], - [ - 46, - 56 - ], - [ - 55, - -108 - ], - [ - 91, - -153 - ], - [ - 77, - -143 - ], - [ - -28, - -76 - ], - [ - 92, - -67 - ], - [ - 63, - -69 - ], - [ - 111, - -31 - ], - [ - 45, - -38 - ], - [ - 28, - -102 - ], - [ - 54, - -16 - ], - [ - 28, - -45 - ], - [ - 5, - -135 - ], - [ - -51, - -45 - ], - [ - -50, - -42 - ], - [ - -115, - -43 - ], - [ - -87, - -98 - ], - [ - -118, - -20 - ], - [ - -149, - 26 - ], - [ - -105, - 0 - ], - [ - -72, - -8 - ], - [ - -58, - -86 - ], - [ - -89, - -53 - ], - [ - -101, - -159 - ], - [ - -80, - -111 - ], - [ - 59, - 20 - ], - [ - 112, - 158 - ], - [ - 146, - 100 - ], - [ - 105, - 12 - ], - [ - 61, - -59 - ], - [ - -66, - -81 - ], - [ - 23, - -129 - ], - [ - 22, - -91 - ], - [ - 91, - -60 - ], - [ - 115, - 18 - ], - [ - 70, - 135 - ], - [ - 5, - -87 - ], - [ - 45, - -44 - ], - [ - -86, - -78 - ], - [ - -155, - -72 - ], - [ - -69, - -48 - ], - [ - -78, - -87 - ], - [ - -53, - 9 - ], - [ - -3, - 102 - ], - [ - 122, - 99 - ], - [ - -112, - -4 - ], - [ - -78, - -15 - ] - ], - [ - [ - 7867, - 16212 - ], - [ - -45, - 68 - ], - [ - 0, - 164 - ], - [ - -31, - 34 - ], - [ - -47, - -20 - ], - [ - -23, - 31 - ], - [ - -53, - -90 - ], - [ - -21, - -93 - ], - [ - -25, - -55 - ], - [ - -30, - -19 - ], - [ - -22, - -6 - ], - [ - -7, - -29 - ], - [ - -128, - 0 - ], - [ - -106, - -1 - ], - [ - -32, - -22 - ], - [ - -73, - -87 - ], - [ - -9, - -9 - ], - [ - -22, - -47 - ], - [ - -64, - 0 - ], - [ - -69, - 0 - ], - [ - -31, - -19 - ], - [ - 11, - -24 - ], - [ - 6, - -36 - ], - [ - -1, - -13 - ], - [ - -91, - -59 - ], - [ - -72, - -19 - ], - [ - -81, - -64 - ], - [ - -18, - 0 - ], - [ - -23, - 19 - ], - [ - -8, - 17 - ], - [ - 1, - 12 - ], - [ - 16, - 42 - ], - [ - 32, - 66 - ], - [ - 21, - 71 - ], - [ - -14, - 105 - ], - [ - -15, - 108 - ], - [ - -73, - 57 - ], - [ - 9, - 21 - ], - [ - -10, - 15 - ], - [ - -19, - 0 - ], - [ - -14, - 19 - ], - [ - -4, - 28 - ], - [ - -13, - -12 - ], - [ - -19, - 3 - ], - [ - 4, - 12 - ], - [ - -16, - 12 - ], - [ - -7, - 32 - ], - [ - -54, - 38 - ], - [ - -57, - 40 - ], - [ - -68, - 46 - ], - [ - -65, - 44 - ], - [ - -63, - -34 - ], - [ - -22, - -1 - ], - [ - -86, - 31 - ], - [ - -57, - -16 - ], - [ - -67, - 38 - ], - [ - -71, - 19 - ], - [ - -49, - 7 - ], - [ - -22, - 20 - ], - [ - -12, - 66 - ], - [ - -24, - 0 - ], - [ - 0, - -46 - ], - [ - -144, - 0 - ], - [ - -239, - 0 - ], - [ - -237, - 0 - ], - [ - -209, - 0 - ], - [ - -209, - 0 - ], - [ - -206, - 0 - ], - [ - -212, - 0 - ], - [ - -69, - 0 - ], - [ - -207, - 0 - ], - [ - -197, - 0 - ] - ], - [ - [ - 4589, - 19569 - ], - [ - -35, - -56 - ], - [ - 155, - 37 - ], - [ - 97, - -61 - ], - [ - 79, - 61 - ], - [ - 64, - -39 - ], - [ - 57, - -118 - ], - [ - 35, - 50 - ], - [ - -50, - 123 - ], - [ - 62, - 17 - ], - [ - 69, - -19 - ], - [ - 78, - -48 - ], - [ - 44, - -117 - ], - [ - 21, - -85 - ], - [ - 118, - -59 - ], - [ - 125, - -57 - ], - [ - -7, - -53 - ], - [ - -115, - -9 - ], - [ - 45, - -47 - ], - [ - -24, - -44 - ], - [ - -126, - 19 - ], - [ - -120, - 33 - ], - [ - -81, - -8 - ], - [ - -131, - -40 - ], - [ - -176, - -18 - ], - [ - -124, - -12 - ], - [ - -38, - 57 - ], - [ - -95, - 33 - ], - [ - -62, - -14 - ], - [ - -86, - 95 - ], - [ - 46, - 13 - ], - [ - 108, - 20 - ], - [ - 98, - -5 - ], - [ - 91, - 21 - ], - [ - -135, - 28 - ], - [ - -149, - -10 - ], - [ - -98, - 3 - ], - [ - -37, - 44 - ], - [ - 161, - 48 - ], - [ - -107, - -2 - ], - [ - -122, - 32 - ], - [ - 59, - 90 - ], - [ - 48, - 48 - ], - [ - 187, - 73 - ], - [ - 71, - -24 - ] - ], - [ - [ - 5263, - 19605 - ], - [ - -61, - -79 - ], - [ - -109, - 84 - ], - [ - 24, - 17 - ], - [ - 93, - 5 - ], - [ - 53, - -27 - ] - ], - [ - [ - 7226, - 19567 - ], - [ - 6, - -33 - ], - [ - -74, - 4 - ], - [ - -75, - 2 - ], - [ - -76, - -16 - ], - [ - -21, - 7 - ], - [ - -76, - 64 - ], - [ - 3, - 43 - ], - [ - 33, - 8 - ], - [ - 160, - -13 - ], - [ - 120, - -66 - ] - ], - [ - [ - 6513, - 19574 - ], - [ - 55, - -75 - ], - [ - 65, - 97 - ], - [ - 176, - 49 - ], - [ - 120, - -124 - ], - [ - -10, - -79 - ], - [ - 138, - 35 - ], - [ - 65, - 48 - ], - [ - 155, - -61 - ], - [ - 96, - -57 - ], - [ - 9, - -52 - ], - [ - 130, - 27 - ], - [ - 72, - -77 - ], - [ - 169, - -47 - ], - [ - 60, - -48 - ], - [ - 66, - -113 - ], - [ - -128, - -56 - ], - [ - 164, - -78 - ], - [ - 111, - -26 - ], - [ - 100, - -110 - ], - [ - 110, - -8 - ], - [ - -22, - -85 - ], - [ - -122, - -139 - ], - [ - -86, - 51 - ], - [ - -110, - 116 - ], - [ - -90, - -15 - ], - [ - -9, - -69 - ], - [ - 74, - -70 - ], - [ - 94, - -55 - ], - [ - 29, - -32 - ], - [ - 46, - -119 - ], - [ - -25, - -86 - ], - [ - -87, - 33 - ], - [ - -175, - 96 - ], - [ - 98, - -104 - ], - [ - 73, - -72 - ], - [ - 11, - -42 - ], - [ - -189, - 48 - ], - [ - -149, - 70 - ], - [ - -85, - 58 - ], - [ - 24, - 34 - ], - [ - -104, - 61 - ], - [ - -101, - 59 - ], - [ - 1, - -35 - ], - [ - -202, - -19 - ], - [ - -59, - 41 - ], - [ - 46, - 88 - ], - [ - 131, - 2 - ], - [ - 144, - 16 - ], - [ - -23, - 43 - ], - [ - 24, - 59 - ], - [ - 90, - 117 - ], - [ - -19, - 53 - ], - [ - -27, - 41 - ], - [ - -107, - 59 - ], - [ - -141, - 40 - ], - [ - 45, - 31 - ], - [ - -74, - 74 - ], - [ - -62, - 7 - ], - [ - -54, - 41 - ], - [ - -38, - -35 - ], - [ - -126, - -16 - ], - [ - -254, - 27 - ], - [ - -147, - 35 - ], - [ - -113, - 18 - ], - [ - -58, - 42 - ], - [ - 73, - 55 - ], - [ - -99, - 1 - ], - [ - -23, - 121 - ], - [ - 54, - 107 - ], - [ - 72, - 49 - ], - [ - 180, - 32 - ], - [ - -52, - -77 - ] - ], - [ - [ - 5552, - 19656 - ], - [ - 83, - -25 - ], - [ - 124, - 15 - ], - [ - 18, - -35 - ], - [ - -65, - -57 - ], - [ - 106, - -52 - ], - [ - -13, - -108 - ], - [ - -114, - -46 - ], - [ - -67, - 10 - ], - [ - -48, - 46 - ], - [ - -174, - 92 - ], - [ - 2, - 39 - ], - [ - 142, - -15 - ], - [ - -77, - 78 - ], - [ - 83, - 58 - ] - ], - [ - [ - 6051, - 19528 - ], - [ - -75, - -90 - ], - [ - -79, - 4 - ], - [ - -44, - 106 - ], - [ - 1, - 59 - ], - [ - 37, - 51 - ], - [ - 69, - 33 - ], - [ - 145, - -4 - ], - [ - 133, - -29 - ], - [ - -104, - -107 - ], - [ - -83, - -23 - ] - ], - [ - [ - 4150, - 19361 - ], - [ - -183, - -58 - ], - [ - -37, - 53 - ], - [ - -161, - 63 - ], - [ - 30, - 51 - ], - [ - 48, - 88 - ], - [ - 61, - 78 - ], - [ - -68, - 74 - ], - [ - 235, - 19 - ], - [ - 100, - -25 - ], - [ - 178, - -7 - ], - [ - 68, - -35 - ], - [ - 74, - -50 - ], - [ - -87, - -30 - ], - [ - -171, - -85 - ], - [ - -87, - -84 - ], - [ - 0, - -52 - ] - ], - [ - [ - 6022, - 19792 - ], - [ - -38, - -46 - ], - [ - -101, - 9 - ], - [ - -85, - 31 - ], - [ - 37, - 54 - ], - [ - 101, - 32 - ], - [ - 60, - -42 - ], - [ - 26, - -38 - ] - ], - [ - [ - 5681, - 20001 - ], - [ - 54, - -55 - ], - [ - 2, - -62 - ], - [ - -32, - -89 - ], - [ - -115, - -12 - ], - [ - -75, - 19 - ], - [ - 2, - 70 - ], - [ - -115, - -10 - ], - [ - -4, - 93 - ], - [ - 75, - -4 - ], - [ - 105, - 41 - ], - [ - 98, - -7 - ], - [ - 5, - 16 - ] - ], - [ - [ - 5004, - 19939 - ], - [ - 28, - -43 - ], - [ - 62, - 20 - ], - [ - 73, - -5 - ], - [ - 12, - -59 - ], - [ - -42, - -57 - ], - [ - -237, - -18 - ], - [ - -175, - -52 - ], - [ - -106, - -3 - ], - [ - -9, - 39 - ], - [ - 145, - 53 - ], - [ - -315, - -14 - ], - [ - -98, - 22 - ], - [ - 95, - 117 - ], - [ - 66, - 33 - ], - [ - 196, - -40 - ], - [ - 124, - -71 - ], - [ - 122, - -9 - ], - [ - -100, - 114 - ], - [ - 64, - 44 - ], - [ - 72, - -14 - ], - [ - 23, - -57 - ] - ], - [ - [ - 5947, - 20047 - ], - [ - 78, - -39 - ], - [ - 137, - 0 - ], - [ - 60, - -39 - ], - [ - -16, - -45 - ], - [ - 80, - -27 - ], - [ - 44, - -29 - ], - [ - 94, - -5 - ], - [ - 102, - -10 - ], - [ - 111, - 26 - ], - [ - 142, - 10 - ], - [ - 113, - -8 - ], - [ - 75, - -46 - ], - [ - 15, - -49 - ], - [ - -43, - -32 - ], - [ - -104, - -26 - ], - [ - -89, - 15 - ], - [ - -200, - -19 - ], - [ - -143, - -2 - ], - [ - -113, - 15 - ], - [ - -185, - 38 - ], - [ - -24, - 66 - ], - [ - -9, - 60 - ], - [ - -70, - 52 - ], - [ - -144, - 15 - ], - [ - -81, - 37 - ], - [ - 27, - 49 - ], - [ - 143, - -7 - ] - ], - [ - [ - 4447, - 20112 - ], - [ - -9, - -92 - ], - [ - -54, - -42 - ], - [ - -65, - -5 - ], - [ - -129, - -52 - ], - [ - -112, - -18 - ], - [ - -95, - 26 - ], - [ - 119, - 90 - ], - [ - 143, - 77 - ], - [ - 107, - -1 - ], - [ - 95, - 17 - ] - ], - [ - [ - 6006, - 20097 - ], - [ - -32, - -3 - ], - [ - -130, - 7 - ], - [ - -19, - 34 - ], - [ - 140, - -2 - ], - [ - 49, - -22 - ], - [ - -8, - -14 - ] - ], - [ - [ - 4867, - 20118 - ], - [ - -130, - -34 - ], - [ - -104, - 39 - ], - [ - 57, - 38 - ], - [ - 101, - 12 - ], - [ - 99, - -19 - ], - [ - -23, - -36 - ] - ], - [ - [ - 4903, - 20227 - ], - [ - -85, - -23 - ], - [ - -116, - 0 - ], - [ - 2, - 17 - ], - [ - 71, - 36 - ], - [ - 37, - -6 - ], - [ - 91, - -24 - ] - ], - [ - [ - 5867, - 20162 - ], - [ - -103, - -25 - ], - [ - -57, - 28 - ], - [ - -29, - 45 - ], - [ - -6, - 49 - ], - [ - 90, - -4 - ], - [ - 41, - -8 - ], - [ - 83, - -42 - ], - [ - -19, - -43 - ] - ], - [ - [ - 5572, - 20194 - ], - [ - 28, - -50 - ], - [ - -114, - 13 - ], - [ - -115, - 39 - ], - [ - -155, - 4 - ], - [ - 67, - 36 - ], - [ - -84, - 29 - ], - [ - -5, - 46 - ], - [ - 137, - -16 - ], - [ - 188, - -44 - ], - [ - 53, - -57 - ] - ], - [ - [ - 6481, - 20354 - ], - [ - 85, - -39 - ], - [ - -96, - -36 - ], - [ - -129, - -90 - ], - [ - -123, - -8 - ], - [ - -145, - 15 - ], - [ - -75, - 49 - ], - [ - 1, - 43 - ], - [ - 56, - 32 - ], - [ - -128, - -1 - ], - [ - -77, - 40 - ], - [ - -44, - 55 - ], - [ - 48, - 53 - ], - [ - 49, - 37 - ], - [ - 71, - 8 - ], - [ - -30, - 27 - ], - [ - 162, - 7 - ], - [ - 89, - -65 - ], - [ - 117, - -25 - ], - [ - 114, - -23 - ], - [ - 55, - -79 - ] - ], - [ - [ - 7772, - 20767 - ], - [ - 187, - -9 - ], - [ - 149, - -15 - ], - [ - 128, - -33 - ], - [ - -3, - -32 - ], - [ - -170, - -52 - ], - [ - -169, - -24 - ], - [ - -63, - -27 - ], - [ - 152, - 0 - ], - [ - -165, - -72 - ], - [ - -113, - -34 - ], - [ - -119, - -98 - ], - [ - -144, - -20 - ], - [ - -45, - -25 - ], - [ - -211, - -13 - ], - [ - 96, - -15 - ], - [ - -48, - -21 - ], - [ - 58, - -59 - ], - [ - -66, - -41 - ], - [ - -108, - -34 - ], - [ - -33, - -47 - ], - [ - -97, - -36 - ], - [ - 9, - -27 - ], - [ - 119, - 4 - ], - [ - 2, - -29 - ], - [ - -186, - -72 - ], - [ - -182, - 33 - ], - [ - -205, - -18 - ], - [ - -104, - 14 - ], - [ - -132, - 6 - ], - [ - -8, - 58 - ], - [ - 128, - 27 - ], - [ - -34, - 87 - ], - [ - 43, - 8 - ], - [ - 186, - -52 - ], - [ - -95, - 77 - ], - [ - -113, - 23 - ], - [ - 56, - 47 - ], - [ - 124, - 28 - ], - [ - 20, - 42 - ], - [ - -99, - 47 - ], - [ - -29, - 62 - ], - [ - 190, - -5 - ], - [ - 55, - -13 - ], - [ - 109, - 43 - ], - [ - -157, - 14 - ], - [ - -244, - -7 - ], - [ - -123, - 40 - ], - [ - -58, - 49 - ], - [ - -82, - 35 - ], - [ - -15, - 41 - ], - [ - 104, - 23 - ], - [ - 81, - 4 - ], - [ - 137, - 19 - ], - [ - 102, - 45 - ], - [ - 87, - -6 - ], - [ - 75, - -34 - ], - [ - 53, - 65 - ], - [ - 92, - 19 - ], - [ - 125, - 13 - ], - [ - 213, - 5 - ], - [ - 37, - -13 - ], - [ - 202, - 21 - ], - [ - 151, - -8 - ], - [ - 150, - -8 - ] - ], - [ - [ - 13275, - 16423 - ], - [ - -5, - -49 - ], - [ - -31, - -20 - ], - [ - -51, - 15 - ], - [ - -15, - -49 - ], - [ - -34, - -4 - ], - [ - -12, - 19 - ], - [ - -39, - -40 - ], - [ - -33, - -6 - ], - [ - -30, - 26 - ] - ], - [ - [ - 13025, - 16315 - ], - [ - -24, - 52 - ], - [ - -34, - -18 - ], - [ - 1, - 54 - ], - [ - 51, - 67 - ], - [ - -2, - 31 - ], - [ - 32, - -11 - ], - [ - 19, - 20 - ] - ], - [ - [ - 13068, - 16510 - ], - [ - 59, - -1 - ], - [ - 15, - 26 - ], - [ - 74, - -36 - ] - ], - [ - [ - 7880, - 4211 - ], - [ - -23, - -48 - ], - [ - -60, - -37 - ], - [ - -34, - 3 - ], - [ - -42, - 10 - ], - [ - -50, - 36 - ], - [ - -73, - 17 - ], - [ - -88, - 67 - ], - [ - -71, - 65 - ], - [ - -96, - 134 - ], - [ - 57, - -25 - ], - [ - 98, - -80 - ], - [ - 93, - -43 - ], - [ - 36, - 55 - ], - [ - 22, - 82 - ], - [ - 65, - 50 - ], - [ - 49, - -15 - ] - ], - [ - [ - 7767, - 4523 - ], - [ - -62, - 1 - ], - [ - -33, - -30 - ], - [ - -63, - -43 - ], - [ - -11, - -112 - ], - [ - -30, - -3 - ], - [ - -78, - 39 - ], - [ - -80, - 84 - ], - [ - -87, - 68 - ], - [ - -22, - 76 - ], - [ - 20, - 71 - ], - [ - -35, - 79 - ], - [ - -9, - 205 - ], - [ - 30, - 115 - ], - [ - 73, - 93 - ], - [ - -106, - 35 - ], - [ - 67, - 106 - ], - [ - 24, - 199 - ], - [ - 77, - -42 - ], - [ - 36, - 249 - ], - [ - -46, - 31 - ], - [ - -22, - -149 - ], - [ - -44, - 17 - ], - [ - 22, - 171 - ], - [ - 24, - 222 - ], - [ - 32, - 82 - ], - [ - -20, - 117 - ], - [ - -6, - 136 - ], - [ - 29, - 3 - ], - [ - 43, - 194 - ], - [ - 48, - 192 - ], - [ - 30, - 179 - ], - [ - -16, - 180 - ], - [ - 20, - 99 - ], - [ - -8, - 148 - ], - [ - 41, - 146 - ], - [ - 12, - 232 - ], - [ - 23, - 249 - ], - [ - 22, - 269 - ], - [ - -6, - 196 - ], - [ - -14, - 169 - ] - ], - [ - [ - 7642, - 8596 - ], - [ - 36, - 31 - ], - [ - 18, - 61 - ] - ], - [ - [ - 17774, - 15286 - ], - [ - -10, - 69 - ], - [ - 2, - 46 - ], - [ - -42, - 28 - ], - [ - -23, - -12 - ], - [ - -18, - 111 - ] - ], - [ - [ - 17683, - 15528 - ], - [ - 20, - 27 - ], - [ - -9, - 28 - ], - [ - 66, - 57 - ], - [ - 48, - 23 - ], - [ - 74, - -16 - ], - [ - 26, - 77 - ], - [ - 90, - 14 - ], - [ - 25, - 48 - ], - [ - 109, - 65 - ], - [ - 10, - 27 - ] - ], - [ - [ - 18142, - 15878 - ], - [ - -5, - 68 - ], - [ - 48, - 31 - ], - [ - -63, - 209 - ], - [ - 138, - 48 - ], - [ - 36, - 27 - ], - [ - 50, - 214 - ], - [ - 138, - -39 - ], - [ - 39, - 54 - ], - [ - 3, - 120 - ], - [ - 58, - 12 - ], - [ - 53, - 79 - ] - ], - [ - [ - 18637, - 16701 - ], - [ - 27, - 10 - ] - ], - [ - [ - 18664, - 16711 - ], - [ - 19, - -83 - ], - [ - 58, - -64 - ], - [ - 100, - -45 - ], - [ - 48, - -97 - ], - [ - -27, - -140 - ], - [ - 25, - -52 - ], - [ - 83, - -20 - ], - [ - 94, - -17 - ], - [ - 84, - -75 - ], - [ - 43, - -13 - ], - [ - 32, - -111 - ], - [ - 41, - -71 - ], - [ - 77, - 3 - ], - [ - 144, - -27 - ], - [ - 92, - 17 - ], - [ - 69, - -18 - ], - [ - 103, - -73 - ], - [ - 85, - 0 - ], - [ - 30, - -37 - ], - [ - 82, - 64 - ], - [ - 112, - 42 - ], - [ - 105, - 4 - ], - [ - 81, - 42 - ], - [ - 50, - 65 - ], - [ - 49, - 40 - ], - [ - -11, - 40 - ], - [ - -23, - 46 - ], - [ - 37, - 77 - ], - [ - 39, - -11 - ], - [ - 72, - -24 - ], - [ - 69, - 64 - ], - [ - 107, - 46 - ], - [ - 51, - 79 - ], - [ - 49, - 34 - ], - [ - 101, - 16 - ], - [ - 55, - -13 - ], - [ - 8, - 42 - ], - [ - -64, - 84 - ], - [ - -55, - 39 - ], - [ - -54, - -45 - ], - [ - -69, - 19 - ], - [ - -39, - -15 - ], - [ - -18, - 49 - ], - [ - 49, - 120 - ], - [ - 34, - 90 - ] - ], - [ - [ - 20681, - 16782 - ], - [ - 84, - -45 - ], - [ - 98, - 76 - ], - [ - -1, - 53 - ], - [ - 63, - 127 - ], - [ - 39, - 38 - ], - [ - -1, - 67 - ], - [ - -38, - 28 - ], - [ - 57, - 60 - ], - [ - 87, - 21 - ], - [ - 92, - 4 - ], - [ - 105, - -36 - ], - [ - 61, - -44 - ], - [ - 43, - -121 - ], - [ - 26, - -52 - ], - [ - 24, - -74 - ], - [ - 26, - -117 - ], - [ - 122, - -38 - ], - [ - 82, - -86 - ], - [ - 28, - -112 - ], - [ - 106, - -1 - ], - [ - 61, - 48 - ], - [ - 115, - 35 - ], - [ - -37, - -108 - ], - [ - -27, - -44 - ], - [ - -24, - -131 - ], - [ - -47, - -117 - ], - [ - -84, - 21 - ], - [ - -60, - -42 - ], - [ - 18, - -103 - ], - [ - -10, - -142 - ], - [ - -35, - -3 - ], - [ - 0, - -61 - ] - ], - [ - [ - 21654, - 15883 - ], - [ - -45, - 71 - ], - [ - -28, - -67 - ], - [ - -107, - -52 - ], - [ - 11, - -63 - ], - [ - -61, - 4 - ], - [ - -33, - 38 - ], - [ - -48, - -85 - ], - [ - -76, - -65 - ], - [ - -57, - -77 - ] - ], - [ - [ - 21210, - 15587 - ], - [ - -98, - -35 - ], - [ - -51, - -56 - ], - [ - -75, - -32 - ], - [ - 37, - 55 - ], - [ - -15, - 47 - ], - [ - 56, - 81 - ], - [ - -37, - 62 - ], - [ - -61, - -42 - ], - [ - -79, - -83 - ], - [ - -43, - -78 - ], - [ - -68, - -6 - ], - [ - -35, - -55 - ], - [ - 36, - -82 - ], - [ - 57, - -19 - ], - [ - 3, - -54 - ], - [ - 55, - -35 - ], - [ - 78, - 85 - ], - [ - 62, - -46 - ], - [ - 45, - -3 - ], - [ - 11, - -63 - ], - [ - -99, - -34 - ], - [ - -32, - -65 - ], - [ - -68, - -60 - ], - [ - -36, - -84 - ], - [ - 75, - -66 - ], - [ - 28, - -118 - ], - [ - 42, - -110 - ], - [ - 48, - -92 - ], - [ - -2, - -89 - ], - [ - -43, - -33 - ], - [ - 16, - -64 - ], - [ - 41, - -37 - ], - [ - -10, - -98 - ], - [ - -18, - -95 - ], - [ - -39, - -10 - ], - [ - -51, - -130 - ], - [ - -56, - -158 - ], - [ - -65, - -143 - ], - [ - -96, - -111 - ], - [ - -97, - -101 - ], - [ - -79, - -13 - ], - [ - -42, - -54 - ], - [ - -24, - 39 - ], - [ - -40, - -59 - ], - [ - -97, - -60 - ], - [ - -74, - -19 - ], - [ - -24, - -127 - ], - [ - -38, - -7 - ], - [ - -19, - 88 - ], - [ - 17, - 46 - ], - [ - -94, - 38 - ], - [ - -33, - -19 - ] - ], - [ - [ - 20079, - 13383 - ], - [ - -70, - 31 - ], - [ - -33, - 49 - ], - [ - 11, - 69 - ], - [ - -64, - 22 - ], - [ - -33, - 45 - ], - [ - -60, - -64 - ], - [ - -67, - -14 - ], - [ - -56, - 1 - ], - [ - -37, - -30 - ] - ], - [ - [ - 19670, - 13492 - ], - [ - -37, - -17 - ], - [ - 11, - -138 - ], - [ - -37, - 4 - ], - [ - -6, - 28 - ] - ], - [ - [ - 19601, - 13369 - ], - [ - -2, - 50 - ], - [ - -52, - -35 - ], - [ - -30, - 22 - ], - [ - -52, - 45 - ], - [ - 21, - 99 - ], - [ - -44, - 24 - ], - [ - -17, - 110 - ], - [ - -74, - -20 - ], - [ - 9, - 142 - ], - [ - 66, - 101 - ], - [ - 3, - 99 - ], - [ - -2, - 91 - ], - [ - -31, - 29 - ], - [ - -23, - 71 - ], - [ - -41, - -9 - ] - ], - [ - [ - 19332, - 14188 - ], - [ - -75, - 18 - ], - [ - 23, - 50 - ], - [ - -32, - 75 - ], - [ - -50, - -51 - ], - [ - -58, - 30 - ], - [ - -81, - -77 - ], - [ - -63, - -89 - ], - [ - -56, - -15 - ] - ], - [ - [ - 18739, - 14072 - ], - [ - -6, - 95 - ], - [ - -43, - -25 - ] - ], - [ - [ - 18690, - 14142 - ], - [ - -81, - 11 - ], - [ - -79, - 28 - ], - [ - -56, - 52 - ], - [ - -55, - 24 - ], - [ - -23, - 58 - ], - [ - -39, - 17 - ], - [ - -71, - 78 - ], - [ - -55, - 37 - ], - [ - -29, - -29 - ] - ], - [ - [ - 18202, - 14418 - ], - [ - -97, - 84 - ], - [ - -69, - 76 - ], - [ - -19, - 132 - ], - [ - 50, - -16 - ], - [ - 2, - 61 - ], - [ - -28, - 62 - ], - [ - 7, - 98 - ], - [ - -75, - 140 - ] - ], - [ - [ - 17973, - 15055 - ], - [ - -114, - 49 - ], - [ - -21, - 92 - ], - [ - -51, - 56 - ] - ], - [ - [ - 20239, - 13038 - ], - [ - -60, - -58 - ], - [ - -57, - 38 - ], - [ - -2, - 103 - ], - [ - 34, - 54 - ], - [ - 76, - 34 - ], - [ - 40, - -3 - ], - [ - 16, - -46 - ], - [ - -31, - -53 - ], - [ - -16, - -69 - ] - ], - [ - [ - 12350, - 11954 - ], - [ - 19, - -171 - ], - [ - -29, - -100 - ], - [ - -19, - -136 - ], - [ - 31, - -103 - ], - [ - -4, - -48 - ] - ], - [ - [ - 12348, - 11396 - ], - [ - -31, - -1 - ], - [ - -49, - 24 - ], - [ - -45, - -2 - ], - [ - -82, - -21 - ], - [ - -49, - -34 - ], - [ - -69, - -44 - ], - [ - -13, - 3 - ] - ], - [ - [ - 12010, - 11321 - ], - [ - 5, - 99 - ], - [ - 7, - 15 - ], - [ - -2, - 47 - ], - [ - -30, - 50 - ], - [ - -22, - 8 - ], - [ - -20, - 33 - ], - [ - 15, - 53 - ], - [ - -7, - 58 - ], - [ - 3, - 35 - ] - ], - [ - [ - 11959, - 11719 - ], - [ - 11, - 0 - ], - [ - 4, - 53 - ], - [ - -5, - 23 - ], - [ - 7, - 17 - ], - [ - 26, - 14 - ], - [ - -18, - 96 - ], - [ - -16, - 50 - ], - [ - 6, - 40 - ], - [ - 14, - 10 - ] - ], - [ - [ - 11988, - 12022 - ], - [ - 9, - 11 - ], - [ - 19, - -18 - ], - [ - 54, - -1 - ], - [ - 13, - 35 - ], - [ - 12, - -3 - ], - [ - 20, - 14 - ], - [ - 11, - -52 - ], - [ - 16, - 16 - ], - [ - 29, - 17 - ] - ], - [ - [ - 13664, - 11069 - ], - [ - -5, - -65 - ], - [ - -56, - 29 - ], - [ - -56, - 31 - ], - [ - -88, - 5 - ] - ], - [ - [ - 13459, - 11069 - ], - [ - -9, - 7 - ], - [ - -41, - -16 - ], - [ - -42, - 16 - ], - [ - -33, - -8 - ] - ], - [ - [ - 13334, - 11068 - ], - [ - -114, - 3 - ] - ], - [ - [ - 13220, - 11071 - ], - [ - 10, - 95 - ], - [ - -27, - 79 - ], - [ - -32, - 21 - ], - [ - -14, - 53 - ], - [ - -18, - 18 - ], - [ - 1, - 33 - ] - ], - [ - [ - 13140, - 11370 - ], - [ - 18, - 85 - ], - [ - 33, - 115 - ], - [ - 20, - 1 - ], - [ - 42, - 71 - ], - [ - 26, - 2 - ], - [ - 39, - -50 - ], - [ - 48, - 41 - ], - [ - 7, - 50 - ], - [ - 15, - 48 - ], - [ - 11, - 61 - ], - [ - 38, - 49 - ], - [ - 14, - 84 - ], - [ - 14, - 27 - ], - [ - 10, - 62 - ], - [ - 19, - 77 - ], - [ - 58, - 93 - ], - [ - 4, - 39 - ], - [ - 8, - 22 - ], - [ - -28, - 48 - ] - ], - [ - [ - 13536, - 12295 - ], - [ - 2, - 38 - ], - [ - 20, - 7 - ] - ], - [ - [ - 13558, - 12340 - ], - [ - 28, - -77 - ], - [ - 4, - -79 - ], - [ - -2, - -80 - ], - [ - 38, - -109 - ], - [ - -39, - 1 - ], - [ - -20, - -9 - ], - [ - -32, - 12 - ], - [ - -15, - -56 - ], - [ - 41, - -70 - ], - [ - 31, - -21 - ], - [ - 10, - -49 - ], - [ - 22, - -83 - ], - [ - -11, - -32 - ] - ], - [ - [ - 13406, - 10065 - ], - [ - -9, - 38 - ] - ], - [ - [ - 13453, - 10224 - ], - [ - 19, - -13 - ], - [ - 24, - 46 - ], - [ - 38, - -1 - ], - [ - 4, - -34 - ], - [ - 26, - -21 - ], - [ - 41, - 75 - ], - [ - 41, - 59 - ], - [ - 17, - 38 - ], - [ - -2, - 99 - ], - [ - 30, - 116 - ], - [ - 32, - 62 - ], - [ - 46, - 58 - ], - [ - 8, - 38 - ], - [ - 2, - 44 - ], - [ - 11, - 42 - ], - [ - -3, - 68 - ], - [ - 8, - 106 - ], - [ - 14, - 75 - ], - [ - 21, - 64 - ], - [ - 4, - 73 - ] - ], - [ - [ - 14456, - 11425 - ], - [ - 42, - -99 - ], - [ - 31, - -14 - ], - [ - 19, - 20 - ], - [ - 32, - -8 - ], - [ - 39, - 25 - ], - [ - 17, - -51 - ], - [ - 61, - -80 - ] - ], - [ - [ - 14697, - 11218 - ], - [ - -4, - -140 - ], - [ - 28, - -16 - ], - [ - -23, - -43 - ], - [ - -27, - -32 - ], - [ - -26, - -62 - ], - [ - -15, - -56 - ], - [ - -4, - -96 - ], - [ - -16, - -46 - ], - [ - -1, - -91 - ] - ], - [ - [ - 14609, - 10636 - ], - [ - -20, - -33 - ], - [ - -2, - -72 - ], - [ - -10, - -9 - ], - [ - -6, - -65 - ] - ], - [ - [ - 14593, - 10257 - ], - [ - 12, - -110 - ], - [ - -7, - -62 - ], - [ - 14, - -70 - ], - [ - 41, - -67 - ], - [ - 37, - -151 - ] - ], - [ - [ - 14690, - 9797 - ], - [ - -27, - 12 - ], - [ - -94, - -20 - ], - [ - -18, - -15 - ], - [ - -20, - -76 - ], - [ - 15, - -53 - ], - [ - -12, - -142 - ], - [ - -9, - -121 - ], - [ - 19, - -21 - ], - [ - 49, - -47 - ], - [ - 19, - 22 - ], - [ - 6, - -129 - ], - [ - -54, - 1 - ], - [ - -28, - 66 - ], - [ - -26, - 51 - ], - [ - -53, - 17 - ], - [ - -16, - 63 - ], - [ - -43, - -38 - ], - [ - -55, - 16 - ], - [ - -24, - 55 - ], - [ - -44, - 11 - ], - [ - -33, - -3 - ], - [ - -4, - 37 - ], - [ - -24, - 3 - ] - ], - [ - [ - 13378, - 10193 - ], - [ - -57, - 127 - ] - ], - [ - [ - 13321, - 10320 - ], - [ - 53, - 66 - ], - [ - -26, - 79 - ], - [ - 24, - 31 - ], - [ - 47, - 14 - ], - [ - 5, - 53 - ], - [ - 37, - -57 - ], - [ - 62, - -5 - ], - [ - 21, - 56 - ], - [ - 9, - 80 - ], - [ - -8, - 94 - ], - [ - -33, - 71 - ], - [ - 31, - 139 - ], - [ - -18, - 24 - ], - [ - -52, - -10 - ], - [ - -19, - 62 - ], - [ - 5, - 52 - ] - ], - [ - [ - 7675, - 10282 - ], - [ - -35, - 63 - ], - [ - -20, - 3 - ], - [ - 45, - 122 - ], - [ - -54, - 56 - ], - [ - -42, - -10 - ], - [ - -25, - 21 - ], - [ - -38, - -32 - ], - [ - -52, - 15 - ], - [ - -41, - 126 - ], - [ - -32, - 31 - ], - [ - -23, - 57 - ], - [ - -46, - 56 - ], - [ - -19, - -11 - ] - ], - [ - [ - 7293, - 10779 - ], - [ - -29, - 28 - ], - [ - -35, - 40 - ], - [ - -20, - -19 - ], - [ - -59, - 17 - ], - [ - -17, - 51 - ], - [ - -13, - -2 - ], - [ - -69, - 69 - ] - ], - [ - [ - 7051, - 10963 - ], - [ - -10, - 37 - ], - [ - 26, - 9 - ], - [ - -3, - 60 - ], - [ - 16, - 44 - ], - [ - 35, - 8 - ], - [ - 29, - 75 - ], - [ - 27, - 63 - ], - [ - -26, - 29 - ], - [ - 14, - 69 - ], - [ - -16, - 110 - ], - [ - 15, - 31 - ], - [ - -11, - 102 - ], - [ - -28, - 64 - ] - ], - [ - [ - 7119, - 11664 - ], - [ - 8, - 58 - ], - [ - 23, - -8 - ], - [ - 13, - 35 - ], - [ - -16, - 71 - ], - [ - 8, - 17 - ] - ], - [ - [ - 7155, - 11837 - ], - [ - 36, - -3 - ], - [ - 53, - 83 - ], - [ - 28, - 13 - ], - [ - 1, - 40 - ], - [ - 13, - 101 - ], - [ - 40, - 56 - ], - [ - 44, - 2 - ], - [ - 5, - 25 - ], - [ - 55, - -10 - ], - [ - 55, - 61 - ], - [ - 27, - 26 - ], - [ - 34, - 58 - ], - [ - 24, - -7 - ], - [ - 19, - -32 - ], - [ - -14, - -40 - ] - ], - [ - [ - 7575, - 12210 - ], - [ - -45, - -20 - ], - [ - -17, - -60 - ], - [ - -27, - -35 - ], - [ - -21, - -44 - ], - [ - -8, - -86 - ], - [ - -19, - -70 - ], - [ - 36, - -8 - ], - [ - 8, - -55 - ], - [ - 16, - -26 - ], - [ - 5, - -49 - ], - [ - -8, - -44 - ], - [ - 3, - -25 - ], - [ - 17, - -10 - ], - [ - 16, - -42 - ], - [ - 90, - 12 - ], - [ - 40, - -16 - ], - [ - 49, - -103 - ], - [ - 29, - 13 - ], - [ - 50, - -7 - ], - [ - 40, - 14 - ], - [ - 24, - -21 - ], - [ - -12, - -64 - ], - [ - -16, - -40 - ], - [ - -5, - -86 - ], - [ - 14, - -80 - ], - [ - 20, - -36 - ], - [ - 2, - -27 - ], - [ - -35, - -59 - ], - [ - 25, - -27 - ], - [ - 18, - -42 - ], - [ - 22, - -119 - ] - ], - [ - [ - 6764, - 11784 - ], - [ - -38, - 27 - ], - [ - -14, - 25 - ], - [ - 8, - 21 - ], - [ - -2, - 26 - ], - [ - -20, - 29 - ], - [ - -27, - 23 - ], - [ - -24, - 16 - ], - [ - -5, - 35 - ], - [ - -18, - 21 - ], - [ - 4, - -35 - ], - [ - -13, - -28 - ], - [ - -16, - 33 - ], - [ - -23, - 12 - ], - [ - -9, - 24 - ], - [ - 0, - 37 - ], - [ - 9, - 37 - ], - [ - -19, - 17 - ], - [ - 16, - 23 - ] - ], - [ - [ - 6573, - 12127 - ], - [ - 10, - 16 - ], - [ - 46, - -32 - ], - [ - 16, - 16 - ], - [ - 22, - -10 - ], - [ - 12, - -25 - ], - [ - 20, - -8 - ], - [ - 17, - 26 - ] - ], - [ - [ - 6716, - 12110 - ], - [ - 18, - -66 - ], - [ - 27, - -48 - ], - [ - 32, - -51 - ] - ], - [ - [ - 6793, - 11945 - ], - [ - -27, - -11 - ], - [ - 1, - -48 - ], - [ - 14, - -18 - ], - [ - -10, - -14 - ], - [ - 3, - -22 - ], - [ - -6, - -24 - ], - [ - -4, - -24 - ] - ], - [ - [ - 6813, - 13579 - ], - [ - 60, - -8 - ], - [ - 55, - -2 - ], - [ - 65, - -41 - ], - [ - 28, - -44 - ], - [ - 65, - 14 - ], - [ - 25, - -28 - ], - [ - 59, - -75 - ], - [ - 43, - -54 - ], - [ - 23, - 2 - ], - [ - 42, - -24 - ], - [ - -5, - -34 - ], - [ - 51, - -5 - ], - [ - 53, - -49 - ], - [ - -9, - -28 - ], - [ - -46, - -16 - ], - [ - -47, - -6 - ], - [ - -48, - 10 - ], - [ - -100, - -12 - ], - [ - 47, - 67 - ], - [ - -28, - 31 - ], - [ - -45, - 8 - ], - [ - -24, - 35 - ], - [ - -17, - 68 - ], - [ - -39, - -4 - ], - [ - -65, - 32 - ], - [ - -21, - 25 - ], - [ - -91, - 19 - ], - [ - -24, - 23 - ], - [ - 26, - 30 - ], - [ - -69, - 6 - ], - [ - -50, - -62 - ], - [ - -29, - -2 - ], - [ - -10, - -29 - ], - [ - -34, - -13 - ], - [ - -30, - 11 - ], - [ - 37, - 37 - ], - [ - 15, - 43 - ], - [ - 31, - 27 - ], - [ - 36, - 23 - ], - [ - 53, - 12 - ], - [ - 17, - 13 - ] - ], - [ - [ - 14829, - 15013 - ], - [ - 5, - 1 - ], - [ - 10, - 28 - ], - [ - 50, - -1 - ], - [ - 64, - 36 - ], - [ - -47, - -51 - ], - [ - 5, - -23 - ] - ], - [ - [ - 14916, - 15003 - ], - [ - -8, - 4 - ], - [ - -13, - -9 - ], - [ - -10, - 3 - ], - [ - -4, - -5 - ], - [ - -1, - 12 - ], - [ - -5, - 8 - ], - [ - -14, - 1 - ], - [ - -19, - -10 - ], - [ - -13, - 6 - ] - ], - [ - [ - 14916, - 15003 - ], - [ - 2, - -10 - ], - [ - -72, - -48 - ], - [ - -34, - 15 - ], - [ - -16, - 48 - ], - [ - 33, - 5 - ] - ], - [ - [ - 13495, - 16661 - ], - [ - -39, - 52 - ], - [ - -36, - 28 - ], - [ - -7, - 51 - ], - [ - -12, - 36 - ], - [ - 50, - 26 - ], - [ - 26, - 30 - ], - [ - 50, - 23 - ], - [ - 18, - 23 - ], - [ - 18, - -14 - ], - [ - 31, - 12 - ] - ], - [ - [ - 13594, - 16928 - ], - [ - 33, - -38 - ], - [ - 52, - -11 - ], - [ - -4, - -33 - ], - [ - 38, - -24 - ], - [ - 10, - 30 - ], - [ - 48, - -13 - ], - [ - 7, - -37 - ], - [ - 52, - -8 - ], - [ - 32, - -59 - ] - ], - [ - [ - 13862, - 16735 - ], - [ - -21, - 0 - ], - [ - -11, - -22 - ], - [ - -16, - -5 - ], - [ - -4, - -27 - ], - [ - -14, - -6 - ], - [ - -2, - -11 - ], - [ - -23, - -12 - ], - [ - -31, - 2 - ], - [ - -10, - -27 - ] - ], - [ - [ - 13068, - 16510 - ], - [ - 9, - 86 - ], - [ - 35, - 82 - ], - [ - -100, - 22 - ], - [ - -33, - 31 - ] - ], - [ - [ - 12979, - 16731 - ], - [ - 4, - 53 - ], - [ - -14, - 27 - ] - ], - [ - [ - 12977, - 16892 - ], - [ - -12, - 126 - ], - [ - 42, - 0 - ], - [ - 18, - 45 - ], - [ - 17, - 110 - ], - [ - -13, - 40 - ] - ], - [ - [ - 13029, - 17213 - ], - [ - 13, - 26 - ], - [ - 59, - 6 - ], - [ - 13, - -26 - ], - [ - 47, - 59 - ], - [ - -16, - 45 - ], - [ - -3, - 68 - ] - ], - [ - [ - 13142, - 17391 - ], - [ - 53, - -16 - ], - [ - 44, - 18 - ] - ], - [ - [ - 13239, - 17393 - ], - [ - 1, - -46 - ], - [ - 71, - -28 - ], - [ - -1, - -42 - ], - [ - 71, - 22 - ], - [ - 39, - 33 - ], - [ - 79, - -47 - ], - [ - 33, - -39 - ] - ], - [ - [ - 13532, - 17246 - ], - [ - 16, - -61 - ], - [ - -19, - -32 - ], - [ - 25, - -42 - ], - [ - 17, - -65 - ], - [ - -5, - -41 - ], - [ - 28, - -77 - ] - ], - [ - [ - 15551, - 12321 - ], - [ - 16, - -37 - ], - [ - -2, - -50 - ], - [ - -40, - -29 - ], - [ - 30, - -33 - ] - ], - [ - [ - 15555, - 12172 - ], - [ - -26, - -64 - ] - ], - [ - [ - 15529, - 12108 - ], - [ - -15, - 21 - ], - [ - -17, - -8 - ], - [ - -39, - 2 - ], - [ - -1, - 36 - ], - [ - -5, - 34 - ], - [ - 23, - 56 - ], - [ - 25, - 53 - ] - ], - [ - [ - 15500, - 12302 - ], - [ - 30, - -11 - ], - [ - 21, - 30 - ] - ], - [ - [ - 13142, - 17391 - ], - [ - -28, - 67 - ], - [ - -3, - 122 - ], - [ - 12, - 33 - ], - [ - 20, - 36 - ], - [ - 61, - 7 - ], - [ - 25, - 33 - ], - [ - 56, - 34 - ], - [ - -2, - -62 - ], - [ - -21, - -39 - ], - [ - 8, - -33 - ], - [ - 38, - -19 - ], - [ - -17, - -45 - ], - [ - -21, - 13 - ], - [ - -50, - -86 - ], - [ - 19, - -59 - ] - ], - [ - [ - 13432, - 17469 - ], - [ - -42, - -98 - ], - [ - -73, - 68 - ], - [ - -9, - 50 - ], - [ - 102, - 40 - ], - [ - 22, - -60 - ] - ], - [ - [ - 7549, - 13162 - ], - [ - 8, - 21 - ], - [ - 55, - -1 - ], - [ - 41, - -31 - ], - [ - 18, - 3 - ], - [ - 13, - -42 - ], - [ - 38, - 2 - ], - [ - -2, - -36 - ], - [ - 31, - -4 - ], - [ - 34, - -44 - ], - [ - -26, - -49 - ], - [ - -33, - 26 - ], - [ - -32, - -5 - ], - [ - -23, - 6 - ], - [ - -12, - -22 - ], - [ - -27, - -7 - ], - [ - -11, - 29 - ], - [ - -23, - -17 - ], - [ - -28, - -83 - ], - [ - -18, - 20 - ], - [ - -3, - 34 - ] - ], - [ - [ - 7549, - 12962 - ], - [ - 1, - 33 - ], - [ - -18, - 36 - ], - [ - 17, - 20 - ], - [ - 6, - 46 - ], - [ - -6, - 65 - ] - ], - [ - [ - 12845, - 13095 - ], - [ - -77, - -12 - ], - [ - -1, - 77 - ], - [ - -32, - 19 - ], - [ - -44, - 35 - ], - [ - -16, - 56 - ], - [ - -236, - 262 - ], - [ - -235, - 261 - ] - ], - [ - [ - 12204, - 13793 - ], - [ - -262, - 291 - ] - ], - [ - [ - 11942, - 14084 - ], - [ - 1, - 23 - ], - [ - 0, - 8 - ] - ], - [ - [ - 11943, - 14115 - ], - [ - 0, - 142 - ], - [ - 112, - 89 - ], - [ - 70, - 18 - ], - [ - 57, - 32 - ], - [ - 27, - 60 - ], - [ - 81, - 48 - ], - [ - 3, - 89 - ], - [ - 41, - 10 - ], - [ - 31, - 45 - ], - [ - 91, - 20 - ], - [ - 13, - 46 - ], - [ - -18, - 26 - ], - [ - -24, - 127 - ], - [ - -4, - 72 - ], - [ - -27, - 77 - ] - ], - [ - [ - 12396, - 15016 - ], - [ - 67, - 66 - ], - [ - 76, - 21 - ], - [ - 44, - 49 - ], - [ - 67, - 37 - ], - [ - 118, - 21 - ], - [ - 115, - 10 - ], - [ - 35, - -18 - ], - [ - 66, - 47 - ], - [ - 74, - 1 - ], - [ - 29, - -28 - ], - [ - 48, - 8 - ] - ], - [ - [ - 13135, - 15230 - ], - [ - -15, - -62 - ], - [ - 11, - -114 - ], - [ - -16, - -99 - ], - [ - -43, - -67 - ], - [ - 6, - -91 - ], - [ - 57, - -71 - ], - [ - 1, - -29 - ], - [ - 43, - -48 - ], - [ - 29, - -216 - ] - ], - [ - [ - 13208, - 14433 - ], - [ - 23, - -106 - ], - [ - 4, - -56 - ], - [ - -12, - -97 - ], - [ - 5, - -55 - ], - [ - -9, - -66 - ], - [ - 6, - -75 - ], - [ - -28, - -50 - ], - [ - 41, - -88 - ], - [ - 3, - -51 - ], - [ - 25, - -67 - ], - [ - 32, - 22 - ], - [ - 55, - -56 - ], - [ - 31, - -75 - ] - ], - [ - [ - 13384, - 13613 - ], - [ - -239, - -229 - ], - [ - -202, - -235 - ], - [ - -98, - -54 - ] - ], - [ - [ - 7293, - 10779 - ], - [ - 10, - -91 - ], - [ - -22, - -78 - ], - [ - -76, - -126 - ], - [ - -83, - -47 - ], - [ - -43, - -104 - ], - [ - -13, - -81 - ], - [ - -40, - -50 - ], - [ - -29, - 61 - ], - [ - -28, - 13 - ], - [ - -29, - -10 - ], - [ - -2, - 44 - ], - [ - 20, - 29 - ], - [ - -8, - 50 - ] - ], - [ - [ - 6950, - 10389 - ], - [ - 37, - 89 - ], - [ - -15, - 53 - ], - [ - -27, - -56 - ], - [ - -42, - 53 - ], - [ - 15, - 33 - ], - [ - -12, - 109 - ], - [ - 24, - 18 - ], - [ - 13, - 75 - ], - [ - 26, - 77 - ], - [ - -4, - 49 - ], - [ - 38, - 26 - ], - [ - 48, - 48 - ] - ], - [ - [ - 15117, - 13437 - ], - [ - -276, - 0 - ], - [ - -271, - 0 - ], - [ - -280, - 0 - ] - ], - [ - [ - 14290, - 13437 - ], - [ - 0, - 441 - ], - [ - 0, - 427 - ], - [ - -21, - 97 - ], - [ - 18, - 74 - ], - [ - -11, - 51 - ], - [ - 26, - 58 - ] - ], - [ - [ - 14302, - 14585 - ], - [ - 92, - 1 - ], - [ - 68, - -31 - ], - [ - 69, - -36 - ], - [ - 32, - -18 - ], - [ - 54, - 38 - ], - [ - 28, - 34 - ], - [ - 62, - 10 - ], - [ - 49, - -15 - ], - [ - 19, - -60 - ], - [ - 17, - 39 - ], - [ - 55, - -28 - ], - [ - 55, - -7 - ], - [ - 34, - 31 - ] - ], - [ - [ - 14936, - 14543 - ], - [ - 39, - -175 - ], - [ - 7, - -32 - ] - ], - [ - [ - 14982, - 14336 - ], - [ - -20, - -48 - ], - [ - -15, - -90 - ], - [ - -19, - -63 - ], - [ - -16, - -21 - ], - [ - -23, - 39 - ], - [ - -32, - 53 - ], - [ - -49, - 172 - ], - [ - -7, - -10 - ], - [ - 28, - -127 - ], - [ - 43, - -121 - ], - [ - 53, - -187 - ], - [ - 26, - -65 - ], - [ - 22, - -68 - ], - [ - 63, - -132 - ], - [ - -14, - -21 - ], - [ - 2, - -78 - ], - [ - 81, - -108 - ], - [ - 12, - -24 - ] - ], - [ - [ - 15500, - 12302 - ], - [ - -24, - 39 - ], - [ - -29, - 70 - ], - [ - -31, - 39 - ], - [ - -18, - 41 - ], - [ - -60, - 48 - ], - [ - -48, - 2 - ], - [ - -17, - 25 - ], - [ - -41, - -29 - ], - [ - -42, - 55 - ], - [ - -22, - -90 - ], - [ - -81, - 25 - ] - ], - [ - [ - 15087, - 12527 - ], - [ - -7, - 48 - ], - [ - 30, - 177 - ], - [ - 6, - 79 - ], - [ - 22, - 37 - ], - [ - 52, - 20 - ], - [ - 35, - 68 - ] - ], - [ - [ - 15225, - 12956 - ], - [ - 40, - -138 - ], - [ - 20, - -111 - ], - [ - 38, - -58 - ], - [ - 95, - -113 - ], - [ - 39, - -69 - ], - [ - 38, - -69 - ], - [ - 21, - -41 - ], - [ - 35, - -36 - ] - ], - [ - [ - 11918, - 15822 - ], - [ - 3, - 85 - ], - [ - -28, - 52 - ], - [ - 98, - 87 - ], - [ - 86, - -22 - ], - [ - 93, - 1 - ], - [ - 74, - -21 - ], - [ - 58, - 7 - ], - [ - 113, - -4 - ] - ], - [ - [ - 12415, - 16007 - ], - [ - 28, - -47 - ], - [ - 128, - -55 - ], - [ - 25, - 26 - ], - [ - 79, - -54 - ], - [ - 81, - 16 - ] - ], - [ - [ - 12756, - 15893 - ], - [ - 3, - -70 - ], - [ - -66, - -80 - ], - [ - -89, - -25 - ], - [ - -6, - -41 - ], - [ - -43, - -66 - ], - [ - -27, - -98 - ], - [ - 27, - -68 - ], - [ - -40, - -54 - ], - [ - -15, - -78 - ], - [ - -53, - -24 - ], - [ - -49, - -92 - ], - [ - -89, - -2 - ], - [ - -66, - 2 - ], - [ - -44, - -42 - ], - [ - -26, - -45 - ], - [ - -34, - 10 - ], - [ - -26, - 40 - ], - [ - -20, - 69 - ], - [ - -65, - 19 - ] - ], - [ - [ - 12028, - 15248 - ], - [ - -6, - 39 - ], - [ - 26, - 45 - ], - [ - 10, - 33 - ], - [ - -25, - 36 - ], - [ - 20, - 79 - ], - [ - -28, - 72 - ], - [ - 30, - 9 - ], - [ - 3, - 57 - ], - [ - 11, - 18 - ], - [ - 1, - 93 - ], - [ - 32, - 33 - ], - [ - -19, - 60 - ], - [ - -41, - 4 - ], - [ - -12, - -15 - ], - [ - -41, - 0 - ], - [ - -18, - 59 - ], - [ - -28, - -18 - ], - [ - -25, - -30 - ] - ], - [ - [ - 14242, - 17731 - ], - [ - 8, - 70 - ], - [ - -25, - -15 - ], - [ - -44, - 43 - ], - [ - -7, - 69 - ], - [ - 89, - 33 - ], - [ - 87, - 18 - ], - [ - 76, - -20 - ], - [ - 72, - 3 - ] - ], - [ - [ - 14498, - 17932 - ], - [ - 11, - -21 - ], - [ - -50, - -69 - ], - [ - 21, - -112 - ], - [ - -30, - -38 - ] - ], - [ - [ - 14450, - 17692 - ], - [ - -58, - 1 - ], - [ - -60, - 44 - ], - [ - -30, - 15 - ], - [ - -60, - -21 - ] - ], - [ - [ - 15529, - 12108 - ], - [ - -15, - -42 - ], - [ - 26, - -66 - ], - [ - 26, - -58 - ], - [ - 26, - -43 - ], - [ - 228, - -142 - ], - [ - 59, - 0 - ] - ], - [ - [ - 15879, - 11757 - ], - [ - -197, - -360 - ], - [ - -91, - -5 - ], - [ - -62, - -85 - ], - [ - -45, - -2 - ], - [ - -19, - -38 - ] - ], - [ - [ - 15465, - 11267 - ], - [ - -47, - 0 - ], - [ - -29, - 41 - ], - [ - -63, - -50 - ], - [ - -21, - -50 - ], - [ - -46, - 9 - ], - [ - -16, - 14 - ], - [ - -16, - -3 - ], - [ - -22, - 1 - ], - [ - -88, - 102 - ], - [ - -49, - 0 - ], - [ - -24, - 39 - ], - [ - 0, - 68 - ], - [ - -36, - 20 - ] - ], - [ - [ - 15008, - 11458 - ], - [ - -41, - 130 - ], - [ - -32, - 28 - ], - [ - -12, - 48 - ], - [ - -36, - 59 - ], - [ - -42, - 8 - ], - [ - 23, - 68 - ], - [ - 37, - 3 - ], - [ - 11, - 37 - ] - ], - [ - [ - 14916, - 11839 - ], - [ - -1, - 108 - ], - [ - 21, - 125 - ], - [ - 33, - 34 - ], - [ - 7, - 49 - ], - [ - 29, - 92 - ], - [ - 42, - 59 - ], - [ - 29, - 118 - ], - [ - 11, - 103 - ] - ], - [ - [ - 14214, - 18716 - ], - [ - -24, - 47 - ], - [ - -2, - 184 - ], - [ - -108, - 82 - ], - [ - -93, - 59 - ] - ], - [ - [ - 13987, - 19088 - ], - [ - 41, - 31 - ], - [ - 78, - -63 - ], - [ - 91, - 6 - ], - [ - 75, - -29 - ], - [ - 66, - 53 - ], - [ - 34, - 88 - ], - [ - 109, - 41 - ], - [ - 89, - -48 - ], - [ - -29, - -84 - ] - ], - [ - [ - 14541, - 19083 - ], - [ - -11, - -84 - ], - [ - 107, - -80 - ], - [ - -64, - -91 - ], - [ - 81, - -136 - ], - [ - -47, - -103 - ], - [ - 63, - -89 - ], - [ - -29, - -78 - ], - [ - 103, - -83 - ], - [ - -26, - -61 - ], - [ - -65, - -69 - ], - [ - -149, - -153 - ] - ], - [ - [ - 14504, - 18056 - ], - [ - -126, - -10 - ], - [ - -123, - -44 - ], - [ - -113, - -25 - ], - [ - -41, - 65 - ], - [ - -67, - 40 - ], - [ - 15, - 118 - ], - [ - -33, - 108 - ], - [ - 33, - 70 - ], - [ - 63, - 75 - ], - [ - 159, - 130 - ], - [ - 47, - 26 - ], - [ - -7, - 50 - ], - [ - -97, - 57 - ] - ], - [ - [ - 24982, - 8717 - ], - [ - 24, - -35 - ], - [ - -12, - -62 - ], - [ - -43, - -17 - ], - [ - -39, - 15 - ], - [ - -6, - 53 - ], - [ - 27, - 41 - ], - [ - 31, - -15 - ], - [ - 18, - 20 - ] - ], - [ - [ - 25051, - 8782 - ], - [ - -45, - -26 - ], - [ - -9, - 45 - ], - [ - 35, - 25 - ], - [ - 22, - 6 - ], - [ - 41, - 38 - ], - [ - 0, - -59 - ], - [ - -44, - -29 - ] - ], - [ - [ - 6, - 8817 - ], - [ - -6, - -6 - ], - [ - 0, - 59 - ], - [ - 14, - 5 - ], - [ - -8, - -58 - ] - ], - [ - [ - 8281, - 4577 - ], - [ - 84, - 72 - ], - [ - 59, - -30 - ], - [ - 42, - 48 - ], - [ - 56, - -54 - ], - [ - -21, - -42 - ], - [ - -94, - -36 - ], - [ - -32, - 42 - ], - [ - -59, - -54 - ], - [ - -35, - 54 - ] - ], - [ - [ - 12943, - 16739 - ], - [ - 16, - -10 - ], - [ - 20, - 2 - ] - ], - [ - [ - 13025, - 16315 - ], - [ - -3, - -34 - ], - [ - 20, - -45 - ], - [ - -24, - -37 - ], - [ - 18, - -93 - ], - [ - 38, - -15 - ], - [ - -8, - -52 - ] - ], - [ - [ - 13066, - 16039 - ], - [ - -63, - -68 - ], - [ - -138, - 33 - ], - [ - -101, - -39 - ], - [ - -8, - -72 - ] - ], - [ - [ - 12415, - 16007 - ], - [ - 36, - 72 - ], - [ - 13, - 239 - ], - [ - -72, - 125 - ], - [ - -51, - 61 - ], - [ - -107, - 46 - ], - [ - -7, - 88 - ], - [ - 91, - 26 - ], - [ - 117, - -31 - ], - [ - -22, - 136 - ], - [ - 66, - -52 - ], - [ - 162, - 94 - ], - [ - 21, - 98 - ], - [ - 61, - 24 - ] - ], - [ - [ - 8747, - 11075 - ], - [ - 17, - 51 - ], - [ - 6, - 54 - ], - [ - 12, - 52 - ], - [ - -27, - 71 - ], - [ - -5, - 82 - ], - [ - 36, - 103 - ] - ], - [ - [ - 8786, - 11488 - ], - [ - 24, - -13 - ], - [ - 51, - -29 - ], - [ - 74, - -101 - ], - [ - 12, - -49 - ] - ], - [ - [ - 13214, - 15854 - ], - [ - -23, - -92 - ], - [ - -32, - 24 - ], - [ - -16, - 81 - ], - [ - 14, - 44 - ], - [ - 45, - 46 - ], - [ - 12, - -103 - ] - ], - [ - [ - 13321, - 10320 - ], - [ - -72, - 121 - ], - [ - -46, - 99 - ], - [ - -42, - 124 - ], - [ - 2, - 40 - ], - [ - 15, - 38 - ], - [ - 17, - 87 - ], - [ - 14, - 89 - ] - ], - [ - [ - 13209, - 10918 - ], - [ - 24, - 7 - ], - [ - 101, - -1 - ], - [ - 0, - 144 - ] - ], - [ - [ - 12115, - 17260 - ], - [ - -52, - 24 - ], - [ - -43, - -1 - ], - [ - 14, - 64 - ], - [ - -14, - 64 - ] - ], - [ - [ - 12020, - 17411 - ], - [ - 58, - 5 - ], - [ - 75, - -74 - ], - [ - -38, - -82 - ] - ], - [ - [ - 12338, - 17832 - ], - [ - -74, - -130 - ], - [ - 71, - 16 - ], - [ - 76, - 0 - ], - [ - -18, - -98 - ], - [ - -63, - -108 - ], - [ - 72, - -7 - ], - [ - 6, - -13 - ], - [ - 62, - -142 - ], - [ - 47, - -19 - ], - [ - 43, - -136 - ], - [ - 20, - -48 - ], - [ - 85, - -23 - ], - [ - -9, - -76 - ], - [ - -35, - -36 - ], - [ - 28, - -62 - ], - [ - -63, - -63 - ], - [ - -93, - 2 - ], - [ - -119, - -33 - ], - [ - -33, - 23 - ], - [ - -46, - -56 - ], - [ - -64, - 14 - ], - [ - -49, - -46 - ], - [ - -37, - 24 - ], - [ - 102, - 126 - ], - [ - 62, - 26 - ], - [ - 0, - 0 - ], - [ - -109, - 20 - ], - [ - -20, - 48 - ], - [ - 73, - 37 - ], - [ - -38, - 64 - ], - [ - 13, - 79 - ], - [ - 104, - -11 - ], - [ - 10, - 70 - ], - [ - -46, - 74 - ], - [ - -2, - 1 - ], - [ - -84, - 21 - ], - [ - -17, - 33 - ], - [ - 26, - 53 - ], - [ - -23, - 34 - ], - [ - -38, - -57 - ], - [ - -4, - 115 - ], - [ - -35, - 62 - ], - [ - 25, - 124 - ], - [ - 54, - 97 - ], - [ - 56, - -10 - ], - [ - 84, - 11 - ] - ], - [ - [ - 15586, - 15727 - ], - [ - -68, - 59 - ], - [ - -74, - -6 - ] - ], - [ - [ - 15444, - 15780 - ], - [ - 11, - 51 - ], - [ - -18, - 82 - ], - [ - -40, - 44 - ], - [ - -39, - 14 - ], - [ - -25, - 37 - ] - ], - [ - [ - 15333, - 16008 - ], - [ - 8, - 14 - ], - [ - 59, - -20 - ], - [ - 103, - -20 - ], - [ - 95, - -57 - ], - [ - 12, - -23 - ], - [ - 42, - 19 - ], - [ - 65, - -25 - ], - [ - 21, - -49 - ], - [ - 44, - -28 - ] - ], - [ - [ - 12549, - 12119 - ], - [ - -5, - -37 - ], - [ - 29, - -62 - ], - [ - 0, - -87 - ], - [ - 7, - -95 - ], - [ - 17, - -44 - ], - [ - -15, - -108 - ], - [ - 5, - -59 - ], - [ - 19, - -76 - ], - [ - 15, - -43 - ] - ], - [ - [ - 12621, - 11508 - ], - [ - -109, - -70 - ], - [ - -39, - -41 - ], - [ - -62, - -35 - ], - [ - -63, - 34 - ] - ], - [ - [ - 11959, - 11719 - ], - [ - -20, - 3 - ], - [ - -14, - -48 - ], - [ - -19, - 1 - ], - [ - -14, - 25 - ], - [ - 5, - 48 - ], - [ - -30, - 74 - ], - [ - -18, - -14 - ], - [ - -15, - -2 - ] - ], - [ - [ - 11834, - 11806 - ], - [ - -19, - -7 - ], - [ - 1, - 44 - ], - [ - -11, - 31 - ], - [ - 2, - 35 - ], - [ - -15, - 50 - ], - [ - -19, - 43 - ], - [ - -56, - 1 - ], - [ - -16, - -23 - ], - [ - -20, - -3 - ], - [ - -12, - -26 - ], - [ - -8, - -33 - ], - [ - -37, - -53 - ] - ], - [ - [ - 11624, - 11865 - ], - [ - -30, - 71 - ], - [ - -28, - 47 - ], - [ - -17, - 16 - ], - [ - -18, - 24 - ], - [ - -8, - 53 - ], - [ - -10, - 26 - ], - [ - -20, - 20 - ] - ], - [ - [ - 11493, - 12122 - ], - [ - 31, - 58 - ], - [ - 21, - -2 - ], - [ - 18, - 20 - ], - [ - 15, - 0 - ], - [ - 11, - 16 - ], - [ - -5, - 40 - ], - [ - 7, - 12 - ], - [ - 1, - 41 - ] - ], - [ - [ - 11592, - 12307 - ], - [ - 34, - -1 - ], - [ - 50, - -29 - ], - [ - 16, - 2 - ], - [ - 5, - 14 - ], - [ - 38, - -10 - ], - [ - 10, - 7 - ] - ], - [ - [ - 11745, - 12290 - ], - [ - 4, - -44 - ], - [ - 11, - 0 - ], - [ - 18, - 16 - ], - [ - 12, - -4 - ], - [ - 19, - -30 - ], - [ - 30, - -10 - ], - [ - 19, - 26 - ], - [ - 23, - 16 - ], - [ - 16, - 17 - ], - [ - 14, - -3 - ], - [ - 16, - -27 - ], - [ - 8, - -33 - ], - [ - 29, - -50 - ], - [ - -15, - -31 - ], - [ - -2, - -39 - ], - [ - 14, - 12 - ], - [ - 9, - -14 - ], - [ - -4, - -36 - ], - [ - 22, - -34 - ] - ], - [ - [ - 11374, - 12375 - ], - [ - 8, - 53 - ] - ], - [ - [ - 11382, - 12428 - ], - [ - 76, - 4 - ], - [ - 16, - 28 - ], - [ - 22, - 2 - ], - [ - 28, - -30 - ], - [ - 21, - 0 - ], - [ - 23, - 20 - ], - [ - 14, - -35 - ], - [ - -30, - -27 - ], - [ - -30, - 3 - ], - [ - -30, - 25 - ], - [ - -26, - -28 - ], - [ - -12, - -1 - ], - [ - -17, - -17 - ], - [ - -63, - 3 - ] - ], - [ - [ - 11493, - 12122 - ], - [ - -37, - 50 - ], - [ - -30, - 8 - ], - [ - -16, - 34 - ], - [ - 1, - 18 - ], - [ - -22, - 25 - ], - [ - -4, - 26 - ] - ], - [ - [ - 11385, - 12283 - ], - [ - 37, - 20 - ], - [ - 23, - -4 - ], - [ - 19, - 13 - ], - [ - 128, - -5 - ] - ], - [ - [ - 13209, - 10918 - ], - [ - -13, - 18 - ], - [ - 24, - 135 - ] - ], - [ - [ - 14013, - 15697 - ], - [ - 45, - 11 - ], - [ - 27, - 26 - ], - [ - 38, - -2 - ], - [ - 11, - 20 - ], - [ - 13, - 4 - ] - ], - [ - [ - 14368, - 15815 - ], - [ - 34, - -32 - ], - [ - -22, - -75 - ], - [ - -16, - -13 - ] - ], - [ - [ - 14364, - 15695 - ], - [ - -43, - 3 - ], - [ - -36, - 12 - ], - [ - -84, - -32 - ], - [ - 48, - -67 - ], - [ - -35, - -20 - ], - [ - -39, - 0 - ], - [ - -37, - 62 - ], - [ - -13, - -26 - ], - [ - 15, - -72 - ], - [ - 35, - -56 - ], - [ - -26, - -27 - ], - [ - 39, - -55 - ], - [ - 34, - -35 - ], - [ - 1, - -67 - ], - [ - -64, - 31 - ], - [ - 20, - -61 - ], - [ - -44, - -12 - ], - [ - 27, - -106 - ], - [ - -47, - -2 - ], - [ - -57, - 52 - ], - [ - -26, - 96 - ], - [ - -12, - 80 - ], - [ - -27, - 55 - ], - [ - -36, - 69 - ], - [ - -5, - 34 - ] - ], - [ - [ - 14200, - 15081 - ], - [ - 38, - -41 - ], - [ - 54, - 7 - ], - [ - 52, - -8 - ], - [ - -2, - -21 - ], - [ - 38, - 14 - ], - [ - -9, - -35 - ], - [ - -100, - -10 - ], - [ - 1, - 19 - ], - [ - -85, - 24 - ], - [ - 13, - 51 - ] - ], - [ - [ - 9288, - 20710 - ], - [ - 234, - 72 - ], - [ - 244, - -6 - ], - [ - 89, - 44 - ], - [ - 247, - 12 - ], - [ - 556, - -15 - ], - [ - 436, - -95 - ], - [ - -128, - -46 - ], - [ - -267, - -6 - ], - [ - -375, - -11 - ], - [ - 35, - -22 - ], - [ - 247, - 13 - ], - [ - 210, - -41 - ], - [ - 135, - 37 - ], - [ - 58, - -43 - ], - [ - -77, - -70 - ], - [ - 178, - 45 - ], - [ - 338, - 46 - ], - [ - 209, - -23 - ], - [ - 39, - -51 - ], - [ - -284, - -86 - ], - [ - -39, - -27 - ], - [ - -223, - -21 - ], - [ - 162, - -6 - ], - [ - -82, - -87 - ], - [ - -56, - -78 - ], - [ - 2, - -134 - ], - [ - 84, - -78 - ], - [ - -109, - -5 - ], - [ - -115, - -38 - ], - [ - 129, - -63 - ], - [ - 16, - -102 - ], - [ - -74, - -11 - ], - [ - 90, - -104 - ], - [ - -155, - -8 - ], - [ - 81, - -49 - ], - [ - -23, - -42 - ], - [ - -98, - -19 - ], - [ - -97, - 0 - ], - [ - 87, - -82 - ], - [ - 1, - -53 - ], - [ - -138, - 50 - ], - [ - -36, - -32 - ], - [ - 94, - -30 - ], - [ - 92, - -74 - ], - [ - 26, - -96 - ], - [ - -124, - -23 - ], - [ - -54, - 46 - ], - [ - -86, - 69 - ], - [ - 24, - -82 - ], - [ - -81, - -63 - ], - [ - 184, - -5 - ], - [ - 96, - -6 - ], - [ - -187, - -105 - ], - [ - -190, - -94 - ], - [ - -204, - -42 - ], - [ - -77, - 0 - ], - [ - -72, - -47 - ], - [ - -97, - -126 - ], - [ - -150, - -84 - ], - [ - -48, - -5 - ], - [ - -93, - -30 - ], - [ - -100, - -28 - ], - [ - -59, - -74 - ], - [ - -1, - -84 - ], - [ - -36, - -79 - ], - [ - -113, - -96 - ], - [ - 28, - -94 - ], - [ - -32, - -99 - ], - [ - -35, - -117 - ], - [ - -99, - -7 - ], - [ - -102, - 98 - ], - [ - -140, - 0 - ], - [ - -67, - 66 - ], - [ - -47, - 117 - ], - [ - -121, - 149 - ], - [ - -35, - 79 - ], - [ - -10, - 107 - ], - [ - -96, - 111 - ], - [ - 25, - 88 - ], - [ - -47, - 43 - ], - [ - 69, - 140 - ], - [ - 105, - 45 - ], - [ - 28, - 50 - ], - [ - 14, - 94 - ], - [ - -79, - -43 - ], - [ - -38, - -18 - ], - [ - -63, - -17 - ], - [ - -85, - 39 - ], - [ - -5, - 82 - ], - [ - 27, - 64 - ], - [ - 65, - 1 - ], - [ - 142, - -32 - ], - [ - -120, - 77 - ], - [ - -62, - 41 - ], - [ - -69, - -17 - ], - [ - -59, - 29 - ], - [ - 78, - 112 - ], - [ - -42, - 45 - ], - [ - -56, - 83 - ], - [ - -83, - 127 - ], - [ - -89, - 47 - ], - [ - 1, - 50 - ], - [ - -187, - 70 - ], - [ - -148, - 9 - ], - [ - -187, - -5 - ], - [ - -170, - -9 - ], - [ - -81, - 38 - ], - [ - -121, - 76 - ], - [ - 183, - 38 - ], - [ - 140, - 6 - ], - [ - -298, - 31 - ], - [ - -157, - 49 - ], - [ - 10, - 47 - ], - [ - 264, - 57 - ], - [ - 255, - 58 - ], - [ - 27, - 44 - ], - [ - -188, - 43 - ], - [ - 60, - 48 - ], - [ - 242, - 83 - ], - [ - 101, - 13 - ], - [ - -29, - 54 - ], - [ - 165, - 32 - ], - [ - 215, - 19 - ], - [ - 214, - 1 - ], - [ - 76, - -38 - ], - [ - 185, - 66 - ], - [ - 166, - -45 - ], - [ - 98, - -9 - ], - [ - 145, - -39 - ], - [ - -166, - 65 - ], - [ - 10, - 51 - ] - ], - [ - [ - 6348, - 12703 - ], - [ - 23, - -22 - ], - [ - 6, - 18 - ], - [ - 20, - -15 - ] - ], - [ - [ - 6397, - 12684 - ], - [ - -31, - -46 - ], - [ - -33, - -33 - ], - [ - -5, - -23 - ], - [ - 5, - -24 - ], - [ - -14, - -30 - ] - ], - [ - [ - 6319, - 12528 - ], - [ - -16, - -8 - ], - [ - 3, - -14 - ], - [ - -13, - -13 - ], - [ - -24, - -30 - ], - [ - -2, - -18 - ] - ], - [ - [ - 6267, - 12445 - ], - [ - -36, - 21 - ], - [ - -43, - 2 - ], - [ - -32, - 24 - ], - [ - -38, - 49 - ] - ], - [ - [ - 6118, - 12541 - ], - [ - 2, - 35 - ], - [ - 8, - 28 - ], - [ - -10, - 23 - ], - [ - 34, - 98 - ], - [ - 89, - 0 - ], - [ - 2, - 41 - ], - [ - -11, - 7 - ], - [ - -8, - 26 - ], - [ - -26, - 28 - ], - [ - -26, - 40 - ], - [ - 32, - 0 - ], - [ - 0, - 68 - ], - [ - 65, - 0 - ], - [ - 64, - -1 - ] - ], - [ - [ - 8314, - 11421 - ], - [ - -47, - 91 - ], - [ - 19, - 33 - ], - [ - -2, - 56 - ], - [ - 43, - 19 - ], - [ - 17, - 22 - ], - [ - -23, - 45 - ], - [ - 6, - 44 - ], - [ - 55, - 70 - ] - ], - [ - [ - 8382, - 11801 - ], - [ - 46, - -44 - ], - [ - 43, - -78 - ], - [ - 2, - -62 - ], - [ - 26, - -3 - ], - [ - 37, - -58 - ], - [ - 28, - -42 - ] - ], - [ - [ - 8564, - 11514 - ], - [ - -11, - -108 - ], - [ - -43, - -31 - ], - [ - 4, - -29 - ], - [ - -13, - -62 - ], - [ - 31, - -87 - ], - [ - 23, - 0 - ], - [ - 9, - -68 - ], - [ - 42, - -104 - ] - ], - [ - [ - 6397, - 12684 - ], - [ - 8, - -5 - ], - [ - 15, - 21 - ], - [ - 20, - 2 - ], - [ - 6, - -10 - ], - [ - 11, - 6 - ], - [ - 33, - -10 - ], - [ - 32, - 3 - ], - [ - 22, - 13 - ], - [ - 8, - 13 - ], - [ - 23, - -6 - ], - [ - 16, - -8 - ], - [ - 19, - 3 - ], - [ - 13, - 10 - ], - [ - 32, - -16 - ], - [ - 11, - -3 - ], - [ - 22, - -23 - ], - [ - 20, - -26 - ], - [ - 25, - -19 - ], - [ - 18, - -33 - ] - ], - [ - [ - 6751, - 12596 - ], - [ - -23, - 3 - ], - [ - -10, - -17 - ], - [ - -24, - -15 - ], - [ - -18, - 0 - ], - [ - -15, - -16 - ], - [ - -14, - 6 - ], - [ - -12, - 18 - ], - [ - -7, - -3 - ], - [ - -9, - -29 - ], - [ - -7, - 1 - ], - [ - -1, - -25 - ], - [ - -25, - -33 - ], - [ - -12, - -14 - ], - [ - -8, - -15 - ], - [ - -20, - 24 - ], - [ - -15, - -32 - ], - [ - -15, - 1 - ], - [ - -16, - -3 - ], - [ - 1, - -59 - ], - [ - -10, - -1 - ], - [ - -9, - -27 - ], - [ - -21, - -5 - ] - ], - [ - [ - 6461, - 12355 - ], - [ - -12, - 37 - ], - [ - -21, - 11 - ] - ], - [ - [ - 6428, - 12403 - ], - [ - 4, - 48 - ], - [ - -9, - 13 - ], - [ - -14, - 9 - ], - [ - -31, - -15 - ], - [ - -3, - 16 - ], - [ - -21, - 20 - ], - [ - -15, - 24 - ], - [ - -20, - 10 - ] - ], - [ - [ - 13841, - 15914 - ], - [ - -7, - -21 - ] - ], - [ - [ - 13834, - 15893 - ], - [ - -66, - 45 - ], - [ - -40, - 43 - ], - [ - -64, - 36 - ], - [ - -59, - 88 - ], - [ - 14, - 9 - ], - [ - -31, - 50 - ], - [ - -2, - 41 - ], - [ - -45, - 19 - ], - [ - -21, - -52 - ], - [ - -20, - 40 - ], - [ - 1, - 42 - ], - [ - 3, - 2 - ] - ], - [ - [ - 13504, - 16256 - ], - [ - 48, - -4 - ], - [ - 13, - 20 - ], - [ - 24, - -20 - ], - [ - 27, - -2 - ], - [ - 0, - 34 - ], - [ - 24, - 12 - ], - [ - 7, - 48 - ], - [ - 55, - 32 - ] - ], - [ - [ - 13702, - 16376 - ], - [ - 22, - -15 - ], - [ - 52, - -51 - ], - [ - 58, - -23 - ], - [ - 26, - 18 - ] - ], - [ - [ - 13860, - 16305 - ], - [ - 17, - -47 - ], - [ - 22, - -34 - ], - [ - -27, - -45 - ] - ], - [ - [ - 7549, - 12962 - ], - [ - -46, - 20 - ], - [ - -33, - -8 - ], - [ - -43, - 9 - ], - [ - -33, - -23 - ], - [ - -37, - 38 - ], - [ - 6, - 38 - ], - [ - 64, - -16 - ], - [ - 53, - -10 - ], - [ - 25, - 27 - ], - [ - -32, - 52 - ], - [ - 1, - 46 - ], - [ - -44, - 18 - ], - [ - 16, - 33 - ], - [ - 42, - -5 - ], - [ - 61, - -19 - ] - ], - [ - [ - 13731, - 16571 - ], - [ - 36, - -31 - ], - [ - 25, - -13 - ], - [ - 59, - 14 - ], - [ - 5, - 25 - ], - [ - 28, - 3 - ], - [ - 34, - 19 - ], - [ - 8, - -8 - ], - [ - 32, - 15 - ], - [ - 17, - 28 - ], - [ - 23, - 8 - ], - [ - 74, - -37 - ], - [ - 15, - 12 - ] - ], - [ - [ - 14087, - 16606 - ], - [ - 39, - -32 - ], - [ - 5, - -32 - ] - ], - [ - [ - 14131, - 16542 - ], - [ - -43, - -26 - ], - [ - -33, - -81 - ], - [ - -42, - -81 - ], - [ - -56, - -23 - ] - ], - [ - [ - 13957, - 16331 - ], - [ - -43, - 5 - ], - [ - -54, - -31 - ] - ], - [ - [ - 13702, - 16376 - ], - [ - -13, - 41 - ], - [ - -12, - 1 - ] - ], - [ - [ - 20962, - 9569 - ], - [ - -29, - -3 - ], - [ - -92, - 85 - ], - [ - 65, - 23 - ], - [ - 36, - -36 - ], - [ - 25, - -37 - ], - [ - -5, - -32 - ] - ], - [ - [ - 21259, - 9730 - ], - [ - 7, - -23 - ], - [ - 1, - -37 - ] - ], - [ - [ - 21267, - 9670 - ], - [ - -45, - -89 - ], - [ - -60, - -27 - ], - [ - -8, - 15 - ], - [ - 6, - 40 - ], - [ - 30, - 74 - ], - [ - 69, - 47 - ] - ], - [ - [ - 20766, - 9826 - ], - [ - 25, - -32 - ], - [ - 43, - 10 - ], - [ - 18, - -51 - ], - [ - -81, - -24 - ], - [ - -48, - -16 - ], - [ - -38, - 1 - ], - [ - 24, - 69 - ], - [ - 38, - 1 - ], - [ - 19, - 42 - ] - ], - [ - [ - 21115, - 9826 - ], - [ - -10, - -67 - ], - [ - -105, - -34 - ], - [ - -93, - 15 - ], - [ - 0, - 44 - ], - [ - 55, - 25 - ], - [ - 44, - -36 - ], - [ - 46, - 9 - ], - [ - 63, - 44 - ] - ], - [ - [ - 20119, - 9984 - ], - [ - 134, - -12 - ], - [ - 15, - 50 - ], - [ - 130, - -58 - ], - [ - 25, - -78 - ], - [ - 105, - -22 - ], - [ - 85, - -71 - ], - [ - -79, - -46 - ], - [ - -77, - 49 - ], - [ - -63, - -4 - ], - [ - -72, - 9 - ], - [ - -66, - 22 - ], - [ - -80, - 46 - ], - [ - -52, - 11 - ], - [ - -29, - -15 - ], - [ - -127, - 50 - ], - [ - -12, - 51 - ], - [ - -64, - 9 - ], - [ - 48, - 115 - ], - [ - 85, - -7 - ], - [ - 56, - -47 - ], - [ - 29, - -9 - ], - [ - 9, - -43 - ] - ], - [ - [ - 21939, - 10052 - ], - [ - -36, - -82 - ], - [ - -7, - 90 - ], - [ - 13, - 43 - ], - [ - 14, - 41 - ], - [ - 16, - -35 - ], - [ - 0, - -57 - ] - ], - [ - [ - 21418, - 10382 - ], - [ - -26, - -40 - ], - [ - -48, - 22 - ], - [ - -14, - 52 - ], - [ - 71, - 6 - ], - [ - 17, - -40 - ] - ], - [ - [ - 21642, - 10426 - ], - [ - 26, - -92 - ], - [ - -59, - 50 - ], - [ - -58, - 10 - ], - [ - -40, - -8 - ], - [ - -48, - 4 - ], - [ - 17, - 66 - ], - [ - 86, - 5 - ], - [ - 76, - -35 - ] - ], - [ - [ - 22376, - 10485 - ], - [ - 2, - -391 - ], - [ - 1, - -391 - ] - ], - [ - [ - 22379, - 9703 - ], - [ - -62, - 99 - ], - [ - -71, - 24 - ], - [ - -17, - -34 - ], - [ - -89, - -4 - ], - [ - 30, - 98 - ], - [ - 44, - 33 - ], - [ - -18, - 130 - ], - [ - -34, - 101 - ], - [ - -135, - 102 - ], - [ - -57, - 10 - ], - [ - -105, - 111 - ], - [ - -21, - -59 - ], - [ - -26, - -10 - ], - [ - -16, - 44 - ], - [ - 0, - 52 - ], - [ - -54, - 59 - ], - [ - 75, - 43 - ], - [ - 50, - -2 - ], - [ - -6, - 32 - ], - [ - -102, - 0 - ], - [ - -27, - 71 - ], - [ - -63, - 22 - ], - [ - -29, - 60 - ], - [ - 94, - 29 - ], - [ - 35, - 39 - ], - [ - 112, - -49 - ], - [ - 11, - -45 - ], - [ - 20, - -194 - ], - [ - 72, - -72 - ], - [ - 58, - 127 - ], - [ - 80, - 73 - ], - [ - 62, - 0 - ], - [ - 60, - -42 - ], - [ - 52, - -43 - ], - [ - 74, - -23 - ] - ], - [ - [ - 21278, - 10968 - ], - [ - -56, - -119 - ], - [ - -53, - -24 - ], - [ - -67, - 24 - ], - [ - -116, - -6 - ], - [ - -61, - -17 - ], - [ - -10, - -91 - ], - [ - 63, - -107 - ], - [ - 37, - 55 - ], - [ - 130, - 40 - ], - [ - -5, - -55 - ], - [ - -31, - 18 - ], - [ - -30, - -71 - ], - [ - -61, - -46 - ], - [ - 66, - -154 - ], - [ - -13, - -41 - ], - [ - 63, - -139 - ], - [ - -1, - -79 - ], - [ - -37, - -35 - ], - [ - -28, - 42 - ], - [ - 34, - 99 - ], - [ - -68, - -47 - ], - [ - -18, - 33 - ], - [ - 9, - 47 - ], - [ - -50, - 70 - ], - [ - 5, - 117 - ], - [ - -46, - -37 - ], - [ - 6, - -139 - ], - [ - 3, - -172 - ], - [ - -45, - -17 - ], - [ - -30, - 35 - ], - [ - 20, - 110 - ], - [ - -10, - 116 - ], - [ - -30, - 1 - ], - [ - -21, - 82 - ], - [ - 28, - 79 - ], - [ - 10, - 95 - ], - [ - 35, - 181 - ], - [ - 15, - 49 - ], - [ - 59, - 89 - ], - [ - 55, - -35 - ], - [ - 88, - -17 - ], - [ - 80, - 5 - ], - [ - 69, - 87 - ], - [ - 12, - -26 - ] - ], - [ - [ - 21518, - 10933 - ], - [ - -4, - -105 - ], - [ - -35, - 12 - ], - [ - -11, - -73 - ], - [ - 29, - -63 - ], - [ - -20, - -15 - ], - [ - -28, - 76 - ], - [ - -21, - 154 - ], - [ - 14, - 95 - ], - [ - 23, - 44 - ], - [ - 5, - -65 - ], - [ - 42, - -11 - ], - [ - 6, - -49 - ] - ], - [ - [ - 20192, - 11038 - ], - [ - 12, - -80 - ], - [ - 47, - -68 - ], - [ - 45, - 24 - ], - [ - 45, - -8 - ], - [ - 40, - 60 - ], - [ - 34, - 11 - ], - [ - 66, - -34 - ], - [ - 57, - 26 - ], - [ - 35, - 167 - ], - [ - 27, - 41 - ], - [ - 24, - 137 - ], - [ - 80, - 0 - ], - [ - 61, - -20 - ] - ], - [ - [ - 20765, - 11294 - ], - [ - -40, - -109 - ], - [ - 51, - -113 - ], - [ - -12, - -56 - ], - [ - 79, - -111 - ], - [ - -83, - -14 - ], - [ - -23, - -82 - ], - [ - 3, - -108 - ], - [ - -67, - -82 - ], - [ - -2, - -120 - ], - [ - -27, - -183 - ], - [ - -10, - 42 - ], - [ - -79, - -54 - ], - [ - -28, - 74 - ], - [ - -50, - 7 - ], - [ - -35, - 38 - ], - [ - -82, - -43 - ], - [ - -26, - 58 - ], - [ - -46, - -7 - ], - [ - -57, - 14 - ], - [ - -11, - 161 - ], - [ - -34, - 33 - ], - [ - -34, - 103 - ], - [ - -10, - 105 - ], - [ - 9, - 111 - ], - [ - 41, - 80 - ] - ], - [ - [ - 19924, - 10095 - ], - [ - -77, - -2 - ], - [ - -59, - 100 - ], - [ - -90, - 98 - ], - [ - -29, - 73 - ], - [ - -53, - 97 - ], - [ - -35, - 90 - ], - [ - -53, - 168 - ], - [ - -61, - 100 - ], - [ - -20, - 103 - ], - [ - -26, - 94 - ], - [ - -63, - 75 - ], - [ - -36, - 103 - ], - [ - -53, - 67 - ], - [ - -73, - 133 - ], - [ - -6, - 61 - ], - [ - 45, - -5 - ], - [ - 108, - -23 - ], - [ - 62, - -118 - ], - [ - 54, - -81 - ], - [ - 38, - -50 - ], - [ - 66, - -129 - ], - [ - 71, - -2 - ], - [ - 58, - -82 - ], - [ - 41, - -100 - ], - [ - 53, - -55 - ], - [ - -28, - -98 - ], - [ - 40, - -42 - ], - [ - 25, - -3 - ], - [ - 12, - -84 - ], - [ - 24, - -67 - ], - [ - 51, - -10 - ], - [ - 34, - -76 - ], - [ - -17, - -149 - ], - [ - -3, - -186 - ] - ], - [ - [ - 18754, - 13443 - ], - [ - -10, - -44 - ], - [ - -48, - 2 - ], - [ - -86, - -25 - ], - [ - 4, - -90 - ], - [ - -37, - -71 - ], - [ - -100, - -81 - ], - [ - -78, - -141 - ], - [ - -53, - -76 - ], - [ - -69, - -78 - ], - [ - 0, - -56 - ], - [ - -35, - -29 - ], - [ - -63, - -43 - ], - [ - -32, - -6 - ], - [ - -21, - -92 - ], - [ - 14, - -156 - ], - [ - 4, - -99 - ], - [ - -29, - -114 - ], - [ - -1, - -204 - ], - [ - -36, - -6 - ], - [ - -32, - -92 - ], - [ - 22, - -39 - ], - [ - -64, - -34 - ], - [ - -23, - -82 - ], - [ - -28, - -34 - ], - [ - -66, - 112 - ], - [ - -33, - 168 - ], - [ - -26, - 121 - ], - [ - -25, - 57 - ], - [ - -37, - 115 - ], - [ - -17, - 150 - ], - [ - -12, - 75 - ], - [ - -64, - 165 - ], - [ - -28, - 232 - ], - [ - -21, - 154 - ], - [ - 0, - 145 - ], - [ - -14, - 112 - ], - [ - -101, - -72 - ], - [ - -49, - 15 - ], - [ - -91, - 145 - ], - [ - 33, - 44 - ], - [ - -20, - 47 - ], - [ - -82, - 101 - ] - ], - [ - [ - 17300, - 13639 - ], - [ - 46, - 81 - ], - [ - 154, - -1 - ], - [ - -14, - 103 - ], - [ - -39, - 61 - ], - [ - -8, - 92 - ], - [ - -46, - 54 - ], - [ - 77, - 126 - ], - [ - 81, - -9 - ], - [ - 73, - 126 - ], - [ - 44, - 121 - ], - [ - 67, - 121 - ], - [ - -1, - 85 - ], - [ - 60, - 70 - ], - [ - -57, - 59 - ], - [ - -24, - 81 - ], - [ - -25, - 105 - ], - [ - 35, - 52 - ], - [ - 105, - -29 - ], - [ - 78, - 18 - ], - [ - 67, - 100 - ] - ], - [ - [ - 18202, - 14418 - ], - [ - -45, - -54 - ], - [ - -27, - -112 - ], - [ - 68, - -46 - ], - [ - 66, - -59 - ], - [ - 91, - -67 - ], - [ - 95, - -15 - ], - [ - 40, - -61 - ], - [ - 54, - -12 - ], - [ - 84, - -28 - ], - [ - 58, - 2 - ], - [ - 8, - 48 - ], - [ - -9, - 76 - ], - [ - 5, - 52 - ] - ], - [ - [ - 19332, - 14188 - ], - [ - 5, - -46 - ], - [ - -24, - -22 - ], - [ - 6, - -74 - ], - [ - -50, - 22 - ], - [ - -91, - -83 - ], - [ - 3, - -68 - ], - [ - -39, - -101 - ], - [ - -3, - -59 - ], - [ - -31, - -98 - ], - [ - -55, - 27 - ], - [ - -3, - -124 - ], - [ - -15, - -41 - ], - [ - 7, - -51 - ], - [ - -34, - -29 - ] - ], - [ - [ - 12115, - 17260 - ], - [ - 12, - -86 - ], - [ - -53, - -107 - ], - [ - -123, - -71 - ], - [ - -99, - 18 - ], - [ - 57, - 125 - ], - [ - -37, - 122 - ], - [ - 95, - 94 - ], - [ - 53, - 56 - ] - ], - [ - [ - 16791, - 14376 - ], - [ - 34, - -63 - ], - [ - 29, - -73 - ], - [ - 66, - -53 - ], - [ - 2, - -105 - ], - [ - 33, - -20 - ], - [ - 6, - -55 - ], - [ - -100, - -62 - ], - [ - -27, - -139 - ] - ], - [ - [ - 16834, - 13806 - ], - [ - -131, - 36 - ], - [ - -76, - 28 - ], - [ - -78, - 15 - ], - [ - -30, - 147 - ], - [ - -34, - 22 - ], - [ - -53, - -22 - ], - [ - -70, - -58 - ], - [ - -86, - 40 - ], - [ - -70, - 92 - ], - [ - -67, - 34 - ], - [ - -47, - 114 - ], - [ - -51, - 160 - ], - [ - -38, - -19 - ], - [ - -44, - 39 - ], - [ - -26, - -47 - ] - ], - [ - [ - 15933, - 14387 - ], - [ - -38, - 64 - ], - [ - -1, - 63 - ], - [ - -22, - 0 - ], - [ - 11, - 87 - ], - [ - -36, - 91 - ], - [ - -85, - 66 - ], - [ - -49, - 114 - ], - [ - 17, - 94 - ], - [ - 35, - 41 - ], - [ - -6, - 70 - ], - [ - -45, - 36 - ], - [ - -45, - 143 - ] - ], - [ - [ - 15669, - 15256 - ], - [ - -39, - 97 - ], - [ - 14, - 37 - ], - [ - -22, - 137 - ], - [ - 48, - 35 - ] - ], - [ - [ - 15955, - 15394 - ], - [ - 22, - -88 - ], - [ - 66, - -25 - ], - [ - 49, - -60 - ], - [ - 99, - -21 - ], - [ - 109, - 32 - ], - [ - 6, - 28 - ] - ], - [ - [ - 16306, - 15260 - ], - [ - 62, - 23 - ], - [ - 49, - 69 - ], - [ - 47, - -4 - ], - [ - 30, - 23 - ], - [ - 50, - -11 - ], - [ - 77, - -61 - ], - [ - 56, - -13 - ], - [ - 79, - -107 - ], - [ - 52, - -4 - ], - [ - 6, - -101 - ] - ], - [ - [ - 15933, - 14387 - ], - [ - -41, - 6 - ] - ], - [ - [ - 15892, - 14393 - ], - [ - -47, - 10 - ], - [ - -51, - -115 - ] - ], - [ - [ - 15794, - 14288 - ], - [ - -130, - 10 - ], - [ - -196, - 241 - ], - [ - -104, - 84 - ], - [ - -84, - 33 - ] - ], - [ - [ - 15280, - 14656 - ], - [ - -28, - 146 - ] - ], - [ - [ - 15252, - 14802 - ], - [ - 154, - 124 - ], - [ - 26, - 145 - ], - [ - -6, - 88 - ], - [ - 38, - 30 - ], - [ - 36, - 75 - ] - ], - [ - [ - 15500, - 15264 - ], - [ - 30, - 18 - ], - [ - 81, - -15 - ], - [ - 24, - -31 - ], - [ - 34, - 20 - ] - ], - [ - [ - 11536, - 18770 - ], - [ - -16, - -78 - ], - [ - 79, - -82 - ], - [ - -91, - -91 - ], - [ - -201, - -82 - ], - [ - -60, - -22 - ], - [ - -92, - 17 - ], - [ - -194, - 38 - ], - [ - 68, - 53 - ], - [ - -151, - 59 - ], - [ - 123, - 23 - ], - [ - -3, - 36 - ], - [ - -146, - 27 - ], - [ - 47, - 79 - ], - [ - 106, - 17 - ], - [ - 108, - -81 - ], - [ - 106, - 65 - ], - [ - 88, - -34 - ], - [ - 113, - 64 - ], - [ - 116, - -8 - ] - ], - [ - [ - 14936, - 14543 - ], - [ - 20, - 39 - ], - [ - -4, - 7 - ], - [ - 18, - 56 - ], - [ - 14, - 90 - ], - [ - 10, - 31 - ], - [ - 2, - 1 - ] - ], - [ - [ - 14996, - 14767 - ], - [ - 23, - 0 - ], - [ - 7, - 21 - ], - [ - 19, - 1 - ] - ], - [ - [ - 15045, - 14789 - ], - [ - 1, - -49 - ], - [ - -10, - -18 - ], - [ - 1, - -1 - ] - ], - [ - [ - 15037, - 14721 - ], - [ - -12, - -38 - ] - ], - [ - [ - 15025, - 14683 - ], - [ - -25, - 17 - ], - [ - -14, - -80 - ], - [ - 17, - -13 - ], - [ - -18, - -17 - ], - [ - -3, - -31 - ], - [ - 33, - 16 - ] - ], - [ - [ - 15015, - 14575 - ], - [ - 2, - -47 - ], - [ - -35, - -192 - ] - ], - [ - [ - 13510, - 16377 - ], - [ - -8, - -59 - ], - [ - 17, - -51 - ] - ], - [ - [ - 13519, - 16267 - ], - [ - -55, - 17 - ], - [ - -57, - -42 - ], - [ - 4, - -60 - ], - [ - -9, - -34 - ], - [ - 23, - -61 - ], - [ - 65, - -61 - ], - [ - 35, - -99 - ], - [ - 78, - -96 - ], - [ - 55, - 0 - ], - [ - 17, - -26 - ], - [ - -20, - -24 - ], - [ - 63, - -44 - ], - [ - 51, - -36 - ], - [ - 60, - -62 - ], - [ - 7, - -23 - ], - [ - -13, - -43 - ], - [ - -39, - 56 - ], - [ - -61, - 20 - ], - [ - -29, - -78 - ], - [ - 50, - -44 - ], - [ - -8, - -63 - ], - [ - -29, - -7 - ], - [ - -37, - -103 - ], - [ - -29, - -9 - ], - [ - 0, - 37 - ], - [ - 14, - 64 - ], - [ - 15, - 26 - ], - [ - -27, - 69 - ], - [ - -21, - 61 - ], - [ - -29, - 15 - ], - [ - -21, - 51 - ], - [ - -44, - 22 - ], - [ - -31, - 49 - ], - [ - -51, - 7 - ], - [ - -55, - 54 - ], - [ - -63, - 79 - ], - [ - -48, - 69 - ], - [ - -21, - 118 - ], - [ - -35, - 14 - ], - [ - -57, - 40 - ], - [ - -32, - -16 - ], - [ - -40, - -56 - ], - [ - -29, - -9 - ] - ], - [ - [ - 13629, - 15384 - ], - [ - -25, - -95 - ], - [ - 11, - -37 - ], - [ - -15, - -62 - ], - [ - -53, - 46 - ], - [ - -36, - 13 - ], - [ - -97, - 61 - ], - [ - 10, - 61 - ], - [ - 81, - -11 - ], - [ - 71, - 13 - ], - [ - 53, - 11 - ] - ], - [ - [ - 13190, - 15741 - ], - [ - 41, - -85 - ], - [ - -9, - -159 - ], - [ - -32, - 8 - ], - [ - -29, - -40 - ], - [ - -26, - 32 - ], - [ - -3, - 144 - ], - [ - -16, - 69 - ], - [ - 39, - -6 - ], - [ - 35, - 37 - ] - ], - [ - [ - 7140, - 13015 - ], - [ - 47, - -10 - ], - [ - 37, - -29 - ], - [ - 12, - -33 - ], - [ - -49, - -2 - ], - [ - -21, - -20 - ], - [ - -39, - 19 - ], - [ - -40, - 44 - ], - [ - 8, - 27 - ], - [ - 29, - 9 - ], - [ - 16, - -5 - ] - ], - [ - [ - 15280, - 14656 - ], - [ - -14, - -19 - ], - [ - -139, - -60 - ], - [ - 69, - -120 - ], - [ - -23, - -20 - ], - [ - -11, - -40 - ], - [ - -53, - -17 - ], - [ - -17, - -43 - ], - [ - -30, - -37 - ], - [ - -78, - 19 - ] - ], - [ - [ - 14984, - 14319 - ], - [ - -2, - 17 - ] - ], - [ - [ - 15015, - 14575 - ], - [ - 10, - 35 - ], - [ - 0, - 73 - ] - ], - [ - [ - 15037, - 14721 - ], - [ - 78, - -47 - ], - [ - 137, - 128 - ] - ], - [ - [ - 21933, - 14894 - ], - [ - 9, - -41 - ], - [ - -39, - -73 - ], - [ - -29, - 39 - ], - [ - -36, - -28 - ], - [ - -18, - -70 - ], - [ - -46, - 34 - ], - [ - 1, - 57 - ], - [ - 38, - 71 - ], - [ - 40, - -14 - ], - [ - 29, - 51 - ], - [ - 51, - -26 - ] - ], - [ - [ - 22375, - 15253 - ], - [ - -27, - -96 - ], - [ - 13, - -60 - ], - [ - -37, - -84 - ], - [ - -89, - -57 - ], - [ - -122, - -7 - ], - [ - -100, - -137 - ], - [ - -46, - 46 - ], - [ - -3, - 90 - ], - [ - -122, - -27 - ], - [ - -82, - -56 - ], - [ - -82, - -3 - ], - [ - 71, - -88 - ], - [ - -47, - -204 - ], - [ - -45, - -50 - ], - [ - -33, - 46 - ], - [ - 17, - 109 - ], - [ - -44, - 34 - ], - [ - -29, - 83 - ], - [ - 66, - 37 - ], - [ - 37, - 75 - ], - [ - 70, - 62 - ], - [ - 51, - 82 - ], - [ - 139, - 36 - ], - [ - 74, - -25 - ], - [ - 73, - 214 - ], - [ - 47, - -58 - ], - [ - 102, - 120 - ], - [ - 40, - 47 - ], - [ - 43, - 147 - ], - [ - -11, - 135 - ], - [ - 29, - 75 - ], - [ - 74, - 22 - ], - [ - 38, - -166 - ], - [ - -2, - -97 - ], - [ - -64, - -121 - ], - [ - 1, - -124 - ] - ], - [ - [ - 22579, - 16097 - ], - [ - 49, - -26 - ], - [ - 50, - 51 - ], - [ - 15, - -135 - ], - [ - -103, - -33 - ], - [ - -61, - -119 - ], - [ - -110, - 82 - ], - [ - -38, - -131 - ], - [ - -77, - -2 - ], - [ - -10, - 120 - ], - [ - 34, - 92 - ], - [ - 75, - 6 - ], - [ - 20, - 166 - ], - [ - 21, - 94 - ], - [ - 82, - -125 - ], - [ - 53, - -40 - ] - ], - [ - [ - 18142, - 15878 - ], - [ - -43, - 17 - ], - [ - -35, - 44 - ], - [ - -103, - 12 - ], - [ - -116, - 3 - ], - [ - -25, - -13 - ], - [ - -99, - 51 - ], - [ - -40, - -25 - ], - [ - -11, - -71 - ], - [ - -114, - 41 - ], - [ - -46, - -17 - ], - [ - -16, - -52 - ] - ], - [ - [ - 17494, - 15868 - ], - [ - -40, - -22 - ], - [ - -92, - -84 - ], - [ - -30, - -86 - ], - [ - -26, - -1 - ], - [ - -19, - 57 - ], - [ - -89, - 4 - ], - [ - -14, - 98 - ], - [ - -34, - 1 - ], - [ - 5, - 121 - ], - [ - -83, - 87 - ], - [ - -120, - -9 - ], - [ - -82, - -18 - ], - [ - -66, - 109 - ], - [ - -57, - 45 - ], - [ - -108, - 86 - ], - [ - -13, - 10 - ], - [ - -180, - -71 - ], - [ - 3, - -442 - ] - ], - [ - [ - 16449, - 15753 - ], - [ - -36, - -6 - ], - [ - -49, - 94 - ], - [ - -47, - 34 - ], - [ - -79, - -25 - ], - [ - -31, - -40 - ] - ], - [ - [ - 16207, - 15810 - ], - [ - -4, - 29 - ], - [ - 18, - 50 - ], - [ - -14, - 42 - ], - [ - -81, - 41 - ], - [ - -31, - 108 - ], - [ - -38, - 30 - ], - [ - -3, - 39 - ], - [ - 68, - -11 - ], - [ - 3, - 87 - ], - [ - 59, - 20 - ], - [ - 61, - -18 - ], - [ - 12, - 117 - ], - [ - -12, - 74 - ], - [ - -70, - -6 - ], - [ - -59, - 30 - ], - [ - -81, - -53 - ], - [ - -65, - -25 - ] - ], - [ - [ - 15970, - 16364 - ], - [ - -35, - 19 - ], - [ - 7, - 62 - ], - [ - -45, - 80 - ], - [ - -51, - -3 - ], - [ - -59, - 81 - ], - [ - 40, - 91 - ], - [ - -21, - 24 - ], - [ - 56, - 132 - ], - [ - 72, - -69 - ], - [ - 8, - 87 - ], - [ - 144, - 131 - ], - [ - 109, - 3 - ], - [ - 154, - -83 - ], - [ - 82, - -49 - ], - [ - 74, - 51 - ], - [ - 111, - 2 - ], - [ - 89, - -62 - ], - [ - 20, - 36 - ], - [ - 98, - -6 - ], - [ - 18, - 57 - ], - [ - -113, - 83 - ], - [ - 67, - 58 - ], - [ - -13, - 33 - ], - [ - 67, - 31 - ], - [ - -51, - 82 - ], - [ - 32, - 41 - ], - [ - 261, - 42 - ], - [ - 34, - 30 - ], - [ - 174, - 44 - ], - [ - 63, - 50 - ], - [ - 125, - -26 - ], - [ - 22, - -125 - ], - [ - 73, - 30 - ], - [ - 90, - -41 - ], - [ - -6, - -66 - ], - [ - 67, - 7 - ], - [ - 174, - 113 - ], - [ - -25, - -37 - ], - [ - 89, - -93 - ], - [ - 156, - -305 - ], - [ - 37, - 63 - ], - [ - 96, - -69 - ], - [ - 100, - 31 - ], - [ - 38, - -22 - ], - [ - 34, - -69 - ], - [ - 49, - -23 - ], - [ - 29, - -51 - ], - [ - 90, - 16 - ], - [ - 37, - -74 - ] - ], - [ - [ - 15465, - 11267 - ], - [ - -61, - -136 - ], - [ - 1, - -437 - ], - [ - 41, - -99 - ] - ], - [ - [ - 15446, - 10595 - ], - [ - -48, - -48 - ], - [ - -18, - -50 - ], - [ - -26, - -8 - ], - [ - -10, - -85 - ], - [ - -22, - -48 - ], - [ - -14, - -80 - ], - [ - -28, - -40 - ] - ], - [ - [ - 15280, - 10236 - ], - [ - -100, - 120 - ], - [ - -5, - 70 - ], - [ - -252, - 244 - ], - [ - -12, - 13 - ] - ], - [ - [ - 14911, - 10683 - ], - [ - -1, - 127 - ], - [ - 20, - 49 - ], - [ - 34, - 79 - ], - [ - 26, - 88 - ], - [ - -31, - 138 - ], - [ - -8, - 60 - ], - [ - -33, - 83 - ] - ], - [ - [ - 14918, - 11307 - ], - [ - 43, - 72 - ], - [ - 47, - 79 - ] - ], - [ - [ - 17683, - 15528 - ], - [ - -132, - -18 - ], - [ - -86, - 38 - ], - [ - -75, - -9 - ], - [ - 6, - 69 - ], - [ - 76, - -20 - ], - [ - 26, - 37 - ] - ], - [ - [ - 17498, - 15625 - ], - [ - 53, - -12 - ], - [ - 89, - 87 - ], - [ - -83, - 63 - ], - [ - -49, - -30 - ], - [ - -52, - 45 - ], - [ - 59, - 78 - ], - [ - -21, - 12 - ] - ], - [ - [ - 19699, - 12259 - ], - [ - -17, - 145 - ], - [ - 45, - 100 - ], - [ - 90, - 23 - ], - [ - 65, - -17 - ] - ], - [ - [ - 19882, - 12510 - ], - [ - 58, - -48 - ], - [ - 31, - 83 - ], - [ - 62, - -44 - ] - ], - [ - [ - 20033, - 12501 - ], - [ - 16, - -80 - ], - [ - -8, - -144 - ], - [ - -118, - -92 - ], - [ - 31, - -73 - ], - [ - -73, - -8 - ], - [ - -61, - -49 - ] - ], - [ - [ - 19820, - 12055 - ], - [ - -58, - 18 - ], - [ - -28, - 62 - ], - [ - -35, - 124 - ] - ], - [ - [ - 21495, - 15429 - ], - [ - 60, - -141 - ], - [ - 17, - -78 - ], - [ - 1, - -138 - ], - [ - -27, - -66 - ], - [ - -63, - -23 - ], - [ - -56, - -50 - ], - [ - -62, - -10 - ], - [ - -8, - 65 - ], - [ - 13, - 90 - ], - [ - -31, - 125 - ], - [ - 52, - 20 - ], - [ - -48, - 103 - ] - ], - [ - [ - 21343, - 15326 - ], - [ - 4, - 11 - ], - [ - 31, - -4 - ], - [ - 28, - 54 - ], - [ - 49, - 6 - ], - [ - 30, - 7 - ], - [ - 10, - 29 - ] - ], - [ - [ - 13947, - 15907 - ], - [ - 13, - 26 - ] - ], - [ - [ - 13960, - 15933 - ], - [ - 16, - 9 - ], - [ - 10, - 40 - ], - [ - 12, - 6 - ], - [ - 10, - -16 - ], - [ - 13, - -8 - ], - [ - 9, - -19 - ], - [ - 12, - -6 - ], - [ - 14, - -22 - ], - [ - 9, - 1 - ], - [ - -7, - -29 - ], - [ - -9, - -15 - ], - [ - 3, - -9 - ] - ], - [ - [ - 14052, - 15865 - ], - [ - -16, - -4 - ], - [ - -41, - -19 - ], - [ - -3, - -24 - ], - [ - -9, - 1 - ] - ], - [ - [ - 15892, - 14393 - ], - [ - 14, - -53 - ], - [ - -6, - -27 - ], - [ - 23, - -90 - ] - ], - [ - [ - 15923, - 14223 - ], - [ - -50, - -4 - ], - [ - -17, - 58 - ], - [ - -62, - 11 - ] - ], - [ - [ - 19670, - 13492 - ], - [ - 40, - -94 - ], - [ - 32, - -109 - ], - [ - 85, - -1 - ], - [ - 28, - -105 - ], - [ - -45, - -31 - ], - [ - -20, - -44 - ], - [ - 83, - -71 - ], - [ - 58, - -142 - ], - [ - 44, - -106 - ], - [ - 53, - -83 - ], - [ - 18, - -85 - ], - [ - -13, - -120 - ] - ], - [ - [ - 19882, - 12510 - ], - [ - 23, - 54 - ], - [ - 3, - 101 - ], - [ - -57, - 105 - ], - [ - -4, - 118 - ], - [ - -53, - 98 - ], - [ - -53, - 8 - ], - [ - -14, - -42 - ], - [ - -40, - -3 - ], - [ - -21, - 21 - ], - [ - -74, - -72 - ], - [ - -1, - 108 - ], - [ - 17, - 126 - ], - [ - -47, - 6 - ], - [ - -4, - 72 - ], - [ - -31, - 37 - ] - ], - [ - [ - 19526, - 13247 - ], - [ - 15, - 44 - ], - [ - 60, - 78 - ] - ], - [ - [ - 14996, - 14767 - ], - [ - 25, - 98 - ], - [ - 35, - 84 - ], - [ - 1, - 5 - ] - ], - [ - [ - 15057, - 14954 - ], - [ - 31, - -7 - ], - [ - 12, - -47 - ], - [ - -38, - -45 - ], - [ - -17, - -66 - ] - ], - [ - [ - 12010, - 11321 - ], - [ - -18, - -1 - ], - [ - -72, - 57 - ], - [ - -64, - 91 - ], - [ - -59, - 66 - ], - [ - -47, - 77 - ] - ], - [ - [ - 11750, - 11611 - ], - [ - 17, - 39 - ], - [ - 3, - 35 - ], - [ - 32, - 65 - ], - [ - 32, - 56 - ] - ], - [ - [ - 13208, - 14433 - ], - [ - 34, - 28 - ], - [ - 7, - 51 - ], - [ - -8, - 49 - ], - [ - 48, - 47 - ], - [ - 21, - 38 - ], - [ - 34, - 34 - ], - [ - 4, - 93 - ] - ], - [ - [ - 13348, - 14773 - ], - [ - 82, - -42 - ], - [ - 30, - 11 - ], - [ - 58, - -20 - ], - [ - 92, - -54 - ], - [ - 33, - -107 - ], - [ - 62, - -23 - ], - [ - 99, - -50 - ], - [ - 74, - -60 - ], - [ - 34, - 31 - ], - [ - 33, - 56 - ], - [ - -16, - 91 - ], - [ - 22, - 59 - ], - [ - 50, - 56 - ], - [ - 48, - 16 - ], - [ - 95, - -24 - ], - [ - 23, - -54 - ], - [ - 26, - 0 - ], - [ - 22, - -21 - ], - [ - 70, - -14 - ], - [ - 17, - -39 - ] - ], - [ - [ - 14290, - 13437 - ], - [ - 0, - -240 - ], - [ - -80, - 0 - ], - [ - -1, - -51 - ] - ], - [ - [ - 14209, - 13146 - ], - [ - -278, - 230 - ], - [ - -278, - 230 - ], - [ - -70, - -66 - ] - ], - [ - [ - 13583, - 13540 - ], - [ - -50, - -45 - ], - [ - -39, - 66 - ], - [ - -110, - 52 - ] - ], - [ - [ - 18249, - 11700 - ], - [ - -11, - -125 - ], - [ - -29, - -34 - ], - [ - -61, - -28 - ], - [ - -33, - 96 - ], - [ - -12, - 172 - ], - [ - 31, - 195 - ], - [ - 49, - -67 - ], - [ - 32, - -84 - ], - [ - 34, - -125 - ] - ], - [ - [ - 14568, - 7323 - ], - [ - 24, - -36 - ], - [ - -22, - -58 - ], - [ - -12, - -39 - ], - [ - -38, - -19 - ], - [ - -13, - -38 - ], - [ - -25, - -12 - ], - [ - -52, - 92 - ], - [ - 37, - 76 - ], - [ - 38, - 47 - ], - [ - 32, - 24 - ], - [ - 31, - -37 - ] - ], - [ - [ - 14185, - 17265 - ], - [ - -17, - 37 - ], - [ - -36, - 13 - ] - ], - [ - [ - 14132, - 17315 - ], - [ - -6, - 30 - ], - [ - 8, - 33 - ], - [ - -31, - 19 - ], - [ - -73, - 21 - ] - ], - [ - [ - 14030, - 17418 - ], - [ - -15, - 101 - ] - ], - [ - [ - 14015, - 17519 - ], - [ - 80, - 37 - ], - [ - 117, - -8 - ], - [ - 68, - 12 - ], - [ - 10, - -25 - ], - [ - 37, - -8 - ], - [ - 67, - -58 - ] - ], - [ - [ - 14015, - 17519 - ], - [ - 3, - 90 - ], - [ - 34, - 76 - ], - [ - 66, - 41 - ], - [ - 55, - -90 - ], - [ - 56, - 2 - ], - [ - 13, - 93 - ] - ], - [ - [ - 14450, - 17692 - ], - [ - 33, - -27 - ], - [ - 6, - -58 - ], - [ - 23, - -71 - ] - ], - [ - [ - 11943, - 14115 - ], - [ - -10, - 0 - ], - [ - 1, - -64 - ], - [ - -43, - -4 - ], - [ - -22, - -27 - ], - [ - -32, - 0 - ], - [ - -25, - 15 - ], - [ - -59, - -13 - ], - [ - -22, - -93 - ], - [ - -22, - -9 - ], - [ - -33, - -151 - ], - [ - -97, - -130 - ], - [ - -23, - -165 - ], - [ - -28, - -54 - ], - [ - -9, - -43 - ], - [ - -157, - -10 - ], - [ - -1, - 0 - ] - ], - [ - [ - 11361, - 13367 - ], - [ - 3, - 56 - ], - [ - 27, - 32 - ], - [ - 23, - 63 - ], - [ - -5, - 41 - ], - [ - 24, - 84 - ], - [ - 39, - 77 - ], - [ - 24, - 19 - ], - [ - 18, - 70 - ], - [ - 2, - 64 - ], - [ - 25, - 74 - ], - [ - 46, - 44 - ], - [ - 45, - 122 - ], - [ - 1, - 2 - ], - [ - 35, - 46 - ], - [ - 65, - 13 - ], - [ - 55, - 82 - ], - [ - 35, - 32 - ], - [ - 58, - 100 - ], - [ - -18, - 150 - ], - [ - 27, - 103 - ], - [ - 9, - 63 - ], - [ - 45, - 81 - ], - [ - 70, - 55 - ], - [ - 52, - 49 - ], - [ - 46, - 125 - ], - [ - 22, - 73 - ], - [ - 51, - 0 - ], - [ - 42, - -51 - ], - [ - 67, - 8 - ], - [ - 72, - -26 - ], - [ - 30, - -2 - ] - ], - [ - [ - 14403, - 16582 - ], - [ - 17, - 18 - ], - [ - 46, - 12 - ], - [ - 51, - -38 - ], - [ - 29, - -4 - ], - [ - 32, - -32 - ], - [ - -5, - -41 - ], - [ - 25, - -20 - ], - [ - 10, - -50 - ], - [ - 24, - -30 - ], - [ - -5, - -18 - ], - [ - 13, - -12 - ], - [ - -18, - -9 - ], - [ - -41, - 3 - ], - [ - -7, - 17 - ], - [ - -15, - -10 - ], - [ - 5, - -21 - ], - [ - -19, - -38 - ], - [ - -12, - -42 - ], - [ - -17, - -13 - ] - ], - [ - [ - 14516, - 16254 - ], - [ - -13, - 55 - ], - [ - 7, - 51 - ], - [ - -2, - 53 - ], - [ - -40, - 71 - ], - [ - -22, - 51 - ], - [ - -22, - 35 - ], - [ - -21, - 12 - ] - ], - [ - [ - 16001, - 9301 - ], - [ - 19, - -51 - ], - [ - 17, - -79 - ], - [ - 11, - -144 - ], - [ - 18, - -57 - ], - [ - -7, - -57 - ], - [ - -12, - -35 - ], - [ - -24, - 70 - ], - [ - -13, - -36 - ], - [ - 13, - -88 - ], - [ - -6, - -51 - ], - [ - -19, - -28 - ], - [ - -4, - -102 - ], - [ - -28, - -139 - ], - [ - -34, - -166 - ], - [ - -43, - -227 - ], - [ - -27, - -167 - ], - [ - -32, - -139 - ], - [ - -56, - -28 - ], - [ - -61, - -51 - ], - [ - -40, - 30 - ], - [ - -56, - 43 - ], - [ - -19, - 64 - ], - [ - -4, - 106 - ], - [ - -25, - 96 - ], - [ - -6, - 86 - ], - [ - 12, - 86 - ], - [ - 32, - 21 - ], - [ - 0, - 40 - ], - [ - 34, - 91 - ], - [ - 6, - 77 - ], - [ - -16, - 56 - ], - [ - -13, - 76 - ], - [ - -6, - 111 - ], - [ - 24, - 67 - ], - [ - 10, - 76 - ], - [ - 35, - 4 - ], - [ - 38, - 25 - ], - [ - 26, - 21 - ], - [ - 31, - 2 - ], - [ - 40, - 68 - ], - [ - 57, - 74 - ], - [ - 21, - 61 - ], - [ - -10, - 51 - ], - [ - 30, - -14 - ], - [ - 38, - 83 - ], - [ - 2, - 72 - ], - [ - 23, - 54 - ], - [ - 24, - -52 - ] - ], - [ - [ - 6118, - 12541 - ], - [ - -78, - 130 - ], - [ - -36, - 39 - ], - [ - -57, - 31 - ], - [ - -39, - -9 - ], - [ - -56, - -45 - ], - [ - -35, - -12 - ], - [ - -50, - 32 - ], - [ - -52, - 23 - ], - [ - -65, - 55 - ], - [ - -52, - 16 - ], - [ - -79, - 56 - ], - [ - -58, - 58 - ], - [ - -18, - 32 - ], - [ - -39, - 7 - ], - [ - -71, - 38 - ], - [ - -29, - 54 - ], - [ - -75, - 69 - ], - [ - -35, - 75 - ], - [ - -17, - 59 - ], - [ - 23, - 11 - ], - [ - -7, - 35 - ], - [ - 16, - 31 - ], - [ - 1, - 41 - ], - [ - -24, - 54 - ], - [ - -6, - 48 - ], - [ - -24, - 60 - ], - [ - -61, - 120 - ], - [ - -70, - 93 - ], - [ - -34, - 75 - ], - [ - -60, - 49 - ], - [ - -13, - 29 - ], - [ - 11, - 75 - ], - [ - -36, - 28 - ], - [ - -41, - 58 - ], - [ - -17, - 84 - ], - [ - -38, - 9 - ], - [ - -40, - 63 - ], - [ - -33, - 59 - ], - [ - -3, - 37 - ], - [ - -37, - 91 - ], - [ - -25, - 92 - ], - [ - 1, - 46 - ], - [ - -50, - 47 - ], - [ - -24, - -5 - ], - [ - -39, - 33 - ], - [ - -12, - -49 - ], - [ - 12, - -57 - ], - [ - 7, - -90 - ], - [ - 24, - -50 - ], - [ - 51, - -82 - ], - [ - 12, - -29 - ], - [ - 10, - -8 - ], - [ - 10, - -41 - ], - [ - 12, - 1 - ], - [ - 14, - -77 - ], - [ - 21, - -31 - ], - [ - 15, - -42 - ], - [ - 44, - -61 - ], - [ - 23, - -112 - ], - [ - 21, - -52 - ], - [ - 19, - -56 - ], - [ - 4, - -64 - ], - [ - 34, - -4 - ], - [ - 27, - -54 - ], - [ - 26, - -54 - ], - [ - -2, - -21 - ], - [ - -29, - -44 - ], - [ - -13, - 0 - ], - [ - -18, - 73 - ], - [ - -46, - 69 - ], - [ - -50, - 58 - ], - [ - -36, - 30 - ], - [ - 3, - 88 - ], - [ - -11, - 65 - ], - [ - -33, - 37 - ], - [ - -48, - 54 - ], - [ - -9, - -16 - ], - [ - -18, - 31 - ], - [ - -43, - 29 - ], - [ - -41, - 70 - ], - [ - 5, - 9 - ], - [ - 29, - -7 - ], - [ - 26, - 45 - ], - [ - 2, - 54 - ], - [ - -53, - 86 - ], - [ - -41, - 33 - ], - [ - -26, - 75 - ], - [ - -26, - 79 - ], - [ - -32, - 95 - ], - [ - -28, - 108 - ] - ], - [ - [ - 4383, - 14700 - ], - [ - 79, - 10 - ], - [ - 88, - 13 - ], - [ - -6, - -24 - ], - [ - 105, - -58 - ], - [ - 159, - -85 - ], - [ - 139, - 1 - ], - [ - 55, - 0 - ], - [ - 0, - 50 - ], - [ - 121, - 0 - ], - [ - 25, - -43 - ], - [ - 36, - -38 - ], - [ - 42, - -52 - ], - [ - 23, - -63 - ], - [ - 17, - -66 - ], - [ - 36, - -36 - ], - [ - 58, - -36 - ], - [ - 44, - 94 - ], - [ - 57, - 3 - ], - [ - 49, - -48 - ], - [ - 35, - -82 - ], - [ - 24, - -70 - ], - [ - 41, - -69 - ], - [ - 15, - -84 - ], - [ - 20, - -56 - ], - [ - 54, - -37 - ], - [ - 50, - -27 - ], - [ - 27, - 4 - ] - ], - [ - [ - 5776, - 13901 - ], - [ - -27, - -106 - ], - [ - -12, - -86 - ], - [ - -5, - -161 - ], - [ - -7, - -58 - ], - [ - 12, - -66 - ], - [ - 22, - -58 - ], - [ - 14, - -93 - ], - [ - 46, - -90 - ], - [ - 16, - -68 - ], - [ - 27, - -59 - ], - [ - 74, - -32 - ], - [ - 29, - -50 - ], - [ - 61, - 33 - ], - [ - 54, - 13 - ], - [ - 52, - 21 - ], - [ - 44, - 21 - ], - [ - 44, - 49 - ], - [ - 17, - 70 - ], - [ - 5, - 100 - ], - [ - 12, - 36 - ], - [ - 48, - 31 - ], - [ - 73, - 28 - ], - [ - 62, - -4 - ], - [ - 42, - 10 - ], - [ - 17, - -26 - ], - [ - -2, - -57 - ], - [ - -38, - -72 - ], - [ - -16, - -73 - ], - [ - 12, - -21 - ], - [ - -10, - -52 - ], - [ - -17, - -93 - ], - [ - -18, - 31 - ], - [ - -15, - -2 - ] - ], - [ - [ - 14052, - 15865 - ], - [ - 23, - 7 - ], - [ - 33, - 2 - ] - ], - [ - [ - 11745, - 12290 - ], - [ - 3, - 37 - ], - [ - -6, - 47 - ], - [ - -26, - 33 - ], - [ - -14, - 69 - ], - [ - -3, - 75 - ] - ], - [ - [ - 11699, - 12551 - ], - [ - 24, - 22 - ], - [ - 11, - 70 - ], - [ - 22, - 3 - ], - [ - 49, - -33 - ], - [ - 39, - 23 - ], - [ - 27, - -8 - ], - [ - 11, - 27 - ], - [ - 279, - 2 - ], - [ - 16, - 84 - ], - [ - -12, - 15 - ], - [ - -34, - 517 - ], - [ - -33, - 518 - ], - [ - 106, - 2 - ] - ], - [ - [ - 12845, - 13095 - ], - [ - 0, - -276 - ], - [ - -38, - -80 - ], - [ - -6, - -74 - ], - [ - -62, - -19 - ], - [ - -95, - -10 - ], - [ - -26, - -43 - ], - [ - -44, - -5 - ] - ], - [ - [ - 19526, - 13247 - ], - [ - -40, - -28 - ], - [ - -40, - -52 - ], - [ - -49, - -5 - ], - [ - -32, - -130 - ], - [ - -30, - -22 - ], - [ - 34, - -105 - ], - [ - 44, - -88 - ], - [ - 29, - -79 - ], - [ - -26, - -104 - ], - [ - -24, - -22 - ], - [ - 17, - -61 - ], - [ - 46, - -95 - ], - [ - 8, - -67 - ], - [ - -1, - -56 - ], - [ - 28, - -109 - ], - [ - -39, - -112 - ], - [ - -33, - -123 - ] - ], - [ - [ - 19418, - 11989 - ], - [ - -7, - 89 - ], - [ - 21, - 92 - ], - [ - -23, - 71 - ], - [ - 5, - 130 - ], - [ - -28, - 63 - ], - [ - -23, - 143 - ], - [ - -12, - 152 - ], - [ - -30, - 99 - ], - [ - -46, - -60 - ], - [ - -79, - -86 - ], - [ - -40, - 11 - ], - [ - -43, - 28 - ], - [ - 24, - 149 - ], - [ - -14, - 112 - ], - [ - -55, - 139 - ], - [ - 9, - 43 - ], - [ - -41, - 15 - ], - [ - -50, - 98 - ] - ], - [ - [ - 13898, - 15821 - ], - [ - -15, - 9 - ], - [ - -19, - 40 - ], - [ - -30, - 23 - ] - ], - [ - [ - 13887, - 16019 - ], - [ - 19, - -21 - ], - [ - 10, - -17 - ], - [ - 23, - -12 - ], - [ - 26, - -25 - ], - [ - -5, - -11 - ] - ], - [ - [ - 18664, - 16711 - ], - [ - 74, - 21 - ], - [ - 133, - 103 - ], - [ - 106, - 57 - ], - [ - 61, - -37 - ], - [ - 72, - -2 - ], - [ - 47, - -56 - ], - [ - 70, - -4 - ], - [ - 100, - -30 - ], - [ - 68, - 83 - ], - [ - -28, - 71 - ], - [ - 72, - 124 - ], - [ - 78, - -49 - ], - [ - 63, - -14 - ], - [ - 82, - -31 - ], - [ - 14, - -90 - ], - [ - 99, - -51 - ], - [ - 65, - 23 - ], - [ - 89, - 15 - ], - [ - 70, - -15 - ], - [ - 68, - -58 - ], - [ - 42, - -61 - ], - [ - 65, - 1 - ], - [ - 88, - -20 - ], - [ - 64, - 30 - ], - [ - 91, - 20 - ], - [ - 103, - 84 - ], - [ - 41, - -13 - ], - [ - 37, - -40 - ], - [ - 83, - 10 - ] - ], - [ - [ - 14957, - 9415 - ], - [ - 52, - 10 - ], - [ - 84, - -34 - ], - [ - 18, - 15 - ], - [ - 49, - 3 - ], - [ - 24, - 36 - ], - [ - 42, - -2 - ], - [ - 76, - 47 - ], - [ - 56, - 69 - ] - ], - [ - [ - 15358, - 9559 - ], - [ - 11, - -53 - ], - [ - -3, - -120 - ], - [ - 9, - -105 - ], - [ - 3, - -188 - ], - [ - 12, - -58 - ], - [ - -21, - -86 - ], - [ - -27, - -83 - ], - [ - -44, - -75 - ], - [ - -64, - -45 - ], - [ - -79, - -59 - ], - [ - -78, - -128 - ], - [ - -27, - -22 - ], - [ - -49, - -86 - ], - [ - -29, - -27 - ], - [ - -5, - -86 - ], - [ - 33, - -91 - ], - [ - 13, - -70 - ], - [ - 1, - -36 - ], - [ - 13, - 6 - ], - [ - -2, - -118 - ], - [ - -12, - -55 - ], - [ - 17, - -21 - ], - [ - -11, - -50 - ], - [ - -29, - -42 - ], - [ - -57, - -41 - ], - [ - -84, - -65 - ], - [ - -31, - -44 - ], - [ - 6, - -51 - ], - [ - 18, - -8 - ], - [ - -6, - -63 - ] - ], - [ - [ - 14836, - 7589 - ], - [ - -53, - 1 - ] - ], - [ - [ - 14783, - 7590 - ], - [ - -6, - 53 - ], - [ - -10, - 54 - ] - ], - [ - [ - 14767, - 7697 - ], - [ - -6, - 43 - ], - [ - 12, - 134 - ], - [ - -18, - 85 - ], - [ - -33, - 169 - ] - ], - [ - [ - 14722, - 8128 - ], - [ - 73, - 136 - ], - [ - 19, - 86 - ], - [ - 10, - 11 - ], - [ - 8, - 71 - ], - [ - -11, - 35 - ], - [ - 3, - 90 - ], - [ - 13, - 83 - ], - [ - 0, - 152 - ], - [ - -36, - 39 - ], - [ - -33, - 8 - ], - [ - -15, - 30 - ], - [ - -32, - 25 - ], - [ - -59, - -2 - ], - [ - -4, - 45 - ] - ], - [ - [ - 14658, - 8937 - ], - [ - -7, - 85 - ], - [ - 212, - 99 - ] - ], - [ - [ - 14863, - 9121 - ], - [ - 40, - -58 - ], - [ - 19, - 11 - ], - [ - 28, - -30 - ], - [ - 4, - -48 - ], - [ - -15, - -56 - ], - [ - 5, - -84 - ], - [ - 46, - -74 - ], - [ - 21, - 83 - ], - [ - 30, - 25 - ], - [ - -6, - 154 - ], - [ - -29, - 87 - ], - [ - -25, - 39 - ], - [ - -24, - -2 - ], - [ - -20, - 156 - ], - [ - 20, - 91 - ] - ], - [ - [ - 11699, - 12551 - ], - [ - -46, - 82 - ], - [ - -42, - 88 - ], - [ - -46, - 32 - ], - [ - -34, - 35 - ], - [ - -39, - -1 - ], - [ - -34, - -26 - ], - [ - -34, - 10 - ], - [ - -24, - -38 - ] - ], - [ - [ - 11400, - 12733 - ], - [ - -6, - 65 - ], - [ - 19, - 59 - ], - [ - 9, - 113 - ], - [ - -8, - 118 - ], - [ - -8, - 60 - ], - [ - 7, - 60 - ], - [ - -18, - 57 - ], - [ - -37, - 52 - ] - ], - [ - [ - 11358, - 13317 - ], - [ - 15, - 40 - ], - [ - 273, - -1 - ], - [ - -13, - 173 - ], - [ - 17, - 62 - ], - [ - 65, - 10 - ], - [ - -2, - 307 - ], - [ - 229, - -6 - ], - [ - 0, - 182 - ] - ], - [ - [ - 14863, - 9121 - ], - [ - -37, - 31 - ], - [ - 21, - 112 - ], - [ - 22, - 41 - ], - [ - -13, - 100 - ], - [ - 14, - 97 - ], - [ - 12, - 32 - ], - [ - -18, - 102 - ], - [ - -33, - 54 - ] - ], - [ - [ - 14831, - 9690 - ], - [ - 68, - -23 - ], - [ - 14, - -33 - ], - [ - 24, - -56 - ], - [ - 20, - -163 - ] - ], - [ - [ - 20595, - 11451 - ], - [ - 54, - 83 - ], - [ - 35, - 94 - ], - [ - 28, - 0 - ], - [ - 36, - -60 - ], - [ - 3, - -52 - ], - [ - 46, - -34 - ], - [ - 58, - -36 - ], - [ - -4, - -47 - ], - [ - -47, - -6 - ], - [ - 12, - -59 - ], - [ - -51, - -40 - ] - ], - [ - [ - 20192, - 11038 - ], - [ - 51, - -41 - ], - [ - 54, - 22 - ], - [ - 14, - 102 - ], - [ - 30, - 22 - ], - [ - 83, - 26 - ], - [ - 50, - 95 - ], - [ - 34, - 76 - ] - ], - [ - [ - 19668, - 11544 - ], - [ - 16, - -12 - ], - [ - 41, - -72 - ], - [ - 29, - -80 - ], - [ - 4, - -81 - ], - [ - -7, - -55 - ], - [ - 6, - -41 - ], - [ - 5, - -71 - ], - [ - 25, - -33 - ], - [ - 27, - -106 - ], - [ - -1, - -41 - ], - [ - -49, - -8 - ], - [ - -66, - 89 - ], - [ - -83, - 95 - ], - [ - -8, - 62 - ], - [ - -40, - 80 - ], - [ - -10, - 99 - ], - [ - -25, - 66 - ], - [ - 8, - 87 - ], - [ - -16, - 51 - ] - ], - [ - [ - 19524, - 11573 - ], - [ - 12, - 21 - ], - [ - 57, - -52 - ], - [ - 6, - -62 - ], - [ - 46, - 14 - ], - [ - 23, - 50 - ] - ], - [ - [ - 14166, - 8695 - ], - [ - 57, - 27 - ], - [ - 45, - -7 - ], - [ - 28, - -27 - ], - [ - 0, - -10 - ] - ], - [ - [ - 13934, - 7826 - ], - [ - 0, - -443 - ], - [ - -62, - -62 - ], - [ - -37, - -8 - ], - [ - -44, - 22 - ], - [ - -31, - 9 - ], - [ - -12, - 51 - ], - [ - -28, - 33 - ], - [ - -33, - -59 - ] - ], - [ - [ - 13687, - 7369 - ], - [ - -52, - 91 - ], - [ - -27, - 87 - ], - [ - -16, - 117 - ], - [ - -17, - 87 - ], - [ - -23, - 185 - ], - [ - -2, - 143 - ], - [ - -9, - 66 - ], - [ - -27, - 49 - ], - [ - -36, - 99 - ], - [ - -36, - 144 - ], - [ - -16, - 75 - ], - [ - -56, - 117 - ], - [ - -5, - 93 - ] - ], - [ - [ - 24104, - 8268 - ], - [ - 57, - -74 - ], - [ - 36, - -55 - ], - [ - -26, - -29 - ], - [ - -39, - 32 - ], - [ - -50, - 54 - ], - [ - -44, - 64 - ], - [ - -47, - 84 - ], - [ - -9, - 41 - ], - [ - 30, - -2 - ], - [ - 39, - -40 - ], - [ - 30, - -41 - ], - [ - 23, - -34 - ] - ], - [ - [ - 13583, - 13540 - ], - [ - 17, - -186 - ], - [ - 26, - -32 - ], - [ - 1, - -38 - ], - [ - 29, - -41 - ], - [ - -15, - -52 - ], - [ - -27, - -243 - ], - [ - -4, - -156 - ], - [ - -89, - -113 - ], - [ - -30, - -158 - ], - [ - 29, - -45 - ], - [ - 0, - -77 - ], - [ - 45, - -3 - ], - [ - -7, - -56 - ] - ], - [ - [ - 13536, - 12295 - ], - [ - -13, - -3 - ], - [ - -47, - 132 - ], - [ - -16, - 4 - ], - [ - -55, - -67 - ], - [ - -54, - 35 - ], - [ - -37, - 7 - ], - [ - -21, - -17 - ], - [ - -40, - 4 - ], - [ - -42, - -51 - ], - [ - -35, - -3 - ], - [ - -84, - 62 - ], - [ - -33, - -29 - ], - [ - -36, - 2 - ], - [ - -26, - 45 - ], - [ - -70, - 45 - ], - [ - -75, - -15 - ], - [ - -18, - -25 - ], - [ - -10, - -69 - ], - [ - -20, - -49 - ], - [ - -5, - -107 - ] - ], - [ - [ - 13140, - 11370 - ], - [ - -72, - -43 - ], - [ - -27, - 6 - ], - [ - -27, - -27 - ], - [ - -55, - 3 - ], - [ - -38, - 75 - ], - [ - -23, - 86 - ], - [ - -49, - 79 - ], - [ - -52, - -1 - ], - [ - -62, - 0 - ] - ], - [ - [ - 6573, - 12127 - ], - [ - -24, - 38 - ], - [ - -33, - 49 - ], - [ - -15, - 40 - ], - [ - -30, - 38 - ], - [ - -35, - 54 - ], - [ - 8, - 19 - ], - [ - 12, - -19 - ], - [ - 5, - 9 - ] - ], - [ - [ - 6751, - 12596 - ], - [ - -6, - -11 - ], - [ - -3, - -27 - ], - [ - 7, - -44 - ], - [ - -16, - -41 - ], - [ - -8, - -48 - ], - [ - -2, - -53 - ], - [ - 4, - -31 - ], - [ - 2, - -54 - ], - [ - -11, - -12 - ], - [ - -6, - -51 - ], - [ - 4, - -32 - ], - [ - -14, - -30 - ], - [ - 3, - -33 - ], - [ - 11, - -19 - ] - ], - [ - [ - 12779, - 16957 - ], - [ - 36, - 33 - ], - [ - 61, - 177 - ], - [ - 95, - 50 - ], - [ - 58, - -4 - ] - ], - [ - [ - 13987, - 19088 - ], - [ - -44, - -5 - ], - [ - -10, - -79 - ], - [ - -131, - 19 - ], - [ - -19, - -67 - ], - [ - -67, - 1 - ], - [ - -46, - -86 - ], - [ - -69, - -133 - ], - [ - -109, - -168 - ], - [ - 26, - -41 - ], - [ - -24, - -48 - ], - [ - -70, - 2 - ], - [ - -45, - -112 - ], - [ - 4, - -160 - ], - [ - 45, - -60 - ], - [ - -23, - -142 - ], - [ - -58, - -82 - ], - [ - -31, - -69 - ] - ], - [ - [ - 13316, - 17858 - ], - [ - -47, - 74 - ], - [ - -137, - -139 - ], - [ - -93, - -28 - ], - [ - -97, - 61 - ], - [ - -24, - 129 - ], - [ - -23, - 277 - ], - [ - 65, - 77 - ], - [ - 184, - 101 - ], - [ - 137, - 124 - ], - [ - 128, - 167 - ], - [ - 167, - 231 - ], - [ - 117, - 91 - ], - [ - 192, - 150 - ], - [ - 153, - 53 - ], - [ - 114, - -7 - ], - [ - 107, - 100 - ], - [ - 127, - -6 - ], - [ - 125, - 24 - ], - [ - 218, - -88 - ], - [ - -90, - -32 - ], - [ - 77, - -75 - ] - ], - [ - [ - 14716, - 19142 - ], - [ - -119, - -48 - ], - [ - -56, - -11 - ] - ], - [ - [ - 14271, - 20137 - ], - [ - -156, - -49 - ], - [ - -123, - 28 - ], - [ - 48, - 31 - ], - [ - -42, - 38 - ], - [ - 145, - 24 - ], - [ - 27, - -45 - ], - [ - 101, - -27 - ] - ], - [ - [ - 13820, - 20359 - ], - [ - 229, - -90 - ], - [ - -175, - -47 - ], - [ - -39, - -88 - ], - [ - -61, - -23 - ], - [ - -33, - -99 - ], - [ - -84, - -5 - ], - [ - -150, - 73 - ], - [ - 63, - 43 - ], - [ - -104, - 35 - ], - [ - -136, - 101 - ], - [ - -54, - 94 - ], - [ - 190, - 43 - ], - [ - 38, - -42 - ], - [ - 99, - 2 - ], - [ - 27, - 41 - ], - [ - 102, - 4 - ], - [ - 88, - -42 - ] - ], - [ - [ - 14321, - 20444 - ], - [ - 137, - -43 - ], - [ - -103, - -64 - ], - [ - -203, - -14 - ], - [ - -205, - 20 - ], - [ - -12, - 33 - ], - [ - -101, - 2 - ], - [ - -76, - 55 - ], - [ - 215, - 33 - ], - [ - 102, - -28 - ], - [ - 70, - 36 - ], - [ - 176, - -30 - ] - ], - [ - [ - 24608, - 5888 - ], - [ - 16, - -49 - ], - [ - 50, - 48 - ], - [ - 20, - -50 - ], - [ - 0, - -51 - ], - [ - -26, - -55 - ], - [ - -45, - -89 - ], - [ - -36, - -48 - ], - [ - 26, - -58 - ], - [ - -54, - -1 - ], - [ - -60, - -46 - ], - [ - -18, - -78 - ], - [ - -40, - -121 - ], - [ - -55, - -54 - ], - [ - -35, - -34 - ], - [ - -64, - 2 - ], - [ - -45, - 40 - ], - [ - -76, - 8 - ], - [ - -11, - 44 - ], - [ - 37, - 89 - ], - [ - 88, - 119 - ], - [ - 45, - 22 - ], - [ - 50, - 46 - ], - [ - 60, - 63 - ], - [ - 41, - 62 - ], - [ - 31, - 89 - ], - [ - 27, - 31 - ], - [ - 10, - 67 - ], - [ - 49, - 55 - ], - [ - 15, - -51 - ] - ], - [ - [ - 24719, - 6460 - ], - [ - 51, - -127 - ], - [ - 1, - 82 - ], - [ - 32, - -33 - ], - [ - 10, - -90 - ], - [ - 56, - -39 - ], - [ - 47, - -10 - ], - [ - 40, - 46 - ], - [ - 36, - -14 - ], - [ - -17, - -107 - ], - [ - -21, - -70 - ], - [ - -54, - 3 - ], - [ - -18, - -37 - ], - [ - 6, - -51 - ], - [ - -10, - -22 - ], - [ - -26, - -65 - ], - [ - -35, - -82 - ], - [ - -54, - -48 - ], - [ - -12, - 31 - ], - [ - -29, - 18 - ], - [ - 40, - 98 - ], - [ - -23, - 66 - ], - [ - -75, - 48 - ], - [ - 2, - 44 - ], - [ - 51, - 42 - ], - [ - 12, - 92 - ], - [ - -4, - 78 - ], - [ - -28, - 80 - ], - [ - 2, - 21 - ], - [ - -33, - 50 - ], - [ - -55, - 106 - ], - [ - -29, - 85 - ], - [ - 26, - 9 - ], - [ - 37, - -66 - ], - [ - 55, - -32 - ], - [ - 19, - -106 - ] - ], - [ - [ - 16456, - 13923 - ], - [ - 20, - 41 - ], - [ - 9, - -11 - ], - [ - -7, - -49 - ], - [ - -9, - -22 - ] - ], - [ - [ - 16479, - 13787 - ], - [ - 31, - -82 - ], - [ - 39, - -43 - ], - [ - 51, - -16 - ], - [ - 41, - -22 - ], - [ - 32, - -68 - ], - [ - 19, - -40 - ], - [ - 25, - -15 - ], - [ - -1, - -27 - ], - [ - -25, - -72 - ], - [ - -11, - -33 - ], - [ - -29, - -39 - ], - [ - -26, - -82 - ], - [ - -32, - 6 - ], - [ - -15, - -28 - ], - [ - -11, - -61 - ], - [ - 9, - -80 - ], - [ - -7, - -15 - ], - [ - -32, - 0 - ], - [ - -43, - -44 - ], - [ - -7, - -59 - ], - [ - -16, - -25 - ], - [ - -43, - 1 - ], - [ - -28, - -30 - ], - [ - 1, - -49 - ], - [ - -34, - -33 - ], - [ - -39, - 11 - ], - [ - -46, - -40 - ], - [ - -32, - -7 - ] - ], - [ - [ - 16250, - 12795 - ], - [ - -23, - 84 - ], - [ - -55, - 198 - ] - ], - [ - [ - 16172, - 13077 - ], - [ - 209, - 120 - ], - [ - 47, - 240 - ], - [ - -32, - 84 - ] - ], - [ - [ - 17300, - 13639 - ], - [ - -51, - 31 - ], - [ - -21, - 86 - ], - [ - -54, - 91 - ], - [ - -128, - -22 - ], - [ - -113, - -2 - ], - [ - -99, - -17 - ] - ], - [ - [ - 7119, - 11664 - ], - [ - -24, - 34 - ], - [ - -15, - 65 - ], - [ - 18, - 32 - ], - [ - -18, - 8 - ], - [ - -13, - 40 - ], - [ - -35, - 33 - ], - [ - -30, - -7 - ], - [ - -14, - -42 - ], - [ - -29, - -30 - ], - [ - -15, - -4 - ], - [ - -7, - -25 - ], - [ - 34, - -65 - ], - [ - -19, - -16 - ], - [ - -11, - -17 - ], - [ - -32, - -7 - ], - [ - -12, - 72 - ], - [ - -9, - -20 - ], - [ - -23, - 7 - ], - [ - -14, - 48 - ], - [ - -29, - 8 - ], - [ - -18, - 14 - ], - [ - -30, - 0 - ], - [ - -2, - -26 - ], - [ - -8, - 18 - ] - ], - [ - [ - 6793, - 11945 - ], - [ - 25, - -43 - ], - [ - -1, - -26 - ], - [ - 28, - -5 - ], - [ - 6, - 10 - ], - [ - 20, - -30 - ], - [ - 34, - 9 - ], - [ - 29, - 30 - ], - [ - 43, - 24 - ], - [ - 24, - 36 - ], - [ - 38, - -7 - ], - [ - -3, - -12 - ], - [ - 39, - -4 - ], - [ - 31, - -20 - ], - [ - 23, - -36 - ], - [ - 26, - -34 - ] - ], - [ - [ - 7642, - 8596 - ], - [ - -70, - 69 - ], - [ - -6, - 49 - ], - [ - -138, - 121 - ], - [ - -125, - 131 - ], - [ - -54, - 74 - ], - [ - -29, - 99 - ], - [ - 12, - 34 - ], - [ - -59, - 158 - ], - [ - -69, - 221 - ], - [ - -66, - 239 - ], - [ - -29, - 55 - ], - [ - -21, - 88 - ], - [ - -55, - 78 - ], - [ - -49, - 49 - ], - [ - 22, - 54 - ], - [ - -34, - 114 - ], - [ - 22, - 84 - ], - [ - 56, - 76 - ] - ], - [ - [ - 21357, - 11807 - ], - [ - 7, - -80 - ], - [ - 4, - -67 - ], - [ - -24, - -110 - ], - [ - -25, - 122 - ], - [ - -33, - -61 - ], - [ - 23, - -88 - ], - [ - -20, - -56 - ], - [ - -82, - 69 - ], - [ - -20, - 87 - ], - [ - 21, - 57 - ], - [ - -44, - 57 - ], - [ - -22, - -50 - ], - [ - -33, - 5 - ], - [ - -51, - -67 - ], - [ - -12, - 35 - ], - [ - 28, - 101 - ], - [ - 44, - 34 - ], - [ - 38, - 45 - ], - [ - 24, - -54 - ], - [ - 53, - 33 - ], - [ - 12, - 53 - ], - [ - 49, - 3 - ], - [ - -4, - 93 - ], - [ - 56, - -57 - ], - [ - 6, - -60 - ], - [ - 5, - -44 - ] - ], - [ - [ - 21190, - 12030 - ], - [ - -25, - -39 - ], - [ - -22, - -76 - ], - [ - -22, - -35 - ], - [ - -43, - 82 - ], - [ - 15, - 33 - ], - [ - 17, - 33 - ], - [ - 8, - 75 - ], - [ - 38, - 7 - ], - [ - -11, - -81 - ], - [ - 52, - 116 - ], - [ - -7, - -115 - ] - ], - [ - [ - 20808, - 11915 - ], - [ - -92, - -114 - ], - [ - 34, - 84 - ], - [ - 50, - 74 - ], - [ - 42, - 83 - ], - [ - 36, - 119 - ], - [ - 13, - -98 - ], - [ - -46, - -66 - ], - [ - -37, - -82 - ] - ], - [ - [ - 21044, - 12224 - ], - [ - 42, - -37 - ], - [ - 44, - 0 - ], - [ - -1, - -50 - ], - [ - -33, - -51 - ], - [ - -44, - -36 - ], - [ - -2, - 56 - ], - [ - 5, - 61 - ], - [ - -11, - 57 - ] - ], - [ - [ - 21296, - 12256 - ], - [ - 20, - -134 - ], - [ - -54, - 32 - ], - [ - 1, - -40 - ], - [ - 17, - -74 - ], - [ - -33, - -27 - ], - [ - -3, - 84 - ], - [ - -21, - 7 - ], - [ - -11, - 72 - ], - [ - 41, - -9 - ], - [ - 0, - 45 - ], - [ - -43, - 92 - ], - [ - 67, - -3 - ], - [ - 19, - -45 - ] - ], - [ - [ - 21019, - 12365 - ], - [ - -19, - -104 - ], - [ - -29, - 60 - ], - [ - -36, - 92 - ], - [ - 60, - -5 - ], - [ - 24, - -43 - ] - ], - [ - [ - 21005, - 13017 - ], - [ - 43, - -34 - ], - [ - 21, - 31 - ], - [ - 6, - -30 - ], - [ - -11, - -50 - ], - [ - 24, - -86 - ], - [ - -18, - -100 - ], - [ - -42, - -40 - ], - [ - -11, - -96 - ], - [ - 16, - -96 - ], - [ - 37, - -13 - ], - [ - 31, - 14 - ], - [ - 87, - -66 - ], - [ - -7, - -66 - ], - [ - 23, - -29 - ], - [ - -7, - -55 - ], - [ - -55, - 59 - ], - [ - -25, - 63 - ], - [ - -18, - -44 - ], - [ - -45, - 72 - ], - [ - -63, - -18 - ], - [ - -35, - 27 - ], - [ - 4, - 49 - ], - [ - 22, - 31 - ], - [ - -21, - 28 - ], - [ - -9, - -44 - ], - [ - -35, - 69 - ], - [ - -10, - 52 - ], - [ - -3, - 115 - ], - [ - 28, - -39 - ], - [ - 8, - 188 - ], - [ - 22, - 108 - ], - [ - 43, - 0 - ] - ], - [ - [ - 22376, - 10485 - ], - [ - 121, - -82 - ], - [ - 129, - -69 - ], - [ - 48, - -62 - ], - [ - 39, - -60 - ], - [ - 11, - -71 - ], - [ - 116, - -74 - ], - [ - 17, - -63 - ], - [ - -64, - -13 - ], - [ - 15, - -80 - ], - [ - 62, - -79 - ], - [ - 46, - -127 - ], - [ - 39, - 4 - ], - [ - -2, - -53 - ], - [ - 53, - -21 - ], - [ - -20, - -22 - ], - [ - 74, - -51 - ], - [ - -8, - -34 - ], - [ - -46, - -9 - ], - [ - -17, - 31 - ], - [ - -60, - 14 - ], - [ - -71, - 18 - ], - [ - -54, - 76 - ], - [ - -39, - 66 - ], - [ - -37, - 105 - ], - [ - -91, - 53 - ], - [ - -59, - -34 - ], - [ - -42, - -40 - ], - [ - 9, - -88 - ], - [ - -55, - -42 - ], - [ - -39, - 20 - ], - [ - -72, - 5 - ] - ], - [ - [ - 23414, - 9979 - ], - [ - -20, - -12 - ], - [ - -30, - 46 - ], - [ - -31, - 76 - ], - [ - -15, - 92 - ], - [ - 10, - 11 - ], - [ - 8, - -35 - ], - [ - 21, - -28 - ], - [ - 33, - -76 - ], - [ - 33, - -40 - ], - [ - -9, - -34 - ] - ], - [ - [ - 23142, - 10140 - ], - [ - -37, - -10 - ], - [ - -11, - -34 - ], - [ - -38, - -29 - ], - [ - -35, - -28 - ], - [ - -37, - 0 - ], - [ - -58, - 35 - ], - [ - -39, - 34 - ], - [ - 5, - 37 - ], - [ - 63, - -18 - ], - [ - 38, - 10 - ], - [ - 10, - 57 - ], - [ - 10, - 3 - ], - [ - 7, - -64 - ], - [ - 40, - 10 - ], - [ - 20, - 41 - ], - [ - 39, - 42 - ], - [ - -8, - 71 - ], - [ - 42, - 2 - ], - [ - 14, - -19 - ], - [ - -2, - -67 - ], - [ - -23, - -73 - ] - ], - [ - [ - 23223, - 10257 - ], - [ - -22, - -32 - ], - [ - -13, - 71 - ], - [ - -17, - 47 - ], - [ - -31, - 39 - ], - [ - -40, - 51 - ], - [ - -50, - 35 - ], - [ - 19, - 29 - ], - [ - 38, - -33 - ], - [ - 24, - -27 - ], - [ - 29, - -29 - ], - [ - 28, - -50 - ], - [ - 26, - -38 - ], - [ - 9, - -63 - ] - ], - [ - [ - 14188, - 16985 - ], - [ - 35, - -105 - ], - [ - -8, - -33 - ], - [ - -34, - -14 - ], - [ - -64, - -100 - ], - [ - 18, - -54 - ], - [ - -15, - 7 - ] - ], - [ - [ - 14120, - 16686 - ], - [ - -66, - 46 - ], - [ - -50, - -17 - ], - [ - -33, - 12 - ], - [ - -42, - -25 - ], - [ - -35, - 42 - ], - [ - -28, - -16 - ], - [ - -4, - 7 - ] - ], - [ - [ - 13532, - 17246 - ], - [ - 47, - 36 - ], - [ - 109, - 55 - ], - [ - 88, - 41 - ], - [ - 70, - -21 - ], - [ - 5, - -29 - ], - [ - 67, - -1 - ] - ], - [ - [ - 13918, - 17327 - ], - [ - 86, - -14 - ], - [ - 128, - 2 - ] - ], - [ - [ - 7927, - 13018 - ], - [ - 36, - -10 - ], - [ - 12, - -24 - ], - [ - -18, - -30 - ], - [ - -52, - 0 - ], - [ - -41, - -4 - ], - [ - -4, - 52 - ], - [ - 10, - 17 - ], - [ - 57, - -1 - ] - ], - [ - [ - 21654, - 15883 - ], - [ - 10, - -21 - ] - ], - [ - [ - 21664, - 15862 - ], - [ - -27, - 7 - ], - [ - -30, - -40 - ], - [ - -21, - -41 - ], - [ - 3, - -86 - ], - [ - -36, - -27 - ], - [ - -12, - -21 - ], - [ - -27, - -35 - ], - [ - -46, - -20 - ], - [ - -30, - -32 - ], - [ - -3, - -52 - ], - [ - -8, - -13 - ], - [ - 28, - -20 - ], - [ - 40, - -53 - ] - ], - [ - [ - 21343, - 15326 - ], - [ - -34, - 23 - ], - [ - -8, - -23 - ], - [ - -21, - -10 - ], - [ - -2, - 23 - ], - [ - -18, - 11 - ], - [ - -19, - 19 - ], - [ - 19, - 53 - ], - [ - 17, - 14 - ], - [ - -7, - 22 - ], - [ - 18, - 65 - ], - [ - -5, - 19 - ], - [ - -40, - 13 - ], - [ - -33, - 32 - ] - ], - [ - [ - 12028, - 15248 - ], - [ - -28, - -31 - ], - [ - -37, - 17 - ], - [ - -36, - -14 - ], - [ - 11, - 94 - ], - [ - -7, - 74 - ], - [ - -31, - 11 - ], - [ - -17, - 45 - ], - [ - 6, - 79 - ], - [ - 28, - 44 - ], - [ - 5, - 48 - ], - [ - 14, - 72 - ], - [ - -1, - 51 - ], - [ - -14, - 43 - ], - [ - -3, - 41 - ] - ], - [ - [ - 16089, - 13767 - ], - [ - -4, - 87 - ], - [ - 19, - 63 - ], - [ - 19, - 13 - ], - [ - 21, - -37 - ], - [ - 1, - -71 - ], - [ - -15, - -70 - ] - ], - [ - [ - 16130, - 13752 - ], - [ - -20, - -9 - ], - [ - -21, - 24 - ] - ], - [ - [ - 14127, - 16104 - ], - [ - -13, - 21 - ], - [ - 16, - 20 - ], - [ - -17, - 15 - ], - [ - -22, - -27 - ], - [ - -40, - 35 - ], - [ - -6, - 50 - ], - [ - -42, - 28 - ], - [ - -8, - 38 - ], - [ - -38, - 47 - ] - ], - [ - [ - 14131, - 16542 - ], - [ - 30, - 25 - ], - [ - 43, - -13 - ], - [ - 45, - 0 - ], - [ - 32, - -30 - ], - [ - 24, - 19 - ], - [ - 51, - 11 - ], - [ - 18, - 28 - ], - [ - 29, - 0 - ] - ], - [ - [ - 14516, - 16254 - ], - [ - 31, - -22 - ], - [ - 32, - 20 - ], - [ - 32, - -21 - ] - ], - [ - [ - 14611, - 16231 - ], - [ - 2, - -31 - ], - [ - -34, - -26 - ], - [ - -21, - 11 - ], - [ - -20, - -144 - ] - ], - [ - [ - 15333, - 16008 - ], - [ - -89, - 101 - ], - [ - -80, - 46 - ], - [ - -60, - 70 - ], - [ - 51, - 19 - ], - [ - 58, - 101 - ], - [ - -39, - 47 - ], - [ - 102, - 49 - ], - [ - -1, - 26 - ], - [ - -63, - -19 - ] - ], - [ - [ - 15212, - 16448 - ], - [ - 2, - 53 - ], - [ - 36, - 34 - ], - [ - 68, - 9 - ], - [ - 11, - 40 - ], - [ - -16, - 66 - ], - [ - 28, - 63 - ], - [ - 0, - 35 - ], - [ - -103, - 39 - ], - [ - -41, - -1 - ], - [ - -43, - 56 - ], - [ - -53, - -19 - ], - [ - -89, - 42 - ], - [ - 2, - 23 - ], - [ - -25, - 53 - ], - [ - -56, - 5 - ], - [ - -6, - 38 - ], - [ - 18, - 24 - ], - [ - -45, - 68 - ], - [ - -72, - -12 - ], - [ - -21, - 6 - ], - [ - -18, - -27 - ], - [ - -26, - 5 - ] - ], - [ - [ - 14498, - 17932 - ], - [ - 79, - 67 - ], - [ - -73, - 57 - ] - ], - [ - [ - 14716, - 19142 - ], - [ - 71, - 42 - ], - [ - 115, - -73 - ], - [ - 191, - -28 - ], - [ - 263, - -136 - ], - [ - 54, - -57 - ], - [ - 4, - -80 - ], - [ - -77, - -63 - ], - [ - -114, - -32 - ], - [ - -311, - 91 - ], - [ - -51, - -15 - ], - [ - 113, - -88 - ], - [ - 5, - -56 - ], - [ - 4, - -122 - ], - [ - 90, - -37 - ], - [ - 55, - -31 - ], - [ - 9, - 58 - ], - [ - -42, - 52 - ], - [ - 44, - 45 - ], - [ - 168, - -74 - ], - [ - 59, - 29 - ], - [ - -47, - 88 - ], - [ - 163, - 117 - ], - [ - 64, - -7 - ], - [ - 65, - -42 - ], - [ - 41, - 83 - ], - [ - -58, - 71 - ], - [ - 34, - 72 - ], - [ - -51, - 75 - ], - [ - 195, - -39 - ], - [ - 39, - -67 - ], - [ - -88, - -15 - ], - [ - 1, - -67 - ], - [ - 54, - -41 - ], - [ - 108, - 26 - ], - [ - 17, - 77 - ], - [ - 146, - 57 - ], - [ - 243, - 103 - ], - [ - 53, - -6 - ], - [ - -69, - -73 - ], - [ - 86, - -12 - ], - [ - 50, - 41 - ], - [ - 131, - 3 - ], - [ - 103, - 50 - ], - [ - 80, - -73 - ], - [ - 79, - 80 - ], - [ - -73, - 69 - ], - [ - 36, - 40 - ], - [ - 206, - -36 - ], - [ - 97, - -38 - ], - [ - 252, - -137 - ], - [ - 47, - 63 - ], - [ - -71, - 63 - ], - [ - -2, - 26 - ], - [ - -84, - 12 - ], - [ - 23, - 56 - ], - [ - -37, - 94 - ], - [ - -2, - 38 - ], - [ - 128, - 109 - ], - [ - 46, - 109 - ], - [ - 52, - 24 - ], - [ - 184, - -32 - ], - [ - 15, - -67 - ], - [ - -66, - -97 - ], - [ - 43, - -38 - ], - [ - 23, - -84 - ], - [ - -16, - -164 - ], - [ - 77, - -74 - ], - [ - -30, - -80 - ], - [ - -137, - -170 - ], - [ - 80, - -18 - ], - [ - 28, - 43 - ], - [ - 76, - 31 - ], - [ - 19, - 59 - ], - [ - 60, - 57 - ], - [ - -40, - 69 - ], - [ - 32, - 79 - ], - [ - -76, - 10 - ], - [ - -17, - 66 - ], - [ - 56, - 121 - ], - [ - -91, - 98 - ], - [ - 125, - 80 - ], - [ - -16, - 86 - ], - [ - 35, - 3 - ], - [ - 36, - -67 - ], - [ - -27, - -116 - ], - [ - 74, - -22 - ], - [ - -31, - 87 - ], - [ - 116, - 47 - ], - [ - 145, - 6 - ], - [ - 129, - -68 - ], - [ - -62, - 100 - ], - [ - -7, - 128 - ], - [ - 121, - 24 - ], - [ - 168, - -5 - ], - [ - 151, - 15 - ], - [ - -57, - 63 - ], - [ - 81, - 79 - ], - [ - 80, - 3 - ], - [ - 135, - 60 - ], - [ - 184, - 16 - ], - [ - 24, - 32 - ], - [ - 183, - 12 - ], - [ - 57, - -27 - ], - [ - 156, - 63 - ], - [ - 128, - -2 - ], - [ - 20, - 52 - ], - [ - 66, - 51 - ], - [ - 165, - 50 - ], - [ - 119, - -39 - ], - [ - -95, - -30 - ], - [ - 158, - -18 - ], - [ - 19, - -60 - ], - [ - 64, - 30 - ], - [ - 204, - -2 - ], - [ - 157, - -59 - ], - [ - 56, - -44 - ], - [ - -18, - -63 - ], - [ - -77, - -35 - ], - [ - -183, - -67 - ], - [ - -52, - -36 - ], - [ - 86, - -16 - ], - [ - 103, - -31 - ], - [ - 63, - 23 - ], - [ - 35, - -77 - ], - [ - 31, - 31 - ], - [ - 112, - 19 - ], - [ - 223, - -20 - ], - [ - 17, - -56 - ], - [ - 292, - -18 - ], - [ - 4, - 92 - ], - [ - 148, - -21 - ], - [ - 111, - 1 - ], - [ - 112, - -63 - ], - [ - 32, - -77 - ], - [ - -41, - -50 - ], - [ - 88, - -95 - ], - [ - 109, - -49 - ], - [ - 68, - 126 - ], - [ - 111, - -54 - ], - [ - 119, - 33 - ], - [ - 135, - -37 - ], - [ - 52, - 33 - ], - [ - 114, - -16 - ], - [ - -51, - 111 - ], - [ - 92, - 52 - ], - [ - 630, - -78 - ], - [ - 59, - -71 - ], - [ - 183, - -92 - ], - [ - 281, - 23 - ], - [ - 139, - -20 - ], - [ - 58, - -50 - ], - [ - -8, - -87 - ], - [ - 85, - -34 - ], - [ - 94, - 24 - ], - [ - 123, - 3 - ], - [ - 132, - -23 - ], - [ - 132, - 13 - ], - [ - 121, - -107 - ], - [ - 87, - 39 - ], - [ - -57, - 76 - ], - [ - 32, - 54 - ], - [ - 222, - -34 - ], - [ - 145, - 7 - ], - [ - 200, - -57 - ], - [ - 98, - -52 - ], - [ - 0, - -478 - ], - [ - -1, - -1 - ], - [ - -89, - -53 - ], - [ - -90, - 9 - ], - [ - 62, - -64 - ], - [ - 42, - -99 - ], - [ - 32, - -32 - ], - [ - 8, - -49 - ], - [ - -18, - -32 - ], - [ - -130, - 26 - ], - [ - -195, - -90 - ], - [ - -62, - -14 - ], - [ - -106, - -85 - ], - [ - -101, - -73 - ], - [ - -26, - -55 - ], - [ - -100, - 83 - ], - [ - -181, - -94 - ], - [ - -32, - 45 - ], - [ - -67, - -52 - ], - [ - -93, - 17 - ], - [ - -23, - -79 - ], - [ - -84, - -116 - ], - [ - 3, - -49 - ], - [ - 79, - -27 - ], - [ - -9, - -174 - ], - [ - -65, - -5 - ], - [ - -30, - -100 - ], - [ - 29, - -52 - ], - [ - -121, - -61 - ], - [ - -25, - -137 - ], - [ - -104, - -29 - ], - [ - -20, - -122 - ], - [ - -101, - -112 - ], - [ - -26, - 83 - ], - [ - -30, - 175 - ], - [ - -38, - 266 - ], - [ - 33, - 167 - ], - [ - 59, - 71 - ], - [ - 3, - 56 - ], - [ - 109, - 27 - ], - [ - 124, - 151 - ], - [ - 120, - 123 - ], - [ - 126, - 96 - ], - [ - 56, - 169 - ], - [ - -85, - -10 - ], - [ - -42, - -99 - ], - [ - -177, - -131 - ], - [ - -57, - 147 - ], - [ - -180, - -41 - ], - [ - -174, - -201 - ], - [ - 57, - -73 - ], - [ - -155, - -32 - ], - [ - -108, - -12 - ], - [ - 5, - 87 - ], - [ - -108, - 18 - ], - [ - -87, - -59 - ], - [ - -213, - 21 - ], - [ - -229, - -36 - ], - [ - -226, - -234 - ], - [ - -267, - -283 - ], - [ - 110, - -15 - ], - [ - 34, - -75 - ], - [ - 68, - -27 - ], - [ - 44, - 60 - ], - [ - 77, - -8 - ], - [ - 100, - -132 - ], - [ - 3, - -102 - ], - [ - -55, - -120 - ], - [ - -6, - -143 - ], - [ - -31, - -192 - ], - [ - -105, - -173 - ], - [ - -23, - -83 - ], - [ - -95, - -140 - ], - [ - -94, - -138 - ], - [ - -45, - -71 - ], - [ - -93, - -71 - ], - [ - -44, - -1 - ], - [ - -44, - 58 - ], - [ - -93, - -88 - ], - [ - -11, - -40 - ] - ], - [ - [ - 15970, - 16364 - ], - [ - -32, - -71 - ], - [ - -67, - -20 - ], - [ - -69, - -124 - ], - [ - 63, - -114 - ], - [ - -7, - -81 - ], - [ - 76, - -141 - ] - ], - [ - [ - 13918, - 17327 - ], - [ - 16, - 52 - ], - [ - 96, - 39 - ] - ], - [ - [ - 14878, - 16312 - ], - [ - 19, - 30 - ], - [ - 49, - -26 - ], - [ - 23, - -4 - ], - [ - 9, - -24 - ], - [ - 10, - -4 - ] - ], - [ - [ - 14988, - 16284 - ], - [ - 1, - -10 - ], - [ - 34, - -29 - ], - [ - 71, - 7 - ], - [ - -14, - -43 - ], - [ - -76, - -20 - ], - [ - -95, - -70 - ], - [ - -38, - 25 - ], - [ - 15, - 56 - ], - [ - -76, - 35 - ], - [ - 12, - 23 - ], - [ - 67, - 40 - ], - [ - -11, - 14 - ] - ], - [ - [ - 22561, - 16885 - ], - [ - 70, - -212 - ], - [ - -103, - 39 - ], - [ - -43, - -173 - ], - [ - 68, - -123 - ], - [ - -2, - -84 - ], - [ - -53, - 73 - ], - [ - -46, - -93 - ], - [ - -12, - 100 - ], - [ - 7, - 117 - ], - [ - -8, - 130 - ], - [ - 17, - 90 - ], - [ - 3, - 161 - ], - [ - -41, - 118 - ], - [ - 6, - 164 - ], - [ - 64, - 55 - ], - [ - -27, - 56 - ], - [ - 31, - 16 - ], - [ - 18, - -79 - ], - [ - 24, - -116 - ], - [ - -2, - -118 - ], - [ - 29, - -121 - ] - ], - [ - [ - 348, - 18785 - ], - [ - 47, - -30 - ], - [ - -17, - 88 - ], - [ - 190, - -18 - ], - [ - 136, - -113 - ], - [ - -69, - -52 - ], - [ - -114, - -12 - ], - [ - -2, - -118 - ], - [ - -28, - -24 - ], - [ - -65, - 3 - ], - [ - -53, - 42 - ], - [ - -93, - 35 - ], - [ - -16, - 52 - ], - [ - -70, - 20 - ], - [ - -80, - -16 - ], - [ - -38, - 42 - ], - [ - 16, - 45 - ], - [ - -84, - -29 - ], - [ - 32, - -56 - ], - [ - -40, - -51 - ], - [ - 0, - 478 - ], - [ - 171, - -92 - ], - [ - 183, - -119 - ], - [ - -6, - -75 - ] - ], - [ - [ - 25095, - 19295 - ], - [ - -76, - -6 - ], - [ - -13, - 38 - ], - [ - 89, - 50 - ], - [ - 0, - -82 - ] - ], - [ - [ - 91, - 19302 - ], - [ - -91, - -7 - ], - [ - 0, - 82 - ], - [ - 9, - 5 - ], - [ - 59, - 0 - ], - [ - 101, - -35 - ], - [ - -6, - -16 - ], - [ - -72, - -29 - ] - ], - [ - [ - 22558, - 19580 - ], - [ - -106, - 0 - ], - [ - -143, - 13 - ], - [ - -12, - 6 - ], - [ - 66, - 48 - ], - [ - 87, - 11 - ], - [ - 99, - -46 - ], - [ - 9, - -32 - ] - ], - [ - [ - 23055, - 19805 - ], - [ - -81, - -47 - ], - [ - -111, - 10 - ], - [ - -130, - 48 - ], - [ - 17, - 38 - ], - [ - 130, - -18 - ], - [ - 175, - -31 - ] - ], - [ - [ - 22661, - 19862 - ], - [ - -55, - -89 - ], - [ - -257, - 4 - ], - [ - -115, - -29 - ], - [ - -138, - 78 - ], - [ - 37, - 83 - ], - [ - 92, - 22 - ], - [ - 184, - -5 - ], - [ - 252, - -64 - ] - ], - [ - [ - 16558, - 19281 - ], - [ - -41, - -10 - ], - [ - -228, - 16 - ], - [ - -18, - 53 - ], - [ - -126, - 32 - ], - [ - -11, - 65 - ], - [ - 72, - 25 - ], - [ - -3, - 66 - ], - [ - 139, - 102 - ], - [ - -65, - 15 - ], - [ - 167, - 105 - ], - [ - -18, - 55 - ], - [ - 155, - 63 - ], - [ - 231, - 77 - ], - [ - 232, - 22 - ], - [ - 119, - 45 - ], - [ - 136, - 16 - ], - [ - 48, - -48 - ], - [ - -47, - -37 - ], - [ - -247, - -60 - ], - [ - -213, - -57 - ], - [ - -216, - -114 - ], - [ - -104, - -117 - ], - [ - -109, - -116 - ], - [ - 14, - -99 - ], - [ - 133, - -99 - ] - ], - [ - [ - 19872, - 20192 - ], - [ - -393, - -47 - ], - [ - 128, - 158 - ], - [ - 57, - 13 - ], - [ - 52, - -8 - ], - [ - 177, - -68 - ], - [ - -21, - -48 - ] - ], - [ - [ - 16112, - 20460 - ], - [ - -93, - -15 - ], - [ - -63, - -10 - ], - [ - -10, - -19 - ], - [ - -81, - -20 - ], - [ - -76, - 28 - ], - [ - 40, - 38 - ], - [ - -155, - 3 - ], - [ - 136, - 22 - ], - [ - 106, - 2 - ], - [ - 14, - -33 - ], - [ - 40, - 29 - ], - [ - 66, - 20 - ], - [ - 103, - -26 - ], - [ - -27, - -19 - ] - ], - [ - [ - 19514, - 20260 - ], - [ - -152, - -15 - ], - [ - -194, - 35 - ], - [ - -116, - 46 - ], - [ - -53, - 86 - ], - [ - -95, - 24 - ], - [ - 181, - 82 - ], - [ - 150, - 27 - ], - [ - 136, - -61 - ], - [ - 160, - -116 - ], - [ - -17, - -108 - ] - ], - [ - [ - 14609, - 10636 - ], - [ - 17, - -12 - ], - [ - 42, - 37 - ] - ], - [ - [ - 14668, - 10661 - ], - [ - 28, - -68 - ], - [ - -4, - -70 - ], - [ - -21, - -15 - ] - ], - [ - [ - 11358, - 13317 - ], - [ - 3, - 50 - ] - ], - [ - [ - 16172, - 13077 - ], - [ - -201, - -46 - ], - [ - -65, - -54 - ], - [ - -50, - -126 - ], - [ - -32, - -20 - ], - [ - -18, - 40 - ], - [ - -26, - -6 - ], - [ - -68, - 12 - ], - [ - -13, - 12 - ], - [ - -80, - -3 - ], - [ - -19, - -11 - ], - [ - -28, - 31 - ], - [ - -19, - -59 - ], - [ - 7, - -50 - ], - [ - -30, - -39 - ] - ], - [ - [ - 15530, - 12758 - ], - [ - -9, - 52 - ], - [ - -21, - 36 - ], - [ - -6, - 48 - ], - [ - -36, - 43 - ], - [ - -37, - 100 - ], - [ - -20, - 98 - ], - [ - -48, - 83 - ], - [ - -31, - 19 - ], - [ - -46, - 115 - ], - [ - -8, - 83 - ], - [ - 3, - 71 - ], - [ - -40, - 133 - ], - [ - -33, - 47 - ], - [ - -38, - 25 - ], - [ - -22, - 68 - ], - [ - 3, - 28 - ], - [ - -19, - 62 - ], - [ - -20, - 27 - ], - [ - -28, - 89 - ], - [ - -42, - 97 - ], - [ - -36, - 82 - ], - [ - -34, - -1 - ], - [ - 10, - 66 - ], - [ - 4, - 42 - ], - [ - 8, - 48 - ] - ], - [ - [ - 15923, - 14223 - ], - [ - 27, - -104 - ], - [ - 34, - -27 - ], - [ - 12, - -42 - ], - [ - 48, - -51 - ], - [ - 4, - -49 - ], - [ - -7, - -40 - ], - [ - 9, - -41 - ], - [ - 20, - -33 - ], - [ - 9, - -40 - ], - [ - 10, - -29 - ] - ], - [ - [ - 16130, - 13752 - ], - [ - 13, - -46 - ] - ], - [ - [ - 14141, - 12134 - ], - [ - 1, - 29 - ], - [ - -25, - 35 - ], - [ - -1, - 70 - ], - [ - -15, - 46 - ], - [ - -24, - -7 - ], - [ - 7, - 44 - ], - [ - 18, - 50 - ], - [ - -8, - 50 - ], - [ - 23, - 37 - ], - [ - -15, - 28 - ], - [ - 19, - 74 - ], - [ - 32, - 88 - ], - [ - 60, - -8 - ], - [ - -4, - 476 - ] - ], - [ - [ - 15117, - 13437 - ], - [ - 23, - -118 - ], - [ - -15, - -22 - ], - [ - 10, - -123 - ], - [ - 25, - -144 - ], - [ - 27, - -29 - ], - [ - 38, - -45 - ] - ], - [ - [ - 14916, - 11839 - ], - [ - -1, - 94 - ], - [ - -10, - 2 - ], - [ - 2, - 60 - ], - [ - -9, - 41 - ], - [ - -36, - 47 - ], - [ - -8, - 87 - ], - [ - 8, - 88 - ], - [ - -32, - 9 - ], - [ - -5, - -27 - ], - [ - -42, - -6 - ], - [ - 17, - -35 - ], - [ - 6, - -72 - ], - [ - -38, - -66 - ], - [ - -35, - -87 - ], - [ - -36, - -12 - ], - [ - -58, - 70 - ], - [ - -27, - -25 - ], - [ - -7, - -35 - ], - [ - -36, - -23 - ], - [ - -2, - -24 - ], - [ - -70, - 0 - ], - [ - -9, - 24 - ], - [ - -51, - 5 - ], - [ - -25, - -21 - ], - [ - -19, - 10 - ], - [ - -36, - 70 - ], - [ - -12, - 33 - ], - [ - -50, - -16 - ], - [ - -19, - -56 - ], - [ - -18, - -107 - ], - [ - -24, - -23 - ], - [ - -21, - -13 - ], - [ - 47, - -47 - ] - ], - [ - [ - 14918, - 11307 - ], - [ - -43, - -55 - ], - [ - -49, - 0 - ], - [ - -56, - -28 - ], - [ - -44, - 27 - ], - [ - -29, - -33 - ] - ], - [ - [ - 11385, - 12283 - ], - [ - -11, - 92 - ] - ], - [ - [ - 11382, - 12428 - ], - [ - -28, - 94 - ], - [ - -35, - 42 - ], - [ - 31, - 23 - ], - [ - 33, - 84 - ], - [ - 17, - 62 - ] - ], - [ - [ - 23849, - 9540 - ], - [ - 19, - -42 - ], - [ - -49, - 1 - ], - [ - -26, - 74 - ], - [ - 41, - -29 - ], - [ - 15, - -4 - ] - ], - [ - [ - 23760, - 9613 - ], - [ - -27, - -3 - ], - [ - -43, - 12 - ], - [ - -14, - 19 - ], - [ - 4, - 47 - ], - [ - 46, - -19 - ], - [ - 23, - -25 - ], - [ - 11, - -31 - ] - ], - [ - [ - 23818, - 9645 - ], - [ - -11, - -22 - ], - [ - -51, - 104 - ], - [ - -15, - 72 - ], - [ - 24, - 0 - ], - [ - 25, - -96 - ], - [ - 28, - -58 - ] - ], - [ - [ - 23692, - 9797 - ], - [ - 3, - -24 - ], - [ - -55, - 51 - ], - [ - -38, - 43 - ], - [ - -26, - 40 - ], - [ - 11, - 12 - ], - [ - 32, - -29 - ], - [ - 57, - -55 - ], - [ - 16, - -38 - ] - ], - [ - [ - 23529, - 9916 - ], - [ - -14, - -7 - ], - [ - -30, - 27 - ], - [ - -29, - 49 - ], - [ - 4, - 20 - ], - [ - 41, - -50 - ], - [ - 28, - -39 - ] - ], - [ - [ - 11750, - 11611 - ], - [ - -19, - 9 - ], - [ - -50, - 49 - ], - [ - -36, - 64 - ], - [ - -12, - 44 - ], - [ - -9, - 88 - ] - ], - [ - [ - 6428, - 12403 - ], - [ - -8, - -28 - ], - [ - -41, - 1 - ], - [ - -25, - 12 - ], - [ - -28, - 24 - ], - [ - -39, - 7 - ], - [ - -20, - 26 - ] - ], - [ - [ - 15555, - 12172 - ], - [ - 23, - -22 - ], - [ - 13, - -49 - ], - [ - 32, - -51 - ], - [ - 34, - 0 - ], - [ - 66, - 31 - ], - [ - 76, - 14 - ], - [ - 61, - 37 - ], - [ - 35, - 8 - ], - [ - 25, - 22 - ], - [ - 40, - 4 - ] - ], - [ - [ - 15960, - 12166 - ], - [ - -1, - -2 - ], - [ - 0, - -49 - ], - [ - 0, - -121 - ], - [ - 0, - -63 - ], - [ - -32, - -74 - ], - [ - -48, - -100 - ] - ], - [ - [ - 15960, - 12166 - ], - [ - 22, - 2 - ], - [ - 32, - 18 - ], - [ - 37, - 12 - ], - [ - 33, - 41 - ], - [ - 26, - 1 - ], - [ - 2, - -33 - ], - [ - -6, - -70 - ], - [ - 0, - -63 - ], - [ - -15, - -44 - ], - [ - -20, - -129 - ], - [ - -33, - -134 - ], - [ - -43, - -153 - ], - [ - -60, - -176 - ], - [ - -60, - -135 - ], - [ - -82, - -163 - ], - [ - -69, - -97 - ], - [ - -105, - -120 - ], - [ - -65, - -91 - ], - [ - -76, - -145 - ], - [ - -16, - -63 - ], - [ - -16, - -29 - ] - ], - [ - [ - 8564, - 11514 - ], - [ - 83, - -24 - ], - [ - 8, - 21 - ], - [ - 56, - 9 - ], - [ - 75, - -32 - ] - ], - [ - [ - 14120, - 16686 - ], - [ - -19, - -31 - ], - [ - -14, - -49 - ] - ], - [ - [ - 13504, - 16256 - ], - [ - 15, - 11 - ] - ], - [ - [ - 14214, - 18716 - ], - [ - -120, - -34 - ], - [ - -68, - -84 - ], - [ - 11, - -73 - ], - [ - -111, - -97 - ], - [ - -134, - -103 - ], - [ - -51, - -169 - ], - [ - 49, - -84 - ], - [ - 67, - -67 - ], - [ - -64, - -135 - ], - [ - -72, - -28 - ], - [ - -27, - -202 - ], - [ - -40, - -112 - ], - [ - -84, - 12 - ], - [ - -40, - -96 - ], - [ - -80, - -5 - ], - [ - -22, - 113 - ], - [ - -59, - 136 - ], - [ - -53, - 170 - ] - ], - [ - [ - 14783, - 7590 - ], - [ - -14, - -53 - ], - [ - -41, - -13 - ], - [ - -41, - 65 - ], - [ - -1, - 41 - ], - [ - 19, - 45 - ], - [ - 7, - 35 - ], - [ - 20, - 9 - ], - [ - 35, - -22 - ] - ], - [ - [ - 15057, - 14954 - ], - [ - -7, - 91 - ], - [ - 17, - 50 - ] - ], - [ - [ - 15067, - 15095 - ], - [ - 19, - 26 - ], - [ - 19, - 26 - ], - [ - 4, - 67 - ], - [ - 22, - -23 - ], - [ - 77, - 33 - ], - [ - 37, - -22 - ], - [ - 58, - 0 - ], - [ - 80, - 45 - ], - [ - 37, - -2 - ], - [ - 80, - 19 - ] - ], - [ - [ - 12678, - 11534 - ], - [ - -57, - -26 - ] - ], - [ - [ - 19699, - 12259 - ], - [ - -63, - 55 - ], - [ - -60, - -2 - ], - [ - 11, - 94 - ], - [ - -62, - 0 - ], - [ - -5, - -132 - ], - [ - -38, - -176 - ], - [ - -23, - -106 - ], - [ - 5, - -86 - ], - [ - 46, - -4 - ], - [ - 28, - -110 - ], - [ - 12, - -103 - ], - [ - 39, - -69 - ], - [ - 42, - -14 - ], - [ - 37, - -62 - ] - ], - [ - [ - 19524, - 11573 - ], - [ - -27, - 46 - ], - [ - -12, - 59 - ], - [ - -37, - 68 - ], - [ - -34, - 57 - ], - [ - -11, - -71 - ], - [ - -14, - 67 - ], - [ - 8, - 75 - ], - [ - 21, - 115 - ] - ], - [ - [ - 17276, - 15253 - ], - [ - 39, - 122 - ], - [ - -15, - 89 - ], - [ - -51, - 29 - ], - [ - 18, - 53 - ], - [ - 58, - -6 - ], - [ - 33, - 66 - ], - [ - 22, - 77 - ], - [ - 94, - 28 - ], - [ - -15, - -55 - ], - [ - 10, - -34 - ], - [ - 29, - 3 - ] - ], - [ - [ - 16306, - 15260 - ], - [ - -13, - 85 - ], - [ - 10, - 125 - ], - [ - -54, - 41 - ], - [ - 18, - 82 - ], - [ - -46, - 7 - ], - [ - 15, - 101 - ], - [ - 66, - -29 - ], - [ - 61, - 38 - ], - [ - -51, - 72 - ], - [ - -20, - 69 - ], - [ - -56, - -31 - ], - [ - -7, - -88 - ], - [ - -22, - 78 - ] - ], - [ - [ - 16449, - 15753 - ], - [ - 79, - 2 - ], - [ - -12, - 60 - ], - [ - 60, - 41 - ], - [ - 58, - 70 - ], - [ - 94, - -63 - ], - [ - 8, - -96 - ], - [ - 26, - -25 - ], - [ - 76, - 6 - ], - [ - 23, - -22 - ], - [ - 35, - -124 - ], - [ - 79, - -82 - ], - [ - 46, - -57 - ], - [ - 73, - -59 - ], - [ - 92, - -51 - ], - [ - -2, - -73 - ] - ], - [ - [ - 21259, - 9730 - ], - [ - 8, - 29 - ], - [ - 60, - 27 - ], - [ - 49, - 4 - ], - [ - 21, - 15 - ], - [ - 27, - -15 - ], - [ - -26, - -33 - ], - [ - -72, - -52 - ], - [ - -59, - -35 - ] - ], - [ - [ - 8248, - 12088 - ], - [ - 40, - 16 - ], - [ - 15, - -5 - ], - [ - -3, - -89 - ], - [ - -58, - -13 - ], - [ - -13, - 11 - ], - [ - 20, - 33 - ], - [ - -1, - 47 - ] - ], - [ - [ - 13135, - 15230 - ], - [ - 75, - 48 - ], - [ - 49, - -14 - ], - [ - -2, - -61 - ], - [ - 59, - 44 - ], - [ - 5, - -23 - ], - [ - -35, - -59 - ], - [ - 0, - -55 - ], - [ - 24, - -30 - ], - [ - -9, - -104 - ], - [ - -46, - -60 - ], - [ - 13, - -66 - ], - [ - 36, - -2 - ], - [ - 18, - -57 - ], - [ - 26, - -18 - ] - ], - [ - [ - 15067, - 15095 - ], - [ - -25, - 54 - ], - [ - 26, - 45 - ], - [ - -42, - -10 - ], - [ - -59, - 28 - ], - [ - -48, - -70 - ], - [ - -105, - -13 - ], - [ - -57, - 64 - ], - [ - -75, - 4 - ], - [ - -16, - -49 - ], - [ - -48, - -15 - ], - [ - -68, - 64 - ], - [ - -76, - -2 - ], - [ - -41, - 119 - ], - [ - -51, - 67 - ], - [ - 34, - 93 - ], - [ - -44, - 58 - ], - [ - 77, - 114 - ], - [ - 107, - 5 - ], - [ - 30, - 91 - ], - [ - 133, - -16 - ], - [ - 83, - 78 - ], - [ - 82, - 34 - ], - [ - 115, - 3 - ], - [ - 122, - -85 - ], - [ - 100, - -46 - ], - [ - 81, - 18 - ], - [ - 60, - -10 - ], - [ - 82, - 62 - ] - ], - [ - [ - 14499, - 15837 - ], - [ - 8, - -46 - ], - [ - 61, - -39 - ], - [ - -12, - -29 - ], - [ - -83, - -7 - ], - [ - -30, - -37 - ], - [ - -58, - -65 - ], - [ - -22, - 56 - ], - [ - 1, - 25 - ] - ], - [ - [ - 21036, - 13724 - ], - [ - -42, - -193 - ], - [ - -29, - -98 - ], - [ - -37, - 101 - ], - [ - -8, - 89 - ], - [ - 41, - 118 - ], - [ - 56, - 91 - ], - [ - 32, - -36 - ], - [ - -13, - -72 - ] - ], - [ - [ - 14668, - 10661 - ], - [ - 24, - 14 - ], - [ - 77, - -1 - ], - [ - 142, - 9 - ] - ], - [ - [ - 15280, - 10236 - ], - [ - -32, - -148 - ], - [ - 4, - -68 - ], - [ - 45, - -43 - ], - [ - 2, - -32 - ], - [ - -19, - -72 - ], - [ - 4, - -36 - ], - [ - -5, - -58 - ], - [ - 24, - -75 - ], - [ - 29, - -118 - ], - [ - 26, - -27 - ] - ], - [ - [ - 14831, - 9690 - ], - [ - -39, - 36 - ], - [ - -45, - 20 - ], - [ - -28, - 20 - ], - [ - -29, - 31 - ] - ], - [ - [ - 15212, - 16448 - ], - [ - -56, - -10 - ], - [ - -46, - -38 - ], - [ - -65, - -7 - ], - [ - -60, - -44 - ], - [ - 3, - -65 - ] - ], - [ - [ - 14878, - 16312 - ], - [ - -9, - 13 - ], - [ - -109, - 31 - ], - [ - -4, - 44 - ], - [ - -65, - -14 - ], - [ - -26, - -66 - ], - [ - -54, - -89 - ] - ], - [ - [ - 8827, - 6746 - ], - [ - -30, - -75 - ], - [ - -79, - -67 - ], - [ - -51, - 24 - ], - [ - -38, - -13 - ], - [ - -65, - 52 - ], - [ - -47, - -4 - ], - [ - -42, - 66 - ] - ], - [ - [ - 7867, - 16212 - ], - [ - 13, - -39 - ], - [ - -75, - -58 - ], - [ - -72, - -42 - ], - [ - -73, - -35 - ], - [ - -37, - -71 - ], - [ - -12, - -27 - ], - [ - -1, - -64 - ], - [ - 23, - -64 - ], - [ - 29, - -3 - ], - [ - -7, - 44 - ], - [ - 21, - -26 - ], - [ - -6, - -35 - ], - [ - -47, - -19 - ], - [ - -33, - 2 - ], - [ - -52, - -21 - ], - [ - -30, - -6 - ], - [ - -41, - -6 - ], - [ - -58, - -34 - ], - [ - 103, - 22 - ], - [ - 20, - -22 - ], - [ - -97, - -36 - ], - [ - -45, - -1 - ], - [ - 2, - 15 - ], - [ - -21, - -33 - ], - [ - 21, - -6 - ], - [ - -15, - -86 - ], - [ - -51, - -92 - ], - [ - -5, - 31 - ], - [ - -16, - 6 - ], - [ - -22, - 30 - ], - [ - 14, - -65 - ], - [ - 17, - -21 - ], - [ - 1, - -46 - ], - [ - -22, - -46 - ], - [ - -39, - -96 - ], - [ - -7, - 5 - ], - [ - 22, - 81 - ], - [ - -36, - 46 - ], - [ - -8, - 100 - ], - [ - -13, - -52 - ], - [ - 15, - -76 - ], - [ - -46, - 19 - ], - [ - 48, - -39 - ], - [ - 3, - -114 - ], - [ - 20, - -8 - ], - [ - 7, - -42 - ], - [ - 10, - -120 - ], - [ - -45, - -89 - ], - [ - -72, - -35 - ], - [ - -46, - -71 - ], - [ - -34, - -8 - ], - [ - -36, - -44 - ], - [ - -10, - -40 - ], - [ - -76, - -78 - ], - [ - -39, - -57 - ], - [ - -33, - -71 - ], - [ - -11, - -85 - ], - [ - 12, - -83 - ], - [ - 24, - -103 - ], - [ - 30, - -85 - ], - [ - 1, - -52 - ], - [ - 33, - -139 - ], - [ - -2, - -81 - ], - [ - -3, - -47 - ], - [ - -18, - -73 - ], - [ - -21, - -15 - ], - [ - -34, - 15 - ], - [ - -11, - 52 - ], - [ - -26, - 28 - ], - [ - -37, - 103 - ], - [ - -33, - 92 - ], - [ - -10, - 47 - ], - [ - 14, - 79 - ], - [ - -19, - 66 - ], - [ - -55, - 101 - ], - [ - -27, - 18 - ], - [ - -70, - -54 - ], - [ - -13, - 6 - ], - [ - -34, - 56 - ], - [ - -43, - 29 - ], - [ - -79, - -15 - ], - [ - -62, - 13 - ], - [ - -53, - -8 - ], - [ - -29, - -19 - ], - [ - 13, - -31 - ], - [ - -2, - -49 - ], - [ - 15, - -24 - ], - [ - -13, - -16 - ], - [ - -26, - 18 - ], - [ - -26, - -23 - ], - [ - -51, - 4 - ], - [ - -52, - 64 - ], - [ - -60, - -15 - ], - [ - -51, - 27 - ], - [ - -44, - -8 - ], - [ - -58, - -28 - ], - [ - -64, - -89 - ], - [ - -69, - -52 - ], - [ - -38, - -57 - ], - [ - -16, - -54 - ], - [ - -1, - -83 - ], - [ - 4, - -57 - ], - [ - 13, - -41 - ] - ], - [ - [ - 4383, - 14700 - ], - [ - -12, - 62 - ], - [ - -45, - 69 - ], - [ - -33, - 14 - ], - [ - -7, - 34 - ], - [ - -39, - 6 - ], - [ - -25, - 33 - ], - [ - -65, - 12 - ], - [ - -18, - 19 - ], - [ - -8, - 66 - ], - [ - -68, - 120 - ], - [ - -58, - 167 - ], - [ - 2, - 28 - ], - [ - -30, - 40 - ], - [ - -54, - 100 - ], - [ - -10, - 98 - ], - [ - -37, - 66 - ], - [ - 15, - 99 - ], - [ - -2, - 103 - ], - [ - -22, - 92 - ], - [ - 27, - 113 - ], - [ - 8, - 109 - ], - [ - 9, - 109 - ], - [ - -13, - 161 - ], - [ - -22, - 102 - ], - [ - -20, - 56 - ], - [ - 8, - 23 - ], - [ - 101, - -41 - ], - [ - 37, - -113 - ], - [ - 17, - 32 - ], - [ - -11, - 98 - ], - [ - -23, - 99 - ] - ], - [ - [ - 3448, - 17372 - ], - [ - -38, - 45 - ], - [ - -62, - 38 - ], - [ - -19, - 105 - ], - [ - -90, - 97 - ], - [ - -38, - 113 - ], - [ - -67, - 8 - ], - [ - -111, - 3 - ], - [ - -81, - 34 - ], - [ - -144, - 125 - ], - [ - -67, - 23 - ], - [ - -122, - 42 - ], - [ - -97, - -10 - ], - [ - -137, - 55 - ], - [ - -83, - 51 - ], - [ - -77, - -25 - ], - [ - 14, - -83 - ], - [ - -38, - -8 - ], - [ - -81, - -25 - ], - [ - -61, - -40 - ], - [ - -77, - -26 - ], - [ - -10, - 71 - ], - [ - 31, - 117 - ], - [ - 74, - 37 - ], - [ - -19, - 30 - ], - [ - -89, - -66 - ], - [ - -47, - -80 - ], - [ - -101, - -86 - ], - [ - 51, - -58 - ], - [ - -66, - -86 - ], - [ - -75, - -50 - ], - [ - -69, - -37 - ], - [ - -18, - -53 - ], - [ - -109, - -62 - ], - [ - -22, - -56 - ], - [ - -81, - -52 - ], - [ - -48, - 10 - ], - [ - -65, - -34 - ], - [ - -71, - -41 - ], - [ - -58, - -40 - ], - [ - -119, - -34 - ], - [ - -11, - 20 - ], - [ - 76, - 56 - ], - [ - 68, - 37 - ], - [ - 74, - 66 - ], - [ - 87, - 13 - ], - [ - 34, - 50 - ], - [ - 97, - 71 - ], - [ - 15, - 24 - ], - [ - 52, - 43 - ], - [ - 12, - 91 - ], - [ - 35, - 71 - ], - [ - -80, - -37 - ], - [ - -22, - 21 - ], - [ - -38, - -44 - ], - [ - -46, - 61 - ], - [ - -19, - -43 - ], - [ - -26, - 60 - ], - [ - -69, - -48 - ], - [ - -43, - 0 - ], - [ - -6, - 71 - ], - [ - 13, - 44 - ], - [ - -45, - 43 - ], - [ - -91, - -23 - ], - [ - -59, - 56 - ], - [ - -48, - 29 - ], - [ - 0, - 68 - ], - [ - -54, - 51 - ], - [ - 27, - 69 - ], - [ - 57, - 67 - ], - [ - 25, - 62 - ], - [ - 57, - 9 - ], - [ - 47, - -20 - ], - [ - 57, - 58 - ], - [ - 50, - -10 - ], - [ - 53, - 37 - ], - [ - -13, - 55 - ], - [ - -39, - 22 - ], - [ - 52, - 46 - ], - [ - -43, - -2 - ], - [ - -74, - -26 - ], - [ - -21, - -26 - ], - [ - -55, - 26 - ], - [ - -99, - -13 - ], - [ - -102, - 29 - ], - [ - -29, - 48 - ], - [ - -88, - 70 - ], - [ - 98, - 50 - ], - [ - 155, - 58 - ], - [ - 58, - 0 - ], - [ - -10, - -60 - ], - [ - 147, - 5 - ], - [ - -56, - 74 - ], - [ - -86, - 46 - ], - [ - -50, - 60 - ], - [ - -67, - 51 - ], - [ - -95, - 38 - ], - [ - 39, - 63 - ], - [ - 123, - 4 - ], - [ - 88, - 55 - ], - [ - 17, - 58 - ], - [ - 71, - 57 - ], - [ - 68, - 14 - ], - [ - 132, - 53 - ], - [ - 64, - -8 - ], - [ - 108, - 64 - ], - [ - 105, - -25 - ], - [ - 50, - -54 - ], - [ - 31, - 23 - ], - [ - 118, - -7 - ], - [ - -4, - -28 - ], - [ - 107, - -20 - ], - [ - 71, - 12 - ], - [ - 147, - -38 - ], - [ - 134, - -12 - ], - [ - 53, - -15 - ], - [ - 93, - 19 - ], - [ - 106, - -36 - ], - [ - 76, - -17 - ] - ], - [ - [ - 1705, - 13087 - ], - [ - -10, - -20 - ], - [ - -18, - 17 - ], - [ - 2, - 33 - ], - [ - -11, - 44 - ], - [ - 3, - 13 - ], - [ - 12, - 20 - ], - [ - -4, - 23 - ], - [ - 4, - 12 - ], - [ - 5, - -3 - ], - [ - 27, - -20 - ], - [ - 12, - -10 - ], - [ - 11, - -16 - ], - [ - 18, - -42 - ], - [ - -2, - -7 - ], - [ - -27, - -26 - ], - [ - -22, - -18 - ] - ], - [ - [ - 1667, - 13274 - ], - [ - -23, - -9 - ], - [ - -12, - 26 - ], - [ - -8, - 9 - ], - [ - -1, - 8 - ], - [ - 7, - 10 - ], - [ - 25, - -11 - ], - [ - 18, - -19 - ], - [ - -6, - -14 - ] - ], - [ - [ - 1620, - 13338 - ], - [ - -2, - -13 - ], - [ - -37, - 3 - ], - [ - 5, - 15 - ], - [ - 34, - -5 - ] - ], - [ - [ - 1558, - 13355 - ], - [ - -4, - -7 - ], - [ - -5, - 2 - ], - [ - -24, - 4 - ], - [ - -9, - 27 - ], - [ - -3, - 5 - ], - [ - 19, - 17 - ], - [ - 6, - -8 - ], - [ - 20, - -40 - ] - ], - [ - [ - 1440, - 13434 - ], - [ - -8, - -12 - ], - [ - -24, - 22 - ], - [ - 4, - 9 - ], - [ - 10, - 12 - ], - [ - 16, - -3 - ], - [ - 2, - -28 - ] - ], - [ - [ - 1882, - 17649 - ], - [ - -70, - -45 - ], - [ - -36, - 31 - ], - [ - -10, - 56 - ], - [ - 63, - 42 - ], - [ - 37, - 19 - ], - [ - 46, - -8 - ], - [ - 30, - -38 - ], - [ - -60, - -57 - ] - ], - [ - [ - 1005, - 17985 - ], - [ - -43, - -19 - ], - [ - -45, - 22 - ], - [ - -43, - 33 - ], - [ - 69, - 20 - ], - [ - 56, - -10 - ], - [ - 6, - -46 - ] - ], - [ - [ - 576, - 18449 - ], - [ - 43, - -23 - ], - [ - 44, - 13 - ], - [ - 56, - -32 - ], - [ - 69, - -16 - ], - [ - -5, - -13 - ], - [ - -53, - -26 - ], - [ - -53, - 27 - ], - [ - -27, - 21 - ], - [ - -61, - -7 - ], - [ - -17, - 11 - ], - [ - 4, - 45 - ] - ], - [ - [ - 7575, - 12210 - ], - [ - -2, - -28 - ], - [ - -41, - -14 - ], - [ - 23, - -55 - ], - [ - -1, - -63 - ], - [ - -31, - -69 - ], - [ - 27, - -95 - ], - [ - 30, - 7 - ], - [ - 15, - 87 - ], - [ - -21, - 42 - ], - [ - -4, - 91 - ], - [ - 87, - 49 - ], - [ - -10, - 56 - ], - [ - 25, - 38 - ], - [ - 25, - -84 - ], - [ - 49, - -2 - ], - [ - 45, - -67 - ], - [ - 3, - -40 - ], - [ - 62, - -1 - ], - [ - 75, - 13 - ], - [ - 40, - -54 - ], - [ - 53, - -15 - ], - [ - 39, - 38 - ], - [ - 1, - 30 - ], - [ - 86, - 7 - ], - [ - 84, - 2 - ], - [ - -59, - -36 - ], - [ - 24, - -56 - ], - [ - 55, - -9 - ], - [ - 53, - -59 - ], - [ - 11, - -96 - ], - [ - 37, - 2 - ], - [ - 27, - -28 - ] - ], - [ - [ - 20079, - 13383 - ], - [ - -93, - -103 - ], - [ - -58, - -113 - ], - [ - -15, - -83 - ], - [ - 53, - -127 - ], - [ - 66, - -157 - ], - [ - 63, - -74 - ], - [ - 42, - -96 - ], - [ - 32, - -222 - ], - [ - -9, - -211 - ], - [ - -58, - -79 - ], - [ - -80, - -77 - ], - [ - -57, - -100 - ], - [ - -87, - -112 - ], - [ - -25, - 77 - ], - [ - 19, - 81 - ], - [ - -52, - 68 - ] - ], - [ - [ - 24248, - 8822 - ], - [ - -23, - -16 - ], - [ - -24, - 52 - ], - [ - 3, - 33 - ], - [ - 44, - -69 - ] - ], - [ - [ - 24196, - 9006 - ], - [ - 12, - -97 - ], - [ - -19, - 15 - ], - [ - -15, - -7 - ], - [ - -10, - 34 - ], - [ - -1, - 91 - ], - [ - 33, - -36 - ] - ], - [ - [ - 16250, - 12795 - ], - [ - -51, - -32 - ], - [ - -13, - -54 - ], - [ - -2, - -41 - ], - [ - -69, - -50 - ], - [ - -112, - -56 - ], - [ - -62, - -85 - ], - [ - -31, - -6 - ], - [ - -21, - 7 - ], - [ - -40, - -50 - ], - [ - -45, - -23 - ], - [ - -58, - -6 - ], - [ - -18, - -7 - ], - [ - -15, - -32 - ], - [ - -19, - -9 - ], - [ - -10, - -30 - ], - [ - -35, - 2 - ], - [ - -22, - -16 - ], - [ - -48, - 6 - ], - [ - -19, - 70 - ], - [ - 2, - 66 - ], - [ - -11, - 35 - ], - [ - -14, - 89 - ], - [ - -20, - 49 - ], - [ - 14, - 6 - ], - [ - -7, - 55 - ], - [ - 9, - 23 - ], - [ - -3, - 52 - ] - ], - [ - [ - 14599, - 8147 - ], - [ - 29, - -1 - ], - [ - 33, - -21 - ], - [ - 24, - 15 - ], - [ - 37, - -12 - ] - ], - [ - [ - 14836, - 7589 - ], - [ - -17, - -87 - ], - [ - -9, - -100 - ], - [ - -18, - -54 - ], - [ - -47, - -61 - ], - [ - -14, - -17 - ], - [ - -29, - -61 - ], - [ - -20, - -62 - ], - [ - -39, - -86 - ], - [ - -79, - -123 - ], - [ - -49, - -72 - ], - [ - -53, - -55 - ], - [ - -73, - -47 - ], - [ - -35, - -6 - ], - [ - -9, - -33 - ], - [ - -43, - 18 - ], - [ - -34, - -23 - ], - [ - -76, - 23 - ], - [ - -42, - -15 - ], - [ - -29, - 7 - ], - [ - -72, - -48 - ], - [ - -59, - -19 - ], - [ - -43, - -45 - ], - [ - -32, - -3 - ], - [ - -30, - 43 - ], - [ - -23, - 2 - ], - [ - -30, - 54 - ], - [ - -3, - -17 - ], - [ - -10, - 32 - ], - [ - 1, - 70 - ], - [ - -23, - 81 - ], - [ - 23, - 22 - ], - [ - -2, - 92 - ], - [ - -46, - 112 - ], - [ - -35, - 102 - ], - [ - 0, - 0 - ], - [ - -50, - 156 - ] - ], - [ - [ - 14658, - 8937 - ], - [ - -53, - -17 - ], - [ - -40, - -47 - ], - [ - -8, - -42 - ], - [ - -25, - -10 - ], - [ - -61, - -98 - ], - [ - -38, - -78 - ], - [ - -24, - -3 - ], - [ - -22, - 14 - ], - [ - -78, - 13 - ] - ] - ], - "transform": { - "scale": [ - 0.01434548714883443, - 0.008335499711981569 - ], - "translate": [ - -180, - -90 - ] - }, - "objects": { - "ne_110m_admin_0_countries": { - "type": "GeometryCollection", - "geometries": [ - { - "arcs": [ - [ - 0, - 1, - 2, - 3, - 4, - 5 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Afghanistan", - "NAME_LONG": "Afghanistan", - "ABBREV": "Afg.", - "FORMAL_EN": "Islamic State of Afghanistan", - "POP_EST": 34124811, - "POP_RANK": 15, - "GDP_MD_EST": 64080, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AF", - "ISO_A3": "AFG", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - [ - 6, - 7, - 8, - 9 - ] - ], - [ - [ - 10, - 11, - 12 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Angola", - "NAME_LONG": "Angola", - "ABBREV": "Ang.", - "FORMAL_EN": "People's Republic of Angola", - "POP_EST": 29310273, - "POP_RANK": 15, - "GDP_MD_EST": 189000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AO", - "ISO_A3": "AGO", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - 13, - 14, - 15, - 16, - 17 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Albania", - "NAME_LONG": "Albania", - "ABBREV": "Alb.", - "FORMAL_EN": "Republic of Albania", - "POP_EST": 3047987, - "POP_RANK": 12, - "GDP_MD_EST": 33900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AL", - "ISO_A3": "ALB", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - 18, - 19, - 20, - 21, - 22 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "United Arab Emirates", - "NAME_LONG": "United Arab Emirates", - "ABBREV": "U.A.E.", - "FORMAL_EN": "United Arab Emirates", - "POP_EST": 6072475, - "POP_RANK": 13, - "GDP_MD_EST": 667200, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AE", - "ISO_A3": "ARE", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - [ - 23, - 24 - ] - ], - [ - [ - 25, - 26, - 27, - 28, - 29, - 30 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Argentina", - "NAME_LONG": "Argentina", - "ABBREV": "Arg.", - "FORMAL_EN": "Argentine Republic", - "POP_EST": 44293293, - "POP_RANK": 15, - "GDP_MD_EST": 879400, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AR", - "ISO_A3": "ARG", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - 31, - 32, - 33, - 34, - 35 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Armenia", - "NAME_LONG": "Armenia", - "ABBREV": "Arm.", - "FORMAL_EN": "Republic of Armenia", - "POP_EST": 3045191, - "POP_RANK": 12, - "GDP_MD_EST": 26300, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AM", - "ISO_A3": "ARM", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - [ - 36 - ] - ], - [ - [ - 37 - ] - ], - [ - [ - 38 - ] - ], - [ - [ - 39 - ] - ], - [ - [ - 40 - ] - ], - [ - [ - 41 - ] - ], - [ - [ - 42 - ] - ], - [ - [ - 43 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Antarctica", - "NAME_LONG": "Antarctica", - "ABBREV": "Ant.", - "FORMAL_EN": "", - "POP_EST": 4050, - "POP_RANK": 4, - "GDP_MD_EST": 810, - "POP_YEAR": 2013, - "GDP_YEAR": 2013, - "ISO_A2": "AQ", - "ISO_A3": "ATA", - "CONTINENT": "Antarctica", - "REGION_UN": "Antarctica", - "SUBREGION": "Antarctica" - } - }, - { - "arcs": [ - [ - 44 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Fr. S. Antarctic Lands", - "NAME_LONG": "French Southern and Antarctic Lands", - "ABBREV": "Fr. S.A.L.", - "FORMAL_EN": "Territory of the French Southern and Antarctic Lands", - "POP_EST": 140, - "POP_RANK": 1, - "GDP_MD_EST": 16, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TF", - "ISO_A3": "ATF", - "CONTINENT": "Seven seas (open ocean)", - "REGION_UN": "Seven seas (open ocean)", - "SUBREGION": "Seven seas (open ocean)" - } - }, - { - "arcs": [ - [ - [ - 45 - ] - ], - [ - [ - 46 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Australia", - "NAME_LONG": "Australia", - "ABBREV": "Auz.", - "FORMAL_EN": "Commonwealth of Australia", - "POP_EST": 23232413, - "POP_RANK": 15, - "GDP_MD_EST": 1189000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AU", - "ISO_A3": "AUS", - "CONTINENT": "Oceania", - "REGION_UN": "Oceania", - "SUBREGION": "Australia and New Zealand" - } - }, - { - "arcs": [ - [ - 47, - 48, - 49, - 50, - 51, - 52, - 53 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Austria", - "NAME_LONG": "Austria", - "ABBREV": "Aust.", - "FORMAL_EN": "Republic of Austria", - "POP_EST": 8754413, - "POP_RANK": 13, - "GDP_MD_EST": 416600, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AT", - "ISO_A3": "AUT", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Western Europe" - } - }, - { - "arcs": [ - [ - [ - -33, - 54, - 55, - 56, - 57 - ] - ], - [ - [ - -35, - 58 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Azerbaijan", - "NAME_LONG": "Azerbaijan", - "ABBREV": "Aze.", - "FORMAL_EN": "Republic of Azerbaijan", - "POP_EST": 9961396, - "POP_RANK": 13, - "GDP_MD_EST": 167900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AZ", - "ISO_A3": "AZE", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - 59, - 60, - 61 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Burundi", - "NAME_LONG": "Burundi", - "ABBREV": "Bur.", - "FORMAL_EN": "Republic of Burundi", - "POP_EST": 11466756, - "POP_RANK": 14, - "GDP_MD_EST": 7892, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BI", - "ISO_A3": "BDI", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - 62, - 63, - 64, - 65, - 66 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Belgium", - "NAME_LONG": "Belgium", - "ABBREV": "Belg.", - "FORMAL_EN": "Kingdom of Belgium", - "POP_EST": 11491346, - "POP_RANK": 14, - "GDP_MD_EST": 508600, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BE", - "ISO_A3": "BEL", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Western Europe" - } - }, - { - "arcs": [ - [ - 67, - 68, - 69, - 70, - 71 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Benin", - "NAME_LONG": "Benin", - "ABBREV": "Benin", - "FORMAL_EN": "Republic of Benin", - "POP_EST": 11038805, - "POP_RANK": 14, - "GDP_MD_EST": 24310, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BJ", - "ISO_A3": "BEN", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -70, - 72, - 73, - 74, - 75, - 76 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Burkina Faso", - "NAME_LONG": "Burkina Faso", - "ABBREV": "B.F.", - "FORMAL_EN": "Burkina Faso", - "POP_EST": 20107509, - "POP_RANK": 15, - "GDP_MD_EST": 32990, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BF", - "ISO_A3": "BFA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - 77, - 78, - 79 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Bangladesh", - "NAME_LONG": "Bangladesh", - "ABBREV": "Bang.", - "FORMAL_EN": "People's Republic of Bangladesh", - "POP_EST": 157826578, - "POP_RANK": 17, - "GDP_MD_EST": 628400, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BD", - "ISO_A3": "BGD", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - 80, - 81, - 82, - 83, - 84, - 85 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Bulgaria", - "NAME_LONG": "Bulgaria", - "ABBREV": "Bulg.", - "FORMAL_EN": "Republic of Bulgaria", - "POP_EST": 7101510, - "POP_RANK": 13, - "GDP_MD_EST": 143100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BG", - "ISO_A3": "BGR", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - [ - 86 - ] - ], - [ - [ - 87 - ] - ], - [ - [ - 88 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Bahamas", - "NAME_LONG": "Bahamas", - "ABBREV": "Bhs.", - "FORMAL_EN": "Commonwealth of the Bahamas", - "POP_EST": 329988, - "POP_RANK": 10, - "GDP_MD_EST": 9066, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BS", - "ISO_A3": "BHS", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Caribbean" - } - }, - { - "arcs": [ - [ - 89, - 90, - 91 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Bosnia and Herz.", - "NAME_LONG": "Bosnia and Herzegovina", - "ABBREV": "B.H.", - "FORMAL_EN": "Bosnia and Herzegovina", - "POP_EST": 3856181, - "POP_RANK": 12, - "GDP_MD_EST": 42530, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BA", - "ISO_A3": "BIH", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - 92, - 93, - 94, - 95, - 96 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Belarus", - "NAME_LONG": "Belarus", - "ABBREV": "Bela.", - "FORMAL_EN": "Republic of Belarus", - "POP_EST": 9549747, - "POP_RANK": 13, - "GDP_MD_EST": 165400, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BY", - "ISO_A3": "BLR", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - 97, - 98, - 99 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Belize", - "NAME_LONG": "Belize", - "ABBREV": "Belize", - "FORMAL_EN": "Belize", - "POP_EST": 360346, - "POP_RANK": 10, - "GDP_MD_EST": 3088, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BZ", - "ISO_A3": "BLZ", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - -27, - 100, - 101, - 102, - 103 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Bolivia", - "NAME_LONG": "Bolivia", - "ABBREV": "Bolivia", - "FORMAL_EN": "Plurinational State of Bolivia", - "POP_EST": 11138234, - "POP_RANK": 14, - "GDP_MD_EST": 78350, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BO", - "ISO_A3": "BOL", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - -29, - 104, - -103, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Brazil", - "NAME_LONG": "Brazil", - "ABBREV": "Brazil", - "FORMAL_EN": "Federative Republic of Brazil", - "POP_EST": 207353391, - "POP_RANK": 17, - "GDP_MD_EST": 3081000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BR", - "ISO_A3": "BRA", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - 113, - 114 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Brunei", - "NAME_LONG": "Brunei Darussalam", - "ABBREV": "Brunei", - "FORMAL_EN": "Negara Brunei Darussalam", - "POP_EST": 443593, - "POP_RANK": 10, - "GDP_MD_EST": 33730, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BN", - "ISO_A3": "BRN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - 115, - 116 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Bhutan", - "NAME_LONG": "Bhutan", - "ABBREV": "Bhutan", - "FORMAL_EN": "Kingdom of Bhutan", - "POP_EST": 758288, - "POP_RANK": 11, - "GDP_MD_EST": 6432, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BT", - "ISO_A3": "BTN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - 117, - 118, - 119, - 120 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Botswana", - "NAME_LONG": "Botswana", - "ABBREV": "Bwa.", - "FORMAL_EN": "Republic of Botswana", - "POP_EST": 2214858, - "POP_RANK": 12, - "GDP_MD_EST": 35900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BW", - "ISO_A3": "BWA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Southern Africa" - } - }, - { - "arcs": [ - [ - 121, - 122, - 123, - 124, - 125, - 126 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Central African Rep.", - "NAME_LONG": "Central African Republic", - "ABBREV": "C.A.R.", - "FORMAL_EN": "Central African Republic", - "POP_EST": 5625118, - "POP_RANK": 13, - "GDP_MD_EST": 3206, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CF", - "ISO_A3": "CAF", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - [ - 127 - ] - ], - [ - [ - 128 - ] - ], - [ - [ - 129 - ] - ], - [ - [ - 130 - ] - ], - [ - [ - 131 - ] - ], - [ - [ - 132 - ] - ], - [ - [ - 133 - ] - ], - [ - [ - 134 - ] - ], - [ - [ - 135 - ] - ], - [ - [ - 136 - ] - ], - [ - [ - 137, - 138, - 139, - 140 - ] - ], - [ - [ - 141 - ] - ], - [ - [ - 142 - ] - ], - [ - [ - 143 - ] - ], - [ - [ - 144 - ] - ], - [ - [ - 145 - ] - ], - [ - [ - 146 - ] - ], - [ - [ - 147 - ] - ], - [ - [ - 148 - ] - ], - [ - [ - 149 - ] - ], - [ - [ - 150 - ] - ], - [ - [ - 151 - ] - ], - [ - [ - 152 - ] - ], - [ - [ - 153 - ] - ], - [ - [ - 154 - ] - ], - [ - [ - 155 - ] - ], - [ - [ - 156 - ] - ], - [ - [ - 157 - ] - ], - [ - [ - 158 - ] - ], - [ - [ - 159 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Canada", - "NAME_LONG": "Canada", - "ABBREV": "Can.", - "FORMAL_EN": "Canada", - "POP_EST": 35623680, - "POP_RANK": 15, - "GDP_MD_EST": 1674000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CA", - "ISO_A3": "CAN", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Northern America" - } - }, - { - "arcs": [ - [ - -51, - 160, - 161, - 162 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Switzerland", - "NAME_LONG": "Switzerland", - "ABBREV": "Switz.", - "FORMAL_EN": "Swiss Confederation", - "POP_EST": 8236303, - "POP_RANK": 13, - "GDP_MD_EST": 496300, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CH", - "ISO_A3": "CHE", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Western Europe" - } - }, - { - "arcs": [ - [ - [ - -24, - 163 - ] - ], - [ - [ - -26, - 164, - 165, - -101 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Chile", - "NAME_LONG": "Chile", - "ABBREV": "Chile", - "FORMAL_EN": "Republic of Chile", - "POP_EST": 17789267, - "POP_RANK": 14, - "GDP_MD_EST": 436100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CL", - "ISO_A3": "CHL", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - [ - -4, - 166, - 167, - 168, - 169, - 170, - 171, - 172, - 173, - 174, - 175, - 176, - 177, - -117, - 178, - 179, - 180, - 181 - ] - ], - [ - [ - 182 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "China", - "NAME_LONG": "China", - "ABBREV": "China", - "FORMAL_EN": "People's Republic of China", - "POP_EST": 1379302771, - "POP_RANK": 18, - "GDP_MD_EST": 21140000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CN", - "ISO_A3": "CHN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Eastern Asia" - } - }, - { - "arcs": [ - [ - -75, - 183, - 184, - 185, - 186, - 187 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Côte d'Ivoire", - "NAME_LONG": "Côte d'Ivoire", - "ABBREV": "I.C.", - "FORMAL_EN": "Republic of Ivory Coast", - "POP_EST": 24184810, - "POP_RANK": 15, - "GDP_MD_EST": 87120, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CI", - "ISO_A3": "CIV", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -127, - 188, - 189, - 190, - 191, - 192, - 193, - 194 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Cameroon", - "NAME_LONG": "Cameroon", - "ABBREV": "Cam.", - "FORMAL_EN": "Republic of Cameroon", - "POP_EST": 24994885, - "POP_RANK": 15, - "GDP_MD_EST": 77240, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CM", - "ISO_A3": "CMR", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - -9, - 195, - -13, - 196, - -125, - 197, - 198, - 199, - -60, - 200, - 201 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Dem. Rep. Congo", - "NAME_LONG": "Democratic Republic of the Congo", - "ABBREV": "D.R.C.", - "FORMAL_EN": "Democratic Republic of the Congo", - "POP_EST": 83301151, - "POP_RANK": 16, - "GDP_MD_EST": 66010, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CD", - "ISO_A3": "COD", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - -12, - 202, - 203, - -189, - -126, - -197 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Congo", - "NAME_LONG": "Republic of the Congo", - "ABBREV": "Rep. Congo", - "FORMAL_EN": "Republic of the Congo", - "POP_EST": 4954674, - "POP_RANK": 12, - "GDP_MD_EST": 30270, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CG", - "ISO_A3": "COG", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - -107, - 204, - 205, - 206, - 207, - 208, - 209 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Colombia", - "NAME_LONG": "Colombia", - "ABBREV": "Col.", - "FORMAL_EN": "Republic of Colombia", - "POP_EST": 47698524, - "POP_RANK": 15, - "GDP_MD_EST": 688000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CO", - "ISO_A3": "COL", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - 210, - 211, - 212, - 213 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Costa Rica", - "NAME_LONG": "Costa Rica", - "ABBREV": "C.R.", - "FORMAL_EN": "Republic of Costa Rica", - "POP_EST": 4930258, - "POP_RANK": 12, - "GDP_MD_EST": 79260, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CR", - "ISO_A3": "CRI", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - 214 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Cuba", - "NAME_LONG": "Cuba", - "ABBREV": "Cuba", - "FORMAL_EN": "Republic of Cuba", - "POP_EST": 11147407, - "POP_RANK": 14, - "GDP_MD_EST": 132900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CU", - "ISO_A3": "CUB", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Caribbean" - } - }, - { - "arcs": [ - [ - 215, - 216 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "N. Cyprus", - "NAME_LONG": "Northern Cyprus", - "ABBREV": "N. Cy.", - "FORMAL_EN": "Turkish Republic of Northern Cyprus", - "POP_EST": 265100, - "POP_RANK": 10, - "GDP_MD_EST": 3600, - "POP_YEAR": 2013, - "GDP_YEAR": 2013, - "ISO_A2": "-99", - "ISO_A3": "-99", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -217, - 217 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Cyprus", - "NAME_LONG": "Cyprus", - "ABBREV": "Cyp.", - "FORMAL_EN": "Republic of Cyprus", - "POP_EST": 1221549, - "POP_RANK": 12, - "GDP_MD_EST": 29260, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CY", - "ISO_A3": "CYP", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -53, - 218, - 219, - 220 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Czechia", - "NAME_LONG": "Czech Republic", - "ABBREV": "Cz.", - "FORMAL_EN": "Czech Republic", - "POP_EST": 10674723, - "POP_RANK": 14, - "GDP_MD_EST": 350900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CZ", - "ISO_A3": "CZE", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - -52, - -163, - 221, - 222, - -63, - 223, - 224, - 225, - 226, - 227, - -219 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Germany", - "NAME_LONG": "Germany", - "ABBREV": "Ger.", - "FORMAL_EN": "Federal Republic of Germany", - "POP_EST": 80594017, - "POP_RANK": 16, - "GDP_MD_EST": 3979000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "DE", - "ISO_A3": "DEU", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Western Europe" - } - }, - { - "arcs": [ - [ - 228, - 229, - 230, - 231 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Djibouti", - "NAME_LONG": "Djibouti", - "ABBREV": "Dji.", - "FORMAL_EN": "Republic of Djibouti", - "POP_EST": 865267, - "POP_RANK": 11, - "GDP_MD_EST": 3345, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "DJ", - "ISO_A3": "DJI", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - [ - -226, - 232 - ] - ], - [ - [ - 233 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Denmark", - "NAME_LONG": "Denmark", - "ABBREV": "Den.", - "FORMAL_EN": "Kingdom of Denmark", - "POP_EST": 5605948, - "POP_RANK": 13, - "GDP_MD_EST": 264800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "DK", - "ISO_A3": "DNK", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - 234, - 235 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Dominican Rep.", - "NAME_LONG": "Dominican Republic", - "ABBREV": "Dom. Rep.", - "FORMAL_EN": "Dominican Republic", - "POP_EST": 10734247, - "POP_RANK": 14, - "GDP_MD_EST": 161900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "DO", - "ISO_A3": "DOM", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Caribbean" - } - }, - { - "arcs": [ - [ - 236, - 237, - 238, - 239, - 240, - 241, - 242, - 243 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Algeria", - "NAME_LONG": "Algeria", - "ABBREV": "Alg.", - "FORMAL_EN": "People's Democratic Republic of Algeria", - "POP_EST": 40969443, - "POP_RANK": 15, - "GDP_MD_EST": 609400, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "DZ", - "ISO_A3": "DZA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Northern Africa" - } - }, - { - "arcs": [ - [ - -206, - 244, - 245 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Ecuador", - "NAME_LONG": "Ecuador", - "ABBREV": "Ecu.", - "FORMAL_EN": "Republic of Ecuador", - "POP_EST": 16290913, - "POP_RANK": 14, - "GDP_MD_EST": 182400, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "EC", - "ISO_A3": "ECU", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - 246, - 247, - 248, - 249, - 250 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Egypt", - "NAME_LONG": "Egypt", - "ABBREV": "Egypt", - "FORMAL_EN": "Arab Republic of Egypt", - "POP_EST": 97041072, - "POP_RANK": 16, - "GDP_MD_EST": 1105000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "EG", - "ISO_A3": "EGY", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Northern Africa" - } - }, - { - "arcs": [ - [ - -232, - 251, - 252, - 253 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Eritrea", - "NAME_LONG": "Eritrea", - "ABBREV": "Erit.", - "FORMAL_EN": "State of Eritrea", - "POP_EST": 5918919, - "POP_RANK": 13, - "GDP_MD_EST": 9169, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ER", - "ISO_A3": "ERI", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - 254, - 255, - 256, - 257 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Spain", - "NAME_LONG": "Spain", - "ABBREV": "Sp.", - "FORMAL_EN": "Kingdom of Spain", - "POP_EST": 48958159, - "POP_RANK": 15, - "GDP_MD_EST": 1690000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ES", - "ISO_A3": "ESP", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - 258, - 259, - 260 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Estonia", - "NAME_LONG": "Estonia", - "ABBREV": "Est.", - "FORMAL_EN": "Republic of Estonia", - "POP_EST": 1251581, - "POP_RANK": 12, - "GDP_MD_EST": 38700, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "EE", - "ISO_A3": "EST", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - -231, - 261, - 262, - 263, - 264, - 265, - -252 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Ethiopia", - "NAME_LONG": "Ethiopia", - "ABBREV": "Eth.", - "FORMAL_EN": "Federal Democratic Republic of Ethiopia", - "POP_EST": 105350020, - "POP_RANK": 17, - "GDP_MD_EST": 174700, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ET", - "ISO_A3": "ETH", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - 266, - 267, - 268, - 269 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Finland", - "NAME_LONG": "Finland", - "ABBREV": "Fin.", - "FORMAL_EN": "Republic of Finland", - "POP_EST": 5491218, - "POP_RANK": 13, - "GDP_MD_EST": 224137, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "FI", - "ISO_A3": "FIN", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - [ - 270 - ] - ], - [ - [ - 271 - ] - ], - [ - [ - 272 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Fiji", - "NAME_LONG": "Fiji", - "ABBREV": "Fiji", - "FORMAL_EN": "Republic of Fiji", - "POP_EST": 920938, - "POP_RANK": 11, - "GDP_MD_EST": 8374, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "FJ", - "ISO_A3": "FJI", - "CONTINENT": "Oceania", - "REGION_UN": "Oceania", - "SUBREGION": "Melanesia" - } - }, - { - "arcs": [ - [ - 273 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Falkland Is.", - "NAME_LONG": "Falkland Islands", - "ABBREV": "Flk. Is.", - "FORMAL_EN": "Falkland Islands", - "POP_EST": 2931, - "POP_RANK": 4, - "GDP_MD_EST": 281.8, - "POP_YEAR": 2014, - "GDP_YEAR": 2012, - "ISO_A2": "FK", - "ISO_A3": "FLK", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - [ - -65, - 274, - -222, - -162, - 275, - 276, - -256, - 277 - ] - ], - [ - [ - -111, - 278, - 279 - ] - ], - [ - [ - 280 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "France", - "NAME_LONG": "France", - "ABBREV": "Fr.", - "FORMAL_EN": "French Republic", - "POP_EST": 67106161, - "POP_RANK": 16, - "GDP_MD_EST": 2699000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "FR", - "ISO_A3": "FRA", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Western Europe" - } - }, - { - "arcs": [ - [ - -190, - -204, - 281, - 282 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Gabon", - "NAME_LONG": "Gabon", - "ABBREV": "Gabon", - "FORMAL_EN": "Gabonese Republic", - "POP_EST": 1772255, - "POP_RANK": 12, - "GDP_MD_EST": 35980, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GA", - "ISO_A3": "GAB", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - [ - 283, - 284 - ] - ], - [ - [ - 285 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "United Kingdom", - "NAME_LONG": "United Kingdom", - "ABBREV": "U.K.", - "FORMAL_EN": "United Kingdom of Great Britain and Northern Ireland", - "POP_EST": 64769452, - "POP_RANK": 16, - "GDP_MD_EST": 2788000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GB", - "ISO_A3": "GBR", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - -32, - 286, - 287, - 288, - -55 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Georgia", - "NAME_LONG": "Georgia", - "ABBREV": "Geo.", - "FORMAL_EN": "Georgia", - "POP_EST": 4926330, - "POP_RANK": 12, - "GDP_MD_EST": 37270, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GE", - "ISO_A3": "GEO", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -74, - 289, - 290, - -184 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Ghana", - "NAME_LONG": "Ghana", - "ABBREV": "Ghana", - "FORMAL_EN": "Republic of Ghana", - "POP_EST": 27499924, - "POP_RANK": 15, - "GDP_MD_EST": 120800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GH", - "ISO_A3": "GHA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -187, - 291, - 292, - 293, - 294, - 295, - 296 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Guinea", - "NAME_LONG": "Guinea", - "ABBREV": "Gin.", - "FORMAL_EN": "Republic of Guinea", - "POP_EST": 12413867, - "POP_RANK": 14, - "GDP_MD_EST": 16080, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GN", - "ISO_A3": "GIN", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - 297, - 298 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Gambia", - "NAME_LONG": "The Gambia", - "ABBREV": "Gambia", - "FORMAL_EN": "Republic of the Gambia", - "POP_EST": 2051363, - "POP_RANK": 12, - "GDP_MD_EST": 3387, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GM", - "ISO_A3": "GMB", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -295, - 299, - 300 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Guinea-Bissau", - "NAME_LONG": "Guinea-Bissau", - "ABBREV": "GnB.", - "FORMAL_EN": "Republic of Guinea-Bissau", - "POP_EST": 1792338, - "POP_RANK": 12, - "GDP_MD_EST": 2851, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GW", - "ISO_A3": "GNB", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -191, - -283, - 301 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Eq. Guinea", - "NAME_LONG": "Equatorial Guinea", - "ABBREV": "Eq. G.", - "FORMAL_EN": "Republic of Equatorial Guinea", - "POP_EST": 778358, - "POP_RANK": 11, - "GDP_MD_EST": 31770, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GQ", - "ISO_A3": "GNQ", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - [ - -14, - 302, - -84, - 303, - 304 - ] - ], - [ - [ - 305 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Greece", - "NAME_LONG": "Greece", - "ABBREV": "Greece", - "FORMAL_EN": "Hellenic Republic", - "POP_EST": 10768477, - "POP_RANK": 14, - "GDP_MD_EST": 290500, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GR", - "ISO_A3": "GRC", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - 306 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Greenland", - "NAME_LONG": "Greenland", - "ABBREV": "Grlnd.", - "FORMAL_EN": "Greenland", - "POP_EST": 57713, - "POP_RANK": 8, - "GDP_MD_EST": 2173, - "POP_YEAR": 2017, - "GDP_YEAR": 2015, - "ISO_A2": "GL", - "ISO_A3": "GRL", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Northern America" - } - }, - { - "arcs": [ - [ - -100, - 307, - 308, - 309, - 310, - 311 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Guatemala", - "NAME_LONG": "Guatemala", - "ABBREV": "Guat.", - "FORMAL_EN": "Republic of Guatemala", - "POP_EST": 15460732, - "POP_RANK": 14, - "GDP_MD_EST": 131800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GT", - "ISO_A3": "GTM", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - -109, - 312, - 313, - 314 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Guyana", - "NAME_LONG": "Guyana", - "ABBREV": "Guy.", - "FORMAL_EN": "Co-operative Republic of Guyana", - "POP_EST": 737718, - "POP_RANK": 11, - "GDP_MD_EST": 6093, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GY", - "ISO_A3": "GUY", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - -309, - 315, - 316, - 317, - 318 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Honduras", - "NAME_LONG": "Honduras", - "ABBREV": "Hond.", - "FORMAL_EN": "Republic of Honduras", - "POP_EST": 9038741, - "POP_RANK": 13, - "GDP_MD_EST": 43190, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "HN", - "ISO_A3": "HND", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - -91, - 319, - 320, - 321, - 322, - 323 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Croatia", - "NAME_LONG": "Croatia", - "ABBREV": "Cro.", - "FORMAL_EN": "Republic of Croatia", - "POP_EST": 4292095, - "POP_RANK": 12, - "GDP_MD_EST": 94240, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "HR", - "ISO_A3": "HRV", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - -236, - 324 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Haiti", - "NAME_LONG": "Haiti", - "ABBREV": "Haiti", - "FORMAL_EN": "Republic of Haiti", - "POP_EST": 10646714, - "POP_RANK": 14, - "GDP_MD_EST": 19340, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "HT", - "ISO_A3": "HTI", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Caribbean" - } - }, - { - "arcs": [ - [ - -48, - 325, - 326, - 327, - 328, - -323, - 329 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Hungary", - "NAME_LONG": "Hungary", - "ABBREV": "Hun.", - "FORMAL_EN": "Republic of Hungary", - "POP_EST": 9850845, - "POP_RANK": 13, - "GDP_MD_EST": 267600, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "HU", - "ISO_A3": "HUN", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - [ - 330 - ] - ], - [ - [ - 331, - 332 - ] - ], - [ - [ - 333 - ] - ], - [ - [ - 334 - ] - ], - [ - [ - 335 - ] - ], - [ - [ - 336 - ] - ], - [ - [ - 337 - ] - ], - [ - [ - 338 - ] - ], - [ - [ - 339, - 340 - ] - ], - [ - [ - 341 - ] - ], - [ - [ - 342 - ] - ], - [ - [ - 343, - 344 - ] - ], - [ - [ - 345 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Indonesia", - "NAME_LONG": "Indonesia", - "ABBREV": "Indo.", - "FORMAL_EN": "Republic of Indonesia", - "POP_EST": 260580739, - "POP_RANK": 17, - "GDP_MD_EST": 3028000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ID", - "ISO_A3": "IDN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - -80, - 346, - 347, - -181, - 348, - -179, - -116, - -178, - 349 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "India", - "NAME_LONG": "India", - "ABBREV": "India", - "FORMAL_EN": "Republic of India", - "POP_EST": 1281935911, - "POP_RANK": 18, - "GDP_MD_EST": 8721000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "IN", - "ISO_A3": "IND", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - -284, - 350 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Ireland", - "NAME_LONG": "Ireland", - "ABBREV": "Ire.", - "FORMAL_EN": "Ireland", - "POP_EST": 5011102, - "POP_RANK": 13, - "GDP_MD_EST": 322000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "IE", - "ISO_A3": "IRL", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - -6, - 351, - 352, - 353, - 354, - -59, - -34, - -58, - 355, - 356 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Iran", - "NAME_LONG": "Iran", - "ABBREV": "Iran", - "FORMAL_EN": "Islamic Republic of Iran", - "POP_EST": 82021564, - "POP_RANK": 16, - "GDP_MD_EST": 1459000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "IR", - "ISO_A3": "IRN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - -354, - 357, - 358, - 359, - 360, - 361, - 362 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Iraq", - "NAME_LONG": "Iraq", - "ABBREV": "Iraq", - "FORMAL_EN": "Republic of Iraq", - "POP_EST": 39192111, - "POP_RANK": 15, - "GDP_MD_EST": 596700, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "IQ", - "ISO_A3": "IRQ", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - 363 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Iceland", - "NAME_LONG": "Iceland", - "ABBREV": "Iceland", - "FORMAL_EN": "Republic of Iceland", - "POP_EST": 339747, - "POP_RANK": 10, - "GDP_MD_EST": 16150, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "IS", - "ISO_A3": "ISL", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - 364, - 365, - 366, - 367, - 368, - 369, - -250 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Israel", - "NAME_LONG": "Israel", - "ABBREV": "Isr.", - "FORMAL_EN": "State of Israel", - "POP_EST": 8299706, - "POP_RANK": 13, - "GDP_MD_EST": 297000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "IL", - "ISO_A3": "ISR", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - [ - -50, - 370, - 371, - -276, - -161 - ] - ], - [ - [ - 372 - ] - ], - [ - [ - 373 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Italy", - "NAME_LONG": "Italy", - "ABBREV": "Italy", - "FORMAL_EN": "Italian Republic", - "POP_EST": 62137802, - "POP_RANK": 16, - "GDP_MD_EST": 2221000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "IT", - "ISO_A3": "ITA", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - 374 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Jamaica", - "NAME_LONG": "Jamaica", - "ABBREV": "Jam.", - "FORMAL_EN": "Jamaica", - "POP_EST": 2990561, - "POP_RANK": 12, - "GDP_MD_EST": 25390, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "JM", - "ISO_A3": "JAM", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Caribbean" - } - }, - { - "arcs": [ - [ - -361, - 375, - 376, - -370, - 377, - -368, - 378 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Jordan", - "NAME_LONG": "Jordan", - "ABBREV": "Jord.", - "FORMAL_EN": "Hashemite Kingdom of Jordan", - "POP_EST": 10248069, - "POP_RANK": 14, - "GDP_MD_EST": 86190, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "JO", - "ISO_A3": "JOR", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - [ - 379 - ] - ], - [ - [ - 380 - ] - ], - [ - [ - 381 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Japan", - "NAME_LONG": "Japan", - "ABBREV": "Japan", - "FORMAL_EN": "Japan", - "POP_EST": 126451398, - "POP_RANK": 17, - "GDP_MD_EST": 4932000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "JP", - "ISO_A3": "JPN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Eastern Asia" - } - }, - { - "arcs": [ - [ - -169, - 382, - 383, - 384, - 385, - 386 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Kazakhstan", - "NAME_LONG": "Kazakhstan", - "ABBREV": "Kaz.", - "FORMAL_EN": "Republic of Kazakhstan", - "POP_EST": 18556698, - "POP_RANK": 14, - "GDP_MD_EST": 460700, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "KZ", - "ISO_A3": "KAZ", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Central Asia" - } - }, - { - "arcs": [ - [ - -264, - 387, - 388, - 389, - 390, - 391 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Kenya", - "NAME_LONG": "Kenya", - "ABBREV": "Ken.", - "FORMAL_EN": "Republic of Kenya", - "POP_EST": 47615739, - "POP_RANK": 15, - "GDP_MD_EST": 152700, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "KE", - "ISO_A3": "KEN", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -168, - 392, - 393, - -383 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Kyrgyzstan", - "NAME_LONG": "Kyrgyzstan", - "ABBREV": "Kgz.", - "FORMAL_EN": "Kyrgyz Republic", - "POP_EST": 5789122, - "POP_RANK": 13, - "GDP_MD_EST": 21010, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "KG", - "ISO_A3": "KGZ", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Central Asia" - } - }, - { - "arcs": [ - [ - 394, - 395, - 396, - 397 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Cambodia", - "NAME_LONG": "Cambodia", - "ABBREV": "Camb.", - "FORMAL_EN": "Kingdom of Cambodia", - "POP_EST": 16204486, - "POP_RANK": 14, - "GDP_MD_EST": 58940, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "KH", - "ISO_A3": "KHM", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - 398, - 399 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "South Korea", - "NAME_LONG": "Republic of Korea", - "ABBREV": "S.K.", - "FORMAL_EN": "Republic of Korea", - "POP_EST": 51181299, - "POP_RANK": 16, - "GDP_MD_EST": 1929000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "KR", - "ISO_A3": "KOR", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Eastern Asia" - } - }, - { - "arcs": [ - [ - -17, - 400, - 401, - 402 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Kosovo", - "NAME_LONG": "Kosovo", - "ABBREV": "Kos.", - "FORMAL_EN": "Republic of Kosovo", - "POP_EST": 1895250, - "POP_RANK": 12, - "GDP_MD_EST": 18490, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "XK", - "ISO_A3": "-99", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - -359, - 403, - 404 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Kuwait", - "NAME_LONG": "Kuwait", - "ABBREV": "Kwt.", - "FORMAL_EN": "State of Kuwait", - "POP_EST": 2875422, - "POP_RANK": 12, - "GDP_MD_EST": 301100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "KW", - "ISO_A3": "KWT", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -176, - 405, - -396, - 406, - 407 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Laos", - "NAME_LONG": "Lao PDR", - "ABBREV": "Laos", - "FORMAL_EN": "Lao People's Democratic Republic", - "POP_EST": 7126706, - "POP_RANK": 13, - "GDP_MD_EST": 40960, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LA", - "ISO_A3": "LAO", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - -366, - 408, - 409 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Lebanon", - "NAME_LONG": "Lebanon", - "ABBREV": "Leb.", - "FORMAL_EN": "Lebanese Republic", - "POP_EST": 6229794, - "POP_RANK": 13, - "GDP_MD_EST": 85160, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LB", - "ISO_A3": "LBN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -186, - 410, - 411, - -292 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Liberia", - "NAME_LONG": "Liberia", - "ABBREV": "Liberia", - "FORMAL_EN": "Republic of Liberia", - "POP_EST": 4689021, - "POP_RANK": 12, - "GDP_MD_EST": 3881, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LR", - "ISO_A3": "LBR", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -243, - 412, - 413, - -248, - 414, - 415, - 416 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Libya", - "NAME_LONG": "Libya", - "ABBREV": "Libya", - "FORMAL_EN": "Libya", - "POP_EST": 6653210, - "POP_RANK": 13, - "GDP_MD_EST": 90890, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LY", - "ISO_A3": "LBY", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Northern Africa" - } - }, - { - "arcs": [ - [ - 417 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Sri Lanka", - "NAME_LONG": "Sri Lanka", - "ABBREV": "Sri L.", - "FORMAL_EN": "Democratic Socialist Republic of Sri Lanka", - "POP_EST": 22409381, - "POP_RANK": 15, - "GDP_MD_EST": 236700, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LK", - "ISO_A3": "LKA", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - 418 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Lesotho", - "NAME_LONG": "Lesotho", - "ABBREV": "Les.", - "FORMAL_EN": "Kingdom of Lesotho", - "POP_EST": 1958042, - "POP_RANK": 12, - "GDP_MD_EST": 6019, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LS", - "ISO_A3": "LSO", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Southern Africa" - } - }, - { - "arcs": [ - [ - -93, - 419, - 420, - 421, - 422 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Lithuania", - "NAME_LONG": "Lithuania", - "ABBREV": "Lith.", - "FORMAL_EN": "Republic of Lithuania", - "POP_EST": 2823859, - "POP_RANK": 12, - "GDP_MD_EST": 85620, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LT", - "ISO_A3": "LTU", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - -64, - -223, - -275 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Luxembourg", - "NAME_LONG": "Luxembourg", - "ABBREV": "Lux.", - "FORMAL_EN": "Grand Duchy of Luxembourg", - "POP_EST": 594130, - "POP_RANK": 11, - "GDP_MD_EST": 58740, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LU", - "ISO_A3": "LUX", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Western Europe" - } - }, - { - "arcs": [ - [ - -94, - -423, - 423, - -261, - 424 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Latvia", - "NAME_LONG": "Latvia", - "ABBREV": "Lat.", - "FORMAL_EN": "Republic of Latvia", - "POP_EST": 1944643, - "POP_RANK": 12, - "GDP_MD_EST": 50650, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LV", - "ISO_A3": "LVA", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - -240, - 425, - 426 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Morocco", - "NAME_LONG": "Morocco", - "ABBREV": "Mor.", - "FORMAL_EN": "Kingdom of Morocco", - "POP_EST": 33986655, - "POP_RANK": 15, - "GDP_MD_EST": 282800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MA", - "ISO_A3": "MAR", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Northern Africa" - } - }, - { - "arcs": [ - [ - 427, - 428 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Moldova", - "NAME_LONG": "Moldova", - "ABBREV": "Mda.", - "FORMAL_EN": "Republic of Moldova", - "POP_EST": 3474121, - "POP_RANK": 12, - "GDP_MD_EST": 18540, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MD", - "ISO_A3": "MDA", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - 429 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Madagascar", - "NAME_LONG": "Madagascar", - "ABBREV": "Mad.", - "FORMAL_EN": "Republic of Madagascar", - "POP_EST": 25054161, - "POP_RANK": 15, - "GDP_MD_EST": 36860, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MG", - "ISO_A3": "MDG", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -98, - -312, - 430, - 431, - 432 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Mexico", - "NAME_LONG": "Mexico", - "ABBREV": "Mex.", - "FORMAL_EN": "United Mexican States", - "POP_EST": 124574795, - "POP_RANK": 17, - "GDP_MD_EST": 2307000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MX", - "ISO_A3": "MEX", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - -18, - -403, - 433, - -85, - -303 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Macedonia", - "NAME_LONG": "Macedonia", - "ABBREV": "Mkd.", - "FORMAL_EN": "Former Yugoslav Republic of Macedonia", - "POP_EST": 2103721, - "POP_RANK": 12, - "GDP_MD_EST": 29520, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MK", - "ISO_A3": "MKD", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - -76, - -188, - -297, - 434, - 435, - -237, - 436 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Mali", - "NAME_LONG": "Mali", - "ABBREV": "Mali", - "FORMAL_EN": "Republic of Mali", - "POP_EST": 17885245, - "POP_RANK": 14, - "GDP_MD_EST": 38090, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ML", - "ISO_A3": "MLI", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -78, - -350, - -177, - -408, - 437, - 438 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Myanmar", - "NAME_LONG": "Myanmar", - "ABBREV": "Myan.", - "FORMAL_EN": "Republic of the Union of Myanmar", - "POP_EST": 55123814, - "POP_RANK": 16, - "GDP_MD_EST": 311100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MM", - "ISO_A3": "MMR", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - -16, - 439, - -320, - -90, - 440, - -401 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Montenegro", - "NAME_LONG": "Montenegro", - "ABBREV": "Mont.", - "FORMAL_EN": "Montenegro", - "POP_EST": 642550, - "POP_RANK": 11, - "GDP_MD_EST": 10610, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ME", - "ISO_A3": "MNE", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - -171, - 441 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Mongolia", - "NAME_LONG": "Mongolia", - "ABBREV": "Mong.", - "FORMAL_EN": "Mongolia", - "POP_EST": 3068243, - "POP_RANK": 12, - "GDP_MD_EST": 37000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MN", - "ISO_A3": "MNG", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Eastern Asia" - } - }, - { - "arcs": [ - [ - 442, - 443, - 444, - 445, - 446, - 447, - 448, - 449 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Mozambique", - "NAME_LONG": "Mozambique", - "ABBREV": "Moz.", - "FORMAL_EN": "Republic of Mozambique", - "POP_EST": 26573706, - "POP_RANK": 15, - "GDP_MD_EST": 35010, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MZ", - "ISO_A3": "MOZ", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -238, - -436, - 450, - 451, - 452 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Mauritania", - "NAME_LONG": "Mauritania", - "ABBREV": "Mrt.", - "FORMAL_EN": "Islamic Republic of Mauritania", - "POP_EST": 3758571, - "POP_RANK": 12, - "GDP_MD_EST": 16710, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MR", - "ISO_A3": "MRT", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -450, - 453, - 454 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Malawi", - "NAME_LONG": "Malawi", - "ABBREV": "Mal.", - "FORMAL_EN": "Republic of Malawi", - "POP_EST": 19196246, - "POP_RANK": 14, - "GDP_MD_EST": 21200, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MW", - "ISO_A3": "MWI", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - [ - -115, - 455, - -344, - 456 - ] - ], - [ - [ - 457, - 458 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Malaysia", - "NAME_LONG": "Malaysia", - "ABBREV": "Malay.", - "FORMAL_EN": "Malaysia", - "POP_EST": 31381992, - "POP_RANK": 15, - "GDP_MD_EST": 863000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MY", - "ISO_A3": "MYS", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - -7, - 459, - -119, - 460, - 461 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Namibia", - "NAME_LONG": "Namibia", - "ABBREV": "Nam.", - "FORMAL_EN": "Republic of Namibia", - "POP_EST": 2484780, - "POP_RANK": 12, - "GDP_MD_EST": 25990, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NA", - "ISO_A3": "NAM", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Southern Africa" - } - }, - { - "arcs": [ - [ - 462 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "New Caledonia", - "NAME_LONG": "New Caledonia", - "ABBREV": "New C.", - "FORMAL_EN": "New Caledonia", - "POP_EST": 279070, - "POP_RANK": 10, - "GDP_MD_EST": 10770, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NC", - "ISO_A3": "NCL", - "CONTINENT": "Oceania", - "REGION_UN": "Oceania", - "SUBREGION": "Melanesia" - } - }, - { - "arcs": [ - [ - -71, - -77, - -437, - -244, - -417, - 463, - -194, - 464 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Niger", - "NAME_LONG": "Niger", - "ABBREV": "Niger", - "FORMAL_EN": "Republic of Niger", - "POP_EST": 19245344, - "POP_RANK": 14, - "GDP_MD_EST": 20150, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NE", - "ISO_A3": "NER", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -72, - -465, - -193, - 465 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Nigeria", - "NAME_LONG": "Nigeria", - "ABBREV": "Nigeria", - "FORMAL_EN": "Federal Republic of Nigeria", - "POP_EST": 190632261, - "POP_RANK": 17, - "GDP_MD_EST": 1089000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NG", - "ISO_A3": "NGA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -212, - 466, - -317, - 467 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Nicaragua", - "NAME_LONG": "Nicaragua", - "ABBREV": "Nic.", - "FORMAL_EN": "Republic of Nicaragua", - "POP_EST": 6025951, - "POP_RANK": 13, - "GDP_MD_EST": 33550, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NI", - "ISO_A3": "NIC", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - -67, - 468, - -224 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Netherlands", - "NAME_LONG": "Netherlands", - "ABBREV": "Neth.", - "FORMAL_EN": "Kingdom of the Netherlands", - "POP_EST": 17084719, - "POP_RANK": 14, - "GDP_MD_EST": 870800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NL", - "ISO_A3": "NLD", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Western Europe" - } - }, - { - "arcs": [ - [ - [ - -268, - 469, - 470, - 471 - ] - ], - [ - [ - 472 - ] - ], - [ - [ - 473 - ] - ], - [ - [ - 474 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Norway", - "NAME_LONG": "Norway", - "ABBREV": "Nor.", - "FORMAL_EN": "Kingdom of Norway", - "POP_EST": 5320045, - "POP_RANK": 13, - "GDP_MD_EST": 364700, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NO", - "ISO_A3": "NOR", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - -180, - -349 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Nepal", - "NAME_LONG": "Nepal", - "ABBREV": "Nepal", - "FORMAL_EN": "Nepal", - "POP_EST": 29384297, - "POP_RANK": 15, - "GDP_MD_EST": 71520, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NP", - "ISO_A3": "NPL", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - [ - 475 - ] - ], - [ - [ - 476 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "New Zealand", - "NAME_LONG": "New Zealand", - "ABBREV": "N.Z.", - "FORMAL_EN": "New Zealand", - "POP_EST": 4510327, - "POP_RANK": 12, - "GDP_MD_EST": 174800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NZ", - "ISO_A3": "NZL", - "CONTINENT": "Oceania", - "REGION_UN": "Oceania", - "SUBREGION": "Australia and New Zealand" - } - }, - { - "arcs": [ - [ - [ - -20, - 477 - ] - ], - [ - [ - -22, - 478, - 479, - 480 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Oman", - "NAME_LONG": "Oman", - "ABBREV": "Oman", - "FORMAL_EN": "Sultanate of Oman", - "POP_EST": 3424386, - "POP_RANK": 12, - "GDP_MD_EST": 173100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "OM", - "ISO_A3": "OMN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -5, - -182, - -348, - 481, - -352 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Pakistan", - "NAME_LONG": "Pakistan", - "ABBREV": "Pak.", - "FORMAL_EN": "Islamic Republic of Pakistan", - "POP_EST": 204924861, - "POP_RANK": 17, - "GDP_MD_EST": 988200, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PK", - "ISO_A3": "PAK", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - -208, - 482, - -214, - 483 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Panama", - "NAME_LONG": "Panama", - "ABBREV": "Pan.", - "FORMAL_EN": "Republic of Panama", - "POP_EST": 3753142, - "POP_RANK": 12, - "GDP_MD_EST": 93120, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PA", - "ISO_A3": "PAN", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - -102, - -166, - 484, - -245, - -205, - -106 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Peru", - "NAME_LONG": "Peru", - "ABBREV": "Peru", - "FORMAL_EN": "Republic of Peru", - "POP_EST": 31036656, - "POP_RANK": 15, - "GDP_MD_EST": 410400, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PE", - "ISO_A3": "PER", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - [ - 485 - ] - ], - [ - [ - 486 - ] - ], - [ - [ - 487 - ] - ], - [ - [ - 488 - ] - ], - [ - [ - 489 - ] - ], - [ - [ - 490 - ] - ], - [ - [ - 491 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Philippines", - "NAME_LONG": "Philippines", - "ABBREV": "Phil.", - "FORMAL_EN": "Republic of the Philippines", - "POP_EST": 104256076, - "POP_RANK": 17, - "GDP_MD_EST": 801900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PH", - "ISO_A3": "PHL", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - [ - -340, - 492 - ] - ], - [ - [ - 493 - ] - ], - [ - [ - 494 - ] - ], - [ - [ - 495 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Papua New Guinea", - "NAME_LONG": "Papua New Guinea", - "ABBREV": "P.N.G.", - "FORMAL_EN": "Independent State of Papua New Guinea", - "POP_EST": 6909701, - "POP_RANK": 13, - "GDP_MD_EST": 28020, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PG", - "ISO_A3": "PNG", - "CONTINENT": "Oceania", - "REGION_UN": "Oceania", - "SUBREGION": "Melanesia" - } - }, - { - "arcs": [ - [ - -97, - 496, - 497, - -220, - -228, - 498, - 499, - -420 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Poland", - "NAME_LONG": "Poland", - "ABBREV": "Pol.", - "FORMAL_EN": "Republic of Poland", - "POP_EST": 38476269, - "POP_RANK": 15, - "GDP_MD_EST": 1052000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PL", - "ISO_A3": "POL", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - 500 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Puerto Rico", - "NAME_LONG": "Puerto Rico", - "ABBREV": "P.R.", - "FORMAL_EN": "Commonwealth of Puerto Rico", - "POP_EST": 3351827, - "POP_RANK": 12, - "GDP_MD_EST": 131000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PR", - "ISO_A3": "PRI", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Caribbean" - } - }, - { - "arcs": [ - [ - -173, - 501, - 502, - -400, - 503 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "North Korea", - "NAME_LONG": "Dem. Rep. Korea", - "ABBREV": "N.K.", - "FORMAL_EN": "Democratic People's Republic of Korea", - "POP_EST": 25248140, - "POP_RANK": 15, - "GDP_MD_EST": 40000, - "POP_YEAR": 2013, - "GDP_YEAR": 2016, - "ISO_A2": "KP", - "ISO_A3": "PRK", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Eastern Asia" - } - }, - { - "arcs": [ - [ - -258, - 504 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Portugal", - "NAME_LONG": "Portugal", - "ABBREV": "Port.", - "FORMAL_EN": "Portuguese Republic", - "POP_EST": 10839514, - "POP_RANK": 14, - "GDP_MD_EST": 297100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PT", - "ISO_A3": "PRT", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - -28, - -104, - -105 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Paraguay", - "NAME_LONG": "Paraguay", - "ABBREV": "Para.", - "FORMAL_EN": "Republic of Paraguay", - "POP_EST": 6943739, - "POP_RANK": 13, - "GDP_MD_EST": 64670, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PY", - "ISO_A3": "PRY", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - -369, - -378 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Palestine", - "NAME_LONG": "Palestine", - "ABBREV": "Pal.", - "FORMAL_EN": "West Bank and Gaza", - "POP_EST": 4543126, - "POP_RANK": 12, - "GDP_MD_EST": 21220.77, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PS", - "ISO_A3": "PSE", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - 505, - 506 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Qatar", - "NAME_LONG": "Qatar", - "ABBREV": "Qatar", - "FORMAL_EN": "State of Qatar", - "POP_EST": 2314307, - "POP_RANK": 12, - "GDP_MD_EST": 334500, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "QA", - "ISO_A3": "QAT", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -81, - 507, - -328, - 508, - -429, - 509, - 510 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Romania", - "NAME_LONG": "Romania", - "ABBREV": "Rom.", - "FORMAL_EN": "Romania", - "POP_EST": 21529967, - "POP_RANK": 15, - "GDP_MD_EST": 441000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "RO", - "ISO_A3": "ROU", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - [ - -56, - -289, - 511, - 512, - -95, - -425, - -260, - 513, - -269, - -472, - 514, - -502, - -172, - -442, - -170, - -387, - 515 - ] - ], - [ - [ - -421, - -500, - 516 - ] - ], - [ - [ - 519 - ] - ], - [ - [ - 520 - ] - ], - [ - [ - 521 - ] - ], - [ - [ - 522 - ] - ], - [ - [ - 523 - ] - ], - [ - [ - 524 - ] - ], - [ - [ - 525 - ] - ], - [ - [ - 526 - ] - ], - [ - [ - 527 - ] - ], - [ - [ - 528 - ] - ], - [ - [ - 529 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Russia", - "NAME_LONG": "Russian Federation", - "ABBREV": "Rus.", - "FORMAL_EN": "Russian Federation", - "POP_EST": 142257519, - "POP_RANK": 17, - "GDP_MD_EST": 3745000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "RU", - "ISO_A3": "RUS", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - -61, - -200, - 530, - 531 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Rwanda", - "NAME_LONG": "Rwanda", - "ABBREV": "Rwa.", - "FORMAL_EN": "Republic of Rwanda", - "POP_EST": 11901484, - "POP_RANK": 14, - "GDP_MD_EST": 21970, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "RW", - "ISO_A3": "RWA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -239, - -453, - 532, - -426 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "W. Sahara", - "NAME_LONG": "Western Sahara", - "ABBREV": "W. Sah.", - "FORMAL_EN": "Sahrawi Arab Democratic Republic", - "POP_EST": 603253, - "POP_RANK": 11, - "GDP_MD_EST": 906.5, - "POP_YEAR": 2017, - "GDP_YEAR": 2007, - "ISO_A2": "EH", - "ISO_A3": "ESH", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Northern Africa" - } - }, - { - "arcs": [ - [ - -23, - -481, - 533, - 534, - -376, - -360, - -405, - 535, - -507, - 536 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Saudi Arabia", - "NAME_LONG": "Saudi Arabia", - "ABBREV": "Saud.", - "FORMAL_EN": "Kingdom of Saudi Arabia", - "POP_EST": 28571770, - "POP_RANK": 15, - "GDP_MD_EST": 1731000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SA", - "ISO_A3": "SAU", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -123, - 537, - -415, - -247, - 538, - -253, - -266, - 539 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Sudan", - "NAME_LONG": "Sudan", - "ABBREV": "Sudan", - "FORMAL_EN": "Republic of the Sudan", - "POP_EST": 37345935, - "POP_RANK": 15, - "GDP_MD_EST": 176300, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SD", - "ISO_A3": "SDN", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Northern Africa" - } - }, - { - "arcs": [ - [ - -124, - -540, - -265, - -392, - 540, - -198 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "S. Sudan", - "NAME_LONG": "South Sudan", - "ABBREV": "S. Sud.", - "FORMAL_EN": "Republic of South Sudan", - "POP_EST": 13026129, - "POP_RANK": 14, - "GDP_MD_EST": 20880, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SS", - "ISO_A3": "SSD", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -296, - -301, - 541, - -299, - 542, - -451, - -435 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Senegal", - "NAME_LONG": "Senegal", - "ABBREV": "Sen.", - "FORMAL_EN": "Republic of Senegal", - "POP_EST": 14668522, - "POP_RANK": 14, - "GDP_MD_EST": 39720, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SN", - "ISO_A3": "SEN", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - [ - 543 - ] - ], - [ - [ - 544 - ] - ], - [ - [ - 545 - ] - ], - [ - [ - 546 - ] - ], - [ - [ - 547 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Solomon Is.", - "NAME_LONG": "Solomon Islands", - "ABBREV": "S. Is.", - "FORMAL_EN": "", - "POP_EST": 647581, - "POP_RANK": 11, - "GDP_MD_EST": 1198, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SB", - "ISO_A3": "SLB", - "CONTINENT": "Oceania", - "REGION_UN": "Oceania", - "SUBREGION": "Melanesia" - } - }, - { - "arcs": [ - [ - -293, - -412, - 548 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Sierra Leone", - "NAME_LONG": "Sierra Leone", - "ABBREV": "S.L.", - "FORMAL_EN": "Republic of Sierra Leone", - "POP_EST": 6163195, - "POP_RANK": 13, - "GDP_MD_EST": 10640, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SL", - "ISO_A3": "SLE", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -310, - -319, - 549 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "El Salvador", - "NAME_LONG": "El Salvador", - "ABBREV": "El. S.", - "FORMAL_EN": "Republic of El Salvador", - "POP_EST": 6172011, - "POP_RANK": 13, - "GDP_MD_EST": 54790, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SV", - "ISO_A3": "SLV", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - -230, - 550, - 551, - -262 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Somaliland", - "NAME_LONG": "Somaliland", - "ABBREV": "Solnd.", - "FORMAL_EN": "Republic of Somaliland", - "POP_EST": 3500000, - "POP_RANK": 12, - "GDP_MD_EST": 12250, - "POP_YEAR": 2013, - "GDP_YEAR": 2013, - "ISO_A2": "-99", - "ISO_A3": "-99", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -263, - -552, - 552, - -388 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Somalia", - "NAME_LONG": "Somalia", - "ABBREV": "Som.", - "FORMAL_EN": "Federal Republic of Somalia", - "POP_EST": 7531386, - "POP_RANK": 13, - "GDP_MD_EST": 4719, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SO", - "ISO_A3": "SOM", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -86, - -434, - -402, - -441, - -92, - -324, - -329, - -508 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Serbia", - "NAME_LONG": "Serbia", - "ABBREV": "Serb.", - "FORMAL_EN": "Republic of Serbia", - "POP_EST": 7111024, - "POP_RANK": 13, - "GDP_MD_EST": 101800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "RS", - "ISO_A3": "SRB", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - -110, - -315, - 553, - -279 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Suriname", - "NAME_LONG": "Suriname", - "ABBREV": "Sur.", - "FORMAL_EN": "Republic of Suriname", - "POP_EST": 591919, - "POP_RANK": 11, - "GDP_MD_EST": 8547, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SR", - "ISO_A3": "SUR", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - -54, - -221, - -498, - 554, - -326 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Slovakia", - "NAME_LONG": "Slovakia", - "ABBREV": "Svk.", - "FORMAL_EN": "Slovak Republic", - "POP_EST": 5445829, - "POP_RANK": 13, - "GDP_MD_EST": 168800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SK", - "ISO_A3": "SVK", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - -49, - -330, - -322, - 555, - -371 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Slovenia", - "NAME_LONG": "Slovenia", - "ABBREV": "Slo.", - "FORMAL_EN": "Republic of Slovenia", - "POP_EST": 1972126, - "POP_RANK": 12, - "GDP_MD_EST": 68350, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SI", - "ISO_A3": "SVN", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - -267, - 556, - -470 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Sweden", - "NAME_LONG": "Sweden", - "ABBREV": "Swe.", - "FORMAL_EN": "Kingdom of Sweden", - "POP_EST": 9960487, - "POP_RANK": 13, - "GDP_MD_EST": 498100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SE", - "ISO_A3": "SWE", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - -446, - 557 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Swaziland", - "NAME_LONG": "Swaziland", - "ABBREV": "Swz.", - "FORMAL_EN": "Kingdom of Swaziland", - "POP_EST": 1467152, - "POP_RANK": 12, - "GDP_MD_EST": 11060, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SZ", - "ISO_A3": "SWZ", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Southern Africa" - } - }, - { - "arcs": [ - [ - -362, - -379, - -367, - -410, - 558, - 559 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Syria", - "NAME_LONG": "Syria", - "ABBREV": "Syria", - "FORMAL_EN": "Syrian Arab Republic", - "POP_EST": 18028549, - "POP_RANK": 14, - "GDP_MD_EST": 50280, - "POP_YEAR": 2017, - "GDP_YEAR": 2015, - "ISO_A2": "SY", - "ISO_A3": "SYR", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -122, - -195, - -464, - -416, - -538 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Chad", - "NAME_LONG": "Chad", - "ABBREV": "Chad", - "FORMAL_EN": "Republic of Chad", - "POP_EST": 12075985, - "POP_RANK": 14, - "GDP_MD_EST": 30590, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TD", - "ISO_A3": "TCD", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - -69, - 560, - -290, - -73 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Togo", - "NAME_LONG": "Togo", - "ABBREV": "Togo", - "FORMAL_EN": "Togolese Republic", - "POP_EST": 7965055, - "POP_RANK": 13, - "GDP_MD_EST": 11610, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TG", - "ISO_A3": "TGO", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -395, - 561, - -459, - 562, - -438, - -407 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Thailand", - "NAME_LONG": "Thailand", - "ABBREV": "Thai.", - "FORMAL_EN": "Kingdom of Thailand", - "POP_EST": 68414135, - "POP_RANK": 16, - "GDP_MD_EST": 1161000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TH", - "ISO_A3": "THA", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - -3, - 563, - -393, - -167 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Tajikistan", - "NAME_LONG": "Tajikistan", - "ABBREV": "Tjk.", - "FORMAL_EN": "Republic of Tajikistan", - "POP_EST": 8468555, - "POP_RANK": 13, - "GDP_MD_EST": 25810, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TJ", - "ISO_A3": "TJK", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Central Asia" - } - }, - { - "arcs": [ - [ - -1, - -357, - 564, - -385, - 565 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Turkmenistan", - "NAME_LONG": "Turkmenistan", - "ABBREV": "Turkm.", - "FORMAL_EN": "Turkmenistan", - "POP_EST": 5351277, - "POP_RANK": 13, - "GDP_MD_EST": 94720, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TM", - "ISO_A3": "TKM", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Central Asia" - } - }, - { - "arcs": [ - [ - -332, - 566 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Timor-Leste", - "NAME_LONG": "Timor-Leste", - "ABBREV": "T.L.", - "FORMAL_EN": "Democratic Republic of Timor-Leste", - "POP_EST": 1291358, - "POP_RANK": 12, - "GDP_MD_EST": 4975, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TL", - "ISO_A3": "TLS", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - 567 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Trinidad and Tobago", - "NAME_LONG": "Trinidad and Tobago", - "ABBREV": "Tr.T.", - "FORMAL_EN": "Republic of Trinidad and Tobago", - "POP_EST": 1218208, - "POP_RANK": 12, - "GDP_MD_EST": 43570, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TT", - "ISO_A3": "TTO", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Caribbean" - } - }, - { - "arcs": [ - [ - -242, - 568, - -413 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Tunisia", - "NAME_LONG": "Tunisia", - "ABBREV": "Tun.", - "FORMAL_EN": "Republic of Tunisia", - "POP_EST": 11403800, - "POP_RANK": 14, - "GDP_MD_EST": 130800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TN", - "ISO_A3": "TUN", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Northern Africa" - } - }, - { - "arcs": [ - [ - [ - -36, - -355, - -363, - -560, - 569, - -287 - ] - ], - [ - [ - -83, - 570, - -304 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Turkey", - "NAME_LONG": "Turkey", - "ABBREV": "Tur.", - "FORMAL_EN": "Republic of Turkey", - "POP_EST": 80845215, - "POP_RANK": 16, - "GDP_MD_EST": 1670000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TR", - "ISO_A3": "TUR", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - 571 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Taiwan", - "NAME_LONG": "Taiwan", - "ABBREV": "Taiwan", - "FORMAL_EN": "", - "POP_EST": 23508428, - "POP_RANK": 15, - "GDP_MD_EST": 1127000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TW", - "ISO_A3": "TWN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Eastern Asia" - } - }, - { - "arcs": [ - [ - -62, - -532, - 572, - -390, - 573, - -443, - -455, - 574, - -201 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Tanzania", - "NAME_LONG": "Tanzania", - "ABBREV": "Tanz.", - "FORMAL_EN": "United Republic of Tanzania", - "POP_EST": 53950935, - "POP_RANK": 16, - "GDP_MD_EST": 150600, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TZ", - "ISO_A3": "TZA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -199, - -541, - -391, - -573, - -531 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Uganda", - "NAME_LONG": "Uganda", - "ABBREV": "Uga.", - "FORMAL_EN": "Republic of Uganda", - "POP_EST": 39570125, - "POP_RANK": 15, - "GDP_MD_EST": 84930, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "UG", - "ISO_A3": "UGA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -96, - -513, - 575, - -518, - 576, - -510, - -428, - -509, - -327, - -555, - -497 - ], - [ - 517, - 518 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Ukraine", - "NAME_LONG": "Ukraine", - "ABBREV": "Ukr.", - "FORMAL_EN": "Ukraine", - "POP_EST": 44033874, - "POP_RANK": 15, - "GDP_MD_EST": 352600, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "UA", - "ISO_A3": "UKR", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - -30, - -113, - 577 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Uruguay", - "NAME_LONG": "Uruguay", - "ABBREV": "Ury.", - "FORMAL_EN": "Oriental Republic of Uruguay", - "POP_EST": 3360148, - "POP_RANK": 12, - "GDP_MD_EST": 73250, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "UY", - "ISO_A3": "URY", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - [ - -141, - 578, - -432, - 579 - ] - ], - [ - [ - -139, - 580 - ] - ], - [ - [ - 581 - ] - ], - [ - [ - 582 - ] - ], - [ - [ - 583 - ] - ], - [ - [ - 584 - ] - ], - [ - [ - 585 - ] - ], - [ - [ - 586 - ] - ], - [ - [ - 587 - ] - ], - [ - [ - 588 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "United States of America", - "NAME_LONG": "United States", - "ABBREV": "U.S.A.", - "FORMAL_EN": "United States of America", - "POP_EST": 326625791, - "POP_RANK": 17, - "GDP_MD_EST": 18560000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "US", - "ISO_A3": "USA", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Northern America" - } - }, - { - "arcs": [ - [ - -2, - -566, - -384, - -394, - -564 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Uzbekistan", - "NAME_LONG": "Uzbekistan", - "ABBREV": "Uzb.", - "FORMAL_EN": "Republic of Uzbekistan", - "POP_EST": 29748859, - "POP_RANK": 15, - "GDP_MD_EST": 202300, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "UZ", - "ISO_A3": "UZB", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Central Asia" - } - }, - { - "arcs": [ - [ - -108, - -210, - 589, - -313 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Venezuela", - "NAME_LONG": "Venezuela", - "ABBREV": "Ven.", - "FORMAL_EN": "Bolivarian Republic of Venezuela", - "POP_EST": 31304016, - "POP_RANK": 15, - "GDP_MD_EST": 468600, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "VE", - "ISO_A3": "VEN", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - -175, - 590, - -397, - -406 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Vietnam", - "NAME_LONG": "Vietnam", - "ABBREV": "Viet.", - "FORMAL_EN": "Socialist Republic of Vietnam", - "POP_EST": 96160163, - "POP_RANK": 16, - "GDP_MD_EST": 594900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "VN", - "ISO_A3": "VNM", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - [ - 591 - ] - ], - [ - [ - 592 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Vanuatu", - "NAME_LONG": "Vanuatu", - "ABBREV": "Van.", - "FORMAL_EN": "Republic of Vanuatu", - "POP_EST": 282814, - "POP_RANK": 10, - "GDP_MD_EST": 723, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "VU", - "ISO_A3": "VUT", - "CONTINENT": "Oceania", - "REGION_UN": "Oceania", - "SUBREGION": "Melanesia" - } - }, - { - "arcs": [ - [ - -480, - 593, - -534 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Yemen", - "NAME_LONG": "Yemen", - "ABBREV": "Yem.", - "FORMAL_EN": "Republic of Yemen", - "POP_EST": 28036829, - "POP_RANK": 15, - "GDP_MD_EST": 73450, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "YE", - "ISO_A3": "YEM", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -118, - 594, - -447, - -558, - -445, - 595, - -461 - ], - [ - -419 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "South Africa", - "NAME_LONG": "South Africa", - "ABBREV": "S.Af.", - "FORMAL_EN": "Republic of South Africa", - "POP_EST": 54841552, - "POP_RANK": 16, - "GDP_MD_EST": 739100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ZA", - "ISO_A3": "ZAF", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Southern Africa" - } - }, - { - "arcs": [ - [ - -10, - -202, - -575, - -454, - -449, - 596, - -120, - -460 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Zambia", - "NAME_LONG": "Zambia", - "ABBREV": "Zambia", - "FORMAL_EN": "Republic of Zambia", - "POP_EST": 15972000, - "POP_RANK": 14, - "GDP_MD_EST": 65170, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ZM", - "ISO_A3": "ZMB", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -121, - -597, - -448, - -595 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Zimbabwe", - "NAME_LONG": "Zimbabwe", - "ABBREV": "Zimb.", - "FORMAL_EN": "Republic of Zimbabwe", - "POP_EST": 13805084, - "POP_RANK": 14, - "GDP_MD_EST": 28330, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ZW", - "ISO_A3": "ZWE", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - } - ] - } - } -} diff --git a/explorer-nextjs/app/components/ComponentError.tsx b/explorer-nextjs/app/components/ComponentError.tsx deleted file mode 100644 index 00b448fb9eb..00000000000 --- a/explorer-nextjs/app/components/ComponentError.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Typography } from '@mui/material'; -import * as React from 'react'; - -export const ComponentError: FCWithChildren<{ text: string }> = ({ text }) => ( - <Typography - sx={{ marginTop: 2, color: 'primary.main', fontSize: 10 }} - variant="body1" - data-testid="delegation-total-amount" - > - {text} - </Typography> -); diff --git a/explorer-nextjs/app/components/ContentCard.tsx b/explorer-nextjs/app/components/ContentCard.tsx deleted file mode 100644 index c83049e5c7a..00000000000 --- a/explorer-nextjs/app/components/ContentCard.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { Card, CardHeader, CardContent, Typography } from '@mui/material' -import React, { ReactEventHandler } from 'react' - -type ContentCardProps = { - title?: React.ReactNode - subtitle?: string - Icon?: React.ReactNode - Action?: React.ReactNode - errorMsg?: string - onClick?: ReactEventHandler -} - -export const ContentCard: FCWithChildren<ContentCardProps> = ({ - title, - Icon, - Action, - subtitle, - errorMsg, - children, - onClick, -}) => ( - <Card onClick={onClick} sx={{ height: '100%' }}> - {title && ( - <CardHeader - title={title || ''} - avatar={Icon} - action={Action} - subheader={subtitle} - /> - )} - {children && <CardContent>{children}</CardContent>} - {errorMsg && ( - <Typography variant="body2" sx={{ color: 'danger', padding: 2 }}> - {errorMsg} - </Typography> - )} - </Card> -) diff --git a/explorer-nextjs/app/components/CustomColumnHeading.tsx b/explorer-nextjs/app/components/CustomColumnHeading.tsx deleted file mode 100644 index e767db34c1e..00000000000 --- a/explorer-nextjs/app/components/CustomColumnHeading.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import * as React from 'react' -import { Box, Typography } from '@mui/material' -import { useTheme } from '@mui/material/styles' -import { Tooltip } from '@nymproject/react/tooltip/Tooltip' - -export const CustomColumnHeading: FCWithChildren<{ - headingTitle: string - tooltipInfo?: string -}> = ({ headingTitle, tooltipInfo }) => { - const theme = useTheme() - - return ( - <Box alignItems="center" display="flex"> - {tooltipInfo && ( - <Tooltip - title={tooltipInfo} - id={headingTitle} - placement="top-start" - textColor={theme.palette.nym.networkExplorer.tooltip.color} - bgColor={theme.palette.nym.networkExplorer.tooltip.background} - maxWidth={230} - arrow - /> - )} - <Typography variant="body2" fontWeight={600} data-testid={headingTitle}> - {headingTitle} - </Typography> - </Box> - ) -} diff --git a/explorer-nextjs/app/components/Delegations/ConfirmationModal.tsx b/explorer-nextjs/app/components/Delegations/ConfirmationModal.tsx deleted file mode 100644 index 8e859f5eba3..00000000000 --- a/explorer-nextjs/app/components/Delegations/ConfirmationModal.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import React from 'react'; -import { - Breakpoint, - Button, - Paper, - Dialog, - DialogActions, - DialogContent, - DialogTitle, - SxProps, - Typography, -} from '@mui/material'; - -export interface ConfirmationModalProps { - open: boolean; - onConfirm: () => void; - onClose?: () => void; - children?: React.ReactNode; - title: React.ReactNode | string; - subTitle?: React.ReactNode | string; - confirmButton: React.ReactNode | string; - disabled?: boolean; - sx?: SxProps; - fullWidth?: boolean; - maxWidth?: Breakpoint; - backdropProps?: object; -} - -export const ConfirmationModal = ({ - open, - onConfirm, - onClose, - children, - title, - subTitle, - confirmButton, - disabled, - sx, - fullWidth, - maxWidth, - backdropProps, -}: ConfirmationModalProps) => { - const Title = ( - <DialogTitle id="responsive-dialog-title" sx={{ pb: 2 }}> - {title} - {subTitle && - (typeof subTitle === 'string' ? ( - <Typography fontWeight={400} variant="subtitle1" fontSize={12} color="grey"> - {subTitle} - </Typography> - ) : ( - subTitle - ))} - </DialogTitle> - ); - const ConfirmButton = - typeof confirmButton === 'string' ? ( - <Button onClick={onConfirm} variant="contained" fullWidth disabled={disabled} sx={{ py: 1.6 }}> - <Typography variant="button" fontSize="large"> - {confirmButton} - </Typography> - </Button> - ) : ( - confirmButton - ); - return ( - <Dialog - open={open} - onClose={onClose} - aria-labelledby="responsive-dialog-title" - maxWidth={maxWidth || 'sm'} - sx={{ textAlign: 'center', ...sx }} - fullWidth={fullWidth} - BackdropProps={backdropProps} - PaperComponent={Paper} - PaperProps={{ elevation: 0 }} - > - {Title} - <DialogContent>{children}</DialogContent> - <DialogActions sx={{ px: 3, pb: 3 }}>{ConfirmButton}</DialogActions> - </Dialog> - ); -}; diff --git a/explorer-nextjs/app/components/Delegations/DelegateIconButton.tsx b/explorer-nextjs/app/components/Delegations/DelegateIconButton.tsx deleted file mode 100644 index 9ea2f54b6b2..00000000000 --- a/explorer-nextjs/app/components/Delegations/DelegateIconButton.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import * as React from 'react' -import { Button, IconButton } from '@mui/material' -import { SxProps } from '@mui/system' -import { useIsMobile } from '@/app/hooks' -import { DelegateIcon } from '@/app/icons/DelevateSVG' - -export const DelegateIconButton: FCWithChildren<{ - size?: 'small' | 'medium' - disabled?: boolean - tooltip?: React.ReactNode - sx?: SxProps - onDelegate: () => void -}> = ({ onDelegate, sx, disabled, size = 'medium' }) => { - const isMobile = useIsMobile() - - const handleOnDelegate = () => { - onDelegate() - } - - if (isMobile) { - return ( - <IconButton size="small" disabled={disabled} onClick={handleOnDelegate}> - <DelegateIcon fontSize="small" /> - </IconButton> - ) - } - - return ( - <Button - variant="outlined" - size={size} - disabled={disabled} - onClick={handleOnDelegate} - sx={sx} - > - Delegate - </Button> - ) -} diff --git a/explorer-nextjs/app/components/Delegations/DelegateModal.tsx b/explorer-nextjs/app/components/Delegations/DelegateModal.tsx deleted file mode 100644 index 5b453e8ad59..00000000000 --- a/explorer-nextjs/app/components/Delegations/DelegateModal.tsx +++ /dev/null @@ -1,191 +0,0 @@ -'use client' - -import React, { useState } from 'react' -import { Box, SxProps } from '@mui/material' -import { IdentityKeyFormField } from '@nymproject/react/mixnodes/IdentityKeyFormField' -import { CurrencyFormField } from '@nymproject/react/currency/CurrencyFormField' -import { CurrencyDenom, DecCoin } from '@nymproject/types' -import { useWalletContext } from '@/app/context/wallet' -import { urls } from '@/app/utils' -import { useDelegationsContext } from '@/app/context/delegations' -import { validateAmount } from '@/app/utils/currency' -import { SimpleModal } from './SimpleModal' -import { ModalListItem } from './ModalListItem' -import { DelegationModalProps } from './DelegationModal' - -const MIN_AMOUNT_TO_DELEGATE = 10 - -type Props = { - mixId: number - identityKey: string - header?: string - buttonText?: string - rewardInterval?: string - estimatedReward?: number - profitMarginPercentage?: string | null - nodeUptimePercentage?: number | null - denom: CurrencyDenom - sx?: SxProps - backdropProps?: object - onClose: () => void - onOk?: (delegationModalProps: DelegationModalProps) => void -} - -export const DelegateModal = ({ - mixId, - identityKey, - onClose, - onOk, - denom, - sx, -}: Props) => { - const [amount, setAmount] = useState<DecCoin | undefined>({ - amount: '10', - denom: 'nym', - }) - const [isValidated, setValidated] = useState<boolean>(false) - const [errorAmount, setErrorAmount] = useState<string | undefined>() - - const { address, balance } = useWalletContext() - const { handleDelegate } = useDelegationsContext() - - const validate = async () => { - let newValidatedValue = true - let errorAmountMessage - - if (amount && !(await validateAmount(amount.amount, '0'))) { - newValidatedValue = false - errorAmountMessage = 'Please enter a valid amount' - } - - if (amount && +amount.amount < MIN_AMOUNT_TO_DELEGATE) { - errorAmountMessage = `Min. delegation amount: ${MIN_AMOUNT_TO_DELEGATE} ${denom.toUpperCase()}` - newValidatedValue = false - } - - if (!amount?.amount.length) { - newValidatedValue = false - } - - if (amount && balance.data && +balance.data - +amount.amount <= 0) { - errorAmountMessage = 'Not enough funds' - newValidatedValue = false - } - - setErrorAmount(errorAmountMessage) - setValidated(newValidatedValue) - } - - const delegateToMixnode = async ({ - delegationMixId, - delegationAmount, - }: { - delegationMixId: number - delegationAmount: string - }) => { - try { - const tx = await handleDelegate(delegationMixId, delegationAmount) - return tx - } catch (e) { - console.error('Failed to delegate to mixnode', e) - throw e - } - } - - const handleConfirm = async () => { - if (mixId && amount && onOk) { - onOk({ - status: 'loading', - }) - try { - if (!address) { - throw new Error('Please connect your wallet') - } - - const tx = await delegateToMixnode({ - delegationMixId: mixId, - delegationAmount: amount.amount, - }) - - if (!tx) { - throw new Error('Failed to delegate') - } - - onOk({ - status: 'success', - message: 'Delegation can take up to one hour to process', - transactions: [ - { - url: `${urls('MAINNET').blockExplorer}/transaction/${ - tx.transactionHash - }`, - hash: tx.transactionHash, - }, - ], - }) - } catch (e) { - console.error('Failed to delegate', e) - onOk({ - status: 'error', - message: (e as Error).message, - }) - } - } - } - - const handleAmountChanged = (newAmount: DecCoin) => { - setAmount(newAmount) - } - - React.useEffect(() => { - validate() - }, [amount, identityKey, mixId]) - - return ( - <SimpleModal - open - onClose={onClose} - onOk={handleConfirm} - header="Delegate" - okLabel="Delegate" - okDisabled={!isValidated} - sx={sx} - > - <Box sx={{ mt: 3 }} gap={2}> - <IdentityKeyFormField - required - fullWidth - label="Node identity key" - onChanged={() => undefined} - initialValue={identityKey} - readOnly - showTickOnValid={false} - /> - </Box> - - <Box display="flex" gap={2} alignItems="center" sx={{ mt: 3 }}> - <CurrencyFormField - showCoinMark={false} - required - fullWidth - autoFocus - label="Amount" - initialValue={amount?.amount || '10'} - onChanged={handleAmountChanged} - denom={denom} - validationError={errorAmount} - /> - </Box> - <Box sx={{ mt: 3 }}> - <ModalListItem - label="Account balance" - value={`${balance.data} NYM`} - divider - fontWeight={600} - /> - </Box> - - <ModalListItem label="Est. fee for this transaction will be calculated in your connected wallet" /> - </SimpleModal> - ) -} diff --git a/explorer-nextjs/app/components/Delegations/DelegationModal.tsx b/explorer-nextjs/app/components/Delegations/DelegationModal.tsx deleted file mode 100644 index 76c37a9e967..00000000000 --- a/explorer-nextjs/app/components/Delegations/DelegationModal.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import React from 'react' -import { Typography, SxProps, Stack } from '@mui/material' -import { Link } from '@nymproject/react/link/Link' -import { LoadingModal } from './LoadingModal' -import { ConfirmationModal } from './ConfirmationModal' -import { ErrorModal } from './ErrorModal' - -export type DelegationModalProps = { - status: 'loading' | 'success' | 'error' | 'info' - message?: string - transactions?: { - url: string - hash: string - }[] -} - -export const DelegationModal: FCWithChildren< - DelegationModalProps & { - open: boolean - onClose: () => void - sx?: SxProps - backdropProps?: object - children?: React.ReactNode - } -> = ({ - status, - message, - transactions, - open, - onClose, - children, - sx, - backdropProps, -}) => { - if (status === 'loading') - return <LoadingModal sx={sx} backdropProps={backdropProps} /> - - if (status === 'error') { - return ( - <ErrorModal message={message} sx={sx} open={open} onClose={onClose}> - {children} - </ErrorModal> - ) - } - - if (status === 'info') { - return ( - <ConfirmationModal - open={open} - title="Connect wallet" - confirmButton="OK" - onConfirm={onClose} - > - <Typography>{message}</Typography> - </ConfirmationModal> - ) - } - - return ( - <ConfirmationModal - open={open} - onConfirm={onClose || (() => {})} - title="Transaction successful" - confirmButton="Done" - > - <Stack alignItems="center" spacing={2} mb={0}> - {message && <Typography>{message}</Typography>} - {transactions?.length === 1 && ( - <Link - href={transactions[0].url} - target="_blank" - sx={{ ml: 1 }} - text="View on blockchain" - noIcon - /> - )} - {transactions && transactions.length > 1 && ( - <Stack alignItems="center" spacing={1}> - <Typography>View the transactions on blockchain:</Typography> - {transactions.map(({ url, hash }) => ( - <Link - href={url} - target="_blank" - sx={{ ml: 1 }} - text={hash.slice(0, 6)} - key={hash} - noIcon - /> - ))} - </Stack> - )} - </Stack> - </ConfirmationModal> - ) -} diff --git a/explorer-nextjs/app/components/Delegations/ErrorModal.tsx b/explorer-nextjs/app/components/Delegations/ErrorModal.tsx deleted file mode 100644 index b9218d1e1ea..00000000000 --- a/explorer-nextjs/app/components/Delegations/ErrorModal.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; -import { Box, Button, Modal, SxProps, Typography } from '@mui/material'; -import { modalStyle } from './SimpleModal'; - -export const ErrorModal: FCWithChildren<{ - open: boolean; - title?: string; - message?: string; - sx?: SxProps; - backdropProps?: object; - onClose: () => void; - children?: React.ReactNode; -}> = ({ children, open, title, message, sx, backdropProps, onClose }) => ( - <Modal open={open} onClose={onClose} BackdropProps={backdropProps}> - <Box sx={{ ...modalStyle(), ...sx }} textAlign="center"> - <Typography color={(theme) => theme.palette.error.main} mb={1}> - {title || 'Oh no! Something went wrong...'} - </Typography> - <Typography my={5} color="text.primary" sx={{ textOverflow: 'wrap', overflowWrap: 'break-word' }}> - {message} - </Typography> - {children} - <Button variant="contained" onClick={onClose}> - Close - </Button> - </Box> - </Modal> -); diff --git a/explorer-nextjs/app/components/Delegations/LoadingModal.tsx b/explorer-nextjs/app/components/Delegations/LoadingModal.tsx deleted file mode 100644 index eda13938d44..00000000000 --- a/explorer-nextjs/app/components/Delegations/LoadingModal.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import { Box, CircularProgress, Modal, Stack, Typography, SxProps } from '@mui/material'; -import { modalStyle } from './SimpleModal'; - -export const LoadingModal: FCWithChildren<{ - text?: string; - sx?: SxProps; - backdropProps?: object; -}> = ({ sx, text = 'Please wait...' }) => ( - <Modal open> - <Box sx={{ ...modalStyle(), ...sx }} textAlign="center"> - <Stack spacing={4} direction="row" alignItems="center"> - <CircularProgress /> - <Typography sx={{ color: 'text.primary' }}>{text}</Typography> - </Stack> - </Box> - </Modal> -); diff --git a/explorer-nextjs/app/components/Delegations/ModalDivider.tsx b/explorer-nextjs/app/components/Delegations/ModalDivider.tsx deleted file mode 100644 index 6258e0bfac9..00000000000 --- a/explorer-nextjs/app/components/Delegations/ModalDivider.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react'; -import { Box, SxProps } from '@mui/material'; - -export const ModalDivider: FCWithChildren<{ - sx?: SxProps; -}> = ({ sx }) => <Box borderTop="1px solid" borderColor="rgba(141, 147, 153, 0.2)" my={1} sx={sx} />; diff --git a/explorer-nextjs/app/components/Delegations/ModalListItem.tsx b/explorer-nextjs/app/components/Delegations/ModalListItem.tsx deleted file mode 100644 index 830c25705ed..00000000000 --- a/explorer-nextjs/app/components/Delegations/ModalListItem.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import { Box, Stack, SxProps, Typography, TypographyProps } from '@mui/material'; -import { ModalDivider } from './ModalDivider'; - -export const ModalListItem: FCWithChildren<{ - label: string; - divider?: boolean; - hidden?: boolean; - fontWeight?: TypographyProps['fontWeight']; - fontSize?: TypographyProps['fontSize']; - light?: boolean; - value?: React.ReactNode; - sxValue?: SxProps; -}> = ({ label, value, hidden, fontWeight, fontSize, divider, sxValue }) => ( - <Box sx={{ display: hidden ? 'none' : 'block' }}> - <Stack direction="row" justifyContent="space-between" alignItems="center"> - <Typography fontSize="smaller" fontWeight={fontWeight} sx={{ color: 'text.primary', fontSize: 14 }}> - {label} - </Typography> - {value && ( - <Typography - fontSize="smaller" - fontWeight={fontWeight} - sx={{ color: 'text.primary', fontSize: fontSize || 14, ...sxValue }} - > - {value} - </Typography> - )} - </Stack> - {divider && <ModalDivider />} - </Box> -); diff --git a/explorer-nextjs/app/components/Delegations/SimpleModal.tsx b/explorer-nextjs/app/components/Delegations/SimpleModal.tsx deleted file mode 100644 index b1909c8c5e3..00000000000 --- a/explorer-nextjs/app/components/Delegations/SimpleModal.tsx +++ /dev/null @@ -1,152 +0,0 @@ -import React from 'react' -import { Box, Button, Modal, Stack, SxProps, Typography } from '@mui/material' -import CloseIcon from '@mui/icons-material/Close' -import ErrorOutline from '@mui/icons-material/ErrorOutline' -import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined' -import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew' -import { useIsMobile } from '@/app/hooks/useIsMobile' - -export const modalStyle = (width: number | string = 600) => ({ - position: 'absolute' as 'absolute', - top: '50%', - left: '50%', - width, - transform: 'translate(-50%, -50%)', - bgcolor: 'background.paper', - boxShadow: 24, - borderRadius: '16px', - p: 4, -}) - -export const StyledBackButton = ({ - onBack, - label, - fullWidth, - sx, -}: { - onBack: () => void - label?: string - fullWidth?: boolean - sx?: SxProps -}) => ( - <Button - disableFocusRipple - size="large" - fullWidth={fullWidth} - variant="outlined" - onClick={onBack} - sx={sx} - > - {label || <ArrowBackIosNewIcon fontSize="small" />} - </Button> -) - -export const SimpleModal: FCWithChildren<{ - open: boolean - hideCloseIcon?: boolean - displayErrorIcon?: boolean - displayInfoIcon?: boolean - headerStyles?: SxProps - subHeaderStyles?: SxProps - buttonFullWidth?: boolean - onClose?: () => void - onOk?: () => Promise<void> - onBack?: () => void - header: string | React.ReactNode - subHeader?: string - okLabel: string - backLabel?: string - backButtonFullWidth?: boolean - okDisabled?: boolean - sx?: SxProps - children?: React.ReactNode -}> = ({ - open, - hideCloseIcon, - displayErrorIcon, - displayInfoIcon, - headerStyles, - buttonFullWidth, - onClose, - okDisabled, - onOk, - onBack, - header, - subHeader, - okLabel, - backLabel, - backButtonFullWidth, - sx, - children, -}) => { - const isMobile = useIsMobile() - - return ( - <Modal open={open} onClose={onClose}> - <Box sx={{ ...modalStyle(isMobile ? '90%' : 600), ...sx }}> - {displayErrorIcon && <ErrorOutline color="error" sx={{ mb: 3 }} />} - {displayInfoIcon && <InfoOutlinedIcon sx={{ mb: 2, color: 'blue' }} />} - <Stack - direction="row" - justifyContent="space-between" - alignItems="center" - > - {typeof header === 'string' ? ( - <Typography - fontSize={20} - fontWeight={600} - sx={{ color: 'text.primary', ...headerStyles }} - > - {header} - </Typography> - ) : ( - header - )} - {!hideCloseIcon && <CloseIcon onClick={onClose} cursor="pointer" />} - </Stack> - - <Typography - mt={subHeader ? 0.5 : 0} - mb={3} - fontSize={12} - color={(theme) => theme.palette.text.secondary} - > - {subHeader} - </Typography> - - {children} - - {(onOk || onBack) && ( - <Box - sx={{ - display: 'flex', - alignItems: 'center', - gap: 2, - mt: 2, - width: buttonFullWidth ? '100%' : null, - }} - > - {onBack && ( - <StyledBackButton - onBack={onBack} - label={backLabel} - fullWidth={backButtonFullWidth} - /> - )} - {onOk && ( - <Button - variant="contained" - fullWidth - size="large" - onClick={onOk} - disabled={okDisabled} - > - {okLabel} - </Button> - )} - </Box> - )} - </Box> - </Modal> - ) -} diff --git a/explorer-nextjs/app/components/Delegations/index.ts b/explorer-nextjs/app/components/Delegations/index.ts deleted file mode 100644 index da51de9bd90..00000000000 --- a/explorer-nextjs/app/components/Delegations/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -export * from './ConfirmationModal'; -export * from './DelegateIconButton'; -export * from './DelegationModal'; -export * from './DelegateModal'; -export * from './ErrorModal'; -export * from './LoadingModal'; -export * from './ModalDivider'; -export * from './ModalListItem'; -export * from './SimpleModal'; -export * from './styles'; diff --git a/explorer-nextjs/app/components/Delegations/styles.ts b/explorer-nextjs/app/components/Delegations/styles.ts deleted file mode 100644 index 9b265517670..00000000000 --- a/explorer-nextjs/app/components/Delegations/styles.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Theme } from '@mui/material/styles'; - -export const backDropStyles = (theme: Theme) => { - const { mode } = theme.palette; - return { - style: { - left: mode === 'light' ? '0' : '50%', - width: '50%', - }, - }; -}; - -export const modalStyles = (theme: Theme) => { - const { mode } = theme.palette; - return { left: mode === 'light' ? '25%' : '75%' }; -}; - -export const dialogStyles = (theme: Theme) => { - const { mode } = theme.palette; - return { left: mode === 'light' ? '-50%' : '50%' }; -}; diff --git a/explorer-nextjs/app/components/DetailTable.tsx b/explorer-nextjs/app/components/DetailTable.tsx deleted file mode 100644 index b068a5c8524..00000000000 --- a/explorer-nextjs/app/components/DetailTable.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import * as React from 'react' -import { - Link, - Paper, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, - TableCellProps, -} from '@mui/material' -import { useTheme } from '@mui/material/styles' -import { Tooltip } from '@nymproject/react/tooltip/Tooltip' -import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard' -import { Box } from '@mui/system' -import { unymToNym } from '@/app/utils/currency' -import { GatewayEnrichedRowType } from './Gateways/Gateways' -import { MixnodeRowType } from './MixNodes' -import { StakeSaturationProgressBar } from './MixNodes/Economics/StakeSaturationProgressBar' -import {EXPLORER_FOR_ACCOUNTS} from "@/app/api/constants"; - -export type ColumnsType = { - field: string - title: string - headerAlign?: TableCellProps['align'] - width?: string | number - tooltipInfo?: string -} - -export interface UniversalTableProps<T = any> { - tableName: string - columnsData: ColumnsType[] - rows: T[] -} - -function formatCellValues(val: string | number, field: string) { - if (field === 'identity_key' && typeof val === 'string') { - return ( - <Box display="flex" justifyContent="flex-end"> - <CopyToClipboard - sx={{ mr: 1, mt: 0.5, fontSize: '18px' }} - value={val} - tooltip={`Copy identity key ${val} to clipboard`} - /> - <span>{val}</span> - </Box> - ) - } - - if (field === 'bond') { - return unymToNym(val, 6) - } - - if (field === 'owner') { - return ( - <Link - underline="none" - color="inherit" - target="_blank" - href={`${EXPLORER_FOR_ACCOUNTS}/account/${val}`} - > - {val} - </Link> - ) - } - - if (field === 'stake_saturation') { - return <StakeSaturationProgressBar value={Number(val)} threshold={100} /> - } - - return val -} - -export const DetailTable: FCWithChildren<{ - tableName: string - columnsData: ColumnsType[] - rows: MixnodeRowType[] | GatewayEnrichedRowType[] | any[] -}> = ({ tableName, columnsData, rows }: UniversalTableProps) => { - const theme = useTheme() - return ( - <TableContainer component={Paper}> - <Table sx={{ minWidth: 1080 }} aria-label={tableName}> - <TableHead> - <TableRow> - {columnsData?.map(({ field, title, width, tooltipInfo }) => ( - <TableCell - key={field} - sx={{ fontSize: 14, fontWeight: 600, width }} - > - <Box sx={{ display: 'flex', alignItems: 'center' }}> - {tooltipInfo && ( - <Box sx={{ display: 'flex', alignItems: 'center' }}> - <Tooltip - title={tooltipInfo} - id={field} - placement="top-start" - textColor={ - theme.palette.nym.networkExplorer.tooltip.color - } - bgColor={ - theme.palette.nym.networkExplorer.tooltip.background - } - maxWidth={230} - arrow - /> - </Box> - )} - {title} - </Box> - </TableCell> - ))} - </TableRow> - </TableHead> - <TableBody> - {rows.map((eachRow) => ( - <TableRow - key={eachRow.id} - sx={{ '&:last-child td, &:last-child th': { border: 0 } }} - > - {columnsData?.map((data, index) => ( - <TableCell - key={data.title} - component="th" - scope="row" - variant="body" - sx={{ - padding: 2, - width: 200, - fontSize: 14, - }} - data-testid={`${data.title.replace(/ /g, '-')}-value`} - > - {formatCellValues( - eachRow[columnsData[index].field], - columnsData[index].field - )} - </TableCell> - ))} - </TableRow> - ))} - </TableBody> - </Table> - </TableContainer> - ) -} diff --git a/explorer-nextjs/app/components/Filters/Filters.tsx b/explorer-nextjs/app/components/Filters/Filters.tsx deleted file mode 100644 index 3a871a5fb4f..00000000000 --- a/explorer-nextjs/app/components/Filters/Filters.tsx +++ /dev/null @@ -1,193 +0,0 @@ -'use client' - -import React, { useState, useEffect, useRef, useCallback } from 'react' -import { - Button, - Dialog, - DialogContent, - DialogActions, - DialogTitle, - Slider, - Typography, - Box, - Snackbar, - Slide, - Alert, -} from '@mui/material' -import { useParams } from 'next/navigation' -import { useMainContext } from '@/app/context/main' -import { - MixnodeStatusWithAll, - toMixnodeStatus, -} from '@/app/typeDefs/explorer-api' -import { EnumFilterKey, TFilterItem, TFilters } from '@/app/typeDefs/filters' -import { Api } from '@/app/api' -import { useIsMobile } from '@/app/hooks/useIsMobile' -import { formatOnSave, generateFilterSchema } from './filterSchema' -import FiltersButton from './FiltersButton' - -const FilterItem = ({ - label, - id, - tooltipInfo, - value, - isSmooth, - marks, - scale, - min, - max, - onChange, -}: TFilterItem & { - onChange: (id: EnumFilterKey, newValue: number[]) => void -}) => ( - <Box sx={{ p: 2 }}> - <Typography gutterBottom>{label}</Typography> - <Typography fontSize={12}>{tooltipInfo}</Typography> - <Slider - value={value} - onChange={(e: Event, newValue: number | number[]) => - onChange(id, newValue as number[]) - } - valueLabelDisplay={isSmooth ? 'auto' : 'off'} - marks={marks} - step={isSmooth ? 1 : null} - scale={scale} - min={min} - max={max} - valueLabelFormat={(val: number) => - val === 100 && id === 'stakeSaturation' ? '>100' : val - } - /> - </Box> -) - -export const Filters = () => { - const { filterMixnodes, fetchMixnodes, mixnodes } = useMainContext() - const { status } = useParams<{ - status: 'active' | 'standby' | 'inactive' | 'all' - }>() - const isMobile = useIsMobile() - - const [showFilters, setShowFilters] = useState(false) - const [isFiltered, setIsFiltered] = useState(false) - const [filters, setFilters] = React.useState<TFilters>() - const [upperSaturationValue, setUpperSaturationValue] = - React.useState<number>(100) - - const baseFilters = useRef<TFilters>() - const prevFilters = useRef<TFilters>() - - const handleToggleShowFilters = () => setShowFilters(!showFilters) - - const initialiseFilters = useCallback(async () => { - const allMixnodes = await Api.fetchMixnodes() - if (allMixnodes) { - setUpperSaturationValue( - Math.round( - Math.max(...allMixnodes.map((m) => m.stake_saturation)) * 100 + 1 - ) - ) - const initFilters = generateFilterSchema() - baseFilters.current = initFilters - prevFilters.current = initFilters - setFilters(initFilters) - } - }, []) - - const handleOnChange = (id: EnumFilterKey, newValue: number[]) => { - if (id === 'stakeSaturation' && newValue[1] === 100) { - newValue.splice(1, 1, upperSaturationValue) - } - setFilters((ftrs) => { - if (ftrs) - return { - ...ftrs, - [id]: { - ...ftrs[id], - value: newValue, - }, - } - return undefined - }) - } - - const handleOnSave = async () => { - setShowFilters(false) - await filterMixnodes(formatOnSave(filters!), status) - setIsFiltered(true) - prevFilters.current = filters - } - - const handleOnCancel = () => { - setShowFilters(false) - setFilters(prevFilters.current) - } - - const resetFilters = () => { - setFilters(baseFilters.current) - setIsFiltered(false) - prevFilters.current = baseFilters.current - } - - const onClearFilters = async () => { - await fetchMixnodes(toMixnodeStatus(MixnodeStatusWithAll[status])) - resetFilters() - } - - useEffect(() => { - initialiseFilters() - }, [initialiseFilters]) - - useEffect(() => { - resetFilters() - }, [status]) - - if (!filters) return null - - return ( - <> - <Snackbar - open={isFiltered} - anchorOrigin={{ vertical: 'top', horizontal: 'center' }} - message="Filters applied" - TransitionComponent={Slide} - transitionDuration={250} - > - <Alert - severity="info" - variant={isMobile ? 'standard' : 'outlined'} - sx={{ color: (t) => t.palette.info.light }} - action={ - <Button size="small" onClick={onClearFilters}> - CLEAR FILTERS - </Button> - } - > - {mixnodes?.data?.length} mixnodes matched your criteria - </Alert> - </Snackbar> - <FiltersButton onClick={handleToggleShowFilters} fullWidth /> - <Dialog - open={showFilters} - onClose={handleToggleShowFilters} - maxWidth="md" - fullWidth - > - <DialogTitle>Mixnode filters</DialogTitle> - <DialogContent dividers> - {Object.values(filters).map((v) => ( - <FilterItem {...v} key={v.id} onChange={handleOnChange} /> - ))} - </DialogContent> - <DialogActions> - <Button size="large" onClick={handleOnCancel}> - Cancel - </Button> - <Button variant="contained" size="large" onClick={handleOnSave}> - Save - </Button> - </DialogActions> - </Dialog> - </> - ) -} diff --git a/explorer-nextjs/app/components/Filters/FiltersButton.tsx b/explorer-nextjs/app/components/Filters/FiltersButton.tsx deleted file mode 100644 index 1e6d3e29405..00000000000 --- a/explorer-nextjs/app/components/Filters/FiltersButton.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { Button, IconButton } from '@mui/material'; -import { Tune } from '@mui/icons-material'; - -type FiltersButtonProps = { - iconOnly?: boolean; - fullWidth?: boolean; - onClick: () => void; -}; - -const FiltersButton = ({ iconOnly, fullWidth, onClick }: FiltersButtonProps) => { - if (iconOnly) { - return ( - <IconButton onClick={onClick} color="primary"> - <Tune /> - </IconButton> - ); - } - - return ( - <Button - fullWidth={fullWidth} - size="large" - variant="contained" - endIcon={<Tune />} - onClick={onClick} - sx={{ textTransform: 'none' }} - > - Filters - </Button> - ); -}; - -export default FiltersButton; diff --git a/explorer-nextjs/app/components/Filters/filterSchema.ts b/explorer-nextjs/app/components/Filters/filterSchema.ts deleted file mode 100644 index c5011114b19..00000000000 --- a/explorer-nextjs/app/components/Filters/filterSchema.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { EnumFilterKey, TFilters } from '../../typeDefs/filters'; - -export const generateFilterSchema = () => ({ - profitMargin: { - label: 'Profit margin (%)', - id: EnumFilterKey.profitMargin, - value: [0, 100], - isSmooth: true, - marks: [ - { label: '0', value: 0 }, - { label: '10', value: 10 }, - { label: '20', value: 20 }, - { label: '30', value: 30 }, - { label: '40', value: 40 }, - { label: '50', value: 50 }, - { label: '60', value: 60 }, - { label: '70', value: 70 }, - { label: '80', value: 80 }, - { label: '90', value: 90 }, - { label: '100', value: 100 }, - ], - tooltipInfo: - 'As a delegator you want to chose nodes with lower profit margin, meaning more payout for their delegators', - }, - stakeSaturation: { - label: 'Stake saturation (%)', - id: EnumFilterKey.stakeSaturation, - value: [0, 100], - isSmooth: true, - marks: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100].map((value) => ({ - value: value < 100 ? value : 100, - label: value < 100 ? value : '>100', - })), - tooltipInfo: "Select nodes with <100% saturation. Any additional stake above 100% saturation won't get rewards", - }, - routingScore: { - label: 'Routing score (%)', - id: EnumFilterKey.routingScore, - value: [0, 100], - isSmooth: true, - marks: [ - { label: '0', value: 0 }, - { label: '10', value: 10 }, - { label: '20', value: 20 }, - { label: '30', value: 30 }, - { label: '40', value: 40 }, - { label: '50', value: 50 }, - { label: '60', value: 60 }, - { label: '70', value: 70 }, - { label: '80', value: 80 }, - { label: '90', value: 90 }, - { label: '100', value: 100 }, - ], - tooltipInfo: 'The higher the routing score the better the performance of the node and so its rewards', - }, -}); - -const formatStakeSaturationValues = ([value_1, value_2]: number[]) => { - const lowerValue = value_1 / 100; - const upperValue = value_2 / 100; - - return [lowerValue, upperValue]; -}; - -export const formatOnSave = (filters: TFilters) => ({ - routingScore: filters.routingScore.value, - profitMargin: filters.profitMargin.value, - stakeSaturation: formatStakeSaturationValues(filters.stakeSaturation.value), -}); diff --git a/explorer-nextjs/app/components/Footer.tsx b/explorer-nextjs/app/components/Footer.tsx deleted file mode 100644 index 3e69bd3c42d..00000000000 --- a/explorer-nextjs/app/components/Footer.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import React from 'react' -import Box from '@mui/material/Box' -import MuiLink from '@mui/material/Link' -import Typography from '@mui/material/Typography' -import { useIsMobile } from '../hooks/useIsMobile' -import { NymVpnIcon } from '../icons/NymVpn' -import { Socials } from './Socials' -import Link from 'next/link' - -export const Footer: FCWithChildren = () => { - const isMobile = useIsMobile() - - return ( - <Box - sx={{ - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - width: '100%', - height: 'auto', - mt: 3, - pt: 3, - pb: 3, - }} - > - <Box - sx={{ - display: 'flex', - flexDirection: 'row', - width: 'auto', - justifyContent: 'center', - alignItems: 'center', - mb: 2, - }} - > - <Box marginRight={1}> - <Link href="http://nymvpn.com" target="_blank"> - <NymVpnIcon /> - </Link> - </Box> - - <Socials isFooter /> - </Box> - - <Typography - sx={{ - fontSize: 12, - textAlign: isMobile ? 'center' : 'end', - color: 'nym.muted.onDarkBg', - }} - > - © {new Date().getFullYear()} Nym Technologies SA, all rights reserved - </Typography> - </Box> - ) -} diff --git a/explorer-nextjs/app/components/Gateways/Gateways.ts b/explorer-nextjs/app/components/Gateways/Gateways.ts deleted file mode 100644 index f4dbf2743cb..00000000000 --- a/explorer-nextjs/app/components/Gateways/Gateways.ts +++ /dev/null @@ -1,52 +0,0 @@ -import {GatewayResponse, GatewayBond, GatewayReportResponse, LocatedGateway} from '@/app/typeDefs/explorer-api'; -import { toPercentInteger } from '@/app/utils'; - -export type GatewayRowType = { - id: string; - owner: string; - identity_key: string; - bond: number; - host: string; - location: string; - version: string; -// node_performance: number; -}; - -export type GatewayEnrichedRowType = GatewayRowType & { - routingScore: string; - avgUptime: string; - clientsPort: number; - mixPort: number; -}; - -export function gatewayToGridRow(arrayOfGateways: GatewayResponse): GatewayRowType[] { - return !arrayOfGateways - ? [] - : arrayOfGateways.map((gw) => ({ - id: gw.owner, - owner: gw.owner, - identity_key: gw.gateway.identity_key || '', - location: gw.location?.country_name.toUpperCase() || '', - bond: gw.pledge_amount.amount || 0, - host: gw.gateway.host || '', - version: gw.gateway.version || '', -// node_performance: toPercentInteger(gw.node_performance.last_24h), - })); -} - -export function gatewayEnrichedToGridRow(gateway: LocatedGateway, report: GatewayReportResponse): GatewayEnrichedRowType { - return { - id: gateway.owner, - owner: gateway.owner, - identity_key: gateway.gateway.identity_key || '', - location: gateway.location?.country_name.toUpperCase() || '', - bond: gateway.pledge_amount.amount || 0, - host: gateway.gateway.host || '', - version: gateway.gateway.version || '', - clientsPort: gateway.gateway.clients_port || 0, - mixPort: gateway.gateway.mix_port || 0, - routingScore: `${report.most_recent}%`, - avgUptime: `${report.last_day || report.last_hour}%`, -// node_performance: toPercentInteger(gateway.node_performance.most_recent), - }; -} diff --git a/explorer-nextjs/app/components/Gateways/VersionDisplaySelector.tsx b/explorer-nextjs/app/components/Gateways/VersionDisplaySelector.tsx deleted file mode 100644 index 10f230e26a5..00000000000 --- a/explorer-nextjs/app/components/Gateways/VersionDisplaySelector.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react' -import { FormControl, MenuItem, Select } from '@mui/material' -import { useIsMobile } from '@/app/hooks/useIsMobile' - -export enum VersionSelectOptions { - latestVersion = 'Latest versions', - olderVersions = 'Older versions', - all = 'All', -} -export const VersionDisplaySelector = ({ - selected, - handleChange, -}: { - selected: VersionSelectOptions - handleChange: (option: VersionSelectOptions) => void -}) => { - const isMobile = useIsMobile() - - return ( - <FormControl size="small"> - <Select - value={selected} - onChange={(e) => handleChange(e.target.value as VersionSelectOptions)} - labelId="simple-select-label" - id="simple-select" - sx={{ - marginRight: isMobile ? 0 : 2, - }} - > - <MenuItem - value={VersionSelectOptions.latestVersion} - data-testid="show-gateway-latest-version" - > - {VersionSelectOptions.latestVersion} - </MenuItem> - <MenuItem - value={VersionSelectOptions.olderVersions} - data-testid="show-gateway-old-versions" - > - {VersionSelectOptions.olderVersions} - </MenuItem> - <MenuItem - value={VersionSelectOptions.all} - data-testid="show-gateway-all-versions" - > - {VersionSelectOptions.all} - </MenuItem> - </Select> - </FormControl> - ) -} diff --git a/explorer-nextjs/app/components/Icons.ts b/explorer-nextjs/app/components/Icons.ts deleted file mode 100644 index 88761b9d215..00000000000 --- a/explorer-nextjs/app/components/Icons.ts +++ /dev/null @@ -1,28 +0,0 @@ -import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'; -import PauseCircleOutlineIcon from '@mui/icons-material/PauseCircleOutline'; -import CircleOutlinedIcon from '@mui/icons-material/CircleOutlined'; -import { MixnodeStatus } from '../typeDefs/explorer-api'; - -export const Icons = { - Mixnodes: { - Status: { - Active: CheckCircleOutlineIcon, - Standby: PauseCircleOutlineIcon, - Inactive: CircleOutlinedIcon, - }, - }, -}; - -export const getMixNodeIcon = (value: any) => { - if (value && typeof value === 'string') { - switch (value) { - case MixnodeStatus.active: - return Icons.Mixnodes.Status.Active; - case MixnodeStatus.standby: - return Icons.Mixnodes.Status.Standby; - default: - return Icons.Mixnodes.Status.Inactive; - } - } - return Icons.Mixnodes.Status.Inactive; -}; diff --git a/explorer-nextjs/app/components/MixNodes/BondBreakdown.tsx b/explorer-nextjs/app/components/MixNodes/BondBreakdown.tsx deleted file mode 100644 index 58ea4c97b2a..00000000000 --- a/explorer-nextjs/app/components/MixNodes/BondBreakdown.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import * as React from 'react' -import { Alert, Box, CircularProgress, Typography } from '@mui/material' -import { useTheme } from '@mui/material/styles' -import Table from '@mui/material/Table' -import TableBody from '@mui/material/TableBody' -import TableCell from '@mui/material/TableCell' -import TableContainer from '@mui/material/TableContainer' -import TableHead from '@mui/material/TableHead' -import TableRow from '@mui/material/TableRow' -import Paper from '@mui/material/Paper' -import { ExpandMore } from '@mui/icons-material' -import { currencyToString } from '@/app/utils/currency' -import { useMixnodeContext } from '@/app/context/mixnode' -import { useIsMobile } from '@/app/hooks/useIsMobile' - -export const BondBreakdownTable: FCWithChildren = () => { - const { mixNode, delegations, uniqDelegations } = useMixnodeContext() - const [showDelegations, toggleShowDelegations] = - React.useState<boolean>(false) - - const [bonds, setBonds] = React.useState({ - delegations: '0', - pledges: '0', - bondsTotal: '0', - hasLoaded: false, - }) - const theme = useTheme() - const isMobile = useIsMobile() - - React.useEffect(() => { - if (mixNode?.data) { - // delegations - const decimalisedDelegations = currencyToString({ - amount: mixNode.data.total_delegation.amount.toString(), - denom: mixNode.data.total_delegation.denom, - }) - - // pledges - const decimalisedPledges = currencyToString({ - amount: mixNode.data.pledge_amount.amount.toString(), - denom: mixNode.data.pledge_amount.denom, - }) - - // bonds total (del + pledges) - const pledgesSum = Number(mixNode.data.pledge_amount.amount) - const delegationsSum = Number(mixNode.data.total_delegation.amount) - const bondsTotal = currencyToString({ - amount: (pledgesSum + delegationsSum).toString(), - }) - - setBonds({ - delegations: decimalisedDelegations, - pledges: decimalisedPledges, - bondsTotal, - hasLoaded: true, - }) - } - }, [mixNode]) - - const expandDelegations = () => { - if (delegations?.data && delegations.data.length > 0) { - toggleShowDelegations(!showDelegations) - } - } - const calcBondPercentage = (num: number) => { - if (mixNode?.data) { - const rawDelegationAmount = Number(mixNode.data.total_delegation.amount) - const rawPledgeAmount = Number(mixNode.data.pledge_amount.amount) - const rawTotalBondsAmount = rawDelegationAmount + rawPledgeAmount - return ((num * 100) / rawTotalBondsAmount).toFixed(1) - } - return 0 - } - - if (mixNode?.isLoading || delegations?.isLoading) { - return <CircularProgress /> - } - - if (mixNode?.error) { - return <Alert severity="error">Mixnode not found</Alert> - } - if (delegations?.error) { - return <Alert severity="error">Unable to get delegations for mixnode</Alert> - } - - return ( - <TableContainer component={Paper}> - <Table sx={{ minWidth: 650 }} aria-label="bond breakdown totals"> - <TableBody> - <TableRow sx={isMobile ? { minWidth: '70vw' } : null}> - <TableCell - sx={{ - fontWeight: 400, - width: '150px', - }} - align="left" - > - Stake total - </TableCell> - <TableCell align="left" data-testid="bond-total-amount"> - {bonds.bondsTotal} - </TableCell> - </TableRow> - <TableRow> - <TableCell align="left">Bond</TableCell> - <TableCell align="left" data-testid="pledge-total-amount"> - {bonds.pledges} - </TableCell> - </TableRow> - <TableRow> - <TableCell onClick={expandDelegations} align="left"> - <Box - sx={{ - display: 'flex', - alignItems: 'center', - }} - > - Delegation total {'\u00A0'} - {delegations?.data && delegations?.data?.length > 0 && ( - <ExpandMore /> - )} - </Box> - </TableCell> - <TableCell align="left" data-testid="delegation-total-amount"> - {bonds.delegations} - </TableCell> - </TableRow> - </TableBody> - </Table> - - {showDelegations && ( - <Box - sx={{ - maxHeight: 400, - overflowY: 'scroll', - p: 2, - background: theme.palette.background.paper, - }} - > - <Box - sx={{ - display: 'flex', - alignItems: 'baseline', - width: '100%', - p: 2, - borderBottom: `1px solid ${theme.palette.divider}`, - }} - data-testid="delegations-total-amount" - > - <Typography - sx={{ - fontSize: 16, - fontWeight: 600, - }} - > - Delegations   - </Typography> - </Box> - <Table stickyHeader> - <TableHead> - <TableRow> - <TableCell - sx={{ - fontWeight: 600, - background: theme.palette.background.paper, - }} - align="left" - > - Delegators - </TableCell> - <TableCell - sx={{ - fontWeight: 600, - background: theme.palette.background.paper, - }} - align="left" - > - Amount - </TableCell> - <TableCell - sx={{ - fontWeight: 600, - background: theme.palette.background.paper, - width: '200px', - }} - align="left" - > - Share of stake - </TableCell> - </TableRow> - </TableHead> - - <TableBody> - {uniqDelegations?.data?.map(({ owner, amount: { amount } }) => ( - <TableRow key={owner}> - <TableCell sx={isMobile ? { width: 190 } : null} align="left"> - {owner} - </TableCell> - <TableCell align="left"> - {currencyToString({ amount: amount.toString() })} - </TableCell> - <TableCell align="left"> - {calcBondPercentage(amount)}% - </TableCell> - </TableRow> - ))} - </TableBody> - </Table> - </Box> - )} - </TableContainer> - ) -} diff --git a/explorer-nextjs/app/components/MixNodes/DetailSection.tsx b/explorer-nextjs/app/components/MixNodes/DetailSection.tsx deleted file mode 100644 index 94a24f338d9..00000000000 --- a/explorer-nextjs/app/components/MixNodes/DetailSection.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import * as React from 'react' -import { Box, Button, Grid, Typography, useTheme } from '@mui/material' -import Identicon from 'react-identicons' -import { useIsMobile } from '@/app/hooks/useIsMobile' -import { MixNodeDescriptionResponse } from '@/app/typeDefs/explorer-api' -import { getMixNodeStatusText, MixNodeStatus } from './Status' -import { MixnodeRowType } from '.' - -interface MixNodeDetailProps { - mixNodeRow: MixnodeRowType - mixnodeDescription: MixNodeDescriptionResponse -} - -export const MixNodeDetailSection: FCWithChildren<MixNodeDetailProps> = ({ - mixNodeRow, - mixnodeDescription, -}) => { - const theme = useTheme() - const palette = [theme.palette.text.primary] - const isMobile = useIsMobile() - const statusText = React.useMemo( - () => getMixNodeStatusText(mixNodeRow.status), - [mixNodeRow.status] - ) - - return ( - <Grid container> - <Grid item xs={12} md={6}> - <Box - display="flex" - flexDirection={isMobile ? 'column' : 'row'} - width="100%" - > - <Box - width={72} - height={72} - sx={{ - minWidth: 72, - minHeight: 72, - borderWidth: 1, - borderColor: theme.palette.text.primary, - borderStyle: 'solid', - borderRadius: '50%', - display: 'grid', - placeItems: 'center', - }} - > - <Identicon - size={43} - string={mixNodeRow.identity_key} - palette={palette} - /> - </Box> - <Box ml={isMobile ? 0 : 2} mt={isMobile ? 2 : 0}> - <Typography fontSize={21}>{mixnodeDescription.name}</Typography> - <Typography> - {(mixnodeDescription.description || '').slice(0, 1000)} - </Typography> - <Button - component="a" - variant="text" - sx={{ - mt: isMobile ? 2 : 4, - borderRadius: '30px', - fontWeight: 600, - padding: 0, - }} - href={mixnodeDescription.link} - target="_blank" - > - <Typography - component="span" - textOverflow="ellipsis" - whiteSpace="nowrap" - overflow="hidden" - maxWidth="250px" - > - {mixnodeDescription.link} - </Typography> - </Button> - </Box> - </Box> - </Grid> - <Grid - item - xs={12} - md={6} - display="flex" - justifyContent={isMobile ? 'start' : 'end'} - mt={isMobile ? 3 : undefined} - > - <Box display="flex" flexDirection="column"> - <Typography - fontWeight="600" - alignSelf={isMobile ? 'start' : 'self-end'} - > - Node status: - </Typography> - <Box mt={2} alignSelf={isMobile ? 'start' : 'self-end'}> - <MixNodeStatus status={mixNodeRow.status} /> - </Box> - <Typography - mt={1} - alignSelf={isMobile ? 'start' : 'self-end'} - color={theme.palette.text.secondary} - fontSize="smaller" - > - This node is {statusText} in this epoch - </Typography> - </Box> - </Grid> - </Grid> - ) -} diff --git a/explorer-nextjs/app/components/MixNodes/Economics/Columns.ts b/explorer-nextjs/app/components/MixNodes/Economics/Columns.ts deleted file mode 100644 index b2115c0749c..00000000000 --- a/explorer-nextjs/app/components/MixNodes/Economics/Columns.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { ColumnsType } from '../../DetailTable'; - -export const EconomicsInfoColumns: ColumnsType[] = [ - { - field: 'estimatedTotalReward', - title: 'Estimated Total Reward', - width: '15%', - tooltipInfo: - 'Estimated node reward (total for the operator and delegators) in the current epoch. There are roughly 24 epochs in a day.', - }, - { - field: 'estimatedOperatorReward', - title: 'Estimated Operator Reward', - width: '15%', - tooltipInfo: - "Estimated operator's reward (including PM and Operating Cost) in the current epoch. There are roughly 24 epochs in a day.", - }, - { - field: 'selectionChance', - title: 'Active Set Probability', - width: '12.5%', - tooltipInfo: - 'Probability of getting selected in the reward set (active and standby nodes) in the next epoch. The more your stake, the higher the chances to be selected.', - }, - { - field: 'profitMargin', - title: 'Profit Margin', - width: '12.5%', - tooltipInfo: - 'Percentage of the delegators rewards that the operator takes as fee before rewards are distributed to the delegators.', - }, - { - field: 'operatingCost', - title: 'Operating Cost', - width: '10%', - tooltipInfo: - 'Monthly operational cost of running this node. This cost is set by the operator and it influences how the rewards are split between the operator and delegators.', - }, - { - field: 'nodePerformance', - title: 'Routing Score', - width: '10%', - tooltipInfo: - "Mixnode's most recent score (measured in the last 15 minutes). Routing score is relative to that of the network. Each time a gateway is tested, the test packets have to go through the full path of the network (gateway + 3 nodes). If a node in the path drop packets it will affect the score of the gateway and other nodes in the test.", - }, - { - field: 'avgUptime', - title: 'Avg. Score', - tooltipInfo: "Mixnode's average routing score in the last 24 hour", - }, -]; diff --git a/explorer-nextjs/app/components/MixNodes/Economics/EconomicsProgress.stories.tsx b/explorer-nextjs/app/components/MixNodes/Economics/EconomicsProgress.stories.tsx deleted file mode 100644 index aef36113df8..00000000000 --- a/explorer-nextjs/app/components/MixNodes/Economics/EconomicsProgress.stories.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import * as React from 'react'; -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { EconomicsProgress } from './EconomicsProgress'; - -export default { - title: 'Mix Node Detail/Economics/ProgressBar', - component: EconomicsProgress, -} as ComponentMeta<typeof EconomicsProgress>; - -const Template: ComponentStory<typeof EconomicsProgress> = (args) => <EconomicsProgress {...args} />; - -export const Empty = Template.bind({}); -Empty.args = {}; - -export const OverThreshold = Template.bind({}); -OverThreshold.args = { - threshold: 100, - value: 120, -}; - -export const UnderThreshold = Template.bind({}); -UnderThreshold.args = { - threshold: 100, - value: 80, -}; - -export const OnThreshold = Template.bind({}); -OnThreshold.args = { - threshold: 100, - value: 100, -}; diff --git a/explorer-nextjs/app/components/MixNodes/Economics/EconomicsProgress.tsx b/explorer-nextjs/app/components/MixNodes/Economics/EconomicsProgress.tsx deleted file mode 100644 index 24db62d1673..00000000000 --- a/explorer-nextjs/app/components/MixNodes/Economics/EconomicsProgress.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as React from 'react'; -import LinearProgress, { LinearProgressProps } from '@mui/material/LinearProgress'; -import { useTheme } from '@mui/material/styles'; -import { Box } from '@mui/system'; - -const parseToNumber = (value: number | undefined | string) => - typeof value === 'string' ? parseInt(value || '', 10) : value || 0; - -export const EconomicsProgress: FCWithChildren< - LinearProgressProps & { - threshold?: number; - color: string; - } -> = ({ threshold, color, ...props }) => { - const theme = useTheme(); - const { value } = props; - - const valueNumber: number = parseToNumber(value); - const thresholdNumber: number = parseToNumber(threshold); - const percentageToDisplay = Math.min(valueNumber, thresholdNumber); - - return ( - <Box - sx={{ - width: 6 / 10, - color: valueNumber > (threshold || 100) ? theme.palette.warning.main : theme.palette.nym.wallet.fee, - }} - > - <LinearProgress - {...props} - variant="determinate" - color={color} - value={percentageToDisplay} - sx={{ width: '100%', borderRadius: '5px' }} - /> - </Box> - ); -}; diff --git a/explorer-nextjs/app/components/MixNodes/Economics/MixNodeEconomics.stories.tsx b/explorer-nextjs/app/components/MixNodes/Economics/MixNodeEconomics.stories.tsx deleted file mode 100644 index c9c82c0438f..00000000000 --- a/explorer-nextjs/app/components/MixNodes/Economics/MixNodeEconomics.stories.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import * as React from 'react'; -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { DelegatorsInfoTable } from './Table'; -import { EconomicsInfoColumns } from './Columns'; -import { EconomicsInfoRowWithIndex } from './types'; - -export default { - title: 'Mix Node Detail/Economics', - component: DelegatorsInfoTable, -} as ComponentMeta<typeof DelegatorsInfoTable>; - -const row: EconomicsInfoRowWithIndex = { - id: 1, - selectionChance: { - value: 'High', - }, - - estimatedOperatorReward: { - value: '80000.123456 NYM', - }, - estimatedTotalReward: { - value: '80000.123456 NYM', - }, - profitMargin: { - value: '10 %', - }, - operatingCost: { - value: '11121 NYM', - }, - avgUptime: { - value: '-', - }, - nodePerformance: { - value: '-', - }, -}; - -const rowGoodProbabilitySelection: EconomicsInfoRowWithIndex = { - ...row, - selectionChance: { - value: 'Good', - }, -}; - -const rowLowProbabilitySelection: EconomicsInfoRowWithIndex = { - ...row, - selectionChance: { - value: 'Low', - }, -}; - -const emptyRow: EconomicsInfoRowWithIndex = { - id: 1, - selectionChance: { - value: '-', - progressBarValue: 0, - }, - - estimatedOperatorReward: { - value: '-', - }, - estimatedTotalReward: { - value: '-', - }, - profitMargin: { - value: '-', - }, - operatingCost: { - value: '-', - }, - avgUptime: { - value: '-', - }, - nodePerformance: { - value: '-', - }, -}; - -const Template: ComponentStory<typeof DelegatorsInfoTable> = (args) => <DelegatorsInfoTable {...args} />; - -export const Empty = Template.bind({}); -Empty.args = { - rows: [emptyRow], - columnsData: EconomicsInfoColumns, - tableName: 'storybook', -}; - -export const selectionChanceHigh = Template.bind({}); -selectionChanceHigh.args = { - rows: [row], - columnsData: EconomicsInfoColumns, - tableName: 'storybook', -}; - -export const selectionChanceGood = Template.bind({}); -selectionChanceGood.args = { - rows: [rowGoodProbabilitySelection], - columnsData: EconomicsInfoColumns, - tableName: 'storybook', -}; - -export const selectionChanceLow = Template.bind({}); -selectionChanceLow.args = { - rows: [rowLowProbabilitySelection], - columnsData: EconomicsInfoColumns, - tableName: 'storybook', -}; diff --git a/explorer-nextjs/app/components/MixNodes/Economics/Rows.ts b/explorer-nextjs/app/components/MixNodes/Economics/Rows.ts deleted file mode 100644 index 62b27cf2292..00000000000 --- a/explorer-nextjs/app/components/MixNodes/Economics/Rows.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { currencyToString, unymToNym } from '@/app/utils/currency'; -import { useMixnodeContext } from '@/app/context/mixnode'; -import { ApiState, MixNodeEconomicDynamicsStatsResponse } from '@/app/typeDefs/explorer-api'; -import { toPercentIntegerString } from '@/app/utils'; -import { EconomicsInfoRowWithIndex } from './types'; - -const selectionChance = (economicDynamicsStats: ApiState<MixNodeEconomicDynamicsStatsResponse> | undefined) => - economicDynamicsStats?.data?.active_set_inclusion_probability || '-'; - -export const EconomicsInfoRows = (): EconomicsInfoRowWithIndex => { - const { economicDynamicsStats, mixNode } = useMixnodeContext(); - - const estimatedNodeRewards = - currencyToString({ - amount: economicDynamicsStats?.data?.estimated_total_node_reward.toString() || '', - }) || '-'; - const estimatedOperatorRewards = - currencyToString({ - amount: economicDynamicsStats?.data?.estimated_operator_reward.toString() || '', - }) || '-'; - const profitMargin = mixNode?.data?.profit_margin_percent - ? toPercentIntegerString(mixNode?.data?.profit_margin_percent) - : '-'; - const avgUptime = mixNode?.data?.node_performance - ? toPercentIntegerString(mixNode?.data?.node_performance.last_24h) - : '-'; - const nodePerformance = mixNode?.data?.node_performance - ? toPercentIntegerString(mixNode?.data?.node_performance.most_recent) - : '-'; - - const opCost = mixNode?.data?.operating_cost; - - return { - id: 1, - estimatedTotalReward: { - value: estimatedNodeRewards, - }, - estimatedOperatorReward: { - value: estimatedOperatorRewards, - }, - selectionChance: { - value: selectionChance(economicDynamicsStats), - }, - profitMargin: { - value: profitMargin ? `${profitMargin} %` : '-', - }, - operatingCost: { - value: opCost ? `${unymToNym(opCost.amount, 6)} NYM` : '-', - }, - avgUptime: { - value: avgUptime ? `${avgUptime} %` : '-', - }, - nodePerformance: { - value: nodePerformance, - }, - }; -}; diff --git a/explorer-nextjs/app/components/MixNodes/Economics/StakeSaturationProgressBar.tsx b/explorer-nextjs/app/components/MixNodes/Economics/StakeSaturationProgressBar.tsx deleted file mode 100644 index e497a72eddb..00000000000 --- a/explorer-nextjs/app/components/MixNodes/Economics/StakeSaturationProgressBar.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from 'react' -import { Box, Typography } from '@mui/material' -import { useIsMobile } from '@/app/hooks/useIsMobile' -import { EconomicsProgress } from './EconomicsProgress' - -export const StakeSaturationProgressBar = ({ - value, - threshold, -}: { - value: number - threshold: number -}) => { - const isTablet = useIsMobile('lg') - const percentageColor = value > (threshold || 100) ? 'warning' : 'inherit' - const textColor = - percentageColor === 'warning' ? 'warning.main' : 'nym.wallet.fee' - - return ( - <Box - sx={{ - display: 'flex', - alignItems: 'center', - flexDirection: isTablet ? 'column' : 'row', - }} - id="field" - color={percentageColor} - > - <Typography - sx={{ - mr: isTablet ? 0 : 1, - mb: isTablet ? 1 : 0, - fontWeight: '600', - fontSize: '12px', - color: textColor, - }} - id="stake-saturation-progress-bar" - > - {value}% - </Typography> - <EconomicsProgress - value={value} - threshold={threshold} - color={percentageColor} - /> - </Box> - ) -} diff --git a/explorer-nextjs/app/components/MixNodes/Economics/Table.tsx b/explorer-nextjs/app/components/MixNodes/Economics/Table.tsx deleted file mode 100644 index a70a013a245..00000000000 --- a/explorer-nextjs/app/components/MixNodes/Economics/Table.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import * as React from 'react' -import { - Paper, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, - Typography, -} from '@mui/material' -import { Box } from '@mui/system' -import { useTheme } from '@mui/material/styles' -import { Tooltip } from '@nymproject/react/tooltip/Tooltip' -import { EconomicsRowsType, EconomicsInfoRowWithIndex } from './types' -import { UniversalTableProps } from '@/app/components/DetailTable' -import { textColour } from '@/app/utils' - -const formatCellValues = (value: EconomicsRowsType, field: string) => ( - <Box sx={{ display: 'flex', alignItems: 'center' }} id="field"> - <Typography sx={{ mr: 1, fontWeight: '600', fontSize: '12px' }} id={field}> - {value.value} - </Typography> - </Box> -) - -export const DelegatorsInfoTable: FCWithChildren< - UniversalTableProps<EconomicsInfoRowWithIndex> -> = ({ tableName, columnsData, rows }) => { - const theme = useTheme() - - return ( - <TableContainer component={Paper}> - <Table sx={{ minWidth: 650 }} aria-label={tableName}> - <TableHead> - <TableRow> - {columnsData?.map(({ field, title, tooltipInfo, width }) => ( - <TableCell - key={field} - sx={{ fontSize: 14, fontWeight: 600, width }} - > - <Box sx={{ display: 'flex', alignItems: 'center' }}> - {tooltipInfo && ( - <Tooltip - title={tooltipInfo} - id={field} - placement="top-start" - textColor={ - theme.palette.nym.networkExplorer.tooltip.color - } - bgColor={ - theme.palette.nym.networkExplorer.tooltip.background - } - maxWidth={230} - arrow - /> - )} - {title} - </Box> - </TableCell> - ))} - </TableRow> - </TableHead> - <TableBody> - {rows?.map((eachRow) => ( - <TableRow - key={eachRow.id} - sx={{ '&:last-child td, &:last-child th': { border: 0 } }} - > - {columnsData?.map((_, index: number) => { - const { field } = columnsData[index] - const value: EconomicsRowsType = (eachRow as any)[field] - return ( - <TableCell - key={_.title} - sx={{ - color: textColour(value, field, theme), - }} - data-testid={`${_.title.replace(/ /g, '-')}-value`} - > - {formatCellValues(value, columnsData[index].field)} - </TableCell> - ) - })} - </TableRow> - ))} - </TableBody> - </Table> - </TableContainer> - ) -} diff --git a/explorer-nextjs/app/components/MixNodes/Economics/index.ts b/explorer-nextjs/app/components/MixNodes/Economics/index.ts deleted file mode 100644 index 6dec7522464..00000000000 --- a/explorer-nextjs/app/components/MixNodes/Economics/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { DelegatorsInfoTable } from './Table'; -export { EconomicsInfoColumns } from './Columns'; -export { EconomicsInfoRows } from './Rows'; diff --git a/explorer-nextjs/app/components/MixNodes/Economics/types.ts b/explorer-nextjs/app/components/MixNodes/Economics/types.ts deleted file mode 100644 index 0bc550253f7..00000000000 --- a/explorer-nextjs/app/components/MixNodes/Economics/types.ts +++ /dev/null @@ -1,20 +0,0 @@ -export type EconomicsRowsType = { - progressBarValue?: number; - value: string; -}; - -type TEconomicsInfoProperties = - | 'estimatedTotalReward' - | 'estimatedOperatorReward' - | 'estimatedOperatorReward' - | 'selectionChance' - | 'profitMargin' - | 'avgUptime' - | 'nodePerformance' - | 'operatingCost'; - -export type EconomicsInfoRow = { - [k in TEconomicsInfoProperties]: EconomicsRowsType; -}; - -export type EconomicsInfoRowWithIndex = EconomicsInfoRow & { id: number }; diff --git a/explorer-nextjs/app/components/MixNodes/Status.tsx b/explorer-nextjs/app/components/MixNodes/Status.tsx deleted file mode 100644 index bc8f1fe6600..00000000000 --- a/explorer-nextjs/app/components/MixNodes/Status.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import * as React from 'react' -import { Typography } from '@mui/material' -import { getMixNodeIcon } from '@/app/components/Icons' -import { MixnodeStatus } from '@/app/typeDefs/explorer-api' -import { useGetMixNodeStatusColor } from '@/app/hooks/useGetMixnodeStatusColor' - -interface MixNodeStatusProps { - status: MixnodeStatus -} -// TODO: should be done with i18n -export const getMixNodeStatusText = (status: MixnodeStatus) => { - switch (status) { - case MixnodeStatus.active: - return 'active' - case MixnodeStatus.standby: - return 'on standby' - default: - return 'inactive' - } -} - -export const MixNodeStatus: FCWithChildren<MixNodeStatusProps> = ({ - status, -}) => { - const Icon = React.useMemo(() => getMixNodeIcon(status), [status]) - const color = useGetMixNodeStatusColor(status) - - return ( - <Typography color={color} display="flex" alignItems="center"> - <Icon /> - <Typography ml={1} component="span" color="inherit"> - {`${status[0].toUpperCase()}${status.slice(1)}`} - </Typography> - </Typography> - ) -} diff --git a/explorer-nextjs/app/components/MixNodes/StatusDropdown.tsx b/explorer-nextjs/app/components/MixNodes/StatusDropdown.tsx deleted file mode 100644 index dc505869ed0..00000000000 --- a/explorer-nextjs/app/components/MixNodes/StatusDropdown.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import * as React from 'react' -import { MenuItem } from '@mui/material' -import Select from '@mui/material/Select' -import { SelectChangeEvent } from '@mui/material/Select/SelectInput' -import { SxProps } from '@mui/system' -import { - MixnodeStatus, - MixnodeStatusWithAll, -} from '@/app/typeDefs/explorer-api' -import { useIsMobile } from '@/app/hooks/useIsMobile' -import { MixNodeStatus } from './Status' - -// TODO: replace with i18n -const ALL_NODES = 'All nodes' - -interface MixNodeStatusDropdownProps { - status?: MixnodeStatusWithAll - sx?: SxProps - onSelectionChanged?: (status?: MixnodeStatusWithAll) => void -} - -export const MixNodeStatusDropdown: FCWithChildren< - MixNodeStatusDropdownProps -> = ({ status, onSelectionChanged, sx }) => { - const isMobile = useIsMobile() - const [statusValue, setStatusValue] = React.useState<MixnodeStatusWithAll>( - status || MixnodeStatusWithAll.all - ) - const onChange = React.useCallback( - (event: SelectChangeEvent) => { - setStatusValue(event.target.value as MixnodeStatusWithAll) - if (onSelectionChanged) { - onSelectionChanged(event.target.value as MixnodeStatusWithAll) - } - }, - [onSelectionChanged] - ) - - return ( - <Select - labelId="mixnodeStatusSelect_label" - id="mixnodeStatusSelect" - value={statusValue} - onChange={onChange} - renderValue={(value) => { - switch (value) { - case 'active': - case 'standby': - case 'inactive': - return <MixNodeStatus status={value as unknown as MixnodeStatus} /> - default: - return ALL_NODES - } - }} - sx={{ - width: isMobile ? '50%' : 200, - ...sx, - }} - > - <MenuItem - value={MixnodeStatus.active} - data-testid="mixnodeStatusSelectOption_active" - > - <MixNodeStatus status={MixnodeStatus.active} /> - </MenuItem> - <MenuItem - value={MixnodeStatus.standby} - data-testid="mixnodeStatusSelectOption_standby" - > - <MixNodeStatus status={MixnodeStatus.standby} /> - </MenuItem> - <MenuItem - value={MixnodeStatus.inactive} - data-testid="mixnodeStatusSelectOption_inactive" - > - <MixNodeStatus status={MixnodeStatus.inactive} /> - </MenuItem> - <MenuItem value={'all'} data-testid="mixnodeStatusSelectOption_allNodes"> - {ALL_NODES} - </MenuItem> - </Select> - ) -} diff --git a/explorer-nextjs/app/components/MixNodes/index.ts b/explorer-nextjs/app/components/MixNodes/index.ts deleted file mode 100644 index ccb6c5a8b3f..00000000000 --- a/explorer-nextjs/app/components/MixNodes/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './Status'; -export * from './StatusDropdown'; -export * from './mappings'; diff --git a/explorer-nextjs/app/components/MixNodes/mappings.ts b/explorer-nextjs/app/components/MixNodes/mappings.ts deleted file mode 100644 index df8558d39bc..00000000000 --- a/explorer-nextjs/app/components/MixNodes/mappings.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* eslint-disable camelcase */ -import { MixNodeResponse, MixNodeResponseItem, MixnodeStatus } from '../../typeDefs/explorer-api'; -import { toPercentInteger, toPercentIntegerString } from '@/app/utils'; -import { unymToNym } from '@/app/utils/currency'; - -export type MixnodeRowType = { - mix_id: number; - id: string; - status: MixnodeStatus; - owner: string; - location: string; - identity_key: string; - bond: number; - self_percentage: string; - pledge_amount: number; - host: string; - layer: string; - profit_percentage: number; - avg_uptime: string; - stake_saturation: React.ReactNode; - operating_cost: number; - node_performance: number; - blacklisted: boolean; -}; - -export function mixnodeToGridRow(arrayOfMixnodes?: MixNodeResponse): MixnodeRowType[] { - return (arrayOfMixnodes || []).map(mixNodeResponseItemToMixnodeRowType); -} - -export function mixNodeResponseItemToMixnodeRowType(item: MixNodeResponseItem): MixnodeRowType { - const pledge = Number(item.pledge_amount.amount) || 0; - const delegations = Number(item.total_delegation.amount) || 0; - const totalBond = pledge + delegations; - const selfPercentage = ((pledge * 100) / totalBond).toFixed(2); - const profitPercentage = toPercentInteger(item.profit_margin_percent) || 0; - const uncappedSaturation = typeof item.uncapped_saturation === 'number' ? item.uncapped_saturation * 100 : 0; - - return { - mix_id: item.mix_id, - id: item.owner, - status: item.status, - owner: item.owner, - identity_key: item.mix_node.identity_key || '', - bond: totalBond || 0, - location: item?.location?.country_name || '', - self_percentage: selfPercentage, - pledge_amount: pledge, - host: item?.mix_node?.host || '', - layer: item?.layer || '', - profit_percentage: profitPercentage, - avg_uptime: `${toPercentIntegerString(item.node_performance.last_24h)}%`, - stake_saturation: Number(uncappedSaturation.toFixed(2)), - operating_cost: Number(unymToNym(item.operating_cost?.amount, 6)) || 0, - node_performance: toPercentInteger(item.node_performance.most_recent), - blacklisted: item.blacklisted, - }; -} diff --git a/explorer-nextjs/app/components/Nav/DesktopNav.tsx b/explorer-nextjs/app/components/Nav/DesktopNav.tsx deleted file mode 100644 index e1faab46f1a..00000000000 --- a/explorer-nextjs/app/components/Nav/DesktopNav.tsx +++ /dev/null @@ -1,379 +0,0 @@ -'use client' - -import * as React from 'react' -import { ExpandLess, ExpandMore, Menu } from '@mui/icons-material' -import { CSSObject, styled, Theme, useTheme } from '@mui/material/styles' -import { Link as MuiLink } from '@mui/material' -import Button from '@mui/material/Button' -import Box from '@mui/material/Box' -import ListItem from '@mui/material/ListItem' -import MuiDrawer from '@mui/material/Drawer' -import AppBar from '@mui/material/AppBar' -import Toolbar from '@mui/material/Toolbar' -import Typography from '@mui/material/Typography' -import List from '@mui/material/List' -import IconButton from '@mui/material/IconButton' -import ListItemButton from '@mui/material/ListItemButton' -import ListItemIcon from '@mui/material/ListItemIcon' -import ListItemText from '@mui/material/ListItemText' -import { NYM_WEBSITE } from '@/app/api/constants' -import { useMainContext } from '@/app/context/main' -import { MobileDrawerClose } from '@/app/icons/MobileDrawerClose' -import { NavOptionType, originalNavOptions } from '@/app/context/nav' -import { ReleaseAlert } from '@/app/components/ReleaseAlert' -import { DarkLightSwitchDesktop } from '@/app/components/Switch' -import { Footer } from '@/app/components/Footer' -import { ConnectKeplrWallet } from '@/app/components/Wallet/ConnectKeplrWallet' -import { usePathname, useRouter } from 'next/navigation' -import {SearchToolbar} from "@/app/components/Nav/Search"; - -const drawerWidth = 255 -const bannerHeight = 80 - -const openedMixin = (theme: Theme): CSSObject => ({ - width: drawerWidth, - transition: theme.transitions.create('width', { - easing: theme.transitions.easing.sharp, - duration: theme.transitions.duration.enteringScreen, - }), - overflowX: 'hidden', -}) - -const closedMixin = (theme: Theme): CSSObject => ({ - transition: theme.transitions.create('width', { - easing: theme.transitions.easing.sharp, - duration: theme.transitions.duration.leavingScreen, - }), - overflowX: 'hidden', - width: `calc(${theme.spacing(7)} + 1px)`, -}) - -const DrawerHeader = styled('div')(({ theme }) => ({ - display: 'flex', - alignItems: 'center', - justifyContent: 'flex-end', - padding: theme.spacing(0, 1), - height: 64, -})) - -const Drawer = styled(MuiDrawer, { - shouldForwardProp: (prop) => prop !== 'open', -})(({ theme, open }) => ({ - width: drawerWidth, - flexShrink: 0, - whiteSpace: 'nowrap', - boxSizing: 'border-box', - ...(open && { - ...openedMixin(theme), - '& .MuiDrawer-paper': openedMixin(theme), - }), - ...(!open && { - ...closedMixin(theme), - '& .MuiDrawer-paper': closedMixin(theme), - }), -})) - -type ExpandableButtonType = { - title: string - url: string - isActive?: boolean - Icon?: React.ReactNode - nested?: NavOptionType[] - isChild?: boolean - isMobile: boolean - drawIsTempOpen: boolean - drawIsFixed: boolean - isExternalLink?: boolean - openDrawer: () => void - closeDrawer?: () => void - fixDrawerClose?: () => void -} - -export const ExpandableButton: FCWithChildren<ExpandableButtonType> = ({ - title, - url, - drawIsTempOpen, - drawIsFixed, - Icon, - nested, - isMobile, - isChild, - isExternalLink, - openDrawer, - closeDrawer, - fixDrawerClose, -}) => { - const { palette } = useTheme() - const pathname = usePathname() - const router = useRouter() - - const handleClick = () => { - if (title === 'Network Components') { - return undefined - } - - if (isExternalLink) { - window.open(url, '_blank') - - return undefined - } - - if (!isExternalLink) { - router.push(url, {}) - } - - if (closeDrawer) { - closeDrawer() - } - } - const selectedStyle = { - background: palette.nym.networkExplorer.nav.selected.main, - borderRight: `3px solid ${palette.nym.highlight}`, - } - - return ( - <> - <ListItem - disablePadding - disableGutters - sx={{ - borderBottom: isChild ? 'none' : '1px solid rgba(255, 255, 255, 0.1)', - ...(pathname === url - ? selectedStyle - : { - background: palette.nym.networkExplorer.nav.background, - borderRight: 'none', - }), - }} - > - <ListItemButton - onClick={() => handleClick()} - sx={{ - pt: 2, - pb: 2, - background: isChild - ? palette.nym.networkExplorer.nav.selected.nested - : 'none', - }} - > - <ListItemIcon sx={{ minWidth: '39px' }}>{Icon}</ListItemIcon> - <ListItemText - primary={title} - sx={{ - color: palette.nym.networkExplorer.nav.text, - }} - /> - </ListItemButton> - </ListItem> - {nested?.map((each) => ( - <ExpandableButton - url={each.url} - key={each.title} - title={each.title} - openDrawer={openDrawer} - drawIsTempOpen={drawIsTempOpen} - closeDrawer={closeDrawer} - drawIsFixed={drawIsFixed} - fixDrawerClose={fixDrawerClose} - isMobile={isMobile} - isChild - isExternalLink={each.isExternal} - /> - ))} - </> - ) -} - -export const Nav: FCWithChildren = ({ children }) => { - const { environment } = useMainContext() - const [drawerIsOpen, setDrawerToOpen] = React.useState(false) - const [fixedOpen, setFixedOpen] = React.useState(false) - // Set maintenance banner to false by default to don't display it - const [openMaintenance, setOpenMaintenance] = React.useState(false) - const theme = useTheme() - - const explorerName = environment - ? `${environment} Explorer` - : 'Mainnet Explorer' - - const switchNetworkText = - environment === 'mainnet' ? 'Switch to Testnet' : 'Switch to Mainnet' - const switchNetworkLink = - environment === 'mainnet' - ? 'https://sandbox-explorer.nymtech.net' - : 'https://explorer.nymtech.net' - - const fixDrawerOpen = () => { - setFixedOpen(true) - setDrawerToOpen(true) - } - - const fixDrawerClose = () => { - setFixedOpen(false) - setDrawerToOpen(false) - } - - const tempDrawerOpen = () => { - if (!fixedOpen) { - setDrawerToOpen(true) - } - } - - const tempDrawerClose = () => { - if (!fixedOpen) { - setDrawerToOpen(false) - } - } - - return ( - <Box sx={{ display: 'flex' }}> - <AppBar - sx={{ - background: theme.palette.nym.networkExplorer.topNav.appBar, - borderRadius: 0, - }} - > - <Toolbar - disableGutters - sx={{ - display: 'flex', - justifyContent: 'space-between', - }} - > - <Box - sx={{ - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - ml: 0.5, - }} - > - <IconButton component="a" href={NYM_WEBSITE} target="_blank"> - {/* <NymLogo /> */} - </IconButton> - <Typography - variant="h6" - noWrap - sx={{ - color: theme.palette.nym.networkExplorer.nav.text, - fontSize: '18px', - fontWeight: 600, - }} - > - <MuiLink - href="/" - underline="none" - color="inherit" - textTransform="capitalize" - > - {explorerName} - </MuiLink> - <Button - size="small" - variant="outlined" - color="inherit" - href={switchNetworkLink} - sx={{ - borderRadius: 2, - textTransform: 'none', - width: 150, - ml: 4, - fontSize: 14, - fontWeight: 600, - }} - > - {switchNetworkText} - </Button> - </Typography> - </Box> - <Box - sx={{ - mr: 2, - alignItems: 'center', - display: 'flex', - }} - > - <Box> - <SearchToolbar/> - </Box> - <Box - sx={{ - display: 'flex', - flexDirection: 'row', - width: 'auto', - pr: 0, - pl: 2, - justifyContent: 'flex-end', - alignItems: 'center', - }} - > - <Box sx={{ mr: 1 }}> - <ConnectKeplrWallet /> - </Box> - <DarkLightSwitchDesktop defaultChecked /> - </Box> - </Box> - </Toolbar> - </AppBar> - <Drawer - variant="permanent" - open={true} - PaperProps={{ - style: { - background: theme.palette.nym.networkExplorer.nav.background, - borderRadius: 0, - top: openMaintenance ? bannerHeight : 0, - }, - }} - > - <DrawerHeader - sx={{ - borderBottom: '1px solid rgba(255, 255, 255, 0.1)', - justifyContent: 'flex-start', - paddingLeft: 0, - display: 'none', - }} - > - <IconButton - onClick={drawerIsOpen ? fixDrawerClose : fixDrawerOpen} - sx={{ - padding: 1, - ml: 1, - color: theme.palette.nym.networkExplorer.nav.text, - }} - > - {drawerIsOpen ? <MobileDrawerClose /> : <Menu />} - </IconButton> - </DrawerHeader> - - <List - sx={{ pb: 0 }} - onMouseEnter={tempDrawerOpen} - onMouseLeave={tempDrawerClose} - > - {originalNavOptions.map((props) => ( - <ExpandableButton - key={props.url} - closeDrawer={tempDrawerClose} - drawIsTempOpen={drawerIsOpen} - drawIsFixed={fixedOpen} - fixDrawerClose={fixDrawerClose} - openDrawer={tempDrawerOpen} - isMobile={false} - {...props} - /> - ))} - </List> - </Drawer> - <Box - style={{ width: `calc(100% - ${drawerWidth}px` }} - sx={{ py: 5, px: 6, mt: 7 }} - > - <ReleaseAlert /> - {children} - <Footer /> - </Box> - </Box> - ) -} diff --git a/explorer-nextjs/app/components/Nav/MobileNav.tsx b/explorer-nextjs/app/components/Nav/MobileNav.tsx deleted file mode 100644 index 3d1cfdcbf99..00000000000 --- a/explorer-nextjs/app/components/Nav/MobileNav.tsx +++ /dev/null @@ -1,147 +0,0 @@ -'use client' - -import * as React from 'react' -import { useTheme } from '@mui/material/styles' -import { - AppBar, - Box, - Drawer, - IconButton, - List, - ListItem, - ListItemButton, - ListItemIcon, - Toolbar, -} from '@mui/material' -import { Menu } from '@mui/icons-material' -import { MaintenanceBanner } from '@nymproject/react/banners/MaintenanceBanner' -import { useIsMobile } from '@/app/hooks/useIsMobile' -import { MobileDrawerClose } from '@/app/icons/MobileDrawerClose' -import { Footer } from '../Footer' -import { ExpandableButton } from './DesktopNav' -import { ConnectKeplrWallet } from '../Wallet/ConnectKeplrWallet' -import { NetworkTitle } from '../NetworkTitle' -import { originalNavOptions } from '@/app/context/nav' -import { ReleaseAlert } from '@/app/components/ReleaseAlert' -import {SearchToolbar} from "@/app/components/Nav/Search"; - -export const MobileNav: FCWithChildren = ({ children }) => { - const theme = useTheme() - const [drawerOpen, setDrawerOpen] = React.useState(false) - // Set maintenance banner to false by default to don't display it - const [openMaintenance, setOpenMaintenance] = React.useState(false) - const isSmallMobile = useIsMobile(400) - - const toggleDrawer = () => { - setDrawerOpen(!drawerOpen) - } - - const openDrawer = () => { - setDrawerOpen(true) - } - - return ( - <Box sx={{ display: 'flex', flexDirection: 'column' }}> - <AppBar - sx={{ - background: theme.palette.nym.networkExplorer.topNav.appBar, - borderRadius: 0, - }} - > - <MaintenanceBanner - open={openMaintenance} - onClick={() => setOpenMaintenance(false)} - /> - <Toolbar - sx={{ - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - width: '100%', - }} - > - <Box - sx={{ - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - }} - > - <IconButton onClick={toggleDrawer}> - <Menu sx={{ color: 'primary.contrastText' }} /> - </IconButton> - {!isSmallMobile && <NetworkTitle />} - </Box> - <Box sx={{ - alignItems: 'center', - display: 'flex', - }}> - <Box mr={0.5}> - <SearchToolbar/> - </Box> - <ConnectKeplrWallet /> - </Box> - </Toolbar> - </AppBar> - <Drawer - anchor="left" - open={drawerOpen} - onClose={toggleDrawer} - PaperProps={{ - style: { - background: theme.palette.nym.networkExplorer.nav.background, - }, - }} - > - <Box role="presentation"> - <List sx={{ pt: 0, pb: 0 }}> - <ListItem - disablePadding - disableGutters - sx={{ - height: 64, - background: theme.palette.nym.networkExplorer.nav.background, - borderBottom: '1px solid rgba(255, 255, 255, 0.1)', - }} - > - <ListItemButton - onClick={toggleDrawer} - sx={{ - pt: 2, - pb: 2, - background: theme.palette.nym.networkExplorer.nav.background, - display: 'flex', - justifyContent: 'flex-start', - }} - > - <ListItemIcon> - <MobileDrawerClose /> - </ListItemIcon> - </ListItemButton> - </ListItem> - {originalNavOptions.map((props) => ( - <ExpandableButton - key={props.url} - title={props.title} - openDrawer={openDrawer} - url={props.url} - drawIsTempOpen={false} - drawIsFixed={false} - Icon={props.Icon} - nested={props.nested} - closeDrawer={toggleDrawer} - isMobile - /> - ))} - </List> - </Box> - </Drawer> - - <Box sx={{ width: '100%', p: 4, mt: 7 }}> - <ReleaseAlert /> - {children} - <Footer /> - </Box> - </Box> - ) -} diff --git a/explorer-nextjs/app/components/Nav/Navbar.tsx b/explorer-nextjs/app/components/Nav/Navbar.tsx deleted file mode 100644 index 15bcd475664..00000000000 --- a/explorer-nextjs/app/components/Nav/Navbar.tsx +++ /dev/null @@ -1,18 +0,0 @@ -'use client' - -import React from 'react' -import { useIsMobile } from '@/app/hooks' -import { MobileNav } from './MobileNav' -import { Nav } from './DesktopNav' - -const Navbar = ({ children }: { children: React.ReactNode }) => { - const isMobile = useIsMobile() - - if (isMobile) { - return <MobileNav>{children}</MobileNav> - } - - return <Nav>{children}</Nav> -} - -export { Navbar } diff --git a/explorer-nextjs/app/components/Nav/Search.tsx b/explorer-nextjs/app/components/Nav/Search.tsx deleted file mode 100644 index 888125b84a0..00000000000 --- a/explorer-nextjs/app/components/Nav/Search.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import React from "react"; -import { styled, alpha } from '@mui/material/styles'; -import AppBar from '@mui/material/AppBar'; -import Box from '@mui/material/Box'; -import Toolbar from '@mui/material/Toolbar'; -import IconButton from '@mui/material/IconButton'; -import Typography from '@mui/material/Typography'; -import InputBase from '@mui/material/InputBase'; -import MenuIcon from '@mui/icons-material/Menu'; -import SearchIcon from '@mui/icons-material/Search'; -import {useRouter} from "next/navigation"; - -const Search = styled('div')(({ theme }) => ({ - position: 'relative', - borderRadius: theme.shape.borderRadius, - backgroundColor: alpha(theme.palette.common.white, 0.15), - '&:hover': { - backgroundColor: alpha(theme.palette.common.white, 0.25), - }, - marginLeft: 0, - width: '100%', - [theme.breakpoints.up('sm')]: { - marginLeft: theme.spacing(1), - width: 'auto', - }, -})); - -const SearchIconWrapper = styled('div')(({ theme }) => ({ - padding: theme.spacing(0, 2), - height: '100%', - position: 'absolute', - pointerEvents: 'none', - display: 'flex', - alignItems: 'center', - justifyContent: 'center', -})); - -const StyledInputBase = styled(InputBase)(({ theme }) => ({ - color: 'inherit', - width: '100%', - '& .MuiInputBase-input': { - padding: theme.spacing(1, 1, 1, 0), - // vertical padding + font size from searchIcon - paddingLeft: `calc(1em + ${theme.spacing(4)})`, - [theme.breakpoints.up('sm')]: { - width: '30ch', - }, - }, -})); - -export const SearchToolbar = () => { - const [search, setSearch] = React.useState<string>(); - const router = useRouter(); - const handleSubmit = async (e: React.SyntheticEvent<HTMLFormElement>) => { - e.preventDefault(); - if(search?.trim().length) { - router.push(`/account/${search.trim()}`); - } - } - return ( - <Search> - <SearchIconWrapper> - <SearchIcon /> - </SearchIconWrapper> - <form onSubmit={handleSubmit}> - <StyledInputBase - placeholder="Search for account id…" - inputProps={{ 'aria-label': 'search' }} - onChange={(event: React.ChangeEvent<HTMLInputElement>) => { - setSearch(event.target.value); - }} - /> - </form> - </Search> - ); -} \ No newline at end of file diff --git a/explorer-nextjs/app/components/NetworkTitle.tsx b/explorer-nextjs/app/components/NetworkTitle.tsx deleted file mode 100644 index 0c450007da0..00000000000 --- a/explorer-nextjs/app/components/NetworkTitle.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React from 'react' -import { Button, Typography, Link as MuiLink } from '@mui/material' -import { useMainContext } from '@/app/context/main' - -type NetworkTitleProps = { - showToggleNetwork?: boolean -} - -const NetworkTitle = ({ showToggleNetwork }: NetworkTitleProps) => { - const { environment } = useMainContext() - - const explorerName = - `${ - environment && environment.charAt(0).toUpperCase() + environment.slice(1) - } Explorer` || 'Mainnet Explorer' - - const switchNetworkText = - environment === 'mainnet' ? 'Switch to Testnet' : 'Switch to Mainnet' - const switchNetworkLink = - environment === 'mainnet' - ? 'https://sandbox-explorer.nymtech.net' - : 'https://explorer.nymtech.net' - return ( - <Typography - variant="h6" - noWrap - sx={{ - color: 'nym.networkExplorer.nav.text', - fontSize: '18px', - fontWeight: 600, - }} - > - <MuiLink href="/" underline="none" color="inherit" fontWeight={700}> - {explorerName} - </MuiLink> - - {showToggleNetwork && ( - <Button - variant="outlined" - color="inherit" - href={switchNetworkLink} - sx={{ - textTransform: 'none', - width: 114, - fontSize: '12px', - fontWeight: 600, - ml: 1, - }} - > - {switchNetworkText} - </Button> - )} - </Typography> - ) -} - -export { NetworkTitle } diff --git a/explorer-nextjs/app/components/ReleaseAlert.tsx b/explorer-nextjs/app/components/ReleaseAlert.tsx deleted file mode 100644 index 5d974420f9d..00000000000 --- a/explorer-nextjs/app/components/ReleaseAlert.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Alert, Box, Typography } from '@mui/material'; - -export const ReleaseAlert = () => ( - <Alert severity="warning" sx={{ mb: 3, fontSize: 'medium', width: '100%' }}> - <Box> - <Typography>You are now viewing the legacy Nym mixnet explorer. Explorer 2.0 is coming soon.</Typography> - </Box> - </Alert> -); diff --git a/explorer-nextjs/app/components/Socials.tsx b/explorer-nextjs/app/components/Socials.tsx deleted file mode 100644 index 4a4856c8f27..00000000000 --- a/explorer-nextjs/app/components/Socials.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import * as React from 'react' -import { Box, IconButton } from '@mui/material' -import { useTheme } from '@mui/material/styles' -import { TelegramIcon } from '../icons/socials/TelegramIcon' -import { GitHubIcon } from '../icons/socials/GitHubIcon' -import { TwitterIcon } from '../icons/socials/TwitterIcon' -import { DiscordIcon } from '../icons/socials/DiscordIcon' - -// socials -export const TELEGRAM_LINK = 'https://nymtech.net/go/telegram'; -export const TWITTER_LINK = 'https://nymtech.net/go/x'; -export const GITHUB_LINK = 'https://nymtech.net/go/github'; -export const DISCORD_LINK = 'https://nymtech.net/go/discord'; - -export const Socials: FCWithChildren<{ isFooter?: boolean }> = ({ - isFooter = false, -}) => { - const theme = useTheme() - const color = isFooter - ? theme.palette.nym.networkExplorer.footer.socialIcons - : theme.palette.nym.networkExplorer.topNav.socialIcons - return ( - <Box> - <IconButton - component="a" - href={TELEGRAM_LINK} - target="_blank" - data-testid="telegram" - > - <TelegramIcon color={color} size={24} /> - </IconButton> - <IconButton - component="a" - href={DISCORD_LINK} - target="_blank" - data-testid="discord" - > - <DiscordIcon color={color} size={24} /> - </IconButton> - <IconButton - component="a" - href={TWITTER_LINK} - target="_blank" - data-testid="twitter" - > - <TwitterIcon color={color} size={24} /> - </IconButton> - <IconButton - component="a" - href={GITHUB_LINK} - target="_blank" - data-testid="github" - > - <GitHubIcon color={color} size={24} /> - </IconButton> - </Box> - ) -} diff --git a/explorer-nextjs/app/components/StatsCard.tsx b/explorer-nextjs/app/components/StatsCard.tsx deleted file mode 100644 index 2c879989867..00000000000 --- a/explorer-nextjs/app/components/StatsCard.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import * as React from 'react' -import { Box, Card, CardContent, IconButton, Typography } from '@mui/material' -import { useTheme } from '@mui/material/styles' -import EastIcon from '@mui/icons-material/East' - -interface StatsCardProps { - icon: React.ReactNode - title: string - count?: string | number - errorMsg?: Error | string - onClick?: () => void - color?: string -} -export const StatsCard: FCWithChildren<StatsCardProps> = ({ - icon, - title, - count, - onClick, - errorMsg, - color: colorProp, -}) => { - const theme = useTheme() - const color = colorProp || theme.palette.text.primary - return ( - <Card onClick={onClick} sx={{ height: '100%' }}> - <CardContent - sx={{ - padding: 1.5, - paddingLeft: 3, - '&:last-child': { - paddingBottom: 1.5, - }, - cursor: 'pointer', - fontSize: 14, - fontWeight: 600, - }} - > - <Box display="flex" alignItems="center" color={color}> - <Box display="flex"> - {icon} - <Typography - ml={3} - mr={0.75} - fontSize="inherit" - fontWeight="inherit" - data-testid={`${title}-amount`} - > - {count === undefined || count === null ? '' : count} - </Typography> - <Typography - mr={1} - fontSize="inherit" - fontWeight="inherit" - data-testid={title} - > - {title} - </Typography> - </Box> - <IconButton color="inherit" sx={{ fontSize: '16px' }}> - <EastIcon fontSize="inherit" /> - </IconButton> - </Box> - {errorMsg && ( - <Typography variant="body2" sx={{ color: 'danger', padding: 2 }}> - {typeof errorMsg === 'string' - ? errorMsg - : errorMsg.message || 'Oh no! An error occurred'} - </Typography> - )} - </CardContent> - </Card> - ) -} diff --git a/explorer-nextjs/app/components/StyledLink.tsx b/explorer-nextjs/app/components/StyledLink.tsx deleted file mode 100644 index 36dd7981807..00000000000 --- a/explorer-nextjs/app/components/StyledLink.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react' -import { Link as MuiLink, SxProps, Typography } from '@mui/material' -import Link from 'next/link' - -type StyledLinkProps = { - to: string - children: React.ReactNode - target?: React.HTMLAttributeAnchorTarget - dataTestId?: string - color?: string - sx?: SxProps -} - -const StyledLink = ({ - to, - children, - dataTestId, - target, - color, - sx, -}: StyledLinkProps) => ( - <Link - href={to} - target={target} - data-testid={dataTestId} - style={{ textDecoration: 'none' }} - > - <Typography component="a" sx={{ ...sx }} color={color}> - {children} - </Typography> - </Link> -) - -export default StyledLink diff --git a/explorer-nextjs/app/components/Switch.tsx b/explorer-nextjs/app/components/Switch.tsx deleted file mode 100644 index 840530a3277..00000000000 --- a/explorer-nextjs/app/components/Switch.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import * as React from 'react'; -import { styled } from '@mui/material/styles'; -import Switch from '@mui/material/Switch'; -import { Button } from '@mui/material'; -import { useMainContext } from '../context/main'; -import { LightSwitchSVG } from '../icons/LightSwitchSVG'; - -export const DarkLightSwitch = styled(Switch)(({ theme }) => ({ - width: 55, - height: 34, - padding: 7, - '& .MuiSwitch-switchBase': { - margin: 1, - padding: 2, - transform: 'translateX(4px)', - '&.Mui-checked': { - color: '#fff', - transform: 'translateX(22px)', - '& .MuiSwitch-thumb:before': { - backgroundImage: - 'url(\'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 20 20"><path fill="black" d="M4.2 2.5l-.7 1.8-1.8.7 1.8.7.7 1.8.6-1.8L6.7 5l-1.9-.7-.6-1.8zm15 8.3a6.7 6.7 0 11-6.6-6.6 5.8 5.8 0 006.6 6.6z"/></svg>\')', - }, - '& + .MuiSwitch-track': { - opacity: 1, - backgroundColor: theme.palette.mode === 'dark' ? '#8796A5' : '#aab4be', - }, - }, - }, - '& .MuiSwitch-thumb': { - backgroundColor: theme.palette.nym.networkExplorer.nav.text, - width: 25, - height: 25, - marginTop: '2px', - '&:before': { - content: "''", - position: 'absolute', - width: '100%', - height: '100%', - left: 0, - top: 0, - backgroundRepeat: 'no-repeat', - backgroundPosition: 'center', - backgroundImage: - 'url(\'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 20 20"><path fill="black" d="M9.305 1.667V3.75h1.389V1.667h-1.39zm-4.707 1.95l-.982.982L5.09 6.072l.982-.982-1.473-1.473zm10.802 0L13.927 5.09l.982.982 1.473-1.473-.982-.982zM10 5.139a4.872 4.872 0 00-4.862 4.86A4.872 4.872 0 0010 14.862 4.872 4.872 0 0014.86 10 4.872 4.872 0 0010 5.139zm0 1.389A3.462 3.462 0 0113.471 10a3.462 3.462 0 01-3.473 3.472A3.462 3.462 0 016.527 10 3.462 3.462 0 0110 6.528zM1.665 9.305v1.39h2.083v-1.39H1.666zm14.583 0v1.39h2.084v-1.39h-2.084zM5.09 13.928L3.616 15.4l.982.982 1.473-1.473-.982-.982zm9.82 0l-.982.982 1.473 1.473.982-.982-1.473-1.473zM9.305 16.25v2.083h1.389V16.25h-1.39z"/></svg>\')', - }, - }, - '& .MuiSwitch-track': { - opacity: 1, - backgroundColor: theme.palette.mode === 'dark' ? '#8796A5' : '#aab4be', - borderRadius: 20 / 2, - }, -})); - -export const DarkLightSwitchMobile: FCWithChildren = () => { - const { toggleMode } = useMainContext(); - return ( - <Button onClick={() => toggleMode()} data-testid="switch-button" sx={{ p: 0, minWidth: 0 }}> - <LightSwitchSVG /> - </Button> - ); -}; - -export const DarkLightSwitchDesktop: FCWithChildren<{ defaultChecked: boolean }> = ({ defaultChecked }) => { - const { toggleMode } = useMainContext(); - return ( - <Button sx={{ paddingLeft: 0 }} onClick={() => toggleMode()} data-testid="switch-button"> - <DarkLightSwitch defaultChecked={defaultChecked} /> - </Button> - ); -}; diff --git a/explorer-nextjs/app/components/TableToolbar.tsx b/explorer-nextjs/app/components/TableToolbar.tsx deleted file mode 100644 index f22b84aca90..00000000000 --- a/explorer-nextjs/app/components/TableToolbar.tsx +++ /dev/null @@ -1,61 +0,0 @@ -'use client' - -import React from 'react' -import { Box, SelectChangeEvent } from '@mui/material' -import { useIsMobile } from '@/app/hooks/useIsMobile' -import { Filters } from './Filters/Filters' - -const fieldsHeight = '42.25px' - -type TableToolBarProps = { - childrenBefore?: React.ReactNode - childrenAfter?: React.ReactNode -} - -export const TableToolbar: FCWithChildren<TableToolBarProps> = ({ - childrenBefore, - childrenAfter, -}) => { - const isMobile = useIsMobile() - return ( - <Box - sx={{ - width: '100%', - marginBottom: 2, - display: 'flex', - flexDirection: isMobile ? 'column' : 'row', - justifyContent: 'space-between', - }} - > - <Box - sx={{ - display: 'flex', - flexDirection: isMobile ? 'column-reverse' : 'row', - alignItems: 'middle', - }} - > - <Box - sx={{ - display: 'flex', - justifyContent: 'space-between', - height: fieldsHeight, - }} - > - {childrenBefore} - </Box> - </Box> - - <Box - sx={{ - display: 'flex', - alignItems: 'center', - justifyContent: 'end', - gap: 1, - marginTop: isMobile ? 2 : 0, - }} - > - {childrenAfter} - </Box> - </Box> - ) -} diff --git a/explorer-nextjs/app/components/Title.tsx b/explorer-nextjs/app/components/Title.tsx deleted file mode 100644 index 032837d3c85..00000000000 --- a/explorer-nextjs/app/components/Title.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from 'react'; -import { Typography } from '@mui/material'; - -export const Title: FCWithChildren<{ text: string }> = ({ text }) => ( - <Typography - variant="h5" - sx={{ - fontWeight: 600, - }} - data-testid={text} - > - {text} - </Typography> -); diff --git a/explorer-nextjs/app/components/Tooltip.tsx b/explorer-nextjs/app/components/Tooltip.tsx deleted file mode 100644 index 0febd9f8914..00000000000 --- a/explorer-nextjs/app/components/Tooltip.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React, { ReactElement } from 'react'; -import { Tooltip as MUITooltip, TooltipComponentsPropsOverrides, TooltipProps } from '@mui/material'; - -type ValueType<T> = T[keyof T]; - -type Props = { - text: string; - id: string; - placement?: ValueType<Pick<TooltipProps, 'placement'>>; - tooltipSx?: TooltipComponentsPropsOverrides; - children: React.ReactNode; -}; - -export const Tooltip = ({ text, id, placement, tooltipSx, children }: Props) => ( - <MUITooltip - title={text} - id={id} - placement={placement || 'top-start'} - componentsProps={{ - tooltip: { - sx: { - maxWidth: 200, - background: (t) => t.palette.nym.networkExplorer.tooltip.background, - color: (t) => t.palette.nym.networkExplorer.tooltip.color, - '& .MuiTooltip-arrow': { - color: (t) => t.palette.nym.networkExplorer.tooltip.background, - }, - }, - ...tooltipSx, - }, - }} - arrow - > - {children as ReactElement<any, any>} - </MUITooltip> -); diff --git a/explorer-nextjs/app/components/TwoColSmallTable.tsx b/explorer-nextjs/app/components/TwoColSmallTable.tsx deleted file mode 100644 index a211c29bdd7..00000000000 --- a/explorer-nextjs/app/components/TwoColSmallTable.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import * as React from 'react'; -import { CircularProgress, Typography } from '@mui/material'; -import Table from '@mui/material/Table'; -import TableBody from '@mui/material/TableBody'; -import TableCell from '@mui/material/TableCell'; -import TableContainer from '@mui/material/TableContainer'; -import TableRow from '@mui/material/TableRow'; -import Paper from '@mui/material/Paper'; -import CheckCircleSharpIcon from '@mui/icons-material/CheckCircleSharp'; -import ErrorIcon from '@mui/icons-material/Error'; - -interface TableProps { - title?: string; - icons?: boolean[]; - keys: string[]; - values: number[]; - marginBottom?: boolean; - error?: string; - loading: boolean; -} - -export const TwoColSmallTable: FCWithChildren<TableProps> = ({ - loading, - title, - icons, - keys, - values, - marginBottom, - error, -}) => ( - <> - {title && <Typography sx={{ marginTop: 2 }}>{title}</Typography>} - - <TableContainer component={Paper} sx={marginBottom ? { marginBottom: 4, marginTop: 2 } : { marginTop: 2 }}> - <Table aria-label="two col small table"> - <TableBody> - {keys.map((each: string, i: number) => ( - <TableRow key={each}> - {icons && <TableCell>{icons[i] ? <CheckCircleSharpIcon /> : <ErrorIcon />}</TableCell>} - <TableCell sx={error ? { opacity: 0.4 } : null} data-testid={each.replace(/ /g, '')}> - {each} - </TableCell> - <TableCell - sx={error ? { opacity: 0.4 } : null} - align="right" - data-testid={`${each.replace(/ /g, '-')}-value`} - > - {values[i]} - </TableCell> - {error && ( - <TableCell align="right" sx={{ opacity: 0.4 }}> - {values[i]} - </TableCell> - )} - {!error && loading && ( - <TableCell align="right"> - <CircularProgress /> - </TableCell> - )} - {error && !icons && ( - <TableCell sx={{ opacity: 0.2 }} align="right"> - <ErrorIcon /> - </TableCell> - )} - </TableRow> - ))} - </TableBody> - </Table> - </TableContainer> - </> -); - -TwoColSmallTable.defaultProps = { - title: undefined, - icons: undefined, - marginBottom: false, - error: undefined, -}; diff --git a/explorer-nextjs/app/components/Universal-DataGrid.tsx b/explorer-nextjs/app/components/Universal-DataGrid.tsx deleted file mode 100644 index 36e98be9ce9..00000000000 --- a/explorer-nextjs/app/components/Universal-DataGrid.tsx +++ /dev/null @@ -1,96 +0,0 @@ -'use client' - -import * as React from 'react' -import { makeStyles } from '@mui/styles' -import { - DataGrid, - GridColDef, - GridEventListener, - useGridApiContext, -} from '@mui/x-data-grid' -import Pagination from '@mui/material/Pagination' -import { LinearProgress } from '@mui/material' -import { GridInitialStateCommunity } from '@mui/x-data-grid/models/gridStateCommunity' - -const useStyles = makeStyles({ - root: { - display: 'flex', - }, -}) - -const CustomPagination = () => { - const apiRef = useGridApiContext() - const classes = useStyles() - console.log(apiRef.current.state) - - return ( - <Pagination - className={classes.root} - sx={{ mt: 2 }} - color="primary" - count={apiRef.current.state.pagination.paginationModel.pageSize} - page={apiRef.current.state.pagination.paginationModel.page + 1} - onChange={(_, value) => apiRef.current.setPage(value - 1)} - /> - ) -} - -type DataGridProps = { - columns: GridColDef[] - pagination?: true | undefined - pageSize?: string | undefined - rows: any - loading?: boolean - initialState?: GridInitialStateCommunity - onRowClick?: GridEventListener<'rowClick'> | undefined -} -export const UniversalDataGrid: FCWithChildren<DataGridProps> = ({ - rows, - columns, - loading, - pagination, - pageSize, - initialState, - onRowClick, -}) => { - if (loading) return <LinearProgress /> - - return ( - <DataGrid - onRowClick={onRowClick} - pagination={pagination} - rows={rows} - slots={{ - pagination: CustomPagination, - }} - columns={columns} - autoHeight - hideFooter={!pagination} - initialState={initialState} - style={{ - width: '100%', - border: 'none', - }} - sx={{ - '*::-webkit-scrollbar': { - width: '1em', - }, - '*::-webkit-scrollbar-track': { - background: (t) => t.palette.nym.networkExplorer.scroll.backgroud, - outline: (t) => - `1px solid ${t.palette.nym.networkExplorer.scroll.border}`, - boxShadow: 'auto', - borderRadius: 'auto', - }, - '*::-webkit-scrollbar-thumb': { - backgroundColor: (t) => t.palette.nym.networkExplorer.scroll.color, - borderRadius: '20px', - width: '.4em', - border: (t) => - `3px solid ${t.palette.nym.networkExplorer.scroll.backgroud}`, - shadow: 'auto', - }, - }} - /> - ) -} diff --git a/explorer-nextjs/app/components/UptimeChart.tsx b/explorer-nextjs/app/components/UptimeChart.tsx deleted file mode 100644 index 00a981a3afc..00000000000 --- a/explorer-nextjs/app/components/UptimeChart.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import * as React from 'react'; -import { CircularProgress, Typography } from '@mui/material'; -import { useTheme } from '@mui/material/styles'; -import { Chart } from 'react-google-charts'; -import { format } from 'date-fns'; -import { ApiState, UptimeStoryResponse } from '../typeDefs/explorer-api'; - -interface ChartProps { - title?: string; - xLabel: string; - yLabel?: string; - uptimeStory: ApiState<UptimeStoryResponse>; - loading: boolean; -} - -type FormattedDateRecord = [string, number]; -type FormattedChartHeadings = string[]; -type FormattedChartData = [FormattedChartHeadings | FormattedDateRecord]; - -export const UptimeChart: FCWithChildren<ChartProps> = ({ title, xLabel, yLabel, uptimeStory, loading }) => { - const [formattedChartData, setFormattedChartData] = React.useState<FormattedChartData>(); - const theme = useTheme(); - const color = theme.palette.text.primary; - React.useEffect(() => { - if (uptimeStory.data?.history) { - const allFormattedChartData: FormattedChartData = [['Date', 'Score']]; - uptimeStory.data.history.forEach((eachDate) => { - const formattedDateUptimeRecord: FormattedDateRecord = [ - format(new Date(eachDate.date), 'MMM dd'), - eachDate.uptime, - ]; - allFormattedChartData.push(formattedDateUptimeRecord); - }); - setFormattedChartData(allFormattedChartData); - } else { - const emptyData: any = [ - ['Date', 'Score'], - ['Jul 27', 10], - ]; - setFormattedChartData(emptyData); - } - }, [uptimeStory]); - - return ( - <> - {title && <Typography>{title}</Typography>} - {loading && <CircularProgress />} - - {!loading && uptimeStory && ( - <Chart - style={{ minHeight: 480 }} - chartType="LineChart" - loader={<p>...</p>} - data={ - uptimeStory.data - ? formattedChartData - : [ - ['Date', 'Routing Score'], - [format(new Date(Date.now()), 'MMM dd'), 0], - ] - } - options={{ - backgroundColor: - theme.palette.mode === 'dark' ? theme.palette.nym.networkExplorer.background.tertiary : undefined, - color: uptimeStory.error ? 'rgba(255, 255, 255, 0.4)' : 'rgba(255, 255, 255, 1)', - colors: ['#FB7A21'], - legend: { - textStyle: { - color, - opacity: uptimeStory.error ? 0.4 : 1, - }, - }, - - intervals: { style: 'sticks' }, - hAxis: { - // horizontal / date - title: xLabel, - titleTextStyle: { - color, - }, - textStyle: { - color, - // fontSize: 11 - }, - gridlines: { - count: -1, - }, - }, - vAxis: { - // vertical / % Routing Score - viewWindow: { - min: 0, - max: 100, - }, - title: yLabel, - titleTextStyle: { - color, - opacity: uptimeStory.error ? 0.4 : 1, - }, - textStyle: { - color, - fontSize: 11, - opacity: uptimeStory.error ? 0.4 : 1, - }, - }, - }} - /> - )} - </> - ); -}; - -UptimeChart.defaultProps = { - title: undefined, -}; diff --git a/explorer-nextjs/app/components/Wallet/ConnectKeplrWallet.tsx b/explorer-nextjs/app/components/Wallet/ConnectKeplrWallet.tsx deleted file mode 100644 index 23114f90560..00000000000 --- a/explorer-nextjs/app/components/Wallet/ConnectKeplrWallet.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import React from 'react' -import { Button, IconButton, Stack, CircularProgress } from '@mui/material' -import CloseIcon from '@mui/icons-material/Close' -import { useIsMobile } from '@/app/hooks/useIsMobile' -import { useWalletContext } from '@/app/context/wallet' -import { WalletAddress, WalletBalance } from '@/app/components/Wallet' - -export const ConnectKeplrWallet = () => { - const { - connectWallet, - disconnectWallet, - isWalletConnected, - isWalletConnecting, - } = useWalletContext() - const isMobile = useIsMobile(1200) - - if (!connectWallet || !disconnectWallet) { - return null - } - - if (isWalletConnected) { - return ( - <Stack direction="row" spacing={1}> - <WalletBalance /> - <WalletAddress /> - <IconButton - size="small" - onClick={async () => { - await disconnectWallet() - }} - > - <CloseIcon fontSize="small" sx={{ color: 'white' }} /> - </IconButton> - </Stack> - ) - } - - return ( - <Button - variant="outlined" - onClick={() => connectWallet()} - disabled={isWalletConnecting} - endIcon={ - isWalletConnecting && <CircularProgress size={14} color="inherit" /> - } - > - Connect {isMobile ? '' : ' Wallet'} - </Button> - ) -} diff --git a/explorer-nextjs/app/components/Wallet/WalletAddress.tsx b/explorer-nextjs/app/components/Wallet/WalletAddress.tsx deleted file mode 100644 index 3e251eb2bb3..00000000000 --- a/explorer-nextjs/app/components/Wallet/WalletAddress.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react' -import { Box, Typography } from '@mui/material' -import { ElipsSVG } from '@/app/icons/ElipsSVG' -import { trimAddress } from '@/app/utils' -import { useWalletContext } from '@/app/context/wallet' - -export const WalletAddress = () => { - const { address } = useWalletContext() - - const displayAddress = trimAddress(address, 7) - - return ( - <Box display="flex" alignItems="center" gap={0.5}> - <ElipsSVG /> - <Typography variant="body1" fontWeight={600}> - {displayAddress} - </Typography> - </Box> - ) -} diff --git a/explorer-nextjs/app/components/Wallet/WalletBalance.tsx b/explorer-nextjs/app/components/Wallet/WalletBalance.tsx deleted file mode 100644 index 7d1c5979bcc..00000000000 --- a/explorer-nextjs/app/components/Wallet/WalletBalance.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react' -import { Box, Typography } from '@mui/material' -import { useWalletContext } from '@/app/context/wallet' -import { useIsMobile } from '@/app/hooks' -import { TokenSVG } from '@/app/icons/TokenSVG' - -export const WalletBalance = () => { - const { balance } = useWalletContext() - const isMobile = useIsMobile(1200) - - const showBalance = !isMobile && balance.status === 'success' - - if (!showBalance) { - return null - } - - return ( - <Box display="flex" alignItems="center" gap={1}> - <TokenSVG /> - <Typography variant="body1" fontWeight={600}> - {balance.data} NYM - </Typography> - </Box> - ) -} diff --git a/explorer-nextjs/app/components/Wallet/index.ts b/explorer-nextjs/app/components/Wallet/index.ts deleted file mode 100644 index 645c8b4ffb1..00000000000 --- a/explorer-nextjs/app/components/Wallet/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './WalletBalance'; -export * from './WalletAddress'; diff --git a/explorer-nextjs/app/components/WorldMap.tsx b/explorer-nextjs/app/components/WorldMap.tsx deleted file mode 100644 index 9b5c3295711..00000000000 --- a/explorer-nextjs/app/components/WorldMap.tsx +++ /dev/null @@ -1,129 +0,0 @@ -'use client' - -import * as React from 'react' -import { scaleLinear } from 'd3-scale' -import { - ComposableMap, - Geographies, - Geography, - Marker, - ZoomableGroup, -} from 'react-simple-maps' -import ReactTooltip from 'react-tooltip' -import { CircularProgress } from '@mui/material' -import { useTheme } from '@mui/material/styles' -import { ApiState, CountryDataResponse } from '../typeDefs/explorer-api' -import MAP_TOPOJSON from '../assets/world-110m.json' - -type MapProps = { - userLocation?: [number, number] - countryData?: ApiState<CountryDataResponse> - loading: boolean -} - -export const WorldMap: FCWithChildren<MapProps> = ({ - countryData, - userLocation, - loading, -}) => { - const { palette } = useTheme() - - const colorScale = React.useMemo(() => { - if (countryData?.data) { - const heighestNumberOfNodes = Math.max( - ...Object.values(countryData.data).map((country) => country.nodes) - ) - return scaleLinear<string, string>() - .domain([ - 0, - 1, - heighestNumberOfNodes / 4, - heighestNumberOfNodes / 2, - heighestNumberOfNodes, - ]) - .range(palette.nym.networkExplorer.map.fills) - .unknown(palette.nym.networkExplorer.map.fills[0]) - } - return () => palette.nym.networkExplorer.map.fills[0] - }, [countryData, palette]) - - const [tooltipContent, setTooltipContent] = React.useState<string | null>( - null - ) - - if (loading) { - return <CircularProgress /> - } - - return ( - <> - <ComposableMap - data-tip="" - style={{ - backgroundColor: palette.nym.networkExplorer.background.tertiary, - width: '100%', - height: 'auto', - }} - viewBox="0, 50, 800, 350" - projection="geoMercator" - projectionConfig={{ - scale: userLocation ? 200 : 100, - center: userLocation, - }} - > - <ZoomableGroup> - <Geographies geography={MAP_TOPOJSON}> - {({ geographies }) => - geographies.map((geo) => { - const d = (countryData?.data || {})[geo.properties.ISO_A3] - return ( - <Geography - key={geo.rsmKey} - geography={geo} - fill={colorScale(d?.nodes || 0)} - stroke={palette.nym.networkExplorer.map.stroke} - strokeWidth={0.2} - onMouseEnter={() => { - const { NAME_LONG } = geo.properties - if (!userLocation) { - setTooltipContent(`${NAME_LONG} | ${d?.nodes || 0}`) - } - }} - onMouseLeave={() => { - setTooltipContent('') - }} - style={{ - hover: - !userLocation && countryData - ? { - fill: palette.nym.highlight, - outline: 'white', - } - : undefined, - }} - /> - ) - }) - } - </Geographies> - - {userLocation && ( - <Marker coordinates={userLocation}> - <g - fill="grey" - stroke="#FF5533" - strokeWidth="2" - strokeLinecap="round" - strokeLinejoin="round" - transform="translate(-12, -10)" - > - <circle cx="12" cy="10" r="5" /> - </g> - </Marker> - )} - </ZoomableGroup> - </ComposableMap> - <ReactTooltip>{tooltipContent}</ReactTooltip> - </> - ) -} diff --git a/explorer-nextjs/app/components/index.ts b/explorer-nextjs/app/components/index.ts deleted file mode 100644 index 92eeebd0102..00000000000 --- a/explorer-nextjs/app/components/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export * from './CustomColumnHeading'; -export * from './Title'; -export * from './Universal-DataGrid'; -export * from './Tooltip'; -export { default as StyledLink } from './StyledLink'; -export * from './Delegations'; -export * from './MixNodes'; -export * from './TableToolbar'; -export * from './Icons'; diff --git a/explorer-nextjs/app/context/cosmos-kit.tsx b/explorer-nextjs/app/context/cosmos-kit.tsx deleted file mode 100644 index 987d30aa656..00000000000 --- a/explorer-nextjs/app/context/cosmos-kit.tsx +++ /dev/null @@ -1,73 +0,0 @@ -'use client' - -import React from 'react' -import { ChainProvider } from '@cosmos-kit/react' -import { wallets as keplr } from '@cosmos-kit/keplr-extension' -import { assets, chains } from 'chain-registry' -import { Chain, AssetList } from '@chain-registry/types' -import { VALIDATOR_BASE_URL } from '@/app/api/constants' - -const nymSandbox: Chain = { - chain_name: 'sandbox', - chain_id: 'sandbox', - bech32_prefix: 'n', - network_type: 'devnet', - pretty_name: 'Nym Sandbox', - status: 'active', - slip44: 118, - apis: { - rpc: [ - { - address: 'https://rpc.sandbox.nymtech.net', - }, - ], - }, -} - -const nymSandboxAssets = { - chain_name: 'sandbox', - assets: [ - { - name: 'Nym', - base: 'unym', - symbol: 'NYM', - display: 'NYM', - denom_units: [], - }, - ], -} - -const CosmosKitProvider = ({ children }: { children: React.ReactNode }) => { - // Only use the nyx chains - const chainsFixedUp = React.useMemo(() => { - const nyx = chains.find((chain) => chain.chain_id === 'nyx') - - return nyx ? [nymSandbox, nyx] : [nymSandbox] - }, [chains]) - - // Only use the nyx assets - const assetsFixedUp = React.useMemo(() => { - const nyx = assets.find((asset) => asset.chain_name === 'nyx') - - return nyx ? [nymSandboxAssets, nyx] : [nymSandboxAssets] - }, [assets]) as AssetList[] - - return ( - <ChainProvider - chains={chainsFixedUp} - assetLists={assetsFixedUp} - wallets={[...keplr]} - endpointOptions={{ - endpoints: { - nyx: { - rpc: [VALIDATOR_BASE_URL], - }, - }, - }} - > - {children} - </ChainProvider> - ) -} - -export default CosmosKitProvider diff --git a/explorer-nextjs/app/context/delegations.tsx b/explorer-nextjs/app/context/delegations.tsx deleted file mode 100644 index 75a099970c9..00000000000 --- a/explorer-nextjs/app/context/delegations.tsx +++ /dev/null @@ -1,252 +0,0 @@ -'use client' - -import React, { - createContext, - useCallback, - useContext, - useMemo, - useState, -} from 'react' -import { - Delegation, - PendingEpochEvent, - PendingEpochEventKind, -} from '@nymproject/contract-clients/Mixnet.types' -import { ExecuteResult } from '@cosmjs/cosmwasm-stargate' -import { useWalletContext } from './wallet' -import { useMainContext } from './main' - -const fee = { gas: '1000000', amount: [{ amount: '1000000', denom: 'unym' }] } - -export type PendingEvent = ReturnType<typeof getEventsByAddress> - -export type DelegationWithRewards = Delegation & { - rewards: string - identityKey: string - pending: PendingEvent -} - -const getEventsByAddress = (kind: PendingEpochEventKind, address: String) => { - if ('delegate' in kind && kind.delegate.owner === address) { - return { - kind: 'delegate' as const, - mixId: kind.delegate.mix_id, - amount: kind.delegate.amount, - } - } - - if ('undelegate' in kind && kind.undelegate.owner === address) { - return { - kind: 'undelegate' as const, - mixId: kind.undelegate.mix_id, - } - } - - return undefined -} - -interface DelegationsState { - delegations?: DelegationWithRewards[] - handleGetDelegations: () => Promise<void> - handleDelegate: ( - mixId: number, - amount: string - ) => Promise<ExecuteResult | undefined> - handleUndelegate: (mixId: number) => Promise<ExecuteResult | undefined> -} - -export const DelegationsContext = createContext<DelegationsState>({ - delegations: undefined, - handleGetDelegations: async () => { - throw new Error('Please connect your wallet') - }, - handleDelegate: async () => { - throw new Error('Please connect your wallet') - }, - handleUndelegate: async () => { - throw new Error('Please connect your wallet') - }, -}) - -export const DelegationsProvider = ({ - children, -}: { - children: React.ReactNode -}) => { - const [delegations, setDelegations] = useState<DelegationWithRewards[]>() - const { address, nymQueryClient, nymClient } = useWalletContext() - const { fetchMixnodes } = useMainContext() - - const handleGetPendingEvents = async () => { - if (!nymQueryClient) { - return undefined - } - - if (!address) { - return undefined - } - - const response = await nymQueryClient.getPendingEpochEvents({}) - const pendingEvents: PendingEvent[] = [] - - response.events.forEach((e: PendingEpochEvent) => { - const event = getEventsByAddress(e.event.kind, address) - if (event) { - pendingEvents.push(event) - } - }) - - return pendingEvents - } - - const handleGetDelegationRewards = async (mixId: number) => { - if (!nymQueryClient) { - return undefined - } - - if (!address) { - return undefined - } - - const response = await nymQueryClient.getPendingDelegatorReward({ - address, - mixId, - }) - - return response - } - - const handleGetDelegations = useCallback(async () => { - if (!nymQueryClient) { - setDelegations(undefined) - return undefined - } - - if (!address) { - setDelegations(undefined) - return undefined - } - - // Get all mixnodes - Required to get the identity key for each delegation - const mixnodes = await fetchMixnodes() - - // Get delegations - const delegationsResponse = await nymQueryClient.getDelegatorDelegations({ - delegator: address, - }) - - // Get rewards for each delegation - const rewardsResponse = await Promise.all( - delegationsResponse.delegations.map((d: Delegation) => - handleGetDelegationRewards(d.mix_id) - ) - ) - - // Get all pending events - const pendingEvents = await handleGetPendingEvents() - - const delegationsWithRewards: DelegationWithRewards[] = [] - - // Merge delegations with rewards and pending events - delegationsResponse.delegations.forEach((d: Delegation, index: number) => { - delegationsWithRewards.push({ - ...d, - pending: pendingEvents?.find((e: PendingEvent) => - e?.mixId === d.mix_id ? e.kind : undefined - ), - identityKey: - mixnodes?.find((m) => m.mix_id === d.mix_id)?.mix_node.identity_key || - '', - rewards: rewardsResponse[index]?.amount_earned_detailed || '0', - }) - }) - - // Add pending events that are not in the delegations list - pendingEvents?.forEach((e) => { - if ( - e && - !delegationsWithRewards.find( - (d: DelegationWithRewards) => d.mix_id === e.mixId - ) - ) { - delegationsWithRewards.push({ - mix_id: e.mixId, - height: 0, - cumulative_reward_ratio: '0', - owner: address, - amount: { - amount: '0', - denom: 'unym', - }, - rewards: '0', - identityKey: - mixnodes?.find((m) => m.mix_id === e.mixId)?.mix_node - .identity_key || '', - pending: e, - }) - } - }) - - setDelegations(delegationsWithRewards) - - return undefined - }, [address, nymQueryClient]) - - const handleDelegate = async (mixId: number, amount: string) => { - if (!address) { - throw new Error('Please connect your wallet') - } - - const amountToDelegate = (Number(amount) * 1000000).toString() - const uNymFunds = [{ amount: amountToDelegate, denom: 'unym' }] - try { - const tx = await nymClient?.delegateToMixnode( - { mixId }, - fee, - 'Delegation from Nym Explorer', - uNymFunds - ) - - return tx as unknown as ExecuteResult - } catch (e) { - console.error('Failed to delegate to mixnode', e) - throw e - } - } - - const handleUndelegate = async (mixId: number) => { - const tx = await nymClient?.undelegateFromMixnode( - { mixId }, - fee, - 'Undelegation from Nym Explorer' - ) - - return tx as unknown as ExecuteResult - } - - const contextValue: DelegationsState = useMemo( - () => ({ - delegations, - handleGetDelegations, - handleDelegate, - handleUndelegate, - }), - [delegations, handleGetDelegations] - ) - - return ( - <DelegationsContext.Provider value={contextValue}> - {children} - </DelegationsContext.Provider> - ) -} - -export const useDelegationsContext = () => { - const context = useContext(DelegationsContext) - if (!context) { - throw new Error( - 'useDelegationsContext must be used within a DelegationsProvider' - ) - } - return context -} diff --git a/explorer-nextjs/app/context/gateway.tsx b/explorer-nextjs/app/context/gateway.tsx deleted file mode 100644 index 458a9da907e..00000000000 --- a/explorer-nextjs/app/context/gateway.tsx +++ /dev/null @@ -1,69 +0,0 @@ -'use client' - -import * as React from 'react' -import { - ApiState, - GatewayReportResponse, - UptimeStoryResponse, -} from '@/app/typeDefs/explorer-api' -import { Api } from '@/app/api' -import { useApiState } from './hooks' - -/** - * This context provides the state for a single gateway by identity key. - */ - -interface GatewayState { - uptimeReport?: ApiState<GatewayReportResponse> - uptimeStory?: ApiState<UptimeStoryResponse> -} - -export const GatewayContext = React.createContext<GatewayState>({}) - -export const useGatewayContext = (): React.ContextType<typeof GatewayContext> => - React.useContext<GatewayState>(GatewayContext) - -/** - * Provides a state context for a gateway by identity - * @param gatewayIdentityKey The identity key of the gateway - */ -export const GatewayContextProvider = ({ - gatewayIdentityKey, - children, -}: { - gatewayIdentityKey: string - children: JSX.Element -}) => { - const [uptimeReport, fetchUptimeReportById, clearUptimeReportById] = - useApiState<GatewayReportResponse>( - gatewayIdentityKey, - Api.fetchGatewayReportById, - 'Failed to fetch gateway uptime report by id' - ) - - const [uptimeStory, fetchUptimeHistory, clearUptimeHistory] = - useApiState<UptimeStoryResponse>( - gatewayIdentityKey, - Api.fetchGatewayUptimeStoryById, - 'Failed to fetch gateway uptime history' - ) - - React.useEffect(() => { - // when the identity key changes, remove all previous data - clearUptimeReportById() - clearUptimeHistory() - Promise.all([fetchUptimeReportById(), fetchUptimeHistory()]) - }, [gatewayIdentityKey]) - - const state = React.useMemo<GatewayState>( - () => ({ - uptimeReport, - uptimeStory, - }), - [uptimeReport, uptimeStory] - ) - - return ( - <GatewayContext.Provider value={state}>{children}</GatewayContext.Provider> - ) -} diff --git a/explorer-nextjs/app/context/hooks.ts b/explorer-nextjs/app/context/hooks.ts deleted file mode 100644 index 55004f89eed..00000000000 --- a/explorer-nextjs/app/context/hooks.ts +++ /dev/null @@ -1,49 +0,0 @@ -'use client' - -import * as React from 'react'; -import { ApiState } from '@/app/typeDefs/explorer-api'; - -/** - * Custom hook to get data from the API by passing an id to a delegate method that fetches the data asynchronously - * @param id The id to fetch - * @param fn Delegate the fetching to this method (must take `(id: string)` as a parameter) - * @param errorMessage A static error message, to use when no dynamic error message is returned - */ -export const useApiState = <T>( - id: string, - fn: (argId: string) => Promise<T>, - errorMessage: string, -): [ApiState<T> | undefined, () => Promise<ApiState<T>>, () => void] => { - // stores the state - const [value, setValue] = React.useState<ApiState<T>>(); - - // clear the value - const clearValueFn = () => setValue(undefined); - - // this provides a method to trigger the delegate to fetch data - const wrappedFetchFn = React.useCallback(async () => { - setValue({ isLoading: true }); - try { - // keep previous state and set to loading - setValue((prevState) => ({ ...prevState, isLoading: true })); - - // delegate to user function to get data and set if successful - const data = await fn(id); - const newValue: ApiState<T> = { - isLoading: false, - data, - }; - setValue(newValue); - return newValue; - } catch (error) { - // return the caught error or create a new error with the static error message - const newValue: ApiState<T> = { - error: error instanceof Error ? error : new Error(errorMessage), - isLoading: false, - }; - setValue(newValue); - return newValue; - } - }, [setValue, fn, id, errorMessage]); - return [value, wrappedFetchFn, clearValueFn]; -}; diff --git a/explorer-nextjs/app/context/main.tsx b/explorer-nextjs/app/context/main.tsx deleted file mode 100644 index 0494b87749c..00000000000 --- a/explorer-nextjs/app/context/main.tsx +++ /dev/null @@ -1,297 +0,0 @@ -'use client' - -import * as React from 'react' -import { PaletteMode } from '@mui/material' -import { - ApiState, - BlockResponse, - CountryDataResponse, - GatewayResponse, - MixNodeResponse, - MixnodeStatus, - SummaryOverviewResponse, - ValidatorsResponse, - Environment, - DirectoryServiceProvider, -} from '@/app/typeDefs/explorer-api' -import { EnumFilterKey } from '@/app/typeDefs/filters' -import { Api, getEnvironment } from '@/app/api' -import { toPercentIntegerString } from '@/app/utils' -import { NavOptionType, originalNavOptions } from './nav' - -interface StateData { - summaryOverview?: ApiState<SummaryOverviewResponse> - block?: ApiState<BlockResponse> - countryData?: ApiState<CountryDataResponse> - gateways?: ApiState<GatewayResponse> - globalError?: string | undefined - mixnodes?: ApiState<MixNodeResponse> - nodes?: ApiState<any> - mode: PaletteMode - validators?: ApiState<ValidatorsResponse> - environment?: Environment - serviceProviders?: ApiState<DirectoryServiceProvider[]> -} - -interface StateApi { - fetchMixnodes: ( - status?: MixnodeStatus - ) => Promise<MixNodeResponse | undefined> - filterMixnodes: (filters: any, status: any) => void - fetchNodes: () => Promise<any> - fetchNodeById: (id: number) => Promise<any> - fetchAccountById: (accountAddr: string) => Promise<any> - toggleMode: () => void -} - -type State = StateData & StateApi - -export const MainContext = React.createContext<State>({ - mode: 'dark', - toggleMode: () => undefined, - filterMixnodes: () => null, - fetchMixnodes: () => Promise.resolve(undefined), - fetchNodes: async () => undefined, - fetchNodeById: async () => undefined, - fetchAccountById: async () => undefined, -}) - -export const useMainContext = (): React.ContextType<typeof MainContext> => - React.useContext<State>(MainContext) - -export const MainContextProvider: FCWithChildren = ({ children }) => { - // network explorer environment - const [environment, setEnvironment] = React.useState<Environment>() - - // light/dark mode - const [mode, setMode] = React.useState<PaletteMode>('dark') - - // global / banner error messaging - const [globalError] = React.useState<string>() - - // various APIs for Overview page - const [summaryOverview, setSummaryOverview] = - React.useState<ApiState<SummaryOverviewResponse>>() - const [nodes, setNodes] = React.useState<ApiState<any>>() - const [mixnodes, setMixnodes] = React.useState<ApiState<MixNodeResponse>>() - const [gateways, setGateways] = React.useState<ApiState<GatewayResponse>>() - const [validators, setValidators] = - React.useState<ApiState<ValidatorsResponse>>() - const [block, setBlock] = React.useState<ApiState<BlockResponse>>() - const [countryData, setCountryData] = - React.useState<ApiState<CountryDataResponse>>() - const [serviceProviders, setServiceProviders] = - React.useState<ApiState<DirectoryServiceProvider[]>>() - - const toggleMode = () => setMode((m) => (m !== 'light' ? 'light' : 'dark')) - - const fetchOverviewSummary = async () => { - try { - const data = await Api.fetchOverviewSummary() - setSummaryOverview({ data, isLoading: false }) - } catch (error) { - setSummaryOverview({ - error: - error instanceof Error - ? error - : new Error('Overview summary api fail'), - isLoading: false, - }) - } - } - - const fetchMixnodes = async () => { - let data - setMixnodes((d) => ({ ...d, isLoading: true })) - try { - data = await Api.fetchMixnodes() - setMixnodes({ data, isLoading: false }) - } catch (error) { - setMixnodes({ - error: error instanceof Error ? error : new Error('Mixnode api fail'), - isLoading: false, - }) - } - return data - } - - const filterMixnodes = async ( - filters: { [key in EnumFilterKey]: number[] }, - status?: MixnodeStatus - ) => { - setMixnodes((d) => ({ ...d, isLoading: true })) - const mxns = await Api.fetchMixnodes() - - const filtered = mxns?.filter( - (m) => - +m.profit_margin_percent >= filters.profitMargin[0] / 100 && - +m.profit_margin_percent <= filters.profitMargin[1] / 100 && - m.stake_saturation >= filters.stakeSaturation[0] && - m.stake_saturation <= filters.stakeSaturation[1] && - m.avg_uptime >= filters.routingScore[0] && - m.avg_uptime <= filters.routingScore[1] - ) - - setMixnodes({ data: filtered, isLoading: false }) - } - - const fetchGateways = async () => { - setGateways((d) => ({ ...d, isLoading: true })) - try { - const data = await Api.fetchGateways() - setGateways({ data, isLoading: false }) - } catch (error) { - setGateways({ - error: error instanceof Error ? error : new Error('Gateways api fail'), - isLoading: false, - }) - } - } - const fetchValidators = async () => { - try { - const data = await Api.fetchValidators() - setValidators({ data, isLoading: false }) - } catch (error) { - setValidators({ - error: - error instanceof Error ? error : new Error('Validators api fail'), - isLoading: false, - }) - } - } - const fetchBlock = async () => { - try { - const data = await Api.fetchBlock() - setBlock({ data, isLoading: false }) - } catch (error) { - setBlock({ - error: error instanceof Error ? error : new Error('Block api fail'), - isLoading: false, - }) - } - } - const fetchCountryData = async () => { - setCountryData({ data: undefined, isLoading: true }) - try { - const res = await Api.fetchCountryData() - setCountryData({ data: res, isLoading: false }) - } catch (error) { - setCountryData({ - error: - error instanceof Error ? error : new Error('Country Data api fail'), - isLoading: false, - }) - } - } - - const fetchServiceProviders = async () => { - setServiceProviders({ data: undefined, isLoading: true }) - try { - const res = await Api.fetchServiceProviders() - const resWithRoutingScorePercentage = res.map((item) => ({ - ...item, - routing_score: item.routing_score - ? `${toPercentIntegerString(item.routing_score.toString())}%` - : item.routing_score, - })) - setServiceProviders({ - data: resWithRoutingScorePercentage, - isLoading: false, - }) - } catch (error) { - setServiceProviders({ - error: - error instanceof Error - ? error - : new Error('Service provider api fail'), - isLoading: false, - }) - } - } - - const fetchNodes = async () => { - setNodes({ data: undefined, isLoading: true }) - try { - const res = await Api.fetchNodes(); - res.forEach((node: any) => node.total_stake = - Math.round(Number.parseFloat(node.rewarding_details?.operator || "0") - + Number.parseFloat(node.rewarding_details?.delegates || "0")) - ); - setNodes({ - data: res.sort((a: any, b: any) => b.total_stake - a.total_stake), - isLoading: false, - }) - } catch (error) { - setNodes({ - error: - error instanceof Error - ? error - : new Error('Service provider api fail'), - isLoading: false, - }) - } }; - - const fetchNodeById = async (id: number) => { - const res = await Api.fetchNodeById(id); - return res; - }; - - const fetchAccountById = async (id: string) => { - const res = await Api.fetchAccountById(id); - return res; - }; - - React.useEffect(() => { - if (environment === 'mainnet') { - fetchServiceProviders() - } - }, [environment]) - - React.useEffect(() => { - setEnvironment(getEnvironment()) - Promise.all([ - fetchOverviewSummary(), - fetchGateways(), - fetchValidators(), - fetchBlock(), - fetchCountryData(), - ]) - }, []) - - const state = React.useMemo<State>( - () => ({ - environment, - block, - countryData, - gateways, - globalError, - mixnodes, - mode, - nodes, - summaryOverview, - validators, - serviceProviders, - toggleMode, - fetchMixnodes, - filterMixnodes, - fetchNodes, - fetchNodeById, - fetchAccountById, - }), - [ - environment, - block, - countryData, - gateways, - globalError, - mixnodes, - mode, - nodes, - summaryOverview, - validators, - serviceProviders, - ] - ) - - return <MainContext.Provider value={state}>{children}</MainContext.Provider> -} diff --git a/explorer-nextjs/app/context/mixnode.tsx b/explorer-nextjs/app/context/mixnode.tsx deleted file mode 100644 index 71b48fd045b..00000000000 --- a/explorer-nextjs/app/context/mixnode.tsx +++ /dev/null @@ -1,173 +0,0 @@ -'use client' - -import * as React from 'react' -import { - ApiState, - DelegationsResponse, - UniqDelegationsResponse, - MixNodeDescriptionResponse, - MixNodeEconomicDynamicsStatsResponse, - MixNodeResponseItem, - StatsResponse, - StatusResponse, - UptimeStoryResponse, -} from '../typeDefs/explorer-api' -import { Api } from '../api' -import { useApiState } from './hooks' -import { - mixNodeResponseItemToMixnodeRowType, - MixnodeRowType, -} from '../components/MixNodes' - -/** - * This context provides the state for a single mixnode by identity key. - */ - -interface MixnodeState { - delegations?: ApiState<DelegationsResponse> - uniqDelegations?: ApiState<UniqDelegationsResponse> - description?: ApiState<MixNodeDescriptionResponse> - economicDynamicsStats?: ApiState<MixNodeEconomicDynamicsStatsResponse> - mixNode?: ApiState<MixNodeResponseItem | undefined> - mixNodeRow?: MixnodeRowType - stats?: ApiState<StatsResponse> - status?: ApiState<StatusResponse> - uptimeStory?: ApiState<UptimeStoryResponse> -} - -export const MixnodeContext = React.createContext<MixnodeState>({}) - -export const useMixnodeContext = (): React.ContextType<typeof MixnodeContext> => - React.useContext<MixnodeState>(MixnodeContext) - -interface MixnodeContextProviderProps { - mixId: string - children: React.ReactNode -} - -/** - * Provides a state context for a mixnode by identity - * @param mixId The mixID of the mixnode - */ -export const MixnodeContextProvider: FCWithChildren< - MixnodeContextProviderProps -> = ({ mixId, children }) => { - const [mixNode, fetchMixnodeById, clearMixnodeById] = useApiState< - MixNodeResponseItem | undefined - >(mixId, Api.fetchMixnodeByID, 'Failed to fetch mixnode by id') - - const [mixNodeRow, setMixnodeRow] = React.useState< - MixnodeRowType | undefined - >() - - const [delegations, fetchDelegations, clearDelegations] = - useApiState<DelegationsResponse>( - mixId, - Api.fetchDelegationsById, - 'Failed to fetch delegations for mixnode' - ) - - const [uniqDelegations, fetchUniqDelegations, clearUniqDelegations] = - useApiState<UniqDelegationsResponse>( - mixId, - Api.fetchUniqDelegationsById, - 'Failed to fetch delegations for mixnode' - ) - - const [status, fetchStatus, clearStatus] = useApiState<StatusResponse>( - mixId, - Api.fetchStatusById, - 'Failed to fetch mixnode status' - ) - - const [stats, fetchStats, clearStats] = useApiState<StatsResponse>( - mixId, - Api.fetchStatsById, - 'Failed to fetch mixnode stats' - ) - - const [description, fetchDescription, clearDescription] = - useApiState<MixNodeDescriptionResponse>( - mixId, - Api.fetchMixnodeDescriptionById, - 'Failed to fetch mixnode description' - ) - - const [ - economicDynamicsStats, - fetchEconomicDynamicsStats, - clearEconomicDynamicsStats, - ] = useApiState<MixNodeEconomicDynamicsStatsResponse>( - mixId, - Api.fetchMixnodeEconomicDynamicsStatsById, - 'Failed to fetch mixnode dynamics stats by id' - ) - - const [uptimeStory, fetchUptimeHistory, clearUptimeHistory] = - useApiState<UptimeStoryResponse>( - mixId, - Api.fetchUptimeStoryById, - 'Failed to fetch mixnode uptime history' - ) - - React.useEffect(() => { - // when the identity key changes, remove all previous data - clearMixnodeById() - clearDelegations() - clearUniqDelegations() - clearStatus() - clearStats() - clearDescription() - clearEconomicDynamicsStats() - clearUptimeHistory() - - // fetch the mixnode, then get all the other stuff - fetchMixnodeById().then((value) => { - if (!value.data || value.error) { - setMixnodeRow(undefined) - return - } - setMixnodeRow(mixNodeResponseItemToMixnodeRowType(value.data)) - Promise.all([ - fetchDelegations(), - fetchUniqDelegations(), - fetchStatus(), - fetchStats(), - fetchDescription(), - fetchEconomicDynamicsStats(), - fetchUptimeHistory(), - ]) - }) - }, [mixId]) - - const state = React.useMemo<MixnodeState>( - () => ({ - delegations, - uniqDelegations, - mixNode, - mixNodeRow, - description, - economicDynamicsStats, - stats, - status, - uptimeStory, - }), - [ - { - delegations, - uniqDelegations, - mixNode, - mixNodeRow, - description, - economicDynamicsStats, - stats, - status, - uptimeStory, - }, - ] - ) - - return ( - <MixnodeContext.Provider value={state}>{children}</MixnodeContext.Provider> - ) -} diff --git a/explorer-nextjs/app/context/nav.tsx b/explorer-nextjs/app/context/nav.tsx deleted file mode 100644 index e41882edbba..00000000000 --- a/explorer-nextjs/app/context/nav.tsx +++ /dev/null @@ -1,59 +0,0 @@ -'use client' - -import * as React from 'react' -import { DelegateIcon } from '@/app/icons/DelevateSVG' -import { BLOCK_EXPLORER_BASE_URL } from '@/app/api/constants' -import { OverviewSVG } from '@/app/icons/OverviewSVG' -import { NodemapSVG } from '@/app/icons/NodemapSVG' -import { NetworkComponentsSVG } from '@/app/icons/NetworksSVG' - -export type NavOptionType = { - url: string - title: string - Icon?: React.ReactNode - nested?: NavOptionType[] - isExpandedChild?: boolean - isExternal?: boolean -} - -export const originalNavOptions: NavOptionType[] = [ - { - url: '/', - title: 'Overview', - Icon: <OverviewSVG />, - }, - { - url: '/network-components', - title: 'Network Components', - Icon: <NetworkComponentsSVG />, - nested: [ - { - url: '/network-components/nodes', - title: 'Nodes', - }, - { - url: '/network-components/mixnodes', - title: 'Mixnodes (legacy)', - }, - { - url: '/network-components/gateways', - title: 'Gateways (legacy)', - }, - { - url: `${BLOCK_EXPLORER_BASE_URL}/validators`, - title: 'Validators', - isExternal: true, - }, - ], - }, - { - url: '/nodemap', - title: 'Nodemap', - Icon: <NodemapSVG />, - }, - { - url: '/delegations', - title: 'Delegations', - Icon: <DelegateIcon sx={{ color: 'white' }} />, - }, -] diff --git a/explorer-nextjs/app/context/node.tsx b/explorer-nextjs/app/context/node.tsx deleted file mode 100644 index 2aa885439c2..00000000000 --- a/explorer-nextjs/app/context/node.tsx +++ /dev/null @@ -1,77 +0,0 @@ -'use client' - -import * as React from 'react' -import { - ApiState, - NymNodeReportResponse, - UptimeStoryResponse, -} from '@/app/typeDefs/explorer-api' -import { Api } from '@/app/api' -import { useApiState } from './hooks' - -/** - * This context provides the state for a single gateway by identity key. - */ - -interface NymNodeState { - uptimeReport?: ApiState<NymNodeReportResponse> - uptimeHistory?: ApiState<UptimeStoryResponse> -} - -export const NymNodeContext = React.createContext<NymNodeState>({}) - -export const useNymNodeContext = (): React.ContextType<typeof NymNodeContext> => - React.useContext<NymNodeState>(NymNodeContext) - -/** - * Provides a state context for a gateway by identity - * @param gatewayIdentityKey The identity key of the gateway - */ -export const NymNodeContextProvider = ({ - nymNodeId, - children, -}: { - nymNodeId: string - children: JSX.Element -}) => { - const [uptimeReport, fetchUptimeReportById, clearUptimeReportById] = - useApiState<any>( - nymNodeId, - Api.fetchNymNodePerformanceById, - 'Failed to fetch gateway uptime report by id' - ) - - const [uptimeHistory, fetchUptimeHistory, clearUptimeHistory] = - useApiState<UptimeStoryResponse>( - nymNodeId, - async (arg) => { - const res = await Api.fetchNymNodeUptimeHistoryById(arg); - const uptimeHistory: UptimeStoryResponse = { - history: res.history.data, - identity: '', - owner: '', - } - return uptimeHistory; - }, - 'Failed to fetch gateway uptime history' - ) - - React.useEffect(() => { - // when the identity key changes, remove all previous data - clearUptimeReportById() - clearUptimeHistory() - Promise.all([fetchUptimeReportById(), fetchUptimeHistory()]) - }, [nymNodeId]) - - const state = React.useMemo<NymNodeState>( - () => ({ - uptimeReport, - uptimeHistory, - }), - [uptimeReport, uptimeHistory] - ) - - return ( - <NymNodeContext.Provider value={state}>{children}</NymNodeContext.Provider> - ) -} diff --git a/explorer-nextjs/app/context/wallet.tsx b/explorer-nextjs/app/context/wallet.tsx deleted file mode 100644 index c9acb6b8509..00000000000 --- a/explorer-nextjs/app/context/wallet.tsx +++ /dev/null @@ -1,123 +0,0 @@ -'use client' - -import React, { - createContext, - useContext, - useEffect, - useMemo, - useState, -} from 'react' -import { useChain } from '@cosmos-kit/react' -import { Wallet } from '@cosmos-kit/core' -import { unymToNym } from '@/app/utils/currency' -import { useNymClient } from '@/app/hooks' -import { - MixnetClient, - MixnetQueryClient, -} from '@nymproject/contract-clients/Mixnet.client' -import { COSMOS_KIT_USE_CHAIN } from '@/app/api/constants' - -interface WalletState { - balance: { status: 'loading' | 'success'; data?: string } - address?: string - isWalletConnected: boolean - isWalletConnecting: boolean - wallet?: Wallet - nymClient?: MixnetClient - nymQueryClient?: MixnetQueryClient - connectWallet: () => Promise<void> - disconnectWallet: () => Promise<void> -} - -export const WalletContext = createContext<WalletState>({ - address: undefined, - balance: { status: 'loading', data: undefined }, - isWalletConnected: false, - isWalletConnecting: false, - nymClient: undefined, - nymQueryClient: undefined, - connectWallet: async () => { - throw new Error('Please connect your wallet') - }, - disconnectWallet: async () => { - throw new Error('Please connect your wallet') - }, -}) - -export const WalletProvider = ({ children }: { children: React.ReactNode }) => { - const [balance, setBalance] = useState<WalletState['balance']>({ - status: 'loading', - data: undefined, - }) - - const { - connect, - disconnect, - wallet, - address, - isWalletConnected, - isWalletConnecting, - getCosmWasmClient, - } = useChain(COSMOS_KIT_USE_CHAIN) - - const { nymClient, nymQueryClient } = useNymClient(address) - - const getBalance = async (walletAddress: string) => { - const account = await getCosmWasmClient() - const uNYMBalance = await account.getBalance(walletAddress, 'unym') - const NYMBalance = unymToNym(uNYMBalance.amount) - - return NYMBalance - } - - const init = async (walletAddress: string) => { - const walletBalance = await getBalance(walletAddress) - setBalance({ status: 'success', data: walletBalance }) - } - - useEffect(() => { - if (isWalletConnected && address) { - init(address) - } - }, [address, isWalletConnected]) - - const handleConnectWallet = async () => { - await connect() - } - - const handleDisconnectWallet = async () => { - await disconnect() - setBalance({ status: 'loading', data: undefined }) - } - - const contextValue: WalletState = useMemo( - () => ({ - address, - balance, - wallet, - isWalletConnected, - isWalletConnecting, - nymClient, - nymQueryClient, - connectWallet: handleConnectWallet, - disconnectWallet: handleDisconnectWallet, - }), - [ - address, - balance, - wallet, - isWalletConnected, - isWalletConnecting, - nymClient, - nymQueryClient, - ] - ) - - return ( - <WalletContext.Provider value={contextValue}> - {children} - </WalletContext.Provider> - ) -} - -export const useWalletContext = () => useContext(WalletContext) diff --git a/explorer-nextjs/app/delegations/page.tsx b/explorer-nextjs/app/delegations/page.tsx deleted file mode 100644 index 60b27b3c912..00000000000 --- a/explorer-nextjs/app/delegations/page.tsx +++ /dev/null @@ -1,311 +0,0 @@ -'use client' - -import React, { useCallback, useEffect, useMemo } from 'react' -import { - Alert, - AlertTitle, - Box, - Button, - Card, - Chip, - IconButton, - Tooltip, - Typography, -} from '@mui/material' -import { DelegationModal, DelegationModalProps, Title } from '@/app/components' -import { useWalletContext } from '@/app/context/wallet' -import { unymToNym } from '@/app/utils/currency' -import { - DelegationWithRewards, - DelegationsProvider, - PendingEvent, - useDelegationsContext, -} from '@/app/context/delegations' -import { urls } from '@/app/utils' -import { useClipboard } from 'use-clipboard-copy' -import { Close } from '@mui/icons-material' -import { useRouter } from 'next/navigation' -import { - MRT_ColumnDef, - MaterialReactTable, - useMaterialReactTable, -} from 'material-react-table' - -const mapToDelegationsRow = ( - delegation: DelegationWithRewards, - index: number -) => ({ - identity: delegation.identityKey, - mix_id: delegation.mix_id, - amount: `${unymToNym(delegation.amount.amount)} NYM`, - rewards: `${unymToNym(delegation.rewards)} NYM`, - id: index, - pending: delegation.pending, -}) - -const Banner = ({ onClose }: { onClose: () => void }) => { - const { copy } = useClipboard() - - return ( - <Alert - severity="info" - sx={{ mb: 3, fontSize: 'medium', width: '100%' }} - action={ - <IconButton size="small" onClick={onClose}> - <Close fontSize="small" /> - </IconButton> - } - > - <AlertTitle> Mobile Delegations Beta</AlertTitle> - <Box> - <Typography> - This is a beta release for mobile delegations If you have any feedback - or feature suggestions contact us at support@nymte.ch - <Button - size="small" - onClick={() => copy('support@nymte.ch')} - sx={{ display: 'inline-block' }} - > - Copy - </Button> - </Typography> - </Box> - </Alert> - ) -} - -const DelegationsPage = () => { - const [confirmationModalProps, setConfirmationModalProps] = React.useState< - DelegationModalProps | undefined - >() - const [isLoading, setIsLoading] = React.useState(false) - const [showBanner, setShowBanner] = React.useState(true) - - const { isWalletConnected } = useWalletContext() - const { handleGetDelegations, handleUndelegate, delegations } = - useDelegationsContext() - - const router = useRouter() - - useEffect(() => { - let timeoutId: NodeJS.Timeout - - const fetchDelegations = async () => { - setIsLoading(true) - try { - await handleGetDelegations() - } catch (error) { - setConfirmationModalProps({ - status: 'error', - message: "Couldn't fetch delegations. Please try again later.", - }) - } finally { - setIsLoading(false) - - timeoutId = setTimeout(() => { - fetchDelegations() - }, 60_000) - } - } - - fetchDelegations() - - return () => { - clearTimeout(timeoutId) - } - }, [handleGetDelegations]) - - const getTooltipTitle = (pending: PendingEvent) => { - if (pending?.kind === 'undelegate') { - return 'You have an undelegation pending' - } - - if (pending?.kind === 'delegate') { - return `You have a delegation pending worth ${unymToNym( - pending.amount.amount - )} NYM` - } - - return undefined - } - - const onUndelegate = useCallback( - async (mixId: number) => { - setConfirmationModalProps({ status: 'loading' }) - - try { - const tx = await handleUndelegate(mixId) - - if (tx) { - setConfirmationModalProps({ - status: 'success', - message: 'Undelegation can take up to one hour to process', - transactions: [ - { - url: `${urls('MAINNET').blockExplorer}/transaction/${ - tx.transactionHash - }`, - hash: tx.transactionHash, - }, - ], - }) - } - } catch (error) { - if (error instanceof Error) { - setConfirmationModalProps({ status: 'error', message: error.message }) - } - } - }, - [handleUndelegate] - ) - - const columns = useMemo< - MRT_ColumnDef<ReturnType<typeof mapToDelegationsRow>>[] - >(() => { - return [ - { - id: 'delegations-data', - header: 'Delegations Data', - columns: [ - { - id: 'identity', - accessorKey: 'identity', - header: 'Identity Key', - width: 400, - }, - { - id: 'mix_id', - accessorKey: 'mix_id', - header: 'Mix ID', - size: 150, - }, - { - id: 'amount', - accessorKey: 'amount', - header: 'Amount', - width: 150, - }, - { - id: 'rewards', - accessorKey: 'rewards', - header: 'Rewards', - width: 150, - enableColumnFilters: false, - }, - { - id: 'undelegate', - accessorKey: 'undelegate', - header: '', - enableSorting: false, - enableColumnActions: false, - Filter: () => null, - Cell: ({ row }) => { - return ( - <Box - sx={{ width: '100%', display: 'flex', justifyContent: 'end' }} - > - {row.original.pending ? ( - <Tooltip - placement="left" - title={getTooltipTitle(row.original.pending)} - onClick={(e) => e.stopPropagation()} - PopperProps={{}} - > - <Chip size="small" label="Pending events" /> - </Tooltip> - ) : ( - <Button - size="small" - variant="outlined" - onClick={(e) => { - e.stopPropagation() - onUndelegate(row.original.mix_id) - }} - > - Undelegate - </Button> - )} - </Box> - ) - }, - }, - ], - }, - ] - }, [onUndelegate]) - - const data = useMemo(() => { - return (delegations || []).map(mapToDelegationsRow) - }, [delegations]) - - const table = useMaterialReactTable({ - columns, - data, - enableFullScreenToggle: false, - state: { - isLoading, - }, - initialState: { - columnPinning: { right: ['undelegate'] }, - }, - }) - - return ( - <Box> - {confirmationModalProps && ( - <DelegationModal - {...confirmationModalProps} - open={Boolean(confirmationModalProps)} - onClose={async () => { - if (confirmationModalProps.status === 'success') { - await handleGetDelegations() - } - setConfirmationModalProps(undefined) - }} - sx={{ - width: { - xs: '90%', - sm: 600, - }, - }} - /> - )} - {showBanner && <Banner onClose={() => setShowBanner(false)} />} - <Box display="flex" justifyContent="space-between" alignItems="center"> - <Title text="Your Delegations" /> - <Button - variant="contained" - color="primary" - onClick={() => router.push('/network-components/mixnodes')} - > - Delegate - </Button> - </Box> - {!isWalletConnected ? ( - <Box> - <Typography mb={2} variant="h6"> - Connect your wallet to view your delegations. - </Typography> - </Box> - ) : null} - - <Card - sx={{ - mt: 2, - padding: 2, - height: '100%', - }} - > - <MaterialReactTable table={table} /> - </Card> - </Box> - ) -} - -const Delegations = () => ( - <DelegationsProvider> - <DelegationsPage /> - </DelegationsProvider> -) - -export default Delegations diff --git a/explorer-nextjs/app/errors/ErrorBoundaryContent.tsx b/explorer-nextjs/app/errors/ErrorBoundaryContent.tsx deleted file mode 100644 index 4dbf9eb16e5..00000000000 --- a/explorer-nextjs/app/errors/ErrorBoundaryContent.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import * as React from 'react' -import { FallbackProps } from 'react-error-boundary' -import { Alert, AlertTitle, Container } from '@mui/material' -import { NymThemeProvider } from '@nymproject/mui-theme' -import { NymLogo } from '@nymproject/react/logo/NymLogo' - -export const ErrorBoundaryContent: FCWithChildren<FallbackProps> = ({ - error, -}) => ( - <NymThemeProvider mode="dark"> - <Container sx={{ py: 4 }}> - <NymLogo height="75px" width="75px" /> - <h1>Oh no! Sorry, something went wrong</h1> - <Alert severity="error" data-testid="error-message"> - <AlertTitle>{error.name}</AlertTitle> - {error.message} - </Alert> - {process.env.NODE_ENV === 'development' && ( - <Alert severity="info" sx={{ mt: 2 }} data-testid="stack-trace"> - <AlertTitle>Stack trace</AlertTitle> - {error.stack} - </Alert> - )} - </Container> - </NymThemeProvider> -) diff --git a/explorer-nextjs/app/hooks/index.ts b/explorer-nextjs/app/hooks/index.ts deleted file mode 100644 index ba04855f779..00000000000 --- a/explorer-nextjs/app/hooks/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './useIsMobile'; -export * from './useIsMounted'; -export * from './useGetMixnodeStatusColor'; -export * from './useNymClient'; diff --git a/explorer-nextjs/app/hooks/useGetMixnodeStatusColor.ts b/explorer-nextjs/app/hooks/useGetMixnodeStatusColor.ts deleted file mode 100644 index 3e1762209f1..00000000000 --- a/explorer-nextjs/app/hooks/useGetMixnodeStatusColor.ts +++ /dev/null @@ -1,19 +0,0 @@ -'use client' - -import { useTheme } from '@mui/material'; -import { MixnodeStatus } from '@/app/typeDefs/explorer-api'; - -export const useGetMixNodeStatusColor = (status: MixnodeStatus) => { - const theme = useTheme(); - - switch (status) { - case MixnodeStatus.active: - return theme.palette.nym.networkExplorer.mixnodes.status.active; - - case MixnodeStatus.standby: - return theme.palette.nym.networkExplorer.mixnodes.status.standby; - - default: - return theme.palette.nym.networkExplorer.mixnodes.status.inactive; - } -}; diff --git a/explorer-nextjs/app/hooks/useIsMobile.ts b/explorer-nextjs/app/hooks/useIsMobile.ts deleted file mode 100644 index 0948d36cbed..00000000000 --- a/explorer-nextjs/app/hooks/useIsMobile.ts +++ /dev/null @@ -1,11 +0,0 @@ -'use client' - -import { Breakpoint, useMediaQuery } from '@mui/material'; -import { useTheme } from '@mui/material/styles'; - -export const useIsMobile = (queryInput: number | Breakpoint = 'md') => { - const theme = useTheme(); - const isMobile = useMediaQuery(theme.breakpoints.down(queryInput)); - - return isMobile; -}; diff --git a/explorer-nextjs/app/hooks/useIsMounted.ts b/explorer-nextjs/app/hooks/useIsMounted.ts deleted file mode 100644 index 5a78ae4fec5..00000000000 --- a/explorer-nextjs/app/hooks/useIsMounted.ts +++ /dev/null @@ -1,16 +0,0 @@ -'use client' - -import { useRef, useEffect, useCallback } from 'react'; - -export function useIsMounted(): () => boolean { - const ref = useRef(false); - - useEffect(() => { - ref.current = true; - return () => { - ref.current = false; - }; - }, []); - - return useCallback(() => ref.current, [ref]); -} diff --git a/explorer-nextjs/app/hooks/useNymClient.tsx b/explorer-nextjs/app/hooks/useNymClient.tsx deleted file mode 100644 index 2fa400b1300..00000000000 --- a/explorer-nextjs/app/hooks/useNymClient.tsx +++ /dev/null @@ -1,44 +0,0 @@ -'use client' - -import { useEffect, useState } from 'react' -import { useChain } from '@cosmos-kit/react' -import { contracts } from '@nymproject/contract-clients' -import { - MixnetClient, - MixnetQueryClient, -} from '@nymproject/contract-clients/Mixnet.client' -import { COSMOS_KIT_USE_CHAIN, NYM_MIXNET_CONTRACT } from '@/app/api/constants' - -export const useNymClient = (address?: string) => { - const [nymClient, setNymClient] = useState<MixnetClient>() - const [nymQueryClient, setNymQueryClient] = useState<MixnetQueryClient>() - - const { getCosmWasmClient, getSigningCosmWasmClient } = - useChain(COSMOS_KIT_USE_CHAIN) - - useEffect(() => { - if (address) { - const init = async () => { - const cosmWasmSigningClient = await getSigningCosmWasmClient() - const cosmWasmClient = await getCosmWasmClient() - - const client = new contracts.Mixnet.MixnetClient( - cosmWasmSigningClient as any, - address, - NYM_MIXNET_CONTRACT - ) - const queryClient = new contracts.Mixnet.MixnetQueryClient( - cosmWasmClient as any, - NYM_MIXNET_CONTRACT - ) - - setNymClient(client) - setNymQueryClient(queryClient) - } - - init() - } - }, [address, getCosmWasmClient, getSigningCosmWasmClient]) - - return { nymClient, nymQueryClient } -} diff --git a/explorer-nextjs/app/icons/DelevateSVG.tsx b/explorer-nextjs/app/icons/DelevateSVG.tsx deleted file mode 100644 index 56180d1b8ad..00000000000 --- a/explorer-nextjs/app/icons/DelevateSVG.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import { SvgIcon, SvgIconProps } from '@mui/material'; - -export const DelegateIcon = (props: SvgIconProps) => ( - <SvgIcon {...props}> - <path d="M4 12V15H6V12H4ZM16 7L14.59 5.59L13 7.17V2H11V7.19L9.39 5.61L8 7L12 11L16 7ZM4 17H20V15H4V17Z" /> - <path d="M20 21C20 21.5523 19.5523 22 19 22H5C4.44772 22 4 21.5523 4 21V20H20V21Z" /> - <rect x="18" y="12" width="2" height="3" /> - <rect x="18" y="17" width="2" height="3" /> - <rect x="4" y="17" width="2" height="3" /> - </SvgIcon> -); diff --git a/explorer-nextjs/app/icons/ElipsSVG.tsx b/explorer-nextjs/app/icons/ElipsSVG.tsx deleted file mode 100644 index 4a430d6cb6a..00000000000 --- a/explorer-nextjs/app/icons/ElipsSVG.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import * as React from 'react'; - -export const ElipsSVG: FCWithChildren = () => ( - <svg xmlns="http://www.w3.org/2000/svg" width="24" height="25" viewBox="0 0 24 25" fill="none"> - <circle cx="12" cy="12.5" r="10" fill="url(#paint0_angular_2549_7570)" /> - <defs> - <radialGradient - id="paint0_angular_2549_7570" - cx="0" - cy="0" - r="1" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(12 12.5) rotate(90) scale(12)" - > - <stop stopColor="#22D27E" /> - <stop offset="1" stopColor="#9002FF" /> - </radialGradient> - </defs> - </svg> -); diff --git a/explorer-nextjs/app/icons/GatewaysSVG.tsx b/explorer-nextjs/app/icons/GatewaysSVG.tsx deleted file mode 100644 index 00e4a21198e..00000000000 --- a/explorer-nextjs/app/icons/GatewaysSVG.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -export const GatewaysSVG: FCWithChildren = () => { - const theme = useTheme(); - const color = theme.palette.text.primary; - return ( - <svg width="24" height="24" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M16.2 12H22.7" stroke={color} strokeWidth="1.3" strokeMiterlimit="10" strokeLinecap="round" /> - <path d="M1.30005 12H12" stroke={color} strokeWidth="1.3" strokeMiterlimit="10" strokeLinecap="round" /> - <path - d="M20.1 9.40015L22.7 12.0001L20.1 14.6001" - stroke={color} - strokeWidth="1.3" - strokeMiterlimit="10" - strokeLinecap="round" - strokeLinejoin="round" - /> - <path - d="M13.2 22.7001H8.59998C6.89998 22.7001 5.59998 21.4001 5.59998 19.7001V4.30005C5.59998 2.60005 6.89998 1.30005 8.59998 1.30005H13.2C14.9 1.30005 16.2 2.60005 16.2 4.30005V19.6C16.2 21.3001 14.8 22.7001 13.2 22.7001Z" - stroke={color} - strokeWidth="1.3" - strokeMiterlimit="10" - strokeLinecap="round" - /> - </svg> - ); -}; diff --git a/explorer-nextjs/app/icons/LightSwitchSVG.tsx b/explorer-nextjs/app/icons/LightSwitchSVG.tsx deleted file mode 100644 index 7a32590dfc8..00000000000 --- a/explorer-nextjs/app/icons/LightSwitchSVG.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -export const LightSwitchSVG: FCWithChildren = () => { - const { palette } = useTheme(); - return ( - <svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path - d="M12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C17.5 22 22 17.5 22 12C22 6.5 17.5 2 12 2Z" - fill={palette.background.default} - /> - <path d="M12 20C7.6 20 4 16.4 4 12C4 7.6 7.6 4 12 4V20Z" fill={palette.text.primary} /> - </svg> - ); -}; diff --git a/explorer-nextjs/app/icons/MixnodesSVG.tsx b/explorer-nextjs/app/icons/MixnodesSVG.tsx deleted file mode 100644 index 56902cb0dec..00000000000 --- a/explorer-nextjs/app/icons/MixnodesSVG.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -export const MixnodesSVG: FCWithChildren = () => { - const theme = useTheme(); - const color = theme.palette.text.primary; - - return ( - <svg width="24" height="24" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M23.0437 13.0291H2.97681" stroke={color} strokeMiterlimit="10" /> - <path d="M23.0437 2.99512H2.97681" stroke={color} strokeMiterlimit="10" /> - <path d="M23.0437 23.0625H2.97681" stroke={color} strokeMiterlimit="10" /> - <path d="M2.97681 23.0621L23.0437 2.99512" stroke={color} strokeMiterlimit="10" /> - <path d="M23.0437 23.0621L2.97681 2.99512" stroke={color} strokeMiterlimit="10" /> - <path d="M13.0103 23.0621L23.0437 2.99512" stroke={color} strokeMiterlimit="10" /> - <path d="M2.97681 2.99512L13.0103 23.0621" stroke={color} strokeMiterlimit="10" /> - <path - d="M13.0099 13.0289L23.0437 23.0621L13.0099 2.99512L2.97681 23.0621L13.0099 2.99512" - stroke={color} - strokeMiterlimit="10" - /> - <path - d="M23.097 12.9846L13.0892 2.97681L3.08142 12.9846L13.0892 22.9924L23.097 12.9846Z" - stroke={color} - strokeMiterlimit="10" - /> - <path - d="M23.0232 4.9536C24.1149 4.9536 25 4.06856 25 2.9768C25 1.88504 24.1149 1 23.0232 1C21.9314 1 21.0464 1.88504 21.0464 2.9768C21.0464 4.06856 21.9314 4.9536 23.0232 4.9536Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M12.9731 4.9536C14.0648 4.9536 14.9499 4.06856 14.9499 2.9768C14.9499 1.88504 14.0648 1 12.9731 1C11.8813 1 10.9963 1.88504 10.9963 2.9768C10.9963 4.06856 11.8813 4.9536 12.9731 4.9536Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M2.9768 4.9536C4.06856 4.9536 4.9536 4.06856 4.9536 2.9768C4.9536 1.88504 4.06856 1 2.9768 1C1.88504 1 1 1.88504 1 2.9768C1 4.06856 1.88504 4.9536 2.9768 4.9536Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M23.0232 15.0029C24.1149 15.0029 25 14.1179 25 13.0261C25 11.9344 24.1149 11.0493 23.0232 11.0493C21.9314 11.0493 21.0464 11.9344 21.0464 13.0261C21.0464 14.1179 21.9314 15.0029 23.0232 15.0029Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M12.9731 15.0029C14.0648 15.0029 14.9499 14.1179 14.9499 13.0261C14.9499 11.9344 14.0648 11.0493 12.9731 11.0493C11.8813 11.0493 10.9963 11.9344 10.9963 13.0261C10.9963 14.1179 11.8813 15.0029 12.9731 15.0029Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M2.9768 15.0029C4.06856 15.0029 4.9536 14.1179 4.9536 13.0261C4.9536 11.9344 4.06856 11.0493 2.9768 11.0493C1.88504 11.0493 1 11.9344 1 13.0261C1 14.1179 1.88504 15.0029 2.9768 15.0029Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M23.0232 25C24.1149 25 25 24.1149 25 23.0232C25 21.9314 24.1149 21.0464 23.0232 21.0464C21.9314 21.0464 21.0464 21.9314 21.0464 23.0232C21.0464 24.1149 21.9314 25 23.0232 25Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M12.9731 25C14.0648 25 14.9499 24.1149 14.9499 23.0232C14.9499 21.9314 14.0648 21.0464 12.9731 21.0464C11.8813 21.0464 10.9963 21.9314 10.9963 23.0232C10.9963 24.1149 11.8813 25 12.9731 25Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M2.9768 25C4.06856 25 4.9536 24.1149 4.9536 23.0232C4.9536 21.9314 4.06856 21.0464 2.9768 21.0464C1.88504 21.0464 1 21.9314 1 23.0232C1 24.1149 1.88504 25 2.9768 25Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - </svg> - ); -}; diff --git a/explorer-nextjs/app/icons/MobileDrawerClose.tsx b/explorer-nextjs/app/icons/MobileDrawerClose.tsx deleted file mode 100644 index 6c8ecfacbc0..00000000000 --- a/explorer-nextjs/app/icons/MobileDrawerClose.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import * as React from 'react'; - -export const MobileDrawerClose: FCWithChildren = (props) => ( - <svg xmlns="http://www.w3.org/2000/svg" viewBox="-3 -5 24 24" width="25" height="25" {...props}> - <path - d="M0 12H13V10H0V12ZM0 7H10V5H0V7ZM0 0V2H13V0H0ZM18 9.59L14.42 6L18 2.41L16.59 1L11.59 6L16.59 11L18 9.59Z" - fill="#F2F2F2" - /> - </svg> -); diff --git a/explorer-nextjs/app/icons/NetworksSVG.tsx b/explorer-nextjs/app/icons/NetworksSVG.tsx deleted file mode 100644 index 0db2b9bdfb8..00000000000 --- a/explorer-nextjs/app/icons/NetworksSVG.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -export const NetworkComponentsSVG: FCWithChildren = () => { - const theme = useTheme(); - const color = theme.palette.nym.networkExplorer.nav.text; - return ( - <svg width="25" height="25" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path - d="M17.2 10.5V4.40002L12 1.40002L6.8 4.40002V10.5L12 13.5L17.2 10.5Z" - stroke={color} - strokeMiterlimit="10" - /> - <path d="M12 19.6V13.5L6.8 10.5L1.5 13.5V19.6L6.8 22.6L12 19.6Z" stroke={color} strokeMiterlimit="10" /> - <path d="M22.5 19.6V13.5L17.2 10.5L12 13.5V19.6L17.2 22.6L22.5 19.6Z" stroke={color} strokeMiterlimit="10" /> - </svg> - ); -}; diff --git a/explorer-nextjs/app/icons/NodemapSVG.tsx b/explorer-nextjs/app/icons/NodemapSVG.tsx deleted file mode 100644 index 9486d64dcc1..00000000000 --- a/explorer-nextjs/app/icons/NodemapSVG.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -export const NodemapSVG: FCWithChildren = () => { - const theme = useTheme(); - const color = theme.palette.nym.networkExplorer.nav.text; - return ( - <svg width="25" height="25" viewBox="0 0 19 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path - d="M1 9.6999C1 5.0999 4.7 1.3999 9.3 1.3999C13.9 1.3999 17.6 5.0999 17.6 9.6999C17.6 14.2999 9.3 21.5999 9.3 21.5999C9.3 21.5999 1 14.2999 1 9.6999Z" - stroke={color} - strokeMiterlimit="10" - /> - <path - d="M9.30005 12C11.233 12 12.8 10.433 12.8 8.5C12.8 6.567 11.233 5 9.30005 5C7.36705 5 5.80005 6.567 5.80005 8.5C5.80005 10.433 7.36705 12 9.30005 12Z" - stroke={color} - strokeMiterlimit="10" - /> - <path d="M1.5 22.5999H17.1" stroke={color} strokeMiterlimit="10" strokeLinecap="round" /> - </svg> - ); -}; diff --git a/explorer-nextjs/app/icons/NymVpn.tsx b/explorer-nextjs/app/icons/NymVpn.tsx deleted file mode 100644 index ab9f484d918..00000000000 --- a/explorer-nextjs/app/icons/NymVpn.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import * as React from 'react' - -interface DiscordIconProps { - size?: { width: number; height: number } -} - -export const NymVpnIcon: FCWithChildren<DiscordIconProps> = ({ size }) => ( - <svg - width={size?.width} - height={size?.height} - viewBox="0 0 170 24" - fill="none" - xmlns="http://www.w3.org/2000/svg" - > - <path - d="M19.6118 0.128906H19.5405V0.187854V20.7961L10.7849 0.164277L10.773 0.128906H10.7255H5.75959H0.187819H0.128418V0.187854V23.8142V23.8732H0.187819H5.75959H5.81899V23.8142V3.17063L14.6103 23.8378L14.6222 23.8732H14.6697H19.6118H25.1717H25.2311V23.8142V0.187854V0.128906H25.1717H19.6118Z" - fill="white" - /> - <path - fillRule="evenodd" - clipRule="evenodd" - d="M19.4121 0H25.3603V24H14.5297L14.4901 23.8819L5.94824 3.80121V24H0V0H10.8663L10.906 0.118132L19.4121 20.1621V0ZM19.5409 20.7951L10.7853 0.163225L10.7734 0.127854H0.128835V23.8721H5.81941V3.16958L14.6107 23.8368L14.6226 23.8721H25.2315V0.127854H19.5409V20.7951Z" - fill="white" - /> - <path - d="M89.8116 0.128906H79.1908H79.1314L79.1195 0.176068L73.6784 20.8904L68.2255 0.176068L68.2136 0.128906H68.1661H57.5215H57.4502V0.187854V23.8142V23.8732H57.5215H63.0814H63.1408V23.8142V3.33568L68.5225 23.826L68.5343 23.8732H68.5937H78.7394H78.7869L78.7988 23.826L84.1804 3.33568V23.8142V23.8732H84.2398H89.8116H89.871V23.8142V0.187854V0.128906H89.8116Z" - fill="white" - /> - <path - fillRule="evenodd" - clipRule="evenodd" - d="M79.0312 0H90.0003V24H84.052V4.33208L78.9242 23.856L78.9238 23.8572L78.8879 24H68.4342L68.3982 23.8572L68.3979 23.856L63.27 4.33208V24H57.3218V0H68.3146L68.3505 0.142699L68.3509 0.144015L73.6787 20.383L78.9949 0.144015L78.9953 0.142765L79.0312 0ZM73.6788 20.8894L68.2259 0.175015L68.214 0.127854H57.4506V23.8721H63.1412V3.33463L68.5229 23.825L68.5348 23.8721H78.7873L78.7992 23.825L84.1809 3.33463V23.8721H89.8714V0.127854H79.1318L79.1199 0.175015L73.6788 20.8894Z" - fill="white" - /> - <path - d="M48.2909 0.128906H48.2553L48.2434 0.152487L41.4836 11.8124L34.6882 0.152487L34.6763 0.128906H34.6407H28.2135H28.0947L28.1541 0.223225L38.6205 18.2142V23.8142V23.8732H38.6799H44.2517H44.3111V23.8142V18.2142L54.7775 0.223225L54.8369 0.128906H54.7181H48.2909Z" - fill="white" - /> - <path - fillRule="evenodd" - clipRule="evenodd" - d="M48.1757 0H55.0693L54.8879 0.288036L44.4399 18.2474V24H38.4917V18.2474L28.0437 0.288036L27.8623 0H34.756L34.8017 0.0907854L41.4833 11.5555L48.1299 0.0909153L48.1757 0ZM48.2434 0.151434L41.4836 11.8114L34.6882 0.151434L34.6763 0.127854H28.0948L28.1542 0.222173L38.6205 18.2131V23.8721H44.3111V18.2131L54.7775 0.222173L54.8369 0.127854H48.2553L48.2434 0.151434Z" - fill="white" - /> - <path - d="M169.238 0V24H166.422C166.006 24 165.654 23.9341 165.366 23.8023C165.088 23.6596 164.811 23.418 164.534 23.0776L153.542 8.76321C153.584 9.19149 153.611 9.60878 153.622 10.0151C153.643 10.4104 153.654 10.7838 153.654 11.1352V24H148.886V0H151.734C151.968 0 152.166 0.0109813 152.326 0.032944C152.486 0.0549066 152.63 0.0988326 152.758 0.164722C152.886 0.219629 153.008 0.30199 153.126 0.411805C153.243 0.521619 153.376 0.669869 153.526 0.856553L164.614 15.2697C164.56 14.8085 164.523 14.3638 164.502 13.9355C164.48 13.4962 164.47 13.0844 164.47 12.7001V0H169.238Z" - fill="#A8A6A6" - /> - <path - d="M134.206 11.7776C135.614 11.7776 136.627 11.4317 137.246 10.7399C137.865 10.048 138.174 9.08167 138.174 7.84077C138.174 7.29169 138.094 6.79204 137.934 6.3418C137.774 5.89156 137.529 5.50721 137.198 5.18874C136.878 4.8593 136.467 4.60673 135.966 4.43102C135.475 4.25532 134.889 4.16747 134.206 4.16747H131.39V11.7776H134.206ZM134.206 0C135.849 0 137.257 0.203157 138.43 0.609471C139.614 1.0048 140.585 1.55388 141.342 2.25669C142.11 2.95951 142.675 3.78861 143.038 4.74399C143.401 5.69938 143.582 6.73164 143.582 7.84077C143.582 9.03775 143.395 10.1359 143.022 11.1352C142.649 12.1345 142.078 12.9911 141.31 13.7049C140.542 14.4187 139.566 14.9787 138.382 15.385C137.209 15.7804 135.817 15.978 134.206 15.978H131.39V24H125.982V0H134.206Z" - fill="#A8A6A6" - /> - <path - d="M121.584 0L112.24 24H107.344L98 0H102.352C102.821 0 103.2 0.115305 103.488 0.345915C103.776 0.565545 103.995 0.851064 104.144 1.20247L108.656 14.0508C108.869 14.6108 109.077 15.2258 109.28 15.8957C109.483 16.5546 109.675 17.2464 109.856 17.9712C110.005 17.2464 110.171 16.5546 110.352 15.8957C110.544 15.2258 110.747 14.6108 110.96 14.0508L115.44 1.20247C115.557 0.894989 115.765 0.620452 116.064 0.378861C116.373 0.126287 116.752 0 117.2 0H121.584Z" - fill="#A8A6A6" - /> - </svg> -) diff --git a/explorer-nextjs/app/icons/OverviewSVG.tsx b/explorer-nextjs/app/icons/OverviewSVG.tsx deleted file mode 100644 index 2ced0bb17b4..00000000000 --- a/explorer-nextjs/app/icons/OverviewSVG.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -export const OverviewSVG: FCWithChildren = () => { - const theme = useTheme(); - const color = theme.palette.nym.networkExplorer.nav.text; - - return ( - <svg width="25" height="25" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M1.4 21.6H22.6" stroke={color} strokeMiterlimit="10" strokeLinecap="round" /> - <path d="M14.1 2.40002H9.9V21.5H14.1V2.40002Z" stroke={color} strokeMiterlimit="10" strokeLinecap="round" /> - <path d="M20.8 6.59998H16.6V21.5H20.8V6.59998Z" stroke={color} strokeMiterlimit="10" strokeLinecap="round" /> - <path d="M7.4 11.8H3.2V21.6H7.4V11.8Z" stroke={color} strokeMiterlimit="10" strokeLinecap="round" /> - </svg> - ); -}; diff --git a/explorer-nextjs/app/icons/TokenSVG.tsx b/explorer-nextjs/app/icons/TokenSVG.tsx deleted file mode 100644 index 94ab1468c92..00000000000 --- a/explorer-nextjs/app/icons/TokenSVG.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from 'react'; - -export const TokenSVG: FCWithChildren = () => { - const color = 'white'; - - return ( - <svg xmlns="http://www.w3.org/2000/svg" width="24" height="25" viewBox="0 0 24 25" fill="none"> - <g clipPath="url(#clip0_2549_7563)"> - <path - d="M20.4841 4.01607C15.8041 -0.67593 8.19607 -0.67593 3.51607 4.01607C-1.17593 8.70807 -1.17593 16.3041 3.51607 20.9841C8.20807 25.6761 15.8041 25.6761 20.4841 20.9841C25.1761 16.3041 25.1761 8.69607 20.4841 4.01607ZM19.4521 19.9521C15.3361 24.0681 8.65207 24.0681 4.53607 19.9521C0.42007 15.8361 0.42007 9.15207 4.53607 5.03607C8.65207 0.92007 15.3361 0.92007 19.4521 5.03607C23.5801 9.16407 23.5801 15.8361 19.4521 19.9521Z" - fill={color} - /> - <path - d="M18.48 19.4965V5.50447C17.868 4.92847 17.184 4.42447 16.452 4.02847V17.4085L7.62002 3.98047C6.85202 4.38847 6.14402 4.89247 5.52002 5.49247V19.4965C6.13202 20.0725 6.81602 20.5765 7.54802 20.9725V7.59247L16.38 21.0205C17.148 20.6125 17.856 20.0965 18.48 19.4965Z" - fill={color} - /> - </g> - <defs> - <clipPath id="clip0_2549_7563"> - <rect width="24" height="24" fill="white" transform="translate(0 0.5)" /> - </clipPath> - </defs> - </svg> - ); -}; diff --git a/explorer-nextjs/app/icons/ValidatorsSVG.tsx b/explorer-nextjs/app/icons/ValidatorsSVG.tsx deleted file mode 100644 index cf03f1c3304..00000000000 --- a/explorer-nextjs/app/icons/ValidatorsSVG.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -export const ValidatorsSVG: FCWithChildren = () => { - const theme = useTheme(); - const color = theme.palette.text.primary; - return ( - <svg width="24" height="24" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> - <g clipPath="url(#clip0)"> - <path - d="M18.2001 18.4V19.7001C18.2001 21.4001 16.9 22.7001 15.2 22.7001H4.30005C2.60005 22.7001 1.30005 21.4001 1.30005 19.7001V4.30005C1.30005 2.60005 2.60005 1.30005 4.30005 1.30005H15.1C16.8 1.30005 18.1 2.60005 18.1 4.30005V5.60005V18.4H18.2001Z" - stroke={color} - strokeWidth="1.3" - strokeMiterlimit="10" - strokeLinecap="round" - /> - <path - d="M13.4 22.7001H17.4C19.1 22.7001 20.4 21.4001 20.4 19.7001V18.4V5.60005V4.30005C20.4 2.60005 19.1 1.30005 17.4 1.30005H11.5" - stroke={color} - strokeWidth="1.3" - strokeMiterlimit="10" - strokeLinecap="round" - /> - <path - d="M15.2 22.7001H19.7C21.4 22.7001 22.7 21.4001 22.7 19.7001V18.4V5.60005V4.30005C22.7 2.60005 21.4 1.30005 19.7 1.30005H13.8" - stroke={color} - strokeWidth="1.3" - strokeMiterlimit="10" - strokeLinecap="round" - /> - <path - d="M5 12.3L7.9 15.3L14.5 8.69995" - stroke={color} - strokeWidth="2" - strokeMiterlimit="10" - strokeLinecap="round" - strokeLinejoin="round" - /> - </g> - <defs> - <clipPath id="clip0"> - <rect width="24" height="24" fill="white" /> - </clipPath> - </defs> - </svg> - ); -}; diff --git a/explorer-nextjs/app/icons/socials/DiscordIcon.tsx b/explorer-nextjs/app/icons/socials/DiscordIcon.tsx deleted file mode 100644 index b81c571c334..00000000000 --- a/explorer-nextjs/app/icons/socials/DiscordIcon.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as React from 'react' -import { useTheme } from '@mui/material/styles' - -interface DiscordIconProps { - size?: number | string - color?: string -} - -export const DiscordIcon: FCWithChildren<DiscordIconProps> = ({ - size, - color: colorProp, -}) => { - const theme = useTheme() - const color = colorProp || theme.palette.text.primary - return ( - <svg width={size} height={size} viewBox="0 0 24 24" fill="none"> - <g clipPath="url(#clip0_1223_2296)"> - <path - d="M12.4 0C5.80002 0 0.400024 5.4 0.400024 12C0.400024 18.6 5.80002 24 12.4 24C19 24 24.4 18.6 24.4 12C24.4 5.4 19 0 12.4 0ZM20.1 15.9C18.8 16.9 17.5 17.5 16.2 17.9C16.2 17.9 16.2 17.9 16.1 17.9C15.8 17.5 15.5 17.1 15.3 16.6V16.5C15.7 16.3 16.1 16.1 16.5 15.9V15.8C16.4 15.7 16.3 15.7 16.3 15.6C16.3 15.6 16.3 15.6 16.2 15.6C13.7 16.8 10.9 16.8 8.40002 15.6C8.40002 15.6 8.40002 15.6 8.30002 15.6C8.20002 15.7 8.10002 15.7 8.10002 15.8V15.9C8.50002 16.1 8.90002 16.3 9.30002 16.5C9.30002 16.5 9.30002 16.5 9.30002 16.6C9.10002 17.1 8.80002 17.5 8.50002 17.9C8.50002 17.9 8.50002 17.9 8.40002 17.9C7.10002 17.5 5.90002 16.9 4.50002 15.9C4.40002 13 5.00002 10.1 7.00002 7.1C8.00002 6.6 9.00002 6.3 10.2 6.1C10.2 6.1 10.2 6.1 10.3 6.1C10.4 6.3 10.6 6.7 10.7 6.9C11.9 6.7 13.1 6.7 14.2 6.9C14.3 6.7 14.5 6.3 14.6 6.1C14.6 6.1 14.6 6.1 14.7 6.1C15.8 6.3 16.9 6.6 17.9 7.1C19.5 9.7 20.4 12.6 20.1 15.9Z" - fill={color} - /> - <path - d="M15 11C14.2 11 13.6 11.7 13.6 12.6C13.6 13.5 14.2 14.2 15 14.2C15.8 14.2 16.4 13.5 16.4 12.6C16.4 11.7 15.8 11 15 11Z" - fill={color} - /> - <path - d="M9.80002 11C9.10002 11 8.40002 11.7 8.40002 12.6C8.40002 13.5 9.00002 14.2 9.80002 14.2C10.6 14.2 11.2 13.5 11.2 12.6C11.2 11.7 10.6 11 9.80002 11Z" - fill={color} - /> - </g> - <defs> - <clipPath id="clip0_1223_2296"> - <rect width="24" height="24" transform="translate(0.400024)" /> - </clipPath> - </defs> - </svg> - ) -} diff --git a/explorer-nextjs/app/icons/socials/GitHubIcon.tsx b/explorer-nextjs/app/icons/socials/GitHubIcon.tsx deleted file mode 100644 index 11389e6969b..00000000000 --- a/explorer-nextjs/app/icons/socials/GitHubIcon.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import * as React from 'react' -import { useTheme } from '@mui/material/styles' - -interface GitHubIconProps { - size?: number | string - color?: string -} - -export const GitHubIcon: FCWithChildren<GitHubIconProps> = ({ - size, - color: colorProp, -}) => { - const theme = useTheme() - const color = colorProp || theme.palette.text.primary - return ( - <svg width={size} height={size} viewBox="0 0 24 24" fill="none"> - <g clipPath="url(#clip0_1223_2302)"> - <path - fillRule="evenodd" - clipRule="evenodd" - d="M12.7 0C5.90002 0 0.400024 5.5 0.400024 12.3C0.400024 17.7 3.90002 22.3 8.80002 24C9.40002 24.1 9.60002 23.7 9.60002 23.4C9.60002 23.1 9.60002 22.1 9.60002 21.1C6.50002 21.7 5.70002 20.3 5.50002 19.7C5.40002 19.3 4.80002 18.3 4.20002 18C3.80002 17.8 3.20002 17.2 4.20002 17.2C5.20002 17.2 5.90002 18.1 6.10002 18.5C7.20002 20.4 9.00002 19.8 9.70002 19.5C9.80002 18.7 10.1 18.2 10.5 17.9C7.80002 17.6 4.90002 16.5 4.90002 11.8C4.90002 10.5 5.40002 9.4 6.20002 8.5C6.00002 8 5.60002 6.8 6.30002 5.1C6.30002 5.1 7.30002 4.8 9.70002 6.4C10.7 6.1 11.7 6 12.8 6C13.8 6 14.9 6.1 15.9 6.4C18.3 4.8 19.3 5.1 19.3 5.1C20 6.8 19.5 8.1 19.4 8.4C20.2 9.3 20.7 10.4 20.7 11.7C20.7 16.4 17.8 17.5 15.1 17.8C15.5 18.2 15.9 18.9 15.9 20.1C15.9 21.7 15.9 23.1 15.9 23.5C15.9 23.8 16.1 24.2 16.7 24.1C21.6 22.5 25.1 17.9 25.1 12.4C25 5.5 19.5 0 12.7 0Z" - fill={color} - /> - </g> - <defs> - <clipPath id="clip0_1223_2302"> - <rect width="24" height="24" transform="translate(0.400024)" /> - </clipPath> - </defs> - </svg> - ) -} diff --git a/explorer-nextjs/app/icons/socials/TelegramIcon.tsx b/explorer-nextjs/app/icons/socials/TelegramIcon.tsx deleted file mode 100644 index a66020a849a..00000000000 --- a/explorer-nextjs/app/icons/socials/TelegramIcon.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import * as React from 'react' -import { useTheme } from '@mui/material/styles' - -interface TelegramIconProps { - size?: number | string - color?: string -} - -export const TelegramIcon: FCWithChildren<TelegramIconProps> = ({ - size, - color: colorProp, -}) => { - const theme = useTheme() - const color = colorProp || theme.palette.text.primary - return ( - <svg width={size} height={size} viewBox="0 0 24 24" fill="none"> - <path - d="M12.4 24C19.029 24 24.4 18.629 24.4 12C24.4 5.371 19.029 0 12.4 0C5.77102 0 0.400024 5.371 0.400024 12C0.400024 18.629 5.77102 24 12.4 24ZM5.89102 11.74L17.461 7.279C17.998 7.085 18.467 7.41 18.293 8.222L18.294 8.221L16.324 17.502C16.178 18.16 15.787 18.32 15.24 18.01L12.24 15.799L10.793 17.193C10.633 17.353 10.498 17.488 10.188 17.488L10.401 14.435L15.961 9.412C16.203 9.199 15.907 9.079 15.588 9.291L8.71702 13.617L5.75502 12.693C5.11202 12.489 5.09802 12.05 5.89102 11.74Z" - fill={color} - /> - </svg> - ) -} diff --git a/explorer-nextjs/app/icons/socials/TwitterIcon.tsx b/explorer-nextjs/app/icons/socials/TwitterIcon.tsx deleted file mode 100644 index 5d94de99a3a..00000000000 --- a/explorer-nextjs/app/icons/socials/TwitterIcon.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import * as React from 'react' -import { useTheme } from '@mui/material/styles' - -interface TwitterIconProps { - size?: number | string - color?: string -} - -export const TwitterIcon: FCWithChildren<TwitterIconProps> = ({ - size, - color: colorProp, -}) => { - const theme = useTheme() - const color = colorProp || theme.palette.text.primary - return ( - <svg width={size} height={size} viewBox="0 0 24 24" fill="none"> - <g clipPath="url(#clip0_1223_2294)"> - <path - d="M12.4 0C5.77362 0 0.400024 5.3736 0.400024 12C0.400024 18.6264 5.77362 24 12.4 24C19.0264 24 24.4 18.6264 24.4 12C24.4 5.3736 19.0264 0 12.4 0ZM17.8791 9.35632C17.8844 9.47443 17.887 9.59308 17.887 9.71228C17.887 13.3519 15.1166 17.5488 10.0502 17.549H10.0504H10.0502C8.49475 17.549 7.0473 17.0931 5.82837 16.3118C6.04388 16.3372 6.26324 16.3499 6.48535 16.3499C7.77588 16.3499 8.9635 15.9097 9.90631 15.1708C8.70056 15.1485 7.68396 14.3522 7.33313 13.2578C7.50104 13.29 7.67371 13.3076 7.85077 13.3076C8.10217 13.3076 8.3457 13.2737 8.57715 13.2105C7.31683 12.9582 6.36743 11.8444 6.36743 10.5106C6.36743 10.4982 6.36743 10.487 6.3678 10.4755C6.73895 10.6818 7.16339 10.806 7.6153 10.8199C6.87573 10.3264 6.38959 9.48285 6.38959 8.52722C6.38959 8.02258 6.526 7.5498 6.76257 7.14276C8.12085 8.80939 10.1508 9.90546 12.4399 10.0206C12.3927 9.81885 12.3683 9.60864 12.3683 9.39258C12.3683 7.87207 13.6019 6.63849 15.123 6.63849C15.9153 6.63849 16.6309 6.97339 17.1335 7.50879C17.761 7.38501 18.3502 7.15576 18.8825 6.84027C18.6765 7.48315 18.24 8.02258 17.6713 8.36371C18.2285 8.29706 18.7595 8.14929 19.2529 7.92993C18.8843 8.48236 18.4169 8.96759 17.8791 9.35632V9.35632Z" - fill={color} - /> - </g> - <defs> - <clipPath id="clip0_1223_2294"> - <rect width="24" height="24" transform="translate(0.400024)" /> - </clipPath> - </defs> - </svg> - ) -} diff --git a/explorer-nextjs/app/layout.tsx b/explorer-nextjs/app/layout.tsx deleted file mode 100644 index a532714d84a..00000000000 --- a/explorer-nextjs/app/layout.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import type { Metadata } from 'next' -import '@interchain-ui/react/styles' -import { App } from './App' - -export const metadata: Metadata = { - title: 'Nym Network Explorer', -} - -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode -}>) { - return ( - <html lang="en"> - <body> - <App>{children}</App> - </body> - </html> - ) -} diff --git a/explorer-nextjs/app/loading.tsx b/explorer-nextjs/app/loading.tsx deleted file mode 100644 index bb90466dc54..00000000000 --- a/explorer-nextjs/app/loading.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react' -import { LinearProgress, Box } from '@mui/material' - -export default function Loading() { - return ( - <Box sx={{ py: 16 }}> - <LinearProgress /> - </Box> - ) -} diff --git a/explorer-nextjs/app/network-components/gateways/[id]/page.tsx b/explorer-nextjs/app/network-components/gateways/[id]/page.tsx deleted file mode 100644 index 87f779872a9..00000000000 --- a/explorer-nextjs/app/network-components/gateways/[id]/page.tsx +++ /dev/null @@ -1,206 +0,0 @@ -'use client' - -import * as React from 'react' -import { Alert, AlertTitle, Box, CircularProgress, Grid } from '@mui/material' -import { useParams } from 'next/navigation' -import {GatewayBond, LocatedGateway} from '@/app/typeDefs/explorer-api' -import { ColumnsType, DetailTable } from '@/app/components/DetailTable' -import { - gatewayEnrichedToGridRow, - GatewayEnrichedRowType, -} from '@/app/components/Gateways/Gateways' -import { ComponentError } from '@/app/components/ComponentError' -import { ContentCard } from '@/app/components/ContentCard' -import { TwoColSmallTable } from '@/app/components/TwoColSmallTable' -import { UptimeChart } from '@/app/components/UptimeChart' -import { - GatewayContextProvider, - useGatewayContext, -} from '@/app/context/gateway' -import { useMainContext } from '@/app/context/main' -import { Title } from '@/app/components/Title' - -const columns: ColumnsType[] = [ - { - field: 'identity_key', - title: 'Identity Key', - headerAlign: 'left', - width: 230, - }, - { - field: 'bond', - title: 'Bond', - headerAlign: 'left', - }, - { - field: 'avgUptime', - title: 'Avg. Score', - headerAlign: 'left', - tooltipInfo: "Gateway's average routing score in the last 24 hours", - }, - { - field: 'host', - title: 'IP', - headerAlign: 'left', - width: 99, - }, - { - field: 'location', - title: 'Location', - headerAlign: 'left', - }, - { - field: 'owner', - title: 'Owner', - headerAlign: 'left', - }, - { - field: 'version', - title: 'Version', - headerAlign: 'left', - }, -] - -/** - * Shows gateway details - */ -const PageGatewayDetailsWithState = ({ - selectedGateway, -}: { - selectedGateway: LocatedGateway | undefined -}) => { - const [enrichGateway, setEnrichGateway] = - React.useState<GatewayEnrichedRowType>() - const [status, setStatus] = React.useState<number[] | undefined>() - const { uptimeReport, uptimeStory } = useGatewayContext() - - React.useEffect(() => { - if (uptimeReport?.data && selectedGateway) { - setEnrichGateway( - gatewayEnrichedToGridRow(selectedGateway, uptimeReport.data) - ) - } - }, [uptimeReport, selectedGateway]) - - React.useEffect(() => { - if (enrichGateway) { - setStatus([enrichGateway.mixPort, enrichGateway.clientsPort]) - } - }, [enrichGateway]) - - return ( - <Box component="main"> - <Title text="Legacy Gateway Detail" /> - - <Alert variant="filled" severity="warning" sx={{ my : 2, pt: 2 }}> - <AlertTitle> - Please update to the latest <code>nym-node</code> binary and migrate your bond and delegations from the wallet - </AlertTitle> - </Alert> - - <Grid container> - <Grid item xs={12}> - <DetailTable - columnsData={columns} - tableName="Gateway detail table" - rows={enrichGateway ? [enrichGateway] : []} - /> - </Grid> - </Grid> - - <Grid container spacing={2} mt={0}> - <Grid item xs={12} md={4}> - {status && ( - <ContentCard title="Gateway Status"> - <TwoColSmallTable - loading={false} - keys={['Mix port', 'Client WS API Port']} - values={status.map((each) => each)} - icons={status.map((elem) => !!elem)} - /> - </ContentCard> - )} - </Grid> - <Grid item xs={12} md={8}> - {uptimeStory && ( - <ContentCard title="Routing Score"> - {uptimeStory.error && ( - <ComponentError text="There was a problem retrieving routing score." /> - )} - <UptimeChart - loading={uptimeStory.isLoading} - xLabel="Date" - yLabel="Daily average" - uptimeStory={uptimeStory} - /> - </ContentCard> - )} - </Grid> - </Grid> - </Box> - ) -} - -/** - * Guard component to handle loadingW and not found states - */ -const PageGatewayDetailGuard = () => { - const [selectedGateway, setSelectedGateway] = React.useState<LocatedGateway>() - const { gateways } = useMainContext() - const { id } = useParams() - - React.useEffect(() => { - if (gateways?.data) { - setSelectedGateway( - gateways.data.find((g) => g.gateway.identity_key === id) - ) - } - }, [gateways, id]) - - if (gateways?.isLoading) { - return <CircularProgress /> - } - - if (gateways?.error) { - // eslint-disable-next-line no-console - console.error(gateways?.error) - return ( - <Alert severity="error"> - Oh no! Could not load mixnode <code>{id || ''}</code> - </Alert> - ) - } - - // loaded, but not found - if (gateways && !gateways.isLoading && !gateways.data) { - return ( - <Alert severity="warning"> - <AlertTitle>Gateway not found</AlertTitle> - Sorry, we could not find a mixnode with id <code>{id || ''}</code> - </Alert> - ) - } - - return <PageGatewayDetailsWithState selectedGateway={selectedGateway} /> -} - -/** - * Wrapper component that adds the mixnode content based on the `id` in the address URL - */ -const PageGatewayDetail = () => { - const { id } = useParams() - - if (!id || typeof id !== 'string') { - return ( - <Alert severity="error">Oh no! No mixnode identity key specified</Alert> - ) - } - - return ( - <GatewayContextProvider gatewayIdentityKey={id}> - <PageGatewayDetailGuard /> - </GatewayContextProvider> - ) -} - -export default PageGatewayDetail diff --git a/explorer-nextjs/app/network-components/gateways/page.tsx b/explorer-nextjs/app/network-components/gateways/page.tsx deleted file mode 100644 index c2660ce3870..00000000000 --- a/explorer-nextjs/app/network-components/gateways/page.tsx +++ /dev/null @@ -1,256 +0,0 @@ -'use client' - -import React, { useMemo } from 'react' -import { Box, Card, Grid, Stack } from '@mui/material' -import { useTheme } from '@mui/material/styles' -import { - MRT_ColumnDef, - MaterialReactTable, - useMaterialReactTable, -} from 'material-react-table' -import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid' -import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard' -import { Tooltip as InfoTooltip } from '@nymproject/react/tooltip/Tooltip' -import { diff, gte, rcompare } from 'semver' -import { useMainContext } from '@/app/context/main' -import { TableToolbar } from '@/app/components/TableToolbar' -import { CustomColumnHeading } from '@/app/components/CustomColumnHeading' -import { Title } from '@/app/components/Title' -import { unymToNym } from '@/app/utils/currency' -import { Tooltip } from '@/app/components/Tooltip' -import { EXPLORER_FOR_ACCOUNTS } from '@/app/api/constants' -import { splice } from '@/app/utils' -import { - VersionDisplaySelector, - VersionSelectOptions, -} from '@/app/components/Gateways/VersionDisplaySelector' -import StyledLink from '@/app/components/StyledLink' -import { - GatewayRowType, - gatewayToGridRow, -} from '@/app/components/Gateways/Gateways' -import {LocatedGateway} from "@/app/typeDefs/explorer-api"; - -const gatewaySanitize = (g?: LocatedGateway): boolean => { - if(!g) { - return false; - } - - if(!g.gateway.version || !g.gateway.version.trim().length) { - return false; - } - - if(g.gateway.version === "null") { - return false; - } - - return true; -} - -const PageGateways = () => { - const { gateways } = useMainContext() - const [versionFilter, setVersionFilter] = - React.useState<VersionSelectOptions>(VersionSelectOptions.all) - - const theme = useTheme() - - const highestVersion = React.useMemo(() => { - if (gateways?.data) { - const versions = gateways.data.filter(gatewaySanitize).reduce( - (a: string[], b) => [...a, b.gateway.version], - [] - ) - const [lastestVersion] = versions.sort(rcompare) - return lastestVersion - } - // fallback value - return '2.0.0' - }, [gateways]) - - const filterByLatestVersions = React.useMemo(() => { - const filtered = gateways?.data?.filter(gatewaySanitize).filter((gw) => { - const versionDiff = diff(highestVersion, gw.gateway.version) - return versionDiff === 'patch' || versionDiff === null - }) - if (filtered) return filtered - return [] - }, [gateways]) - - const filterByOlderVersions = React.useMemo(() => { - const filtered = gateways?.data?.filter(gatewaySanitize).filter((gw) => { - const versionDiff = diff(highestVersion, gw.gateway.version) - return versionDiff === 'major' || versionDiff === 'minor' - }) - if (filtered) return filtered - return [] - }, [gateways]) - - const filteredByVersion = React.useMemo(() => { - switch (versionFilter) { - case VersionSelectOptions.latestVersion: - return filterByLatestVersions - case VersionSelectOptions.olderVersions: - return filterByOlderVersions - case VersionSelectOptions.all: - return gateways?.data || [] - default: - return [] - } - }, [versionFilter, gateways]) - - const data = useMemo(() => { - return gatewayToGridRow(filteredByVersion || []) - }, [filteredByVersion]) - - const columns = useMemo<MRT_ColumnDef<GatewayRowType>[]>(() => { - return [ - { - id: 'gateway-data', - header: 'Gateways Data', - columns: [ - { - id: 'identity_key', - header: 'Identity Key', - accessorKey: 'identity_key', - size: 250, - Cell: ({ row }) => { - return ( - <Stack direction="row" alignItems="center" gap={1}> - <CopyToClipboard - sx={{ mr: 0.5, color: 'grey.400' }} - smallIcons - value={row.original.identity_key} - tooltip={`Copy identity key ${row.original.identity_key} to clipboard`} - /> - <StyledLink - to={`/network-components/gateways/${row.original.identity_key}`} - dataTestId="identity-link" - color="text.primary" - > - {splice(7, 29, row.original.identity_key)} - </StyledLink> - </Stack> - ) - }, - }, - { - id: 'version', - header: 'Version', - accessorKey: 'version', - size: 150, - Cell: ({ row }) => { - return ( - <StyledLink - to={`/network-components/gateways/${row.original.identity_key}`} - data-testid="version" - color="text.primary" - > - {row.original.version} - </StyledLink> - ) - }, - }, - { - id: 'location', - header: 'Location', - accessorKey: 'location', - size: 150, - Cell: ({ row }) => { - return ( - <Box - sx={{ justifyContent: 'flex-start', cursor: 'pointer' }} - data-testid="location-button" - > - <Tooltip - text={row.original.location} - id="gateway-location-text" - > - <Box - sx={{ - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - }} - > - {row.original.location} - </Box> - </Tooltip> - </Box> - ) - }, - }, - { - id: 'host', - header: 'IP:Port', - accessorKey: 'host', - size: 150, - Cell: ({ row }) => { - return ( - <StyledLink - to={`/network-components/gateways/${row.original.identity_key}`} - data-testid="host" - color="text.primary" - > - {row.original.host} - </StyledLink> - ) - }, - }, - { - id: 'owner', - header: 'Owner', - accessorKey: 'owner', - size: 150, - Cell: ({ row }) => { - return ( - <StyledLink - to={`${EXPLORER_FOR_ACCOUNTS}/account/${row.original.owner}`} - target="_blank" - data-testid="owner" - color="text.primary" - > - {splice(7, 29, row.original.owner)} - </StyledLink> - ) - }, - }, - ], - }, - ] - }, []) - - const table = useMaterialReactTable({ - columns, - data, - }) - - return ( - <> - <Box mb={2}> - <Title text="Legacy Gateways" /> - </Box> - <Grid container> - <Grid item xs={12}> - <Card - sx={{ - padding: 2, - height: '100%', - }} - > - <TableToolbar - childrenBefore={ - <VersionDisplaySelector - handleChange={(option) => setVersionFilter(option)} - selected={versionFilter} - /> - } - /> - <MaterialReactTable table={table} /> - </Card> - </Grid> - </Grid> - </> - ) -} - -export default PageGateways diff --git a/explorer-nextjs/app/network-components/mixnodes/[id]/page.tsx b/explorer-nextjs/app/network-components/mixnodes/[id]/page.tsx deleted file mode 100644 index 5e03b5d1326..00000000000 --- a/explorer-nextjs/app/network-components/mixnodes/[id]/page.tsx +++ /dev/null @@ -1,302 +0,0 @@ -'use client' - -import * as React from 'react' -import { - Alert, - AlertTitle, - Box, - CircularProgress, - Grid, - Typography, -} from '@mui/material' -import { ColumnsType, DetailTable } from '@/app/components/DetailTable' -import { BondBreakdownTable } from '@/app/components/MixNodes/BondBreakdown' -import { - DelegatorsInfoTable, - EconomicsInfoColumns, - EconomicsInfoRows, -} from '@/app/components/MixNodes/Economics' -import { ComponentError } from '@/app/components/ComponentError' -import { ContentCard } from '@/app/components/ContentCard' -import { TwoColSmallTable } from '@/app/components/TwoColSmallTable' -import { UptimeChart } from '@/app/components/UptimeChart' -import { WorldMap } from '@/app/components/WorldMap' -import { MixNodeDetailSection } from '@/app/components/MixNodes/DetailSection' -import { - MixnodeContextProvider, - useMixnodeContext, -} from '@/app/context/mixnode' -import { Title } from '@/app/components/Title' -import { useIsMobile } from '@/app/hooks/useIsMobile' -import { useParams } from 'next/navigation' - -const columns: ColumnsType[] = [ - { - field: 'owner', - title: 'Owner', - width: '15%', - }, - { - field: 'identity_key', - title: 'Identity Key', - width: '15%', - }, - - { - field: 'bond', - title: 'Stake', - width: '12.5%', - }, - { - field: 'stake_saturation', - title: 'Stake Saturation', - width: '12.5%', - tooltipInfo: - 'Level of stake saturation for this node. Nodes receive more rewards the higher their saturation level, up to 100%. Beyond 100% no additional rewards are granted. The current stake saturation level is 940k NYMs, computed as S/K where S is target amount of tokens staked in the network and K is the number of nodes in the reward set.', - }, - { - field: 'self_percentage', - width: '10%', - title: 'Bond %', - tooltipInfo: - "Percentage of the operator's bond to the total stake on the node", - }, - - { - field: 'host', - width: '10%', - title: 'Host', - }, - { - field: 'location', - title: 'Location', - }, - - { - field: 'layer', - title: 'Layer', - }, -] - -/** - * Shows mix node details - */ -const PageMixnodeDetailWithState = () => { - const { - mixNode, - mixNodeRow, - description, - stats, - status, - uptimeStory, - uniqDelegations, - } = useMixnodeContext() - const isMobile = useIsMobile() - return ( - <Box component="main"> - <Title text="Legacy Mixnode Detail" /> - <Alert variant="filled" severity="warning" sx={{ my : 2, pt: 2 }}> - <AlertTitle> - Please update to the latest <code>nym-node</code> binary and migrate your bond and delegations from the wallet - </AlertTitle> - </Alert> - <Grid container spacing={2} mt={1} mb={6}> - <Grid item xs={12}> - {mixNodeRow && description?.data && ( - <MixNodeDetailSection - mixNodeRow={mixNodeRow} - mixnodeDescription={description.data} - /> - )} - {mixNodeRow?.blacklisted && ( - <Typography - textAlign={isMobile ? 'left' : 'right'} - fontSize="smaller" - sx={{ color: 'error.main' }} - > - This node is having a poor performance - </Typography> - )} - </Grid> - </Grid> - <Grid container> - <Grid item xs={12}> - <DetailTable - columnsData={columns} - tableName="Mixnode detail table" - rows={mixNodeRow ? [mixNodeRow] : []} - /> - </Grid> - </Grid> - <Grid container spacing={2} mt={0}> - <Grid item xs={12}> - <DelegatorsInfoTable - columnsData={EconomicsInfoColumns} - tableName="Delegators info table" - rows={[EconomicsInfoRows()]} - /> - </Grid> - </Grid> - <Grid container spacing={2} mt={0}> - <Grid item xs={12}> - <ContentCard - title={`Stake Breakdown (${uniqDelegations?.data?.length} delegators)`} - > - <BondBreakdownTable /> - </ContentCard> - </Grid> - </Grid> - <Grid container spacing={2} mt={0}> - <Grid item xs={12} md={4}> - <ContentCard title="Mixnode Stats"> - {stats && ( - <> - {stats.error && ( - <ComponentError text="There was a problem retrieving this nodes stats." /> - )} - <TwoColSmallTable - loading={stats.isLoading} - error={stats?.error?.message} - title="Since startup" - keys={['Received', 'Sent', 'Explicitly dropped']} - values={[ - stats?.data?.packets_received_since_startup || 0, - stats?.data?.packets_sent_since_startup || 0, - stats?.data?.packets_explicitly_dropped_since_startup || 0, - ]} - /> - <TwoColSmallTable - loading={stats.isLoading} - error={stats?.error?.message} - title="Since last update" - keys={['Received', 'Sent', 'Explicitly dropped']} - values={[ - stats?.data?.packets_received_since_last_update || 0, - stats?.data?.packets_sent_since_last_update || 0, - stats?.data?.packets_explicitly_dropped_since_last_update || - 0, - ]} - marginBottom - /> - </> - )} - {!stats && <Typography>No stats information</Typography>} - </ContentCard> - </Grid> - <Grid item xs={12} md={8}> - {uptimeStory && ( - <ContentCard title="Routing Score"> - {uptimeStory.error && ( - <ComponentError text="There was a problem retrieving routing score." /> - )} - <UptimeChart - loading={uptimeStory.isLoading} - xLabel="Date" - yLabel="Daily average" - uptimeStory={uptimeStory} - /> - </ContentCard> - )} - </Grid> - </Grid> - <Grid container spacing={2} mt={0}> - <Grid item xs={12} md={4}> - {status && ( - <ContentCard title="Mixnode Status"> - {status.error && ( - <ComponentError text="There was a problem retrieving port information" /> - )} - <TwoColSmallTable - loading={status.isLoading} - error={status?.error?.message} - keys={['Mix port', 'Verloc port', 'HTTP port']} - values={[1789, 1790, 8000].map((each) => each)} - icons={ - (status?.data?.ports && Object.values(status.data.ports)) || [ - false, - false, - false, - ] - } - /> - </ContentCard> - )} - </Grid> - <Grid item xs={12} md={8}> - {mixNode && ( - <ContentCard title="Location"> - {mixNode?.error && ( - <ComponentError text="There was a problem retrieving this mixnode location" /> - )} - {mixNode?.data?.location?.latitude && - mixNode?.data?.location?.longitude && ( - <WorldMap - loading={mixNode.isLoading} - userLocation={[ - mixNode.data.location.longitude, - mixNode.data.location.latitude, - ]} - /> - )} - </ContentCard> - )} - </Grid> - </Grid> - </Box> - ) -} - -/** - * Guard component to handle loading and not found states - */ -const PageMixnodeDetailGuard = () => { - const { mixNode } = useMixnodeContext() - const { id } = useParams() - - if (mixNode?.isLoading) { - return <CircularProgress /> - } - - if (mixNode?.error) { - // eslint-disable-next-line no-console - console.error(mixNode?.error) - return ( - <Alert severity="error"> - Oh no! Could not load mixnode <code>{id || ''}</code> - </Alert> - ) - } - - // loaded, but not found - if (mixNode && !mixNode.isLoading && !mixNode.data) { - return ( - <Alert severity="warning"> - <AlertTitle>Mixnode not found</AlertTitle> - Sorry, we could not find a mixnode with id <code>{id || ''}</code> - </Alert> - ) - } - - return <PageMixnodeDetailWithState /> -} - -/** - * Wrapper component that adds the mixnode content based on the `id` in the address URL - */ -const PageMixnodeDetail = () => { - const { id } = useParams() - - if (!id || typeof id !== 'string') { - return ( - <Alert severity="error">Oh no! No mixnode identity key specified</Alert> - ) - } - - return ( - <MixnodeContextProvider mixId={id}> - <PageMixnodeDetailGuard /> - </MixnodeContextProvider> - ) -} - -export default PageMixnodeDetail diff --git a/explorer-nextjs/app/network-components/mixnodes/page.tsx b/explorer-nextjs/app/network-components/mixnodes/page.tsx deleted file mode 100644 index 2f2774a7f43..00000000000 --- a/explorer-nextjs/app/network-components/mixnodes/page.tsx +++ /dev/null @@ -1,382 +0,0 @@ -'use client' - -import React, { useCallback, useMemo } from 'react' -import { useRouter, useSearchParams } from 'next/navigation' -import { - MaterialReactTable, - useMaterialReactTable, - type MRT_ColumnDef, -} from 'material-react-table' -import { Grid, Card, Button, Box, Stack } from '@mui/material' -import { - CustomColumnHeading, - DelegateIconButton, - DelegateModal, - DelegationModal, - DelegationModalProps, - MixNodeStatusDropdown, - MixnodeRowType, - StyledLink, - TableToolbar, - Title, - Tooltip, - mixnodeToGridRow, -} from '@/app/components' -import { DelegationsProvider } from '@/app/context/delegations' -import { useWalletContext } from '@/app/context/wallet' -import { useGetMixNodeStatusColor, useIsMobile } from '@/app/hooks' -import { useMainContext } from '@/app/context/main' -import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard' -import { splice } from '@/app/utils' -import { currencyToString } from '@/app/utils/currency' -import { EXPLORER_FOR_ACCOUNTS } from '@/app/api/constants' -import { - MixnodeStatusWithAll, - toMixnodeStatus, -} from '@/app/typeDefs/explorer-api' - -export default function MixnodesPage() { - const isMobile = useIsMobile() - const { isWalletConnected } = useWalletContext() - const { mixnodes, fetchMixnodes } = useMainContext() - const router = useRouter() - - const [itemSelectedForDelegation, setItemSelectedForDelegation] = - React.useState<{ - mixId: number - identityKey: string - }>() - const [confirmationModalProps, setConfirmationModalProps] = React.useState< - DelegationModalProps | undefined - >() - - const search = useSearchParams() - const status = search.get('status') as MixnodeStatusWithAll - - React.useEffect(() => { - // when the status changes, get the mixnodes - fetchMixnodes(toMixnodeStatus(status)) - }, [status]) - - const handleMixnodeStatusChanged = (newStatus?: MixnodeStatusWithAll) => { - router.push( - newStatus && newStatus !== 'all' - ? `/network-components/mixnodes?status=${newStatus}` - : '/network-components/mixnodes' - ) - } - - const handleOnDelegate = useCallback( - ({ identityKey, mixId }: { identityKey: string; mixId: number }) => { - if (!isWalletConnected) { - setConfirmationModalProps({ - status: 'info', - message: 'Please connect your wallet to delegate', - }) - } else { - setItemSelectedForDelegation({ identityKey, mixId }) - } - }, - [isWalletConnected] - ) - - const handleNewDelegation = (delegationModalProps: DelegationModalProps) => { - setItemSelectedForDelegation(undefined) - setConfirmationModalProps(delegationModalProps) - } - - const columns = useMemo<MRT_ColumnDef<MixnodeRowType>[]>(() => { - return [ - { - id: 'mixnode-data', - header: 'Mixnode Data', - columns: [ - { - id: 'delegate', - accessorKey: 'delegate', - size: isMobile ? 50 : 150, - header: '', - grow: false, - Cell: ({ row }) => ( - <DelegateIconButton - size="small" - onDelegate={() => - handleOnDelegate({ - identityKey: row.original.identity_key, - mixId: row.original.mix_id, - }) - } - /> - ), - enableSorting: false, - enableColumnActions: false, - Filter: () => null, - }, - { - id: 'identity_key', - header: 'Identity Key', - accessorKey: 'identity_key', - size: 250, - Cell: ({ row }) => { - return ( - <Stack direction="row" alignItems="center" gap={1}> - <CopyToClipboard - sx={{ mr: 0.5, color: 'grey.400' }} - smallIcons - value={row.original.identity_key} - tooltip={`Copy identity key ${row.original.identity_key} to clipboard`} - /> - <StyledLink - to={`/network-components/mixnodes/${row.original.mix_id}`} - color={useGetMixNodeStatusColor(row.original.status)} - dataTestId="identity-link" - > - {splice(7, 29, row.original.identity_key)} - </StyledLink> - </Stack> - ) - }, - }, - { - id: 'bond', - header: 'Stake', - accessorKey: 'bond', - Cell: ({ row }) => ( - <StyledLink - to={`/network-components/mixnodes/${row.original.mix_id}`} - color={useGetMixNodeStatusColor(row.original.status)} - > - {currencyToString({ amount: row.original.bond.toString() })} - </StyledLink> - ), - }, - { - id: 'stake_saturation', - header: 'Stake Saturation', - accessorKey: 'stake_saturation', - size: 225, - Header() { - return ( - <CustomColumnHeading - headingTitle="Stake Saturation" - tooltipInfo="Level of stake saturation for this node. Nodes receive more rewards the higher their saturation level, up to 100%. Beyond 100% no additional rewards are granted. The current stake saturation level is 940k NYMs, computed as S/K where S is target amount of tokens staked in the network and K is the number of nodes in the reward set." - /> - ) - }, - Cell: ({ row }) => ( - <StyledLink - to={`/network-components/mixnodes/${row.original.mix_id}`} - color={useGetMixNodeStatusColor(row.original.status)} - >{`${row.original.stake_saturation} %`}</StyledLink> - ), - }, - { - id: 'pledge_amount', - header: 'Bond', - accessorKey: 'pledge_amount', - size: 185, - Header: () => ( - <CustomColumnHeading - headingTitle="Bond" - tooltipInfo="Node operator's share of stake." - /> - ), - Cell: ({ row }) => ( - <StyledLink - to={`/network-components/mixnodes/${row.original.mix_id}`} - color={useGetMixNodeStatusColor(row.original.status)} - > - {currencyToString({ - amount: row.original.pledge_amount.toString(), - })} - </StyledLink> - ), - }, - { - id: 'profit_percentage', - accessorKey: 'profit_percentage', - header: 'Profit Margin', - size: 145, - Header: () => ( - <CustomColumnHeading - headingTitle="Profit Margin" - tooltipInfo="Percentage of the delegators rewards that the operator takes as fee before rewards are distributed to the delegators." - /> - ), - Cell: ({ row }) => ( - <StyledLink - to={`/network-components/mixnodes/${row.original.mix_id}`} - color={useGetMixNodeStatusColor(row.original.status)} - >{`${row.original.profit_percentage}%`}</StyledLink> - ), - }, - { - id: 'operating_cost', - accessorKey: 'operating_cost', - size: 220, - header: 'Operating Cost', - disableColumnMenu: true, - Header: () => ( - <CustomColumnHeading - headingTitle="Operating Cost" - tooltipInfo="Monthly operational cost of running this node. This cost is set by the operator and it influences how the rewards are split between the operator and delegators." - /> - ), - Cell: ({ row }) => ( - <StyledLink - to={`/network-components/mixnodes/${row.original.mix_id}`} - color={useGetMixNodeStatusColor(row.original.status)} - >{`${row.original.operating_cost} NYM`}</StyledLink> - ), - }, - { - id: 'owner', - accessorKey: 'owner', - size: 150, - header: 'Owner', - Header: () => <CustomColumnHeading headingTitle="Owner" />, - Cell: ({ row }) => ( - <StyledLink - to={`${EXPLORER_FOR_ACCOUNTS}/account/${row.original.owner}`} - color={useGetMixNodeStatusColor(row.original.status)} - target="_blank" - data-testid="big-dipper-link" - > - {splice(7, 29, row.original.owner)} - </StyledLink> - ), - }, - { - id: 'location', - accessorKey: 'location', - header: 'Location', - maxSize: 150, - Header: () => <CustomColumnHeading headingTitle="Location" />, - Cell: ({ row }) => ( - <Tooltip text={row.original.location} id="mixnode-location-text"> - <Box - sx={{ - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - cursor: 'pointer', - color: useGetMixNodeStatusColor(row.original.status), - }} - > - {row.original.location} - </Box> - </Tooltip> - ), - }, - { - id: 'host', - accessorKey: 'host', - header: 'Host', - size: 130, - Header: () => <CustomColumnHeading headingTitle="Host" />, - Cell: ({ row }) => ( - <StyledLink - color={useGetMixNodeStatusColor(row.original.status)} - to={`/network-components/mixnodes/${row.original.mix_id}`} - > - {row.original.host} - </StyledLink> - ), - }, - ], - }, - ] - }, [handleOnDelegate, isMobile]) - - const data = useMemo(() => { - return mixnodeToGridRow(mixnodes?.data) - }, [mixnodes?.data]) - - const table = useMaterialReactTable({ - columns, - data, - enableFullScreenToggle: false, - state: { - isLoading: mixnodes?.isLoading, - }, - layoutMode: 'grid-no-grow', - initialState: { - columnPinning: { left: ['delegate'] }, - }, - }) - - return ( - <DelegationsProvider> - <Box mb={2}> - <Title text="Legacy Mixnodes" /> - </Box> - <Grid container> - <Grid item xs={12}> - <Card - sx={{ - padding: 2, - height: '100%', - }} - > - <TableToolbar - childrenBefore={ - <MixNodeStatusDropdown - sx={{ mr: 2 }} - status={status} - onSelectionChanged={handleMixnodeStatusChanged} - /> - } - childrenAfter={ - isWalletConnected && ( - <Button - fullWidth - size="large" - variant="outlined" - onClick={() => router.push('/delegations')} - > - Delegations - </Button> - ) - } - /> - <MaterialReactTable table={table} /> - </Card> - </Grid> - </Grid> - {itemSelectedForDelegation && ( - <DelegateModal - onClose={() => { - setItemSelectedForDelegation(undefined) - }} - header="Delegate" - buttonText="Delegate stake" - denom="nym" - onOk={(delegationModalProps: DelegationModalProps) => - handleNewDelegation(delegationModalProps) - } - identityKey={itemSelectedForDelegation.identityKey} - mixId={itemSelectedForDelegation.mixId} - /> - )} - - {confirmationModalProps && ( - <DelegationModal - {...confirmationModalProps} - open={Boolean(confirmationModalProps)} - onClose={async () => { - setConfirmationModalProps(undefined) - if (confirmationModalProps.status === 'success') { - router.push('/delegations') - } - }} - sx={{ - width: { - xs: '90%', - sm: 600, - }, - }} - /> - )} - </DelegationsProvider> - ) -} diff --git a/explorer-nextjs/app/network-components/nodes/DeclaredRole.tsx b/explorer-nextjs/app/network-components/nodes/DeclaredRole.tsx deleted file mode 100644 index fac36689f2d..00000000000 --- a/explorer-nextjs/app/network-components/nodes/DeclaredRole.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from "react"; -import { Chip } from "@mui/material"; - -export const DeclaredRole = ({ declared_role }: { declared_role?: any }) => ( - <> - {declared_role?.mixnode && <Chip size="small" label="Mixnode" sx={{ mr: 0.5 }} color="info" />} - {declared_role?.entry && <Chip size="small" label="Entry" sx={{ mr: 0.5 }} color="success" />} - {declared_role?.exit_nr && <Chip size="small" label="Exit NR" sx={{ mr: 0.5 }} color="warning" />} - {declared_role?.exit_ipr && <Chip size="small" label="Exit IPR" sx={{ mr: 0.5 }} color="warning" />} - </> -) \ No newline at end of file diff --git a/explorer-nextjs/app/network-components/nodes/[id]/NodeDelegationsTable.tsx b/explorer-nextjs/app/network-components/nodes/[id]/NodeDelegationsTable.tsx deleted file mode 100644 index a1b754ccce6..00000000000 --- a/explorer-nextjs/app/network-components/nodes/[id]/NodeDelegationsTable.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import React, {useMemo} from "react"; -import {MaterialReactTable, MRT_ColumnDef, useMaterialReactTable} from "material-react-table"; -import StyledLink from "../../../components/StyledLink"; -import {EXPLORER_FOR_ACCOUNTS} from "@/app/api/constants"; -import {splice} from "@/app/utils"; -import {humanReadableCurrencyToString} from "@/app/utils/currency"; -import {Typography} from "@mui/material"; -import {useTheme} from "@mui/material/styles"; -import WarningIcon from '@mui/icons-material/Warning'; -import { Tooltip } from '@/app/components/Tooltip' - -export const NodeDelegationsTable = ({ node }: { node: any}) => { - const columns = useMemo<MRT_ColumnDef<any>[]>(() => { - return [ - { - id: 'nym-node-delegation-data', - header: 'Nym Node Delegations', - columns: [ - { - id: 'owner', - header: 'Delegator', - accessorKey: 'owner', - size: 150, - Cell: ({ row }) => { - return ( - <StyledLink - to={`${EXPLORER_FOR_ACCOUNTS}/account/${row.original.owner || "-"}`} - target="_blank" - data-testid="bond_information.node.owner" - color="text.primary" - > - {splice(7, 29, row.original.owner)} - </StyledLink> - ) - }, - }, - { - id: 'amount', - header: 'Amount', - accessorKey: 'amount', - size: 150, - Cell: ({ row }) => ( - <>{humanReadableCurrencyToString(row.original.amount)}</> - ) - }, - { - id: 'height', - header: 'Delegated at height', - accessorKey: 'height', - size: 150, - }, - { - id: 'proxy', - header: 'From vesting account?', - accessorKey: 'proxy', - size: 250, - Cell: ({ row }) => { - if(row.original.proxy?.length) { - return ( - <VestingDelegationWarning>Please re-delegate from your main account</VestingDelegationWarning> - ) - } - } - }, - ] - } - ]; - }, []); - - const table = useMaterialReactTable({ - columns, - data: node ? node.delegations : [], - }); - - return ( - <MaterialReactTable table={table} /> - ); -} - -export const VestingDelegationWarning = ({children, plural}: { plural?: boolean, children: React.ReactNode}) => { - const theme = useTheme(); - return ( - <Tooltip - text={`${plural ? 'These delegations have' : 'This delegation has'} been made with a vesting account. All tokens are liquid, if you are the delegator, please move the tokens into your main account and make the delegation from there.`} - id="delegations" - > - <Typography fontSize="inherit" color={theme.palette.warning.main} display="flex" alignItems="center"> - <WarningIcon sx={{ mr: 0.5 }}/> - {children} - </Typography> - </Tooltip> - ); -} \ No newline at end of file diff --git a/explorer-nextjs/app/network-components/nodes/[id]/page.tsx b/explorer-nextjs/app/network-components/nodes/[id]/page.tsx deleted file mode 100644 index 95a172d21e2..00000000000 --- a/explorer-nextjs/app/network-components/nodes/[id]/page.tsx +++ /dev/null @@ -1,336 +0,0 @@ -"use client"; - -import * as React from "react"; -import { Alert, AlertTitle, Box, CircularProgress, Grid } from "@mui/material"; -import { useParams } from "next/navigation"; -import { ColumnsType, DetailTable } from "@/app/components/DetailTable"; -import { ComponentError } from "@/app/components/ComponentError"; -import { ContentCard } from "@/app/components/ContentCard"; -import { UptimeChart } from "@/app/components/UptimeChart"; -import { NymNodeContextProvider, useNymNodeContext } from "@/app/context/node"; -import { useMainContext } from "@/app/context/main"; -import { Title } from "@/app/components/Title"; -import Paper from "@mui/material/Paper"; -import Table from "@mui/material/Table"; -import TableBody from "@mui/material/TableBody"; -import TableCell from "@mui/material/TableCell"; -import TableContainer from "@mui/material/TableContainer"; -import TableRow from "@mui/material/TableRow"; -import { humanReadableCurrencyToString } from "@/app/utils/currency"; -import { DeclaredRole } from "@/app/network-components/nodes/DeclaredRole"; -import { - NodeDelegationsTable, - VestingDelegationWarning, -} from "@/app/network-components/nodes/[id]/NodeDelegationsTable"; - -const columns: ColumnsType[] = [ - { - field: "identity_key", - title: "Identity Key", - headerAlign: "left", - width: 230, - }, - { - field: "bond", - title: "Bond", - headerAlign: "left", - }, - { - field: "host", - title: "IP", - headerAlign: "left", - width: 99, - }, - { - field: "location", - title: "Location", - headerAlign: "left", - }, - { - field: "owner", - title: "Owner", - headerAlign: "left", - }, - { - field: "version", - title: "Version", - headerAlign: "left", - }, -]; - -interface NodeEnrichedRowType { - node_id: number; - identity_key: string; - bond: string; - host: string; - location: string; - owner: string; - version: string; -} - -function nodeEnrichedToGridRow(node: any): NodeEnrichedRowType { - return { - node_id: node.node_id, - owner: node.bond_information?.owner || "", - identity_key: node.bond_information?.node?.identity_key || "", - location: node.location?.country_name || "", - bond: node.bond_information?.original_pledge.amount || 0, // TODO: format - host: node.bond_information?.node?.host || "", - version: node.description?.build_information?.build_version || "", - }; -} - -/** - * Shows nym node details - */ -const PageNymNodeDetailsWithState = ({ - selectedNymNode, -}: { - selectedNymNode?: any; -}) => { - const { uptimeHistory } = useNymNodeContext(); - const enrichedData = React.useMemo( - () => (selectedNymNode ? [nodeEnrichedToGridRow(selectedNymNode)] : []), - [] - ); - - const hasVestingContractDelegations = React.useMemo( - () => selectedNymNode?.delegations?.filter((d: any) => d.proxy)?.length, - [selectedNymNode] - ); - - return ( - <Box component="main"> - <Title text="Nym Node Detail" /> - - <Grid container mt={4}> - <Grid item xs={12}> - <DetailTable - columnsData={columns} - tableName="Node detail table" - rows={enrichedData} - /> - </Grid> - </Grid> - - <Grid container mt={2} spacing={2}> - {selectedNymNode.rewarding_details && ( - <Grid item xs={12} md={4}> - <TableContainer component={Paper}> - <Table> - <TableBody> - <TableRow> - <TableCell colSpan={2}>Delegations and Rewards</TableCell> - </TableRow> - <TableRow> - <TableCell - component="th" - scope="row" - sx={{ color: "inherit" }} - > - <strong>Operator</strong> - </TableCell> - <TableCell align="right"> - {humanReadableCurrencyToString({ - amount: - selectedNymNode.rewarding_details.operator.split( - "." - )[0], - denom: "unym", - })} - </TableCell> - </TableRow> - <TableRow> - <TableCell - component="th" - scope="row" - sx={{ color: "inherit" }} - > - <strong> - {hasVestingContractDelegations ? ( - <VestingDelegationWarning plural={true}> - Delegates ( - { - selectedNymNode.rewarding_details - .unique_delegations - }{" "} - delegates) - </VestingDelegationWarning> - ) : ( - <> - Delegates ( - { - selectedNymNode.rewarding_details - .unique_delegations - }{" "} - delegates) - </> - )} - </strong> - </TableCell> - <TableCell align="right"> - {humanReadableCurrencyToString({ - amount: - selectedNymNode.rewarding_details.delegates.split( - "." - )[0], - denom: "unym", - })} - </TableCell> - </TableRow> - <TableRow> - <TableCell - component="th" - scope="row" - sx={{ color: "inherit" }} - > - <strong>Profit margin</strong> - </TableCell> - <TableCell align="right"> - {selectedNymNode.rewarding_details.cost_params - .profit_margin_percent * 100} - % - </TableCell> - </TableRow> - <TableRow> - <TableCell - component="th" - scope="row" - sx={{ color: "inherit" }} - > - <strong>Operator costs</strong> - </TableCell> - <TableCell align="right"> - {humanReadableCurrencyToString( - selectedNymNode.rewarding_details.cost_params - .interval_operating_cost - )} - </TableCell> - </TableRow> - </TableBody> - </Table> - </TableContainer> - </Grid> - )} - - {selectedNymNode.description?.declared_role && ( - <Grid item xs={12} md={4}> - <TableContainer component={Paper}> - <Table> - <TableBody> - <TableRow> - <TableCell colSpan={2}>Node roles</TableCell> - </TableRow> - <TableRow> - <TableCell>Self declared roles</TableCell> - <TableCell> - <DeclaredRole - declared_role={ - selectedNymNode.description?.declared_role - } - /> - </TableCell> - </TableRow> - </TableBody> - </Table> - </TableContainer> - </Grid> - )} - </Grid> - - <Grid container spacing={2} mt={2}> - <Grid item xs={12} md={8}> - {uptimeHistory && ( - <ContentCard title="Routing Score"> - {uptimeHistory.error && ( - <ComponentError text="There was a problem retrieving routing score." /> - )} - <UptimeChart - loading={uptimeHistory.isLoading} - xLabel="Date" - yLabel="Daily average" - uptimeStory={uptimeHistory} - /> - </ContentCard> - )} - </Grid> - </Grid> - - <Box mt={2}> - <NodeDelegationsTable node={selectedNymNode} /> - </Box> - </Box> - ); -}; - -/** - * Guard component to handle loading and not found states - */ -const PageNymNodeDetailGuard = () => { - const [selectedNode, setSelectedNode] = React.useState<any>(); - const [isLoading, setLoading] = React.useState<boolean>(true); - const [error, setError] = React.useState<string>(); - const { fetchNodeById } = useMainContext(); - const { id } = useParams(); - - React.useEffect(() => { - setSelectedNode(undefined); - setLoading(true); - (async () => { - if (typeof id === "string") { - try { - const res = await fetchNodeById(Number.parseInt(id)); - setSelectedNode(res); - } catch (e: any) { - setError(e.message); - } finally { - setLoading(false); - } - } - })(); - }, [id, fetchNodeById]); - - if (isLoading) { - return <CircularProgress />; - } - - // loaded, but not found - if (error) { - return ( - <Alert severity="warning"> - <AlertTitle>Nym node not found</AlertTitle> - Sorry, we could not find a node with id <code>{id || ""}</code> - </Alert> - ); - } - - if (!selectedNode) { - return ( - <Alert severity="warning"> - <AlertTitle>Legacy Node</AlertTitle> - Unable to load details for the selected Nym node. - </Alert> - ); - } - - return <PageNymNodeDetailsWithState selectedNymNode={selectedNode} />; -}; - -/** - * Wrapper component that adds the node content based on the `id` in the address URL - */ -const PageNymNodeDetail = () => { - const { id } = useParams(); - - if (!id || typeof id !== "string") { - return <Alert severity="error">Oh no! Could not find that node</Alert>; - } - - return ( - <NymNodeContextProvider nymNodeId={id}> - <PageNymNodeDetailGuard /> - </NymNodeContextProvider> - ); -}; - -export default PageNymNodeDetail; diff --git a/explorer-nextjs/app/network-components/nodes/page.tsx b/explorer-nextjs/app/network-components/nodes/page.tsx deleted file mode 100644 index 75e5b97fdd0..00000000000 --- a/explorer-nextjs/app/network-components/nodes/page.tsx +++ /dev/null @@ -1,254 +0,0 @@ -'use client' - -import React, { useMemo } from 'react' -import { Box, Card, Grid, Stack, Chip } from '@mui/material' -import { useTheme } from '@mui/material/styles' -import { - MRT_ColumnDef, - MaterialReactTable, - useMaterialReactTable, -} from 'material-react-table' -import { diff, gte, rcompare } from 'semver' -import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid' -import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard' -import { Tooltip as InfoTooltip } from '@nymproject/react/tooltip/Tooltip' -import { useMainContext } from '@/app/context/main' -import { CustomColumnHeading } from '@/app/components/CustomColumnHeading' -import { Title } from '@/app/components/Title' -import { humanReadableCurrencyToString } from '@/app/utils/currency' -import { Tooltip } from '@/app/components/Tooltip' -import { EXPLORER_FOR_ACCOUNTS } from '@/app/api/constants' -import { splice } from '@/app/utils' - -import StyledLink from '@/app/components/StyledLink' -import {DeclaredRole} from "@/app/network-components/nodes/DeclaredRole"; - -function getFlagEmoji(countryCode: string) { - const codePoints = countryCode - .toUpperCase() - .split('') - .map(char => 127397 + char.charCodeAt(0)); - return String.fromCodePoint(...codePoints); -} - -const PageNodes = () => { - const [isLoading, setLoading] = React.useState(true); - const { nodes, fetchNodes } = useMainContext() - - React.useEffect(() => { - (async () => { - try { - await fetchNodes(); - } finally { - setLoading(false); - } - })(); - }, []); - - const columns = useMemo<MRT_ColumnDef<any>[]>(() => { - return [ - { - id: 'nym-node-data', - header: 'Nym Node Data', - columns: [ - { - id: 'node_id', - header: 'Node Id', - accessorKey: 'node_id', - size: 75, - }, - { - id: 'identity_key', - header: 'Identity Key', - accessorKey: 'identity_key', - size: 250, - Cell: ({ row }) => { - return ( - <Stack direction="row" alignItems="center" gap={1}> - <CopyToClipboard - sx={{ mr: 0.5, color: 'grey.400' }} - smallIcons - value={row.original.bond_information.node.identity_key} - tooltip={`Copy identity key ${row.original.bond_information.node.identity_key} to clipboard`} - /> - <StyledLink - to={`/network-components/nodes/${row.original.node_id}`} - dataTestId="identity-link" - color="text.primary" - > - {splice(7, 29, row.original.bond_information.node.identity_key)} - </StyledLink> - </Stack> - ) - }, - }, - { - id: 'version', - header: 'Version', - accessorKey: 'description.build_information.build_version', - size: 75, - Cell: ({ row }) => { - return ( - <StyledLink - to={`/network-components/nodes/${row.original.node_id}`} - data-testid="version" - color="text.primary" - > - {row.original.description?.build_information?.build_version || "-"} - </StyledLink> - ) - }, - }, - { - id: 'contract_node_type', - header: 'Kind', - accessorKey: 'contract_node_type', - size: 150, - Cell: ({ row }) => { - return ( - <StyledLink - to={`/network-components/nodes/${row.original.node_id}`} - data-testid="contract_node_type" - color="text.primary" - > - <code>{row.original.contract_node_type || "-"}</code> - </StyledLink> - ) - }, - }, - { - id: 'declared_role', - header: 'Declare Role', - accessorKey: 'description.declared_role', - size: 250, - Cell: ({ row }) => { - return ( - <Box - sx={{ justifyContent: 'flex-start', cursor: 'pointer' }} - data-testid="declared_role-button" - > - <DeclaredRole declared_role={row.original.description?.declared_role}/> - </Box> - ) - }, - }, - { - id: 'total_stake', - header: 'Total Stake', - accessorKey: 'description.total_stake', - size: 250, - Cell: ({ row }) => { - return ( - <Box - sx={{ justifyContent: 'flex-start', cursor: 'pointer' }} - data-testid="total_stake-button" - > - {humanReadableCurrencyToString({ amount: row.original.total_stake || 0, denom: "unym" })} - </Box> - ) - }, - }, - { - id: 'location', - header: 'Location', - accessorKey: 'location.country_name', - size: 75, - Cell: ({ row }) => { - return ( - <Box - sx={{ justifyContent: 'flex-start', cursor: 'pointer' }} - data-testid="location-button" - > - <Tooltip - text={row.original.location?.country_name || "-"} - id="nym-node-location-text" - > - <Box - sx={{ - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - }} - > - {row.original.location?.country_name ? <>{getFlagEmoji(row.original.location.two_letter_iso_country_code.toUpperCase())} {row.original.location.two_letter_iso_country_code}</> : <>-</> } - </Box> - </Tooltip> - </Box> - ) - }, - }, - { - id: 'host', - header: 'IP', - accessorKey: 'bond_information.node.host', - size: 150, - Cell: ({ row }) => { - return ( - <StyledLink - to={`/network-components/nodes/${row.original.node_id}`} - data-testid="host" - color="text.primary" - > - {row.original.bond_information?.node?.host || "-"} - </StyledLink> - ) - }, - }, - { - id: 'owner', - header: 'Owner', - accessorKey: 'bond_information.owner', - size: 150, - Cell: ({ row }) => { - return ( - <StyledLink - to={`${EXPLORER_FOR_ACCOUNTS}/account/${row.original.bond_information?.owner || "-"}`} - target="_blank" - data-testid="bond_information.node.owner" - color="text.primary" - > - {splice(7, 29, row.original.bond_information?.owner)} - </StyledLink> - ) - }, - }, - ], - }, - ] - }, []) - - const table = useMaterialReactTable({ - columns, - data: nodes?.data || [], - state: { - isLoading, - showLoadingOverlay: isLoading, - }, - initialState: { - isLoading: true, - showLoadingOverlay: true, - } - }) - - return ( - <> - <Box mb={2}> - <Title text="Nym Nodes" /> - </Box> - <Grid container> - <Grid item xs={12}> - <Card - sx={{ - padding: 2, - height: '100%', - }} - > - <MaterialReactTable table={table} /> - </Card> - </Grid> - </Grid> - </> - ) -} - -export default PageNodes diff --git a/explorer-nextjs/app/nodemap/page.tsx b/explorer-nextjs/app/nodemap/page.tsx deleted file mode 100644 index 674ae57a5e0..00000000000 --- a/explorer-nextjs/app/nodemap/page.tsx +++ /dev/null @@ -1,85 +0,0 @@ -'use client' - -import React, { useMemo } from 'react' -import { - Alert, - Box, - CircularProgress, - Grid, - SelectChangeEvent, - Typography, -} from '@mui/material' -import { ContentCard } from '@/app/components/ContentCard' -import { TableToolbar } from '@/app/components/TableToolbar' -import { Title } from '@/app/components/Title' -import { WorldMap } from '@/app/components/WorldMap' -import { useMainContext } from '@/app/context/main' -import { CountryDataRowType, countryDataToGridRow } from '@/app/utils' -import { - MRT_ColumnDef, - MaterialReactTable, - useMaterialReactTable, -} from 'material-react-table' - -const PageMixnodesMap = () => { - const { countryData } = useMainContext() - - const data = useMemo(() => { - return countryDataToGridRow(Object.values(countryData?.data || {})) - }, [countryData]) - - const columns = useMemo<MRT_ColumnDef<CountryDataRowType>[]>(() => { - return [ - { - id: 'delegations-data', - header: 'Global Mixnodes Data', - columns: [ - { - id: 'country-name', - header: 'Location', - accessorKey: 'countryName', - }, - { - id: 'nodes', - header: 'Nodes', - accessorKey: 'nodes', - }, - { - id: 'percentage', - header: 'Percentage', - accessorKey: 'percentage', - }, - ], - }, - ] - }, []) - - const table = useMaterialReactTable({ - columns, - data, - }) - - return ( - <Box component="main" sx={{ flexGrow: 1 }}> - <Grid> - <Grid item data-testid="mixnodes-globe"> - <Title text="Mixnodes Around the Globe" /> - </Grid> - <Grid item> - <Grid container spacing={2}> - <Grid item xs={12}> - <ContentCard title="Distribution of nodes"> - <WorldMap loading={false} countryData={countryData} /> - <Box sx={{ marginTop: 2 }} /> - <TableToolbar /> - <MaterialReactTable table={table} /> - </ContentCard> - </Grid> - </Grid> - </Grid> - </Grid> - </Box> - ) -} - -export default PageMixnodesMap diff --git a/explorer-nextjs/app/page.tsx b/explorer-nextjs/app/page.tsx deleted file mode 100644 index 2c6f9f781c1..00000000000 --- a/explorer-nextjs/app/page.tsx +++ /dev/null @@ -1,144 +0,0 @@ -'use client' - -import React, { useEffect } from 'react' -import { Box, Grid, Link, Typography } from '@mui/material' -import { useTheme } from '@mui/material/styles' -import OpenInNewIcon from '@mui/icons-material/OpenInNew' -import { PeopleAlt } from '@mui/icons-material' -import { Title } from '@/app/components/Title' -import { StatsCard } from '@/app/components/StatsCard' -import { MixnodesSVG } from '@/app/icons/MixnodesSVG' -import { Icons } from '@/app/components/Icons' -import { GatewaysSVG } from '@/app/icons/GatewaysSVG' -import { ValidatorsSVG } from '@/app/icons/ValidatorsSVG' -import { ContentCard } from '@/app/components/ContentCard' -import { WorldMap } from '@/app/components/WorldMap' -import { BLOCK_EXPLORER_BASE_URL } from '@/app/api/constants' -import { formatNumber } from '@/app/utils' -import { useMainContext } from './context/main' -import { useRouter } from 'next/navigation' - -const PageOverview = () => { - const theme = useTheme() - const router = useRouter() - - const { - summaryOverview, - gateways, - validators, - block, - countryData, - serviceProviders, - } = useMainContext() - return ( - <Box component="main" sx={{ flexGrow: 1 }}> - <Grid> - <Grid item paddingBottom={3}> - <Title text="Overview" /> - </Grid> - <Grid item> - <Grid container spacing={3}> - {summaryOverview && ( - <> - <Grid item xs={12} md={4}> - <StatsCard - onClick={() => router.push('/network-components/nodes')} - title="Nodes" - icon={<MixnodesSVG />} - count={summaryOverview.data?.nymnodes?.count || ''} - errorMsg={summaryOverview?.error} - /> - </Grid> - </> - )} - {summaryOverview && ( - <Grid item xs={12} md={4}> - <StatsCard - onClick={() => router.push('/network-components/nodes')} - title="Mixnodes" - count={summaryOverview.data?.nymnodes?.roles?.mixnode || ''} - icon={<GatewaysSVG />} - /> - </Grid> - )} - {summaryOverview && ( - <Grid item xs={12} md={4}> - <StatsCard - onClick={() => router.push('/network-components/nodes')} - title="Entry Gateways" - count={summaryOverview.data?.nymnodes?.roles?.entry || ''} - icon={<GatewaysSVG />} - /> - </Grid> - )} - {summaryOverview && ( - <Grid item xs={12} md={4}> - <StatsCard - onClick={() => router.push('/network-components/nodes')} - title="Exit Gateways" - count={summaryOverview.data?.nymnodes?.roles?.exit_ipr || ''} - icon={<GatewaysSVG />} - /> - </Grid> - )} - {summaryOverview && ( - <Grid item xs={12} md={4}> - <StatsCard - onClick={() => router.push('/network-components/nodes')} - title="SOCKS5 Network Requesters" - count={summaryOverview.data?.nymnodes?.roles?.exit_nr || ''} - icon={<GatewaysSVG />} - /> - </Grid> - )} - {validators && ( - <Grid item xs={12} md={4}> - <StatsCard - onClick={() => window.open(`${BLOCK_EXPLORER_BASE_URL}/validators`)} - title="Validators" - count={validators?.data?.count || ''} - errorMsg={validators?.error} - icon={<ValidatorsSVG />} - /> - </Grid> - )} - {block?.data && ( - <Grid item xs={12}> - <Link - href={`${BLOCK_EXPLORER_BASE_URL}/blocks`} - target="_blank" - rel="noreferrer" - underline="none" - color="inherit" - marginY={2} - paddingX={3} - paddingY={0.25} - fontSize={14} - fontWeight={600} - display="flex" - alignItems="center" - > - <Typography fontWeight="inherit" fontSize="inherit"> - Current block height is {formatNumber(block.data)} - </Typography> - <OpenInNewIcon - fontWeight="inherit" - fontSize="inherit" - sx={{ ml: 0.5 }} - /> - </Link> - </Grid> - )} - <Grid item xs={12}> - <ContentCard title="Distribution of nodes around the world"> - <WorldMap loading={false} countryData={countryData} /> - </ContentCard> - </Grid> - </Grid> - </Grid> - </Grid> - </Box> - ) -} - -export default PageOverview diff --git a/explorer-nextjs/app/providers/index.tsx b/explorer-nextjs/app/providers/index.tsx deleted file mode 100644 index 346d2fc88eb..00000000000 --- a/explorer-nextjs/app/providers/index.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react' -import CosmosKitProvider from '@/app/context/cosmos-kit' -import { WalletProvider } from '@/app/context/wallet' -import { NetworkExplorerThemeProvider } from '@/app/theme' -import { MainContextProvider } from '@/app/context/main' - -const Providers = ({ children }: { children: React.ReactNode }) => { - return ( - <MainContextProvider> - <NetworkExplorerThemeProvider> - <CosmosKitProvider> - <WalletProvider>{children}</WalletProvider> - </CosmosKitProvider> - </NetworkExplorerThemeProvider> - </MainContextProvider> - ) -} - -export { Providers } diff --git a/explorer-nextjs/app/theme/index.tsx b/explorer-nextjs/app/theme/index.tsx deleted file mode 100644 index fd072cfc648..00000000000 --- a/explorer-nextjs/app/theme/index.tsx +++ /dev/null @@ -1,15 +0,0 @@ -'use client' - -import * as React from 'react' -import { NymNetworkExplorerThemeProvider } from '@nymproject/mui-theme' -import { useMainContext } from '../context/main' - -export const NetworkExplorerThemeProvider: FCWithChildren = ({ children }) => { - const { mode } = useMainContext() - - return ( - <NymNetworkExplorerThemeProvider mode={mode}> - {children} - </NymNetworkExplorerThemeProvider> - ) -} diff --git a/explorer-nextjs/app/theme/mui-theme.d.ts b/explorer-nextjs/app/theme/mui-theme.d.ts deleted file mode 100644 index 6d5f9aabf1d..00000000000 --- a/explorer-nextjs/app/theme/mui-theme.d.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Theme, ThemeOptions, Palette, PaletteOptions } from '@mui/material/styles'; -import { NymTheme, NymPaletteWithExtensions, NymPaletteWithExtensionsOptions } from '@nymproject/mui-theme'; - -/** - * If you are unfamiliar with Material UI theming, please read the following first: - * - https://mui.com/customization/theming/ - * - https://mui.com/customization/palette/ - * - https://mui.com/customization/dark-mode/#dark-mode-with-custom-palette - * - * This file adds typings to the theme using Typescript's module augmentation. - * - * Read the following if you are unfamiliar with module augmentation and declaration merging. Then - * look at the recommendations from Material UI docs for implementation: - * - https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation - * - https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces - * - https://mui.com/customization/palette/#adding-new-colors - * - * - * IMPORTANT: - * - * The type augmentation must match MUI's definitions. So, notice the use of `interface` rather than - * `type Foo = { ... }` - this is necessary to merge the definitions. - */ - -declare module '@mui/material/styles' { - /** - * This augments the definitions of the MUI Theme with the Nym theme, as well as - * a partial `ThemeOptions` type used by `createTheme` - * - * IMPORTANT: only add extensions to the interfaces above, do not modify the lines below - */ - interface Theme extends NymTheme { } - interface ThemeOptions extends Partial<NymTheme> { } - interface Palette extends NymPaletteWithExtensions { } - interface PaletteOptions extends NymPaletteWithExtensionsOptions { } -} diff --git a/explorer-nextjs/app/typeDefs/explorer-api.ts b/explorer-nextjs/app/typeDefs/explorer-api.ts deleted file mode 100644 index b15490008d7..00000000000 --- a/explorer-nextjs/app/typeDefs/explorer-api.ts +++ /dev/null @@ -1,294 +0,0 @@ -/* eslint-disable camelcase */ - -export interface ClientConfig { - url: string; - version: string; -} - -export interface SummaryOverviewResponse { - mixnodes: { - count: number; - activeset: { - active: number; - standby: number; - inactive: number; - }; - }; - gateways: { - count: number; - }; - validators: { - count: number; - }; - nymnodes: { - count: number; - roles: { - mixnode: number; - entry: number; - exit_nr: number; - exit_ipr: number; - }; - }; -} - -export interface MixNode { - host: string; - mix_port: number; - http_api_port: number; - verloc_port: number; - sphinx_key: string; - identity_key: string; - version: string; - location: string; -} - -export interface Gateway { - host: string; - mix_port: number; - clients_port: number; - location: string; - sphinx_key: string; - identity_key: string; - version: string; -} - -export interface Amount { - denom: string; - amount: number; -} - -export enum MixnodeStatus { - active = 'active', // in both the active set and the rewarded set - standby = 'standby', // only in the rewarded set - inactive = 'inactive', // in neither the rewarded set nor the active set -} - -export enum MixnodeStatusWithAll { - active = 'active', // in both the active set and the rewarded set - standby = 'standby', // only in the rewarded set - inactive = 'inactive', // in neither the rewarded set nor the active set - all = 'all', // any status -} - -export const toMixnodeStatus = (status?: MixnodeStatusWithAll): MixnodeStatus | undefined => { - if (!status || status === MixnodeStatusWithAll.all) { - return undefined; - } - return status as unknown as MixnodeStatus; -}; - -export interface MixNodeResponseItem { - mix_id: number; - pledge_amount: Amount; - total_delegation: Amount; - owner: string; - layer: string; - status: MixnodeStatus; - location: { - country_name: string; - latitude?: number; - longitude?: number; - three_letter_iso_country_code: string; - two_letter_iso_country_code: string; - }; - mix_node: MixNode; - avg_uptime: number; - node_performance: NodePerformance; - stake_saturation: number; - uncapped_saturation: number; - operating_cost: Amount; - profit_margin_percent: string; - blacklisted: boolean; -} - -export type MixNodeResponse = MixNodeResponseItem[]; - -export interface MixNodeReportResponse { - identity: string; - owner: string; - most_recent_ipv4: boolean; - most_recent_ipv6: boolean; - last_hour_ipv4: number; - last_hour_ipv6: number; - last_day_ipv4: number; - last_day_ipv6: number; -} - -export interface StatsResponse { - update_time: Date; - previous_update_time: Date; - packets_received_since_startup: number; - packets_sent_since_startup: number; - packets_explicitly_dropped_since_startup: number; - packets_received_since_last_update: number; - packets_sent_since_last_update: number; - packets_explicitly_dropped_since_last_update: number; -} - -export interface NodePerformance { - most_recent: string; - last_hour: string; - last_24h: string; -} - -export type MixNodeHistoryResponse = StatsResponse; - -export interface GatewayBond { - block_height: number; - pledge_amount: Amount; - total_delegation: Amount; - owner: string; - gateway: Gateway; - node_performance: NodePerformance; - location?: Location; -} - -export interface GatewayBondAnnotated { - gateway_bond: GatewayBond; - node_performance: NodePerformance; -} - -export interface Location { - two_letter_iso_country_code: string; - three_letter_iso_country_code: string; - country_name: string; - latitude?: number; - longitude?: number; -} - -export interface LocatedGateway { - pledge_amount: Amount; - owner: string; - block_height: number; - gateway: Gateway; - proxy?: string; - location?: Location; -} - -export type GatewayResponse = LocatedGateway[]; - -export interface NymNodeReportResponse { - identity: string; - owner: string; - most_recent: number; - last_hour: number; - last_day: number; -} - -export interface GatewayReportResponse { - identity: string; - owner: string; - most_recent: number; - last_hour: number; - last_day: number; -} - -export type GatewayHistoryResponse = StatsResponse; - -export interface MixNodeDescriptionResponse { - name: string; - description: string; - link: string; - location: string; -} - -export type MixNodeStatsResponse = StatsResponse; - -export interface Validator { - address: string; - proposer_priority: string; - pub_key: { - type: string; - value: string; - }; -} -export interface ValidatorsResponse { - block_height: number; - count: string; - total: string; - validators: Validator[]; -} - -export type CountryData = { - ISO3: string; - nodes: number; -}; - -export type Delegation = { - owner: string; - amount: Amount; - block_height: number; -}; - -export type DelegationUniq = { - owner: string; - amount: Amount; -}; - -export type DelegationsResponse = Delegation[]; - -export type UniqDelegationsResponse = DelegationUniq[]; - -export interface CountryDataResponse { - [threeLetterCountryCode: string]: CountryData; -} - -export type BlockType = number; -export type BlockResponse = BlockType; - -export interface ApiState<RESPONSE> { - isLoading: boolean; - data?: RESPONSE; - error?: Error; -} - -export type StatusResponse = { - pending: boolean; - ports: { - 1789: boolean; - 1790: boolean; - 8000: boolean; - }; -}; - -export type UptimeTime = { - date: string; - uptime: number; -}; - -export type UptimeStoryResponse = { - history: UptimeTime[]; - identity: string; - owner: string; -}; - -export type MixNodeEconomicDynamicsStatsResponse = { - stake_saturation: number; - uncapped_saturation: number; - // TODO: when v2 will be deployed, remove cases: VeryHigh, Moderate and VeryLow - active_set_inclusion_probability: 'High' | 'Good' | 'Low'; - reserve_set_inclusion_probability: 'High' | 'Good' | 'Low'; - estimated_total_node_reward: number; - estimated_operator_reward: number; - estimated_delegators_reward: number; - current_interval_uptime: number; -}; - -export type Environment = 'mainnet' | 'sandbox' | 'qa'; - -export type ServiceProviderType = 'Network Requester'; - -export type DirectoryServiceProvider = { - id: string; - description: string; - address: string; - gateway: string; - routing_score: string | null; - service_type: ServiceProviderType; -}; - -export type DirectoryService = { - id: string; - description: string; - items: DirectoryServiceProvider[]; -}; diff --git a/explorer-nextjs/app/typeDefs/filters.ts b/explorer-nextjs/app/typeDefs/filters.ts deleted file mode 100644 index 53de60cb87a..00000000000 --- a/explorer-nextjs/app/typeDefs/filters.ts +++ /dev/null @@ -1,22 +0,0 @@ -// eslint-disable-next-line import/no-extraneous-dependencies -import { Mark } from '@mui/base'; - -export enum EnumFilterKey { - profitMargin = 'profitMargin', - stakeSaturation = 'stakeSaturation', - routingScore = 'routingScore', -} - -export type TFilterItem = { - label: string; - id: EnumFilterKey; - value: number[]; - isSmooth?: boolean; - marks: Mark[]; - min?: number; - max?: number; - scale?: (value: number) => number; - tooltipInfo?: string; -}; - -export type TFilters = { [key in EnumFilterKey]: TFilterItem }; diff --git a/explorer-nextjs/app/typeDefs/network.ts b/explorer-nextjs/app/typeDefs/network.ts deleted file mode 100644 index f8615cd9928..00000000000 --- a/explorer-nextjs/app/typeDefs/network.ts +++ /dev/null @@ -1 +0,0 @@ -export type Network = 'QA' | 'SANDBOX' | 'MAINNET'; diff --git a/explorer-nextjs/app/typeDefs/tables.ts b/explorer-nextjs/app/typeDefs/tables.ts deleted file mode 100644 index 1ab2ffead48..00000000000 --- a/explorer-nextjs/app/typeDefs/tables.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type TableHeading = { - id: string; - numeric: boolean; - disablePadding: boolean; - label: string; -}; - -export type TableHeadingsType = TableHeading[]; diff --git a/explorer-nextjs/app/typings/FC.d.ts b/explorer-nextjs/app/typings/FC.d.ts deleted file mode 100644 index 08ebdfa298a..00000000000 --- a/explorer-nextjs/app/typings/FC.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare type FCWithChildren<P = {}> = React.FC<React.PropsWithChildren<P>>; diff --git a/explorer-nextjs/app/typings/jpeg.d.ts b/explorer-nextjs/app/typings/jpeg.d.ts deleted file mode 100644 index af2ed729133..00000000000 --- a/explorer-nextjs/app/typings/jpeg.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -declare module '*.jpeg' { - const value: any; - export default value; -} - -declare module '*.jpg' { - const value: any; - export default value; -} diff --git a/explorer-nextjs/app/typings/json.d.ts b/explorer-nextjs/app/typings/json.d.ts deleted file mode 100644 index b72dd46ee5d..00000000000 --- a/explorer-nextjs/app/typings/json.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.json' { - const content: any; - export default content; -} diff --git a/explorer-nextjs/app/typings/png.d.ts b/explorer-nextjs/app/typings/png.d.ts deleted file mode 100644 index dd84df40a48..00000000000 --- a/explorer-nextjs/app/typings/png.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.png' { - const content: any; - export default content; -} diff --git a/explorer-nextjs/app/typings/react-identicons.d.ts b/explorer-nextjs/app/typings/react-identicons.d.ts deleted file mode 100644 index 6c460eff998..00000000000 --- a/explorer-nextjs/app/typings/react-identicons.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -declare module 'react-identicons' { - import * as React from 'react'; - - interface IdenticonProps { - string: string; - size?: number; - padding?: number; - bg?: string; - fg?: string; - palette?: string[]; - count?: number; - // getColor: Function; - } - - declare function Identicon(props: IdenticonProps): React.ReactElement<IdenticonProps>; - - export default Identicon; -} diff --git a/explorer-nextjs/app/typings/react-tooltip.d.ts b/explorer-nextjs/app/typings/react-tooltip.d.ts deleted file mode 100644 index 98cb6d592d2..00000000000 --- a/explorer-nextjs/app/typings/react-tooltip.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'react-tooltip'; diff --git a/explorer-nextjs/app/typings/svg.d.ts b/explorer-nextjs/app/typings/svg.d.ts deleted file mode 100644 index 091d25e2101..00000000000 --- a/explorer-nextjs/app/typings/svg.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.svg' { - const content: any; - export default content; -} diff --git a/explorer-nextjs/app/utils/currency.ts b/explorer-nextjs/app/utils/currency.ts deleted file mode 100644 index 07bdc890de7..00000000000 --- a/explorer-nextjs/app/utils/currency.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { printableCoin } from '@nymproject/nym-validator-client'; -import Big from 'big.js'; -import { DecCoin, isValidRawCoin } from '@nymproject/types'; - -const DENOM = process.env.CURRENCY_DENOM || 'unym'; -const DENOM_STAKING = process.env.CURRENCY_STAKING_DENOM || 'unyx'; - -export const toDisplay = (val: string | number | Big, dp = 4) => { - let displayValue; - try { - displayValue = Big(val).toFixed(dp); - } catch (e: any) { - console.warn(`${displayValue} not a valid decimal number: ${e}`); - } - return displayValue; -}; - -export const currencyToString = ({ amount, dp, denom = DENOM }: { amount: string; dp?: number; denom?: string }) => { - if (!dp) { - printableCoin({ - amount, - denom, - }); - } - - const [printableAmount, printableDenom] = printableCoin({ - amount, - denom, - }).split(/\s+/); - - return `${toDisplay(printableAmount, dp)} ${printableDenom}`; -}; - -function addThousandsSeparator(value: string) { - return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " "); -} - -export const humanReadableCurrencyToString = ({ amount, denom }: { amount: string, denom: string }) => { - const str = currencyToString({ amount, denom, dp: 2 }); - const parts = str.split('.'); - return [addThousandsSeparator(parts[0]), parts[1]].join('.'); -} - -export const stakingCurrencyToString = (amount: string, denom: string = DENOM_STAKING) => - printableCoin({ - amount, - denom, - }); - -/** - * Converts a decimal number to a pretty representation - * with fixed decimal places. - * - * @param val - a decimal number of string form - * @param dp - number of decimal places (4 by default ie. 0.0000) - * @returns A prettyfied decimal number - */ - -/** - * Converts a decimal number of μNYM (micro NYM) to NYM. - * - * @param unym - a decimal number of μNYM - * @param dp - number of decimal places (4 by default ie. 0.0000) - * @returns The corresponding decimal number in NYM - */ -export const unymToNym = (unym: string | number | Big, dp = 4) => { - let nym; - try { - nym = Big(unym).div(1_000_000).toFixed(dp); - } catch (e: any) { - console.warn(`${unym} not a valid decimal number: ${e}`); - } - return nym; -}; - -export const validateAmount = async ( - majorAmountAsString: DecCoin['amount'], - minimumAmountAsString: DecCoin['amount'], -): Promise<boolean> => { - // tests basic coin value requirements, like no more than 6 decimal places, value lower than total supply, etc - if (!Number(majorAmountAsString)) { - return false; - } - - if (!isValidRawCoin(majorAmountAsString)) { - return false; - } - - const majorValueFloat = parseInt(majorAmountAsString, Number(10)); - - return majorValueFloat >= parseInt(minimumAmountAsString, Number(10)); -}; - -/** - * Takes a DecCoin and prettify its amount to a representation - * with fixed decimal places. - * - * @param coin - a DecCoin - * @param dp - number of decimal places to apply to amount (4 by default ie. 0.0000) - * @returns A DecCoin with prettified amount - */ -export const decCoinToDisplay = (coin: DecCoin, dp = 4) => { - const displayCoin = { ...coin }; - try { - displayCoin.amount = Big(coin.amount).toFixed(dp); - } catch (e: any) { - console.warn(`${coin.amount} not a valid decimal number: ${e}`); - } - return displayCoin; -}; diff --git a/explorer-nextjs/app/utils/index.ts b/explorer-nextjs/app/utils/index.ts deleted file mode 100644 index e3c3e4ae19f..00000000000 --- a/explorer-nextjs/app/utils/index.ts +++ /dev/null @@ -1,124 +0,0 @@ -/* eslint-disable camelcase */ -import { MutableRefObject } from 'react'; -import { Theme } from '@mui/material/styles'; -import { registerLocale, getName } from 'i18n-iso-countries'; -import Big from 'big.js'; -import { CountryData } from '@/app/typeDefs/explorer-api'; -import { EconomicsRowsType } from '@/app/components/MixNodes/Economics/types'; -import { Network } from '../typeDefs/network'; - -registerLocale(require('i18n-iso-countries/langs/en.json')); - -export function formatNumber(num: number): string { - return new Intl.NumberFormat().format(num); -} - -export function scrollToRef(ref: MutableRefObject<HTMLDivElement | undefined>): void { - if (ref?.current) ref.current.scrollIntoView(); -} - -export type CountryDataRowType = { - id: number; - ISO3: string; - nodes: number; - countryName: string; - percentage: string; -}; - -export function countryDataToGridRow(countriesData: CountryData[]): CountryDataRowType[] { - const totalNodes = countriesData.reduce((acc, obj) => acc + obj.nodes, 0); - const formatted = countriesData.map((each: CountryData, index: number) => { - const updatedCountryRecord: CountryDataRowType = { - ...each, - id: index, - countryName: getName(each.ISO3, 'en', { select: 'alias' }), - percentage: ((each.nodes * 100) / totalNodes).toFixed(1), - }; - return updatedCountryRecord; - }); - - const sorted = formatted.sort((a, b) => (a.nodes < b.nodes ? 1 : -1)); - return sorted; -} - -export const splice = (start: number, deleteCount: number, address?: string): string => { - if (address) { - const array = address.split(''); - array.splice(start, deleteCount, '...'); - return array.join(''); - } - return ''; -}; - -export const trimAddress = (address = '', trimBy = 6) => `${address.slice(0, trimBy)}...${address.slice(-trimBy)}`; - -/** - * Converts a stringified percentage float (0.0-1.0) to a stringified integer (0-100). - * - * @param value - the percentage to convert - * @returns A stringified integer - */ -export const toPercentIntegerString = (value: string) => Math.round(Number(value) * 100).toString(); -export const toPercentInteger = (value: string) => Math.round(Number(value) * 100); - -export const textColour = (value: EconomicsRowsType, field: string, theme: Theme) => { - const progressBarValue = value?.progressBarValue || 0; - const fieldValue = value.value; - - if (progressBarValue > 100) { - return theme.palette.warning.main; - } - if (field === 'selectionChance') { - // TODO: when v2 will be deployed, remove cases: VeryHigh, Moderate and VeryLow - switch (fieldValue) { - case 'High': - case 'VeryHigh': - return theme.palette.nym.networkExplorer.selectionChance.overModerate; - case 'Good': - case 'Moderate': - return theme.palette.nym.networkExplorer.selectionChance.moderate; - case 'Low': - case 'VeryLow': - return theme.palette.nym.networkExplorer.selectionChance.underModerate; - default: - return theme.palette.nym.wallet.fee; - } - } - return theme.palette.nym.wallet.fee; -}; - -export const isGreaterThan = (a: number, b: number) => a > b; - -export const isLessThan = (a: number, b: number) => a < b; - -/** - * - * Checks if the user's balance is enough to pay the fee - * @param balance - The user's current balance - * @param fee - The fee for the tx - * @param tx - The amount of the tx - * @returns boolean - * - */ - -export const isBalanceEnough = (fee: string, tx: string = '0', balance: string = '0') => { - console.log('balance', balance, fee, tx); - try { - return Big(balance).gte(Big(fee).plus(Big(tx))); - } catch (e) { - console.log(e); - return false; - } -}; - -export const urls = (networkName?: Network) => - networkName === 'MAINNET' - ? { - mixnetExplorer: 'https://mixnet.explorers.guru/', - blockExplorer: 'https://blocks.nymtech.net', - networkExplorer: 'https://explorer.nymtech.net', - } - : { - blockExplorer: `https://${networkName}-blocks.nymtech.net`, - networkExplorer: `https://${networkName}-explorer.nymtech.net`, - }; diff --git a/explorer-nextjs/next.config.mjs b/explorer-nextjs/next.config.mjs deleted file mode 100644 index d6422901450..00000000000 --- a/explorer-nextjs/next.config.mjs +++ /dev/null @@ -1,14 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = { - async redirects() { - return [ - { - source: '/network-components/mixnode/:id', // Match the old URL - destination: '/network-components/nodes/:id', // Redirect to the new URL - permanent: true, - }, - ]; - }, -}; - -export default nextConfig; diff --git a/explorer-nextjs/package.json b/explorer-nextjs/package.json deleted file mode 100644 index 555749547b7..00000000000 --- a/explorer-nextjs/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "@nymproject/network-explorer", - "version": "1.0.0", - "scripts": { - "dev": "next dev", - "build": "next build", - "build:prod": "yarn --cwd .. build && next build", - "start": "next start", - "lint": "next lint" - }, - "dependencies": { - "@nymproject/react": "^1.0.0", - "@nymproject/nym-validator-client": "0.18.0", - "next": "14.2.26", - "react": "^18", - "react-dom": "^18", - "react-error-boundary": "^4.0.13", - "material-react-table": "^2.12.1", - "@mui/x-date-pickers": "7.1.1", - "@mui/x-data-grid": "7.1.1", - "@mui/x-charts": "^7.22.3" - }, - "devDependencies": { - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", - "eslint": "^8", - "eslint-config-next": "14.1.4", - "typescript": "^5" - } -} diff --git a/explorer-nextjs/public/favicon.ico b/explorer-nextjs/public/favicon.ico deleted file mode 100644 index bc951a1c6f2..00000000000 Binary files a/explorer-nextjs/public/favicon.ico and /dev/null differ diff --git a/explorer-nextjs/public/next.svg b/explorer-nextjs/public/next.svg deleted file mode 100644 index 5174b28c565..00000000000 --- a/explorer-nextjs/public/next.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg> \ No newline at end of file diff --git a/explorer-nextjs/public/vercel.svg b/explorer-nextjs/public/vercel.svg deleted file mode 100644 index d2f84222734..00000000000 --- a/explorer-nextjs/public/vercel.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg> \ No newline at end of file diff --git a/explorer-nextjs/tsconfig.json b/explorer-nextjs/tsconfig.json deleted file mode 100644 index 701d0e69846..00000000000 --- a/explorer-nextjs/tsconfig.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "compilerOptions": { - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "CommonJS", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], - "paths": { - "@/*": [ - "./*" - ], - "@assets/*": [ - "../assets/*" - ] - }, - "moduleResolution": "node", - "target": "ES2017" - }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - ".next/types/**/*.ts" - ], - "exclude": [ - "node_modules" - ] -} diff --git a/explorer/.babelrc b/explorer/.babelrc deleted file mode 100644 index 85e1f1ba26e..00000000000 --- a/explorer/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["@babel/env", "@babel/react"] -} \ No newline at end of file diff --git a/explorer/.editorconfig b/explorer/.editorconfig deleted file mode 100644 index c35daeee9be..00000000000 --- a/explorer/.editorconfig +++ /dev/null @@ -1,18 +0,0 @@ -# See http://editorconfig.org/ -# EditorConfig helps developers define and maintain consistent coding styles -# between different editors and IDEs. The EditorConfig project consists of a -# file format for defining coding styles and a collection of text editor plugins -# that enable editors to read the file format and adhere to defined styles. -# EditorConfig files are easily readable and they work nicely with version -# control systems. - -[*] -indent_style = space -indent_size = 2 -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.md] -trim_trailing_whitespace = false diff --git a/explorer/.env.dev b/explorer/.env.dev deleted file mode 100644 index 3cc86ae00ca..00000000000 --- a/explorer/.env.dev +++ /dev/null @@ -1,9 +0,0 @@ -# When running the explorer API locally -#EXPLORER_API_URL=http://localhost:8000/v1 - -EXPLORER_API_URL=https://sandbox-explorer.nymtech.net/api/v1 -NYM_API_URL=https://sandbox-nym-api1.nymtech.net -VALIDATOR_URL=https://rpc.sandbox.nymtech.net -BIG_DIPPER_URL=https://sandbox-blocks.nymtech.net -CURRENCY_DENOM=unym -CURRENCY_STAKING_DENOM=unyx diff --git a/explorer/.env.prod b/explorer/.env.prod deleted file mode 100644 index 2e927b29479..00000000000 --- a/explorer/.env.prod +++ /dev/null @@ -1,6 +0,0 @@ -EXPLORER_API_URL=https://explorer.nymtech.net/api/v1 -NYM_API_URL=https://validator.nymtech.net -VALIDATOR_URL=https://rpc.nymtech.net -BIG_DIPPER_URL=https://blocks.nymtech.net -CURRENCY_DENOM=unym -CURRENCY_STAKING_DENOM=unyx \ No newline at end of file diff --git a/explorer/.env.qa b/explorer/.env.qa deleted file mode 100644 index dd7052ce4d4..00000000000 --- a/explorer/.env.qa +++ /dev/null @@ -1,6 +0,0 @@ -EXPLORER_API_URL=https://qa-explorer.nymtech.net/api/v1 -NYM_API_URL=https://qa-validator-api.nymtech.net -VALIDATOR_URL=https://qa-validator.nymtech.net -BIG_DIPPER_URL=https://qa-blocks.nymtech.net -CURRENCY_DENOM=unym -CURRENCY_STAKING_DENOM=unyx diff --git a/explorer/.eslintrc.js b/explorer/.eslintrc.js deleted file mode 100644 index 5feba990843..00000000000 --- a/explorer/.eslintrc.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - extends: [ - '@nymproject/eslint-config-react-typescript' - ], - overrides: [ - { - files: ['*.ts'], - parserOptions: { - project: 'tsconfig.json', - tsconfigRootDir: __dirname, - } - } - ] -} diff --git a/explorer/.gitignore b/explorer/.gitignore deleted file mode 100644 index b8b1827577e..00000000000 --- a/explorer/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -dist -.DS_Store -detailAPI.md -!.env.dev diff --git a/explorer/.nvmrc b/explorer/.nvmrc deleted file mode 100644 index 3c032078a4a..00000000000 --- a/explorer/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -18 diff --git a/explorer/.prettierrc b/explorer/.prettierrc deleted file mode 100644 index ccf75b89de0..00000000000 --- a/explorer/.prettierrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "trailingComma": "all", - "singleQuote": true, - "printWidth": 120, - "tabWidth": 2 -} diff --git a/explorer/.storybook/main.js b/explorer/.storybook/main.js deleted file mode 100644 index 1c2a975321f..00000000000 --- a/explorer/.storybook/main.js +++ /dev/null @@ -1,63 +0,0 @@ -/* eslint-disable no-param-reassign */ -const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); -const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); - -module.exports = { - stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], - addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'], - framework: '@storybook/react', - core: { - builder: 'webpack5', - }, - // webpackFinal: async (config, { configType }) => { - // // `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION' - // // You can change the configuration based on that. - // // 'PRODUCTION' is used when building the static version of storybook. - webpackFinal: async (config) => { - config.module.rules.forEach((rule) => { - // look for SVG import rule and replace - // NOTE: the rule before modification is /\.(svg|ico|jpg|jpeg|png|apng|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/ - if (rule.test?.toString().includes('svg')) { - rule.test = /\.(ico|jpg|jpeg|png|apng|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/; - } - }); - - // handle asset loading with this - config.module.rules.unshift({ - test: /\.svg(\?.*)?$/i, - issuer: /\.[jt]sx?$/, - use: ['@svgr/webpack'], - }); - - config.resolve.extensions = ['.tsx', '.ts', '.js']; - config.resolve.plugins = [new TsconfigPathsPlugin()]; - - config.resolve.fallback = { - fs: false, - tls: false, - path: false, - http: false, - https: false, - stream: false, - crypto: false, - net: false, - zlib: false, - }; - - config.plugins.push(new ForkTsCheckerWebpackPlugin({ - typescript: { - mode: 'write-references', - diagnosticOptions: { - semantic: true, - syntactic: true, - }, - }, - })); - - // Return the altered config - return config; - }, - features: { - emotionAlias: false, - }, -}; diff --git a/explorer/.storybook/preview.js b/explorer/.storybook/preview.js deleted file mode 100644 index 5d97f3b5ab7..00000000000 --- a/explorer/.storybook/preview.js +++ /dev/null @@ -1,56 +0,0 @@ -/* eslint-disable react/react-in-jsx-scope */ -import { NymNetworkExplorerThemeProvider } from '@nymproject/mui-theme'; -import { Box } from '@mui/material'; - -export const parameters = { - actions: { argTypesRegex: "^on[A-Z].*" }, - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/, - }, - }, -} - -const withThemeProvider = (Story, context) => ( - <div style={{ display: 'grid', height: '100%', gridTemplateColumns: '50% 50%' }}> - <div> - <NymNetworkExplorerThemeProvider mode="light"> - <Box - p={4} - sx={{ - display: 'grid', - gridTemplateRows: '80vh 2rem', - background: (theme) => theme.palette.background.default, - color: (theme) => theme.palette.text.primary, - }} - > - <Box sx={{ overflowY: 'auto' }}> - <Story {...context} /> - </Box> - <h4 style={{ textAlign: 'center' }}>Light mode</h4> - </Box> - </NymNetworkExplorerThemeProvider> - </div> - <div> - <NymNetworkExplorerThemeProvider mode="dark"> - <Box - p={4} - sx={{ - display: 'grid', - gridTemplateRows: '80vh 2rem', - background: (theme) => theme.palette.background.default, - color: (theme) => theme.palette.text.primary, - }} - > - <Box sx={{ overflowY: 'auto' }}> - <Story {...context} /> - </Box> - <h4 style={{ textAlign: 'center' }}>Dark mode</h4> - </Box> - </NymNetworkExplorerThemeProvider> - </div> - </div> -); - -export const decorators = [withThemeProvider]; diff --git a/explorer/.vscode/settings.json b/explorer/.vscode/settings.json deleted file mode 100644 index 246e9c6e897..00000000000 --- a/explorer/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "editor.codeActionsOnSave": { - "source.fixAll.eslint": true - } -} diff --git a/explorer/CHANGELOG.md b/explorer/CHANGELOG.md deleted file mode 100644 index 8446a3c5b2b..00000000000 --- a/explorer/CHANGELOG.md +++ /dev/null @@ -1,47 +0,0 @@ -## UNRELEASED - -- nothing yet - -## [nym-explorer-v1.0.6](https://github.com/nymtech/nym/tree/nym-explorer-v1.0.6) (2023-02-21) - -- Allow user to filter gateways but current and old versions -- Add copy buttons to gateway identity keys - -## [nym-explorer-v1.0.5](https://github.com/nymtech/nym/tree/nym-explorer-v1.0.5) (2023-02-14) - -- NE - link `Owner` field on the node detail page to the account details on NG explorer ([#2923]) -- NE - Upgrade Sandbox and make below changes: ([#2332]) - -[#2923]: https://github.com/nymtech/nym/issues/2923 -[#2332]: https://github.com/nymtech/nym/issues/2332 - -## [nym-explorer-v1.0.4](https://github.com/nymtech/nym/tree/nym-explorer-v1.0.4) (2023-01-31) - -- Add routing score on gateway list ([#2913]) -- Add gateway's last Routing Score to the gateways list page ([#2186]) -- Upgrade Sandbox and make below changes: ([#2332]) - -[#2913]: https://github.com/nymtech/nym/pull/2913 -[#2186]: https://github.com/nymtech/nym/issues/2186 -[#2332]: https://github.com/nymtech/nym/issues/2332 - -## [nym-explorer-v1.0.3](https://github.com/nymtech/nym/tree/nym-explorer-v1.0.3) (2023-01-24) - -- Stake Saturation tooltip on node list and node pages updated ([#2877]) -- Sandbox Upgrade : Name change from "Network Explorer" to "Sandbox Explorer", button to mainnet explorer and link to faucet ([#2332)]) - -[#2877]: https://github.com/nymtech/nym/issues/2877 -[#2332]: https://github.com/nymtech/nym/issues/2332 - -## [nym-explorer-v1.0.2](https://github.com/nymtech/nym/tree/nym-explorer-v1.0.2) (2023-01-17) - -- changing the explorers guru link ([#2820]) - -[#2820]: https://github.com/nymtech/nym/pull/2820 - -## [nym-explorer-v1.0.1](https://github.com/nymtech/nym/tree/nym-explorer-v1.0.1) (2023-01-10) - -- Feat/2161 ne gate version by @gala1234 in https://github.com/nymtech/nym/pull/2743 -- fix(explorer): set gateway bond 6 decimals by @doums in https://github.com/nymtech/nym/pull/2741 -- Feat/2130 tables update rebase by @gala1234 in https://github.com/nymtech/nym/pull/2742 -- fix(explorer,explorer-api): mixnode location by @doums in https://github.com/nymtech/nym-api diff --git a/explorer/README.md b/explorer/README.md deleted file mode 100644 index a7bbc2346a5..00000000000 --- a/explorer/README.md +++ /dev/null @@ -1,77 +0,0 @@ -# Nym Network Explorer - -The network explorer lets you explore the Nym network. - -## Getting started - -You will need: - -- NodeJS (use `nvm install` to automatically install the correct version) -- `npm` -- `yarn` - -> **Note**: This project ipart of a mono repo, so you will need to build the shared packages before starting. And any time they change, you'll need to rebuild them. - -From the [root of the repository](../README.md) run the following to build shared packages: - -``` -yarn -yarn build -``` - -From the `explorer` directory of the `nym` monorepo, run: - -``` -cd explorer -yarn start -``` - -You can then open a browser to http://localhost:3000 and start development. - -## Development - -Documentation for developers [can be found here](./docs). - -Several environment variables are required. They can be -provisioned via a `.env` file. For convenience a `.env.dev` is -provided, just copy its content into `.env`. - -#### Required env vars - -``` -EXPLORER_API_URL -NYM_API_URL -VALIDATOR_URL -BIG_DIPPER_URL -CURRENCY_DENOM -CURRENCY_STAKING_DENOM -``` - -## Deployment - -Build the UI with (starting in the repository root): - -``` -yarn -yarn build -cd explorer -yarn build -``` - -The output will be in the `dist` directory. Serve this with `nginx` or `httpd`. - -Make sure you have built the [explorer-api](./explorer-api) and are running it as a service proxied through -`nginx` or `httpd` so that both the UI and API are running on the same host. - -## License - -Please see the [project README](./README.md) and the [LICENSES directory](../LICENSES) for license details for all Nym software. - -## Contributing - -If you would like to contribute to the Network Explorer send us a PR or -[raise an issue on GitHub](https://github.com/nymtech/nym/issues) and tag them with `network-explorer`. - -## Development - -Please see [development docs](./docs) here for more information on the structure and design of this app. diff --git a/explorer/docs/README.md b/explorer/docs/README.md deleted file mode 100644 index bb0d0be99a2..00000000000 --- a/explorer/docs/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# Nym Network Explorer - Development Docs - -## Getting started - -You will need: - -- NodeJS -- `nvm` - -We use the following: - -- Typescript -- `eslint` -- `webpack` -- `jest` -- `react-material-ui` -- `react` 17 - -## Development mode - -Copy the `.env.prod` file to `.env` to configure your environment. Using the live sandbox Explorer API is the best way to do development, so the prod settings are good. - -Run the following: - -``` -npm install -npm run start -``` - -A development server with hot reloading will be running on http://localhost:3000. - -## Linting - -`eslint` and `prettier` are configured. - -You can lint the code by running: - -``` -npm run lint -``` - -> **Note:** this will only show linting errors and will not fix them - -To fix all linting errors automatically run: - -``` -npm run lint:fix -``` diff --git a/explorer/jest.config.js b/explorer/jest.config.js deleted file mode 100644 index e86e13bab91..00000000000 --- a/explorer/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', -}; diff --git a/explorer/package.json b/explorer/package.json deleted file mode 100644 index d2426f61224..00000000000 --- a/explorer/package.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "name": "@nym/network-explorer", - "version": "1.0.7", - "private": true, - "license": "Apache-2.0", - "scripts": { - "start": "webpack serve --progress --port 3000", - "build": "webpack build --progress --config webpack.prod.js", - "ci:dev": "echo 'Building CI for branch preview...' && yarn --cwd .. build && cp .env.dev .env && yarn build", - "ci:prod": "echo 'Building CI for prod preview...' && yarn --cwd .. build && cp .env.prod .env && yarn build", - "ci": "[ \"$CI_PROD\" = true ] && yarn ci:prod || yarn ci:dev", - "build:serve": "npx serve dist", - "test": "jest", - "test:watch": "jest --watch", - "tsc": "tsc --noEmit true", - "tsc:watch": "tsc --watch --noEmit true", - "lint": "eslint src", - "lint:fix": "eslint src --fix", - "prestorybook": "yarn --cwd .. build", - "storybook": "start-storybook -p 6006", - "storybook:build": "build-storybook" - }, - "dependencies": { - "@chain-registry/types": "^0.18.0", - "@cosmjs/cosmwasm-stargate": "^0.32.0", - "@cosmjs/crypto": "^0.32.0", - "@cosmjs/encoding": "^0.32.0", - "@cosmjs/math": "^0.26.2", - "@cosmjs/stargate": "^0.32.0", - "@cosmjs/tendermint-rpc": "^0.32.0", - "@cosmos-kit/core": "^2.8.9", - "@cosmos-kit/keplr-extension": "^2.7.9", - "@cosmos-kit/react": "^2.10.11", - "@emotion/react": "^11.4.1", - "@emotion/styled": "^11.3.0", - "@interchain-ui/react": "^1.14.2", - "@mui/icons-material": "^5.0.0", - "@mui/material": "^5.0.1", - "@mui/styles": "^5.0.1", - "@mui/system": "^5.0.1", - "@mui/x-data-grid": "^5.0.0-beta.5", - "@nymproject/contract-clients": "1.2.4-rc.1", - "@nymproject/mui-theme": "^1.0.0", - "@nymproject/node-tester": "^1.0.0", - "@nymproject/nym-validator-client": "^0.18.0", - "@nymproject/react": "^1.0.0", - "@nymproject/types": "^1.0.0", - "@tauri-apps/api": "^1.5.1", - "big.js": "^6.2.1", - "bs58": "^5.0.0", - "buffer": "^6.0.3", - "chain-registry": "^1.29.1", - "cosmjs-types": "^0.9.0", - "d3-scale": "^4.0.0", - "date-fns": "^2.24.0", - "i18n-iso-countries": "^6.8.0", - "lodash": "^4.17.21", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-error-boundary": "^3.1.4", - "react-google-charts": "^3.0.15", - "react-identicons": "^1.2.5", - "react-router-dom": "6", - "react-simple-maps": "^2.3.0", - "react-tooltip": "^4.2.21", - "semver": "^7.3.8", - "use-clipboard-copy": "^0.2.0" - }, - "devDependencies": { - "@babel/core": "^7.15.0", - "@nymproject/eslint-config-react-typescript": "^1.0.0", - "@pmmmwh/react-refresh-webpack-plugin": "^0.5.4", - "@storybook/addon-actions": "^6.5.8", - "@storybook/addon-essentials": "^6.5.8", - "@storybook/addon-interactions": "^6.5.8", - "@storybook/addon-links": "^6.5.8", - "@storybook/react": "^6.5.15", - "@storybook/testing-library": "^0.0.9", - "@svgr/webpack": "^6.1.1", - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^12.0.0", - "@types/d3-fetch": "^3.0.1", - "@types/d3-geo": "^3.0.2", - "@types/d3-scale": "^4.0.1", - "@types/geojson": "^7946.0.8", - "@types/jest": "^27.0.1", - "@types/node": "^16.7.13", - "@types/react": "^18.0.26", - "@types/react-dom": "^18.0.10", - "@types/react-simple-maps": "^1.0.6", - "@types/react-tooltip": "^4.2.4", - "@types/topojson-client": "^3.1.0", - "@typescript-eslint/eslint-plugin": "^5.13.0", - "@typescript-eslint/parser": "^5.13.0", - "babel-loader": "^8.3.0", - "babel-plugin-root-import": "^6.6.0", - "clean-webpack-plugin": "^4.0.0", - "css-loader": "^6.7.3", - "css-minimizer-webpack-plugin": "^3.0.2", - "dotenv-webpack": "^7.0.3", - "eslint": "^8.10.0", - "eslint-config-airbnb": "^19.0.4", - "eslint-config-airbnb-typescript": "^16.1.0", - "eslint-config-prettier": "^8.5.0", - "eslint-import-resolver-root-import": "^1.0.4", - "eslint-plugin-import": "^2.25.4", - "eslint-plugin-jest": "^26.1.1", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-prettier": "^4.0.0", - "eslint-plugin-react": "^7.29.2", - "eslint-plugin-react-hooks": "^4.3.0", - "eslint-plugin-storybook": "^0.5.12", - "favicons-webpack-plugin": "^5.0.2", - "file-loader": "^6.2.0", - "fork-ts-checker-webpack-plugin": "^7.2.1", - "html-webpack-plugin": "^5.3.2", - "jest": "^27.1.0", - "mini-css-extract-plugin": "^2.2.2", - "prettier": "^2.8.7", - "react-refresh": "^0.10.0", - "react-refresh-typescript": "^2.0.2", - "style-loader": "^3.3.1", - "ts-jest": "^27.0.5", - "ts-loader": "^9.4.2", - "tsconfig-paths-webpack-plugin": "^3.5.2", - "typescript": "^4.6.2", - "url-loader": "^4.1.1", - "webpack": "^5.75.0", - "webpack-cli": "^4.8.0", - "webpack-dev-server": "^4.5.0", - "webpack-favicons": "^1.3.8", - "webpack-merge": "^5.8.0" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -} diff --git a/explorer/src/App.tsx b/explorer/src/App.tsx deleted file mode 100644 index 4e6fcc41e87..00000000000 --- a/explorer/src/App.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import * as React from 'react'; -import { Nav } from './components/Nav'; -import { MobileNav } from './components/MobileNav'; -import { Routes } from './routes/index'; -import { useIsMobile } from './hooks/useIsMobile'; - -export const App: FCWithChildren = () => { - const isMobile = useIsMobile(); - - if (isMobile) { - return ( - <MobileNav> - <Routes /> - </MobileNav> - ); - } - return ( - <Nav> - <Routes /> - </Nav> - ); -}; diff --git a/explorer/src/api/constants.ts b/explorer/src/api/constants.ts deleted file mode 100644 index fbb8c18d6b8..00000000000 --- a/explorer/src/api/constants.ts +++ /dev/null @@ -1,31 +0,0 @@ -// master APIs -export const API_BASE_URL = process.env.EXPLORER_API_URL; -export const NYM_API_BASE_URL = process.env.NYM_API_URL; -export const VALIDATOR_BASE_URL = process.env.VALIDATOR_URL || 'https://rpc.nymtech.net'; -export const BIG_DIPPER = process.env.BIG_DIPPER_URL; - -// specific API routes -export const OVERVIEW_API = `${API_BASE_URL}/overview`; -export const MIXNODE_PING = `${API_BASE_URL}/ping`; -export const MIXNODES_API = `${API_BASE_URL}/mix-nodes`; -export const MIXNODE_API = `${API_BASE_URL}/mix-node`; -export const GATEWAYS_EXPLORER_API = `${API_BASE_URL}/gateways`; -export const GATEWAYS_API = `${NYM_API_BASE_URL}/api/v1/status/gateways/detailed`; -export const VALIDATORS_API = `${VALIDATOR_BASE_URL}/validators`; -export const BLOCK_API = `${NYM_API_BASE_URL}/block`; -export const COUNTRY_DATA_API = `${API_BASE_URL}/countries`; -export const UPTIME_STORY_API = `${NYM_API_BASE_URL}/api/v1/status/mixnode`; // add ID then '/history' to this. -export const UPTIME_STORY_API_GATEWAY = `${NYM_API_BASE_URL}/api/v1/status/gateway`; // add ID then '/history' or '/report' to this -export const SERVICE_PROVIDERS = `${API_BASE_URL}/service-providers`; - -// errors -export const MIXNODE_API_ERROR = "We're having trouble finding that record, please try again or Contact Us."; - -export const NYM_WEBSITE = 'https://nymtech.net'; - -export const NYM_BIG_DIPPER = 'https://mixnet.explorers.guru'; - -export const NYM_MIXNET_CONTRACT = - process.env.NYM_MIXNET_CONTRACT || 'n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr'; -export const COSMOS_KIT_USE_CHAIN = process.env.COSMOS_KIT_USE_CHAIN || 'sandbox'; -export const WALLET_CONNECT_PROJECT_ID = process.env.WALLET_CONNECT_PROJECT_ID || ''; diff --git a/explorer/src/api/index.ts b/explorer/src/api/index.ts deleted file mode 100644 index a2b134d4aeb..00000000000 --- a/explorer/src/api/index.ts +++ /dev/null @@ -1,173 +0,0 @@ -import keyBy from 'lodash/keyBy'; -import { - API_BASE_URL, - BLOCK_API, - COUNTRY_DATA_API, - GATEWAYS_API, - UPTIME_STORY_API_GATEWAY, - MIXNODE_API, - MIXNODE_PING, - MIXNODES_API, - OVERVIEW_API, - UPTIME_STORY_API, - VALIDATORS_API, - SERVICE_PROVIDERS, - GATEWAYS_EXPLORER_API, -} from './constants'; - -import { - CountryDataResponse, - DelegationsResponse, - UniqDelegationsResponse, - GatewayReportResponse, - UptimeStoryResponse, - MixNodeDescriptionResponse, - MixNodeResponse, - MixNodeResponseItem, - MixnodeStatus, - MixNodeEconomicDynamicsStatsResponse, - StatsResponse, - StatusResponse, - SummaryOverviewResponse, - ValidatorsResponse, - Environment, - GatewayBondAnnotated, - GatewayBond, - DirectoryServiceProvider, - LocatedGateway, -} from '../typeDefs/explorer-api'; - -function getFromCache(key: string) { - const ts = Number(localStorage.getItem('ts')); - const hasExpired = Date.now() - ts > 5000; - const curr = localStorage.getItem(key); - if (curr && !hasExpired) { - return JSON.parse(curr); - } - return undefined; -} - -function storeInCache(key: string, data: any) { - localStorage.setItem(key, data); - localStorage.setItem('ts', Date.now().toString()); -} - -export class Api { - static fetchOverviewSummary = async (): Promise<SummaryOverviewResponse> => { - const cache = getFromCache('overview-summary'); - if (cache) { - return cache; - } - const res = await fetch(`${OVERVIEW_API}/summary`); - const json = await res.json(); - storeInCache('overview-summary', JSON.stringify(json)); - return json; - }; - - static fetchMixnodes = async (): Promise<MixNodeResponse> => { - const cachedMixnodes = getFromCache('mixnodes'); - if (cachedMixnodes) { - return cachedMixnodes; - } - - const res = await fetch(MIXNODES_API); - const json = await res.json(); - storeInCache('mixnodes', JSON.stringify(json)); - return json; - }; - - static fetchMixnodesActiveSetByStatus = async (status: MixnodeStatus): Promise<MixNodeResponse> => { - const cachedMixnodes = getFromCache(`mixnodes-${status}`); - if (cachedMixnodes) { - return cachedMixnodes; - } - const res = await fetch(`${MIXNODES_API}/active-set/${status}`); - const json = await res.json(); - storeInCache(`mixnodes-${status}`, JSON.stringify(json)); - return json; - }; - - static fetchMixnodeByID = async (id: string): Promise<MixNodeResponseItem | undefined> => { - const response = await fetch(`${MIXNODE_API}/${id}`); - - // when the mixnode is not found, returned undefined - if (response.status === 404) { - return undefined; - } - - return response.json(); - }; - - static fetchGateways = async (): Promise<GatewayBond[]> => { - const res = await fetch(GATEWAYS_API); - const gatewaysAnnotated: GatewayBondAnnotated[] = await res.json(); - const res2 = await fetch(GATEWAYS_EXPLORER_API); - const locatedGateways: LocatedGateway[] = await res2.json(); - const locatedGatewaysByOwner = keyBy(locatedGateways, 'owner'); - return gatewaysAnnotated.map(({ gateway_bond, node_performance }) => ({ - ...gateway_bond, - node_performance, - location: locatedGatewaysByOwner[gateway_bond.owner]?.location, - })); - }; - - static fetchGatewayUptimeStoryById = async (id: string): Promise<UptimeStoryResponse> => - (await fetch(`${UPTIME_STORY_API_GATEWAY}/${id}/history`)).json(); - - static fetchGatewayReportById = async (id: string): Promise<GatewayReportResponse> => - (await fetch(`${UPTIME_STORY_API_GATEWAY}/${id}/report`)).json(); - - static fetchValidators = async (): Promise<ValidatorsResponse> => { - const res = await fetch(VALIDATORS_API); - const json = await res.json(); - return json.result; - }; - - static fetchBlock = async (): Promise<number> => { - const res = await fetch(BLOCK_API); - const json = await res.json(); - const { height } = json.result.block.header; - return height; - }; - - static fetchCountryData = async (): Promise<CountryDataResponse> => { - const result: CountryDataResponse = {}; - const res = await fetch(COUNTRY_DATA_API); - const json = await res.json(); - Object.keys(json).forEach((ISO3) => { - result[ISO3] = { ISO3, nodes: json[ISO3] }; - }); - return result; - }; - - static fetchDelegationsById = async (id: string): Promise<DelegationsResponse> => - (await fetch(`${MIXNODE_API}/${id}/delegations`)).json(); - - static fetchUniqDelegationsById = async (id: string): Promise<UniqDelegationsResponse> => - (await fetch(`${MIXNODE_API}/${id}/delegations/summed`)).json(); - - static fetchStatsById = async (id: string): Promise<StatsResponse> => - (await fetch(`${MIXNODE_API}/${id}/stats`)).json(); - - static fetchMixnodeDescriptionById = async (id: string): Promise<MixNodeDescriptionResponse> => - (await fetch(`${MIXNODE_API}/${id}/description`)).json(); - - static fetchMixnodeEconomicDynamicsStatsById = async (id: string): Promise<MixNodeEconomicDynamicsStatsResponse> => - (await fetch(`${MIXNODE_API}/${id}/economic-dynamics-stats`)).json(); - - static fetchStatusById = async (id: string): Promise<StatusResponse> => (await fetch(`${MIXNODE_PING}/${id}`)).json(); - - static fetchUptimeStoryById = async (id: string): Promise<UptimeStoryResponse> => - (await fetch(`${UPTIME_STORY_API}/${id}/history`)).json(); - - static fetchServiceProviders = async (): Promise<DirectoryServiceProvider[]> => { - const res = await fetch(SERVICE_PROVIDERS); - const json = await res.json(); - return json; - }; -} - -export const getEnvironment = (): Environment => { - const matchEnv = (env: Environment) => API_BASE_URL?.toLocaleLowerCase().includes(env) && env; - return matchEnv('sandbox') || matchEnv('qa') || 'mainnet'; -}; diff --git a/explorer/src/assets/world-110m.json b/explorer/src/assets/world-110m.json deleted file mode 100644 index 5c999c82ca2..00000000000 --- a/explorer/src/assets/world-110m.json +++ /dev/null @@ -1,39718 +0,0 @@ -{ - "type": "Topology", - "arcs": [ - [ - [ - 16814, - 15074 - ], - [ - 71, - -45 - ], - [ - 53, - 16 - ], - [ - 15, - 54 - ], - [ - 55, - 18 - ], - [ - 39, - 37 - ], - [ - 14, - 95 - ], - [ - 59, - 24 - ], - [ - 11, - 42 - ], - [ - 32, - -32 - ], - [ - 21, - -3 - ] - ], - [ - [ - 17184, - 15280 - ], - [ - 39, - -1 - ], - [ - 53, - -26 - ] - ], - [ - [ - 17276, - 15253 - ], - [ - 21, - -14 - ], - [ - 51, - 38 - ], - [ - 23, - -23 - ], - [ - 23, - 55 - ], - [ - 41, - -2 - ], - [ - 11, - 17 - ], - [ - 7, - 49 - ], - [ - 30, - 41 - ], - [ - 38, - -27 - ], - [ - -8, - -37 - ], - [ - 22, - -5 - ], - [ - -7, - -101 - ], - [ - 28, - -39 - ], - [ - 24, - 25 - ], - [ - 31, - 12 - ], - [ - 43, - 53 - ], - [ - 48, - -8 - ], - [ - 72, - -1 - ] - ], - [ - [ - 17774, - 15286 - ], - [ - 13, - -34 - ] - ], - [ - [ - 17787, - 15252 - ], - [ - -41, - -13 - ], - [ - -35, - -23 - ], - [ - -80, - -14 - ], - [ - -75, - -25 - ], - [ - -41, - -52 - ], - [ - 17, - -51 - ], - [ - 8, - -60 - ], - [ - -35, - -50 - ], - [ - 3, - -46 - ], - [ - -19, - -43 - ], - [ - -67, - 4 - ], - [ - 28, - -80 - ], - [ - -45, - -30 - ], - [ - -29, - -73 - ], - [ - 4, - -72 - ], - [ - -28, - -33 - ], - [ - -26, - 11 - ], - [ - -53, - -16 - ], - [ - -7, - -33 - ], - [ - -52, - 0 - ], - [ - -39, - -68 - ], - [ - -3, - -102 - ], - [ - -90, - -50 - ], - [ - -49, - 10 - ], - [ - -14, - -26 - ], - [ - -42, - 15 - ], - [ - -69, - -17 - ], - [ - -117, - 61 - ] - ], - [ - [ - 16791, - 14376 - ], - [ - 63, - 109 - ], - [ - -6, - 77 - ], - [ - -52, - 20 - ], - [ - -6, - 76 - ], - [ - -23, - 96 - ], - [ - 30, - 66 - ], - [ - -30, - 17 - ], - [ - 19, - 88 - ], - [ - 28, - 149 - ] - ], - [ - [ - 14166, - 8695 - ], - [ - -128, - -49 - ], - [ - -169, - 17 - ], - [ - -48, - 58 - ], - [ - -283, - -6 - ], - [ - -11, - -8 - ], - [ - -41, - 54 - ], - [ - -45, - 4 - ], - [ - -42, - -21 - ], - [ - -34, - -22 - ] - ], - [ - [ - 13365, - 8722 - ], - [ - -6, - 75 - ], - [ - 10, - 105 - ], - [ - 24, - 110 - ], - [ - 3, - 52 - ], - [ - 23, - 108 - ], - [ - 16, - 49 - ], - [ - 41, - 79 - ], - [ - 22, - 53 - ], - [ - 7, - 89 - ], - [ - -3, - 68 - ], - [ - -21, - 43 - ], - [ - -19, - 72 - ], - [ - -17, - 72 - ], - [ - 4, - 25 - ], - [ - 21, - 48 - ], - [ - -21, - 116 - ], - [ - -14, - 80 - ], - [ - -35, - 76 - ], - [ - 6, - 23 - ] - ], - [ - [ - 13406, - 10065 - ], - [ - 29, - 16 - ], - [ - 20, - -2 - ], - [ - 25, - 15 - ], - [ - 206, - -2 - ], - [ - 17, - -89 - ], - [ - 20, - -72 - ], - [ - 16, - -39 - ], - [ - 27, - -63 - ], - [ - 46, - 10 - ], - [ - 23, - 17 - ], - [ - 38, - -17 - ], - [ - 11, - 30 - ], - [ - 17, - 70 - ], - [ - 43, - 4 - ], - [ - 4, - 21 - ], - [ - 36, - 1 - ], - [ - -6, - -44 - ], - [ - 84, - 2 - ], - [ - 1, - -76 - ], - [ - 15, - -46 - ], - [ - -11, - -73 - ], - [ - 5, - -73 - ], - [ - 24, - -45 - ], - [ - -4, - -143 - ], - [ - 17, - 11 - ], - [ - 30, - -3 - ], - [ - 44, - 18 - ], - [ - 31, - -7 - ] - ], - [ - [ - 14214, - 9486 - ], - [ - 8, - -37 - ], - [ - -8, - -58 - ], - [ - 12, - -56 - ], - [ - -10, - -45 - ], - [ - 6, - -42 - ], - [ - -146, - 2 - ], - [ - -3, - -382 - ], - [ - 47, - -98 - ], - [ - 46, - -75 - ] - ], - [ - [ - 13397, - 10103 - ], - [ - -19, - 90 - ] - ], - [ - [ - 13378, - 10193 - ], - [ - 28, - 52 - ], - [ - 21, - 20 - ], - [ - 26, - -41 - ] - ], - [ - [ - 13453, - 10224 - ], - [ - -25, - -26 - ], - [ - -11, - -30 - ], - [ - -3, - -53 - ], - [ - -17, - -12 - ] - ], - [ - [ - 14013, - 15697 - ], - [ - -2, - -31 - ], - [ - -22, - -18 - ], - [ - -4, - -39 - ], - [ - -33, - -58 - ] - ], - [ - [ - 13952, - 15551 - ], - [ - -12, - 8 - ], - [ - -1, - 27 - ], - [ - -39, - 40 - ], - [ - -6, - 57 - ], - [ - 6, - 82 - ], - [ - 10, - 37 - ], - [ - -12, - 19 - ] - ], - [ - [ - 13898, - 15821 - ], - [ - -5, - 38 - ], - [ - 30, - 59 - ], - [ - 5, - -22 - ], - [ - 19, - 11 - ] - ], - [ - [ - 13947, - 15907 - ], - [ - 14, - -33 - ], - [ - 17, - -12 - ], - [ - 5, - -43 - ] - ], - [ - [ - 13983, - 15819 - ], - [ - -9, - -41 - ], - [ - 10, - -52 - ], - [ - 29, - -29 - ] - ], - [ - [ - 16143, - 13706 - ], - [ - 12, - 6 - ], - [ - 3, - -33 - ], - [ - 55, - 19 - ], - [ - 57, - -3 - ], - [ - 42, - -4 - ], - [ - 48, - 81 - ], - [ - 52, - 77 - ], - [ - 44, - 74 - ] - ], - [ - [ - 16456, - 13923 - ], - [ - 13, - -41 - ] - ], - [ - [ - 16469, - 13882 - ], - [ - 10, - -95 - ] - ], - [ - [ - 16479, - 13787 - ], - [ - -36, - 0 - ], - [ - -5, - -78 - ], - [ - 12, - -17 - ], - [ - -32, - -24 - ], - [ - 0, - -49 - ], - [ - -20, - -49 - ], - [ - -2, - -49 - ] - ], - [ - [ - 16396, - 13521 - ], - [ - -14, - -25 - ], - [ - -210, - 61 - ], - [ - -26, - 121 - ], - [ - -3, - 28 - ] - ], - [ - [ - 7880, - 4211 - ], - [ - -42, - 4 - ], - [ - -75, - 0 - ], - [ - 0, - 267 - ] - ], - [ - [ - 7763, - 4482 - ], - [ - 27, - -55 - ], - [ - 35, - -90 - ], - [ - 90, - -72 - ], - [ - 98, - -30 - ], - [ - -31, - -60 - ], - [ - -67, - -6 - ], - [ - -35, - 42 - ] - ], - [ - [ - 7767, - 4523 - ], - [ - -64, - 19 - ], - [ - -169, - 16 - ], - [ - -28, - 70 - ], - [ - 1, - 90 - ], - [ - -47, - -8 - ], - [ - -24, - 43 - ], - [ - -6, - 128 - ], - [ - 53, - 52 - ], - [ - 22, - 76 - ], - [ - -8, - 61 - ], - [ - 37, - 102 - ], - [ - 26, - 159 - ], - [ - -8, - 71 - ], - [ - 31, - 22 - ], - [ - -8, - 46 - ], - [ - -32, - 24 - ], - [ - 23, - 50 - ], - [ - -32, - 46 - ], - [ - -16, - 138 - ], - [ - 28, - 24 - ], - [ - -12, - 147 - ], - [ - 17, - 122 - ], - [ - 18, - 107 - ], - [ - 42, - 44 - ], - [ - -21, - 117 - ], - [ - 0, - 110 - ], - [ - 52, - 79 - ], - [ - -1, - 100 - ], - [ - 40, - 117 - ], - [ - 0, - 110 - ], - [ - -18, - 22 - ], - [ - -32, - 207 - ], - [ - 43, - 124 - ], - [ - -7, - 116 - ], - [ - 25, - 109 - ], - [ - 46, - 113 - ], - [ - 49, - 74 - ], - [ - -21, - 47 - ], - [ - 14, - 39 - ], - [ - -2, - 200 - ], - [ - 76, - 59 - ], - [ - 24, - 125 - ], - [ - -8, - 30 - ] - ], - [ - [ - 7870, - 8070 - ], - [ - 58, - 108 - ], - [ - 91, - -29 - ], - [ - 41, - -87 - ], - [ - 27, - 97 - ], - [ - 80, - -5 - ], - [ - 11, - -26 - ] - ], - [ - [ - 8178, - 8128 - ], - [ - 128, - -196 - ], - [ - 57, - -18 - ], - [ - 85, - -89 - ], - [ - 72, - -47 - ], - [ - 10, - -52 - ], - [ - -69, - -183 - ], - [ - 71, - -32 - ], - [ - 78, - -19 - ], - [ - 55, - 20 - ], - [ - 63, - 91 - ], - [ - 12, - 106 - ] - ], - [ - [ - 8740, - 7709 - ], - [ - 34, - 23 - ], - [ - 35, - -69 - ], - [ - -1, - -96 - ], - [ - -59, - -66 - ], - [ - -47, - -49 - ], - [ - -78, - -116 - ], - [ - -93, - -164 - ] - ], - [ - [ - 8531, - 7172 - ], - [ - -18, - -96 - ], - [ - -19, - -123 - ], - [ - 1, - -120 - ], - [ - -15, - -26 - ], - [ - -5, - -78 - ] - ], - [ - [ - 8475, - 6729 - ], - [ - -5, - -63 - ], - [ - 88, - -102 - ], - [ - -9, - -83 - ], - [ - 43, - -52 - ], - [ - -3, - -59 - ], - [ - -67, - -154 - ], - [ - -103, - -64 - ], - [ - -140, - -25 - ], - [ - -77, - 12 - ], - [ - 15, - -71 - ], - [ - -14, - -90 - ], - [ - 12, - -61 - ], - [ - -41, - -42 - ], - [ - -72, - -17 - ], - [ - -67, - 44 - ], - [ - -27, - -31 - ], - [ - 10, - -119 - ], - [ - 47, - -37 - ], - [ - 38, - 38 - ], - [ - 21, - -62 - ], - [ - -64, - -37 - ], - [ - -56, - -75 - ], - [ - -10, - -121 - ], - [ - -17, - -64 - ], - [ - -66, - 0 - ], - [ - -54, - -62 - ], - [ - -20, - -90 - ], - [ - 68, - -87 - ], - [ - 67, - -25 - ], - [ - -24, - -107 - ], - [ - -83, - -68 - ], - [ - -45, - -141 - ], - [ - -63, - -47 - ], - [ - -29, - -56 - ], - [ - 22, - -125 - ], - [ - 47, - -69 - ], - [ - -30, - 6 - ] - ], - [ - [ - 15586, - 15727 - ], - [ - 96, - 19 - ] - ], - [ - [ - 15682, - 15746 - ], - [ - 15, - -32 - ], - [ - 26, - -21 - ], - [ - -14, - -30 - ], - [ - 38, - -41 - ], - [ - -20, - -38 - ], - [ - 29, - -33 - ], - [ - 32, - -19 - ], - [ - 1, - -84 - ] - ], - [ - [ - 15789, - 15448 - ], - [ - -25, - -3 - ] - ], - [ - [ - 15764, - 15445 - ], - [ - -28, - 69 - ], - [ - 0, - 19 - ], - [ - -31, - 0 - ], - [ - -20, - 32 - ], - [ - -15, - -3 - ] - ], - [ - [ - 15670, - 15562 - ], - [ - -27, - 35 - ], - [ - -52, - 29 - ], - [ - 6, - 59 - ], - [ - -11, - 42 - ] - ], - [ - [ - 8395, - 1195 - ], - [ - -21, - -61 - ], - [ - -20, - -54 - ], - [ - -146, - 16 - ], - [ - -156, - -7 - ], - [ - -87, - 40 - ], - [ - 0, - 5 - ], - [ - -38, - 35 - ], - [ - 157, - -5 - ], - [ - 150, - -11 - ], - [ - 52, - 49 - ], - [ - 36, - 42 - ], - [ - 73, - -49 - ] - ], - [ - [ - 1449, - 1260 - ], - [ - -133, - -16 - ], - [ - -92, - 42 - ], - [ - -41, - 42 - ], - [ - -3, - 7 - ], - [ - -45, - 33 - ], - [ - 43, - 45 - ], - [ - 129, - -19 - ], - [ - 70, - -38 - ], - [ - 53, - -42 - ], - [ - 19, - -54 - ] - ], - [ - [ - 9400, - 1434 - ], - [ - 86, - -52 - ], - [ - 30, - -73 - ], - [ - 8, - -51 - ], - [ - 3, - -61 - ], - [ - -108, - -38 - ], - [ - -113, - -31 - ], - [ - -131, - -28 - ], - [ - -147, - -23 - ], - [ - -165, - 7 - ], - [ - -91, - 40 - ], - [ - 12, - 49 - ], - [ - 149, - 33 - ], - [ - 60, - 40 - ], - [ - 44, - 52 - ], - [ - 31, - 44 - ], - [ - 42, - 43 - ], - [ - 45, - 49 - ], - [ - 36, - 0 - ], - [ - 104, - 26 - ], - [ - 105, - -26 - ] - ], - [ - [ - 4098, - 1979 - ], - [ - 90, - -18 - ], - [ - 83, - 21 - ], - [ - -39, - -43 - ], - [ - -66, - -30 - ], - [ - -97, - 9 - ], - [ - -69, - 43 - ], - [ - 15, - 40 - ], - [ - 83, - -22 - ] - ], - [ - [ - 3795, - 1982 - ], - [ - 106, - -47 - ], - [ - -41, - 4 - ], - [ - -90, - 12 - ], - [ - -95, - 33 - ], - [ - 50, - 26 - ], - [ - 70, - -28 - ] - ], - [ - [ - 5648, - 2167 - ], - [ - 76, - -16 - ], - [ - 77, - 14 - ], - [ - 41, - -68 - ], - [ - -55, - 9 - ], - [ - -85, - -4 - ], - [ - -86, - 4 - ], - [ - -94, - -7 - ], - [ - -71, - 24 - ], - [ - -37, - 49 - ], - [ - 44, - 21 - ], - [ - 89, - -16 - ], - [ - 101, - -10 - ] - ], - [ - [ - 7776, - 2285 - ], - [ - 8, - -54 - ], - [ - -12, - -47 - ], - [ - -19, - -45 - ], - [ - -82, - -16 - ], - [ - -78, - -24 - ], - [ - -92, - 2 - ], - [ - 35, - 47 - ], - [ - -82, - -16 - ], - [ - -78, - -17 - ], - [ - -53, - 36 - ], - [ - -5, - 49 - ], - [ - 77, - 47 - ], - [ - 48, - 14 - ], - [ - 80, - -5 - ], - [ - 21, - 62 - ], - [ - 4, - 44 - ], - [ - -2, - 97 - ], - [ - 40, - 56 - ], - [ - 64, - 19 - ], - [ - 37, - -45 - ], - [ - 17, - -44 - ], - [ - 30, - -55 - ], - [ - 23, - -51 - ], - [ - 19, - -54 - ] - ], - [ - [ - 8462, - 3101 - ], - [ - -30, - -26 - ], - [ - -52, - 19 - ], - [ - -58, - -12 - ], - [ - -47, - -28 - ], - [ - -51, - -31 - ], - [ - -34, - -35 - ], - [ - -10, - -47 - ], - [ - 4, - -45 - ], - [ - 33, - -40 - ], - [ - -48, - -28 - ], - [ - -65, - -9 - ], - [ - -38, - -40 - ], - [ - -41, - -38 - ], - [ - -44, - -51 - ], - [ - -11, - -45 - ], - [ - 25, - -50 - ], - [ - 37, - -37 - ], - [ - 57, - -28 - ], - [ - 53, - -38 - ], - [ - 29, - -47 - ], - [ - 15, - -45 - ], - [ - 20, - -47 - ], - [ - 33, - -40 - ], - [ - 21, - -44 - ], - [ - 9, - -111 - ], - [ - 21, - -44 - ], - [ - 5, - -47 - ], - [ - 22, - -47 - ], - [ - -10, - -64 - ], - [ - -38, - -49 - ], - [ - -41, - -40 - ], - [ - -93, - -17 - ], - [ - -31, - -42 - ], - [ - -42, - -40 - ], - [ - -106, - -45 - ], - [ - -92, - -18 - ], - [ - -88, - -26 - ], - [ - -94, - -26 - ], - [ - -56, - -50 - ], - [ - -112, - -4 - ], - [ - -123, - 4 - ], - [ - -110, - -9 - ], - [ - -118, - 0 - ], - [ - 22, - -47 - ], - [ - 107, - -21 - ], - [ - 77, - -33 - ], - [ - 44, - -42 - ], - [ - -78, - -38 - ], - [ - -120, - 12 - ], - [ - -100, - -31 - ], - [ - -4, - -49 - ], - [ - -2, - -47 - ], - [ - 82, - -40 - ], - [ - 15, - -45 - ], - [ - 88, - -44 - ], - [ - 148, - -19 - ], - [ - 125, - -33 - ], - [ - 100, - -38 - ], - [ - 127, - -37 - ], - [ - 173, - -19 - ], - [ - 171, - -33 - ], - [ - 119, - -35 - ], - [ - 130, - -40 - ], - [ - 68, - -57 - ], - [ - 34, - -44 - ], - [ - 85, - 42 - ], - [ - 114, - 35 - ], - [ - 122, - 38 - ], - [ - 144, - 30 - ], - [ - 125, - 33 - ], - [ - 173, - 3 - ], - [ - 171, - -17 - ], - [ - 140, - -28 - ], - [ - 45, - 52 - ], - [ - 97, - 35 - ], - [ - 177, - 2 - ], - [ - 137, - 26 - ], - [ - 131, - 26 - ], - [ - 145, - 16 - ], - [ - 154, - 22 - ], - [ - 108, - 30 - ], - [ - -49, - 42 - ], - [ - -30, - 43 - ], - [ - 0, - 44 - ], - [ - -135, - -4 - ], - [ - -143, - -19 - ], - [ - -137, - 0 - ], - [ - -19, - 45 - ], - [ - 10, - 89 - ], - [ - 31, - 26 - ], - [ - 100, - 28 - ], - [ - 117, - 28 - ], - [ - 85, - 35 - ], - [ - 84, - 36 - ], - [ - 63, - 47 - ], - [ - 96, - 21 - ], - [ - 94, - 16 - ], - [ - 48, - 10 - ], - [ - 108, - 4 - ], - [ - 102, - 17 - ], - [ - 86, - 23 - ], - [ - 85, - 29 - ], - [ - 76, - 28 - ], - [ - 97, - 37 - ], - [ - 61, - 40 - ], - [ - 66, - 36 - ], - [ - 20, - 47 - ], - [ - -73, - 28 - ], - [ - 24, - 49 - ], - [ - 47, - 38 - ], - [ - 72, - 23 - ], - [ - 77, - 29 - ], - [ - 71, - 37 - ], - [ - 54, - 47 - ], - [ - 34, - 57 - ], - [ - 51, - 33 - ], - [ - 83, - -7 - ], - [ - 34, - -40 - ], - [ - 83, - -5 - ], - [ - 3, - 45 - ], - [ - 36, - 47 - ], - [ - 75, - -12 - ], - [ - 18, - -45 - ], - [ - 83, - -7 - ], - [ - 90, - 21 - ], - [ - 87, - 14 - ], - [ - 80, - -7 - ], - [ - 30, - -49 - ], - [ - 76, - 40 - ], - [ - 71, - 21 - ], - [ - 79, - 16 - ], - [ - 78, - 17 - ], - [ - 71, - 28 - ], - [ - 78, - 19 - ], - [ - 60, - 26 - ], - [ - 42, - 42 - ], - [ - 52, - -30 - ], - [ - 72, - 16 - ], - [ - 51, - -56 - ], - [ - 40, - -43 - ], - [ - 79, - 24 - ], - [ - 31, - 47 - ], - [ - 71, - 33 - ], - [ - 92, - -7 - ], - [ - 27, - -45 - ], - [ - 57, - 45 - ], - [ - 75, - 14 - ], - [ - 82, - 4 - ], - [ - 74, - -2 - ], - [ - 78, - -14 - ], - [ - 75, - -7 - ], - [ - 33, - -40 - ], - [ - 45, - -35 - ], - [ - 76, - 21 - ], - [ - 82, - 5 - ], - [ - 79, - 0 - ], - [ - 78, - 2 - ], - [ - 70, - 16 - ], - [ - 74, - 15 - ], - [ - 61, - 32 - ], - [ - 65, - 22 - ], - [ - 71, - 11 - ], - [ - 54, - 33 - ], - [ - 38, - 66 - ], - [ - 40, - 40 - ], - [ - 72, - -19 - ], - [ - 27, - -42 - ], - [ - 60, - -28 - ], - [ - 73, - 9 - ], - [ - 49, - -42 - ], - [ - 52, - -31 - ], - [ - 71, - 28 - ], - [ - 24, - 52 - ], - [ - 63, - 21 - ], - [ - 72, - 40 - ], - [ - 69, - 17 - ], - [ - 82, - 23 - ], - [ - 54, - 26 - ], - [ - 58, - 28 - ], - [ - 54, - 26 - ], - [ - 66, - -14 - ], - [ - 63, - 42 - ], - [ - 45, - 33 - ], - [ - 65, - -2 - ], - [ - 57, - 28 - ], - [ - 14, - 42 - ], - [ - 59, - 33 - ], - [ - 57, - 24 - ], - [ - 70, - 19 - ], - [ - 64, - 9 - ], - [ - 61, - -7 - ], - [ - 66, - -12 - ], - [ - 56, - -33 - ], - [ - 7, - -51 - ], - [ - 61, - -40 - ], - [ - 42, - -33 - ], - [ - 84, - -14 - ], - [ - 46, - -33 - ], - [ - 58, - -33 - ], - [ - 66, - -7 - ], - [ - 56, - 23 - ], - [ - 60, - 50 - ], - [ - 66, - -26 - ], - [ - 68, - -14 - ], - [ - 66, - -14 - ], - [ - 68, - -10 - ], - [ - 70, - 0 - ], - [ - 57, - -124 - ], - [ - -3, - -31 - ], - [ - -8, - -54 - ], - [ - -67, - -31 - ], - [ - -54, - -44 - ], - [ - 9, - -47 - ], - [ - 78, - 2 - ], - [ - -10, - -47 - ], - [ - -35, - -45 - ], - [ - -33, - -49 - ], - [ - 53, - -38 - ], - [ - 81, - -11 - ], - [ - 81, - 21 - ], - [ - 38, - 47 - ], - [ - 23, - 45 - ], - [ - 38, - 37 - ], - [ - 44, - 35 - ], - [ - 18, - 43 - ], - [ - 36, - 58 - ], - [ - 44, - 12 - ], - [ - 79, - 5 - ], - [ - 70, - 14 - ], - [ - 71, - 19 - ], - [ - 34, - 47 - ], - [ - 21, - 45 - ], - [ - 47, - 44 - ], - [ - 69, - 31 - ], - [ - 58, - 23 - ], - [ - 39, - 40 - ], - [ - 39, - 21 - ], - [ - 51, - 19 - ], - [ - 69, - -12 - ], - [ - 63, - 12 - ], - [ - 68, - 14 - ], - [ - 77, - -7 - ], - [ - 50, - 33 - ], - [ - 36, - 80 - ], - [ - 26, - -33 - ], - [ - 33, - -56 - ], - [ - 58, - -24 - ], - [ - 67, - -9 - ], - [ - 67, - 14 - ], - [ - 71, - -9 - ], - [ - 66, - -3 - ], - [ - 43, - 12 - ], - [ - 59, - -7 - ], - [ - 53, - -26 - ], - [ - 63, - 16 - ], - [ - 75, - 0 - ], - [ - 64, - 17 - ], - [ - 73, - -17 - ], - [ - 46, - 40 - ], - [ - 36, - 40 - ], - [ - 47, - 33 - ], - [ - 88, - 90 - ], - [ - 45, - -17 - ], - [ - 53, - -33 - ], - [ - 46, - -42 - ], - [ - 89, - -73 - ], - [ - 69, - -2 - ], - [ - 64, - 0 - ], - [ - 75, - 14 - ], - [ - 75, - 16 - ], - [ - 57, - 33 - ], - [ - 48, - 35 - ], - [ - 78, - 5 - ], - [ - 52, - 26 - ], - [ - 54, - -23 - ], - [ - 36, - -38 - ], - [ - 49, - -38 - ], - [ - 76, - 5 - ], - [ - 48, - -31 - ], - [ - 83, - -30 - ], - [ - 88, - -12 - ], - [ - 72, - 10 - ], - [ - 55, - 37 - ], - [ - 46, - 38 - ], - [ - 63, - 9 - ], - [ - 63, - -16 - ], - [ - 72, - -12 - ], - [ - 66, - 19 - ], - [ - 63, - 0 - ], - [ - 61, - -12 - ], - [ - 64, - -12 - ], - [ - 63, - 21 - ], - [ - 75, - 19 - ], - [ - 71, - 5 - ], - [ - 79, - 0 - ], - [ - 64, - 12 - ], - [ - 63, - 9 - ], - [ - 19, - 59 - ], - [ - 3, - 49 - ], - [ - 44, - -33 - ], - [ - 12, - -54 - ], - [ - 23, - -49 - ], - [ - 29, - -40 - ], - [ - 59, - -21 - ], - [ - 79, - 7 - ], - [ - 91, - 2 - ], - [ - 63, - 7 - ], - [ - 92, - 0 - ], - [ - 65, - 3 - ], - [ - 92, - -5 - ], - [ - 77, - -10 - ], - [ - 50, - -37 - ], - [ - -14, - -45 - ], - [ - 45, - -35 - ], - [ - 75, - -28 - ], - [ - 78, - -31 - ], - [ - 90, - -21 - ], - [ - 94, - -19 - ], - [ - 71, - -19 - ], - [ - 79, - -2 - ], - [ - 45, - 40 - ], - [ - 62, - -33 - ], - [ - 53, - -38 - ], - [ - 62, - -28 - ], - [ - 84, - -12 - ], - [ - 81, - -14 - ], - [ - 34, - -47 - ], - [ - 79, - -28 - ], - [ - 53, - -42 - ], - [ - 78, - -19 - ], - [ - 81, - 2 - ], - [ - 75, - -7 - ], - [ - 83, - 3 - ], - [ - 83, - -10 - ], - [ - 78, - -16 - ], - [ - 73, - -28 - ], - [ - 72, - -24 - ], - [ - 49, - -35 - ], - [ - -8, - -47 - ], - [ - -37, - -42 - ], - [ - -31, - -55 - ], - [ - -25, - -42 - ], - [ - -33, - -49 - ], - [ - -91, - -19 - ], - [ - -41, - -42 - ], - [ - -90, - -26 - ], - [ - -32, - -47 - ], - [ - -47, - -45 - ], - [ - -51, - -38 - ], - [ - -29, - -49 - ], - [ - -17, - -45 - ], - [ - -7, - -54 - ], - [ - 1, - -44 - ], - [ - 40, - -47 - ], - [ - 15, - -45 - ], - [ - 32, - -42 - ], - [ - 130, - -17 - ], - [ - 27, - -51 - ], - [ - -125, - -19 - ], - [ - -107, - -26 - ], - [ - -132, - -5 - ], - [ - -59, - -68 - ], - [ - -12, - -56 - ], - [ - -30, - -45 - ], - [ - -37, - -45 - ], - [ - 93, - -40 - ], - [ - 35, - -49 - ], - [ - 60, - -45 - ], - [ - 85, - -40 - ], - [ - 97, - -37 - ], - [ - 105, - -38 - ], - [ - 160, - -38 - ], - [ - 35, - -58 - ], - [ - 201, - -26 - ], - [ - 14, - -9 - ], - [ - 52, - -36 - ], - [ - 192, - 31 - ], - [ - 160, - -38 - ], - [ - 120, - -29 - ], - [ - 0, - -634 - ], - [ - -25095, - 0 - ], - [ - 0, - 634 - ], - [ - 4, - -1 - ], - [ - 62, - 70 - ], - [ - 125, - -38 - ], - [ - 8, - 5 - ], - [ - 74, - 38 - ], - [ - 10, - -1 - ], - [ - 8, - -1 - ], - [ - 101, - -50 - ], - [ - 88, - 50 - ], - [ - 16, - 6 - ], - [ - 204, - 22 - ], - [ - 67, - -28 - ], - [ - 33, - -15 - ], - [ - 105, - -40 - ], - [ - 198, - -30 - ], - [ - 157, - -38 - ], - [ - 269, - -28 - ], - [ - 200, - 33 - ], - [ - 297, - -24 - ], - [ - 168, - -37 - ], - [ - 184, - 35 - ], - [ - 194, - 33 - ], - [ - 15, - 56 - ], - [ - -275, - 5 - ], - [ - -225, - 28 - ], - [ - -59, - 47 - ], - [ - -187, - 26 - ], - [ - 13, - 54 - ], - [ - 25, - 50 - ], - [ - 26, - 44 - ], - [ - -13, - 50 - ], - [ - -116, - 33 - ], - [ - -54, - 42 - ], - [ - -107, - 37 - ], - [ - 169, - -7 - ], - [ - 161, - 19 - ], - [ - 101, - -40 - ], - [ - 124, - 36 - ], - [ - 115, - 44 - ], - [ - 56, - 40 - ], - [ - -25, - 50 - ], - [ - -90, - 32 - ], - [ - -102, - 36 - ], - [ - -143, - 7 - ], - [ - -126, - 16 - ], - [ - -135, - 12 - ], - [ - -45, - 45 - ], - [ - -90, - 37 - ], - [ - -55, - 43 - ], - [ - -22, - 136 - ], - [ - 34, - -12 - ], - [ - 63, - -37 - ], - [ - 115, - 11 - ], - [ - 110, - 17 - ], - [ - 58, - -52 - ], - [ - 110, - 12 - ], - [ - 93, - 26 - ], - [ - 87, - 33 - ], - [ - 80, - 39 - ], - [ - 105, - 12 - ], - [ - -3, - 45 - ], - [ - -24, - 45 - ], - [ - 20, - 42 - ], - [ - 90, - 21 - ], - [ - 41, - -40 - ], - [ - 107, - 24 - ], - [ - 80, - 30 - ], - [ - 100, - 3 - ], - [ - 94, - 11 - ], - [ - 94, - 28 - ], - [ - 75, - 26 - ], - [ - 85, - 26 - ], - [ - 55, - -7 - ], - [ - 47, - -9 - ], - [ - 104, - 16 - ], - [ - 93, - -21 - ], - [ - 95, - 2 - ], - [ - 92, - 17 - ], - [ - 94, - -12 - ], - [ - 104, - -12 - ], - [ - 97, - 5 - ], - [ - 101, - -2 - ], - [ - 104, - -3 - ], - [ - 95, - 5 - ], - [ - 71, - 35 - ], - [ - 85, - 19 - ], - [ - 87, - -26 - ], - [ - 84, - 21 - ], - [ - 75, - 43 - ], - [ - 45, - -38 - ], - [ - 24, - -42 - ], - [ - 45, - -40 - ], - [ - 73, - 35 - ], - [ - 83, - -45 - ], - [ - 94, - -14 - ], - [ - 81, - -33 - ], - [ - 98, - 7 - ], - [ - 89, - 22 - ], - [ - 105, - -5 - ], - [ - 94, - -17 - ], - [ - 96, - -21 - ], - [ - 37, - 52 - ], - [ - -46, - 40 - ], - [ - -34, - 42 - ], - [ - -90, - 10 - ], - [ - -39, - 44 - ], - [ - -15, - 45 - ], - [ - -25, - 89 - ], - [ - 53, - -16 - ], - [ - 92, - -7 - ], - [ - 90, - 7 - ], - [ - 82, - -19 - ], - [ - 71, - -35 - ], - [ - 30, - -42 - ], - [ - 94, - -8 - ], - [ - 90, - 17 - ], - [ - 96, - 23 - ], - [ - 86, - 15 - ], - [ - 71, - -29 - ], - [ - 93, - 10 - ], - [ - 60, - 91 - ], - [ - 56, - -54 - ], - [ - 80, - -21 - ], - [ - 88, - 12 - ], - [ - 57, - -47 - ], - [ - 91, - -5 - ], - [ - 85, - -14 - ], - [ - 83, - -26 - ], - [ - 55, - 45 - ], - [ - 27, - 42 - ], - [ - 70, - -47 - ], - [ - 95, - 12 - ], - [ - 71, - -26 - ], - [ - 48, - -40 - ], - [ - 93, - 12 - ], - [ - 72, - 26 - ], - [ - 71, - 30 - ], - [ - 85, - 17 - ], - [ - 98, - 14 - ], - [ - 89, - 16 - ], - [ - 68, - 26 - ], - [ - 41, - 38 - ], - [ - 17, - 52 - ], - [ - -8, - 49 - ], - [ - -22, - 47 - ], - [ - -25, - 47 - ], - [ - -22, - 47 - ], - [ - -18, - 42 - ], - [ - -4, - 47 - ], - [ - 7, - 47 - ], - [ - 33, - 45 - ], - [ - 27, - 49 - ], - [ - 11, - 47 - ], - [ - -13, - 52 - ], - [ - -9, - 47 - ], - [ - 35, - 54 - ], - [ - 38, - 35 - ], - [ - 45, - 45 - ], - [ - 48, - 38 - ], - [ - 56, - 35 - ], - [ - 27, - 52 - ], - [ - 38, - 33 - ], - [ - 44, - 30 - ], - [ - 67, - 7 - ], - [ - 43, - 38 - ], - [ - 50, - 23 - ], - [ - 57, - 14 - ], - [ - 50, - 31 - ], - [ - 40, - 38 - ], - [ - 55, - 14 - ], - [ - 41, - -31 - ], - [ - -26, - -40 - ], - [ - -71, - -35 - ] - ], - [ - [ - 17353, - 4964 - ], - [ - 45, - -38 - ], - [ - 66, - -15 - ], - [ - 2, - -23 - ], - [ - -19, - -54 - ], - [ - -107, - -8 - ], - [ - -2, - 64 - ], - [ - 10, - 49 - ], - [ - 5, - 25 - ] - ], - [ - [ - 22683, - 5903 - ], - [ - 67, - -41 - ], - [ - 38, - 16 - ], - [ - 55, - 23 - ], - [ - 41, - -8 - ], - [ - 5, - -142 - ], - [ - -23, - -41 - ], - [ - -8, - -97 - ], - [ - -24, - 33 - ], - [ - -48, - -84 - ], - [ - -15, - 7 - ], - [ - -43, - 4 - ], - [ - -43, - 102 - ], - [ - -9, - 79 - ], - [ - -40, - 105 - ], - [ - 1, - 55 - ], - [ - 46, - -11 - ] - ], - [ - [ - 22555, - 9146 - ], - [ - 25, - -94 - ], - [ - 45, - 45 - ], - [ - 23, - -51 - ], - [ - 33, - -47 - ], - [ - -7, - -53 - ], - [ - 15, - -103 - ], - [ - 11, - -59 - ], - [ - 17, - -15 - ], - [ - 19, - -103 - ], - [ - -7, - -62 - ], - [ - 23, - -81 - ], - [ - 75, - -63 - ], - [ - 50, - -57 - ], - [ - 46, - -52 - ], - [ - -9, - -29 - ], - [ - 40, - -75 - ], - [ - 27, - -130 - ], - [ - 28, - 26 - ], - [ - 28, - -52 - ], - [ - 17, - 19 - ], - [ - 12, - -128 - ], - [ - 50, - -73 - ], - [ - 32, - -46 - ], - [ - 55, - -97 - ], - [ - 19, - -97 - ], - [ - 2, - -68 - ], - [ - -5, - -74 - ], - [ - 34, - -102 - ], - [ - -4, - -106 - ], - [ - -12, - -56 - ], - [ - -19, - -107 - ], - [ - 1, - -69 - ], - [ - -14, - -86 - ], - [ - -30, - -109 - ], - [ - -52, - -59 - ], - [ - -26, - -93 - ], - [ - -23, - -59 - ], - [ - -20, - -104 - ], - [ - -27, - -59 - ], - [ - -18, - -90 - ], - [ - -9, - -83 - ], - [ - 4, - -38 - ], - [ - -40, - -41 - ], - [ - -78, - -5 - ], - [ - -65, - -49 - ], - [ - -32, - -46 - ], - [ - -42, - -52 - ], - [ - -58, - 53 - ], - [ - -42, - 21 - ], - [ - 10, - 63 - ], - [ - -38, - -23 - ], - [ - -61, - -87 - ], - [ - -60, - 33 - ], - [ - -39, - 19 - ], - [ - -40, - 8 - ], - [ - -68, - 35 - ], - [ - -45, - 74 - ], - [ - -13, - 91 - ], - [ - -16, - 61 - ], - [ - -34, - 48 - ], - [ - -67, - 15 - ], - [ - 23, - 58 - ], - [ - -17, - 89 - ], - [ - -34, - -83 - ], - [ - -62, - -22 - ], - [ - 36, - 66 - ], - [ - 11, - 70 - ], - [ - 27, - 58 - ], - [ - -6, - 89 - ], - [ - -57, - -102 - ], - [ - -43, - -41 - ], - [ - -27, - -96 - ], - [ - -54, - 50 - ], - [ - 2, - 63 - ], - [ - -44, - 87 - ], - [ - -37, - 45 - ], - [ - 14, - 28 - ], - [ - -90, - 73 - ], - [ - -49, - 3 - ], - [ - -67, - 59 - ], - [ - -125, - -12 - ], - [ - -90, - -43 - ], - [ - -79, - -40 - ], - [ - -67, - 8 - ], - [ - -74, - -61 - ], - [ - -60, - -28 - ], - [ - -14, - -63 - ], - [ - -25, - -49 - ], - [ - -60, - -2 - ], - [ - -43, - -11 - ], - [ - -62, - 22 - ], - [ - -50, - -13 - ], - [ - -48, - -6 - ], - [ - -41, - -64 - ], - [ - -21, - 6 - ], - [ - -35, - -34 - ], - [ - -33, - -38 - ], - [ - -51, - 4 - ], - [ - -47, - 0 - ], - [ - -74, - 77 - ], - [ - -37, - 23 - ], - [ - 1, - 68 - ], - [ - 35, - 17 - ], - [ - 12, - 27 - ], - [ - -3, - 43 - ], - [ - 9, - 84 - ], - [ - -8, - 71 - ], - [ - -37, - 121 - ], - [ - -11, - 68 - ], - [ - 3, - 69 - ], - [ - -28, - 78 - ], - [ - -2, - 35 - ], - [ - -31, - 48 - ], - [ - -8, - 94 - ], - [ - -40, - 95 - ], - [ - -10, - 51 - ], - [ - 31, - -52 - ], - [ - -24, - 111 - ], - [ - 35, - -34 - ], - [ - 20, - -47 - ], - [ - -1, - 62 - ], - [ - -34, - 94 - ], - [ - -7, - 38 - ], - [ - -16, - 36 - ], - [ - 8, - 69 - ], - [ - 14, - 30 - ], - [ - 9, - 60 - ], - [ - -7, - 70 - ], - [ - 29, - 86 - ], - [ - 5, - -91 - ], - [ - 29, - 82 - ], - [ - 57, - 40 - ], - [ - 34, - 52 - ], - [ - 53, - 44 - ], - [ - 32, - 9 - ], - [ - 19, - -15 - ], - [ - 55, - 45 - ], - [ - 42, - 13 - ], - [ - 11, - 27 - ], - [ - 18, - 10 - ], - [ - 39, - -2 - ], - [ - 73, - 35 - ], - [ - 38, - 53 - ], - [ - 18, - 64 - ], - [ - 41, - 61 - ], - [ - 3, - 48 - ], - [ - 2, - 65 - ], - [ - 49, - 102 - ], - [ - 29, - -103 - ], - [ - 30, - 23 - ], - [ - -25, - 57 - ], - [ - 22, - 58 - ], - [ - 30, - -26 - ], - [ - 9, - 92 - ], - [ - 38, - 59 - ], - [ - 17, - 47 - ], - [ - 35, - 20 - ], - [ - 1, - 34 - ], - [ - 30, - -14 - ], - [ - 2, - 30 - ], - [ - 30, - 17 - ], - [ - 34, - 16 - ], - [ - 52, - -55 - ], - [ - 38, - -71 - ], - [ - 44, - 0 - ], - [ - 44, - -12 - ], - [ - -15, - 66 - ], - [ - 34, - 96 - ], - [ - 31, - 32 - ], - [ - -11, - 30 - ], - [ - 31, - 68 - ], - [ - 42, - 43 - ], - [ - 36, - -15 - ], - [ - 58, - 23 - ], - [ - -1, - 61 - ], - [ - -51, - 40 - ], - [ - 37, - 17 - ], - [ - 46, - -30 - ], - [ - 37, - -49 - ], - [ - 59, - -31 - ], - [ - 20, - 13 - ], - [ - 43, - -37 - ], - [ - 41, - 34 - ], - [ - 26, - -10 - ], - [ - 16, - 23 - ], - [ - 32, - -60 - ], - [ - -18, - -64 - ], - [ - -27, - -48 - ], - [ - -24, - -4 - ], - [ - 8, - -48 - ], - [ - -20, - -60 - ], - [ - -25, - -59 - ], - [ - 5, - -34 - ], - [ - 55, - -66 - ], - [ - 54, - -39 - ], - [ - 36, - -41 - ], - [ - 50, - -71 - ], - [ - 20, - 0 - ], - [ - 37, - -31 - ], - [ - 10, - -37 - ], - [ - 67, - -41 - ], - [ - 46, - 41 - ], - [ - 13, - 65 - ], - [ - 14, - 53 - ], - [ - 9, - 66 - ], - [ - 21, - 95 - ], - [ - -9, - 58 - ], - [ - 5, - 35 - ], - [ - -8, - 69 - ], - [ - 9, - 90 - ], - [ - 13, - 25 - ], - [ - -11, - 40 - ], - [ - 17, - 63 - ], - [ - 13, - 66 - ], - [ - 2, - 34 - ], - [ - 26, - 45 - ], - [ - 20, - -58 - ], - [ - 5, - -76 - ], - [ - 17, - -14 - ], - [ - 3, - -51 - ], - [ - 25, - -61 - ], - [ - 5, - -67 - ], - [ - -2, - -44 - ] - ], - [ - [ - 13731, - 16571 - ], - [ - -5, - -50 - ], - [ - -39, - 0 - ], - [ - 13, - -26 - ], - [ - -23, - -77 - ] - ], - [ - [ - 13677, - 16418 - ], - [ - -13, - -20 - ], - [ - -61, - -3 - ], - [ - -35, - -27 - ], - [ - -58, - 9 - ] - ], - [ - [ - 13510, - 16377 - ], - [ - -100, - 31 - ], - [ - -15, - 42 - ], - [ - -69, - -21 - ], - [ - -8, - -23 - ], - [ - -43, - 17 - ] - ], - [ - [ - 13275, - 16423 - ], - [ - -35, - 3 - ], - [ - -32, - 22 - ], - [ - 11, - 29 - ], - [ - -3, - 22 - ] - ], - [ - [ - 13216, - 16499 - ], - [ - 21, - 6 - ], - [ - 36, - -33 - ], - [ - 10, - 32 - ], - [ - 61, - -5 - ], - [ - 50, - 21 - ], - [ - 33, - -4 - ], - [ - 22, - -24 - ], - [ - 7, - 20 - ], - [ - -10, - 78 - ], - [ - 25, - 16 - ], - [ - 24, - 55 - ] - ], - [ - [ - 13495, - 16661 - ], - [ - 52, - -39 - ], - [ - 39, - 49 - ], - [ - 25, - 9 - ], - [ - 54, - -36 - ], - [ - 33, - 6 - ], - [ - 32, - -23 - ] - ], - [ - [ - 13730, - 16627 - ], - [ - -6, - -15 - ], - [ - 7, - -41 - ] - ], - [ - [ - 15682, - 15746 - ], - [ - 18, - 19 - ], - [ - 51, - -34 - ], - [ - 38, - -7 - ], - [ - 10, - 14 - ], - [ - -35, - 65 - ], - [ - 18, - 16 - ] - ], - [ - [ - 15782, - 15819 - ], - [ - 20, - -4 - ], - [ - 48, - -73 - ], - [ - 31, - -8 - ], - [ - 12, - 31 - ], - [ - 41, - 48 - ] - ], - [ - [ - 15934, - 15813 - ], - [ - 37, - -63 - ], - [ - 35, - -85 - ], - [ - 33, - -6 - ], - [ - 21, - -32 - ], - [ - -57, - -10 - ], - [ - -12, - -93 - ], - [ - -12, - -42 - ], - [ - -26, - -28 - ], - [ - 2, - -60 - ] - ], - [ - [ - 15955, - 15394 - ], - [ - -17, - -6 - ], - [ - -44, - 63 - ], - [ - 24, - 60 - ], - [ - -20, - 35 - ], - [ - -26, - -9 - ], - [ - -83, - -89 - ] - ], - [ - [ - 15764, - 15445 - ], - [ - -48, - 16 - ], - [ - -35, - 55 - ], - [ - -11, - 46 - ] - ], - [ - [ - 14593, - 10257 - ], - [ - -5, - 145 - ], - [ - -17, - 55 - ] - ], - [ - [ - 14571, - 10457 - ], - [ - 42, - -10 - ], - [ - 21, - 68 - ], - [ - 37, - -7 - ] - ], - [ - [ - 14671, - 10508 - ], - [ - 5, - -48 - ], - [ - 15, - -27 - ], - [ - 0, - -39 - ], - [ - -17, - -25 - ], - [ - -27, - -62 - ], - [ - -25, - -44 - ], - [ - -29, - -6 - ] - ], - [ - [ - 12977, - 16892 - ], - [ - -8, - -81 - ] - ], - [ - [ - 12969, - 16811 - ], - [ - -18, - -5 - ], - [ - -8, - -67 - ] - ], - [ - [ - 12943, - 16739 - ], - [ - -61, - 55 - ], - [ - -36, - -9 - ], - [ - -48, - 56 - ], - [ - -33, - 48 - ], - [ - -32, - 2 - ], - [ - -10, - 42 - ] - ], - [ - [ - 12723, - 16933 - ], - [ - 56, - 24 - ] - ], - [ - [ - 12779, - 16957 - ], - [ - 51, - -9 - ], - [ - 64, - 25 - ], - [ - 44, - -53 - ], - [ - 39, - -28 - ] - ], - [ - [ - 12735, - 11548 - ], - [ - -57, - -14 - ] - ], - [ - [ - 12678, - 11534 - ], - [ - -18, - 83 - ], - [ - 4, - 275 - ], - [ - -15, - 25 - ], - [ - -2, - 59 - ], - [ - -24, - 42 - ], - [ - -22, - 35 - ], - [ - 9, - 64 - ] - ], - [ - [ - 12610, - 12117 - ], - [ - 24, - 13 - ], - [ - 14, - 53 - ], - [ - 34, - 11 - ], - [ - 16, - 36 - ] - ], - [ - [ - 12698, - 12230 - ], - [ - 23, - 35 - ], - [ - 25, - 0 - ], - [ - 53, - -69 - ] - ], - [ - [ - 12799, - 12196 - ], - [ - -2, - -40 - ], - [ - 15, - -71 - ], - [ - -14, - -48 - ], - [ - 8, - -33 - ], - [ - -34, - -74 - ], - [ - -21, - -37 - ], - [ - -14, - -75 - ], - [ - 2, - -77 - ], - [ - -4, - -193 - ] - ], - [ - [ - 12610, - 12117 - ], - [ - -61, - 2 - ] - ], - [ - [ - 12549, - 12119 - ], - [ - -32, - 10 - ], - [ - -23, - -20 - ], - [ - -30, - 9 - ], - [ - -121, - -6 - ], - [ - -2, - -68 - ], - [ - 9, - -90 - ] - ], - [ - [ - 12350, - 11954 - ], - [ - -47, - 31 - ], - [ - -33, - -5 - ], - [ - -24, - -30 - ], - [ - -32, - 26 - ], - [ - -12, - 39 - ], - [ - -31, - 26 - ] - ], - [ - [ - 12171, - 12041 - ], - [ - -5, - 70 - ], - [ - 19, - 51 - ], - [ - -1, - 40 - ], - [ - 55, - 100 - ], - [ - 10, - 82 - ], - [ - 19, - 29 - ], - [ - 34, - -16 - ], - [ - 29, - 25 - ], - [ - 10, - 31 - ], - [ - 54, - 53 - ], - [ - 13, - 38 - ], - [ - 65, - 50 - ], - [ - 39, - 17 - ], - [ - 17, - -23 - ], - [ - 45, - 0 - ] - ], - [ - [ - 12574, - 12588 - ], - [ - -6, - -58 - ], - [ - 9, - -55 - ], - [ - 40, - -78 - ], - [ - 2, - -58 - ], - [ - 80, - -27 - ], - [ - -1, - -82 - ] - ], - [ - [ - 19008, - 13441 - ], - [ - -2, - -86 - ], - [ - -24, - 19 - ], - [ - 4, - -97 - ] - ], - [ - [ - 18986, - 13277 - ], - [ - -20, - 63 - ], - [ - -4, - 61 - ], - [ - -13, - 57 - ], - [ - -29, - 70 - ], - [ - -64, - 5 - ], - [ - 6, - -49 - ], - [ - -22, - -67 - ], - [ - -29, - 24 - ], - [ - -11, - -22 - ], - [ - -19, - 13 - ], - [ - -27, - 11 - ] - ], - [ - [ - 18754, - 13443 - ], - [ - -11, - 99 - ], - [ - -24, - 90 - ], - [ - 12, - 72 - ], - [ - -43, - 33 - ], - [ - 15, - 43 - ], - [ - 44, - 45 - ], - [ - -51, - 64 - ], - [ - 25, - 81 - ], - [ - 55, - -52 - ], - [ - 34, - -6 - ], - [ - 6, - -83 - ], - [ - 66, - -17 - ], - [ - 65, - 2 - ], - [ - 40, - -20 - ], - [ - -32, - -102 - ], - [ - -31, - -7 - ], - [ - -22, - -68 - ], - [ - 38, - -62 - ], - [ - 12, - 76 - ], - [ - 19, - 1 - ], - [ - 37, - -191 - ] - ], - [ - [ - 14127, - 16104 - ], - [ - 20, - -49 - ], - [ - 27, - 8 - ], - [ - 54, - -18 - ], - [ - 102, - -7 - ], - [ - 34, - 31 - ], - [ - 83, - 28 - ], - [ - 50, - -44 - ], - [ - 41, - -12 - ] - ], - [ - [ - 14538, - 16041 - ], - [ - -36, - -50 - ], - [ - -25, - -86 - ], - [ - 22, - -68 - ] - ], - [ - [ - 14499, - 15837 - ], - [ - -60, - 16 - ], - [ - -71, - -38 - ] - ], - [ - [ - 14368, - 15815 - ], - [ - -1, - -60 - ], - [ - -63, - -11 - ], - [ - -49, - 42 - ], - [ - -56, - -33 - ], - [ - -52, - 3 - ] - ], - [ - [ - 14147, - 15756 - ], - [ - -4, - 80 - ], - [ - -35, - 38 - ] - ], - [ - [ - 14108, - 15874 - ], - [ - 11, - 17 - ], - [ - -7, - 15 - ], - [ - 11, - 38 - ], - [ - 27, - 37 - ], - [ - -34, - 52 - ], - [ - -6, - 44 - ], - [ - 17, - 27 - ] - ], - [ - [ - 7143, - 13648 - ], - [ - -17, - -6 - ], - [ - -18, - 69 - ], - [ - -26, - 35 - ], - [ - 15, - 76 - ], - [ - 21, - -5 - ], - [ - 24, - -100 - ], - [ - 1, - -69 - ] - ], - [ - [ - 7123, - 13986 - ], - [ - -76, - -19 - ], - [ - -5, - 44 - ], - [ - 33, - 10 - ], - [ - 46, - -4 - ], - [ - 2, - -31 - ] - ], - [ - [ - 7180, - 13987 - ], - [ - -12, - -85 - ], - [ - -13, - 15 - ], - [ - 1, - 63 - ], - [ - -31, - 47 - ], - [ - 0, - 14 - ], - [ - 55, - -54 - ] - ], - [ - [ - 13887, - 16019 - ], - [ - -13, - -11 - ], - [ - -23, - -28 - ], - [ - -10, - -66 - ] - ], - [ - [ - 13841, - 15914 - ], - [ - -61, - 45 - ], - [ - -27, - 50 - ], - [ - -26, - 27 - ], - [ - -32, - 45 - ], - [ - -15, - 37 - ], - [ - -35, - 56 - ], - [ - 15, - 50 - ], - [ - 25, - -28 - ], - [ - 15, - 25 - ], - [ - 33, - 3 - ], - [ - 60, - -20 - ], - [ - 48, - 2 - ], - [ - 31, - -27 - ] - ], - [ - [ - 13872, - 16179 - ], - [ - 26, - 0 - ], - [ - -18, - -52 - ], - [ - 34, - -47 - ], - [ - -10, - -56 - ], - [ - -17, - -5 - ] - ], - [ - [ - 14185, - 17265 - ], - [ - 67, - -1 - ], - [ - 76, - 45 - ], - [ - 16, - 68 - ], - [ - 57, - 39 - ], - [ - -7, - 53 - ] - ], - [ - [ - 14394, - 17469 - ], - [ - 43, - 20 - ], - [ - 75, - 47 - ] - ], - [ - [ - 14512, - 17536 - ], - [ - 73, - -30 - ], - [ - 10, - -30 - ], - [ - 37, - 14 - ], - [ - 68, - -28 - ], - [ - 6, - -57 - ], - [ - -14, - -32 - ], - [ - 43, - -79 - ], - [ - 29, - -22 - ], - [ - -5, - -21 - ], - [ - 47, - -21 - ], - [ - 21, - -32 - ], - [ - -28, - -27 - ], - [ - -56, - 5 - ], - [ - -13, - -12 - ], - [ - 16, - -39 - ], - [ - 17, - -77 - ] - ], - [ - [ - 14763, - 17048 - ], - [ - -60, - -7 - ], - [ - -21, - -27 - ], - [ - -5, - -60 - ], - [ - -27, - 12 - ], - [ - -63, - -6 - ], - [ - -18, - 28 - ], - [ - -27, - -21 - ], - [ - -26, - 17 - ], - [ - -55, - 3 - ], - [ - -78, - 28 - ], - [ - -70, - 10 - ], - [ - -54, - -3 - ], - [ - -38, - -32 - ], - [ - -33, - -5 - ] - ], - [ - [ - 14188, - 16985 - ], - [ - -2, - 53 - ], - [ - -21, - 56 - ], - [ - 42, - 24 - ], - [ - 0, - 48 - ], - [ - -19, - 46 - ], - [ - -3, - 53 - ] - ], - [ - [ - 6333, - 12934 - ], - [ - 0, - 17 - ], - [ - 8, - 6 - ], - [ - 13, - -14 - ], - [ - 25, - 72 - ], - [ - 13, - 2 - ] - ], - [ - [ - 6392, - 13017 - ], - [ - 1, - -18 - ], - [ - 13, - -1 - ], - [ - -1, - -32 - ], - [ - -12, - -52 - ], - [ - 6, - -19 - ], - [ - -7, - -43 - ], - [ - 4, - -11 - ], - [ - -8, - -61 - ], - [ - -13, - -31 - ], - [ - -13, - -4 - ], - [ - -14, - -42 - ] - ], - [ - [ - 6348, - 12703 - ], - [ - -21, - 0 - ], - [ - 6, - 136 - ], - [ - 0, - 95 - ] - ], - [ - [ - 7870, - 8070 - ], - [ - -51, - -17 - ], - [ - -27, - 166 - ], - [ - -37, - 134 - ], - [ - 22, - 116 - ], - [ - -37, - 51 - ], - [ - -9, - 87 - ], - [ - -35, - 81 - ] - ], - [ - [ - 7696, - 8688 - ], - [ - 44, - 130 - ], - [ - -30, - 100 - ], - [ - 16, - 41 - ], - [ - -12, - 44 - ], - [ - 27, - 60 - ], - [ - 2, - 102 - ], - [ - 3, - 85 - ], - [ - 15, - 40 - ], - [ - -60, - 193 - ] - ], - [ - [ - 7701, - 9483 - ], - [ - 52, - -10 - ], - [ - 35, - 3 - ], - [ - 16, - 36 - ], - [ - 61, - 49 - ], - [ - 37, - 45 - ], - [ - 91, - 20 - ], - [ - -8, - -90 - ], - [ - 9, - -46 - ], - [ - -6, - -80 - ], - [ - 76, - -108 - ], - [ - 78, - -20 - ], - [ - 28, - -44 - ], - [ - 47, - -24 - ], - [ - 29, - -35 - ], - [ - 43, - 1 - ], - [ - 41, - -35 - ], - [ - 3, - -70 - ], - [ - 14, - -35 - ], - [ - 0, - -52 - ], - [ - -20, - -2 - ], - [ - 27, - -139 - ], - [ - 134, - -5 - ], - [ - -11, - -70 - ], - [ - 8, - -47 - ], - [ - 38, - -34 - ], - [ - 16, - -74 - ], - [ - -12, - -95 - ], - [ - -19, - -52 - ], - [ - 7, - -69 - ], - [ - -22, - -24 - ] - ], - [ - [ - 8493, - 8377 - ], - [ - -1, - 37 - ], - [ - -65, - 61 - ], - [ - -65, - 2 - ], - [ - -122, - -35 - ], - [ - -33, - -106 - ], - [ - -2, - -64 - ], - [ - -27, - -144 - ] - ], - [ - [ - 8740, - 7709 - ], - [ - 13, - 70 - ], - [ - 10, - 70 - ], - [ - 0, - 66 - ], - [ - -25, - 22 - ], - [ - -26, - -19 - ], - [ - -26, - 5 - ], - [ - -9, - 46 - ], - [ - -6, - 110 - ], - [ - -13, - 36 - ], - [ - -47, - 33 - ], - [ - -29, - -24 - ], - [ - -73, - 23 - ], - [ - 4, - 163 - ], - [ - -20, - 67 - ] - ], - [ - [ - 7701, - 9483 - ], - [ - -40, - -20 - ], - [ - -31, - 13 - ], - [ - 4, - 183 - ], - [ - -57, - -71 - ], - [ - -61, - 3 - ], - [ - -27, - 64 - ], - [ - -46, - 7 - ], - [ - 15, - 52 - ], - [ - -39, - 73 - ], - [ - -29, - 108 - ], - [ - 18, - 22 - ], - [ - 0, - 50 - ], - [ - 42, - 35 - ], - [ - -7, - 65 - ], - [ - 18, - 41 - ], - [ - 5, - 56 - ], - [ - 80, - 82 - ], - [ - 57, - 23 - ], - [ - 10, - 18 - ], - [ - 62, - -5 - ] - ], - [ - [ - 7675, - 10282 - ], - [ - 32, - 328 - ], - [ - 1, - 53 - ], - [ - -11, - 68 - ], - [ - -31, - 44 - ], - [ - 1, - 87 - ], - [ - 39, - 20 - ], - [ - 14, - -13 - ], - [ - 2, - 46 - ], - [ - -40, - 13 - ], - [ - -1, - 75 - ], - [ - 135, - -3 - ], - [ - 24, - 42 - ], - [ - 19, - -38 - ], - [ - 14, - -71 - ], - [ - 13, - 15 - ] - ], - [ - [ - 7886, - 10948 - ], - [ - 38, - -64 - ], - [ - 54, - 8 - ], - [ - 14, - 37 - ], - [ - 52, - 28 - ], - [ - 28, - 19 - ], - [ - 8, - 51 - ], - [ - 50, - 34 - ], - [ - -4, - 25 - ], - [ - -59, - 11 - ], - [ - -9, - 75 - ], - [ - 2, - 81 - ], - [ - -31, - 31 - ], - [ - 13, - 11 - ], - [ - 52, - -15 - ], - [ - 55, - -30 - ], - [ - 21, - 28 - ], - [ - 50, - 19 - ], - [ - 78, - 44 - ], - [ - 25, - 46 - ], - [ - -9, - 34 - ] - ], - [ - [ - 8314, - 11421 - ], - [ - 36, - 5 - ], - [ - 16, - -27 - ], - [ - -9, - -53 - ], - [ - 24, - -18 - ], - [ - 16, - -56 - ], - [ - -19, - -42 - ], - [ - -11, - -102 - ], - [ - 18, - -61 - ], - [ - 5, - -55 - ], - [ - 43, - -57 - ], - [ - 34, - -6 - ], - [ - 7, - 24 - ], - [ - 23, - 5 - ], - [ - 31, - 21 - ], - [ - 23, - 32 - ], - [ - 38, - -10 - ], - [ - 17, - 4 - ] - ], - [ - [ - 8606, - 11025 - ], - [ - 38, - -10 - ], - [ - 6, - 25 - ], - [ - -11, - 24 - ], - [ - 7, - 34 - ], - [ - 28, - -10 - ], - [ - 33, - 12 - ], - [ - 40, - -25 - ] - ], - [ - [ - 8747, - 11075 - ], - [ - 30, - -25 - ], - [ - 22, - 32 - ], - [ - 15, - -5 - ], - [ - 10, - -33 - ], - [ - 33, - 8 - ], - [ - 27, - 46 - ], - [ - 21, - 88 - ], - [ - 42, - 110 - ] - ], - [ - [ - 8947, - 11296 - ], - [ - 23, - 5 - ], - [ - 18, - -66 - ], - [ - 39, - -210 - ], - [ - 37, - -19 - ], - [ - 2, - -83 - ], - [ - -53, - -99 - ], - [ - 22, - -36 - ], - [ - 123, - -19 - ], - [ - 3, - -120 - ], - [ - 53, - 78 - ], - [ - 87, - -43 - ], - [ - 116, - -73 - ], - [ - 34, - -70 - ], - [ - -11, - -67 - ], - [ - 81, - 37 - ], - [ - 136, - -63 - ], - [ - 104, - 5 - ], - [ - 103, - -100 - ], - [ - 89, - -134 - ], - [ - 53, - -35 - ], - [ - 60, - -5 - ], - [ - 25, - -37 - ], - [ - 24, - -153 - ], - [ - 12, - -73 - ], - [ - -28, - -198 - ], - [ - -36, - -78 - ], - [ - -98, - -167 - ], - [ - -44, - -136 - ], - [ - -52, - -104 - ], - [ - -17, - -2 - ], - [ - -20, - -89 - ], - [ - 5, - -224 - ], - [ - -19, - -185 - ], - [ - -8, - -79 - ], - [ - -22, - -48 - ], - [ - -12, - -160 - ], - [ - -71, - -157 - ], - [ - -12, - -124 - ], - [ - -56, - -52 - ], - [ - -16, - -71 - ], - [ - -76, - 0 - ], - [ - -110, - -46 - ], - [ - -49, - -54 - ], - [ - -78, - -35 - ], - [ - -82, - -95 - ], - [ - -59, - -119 - ], - [ - -10, - -90 - ], - [ - 11, - -66 - ], - [ - -13, - -121 - ], - [ - -15, - -59 - ], - [ - -49, - -66 - ], - [ - -77, - -211 - ], - [ - -62, - -95 - ], - [ - -47, - -56 - ], - [ - -32, - -114 - ], - [ - -46, - -69 - ] - ], - [ - [ - 8827, - 6746 - ], - [ - -19, - 68 - ], - [ - 30, - 57 - ], - [ - -40, - 82 - ], - [ - -55, - 66 - ], - [ - -71, - 77 - ], - [ - -26, - -4 - ], - [ - -70, - 93 - ], - [ - -45, - -13 - ] - ], - [ - [ - 20508, - 11340 - ], - [ - 28, - 45 - ], - [ - 59, - 66 - ] - ], - [ - [ - 20595, - 11451 - ], - [ - -3, - -59 - ], - [ - -4, - -77 - ], - [ - -33, - 4 - ], - [ - -15, - -41 - ], - [ - -32, - 62 - ] - ], - [ - [ - 18940, - 14129 - ], - [ - 28, - -38 - ], - [ - -5, - -74 - ], - [ - -57, - -4 - ], - [ - -59, - 8 - ], - [ - -44, - -18 - ], - [ - -63, - 45 - ], - [ - -1, - 24 - ] - ], - [ - [ - 18739, - 14072 - ], - [ - 46, - 89 - ], - [ - 37, - 31 - ], - [ - 50, - -28 - ], - [ - 37, - -3 - ], - [ - 31, - -32 - ] - ], - [ - [ - 14599, - 8147 - ], - [ - -98, - -88 - ], - [ - -63, - -90 - ], - [ - -23, - -80 - ], - [ - -21, - -45 - ], - [ - -38, - -10 - ], - [ - -12, - -57 - ], - [ - -7, - -37 - ], - [ - -45, - -28 - ], - [ - -57, - 6 - ], - [ - -33, - 33 - ], - [ - -29, - 15 - ], - [ - -34, - -28 - ], - [ - -18, - -58 - ], - [ - -33, - -36 - ], - [ - -34, - -53 - ], - [ - -50, - -12 - ], - [ - -16, - 42 - ], - [ - 7, - 73 - ], - [ - -42, - 114 - ], - [ - -19, - 18 - ] - ], - [ - [ - 13934, - 7826 - ], - [ - 0, - 350 - ], - [ - 69, - 4 - ], - [ - 2, - 427 - ], - [ - 52, - 4 - ], - [ - 108, - 42 - ], - [ - 26, - -49 - ], - [ - 45, - 47 - ], - [ - 21, - 0 - ], - [ - 39, - 27 - ] - ], - [ - [ - 14296, - 8678 - ], - [ - 13, - -9 - ] - ], - [ - [ - 14309, - 8669 - ], - [ - 26, - -96 - ], - [ - 14, - -21 - ], - [ - 22, - -69 - ], - [ - 79, - -132 - ], - [ - 30, - -13 - ], - [ - 0, - -42 - ], - [ - 21, - -76 - ], - [ - 54, - -19 - ], - [ - 44, - -54 - ] - ], - [ - [ - 13613, - 11688 - ], - [ - 57, - 9 - ], - [ - 13, - 30 - ], - [ - 12, - -2 - ], - [ - 17, - -27 - ], - [ - 88, - 46 - ], - [ - 29, - 47 - ], - [ - 37, - 42 - ], - [ - -7, - 42 - ], - [ - 20, - 11 - ], - [ - 67, - -8 - ], - [ - 65, - 56 - ], - [ - 51, - 131 - ], - [ - 35, - 48 - ], - [ - 44, - 21 - ] - ], - [ - [ - 14141, - 12134 - ], - [ - 8, - -51 - ], - [ - 40, - -75 - ], - [ - 1, - -49 - ], - [ - -12, - -50 - ], - [ - 5, - -38 - ], - [ - 24, - -34 - ], - [ - 53, - -53 - ] - ], - [ - [ - 14260, - 11784 - ], - [ - 38, - -48 - ], - [ - 1, - -39 - ], - [ - 47, - -63 - ], - [ - 29, - -51 - ], - [ - 17, - -72 - ], - [ - 53, - -48 - ], - [ - 11, - -38 - ] - ], - [ - [ - 14456, - 11425 - ], - [ - -23, - -13 - ], - [ - -45, - 3 - ], - [ - -52, - 13 - ], - [ - -26, - -11 - ], - [ - -11, - -29 - ], - [ - -22, - -3 - ], - [ - -28, - 25 - ], - [ - -77, - -60 - ], - [ - -32, - 12 - ], - [ - -10, - -9 - ], - [ - -21, - -72 - ], - [ - -52, - 23 - ], - [ - -51, - 12 - ], - [ - -44, - 44 - ], - [ - -57, - 41 - ], - [ - -38, - -39 - ], - [ - -27, - -61 - ], - [ - -6, - -83 - ] - ], - [ - [ - 13834, - 11218 - ], - [ - -45, - 6 - ], - [ - -47, - 20 - ], - [ - -42, - -63 - ], - [ - -36, - -112 - ] - ], - [ - [ - 13664, - 11069 - ], - [ - -8, - 35 - ], - [ - -3, - 55 - ], - [ - -32, - 38 - ], - [ - -25, - 62 - ], - [ - -6, - 43 - ], - [ - -33, - 63 - ], - [ - 5, - 36 - ], - [ - -7, - 50 - ], - [ - 6, - 93 - ], - [ - 17, - 22 - ], - [ - 35, - 122 - ] - ], - [ - [ - 8110, - 16382 - ], - [ - 50, - -16 - ], - [ - 65, - 3 - ], - [ - -35, - -49 - ], - [ - -25, - -8 - ], - [ - -89, - 51 - ], - [ - -17, - 40 - ], - [ - 26, - 37 - ], - [ - 25, - -58 - ] - ], - [ - [ - 8239, - 16688 - ], - [ - -34, - -2 - ], - [ - -90, - 38 - ], - [ - -65, - 56 - ], - [ - 24, - 10 - ], - [ - 92, - -30 - ], - [ - 71, - -50 - ], - [ - 2, - -22 - ] - ], - [ - [ - 3938, - 16617 - ], - [ - -35, - -17 - ], - [ - -115, - 55 - ], - [ - -21, - 42 - ], - [ - -62, - 42 - ], - [ - -13, - 34 - ], - [ - -71, - 22 - ], - [ - -27, - 65 - ], - [ - 6, - 28 - ], - [ - 73, - -26 - ], - [ - 43, - -18 - ], - [ - 65, - -13 - ], - [ - 24, - -41 - ], - [ - 34, - -57 - ], - [ - 70, - -50 - ], - [ - 29, - -66 - ] - ], - [ - [ - 8634, - 16878 - ], - [ - -46, - -105 - ], - [ - 46, - 41 - ], - [ - 47, - -26 - ], - [ - -25, - -42 - ], - [ - 62, - -33 - ], - [ - 32, - 29 - ], - [ - 70, - -36 - ], - [ - -22, - -88 - ], - [ - 49, - 20 - ], - [ - 9, - -63 - ], - [ - 21, - -75 - ], - [ - -29, - -106 - ], - [ - -31, - -4 - ], - [ - -46, - 23 - ], - [ - 15, - 98 - ], - [ - -20, - 15 - ], - [ - -80, - -104 - ], - [ - -42, - 4 - ], - [ - 49, - 56 - ], - [ - -67, - 30 - ], - [ - -75, - -8 - ], - [ - -135, - 4 - ], - [ - -11, - 36 - ], - [ - 44, - 42 - ], - [ - -30, - 32 - ], - [ - 58, - 73 - ], - [ - 72, - 191 - ], - [ - 43, - 68 - ], - [ - 61, - 41 - ], - [ - 32, - -5 - ], - [ - -13, - -32 - ], - [ - -38, - -76 - ] - ], - [ - [ - 3264, - 17296 - ], - [ - 33, - -16 - ], - [ - 66, - 10 - ], - [ - -20, - -136 - ], - [ - 60, - -97 - ], - [ - -28, - 0 - ], - [ - -42, - 55 - ], - [ - -25, - 56 - ], - [ - -36, - 37 - ], - [ - -12, - 53 - ], - [ - 4, - 38 - ] - ], - [ - [ - 7022, - 18254 - ], - [ - -27, - -63 - ], - [ - -31, - 10 - ], - [ - -18, - 36 - ], - [ - 3, - 9 - ], - [ - 27, - 36 - ], - [ - 28, - -3 - ], - [ - 18, - -25 - ] - ], - [ - [ - 6839, - 18321 - ], - [ - -82, - -67 - ], - [ - -49, - 3 - ], - [ - -16, - 33 - ], - [ - 52, - 55 - ], - [ - 96, - -1 - ], - [ - -1, - -23 - ] - ], - [ - [ - 6611, - 18674 - ], - [ - 13, - -53 - ], - [ - 36, - 19 - ], - [ - 40, - -32 - ], - [ - 77, - -41 - ], - [ - 79, - -37 - ], - [ - 7, - -57 - ], - [ - 51, - 9 - ], - [ - 50, - -40 - ], - [ - -62, - -37 - ], - [ - -109, - 28 - ], - [ - -39, - 54 - ], - [ - -69, - -63 - ], - [ - -99, - -62 - ], - [ - -24, - 70 - ], - [ - -95, - -12 - ], - [ - 61, - 59 - ], - [ - 9, - 95 - ], - [ - 24, - 110 - ], - [ - 50, - -10 - ] - ], - [ - [ - 7259, - 18853 - ], - [ - -78, - -6 - ], - [ - -18, - 59 - ], - [ - 30, - 67 - ], - [ - 64, - 17 - ], - [ - 54, - -34 - ], - [ - 1, - -51 - ], - [ - -8, - -17 - ], - [ - -45, - -35 - ] - ], - [ - [ - 5880, - 19088 - ], - [ - -43, - -42 - ], - [ - -94, - 36 - ], - [ - -57, - -13 - ], - [ - -95, - 54 - ], - [ - 61, - 37 - ], - [ - 49, - 52 - ], - [ - 74, - -34 - ], - [ - 42, - -21 - ], - [ - 21, - -23 - ], - [ - 42, - -46 - ] - ], - [ - [ - 3985, - 16676 - ], - [ - -10, - 0 - ], - [ - -135, - 118 - ], - [ - -50, - 52 - ], - [ - -126, - 49 - ], - [ - -39, - 106 - ], - [ - 10, - 74 - ], - [ - -89, - 51 - ], - [ - -12, - 97 - ], - [ - -84, - 87 - ], - [ - -2, - 62 - ] - ], - [ - [ - 3448, - 17372 - ], - [ - 39, - 58 - ], - [ - -2, - 75 - ], - [ - -119, - 77 - ], - [ - -71, - 137 - ], - [ - -43, - 86 - ], - [ - -64, - 54 - ], - [ - -47, - 49 - ], - [ - -37, - 62 - ], - [ - -70, - -39 - ], - [ - -68, - -67 - ], - [ - -62, - 79 - ], - [ - -49, - 52 - ], - [ - -68, - 34 - ], - [ - -68, - 3 - ], - [ - 0, - 683 - ], - [ - 1, - 445 - ] - ], - [ - [ - 2720, - 19160 - ], - [ - 130, - -28 - ], - [ - 109, - -58 - ], - [ - 73, - -11 - ], - [ - 61, - 50 - ], - [ - 85, - 37 - ], - [ - 103, - -14 - ], - [ - 105, - 52 - ], - [ - 114, - 30 - ], - [ - 48, - -49 - ], - [ - 52, - 28 - ], - [ - 15, - 56 - ], - [ - 48, - -13 - ], - [ - 118, - -107 - ], - [ - 93, - 81 - ], - [ - 9, - -91 - ], - [ - 86, - 20 - ], - [ - 26, - 35 - ], - [ - 85, - -7 - ], - [ - 106, - -51 - ], - [ - 164, - -44 - ], - [ - 96, - -20 - ], - [ - 68, - 8 - ], - [ - 94, - -61 - ], - [ - -98, - -60 - ], - [ - 126, - -25 - ], - [ - 188, - 14 - ], - [ - 59, - 21 - ], - [ - 75, - -72 - ], - [ - 75, - 61 - ], - [ - -71, - 50 - ], - [ - 45, - 42 - ], - [ - 85, - 5 - ], - [ - 56, - 12 - ], - [ - 56, - -29 - ], - [ - 70, - -65 - ], - [ - 78, - 10 - ], - [ - 123, - -54 - ], - [ - 109, - 19 - ], - [ - 101, - -3 - ], - [ - -8, - 75 - ], - [ - 62, - 20 - ], - [ - 108, - -40 - ], - [ - 0, - -114 - ], - [ - 44, - 96 - ], - [ - 56, - -3 - ], - [ - 32, - 120 - ], - [ - -75, - 74 - ], - [ - -81, - 49 - ], - [ - 5, - 132 - ], - [ - 83, - 87 - ], - [ - 92, - -19 - ], - [ - 70, - -53 - ], - [ - 95, - -135 - ], - [ - -62, - -59 - ], - [ - 130, - -24 - ], - [ - -1, - -123 - ], - [ - 93, - 94 - ], - [ - 84, - -77 - ], - [ - -21, - -89 - ], - [ - 67, - -81 - ], - [ - 73, - 87 - ], - [ - 51, - 103 - ], - [ - 4, - 132 - ], - [ - 99, - -9 - ], - [ - 103, - -18 - ], - [ - 94, - -60 - ], - [ - 4, - -59 - ], - [ - -52, - -64 - ], - [ - 49, - -64 - ], - [ - -9, - -59 - ], - [ - -136, - -83 - ], - [ - -97, - -19 - ], - [ - -72, - 36 - ], - [ - -21, - -60 - ], - [ - -67, - -101 - ], - [ - -21, - -53 - ], - [ - -80, - -81 - ], - [ - -100, - -8 - ], - [ - -55, - -51 - ], - [ - -5, - -78 - ], - [ - -81, - -15 - ], - [ - -85, - -97 - ], - [ - -76, - -135 - ], - [ - -27, - -94 - ], - [ - -4, - -140 - ], - [ - 103, - -20 - ], - [ - 31, - -112 - ], - [ - 33, - -91 - ], - [ - 97, - 24 - ], - [ - 130, - -52 - ], - [ - 69, - -46 - ], - [ - 50, - -57 - ], - [ - 88, - -33 - ], - [ - 73, - -50 - ], - [ - 116, - -7 - ], - [ - 75, - -12 - ], - [ - -11, - -104 - ], - [ - 22, - -120 - ], - [ - 50, - -134 - ], - [ - 104, - -114 - ], - [ - 54, - 39 - ], - [ - 37, - 123 - ], - [ - -36, - 189 - ], - [ - -49, - 64 - ], - [ - 111, - 56 - ], - [ - 79, - 84 - ], - [ - 39, - 84 - ], - [ - -6, - 80 - ], - [ - -47, - 102 - ], - [ - -85, - 90 - ], - [ - 82, - 126 - ], - [ - -30, - 108 - ], - [ - -23, - 188 - ], - [ - 48, - 27 - ], - [ - 120, - -32 - ], - [ - 72, - -12 - ], - [ - 57, - 32 - ], - [ - 65, - -41 - ], - [ - 86, - -70 - ], - [ - 21, - -46 - ], - [ - 124, - -9 - ], - [ - -2, - -101 - ], - [ - 24, - -152 - ], - [ - 63, - -19 - ], - [ - 51, - -70 - ], - [ - 101, - 66 - ], - [ - 66, - 133 - ], - [ - 46, - 56 - ], - [ - 55, - -108 - ], - [ - 91, - -153 - ], - [ - 77, - -143 - ], - [ - -28, - -76 - ], - [ - 92, - -67 - ], - [ - 63, - -69 - ], - [ - 111, - -31 - ], - [ - 45, - -38 - ], - [ - 28, - -102 - ], - [ - 54, - -16 - ], - [ - 28, - -45 - ], - [ - 5, - -135 - ], - [ - -51, - -45 - ], - [ - -50, - -42 - ], - [ - -115, - -43 - ], - [ - -87, - -98 - ], - [ - -118, - -20 - ], - [ - -149, - 26 - ], - [ - -105, - 0 - ], - [ - -72, - -8 - ], - [ - -58, - -86 - ], - [ - -89, - -53 - ], - [ - -101, - -159 - ], - [ - -80, - -111 - ], - [ - 59, - 20 - ], - [ - 112, - 158 - ], - [ - 146, - 100 - ], - [ - 105, - 12 - ], - [ - 61, - -59 - ], - [ - -66, - -81 - ], - [ - 23, - -129 - ], - [ - 22, - -91 - ], - [ - 91, - -60 - ], - [ - 115, - 18 - ], - [ - 70, - 135 - ], - [ - 5, - -87 - ], - [ - 45, - -44 - ], - [ - -86, - -78 - ], - [ - -155, - -72 - ], - [ - -69, - -48 - ], - [ - -78, - -87 - ], - [ - -53, - 9 - ], - [ - -3, - 102 - ], - [ - 122, - 99 - ], - [ - -112, - -4 - ], - [ - -78, - -15 - ] - ], - [ - [ - 7867, - 16212 - ], - [ - -45, - 68 - ], - [ - 0, - 164 - ], - [ - -31, - 34 - ], - [ - -47, - -20 - ], - [ - -23, - 31 - ], - [ - -53, - -90 - ], - [ - -21, - -93 - ], - [ - -25, - -55 - ], - [ - -30, - -19 - ], - [ - -22, - -6 - ], - [ - -7, - -29 - ], - [ - -128, - 0 - ], - [ - -106, - -1 - ], - [ - -32, - -22 - ], - [ - -73, - -87 - ], - [ - -9, - -9 - ], - [ - -22, - -47 - ], - [ - -64, - 0 - ], - [ - -69, - 0 - ], - [ - -31, - -19 - ], - [ - 11, - -24 - ], - [ - 6, - -36 - ], - [ - -1, - -13 - ], - [ - -91, - -59 - ], - [ - -72, - -19 - ], - [ - -81, - -64 - ], - [ - -18, - 0 - ], - [ - -23, - 19 - ], - [ - -8, - 17 - ], - [ - 1, - 12 - ], - [ - 16, - 42 - ], - [ - 32, - 66 - ], - [ - 21, - 71 - ], - [ - -14, - 105 - ], - [ - -15, - 108 - ], - [ - -73, - 57 - ], - [ - 9, - 21 - ], - [ - -10, - 15 - ], - [ - -19, - 0 - ], - [ - -14, - 19 - ], - [ - -4, - 28 - ], - [ - -13, - -12 - ], - [ - -19, - 3 - ], - [ - 4, - 12 - ], - [ - -16, - 12 - ], - [ - -7, - 32 - ], - [ - -54, - 38 - ], - [ - -57, - 40 - ], - [ - -68, - 46 - ], - [ - -65, - 44 - ], - [ - -63, - -34 - ], - [ - -22, - -1 - ], - [ - -86, - 31 - ], - [ - -57, - -16 - ], - [ - -67, - 38 - ], - [ - -71, - 19 - ], - [ - -49, - 7 - ], - [ - -22, - 20 - ], - [ - -12, - 66 - ], - [ - -24, - 0 - ], - [ - 0, - -46 - ], - [ - -144, - 0 - ], - [ - -239, - 0 - ], - [ - -237, - 0 - ], - [ - -209, - 0 - ], - [ - -209, - 0 - ], - [ - -206, - 0 - ], - [ - -212, - 0 - ], - [ - -69, - 0 - ], - [ - -207, - 0 - ], - [ - -197, - 0 - ] - ], - [ - [ - 4589, - 19569 - ], - [ - -35, - -56 - ], - [ - 155, - 37 - ], - [ - 97, - -61 - ], - [ - 79, - 61 - ], - [ - 64, - -39 - ], - [ - 57, - -118 - ], - [ - 35, - 50 - ], - [ - -50, - 123 - ], - [ - 62, - 17 - ], - [ - 69, - -19 - ], - [ - 78, - -48 - ], - [ - 44, - -117 - ], - [ - 21, - -85 - ], - [ - 118, - -59 - ], - [ - 125, - -57 - ], - [ - -7, - -53 - ], - [ - -115, - -9 - ], - [ - 45, - -47 - ], - [ - -24, - -44 - ], - [ - -126, - 19 - ], - [ - -120, - 33 - ], - [ - -81, - -8 - ], - [ - -131, - -40 - ], - [ - -176, - -18 - ], - [ - -124, - -12 - ], - [ - -38, - 57 - ], - [ - -95, - 33 - ], - [ - -62, - -14 - ], - [ - -86, - 95 - ], - [ - 46, - 13 - ], - [ - 108, - 20 - ], - [ - 98, - -5 - ], - [ - 91, - 21 - ], - [ - -135, - 28 - ], - [ - -149, - -10 - ], - [ - -98, - 3 - ], - [ - -37, - 44 - ], - [ - 161, - 48 - ], - [ - -107, - -2 - ], - [ - -122, - 32 - ], - [ - 59, - 90 - ], - [ - 48, - 48 - ], - [ - 187, - 73 - ], - [ - 71, - -24 - ] - ], - [ - [ - 5263, - 19605 - ], - [ - -61, - -79 - ], - [ - -109, - 84 - ], - [ - 24, - 17 - ], - [ - 93, - 5 - ], - [ - 53, - -27 - ] - ], - [ - [ - 7226, - 19567 - ], - [ - 6, - -33 - ], - [ - -74, - 4 - ], - [ - -75, - 2 - ], - [ - -76, - -16 - ], - [ - -21, - 7 - ], - [ - -76, - 64 - ], - [ - 3, - 43 - ], - [ - 33, - 8 - ], - [ - 160, - -13 - ], - [ - 120, - -66 - ] - ], - [ - [ - 6513, - 19574 - ], - [ - 55, - -75 - ], - [ - 65, - 97 - ], - [ - 176, - 49 - ], - [ - 120, - -124 - ], - [ - -10, - -79 - ], - [ - 138, - 35 - ], - [ - 65, - 48 - ], - [ - 155, - -61 - ], - [ - 96, - -57 - ], - [ - 9, - -52 - ], - [ - 130, - 27 - ], - [ - 72, - -77 - ], - [ - 169, - -47 - ], - [ - 60, - -48 - ], - [ - 66, - -113 - ], - [ - -128, - -56 - ], - [ - 164, - -78 - ], - [ - 111, - -26 - ], - [ - 100, - -110 - ], - [ - 110, - -8 - ], - [ - -22, - -85 - ], - [ - -122, - -139 - ], - [ - -86, - 51 - ], - [ - -110, - 116 - ], - [ - -90, - -15 - ], - [ - -9, - -69 - ], - [ - 74, - -70 - ], - [ - 94, - -55 - ], - [ - 29, - -32 - ], - [ - 46, - -119 - ], - [ - -25, - -86 - ], - [ - -87, - 33 - ], - [ - -175, - 96 - ], - [ - 98, - -104 - ], - [ - 73, - -72 - ], - [ - 11, - -42 - ], - [ - -189, - 48 - ], - [ - -149, - 70 - ], - [ - -85, - 58 - ], - [ - 24, - 34 - ], - [ - -104, - 61 - ], - [ - -101, - 59 - ], - [ - 1, - -35 - ], - [ - -202, - -19 - ], - [ - -59, - 41 - ], - [ - 46, - 88 - ], - [ - 131, - 2 - ], - [ - 144, - 16 - ], - [ - -23, - 43 - ], - [ - 24, - 59 - ], - [ - 90, - 117 - ], - [ - -19, - 53 - ], - [ - -27, - 41 - ], - [ - -107, - 59 - ], - [ - -141, - 40 - ], - [ - 45, - 31 - ], - [ - -74, - 74 - ], - [ - -62, - 7 - ], - [ - -54, - 41 - ], - [ - -38, - -35 - ], - [ - -126, - -16 - ], - [ - -254, - 27 - ], - [ - -147, - 35 - ], - [ - -113, - 18 - ], - [ - -58, - 42 - ], - [ - 73, - 55 - ], - [ - -99, - 1 - ], - [ - -23, - 121 - ], - [ - 54, - 107 - ], - [ - 72, - 49 - ], - [ - 180, - 32 - ], - [ - -52, - -77 - ] - ], - [ - [ - 5552, - 19656 - ], - [ - 83, - -25 - ], - [ - 124, - 15 - ], - [ - 18, - -35 - ], - [ - -65, - -57 - ], - [ - 106, - -52 - ], - [ - -13, - -108 - ], - [ - -114, - -46 - ], - [ - -67, - 10 - ], - [ - -48, - 46 - ], - [ - -174, - 92 - ], - [ - 2, - 39 - ], - [ - 142, - -15 - ], - [ - -77, - 78 - ], - [ - 83, - 58 - ] - ], - [ - [ - 6051, - 19528 - ], - [ - -75, - -90 - ], - [ - -79, - 4 - ], - [ - -44, - 106 - ], - [ - 1, - 59 - ], - [ - 37, - 51 - ], - [ - 69, - 33 - ], - [ - 145, - -4 - ], - [ - 133, - -29 - ], - [ - -104, - -107 - ], - [ - -83, - -23 - ] - ], - [ - [ - 4150, - 19361 - ], - [ - -183, - -58 - ], - [ - -37, - 53 - ], - [ - -161, - 63 - ], - [ - 30, - 51 - ], - [ - 48, - 88 - ], - [ - 61, - 78 - ], - [ - -68, - 74 - ], - [ - 235, - 19 - ], - [ - 100, - -25 - ], - [ - 178, - -7 - ], - [ - 68, - -35 - ], - [ - 74, - -50 - ], - [ - -87, - -30 - ], - [ - -171, - -85 - ], - [ - -87, - -84 - ], - [ - 0, - -52 - ] - ], - [ - [ - 6022, - 19792 - ], - [ - -38, - -46 - ], - [ - -101, - 9 - ], - [ - -85, - 31 - ], - [ - 37, - 54 - ], - [ - 101, - 32 - ], - [ - 60, - -42 - ], - [ - 26, - -38 - ] - ], - [ - [ - 5681, - 20001 - ], - [ - 54, - -55 - ], - [ - 2, - -62 - ], - [ - -32, - -89 - ], - [ - -115, - -12 - ], - [ - -75, - 19 - ], - [ - 2, - 70 - ], - [ - -115, - -10 - ], - [ - -4, - 93 - ], - [ - 75, - -4 - ], - [ - 105, - 41 - ], - [ - 98, - -7 - ], - [ - 5, - 16 - ] - ], - [ - [ - 5004, - 19939 - ], - [ - 28, - -43 - ], - [ - 62, - 20 - ], - [ - 73, - -5 - ], - [ - 12, - -59 - ], - [ - -42, - -57 - ], - [ - -237, - -18 - ], - [ - -175, - -52 - ], - [ - -106, - -3 - ], - [ - -9, - 39 - ], - [ - 145, - 53 - ], - [ - -315, - -14 - ], - [ - -98, - 22 - ], - [ - 95, - 117 - ], - [ - 66, - 33 - ], - [ - 196, - -40 - ], - [ - 124, - -71 - ], - [ - 122, - -9 - ], - [ - -100, - 114 - ], - [ - 64, - 44 - ], - [ - 72, - -14 - ], - [ - 23, - -57 - ] - ], - [ - [ - 5947, - 20047 - ], - [ - 78, - -39 - ], - [ - 137, - 0 - ], - [ - 60, - -39 - ], - [ - -16, - -45 - ], - [ - 80, - -27 - ], - [ - 44, - -29 - ], - [ - 94, - -5 - ], - [ - 102, - -10 - ], - [ - 111, - 26 - ], - [ - 142, - 10 - ], - [ - 113, - -8 - ], - [ - 75, - -46 - ], - [ - 15, - -49 - ], - [ - -43, - -32 - ], - [ - -104, - -26 - ], - [ - -89, - 15 - ], - [ - -200, - -19 - ], - [ - -143, - -2 - ], - [ - -113, - 15 - ], - [ - -185, - 38 - ], - [ - -24, - 66 - ], - [ - -9, - 60 - ], - [ - -70, - 52 - ], - [ - -144, - 15 - ], - [ - -81, - 37 - ], - [ - 27, - 49 - ], - [ - 143, - -7 - ] - ], - [ - [ - 4447, - 20112 - ], - [ - -9, - -92 - ], - [ - -54, - -42 - ], - [ - -65, - -5 - ], - [ - -129, - -52 - ], - [ - -112, - -18 - ], - [ - -95, - 26 - ], - [ - 119, - 90 - ], - [ - 143, - 77 - ], - [ - 107, - -1 - ], - [ - 95, - 17 - ] - ], - [ - [ - 6006, - 20097 - ], - [ - -32, - -3 - ], - [ - -130, - 7 - ], - [ - -19, - 34 - ], - [ - 140, - -2 - ], - [ - 49, - -22 - ], - [ - -8, - -14 - ] - ], - [ - [ - 4867, - 20118 - ], - [ - -130, - -34 - ], - [ - -104, - 39 - ], - [ - 57, - 38 - ], - [ - 101, - 12 - ], - [ - 99, - -19 - ], - [ - -23, - -36 - ] - ], - [ - [ - 4903, - 20227 - ], - [ - -85, - -23 - ], - [ - -116, - 0 - ], - [ - 2, - 17 - ], - [ - 71, - 36 - ], - [ - 37, - -6 - ], - [ - 91, - -24 - ] - ], - [ - [ - 5867, - 20162 - ], - [ - -103, - -25 - ], - [ - -57, - 28 - ], - [ - -29, - 45 - ], - [ - -6, - 49 - ], - [ - 90, - -4 - ], - [ - 41, - -8 - ], - [ - 83, - -42 - ], - [ - -19, - -43 - ] - ], - [ - [ - 5572, - 20194 - ], - [ - 28, - -50 - ], - [ - -114, - 13 - ], - [ - -115, - 39 - ], - [ - -155, - 4 - ], - [ - 67, - 36 - ], - [ - -84, - 29 - ], - [ - -5, - 46 - ], - [ - 137, - -16 - ], - [ - 188, - -44 - ], - [ - 53, - -57 - ] - ], - [ - [ - 6481, - 20354 - ], - [ - 85, - -39 - ], - [ - -96, - -36 - ], - [ - -129, - -90 - ], - [ - -123, - -8 - ], - [ - -145, - 15 - ], - [ - -75, - 49 - ], - [ - 1, - 43 - ], - [ - 56, - 32 - ], - [ - -128, - -1 - ], - [ - -77, - 40 - ], - [ - -44, - 55 - ], - [ - 48, - 53 - ], - [ - 49, - 37 - ], - [ - 71, - 8 - ], - [ - -30, - 27 - ], - [ - 162, - 7 - ], - [ - 89, - -65 - ], - [ - 117, - -25 - ], - [ - 114, - -23 - ], - [ - 55, - -79 - ] - ], - [ - [ - 7772, - 20767 - ], - [ - 187, - -9 - ], - [ - 149, - -15 - ], - [ - 128, - -33 - ], - [ - -3, - -32 - ], - [ - -170, - -52 - ], - [ - -169, - -24 - ], - [ - -63, - -27 - ], - [ - 152, - 0 - ], - [ - -165, - -72 - ], - [ - -113, - -34 - ], - [ - -119, - -98 - ], - [ - -144, - -20 - ], - [ - -45, - -25 - ], - [ - -211, - -13 - ], - [ - 96, - -15 - ], - [ - -48, - -21 - ], - [ - 58, - -59 - ], - [ - -66, - -41 - ], - [ - -108, - -34 - ], - [ - -33, - -47 - ], - [ - -97, - -36 - ], - [ - 9, - -27 - ], - [ - 119, - 4 - ], - [ - 2, - -29 - ], - [ - -186, - -72 - ], - [ - -182, - 33 - ], - [ - -205, - -18 - ], - [ - -104, - 14 - ], - [ - -132, - 6 - ], - [ - -8, - 58 - ], - [ - 128, - 27 - ], - [ - -34, - 87 - ], - [ - 43, - 8 - ], - [ - 186, - -52 - ], - [ - -95, - 77 - ], - [ - -113, - 23 - ], - [ - 56, - 47 - ], - [ - 124, - 28 - ], - [ - 20, - 42 - ], - [ - -99, - 47 - ], - [ - -29, - 62 - ], - [ - 190, - -5 - ], - [ - 55, - -13 - ], - [ - 109, - 43 - ], - [ - -157, - 14 - ], - [ - -244, - -7 - ], - [ - -123, - 40 - ], - [ - -58, - 49 - ], - [ - -82, - 35 - ], - [ - -15, - 41 - ], - [ - 104, - 23 - ], - [ - 81, - 4 - ], - [ - 137, - 19 - ], - [ - 102, - 45 - ], - [ - 87, - -6 - ], - [ - 75, - -34 - ], - [ - 53, - 65 - ], - [ - 92, - 19 - ], - [ - 125, - 13 - ], - [ - 213, - 5 - ], - [ - 37, - -13 - ], - [ - 202, - 21 - ], - [ - 151, - -8 - ], - [ - 150, - -8 - ] - ], - [ - [ - 13275, - 16423 - ], - [ - -5, - -49 - ], - [ - -31, - -20 - ], - [ - -51, - 15 - ], - [ - -15, - -49 - ], - [ - -34, - -4 - ], - [ - -12, - 19 - ], - [ - -39, - -40 - ], - [ - -33, - -6 - ], - [ - -30, - 26 - ] - ], - [ - [ - 13025, - 16315 - ], - [ - -24, - 52 - ], - [ - -34, - -18 - ], - [ - 1, - 54 - ], - [ - 51, - 67 - ], - [ - -2, - 31 - ], - [ - 32, - -11 - ], - [ - 19, - 20 - ] - ], - [ - [ - 13068, - 16510 - ], - [ - 59, - -1 - ], - [ - 15, - 26 - ], - [ - 74, - -36 - ] - ], - [ - [ - 7880, - 4211 - ], - [ - -23, - -48 - ], - [ - -60, - -37 - ], - [ - -34, - 3 - ], - [ - -42, - 10 - ], - [ - -50, - 36 - ], - [ - -73, - 17 - ], - [ - -88, - 67 - ], - [ - -71, - 65 - ], - [ - -96, - 134 - ], - [ - 57, - -25 - ], - [ - 98, - -80 - ], - [ - 93, - -43 - ], - [ - 36, - 55 - ], - [ - 22, - 82 - ], - [ - 65, - 50 - ], - [ - 49, - -15 - ] - ], - [ - [ - 7767, - 4523 - ], - [ - -62, - 1 - ], - [ - -33, - -30 - ], - [ - -63, - -43 - ], - [ - -11, - -112 - ], - [ - -30, - -3 - ], - [ - -78, - 39 - ], - [ - -80, - 84 - ], - [ - -87, - 68 - ], - [ - -22, - 76 - ], - [ - 20, - 71 - ], - [ - -35, - 79 - ], - [ - -9, - 205 - ], - [ - 30, - 115 - ], - [ - 73, - 93 - ], - [ - -106, - 35 - ], - [ - 67, - 106 - ], - [ - 24, - 199 - ], - [ - 77, - -42 - ], - [ - 36, - 249 - ], - [ - -46, - 31 - ], - [ - -22, - -149 - ], - [ - -44, - 17 - ], - [ - 22, - 171 - ], - [ - 24, - 222 - ], - [ - 32, - 82 - ], - [ - -20, - 117 - ], - [ - -6, - 136 - ], - [ - 29, - 3 - ], - [ - 43, - 194 - ], - [ - 48, - 192 - ], - [ - 30, - 179 - ], - [ - -16, - 180 - ], - [ - 20, - 99 - ], - [ - -8, - 148 - ], - [ - 41, - 146 - ], - [ - 12, - 232 - ], - [ - 23, - 249 - ], - [ - 22, - 269 - ], - [ - -6, - 196 - ], - [ - -14, - 169 - ] - ], - [ - [ - 7642, - 8596 - ], - [ - 36, - 31 - ], - [ - 18, - 61 - ] - ], - [ - [ - 17774, - 15286 - ], - [ - -10, - 69 - ], - [ - 2, - 46 - ], - [ - -42, - 28 - ], - [ - -23, - -12 - ], - [ - -18, - 111 - ] - ], - [ - [ - 17683, - 15528 - ], - [ - 20, - 27 - ], - [ - -9, - 28 - ], - [ - 66, - 57 - ], - [ - 48, - 23 - ], - [ - 74, - -16 - ], - [ - 26, - 77 - ], - [ - 90, - 14 - ], - [ - 25, - 48 - ], - [ - 109, - 65 - ], - [ - 10, - 27 - ] - ], - [ - [ - 18142, - 15878 - ], - [ - -5, - 68 - ], - [ - 48, - 31 - ], - [ - -63, - 209 - ], - [ - 138, - 48 - ], - [ - 36, - 27 - ], - [ - 50, - 214 - ], - [ - 138, - -39 - ], - [ - 39, - 54 - ], - [ - 3, - 120 - ], - [ - 58, - 12 - ], - [ - 53, - 79 - ] - ], - [ - [ - 18637, - 16701 - ], - [ - 27, - 10 - ] - ], - [ - [ - 18664, - 16711 - ], - [ - 19, - -83 - ], - [ - 58, - -64 - ], - [ - 100, - -45 - ], - [ - 48, - -97 - ], - [ - -27, - -140 - ], - [ - 25, - -52 - ], - [ - 83, - -20 - ], - [ - 94, - -17 - ], - [ - 84, - -75 - ], - [ - 43, - -13 - ], - [ - 32, - -111 - ], - [ - 41, - -71 - ], - [ - 77, - 3 - ], - [ - 144, - -27 - ], - [ - 92, - 17 - ], - [ - 69, - -18 - ], - [ - 103, - -73 - ], - [ - 85, - 0 - ], - [ - 30, - -37 - ], - [ - 82, - 64 - ], - [ - 112, - 42 - ], - [ - 105, - 4 - ], - [ - 81, - 42 - ], - [ - 50, - 65 - ], - [ - 49, - 40 - ], - [ - -11, - 40 - ], - [ - -23, - 46 - ], - [ - 37, - 77 - ], - [ - 39, - -11 - ], - [ - 72, - -24 - ], - [ - 69, - 64 - ], - [ - 107, - 46 - ], - [ - 51, - 79 - ], - [ - 49, - 34 - ], - [ - 101, - 16 - ], - [ - 55, - -13 - ], - [ - 8, - 42 - ], - [ - -64, - 84 - ], - [ - -55, - 39 - ], - [ - -54, - -45 - ], - [ - -69, - 19 - ], - [ - -39, - -15 - ], - [ - -18, - 49 - ], - [ - 49, - 120 - ], - [ - 34, - 90 - ] - ], - [ - [ - 20681, - 16782 - ], - [ - 84, - -45 - ], - [ - 98, - 76 - ], - [ - -1, - 53 - ], - [ - 63, - 127 - ], - [ - 39, - 38 - ], - [ - -1, - 67 - ], - [ - -38, - 28 - ], - [ - 57, - 60 - ], - [ - 87, - 21 - ], - [ - 92, - 4 - ], - [ - 105, - -36 - ], - [ - 61, - -44 - ], - [ - 43, - -121 - ], - [ - 26, - -52 - ], - [ - 24, - -74 - ], - [ - 26, - -117 - ], - [ - 122, - -38 - ], - [ - 82, - -86 - ], - [ - 28, - -112 - ], - [ - 106, - -1 - ], - [ - 61, - 48 - ], - [ - 115, - 35 - ], - [ - -37, - -108 - ], - [ - -27, - -44 - ], - [ - -24, - -131 - ], - [ - -47, - -117 - ], - [ - -84, - 21 - ], - [ - -60, - -42 - ], - [ - 18, - -103 - ], - [ - -10, - -142 - ], - [ - -35, - -3 - ], - [ - 0, - -61 - ] - ], - [ - [ - 21654, - 15883 - ], - [ - -45, - 71 - ], - [ - -28, - -67 - ], - [ - -107, - -52 - ], - [ - 11, - -63 - ], - [ - -61, - 4 - ], - [ - -33, - 38 - ], - [ - -48, - -85 - ], - [ - -76, - -65 - ], - [ - -57, - -77 - ] - ], - [ - [ - 21210, - 15587 - ], - [ - -98, - -35 - ], - [ - -51, - -56 - ], - [ - -75, - -32 - ], - [ - 37, - 55 - ], - [ - -15, - 47 - ], - [ - 56, - 81 - ], - [ - -37, - 62 - ], - [ - -61, - -42 - ], - [ - -79, - -83 - ], - [ - -43, - -78 - ], - [ - -68, - -6 - ], - [ - -35, - -55 - ], - [ - 36, - -82 - ], - [ - 57, - -19 - ], - [ - 3, - -54 - ], - [ - 55, - -35 - ], - [ - 78, - 85 - ], - [ - 62, - -46 - ], - [ - 45, - -3 - ], - [ - 11, - -63 - ], - [ - -99, - -34 - ], - [ - -32, - -65 - ], - [ - -68, - -60 - ], - [ - -36, - -84 - ], - [ - 75, - -66 - ], - [ - 28, - -118 - ], - [ - 42, - -110 - ], - [ - 48, - -92 - ], - [ - -2, - -89 - ], - [ - -43, - -33 - ], - [ - 16, - -64 - ], - [ - 41, - -37 - ], - [ - -10, - -98 - ], - [ - -18, - -95 - ], - [ - -39, - -10 - ], - [ - -51, - -130 - ], - [ - -56, - -158 - ], - [ - -65, - -143 - ], - [ - -96, - -111 - ], - [ - -97, - -101 - ], - [ - -79, - -13 - ], - [ - -42, - -54 - ], - [ - -24, - 39 - ], - [ - -40, - -59 - ], - [ - -97, - -60 - ], - [ - -74, - -19 - ], - [ - -24, - -127 - ], - [ - -38, - -7 - ], - [ - -19, - 88 - ], - [ - 17, - 46 - ], - [ - -94, - 38 - ], - [ - -33, - -19 - ] - ], - [ - [ - 20079, - 13383 - ], - [ - -70, - 31 - ], - [ - -33, - 49 - ], - [ - 11, - 69 - ], - [ - -64, - 22 - ], - [ - -33, - 45 - ], - [ - -60, - -64 - ], - [ - -67, - -14 - ], - [ - -56, - 1 - ], - [ - -37, - -30 - ] - ], - [ - [ - 19670, - 13492 - ], - [ - -37, - -17 - ], - [ - 11, - -138 - ], - [ - -37, - 4 - ], - [ - -6, - 28 - ] - ], - [ - [ - 19601, - 13369 - ], - [ - -2, - 50 - ], - [ - -52, - -35 - ], - [ - -30, - 22 - ], - [ - -52, - 45 - ], - [ - 21, - 99 - ], - [ - -44, - 24 - ], - [ - -17, - 110 - ], - [ - -74, - -20 - ], - [ - 9, - 142 - ], - [ - 66, - 101 - ], - [ - 3, - 99 - ], - [ - -2, - 91 - ], - [ - -31, - 29 - ], - [ - -23, - 71 - ], - [ - -41, - -9 - ] - ], - [ - [ - 19332, - 14188 - ], - [ - -75, - 18 - ], - [ - 23, - 50 - ], - [ - -32, - 75 - ], - [ - -50, - -51 - ], - [ - -58, - 30 - ], - [ - -81, - -77 - ], - [ - -63, - -89 - ], - [ - -56, - -15 - ] - ], - [ - [ - 18739, - 14072 - ], - [ - -6, - 95 - ], - [ - -43, - -25 - ] - ], - [ - [ - 18690, - 14142 - ], - [ - -81, - 11 - ], - [ - -79, - 28 - ], - [ - -56, - 52 - ], - [ - -55, - 24 - ], - [ - -23, - 58 - ], - [ - -39, - 17 - ], - [ - -71, - 78 - ], - [ - -55, - 37 - ], - [ - -29, - -29 - ] - ], - [ - [ - 18202, - 14418 - ], - [ - -97, - 84 - ], - [ - -69, - 76 - ], - [ - -19, - 132 - ], - [ - 50, - -16 - ], - [ - 2, - 61 - ], - [ - -28, - 62 - ], - [ - 7, - 98 - ], - [ - -75, - 140 - ] - ], - [ - [ - 17973, - 15055 - ], - [ - -114, - 49 - ], - [ - -21, - 92 - ], - [ - -51, - 56 - ] - ], - [ - [ - 20239, - 13038 - ], - [ - -60, - -58 - ], - [ - -57, - 38 - ], - [ - -2, - 103 - ], - [ - 34, - 54 - ], - [ - 76, - 34 - ], - [ - 40, - -3 - ], - [ - 16, - -46 - ], - [ - -31, - -53 - ], - [ - -16, - -69 - ] - ], - [ - [ - 12350, - 11954 - ], - [ - 19, - -171 - ], - [ - -29, - -100 - ], - [ - -19, - -136 - ], - [ - 31, - -103 - ], - [ - -4, - -48 - ] - ], - [ - [ - 12348, - 11396 - ], - [ - -31, - -1 - ], - [ - -49, - 24 - ], - [ - -45, - -2 - ], - [ - -82, - -21 - ], - [ - -49, - -34 - ], - [ - -69, - -44 - ], - [ - -13, - 3 - ] - ], - [ - [ - 12010, - 11321 - ], - [ - 5, - 99 - ], - [ - 7, - 15 - ], - [ - -2, - 47 - ], - [ - -30, - 50 - ], - [ - -22, - 8 - ], - [ - -20, - 33 - ], - [ - 15, - 53 - ], - [ - -7, - 58 - ], - [ - 3, - 35 - ] - ], - [ - [ - 11959, - 11719 - ], - [ - 11, - 0 - ], - [ - 4, - 53 - ], - [ - -5, - 23 - ], - [ - 7, - 17 - ], - [ - 26, - 14 - ], - [ - -18, - 96 - ], - [ - -16, - 50 - ], - [ - 6, - 40 - ], - [ - 14, - 10 - ] - ], - [ - [ - 11988, - 12022 - ], - [ - 9, - 11 - ], - [ - 19, - -18 - ], - [ - 54, - -1 - ], - [ - 13, - 35 - ], - [ - 12, - -3 - ], - [ - 20, - 14 - ], - [ - 11, - -52 - ], - [ - 16, - 16 - ], - [ - 29, - 17 - ] - ], - [ - [ - 13664, - 11069 - ], - [ - -5, - -65 - ], - [ - -56, - 29 - ], - [ - -56, - 31 - ], - [ - -88, - 5 - ] - ], - [ - [ - 13459, - 11069 - ], - [ - -9, - 7 - ], - [ - -41, - -16 - ], - [ - -42, - 16 - ], - [ - -33, - -8 - ] - ], - [ - [ - 13334, - 11068 - ], - [ - -114, - 3 - ] - ], - [ - [ - 13220, - 11071 - ], - [ - 10, - 95 - ], - [ - -27, - 79 - ], - [ - -32, - 21 - ], - [ - -14, - 53 - ], - [ - -18, - 18 - ], - [ - 1, - 33 - ] - ], - [ - [ - 13140, - 11370 - ], - [ - 18, - 85 - ], - [ - 33, - 115 - ], - [ - 20, - 1 - ], - [ - 42, - 71 - ], - [ - 26, - 2 - ], - [ - 39, - -50 - ], - [ - 48, - 41 - ], - [ - 7, - 50 - ], - [ - 15, - 48 - ], - [ - 11, - 61 - ], - [ - 38, - 49 - ], - [ - 14, - 84 - ], - [ - 14, - 27 - ], - [ - 10, - 62 - ], - [ - 19, - 77 - ], - [ - 58, - 93 - ], - [ - 4, - 39 - ], - [ - 8, - 22 - ], - [ - -28, - 48 - ] - ], - [ - [ - 13536, - 12295 - ], - [ - 2, - 38 - ], - [ - 20, - 7 - ] - ], - [ - [ - 13558, - 12340 - ], - [ - 28, - -77 - ], - [ - 4, - -79 - ], - [ - -2, - -80 - ], - [ - 38, - -109 - ], - [ - -39, - 1 - ], - [ - -20, - -9 - ], - [ - -32, - 12 - ], - [ - -15, - -56 - ], - [ - 41, - -70 - ], - [ - 31, - -21 - ], - [ - 10, - -49 - ], - [ - 22, - -83 - ], - [ - -11, - -32 - ] - ], - [ - [ - 13406, - 10065 - ], - [ - -9, - 38 - ] - ], - [ - [ - 13453, - 10224 - ], - [ - 19, - -13 - ], - [ - 24, - 46 - ], - [ - 38, - -1 - ], - [ - 4, - -34 - ], - [ - 26, - -21 - ], - [ - 41, - 75 - ], - [ - 41, - 59 - ], - [ - 17, - 38 - ], - [ - -2, - 99 - ], - [ - 30, - 116 - ], - [ - 32, - 62 - ], - [ - 46, - 58 - ], - [ - 8, - 38 - ], - [ - 2, - 44 - ], - [ - 11, - 42 - ], - [ - -3, - 68 - ], - [ - 8, - 106 - ], - [ - 14, - 75 - ], - [ - 21, - 64 - ], - [ - 4, - 73 - ] - ], - [ - [ - 14456, - 11425 - ], - [ - 42, - -99 - ], - [ - 31, - -14 - ], - [ - 19, - 20 - ], - [ - 32, - -8 - ], - [ - 39, - 25 - ], - [ - 17, - -51 - ], - [ - 61, - -80 - ] - ], - [ - [ - 14697, - 11218 - ], - [ - -4, - -140 - ], - [ - 28, - -16 - ], - [ - -23, - -43 - ], - [ - -27, - -32 - ], - [ - -26, - -62 - ], - [ - -15, - -56 - ], - [ - -4, - -96 - ], - [ - -16, - -46 - ], - [ - -1, - -91 - ] - ], - [ - [ - 14609, - 10636 - ], - [ - -20, - -33 - ], - [ - -2, - -72 - ], - [ - -10, - -9 - ], - [ - -6, - -65 - ] - ], - [ - [ - 14593, - 10257 - ], - [ - 12, - -110 - ], - [ - -7, - -62 - ], - [ - 14, - -70 - ], - [ - 41, - -67 - ], - [ - 37, - -151 - ] - ], - [ - [ - 14690, - 9797 - ], - [ - -27, - 12 - ], - [ - -94, - -20 - ], - [ - -18, - -15 - ], - [ - -20, - -76 - ], - [ - 15, - -53 - ], - [ - -12, - -142 - ], - [ - -9, - -121 - ], - [ - 19, - -21 - ], - [ - 49, - -47 - ], - [ - 19, - 22 - ], - [ - 6, - -129 - ], - [ - -54, - 1 - ], - [ - -28, - 66 - ], - [ - -26, - 51 - ], - [ - -53, - 17 - ], - [ - -16, - 63 - ], - [ - -43, - -38 - ], - [ - -55, - 16 - ], - [ - -24, - 55 - ], - [ - -44, - 11 - ], - [ - -33, - -3 - ], - [ - -4, - 37 - ], - [ - -24, - 3 - ] - ], - [ - [ - 13378, - 10193 - ], - [ - -57, - 127 - ] - ], - [ - [ - 13321, - 10320 - ], - [ - 53, - 66 - ], - [ - -26, - 79 - ], - [ - 24, - 31 - ], - [ - 47, - 14 - ], - [ - 5, - 53 - ], - [ - 37, - -57 - ], - [ - 62, - -5 - ], - [ - 21, - 56 - ], - [ - 9, - 80 - ], - [ - -8, - 94 - ], - [ - -33, - 71 - ], - [ - 31, - 139 - ], - [ - -18, - 24 - ], - [ - -52, - -10 - ], - [ - -19, - 62 - ], - [ - 5, - 52 - ] - ], - [ - [ - 7675, - 10282 - ], - [ - -35, - 63 - ], - [ - -20, - 3 - ], - [ - 45, - 122 - ], - [ - -54, - 56 - ], - [ - -42, - -10 - ], - [ - -25, - 21 - ], - [ - -38, - -32 - ], - [ - -52, - 15 - ], - [ - -41, - 126 - ], - [ - -32, - 31 - ], - [ - -23, - 57 - ], - [ - -46, - 56 - ], - [ - -19, - -11 - ] - ], - [ - [ - 7293, - 10779 - ], - [ - -29, - 28 - ], - [ - -35, - 40 - ], - [ - -20, - -19 - ], - [ - -59, - 17 - ], - [ - -17, - 51 - ], - [ - -13, - -2 - ], - [ - -69, - 69 - ] - ], - [ - [ - 7051, - 10963 - ], - [ - -10, - 37 - ], - [ - 26, - 9 - ], - [ - -3, - 60 - ], - [ - 16, - 44 - ], - [ - 35, - 8 - ], - [ - 29, - 75 - ], - [ - 27, - 63 - ], - [ - -26, - 29 - ], - [ - 14, - 69 - ], - [ - -16, - 110 - ], - [ - 15, - 31 - ], - [ - -11, - 102 - ], - [ - -28, - 64 - ] - ], - [ - [ - 7119, - 11664 - ], - [ - 8, - 58 - ], - [ - 23, - -8 - ], - [ - 13, - 35 - ], - [ - -16, - 71 - ], - [ - 8, - 17 - ] - ], - [ - [ - 7155, - 11837 - ], - [ - 36, - -3 - ], - [ - 53, - 83 - ], - [ - 28, - 13 - ], - [ - 1, - 40 - ], - [ - 13, - 101 - ], - [ - 40, - 56 - ], - [ - 44, - 2 - ], - [ - 5, - 25 - ], - [ - 55, - -10 - ], - [ - 55, - 61 - ], - [ - 27, - 26 - ], - [ - 34, - 58 - ], - [ - 24, - -7 - ], - [ - 19, - -32 - ], - [ - -14, - -40 - ] - ], - [ - [ - 7575, - 12210 - ], - [ - -45, - -20 - ], - [ - -17, - -60 - ], - [ - -27, - -35 - ], - [ - -21, - -44 - ], - [ - -8, - -86 - ], - [ - -19, - -70 - ], - [ - 36, - -8 - ], - [ - 8, - -55 - ], - [ - 16, - -26 - ], - [ - 5, - -49 - ], - [ - -8, - -44 - ], - [ - 3, - -25 - ], - [ - 17, - -10 - ], - [ - 16, - -42 - ], - [ - 90, - 12 - ], - [ - 40, - -16 - ], - [ - 49, - -103 - ], - [ - 29, - 13 - ], - [ - 50, - -7 - ], - [ - 40, - 14 - ], - [ - 24, - -21 - ], - [ - -12, - -64 - ], - [ - -16, - -40 - ], - [ - -5, - -86 - ], - [ - 14, - -80 - ], - [ - 20, - -36 - ], - [ - 2, - -27 - ], - [ - -35, - -59 - ], - [ - 25, - -27 - ], - [ - 18, - -42 - ], - [ - 22, - -119 - ] - ], - [ - [ - 6764, - 11784 - ], - [ - -38, - 27 - ], - [ - -14, - 25 - ], - [ - 8, - 21 - ], - [ - -2, - 26 - ], - [ - -20, - 29 - ], - [ - -27, - 23 - ], - [ - -24, - 16 - ], - [ - -5, - 35 - ], - [ - -18, - 21 - ], - [ - 4, - -35 - ], - [ - -13, - -28 - ], - [ - -16, - 33 - ], - [ - -23, - 12 - ], - [ - -9, - 24 - ], - [ - 0, - 37 - ], - [ - 9, - 37 - ], - [ - -19, - 17 - ], - [ - 16, - 23 - ] - ], - [ - [ - 6573, - 12127 - ], - [ - 10, - 16 - ], - [ - 46, - -32 - ], - [ - 16, - 16 - ], - [ - 22, - -10 - ], - [ - 12, - -25 - ], - [ - 20, - -8 - ], - [ - 17, - 26 - ] - ], - [ - [ - 6716, - 12110 - ], - [ - 18, - -66 - ], - [ - 27, - -48 - ], - [ - 32, - -51 - ] - ], - [ - [ - 6793, - 11945 - ], - [ - -27, - -11 - ], - [ - 1, - -48 - ], - [ - 14, - -18 - ], - [ - -10, - -14 - ], - [ - 3, - -22 - ], - [ - -6, - -24 - ], - [ - -4, - -24 - ] - ], - [ - [ - 6813, - 13579 - ], - [ - 60, - -8 - ], - [ - 55, - -2 - ], - [ - 65, - -41 - ], - [ - 28, - -44 - ], - [ - 65, - 14 - ], - [ - 25, - -28 - ], - [ - 59, - -75 - ], - [ - 43, - -54 - ], - [ - 23, - 2 - ], - [ - 42, - -24 - ], - [ - -5, - -34 - ], - [ - 51, - -5 - ], - [ - 53, - -49 - ], - [ - -9, - -28 - ], - [ - -46, - -16 - ], - [ - -47, - -6 - ], - [ - -48, - 10 - ], - [ - -100, - -12 - ], - [ - 47, - 67 - ], - [ - -28, - 31 - ], - [ - -45, - 8 - ], - [ - -24, - 35 - ], - [ - -17, - 68 - ], - [ - -39, - -4 - ], - [ - -65, - 32 - ], - [ - -21, - 25 - ], - [ - -91, - 19 - ], - [ - -24, - 23 - ], - [ - 26, - 30 - ], - [ - -69, - 6 - ], - [ - -50, - -62 - ], - [ - -29, - -2 - ], - [ - -10, - -29 - ], - [ - -34, - -13 - ], - [ - -30, - 11 - ], - [ - 37, - 37 - ], - [ - 15, - 43 - ], - [ - 31, - 27 - ], - [ - 36, - 23 - ], - [ - 53, - 12 - ], - [ - 17, - 13 - ] - ], - [ - [ - 14829, - 15013 - ], - [ - 5, - 1 - ], - [ - 10, - 28 - ], - [ - 50, - -1 - ], - [ - 64, - 36 - ], - [ - -47, - -51 - ], - [ - 5, - -23 - ] - ], - [ - [ - 14916, - 15003 - ], - [ - -8, - 4 - ], - [ - -13, - -9 - ], - [ - -10, - 3 - ], - [ - -4, - -5 - ], - [ - -1, - 12 - ], - [ - -5, - 8 - ], - [ - -14, - 1 - ], - [ - -19, - -10 - ], - [ - -13, - 6 - ] - ], - [ - [ - 14916, - 15003 - ], - [ - 2, - -10 - ], - [ - -72, - -48 - ], - [ - -34, - 15 - ], - [ - -16, - 48 - ], - [ - 33, - 5 - ] - ], - [ - [ - 13495, - 16661 - ], - [ - -39, - 52 - ], - [ - -36, - 28 - ], - [ - -7, - 51 - ], - [ - -12, - 36 - ], - [ - 50, - 26 - ], - [ - 26, - 30 - ], - [ - 50, - 23 - ], - [ - 18, - 23 - ], - [ - 18, - -14 - ], - [ - 31, - 12 - ] - ], - [ - [ - 13594, - 16928 - ], - [ - 33, - -38 - ], - [ - 52, - -11 - ], - [ - -4, - -33 - ], - [ - 38, - -24 - ], - [ - 10, - 30 - ], - [ - 48, - -13 - ], - [ - 7, - -37 - ], - [ - 52, - -8 - ], - [ - 32, - -59 - ] - ], - [ - [ - 13862, - 16735 - ], - [ - -21, - 0 - ], - [ - -11, - -22 - ], - [ - -16, - -5 - ], - [ - -4, - -27 - ], - [ - -14, - -6 - ], - [ - -2, - -11 - ], - [ - -23, - -12 - ], - [ - -31, - 2 - ], - [ - -10, - -27 - ] - ], - [ - [ - 13068, - 16510 - ], - [ - 9, - 86 - ], - [ - 35, - 82 - ], - [ - -100, - 22 - ], - [ - -33, - 31 - ] - ], - [ - [ - 12979, - 16731 - ], - [ - 4, - 53 - ], - [ - -14, - 27 - ] - ], - [ - [ - 12977, - 16892 - ], - [ - -12, - 126 - ], - [ - 42, - 0 - ], - [ - 18, - 45 - ], - [ - 17, - 110 - ], - [ - -13, - 40 - ] - ], - [ - [ - 13029, - 17213 - ], - [ - 13, - 26 - ], - [ - 59, - 6 - ], - [ - 13, - -26 - ], - [ - 47, - 59 - ], - [ - -16, - 45 - ], - [ - -3, - 68 - ] - ], - [ - [ - 13142, - 17391 - ], - [ - 53, - -16 - ], - [ - 44, - 18 - ] - ], - [ - [ - 13239, - 17393 - ], - [ - 1, - -46 - ], - [ - 71, - -28 - ], - [ - -1, - -42 - ], - [ - 71, - 22 - ], - [ - 39, - 33 - ], - [ - 79, - -47 - ], - [ - 33, - -39 - ] - ], - [ - [ - 13532, - 17246 - ], - [ - 16, - -61 - ], - [ - -19, - -32 - ], - [ - 25, - -42 - ], - [ - 17, - -65 - ], - [ - -5, - -41 - ], - [ - 28, - -77 - ] - ], - [ - [ - 15551, - 12321 - ], - [ - 16, - -37 - ], - [ - -2, - -50 - ], - [ - -40, - -29 - ], - [ - 30, - -33 - ] - ], - [ - [ - 15555, - 12172 - ], - [ - -26, - -64 - ] - ], - [ - [ - 15529, - 12108 - ], - [ - -15, - 21 - ], - [ - -17, - -8 - ], - [ - -39, - 2 - ], - [ - -1, - 36 - ], - [ - -5, - 34 - ], - [ - 23, - 56 - ], - [ - 25, - 53 - ] - ], - [ - [ - 15500, - 12302 - ], - [ - 30, - -11 - ], - [ - 21, - 30 - ] - ], - [ - [ - 13142, - 17391 - ], - [ - -28, - 67 - ], - [ - -3, - 122 - ], - [ - 12, - 33 - ], - [ - 20, - 36 - ], - [ - 61, - 7 - ], - [ - 25, - 33 - ], - [ - 56, - 34 - ], - [ - -2, - -62 - ], - [ - -21, - -39 - ], - [ - 8, - -33 - ], - [ - 38, - -19 - ], - [ - -17, - -45 - ], - [ - -21, - 13 - ], - [ - -50, - -86 - ], - [ - 19, - -59 - ] - ], - [ - [ - 13432, - 17469 - ], - [ - -42, - -98 - ], - [ - -73, - 68 - ], - [ - -9, - 50 - ], - [ - 102, - 40 - ], - [ - 22, - -60 - ] - ], - [ - [ - 7549, - 13162 - ], - [ - 8, - 21 - ], - [ - 55, - -1 - ], - [ - 41, - -31 - ], - [ - 18, - 3 - ], - [ - 13, - -42 - ], - [ - 38, - 2 - ], - [ - -2, - -36 - ], - [ - 31, - -4 - ], - [ - 34, - -44 - ], - [ - -26, - -49 - ], - [ - -33, - 26 - ], - [ - -32, - -5 - ], - [ - -23, - 6 - ], - [ - -12, - -22 - ], - [ - -27, - -7 - ], - [ - -11, - 29 - ], - [ - -23, - -17 - ], - [ - -28, - -83 - ], - [ - -18, - 20 - ], - [ - -3, - 34 - ] - ], - [ - [ - 7549, - 12962 - ], - [ - 1, - 33 - ], - [ - -18, - 36 - ], - [ - 17, - 20 - ], - [ - 6, - 46 - ], - [ - -6, - 65 - ] - ], - [ - [ - 12845, - 13095 - ], - [ - -77, - -12 - ], - [ - -1, - 77 - ], - [ - -32, - 19 - ], - [ - -44, - 35 - ], - [ - -16, - 56 - ], - [ - -236, - 262 - ], - [ - -235, - 261 - ] - ], - [ - [ - 12204, - 13793 - ], - [ - -262, - 291 - ] - ], - [ - [ - 11942, - 14084 - ], - [ - 1, - 23 - ], - [ - 0, - 8 - ] - ], - [ - [ - 11943, - 14115 - ], - [ - 0, - 142 - ], - [ - 112, - 89 - ], - [ - 70, - 18 - ], - [ - 57, - 32 - ], - [ - 27, - 60 - ], - [ - 81, - 48 - ], - [ - 3, - 89 - ], - [ - 41, - 10 - ], - [ - 31, - 45 - ], - [ - 91, - 20 - ], - [ - 13, - 46 - ], - [ - -18, - 26 - ], - [ - -24, - 127 - ], - [ - -4, - 72 - ], - [ - -27, - 77 - ] - ], - [ - [ - 12396, - 15016 - ], - [ - 67, - 66 - ], - [ - 76, - 21 - ], - [ - 44, - 49 - ], - [ - 67, - 37 - ], - [ - 118, - 21 - ], - [ - 115, - 10 - ], - [ - 35, - -18 - ], - [ - 66, - 47 - ], - [ - 74, - 1 - ], - [ - 29, - -28 - ], - [ - 48, - 8 - ] - ], - [ - [ - 13135, - 15230 - ], - [ - -15, - -62 - ], - [ - 11, - -114 - ], - [ - -16, - -99 - ], - [ - -43, - -67 - ], - [ - 6, - -91 - ], - [ - 57, - -71 - ], - [ - 1, - -29 - ], - [ - 43, - -48 - ], - [ - 29, - -216 - ] - ], - [ - [ - 13208, - 14433 - ], - [ - 23, - -106 - ], - [ - 4, - -56 - ], - [ - -12, - -97 - ], - [ - 5, - -55 - ], - [ - -9, - -66 - ], - [ - 6, - -75 - ], - [ - -28, - -50 - ], - [ - 41, - -88 - ], - [ - 3, - -51 - ], - [ - 25, - -67 - ], - [ - 32, - 22 - ], - [ - 55, - -56 - ], - [ - 31, - -75 - ] - ], - [ - [ - 13384, - 13613 - ], - [ - -239, - -229 - ], - [ - -202, - -235 - ], - [ - -98, - -54 - ] - ], - [ - [ - 7293, - 10779 - ], - [ - 10, - -91 - ], - [ - -22, - -78 - ], - [ - -76, - -126 - ], - [ - -83, - -47 - ], - [ - -43, - -104 - ], - [ - -13, - -81 - ], - [ - -40, - -50 - ], - [ - -29, - 61 - ], - [ - -28, - 13 - ], - [ - -29, - -10 - ], - [ - -2, - 44 - ], - [ - 20, - 29 - ], - [ - -8, - 50 - ] - ], - [ - [ - 6950, - 10389 - ], - [ - 37, - 89 - ], - [ - -15, - 53 - ], - [ - -27, - -56 - ], - [ - -42, - 53 - ], - [ - 15, - 33 - ], - [ - -12, - 109 - ], - [ - 24, - 18 - ], - [ - 13, - 75 - ], - [ - 26, - 77 - ], - [ - -4, - 49 - ], - [ - 38, - 26 - ], - [ - 48, - 48 - ] - ], - [ - [ - 15117, - 13437 - ], - [ - -276, - 0 - ], - [ - -271, - 0 - ], - [ - -280, - 0 - ] - ], - [ - [ - 14290, - 13437 - ], - [ - 0, - 441 - ], - [ - 0, - 427 - ], - [ - -21, - 97 - ], - [ - 18, - 74 - ], - [ - -11, - 51 - ], - [ - 26, - 58 - ] - ], - [ - [ - 14302, - 14585 - ], - [ - 92, - 1 - ], - [ - 68, - -31 - ], - [ - 69, - -36 - ], - [ - 32, - -18 - ], - [ - 54, - 38 - ], - [ - 28, - 34 - ], - [ - 62, - 10 - ], - [ - 49, - -15 - ], - [ - 19, - -60 - ], - [ - 17, - 39 - ], - [ - 55, - -28 - ], - [ - 55, - -7 - ], - [ - 34, - 31 - ] - ], - [ - [ - 14936, - 14543 - ], - [ - 39, - -175 - ], - [ - 7, - -32 - ] - ], - [ - [ - 14982, - 14336 - ], - [ - -20, - -48 - ], - [ - -15, - -90 - ], - [ - -19, - -63 - ], - [ - -16, - -21 - ], - [ - -23, - 39 - ], - [ - -32, - 53 - ], - [ - -49, - 172 - ], - [ - -7, - -10 - ], - [ - 28, - -127 - ], - [ - 43, - -121 - ], - [ - 53, - -187 - ], - [ - 26, - -65 - ], - [ - 22, - -68 - ], - [ - 63, - -132 - ], - [ - -14, - -21 - ], - [ - 2, - -78 - ], - [ - 81, - -108 - ], - [ - 12, - -24 - ] - ], - [ - [ - 15500, - 12302 - ], - [ - -24, - 39 - ], - [ - -29, - 70 - ], - [ - -31, - 39 - ], - [ - -18, - 41 - ], - [ - -60, - 48 - ], - [ - -48, - 2 - ], - [ - -17, - 25 - ], - [ - -41, - -29 - ], - [ - -42, - 55 - ], - [ - -22, - -90 - ], - [ - -81, - 25 - ] - ], - [ - [ - 15087, - 12527 - ], - [ - -7, - 48 - ], - [ - 30, - 177 - ], - [ - 6, - 79 - ], - [ - 22, - 37 - ], - [ - 52, - 20 - ], - [ - 35, - 68 - ] - ], - [ - [ - 15225, - 12956 - ], - [ - 40, - -138 - ], - [ - 20, - -111 - ], - [ - 38, - -58 - ], - [ - 95, - -113 - ], - [ - 39, - -69 - ], - [ - 38, - -69 - ], - [ - 21, - -41 - ], - [ - 35, - -36 - ] - ], - [ - [ - 11918, - 15822 - ], - [ - 3, - 85 - ], - [ - -28, - 52 - ], - [ - 98, - 87 - ], - [ - 86, - -22 - ], - [ - 93, - 1 - ], - [ - 74, - -21 - ], - [ - 58, - 7 - ], - [ - 113, - -4 - ] - ], - [ - [ - 12415, - 16007 - ], - [ - 28, - -47 - ], - [ - 128, - -55 - ], - [ - 25, - 26 - ], - [ - 79, - -54 - ], - [ - 81, - 16 - ] - ], - [ - [ - 12756, - 15893 - ], - [ - 3, - -70 - ], - [ - -66, - -80 - ], - [ - -89, - -25 - ], - [ - -6, - -41 - ], - [ - -43, - -66 - ], - [ - -27, - -98 - ], - [ - 27, - -68 - ], - [ - -40, - -54 - ], - [ - -15, - -78 - ], - [ - -53, - -24 - ], - [ - -49, - -92 - ], - [ - -89, - -2 - ], - [ - -66, - 2 - ], - [ - -44, - -42 - ], - [ - -26, - -45 - ], - [ - -34, - 10 - ], - [ - -26, - 40 - ], - [ - -20, - 69 - ], - [ - -65, - 19 - ] - ], - [ - [ - 12028, - 15248 - ], - [ - -6, - 39 - ], - [ - 26, - 45 - ], - [ - 10, - 33 - ], - [ - -25, - 36 - ], - [ - 20, - 79 - ], - [ - -28, - 72 - ], - [ - 30, - 9 - ], - [ - 3, - 57 - ], - [ - 11, - 18 - ], - [ - 1, - 93 - ], - [ - 32, - 33 - ], - [ - -19, - 60 - ], - [ - -41, - 4 - ], - [ - -12, - -15 - ], - [ - -41, - 0 - ], - [ - -18, - 59 - ], - [ - -28, - -18 - ], - [ - -25, - -30 - ] - ], - [ - [ - 14242, - 17731 - ], - [ - 8, - 70 - ], - [ - -25, - -15 - ], - [ - -44, - 43 - ], - [ - -7, - 69 - ], - [ - 89, - 33 - ], - [ - 87, - 18 - ], - [ - 76, - -20 - ], - [ - 72, - 3 - ] - ], - [ - [ - 14498, - 17932 - ], - [ - 11, - -21 - ], - [ - -50, - -69 - ], - [ - 21, - -112 - ], - [ - -30, - -38 - ] - ], - [ - [ - 14450, - 17692 - ], - [ - -58, - 1 - ], - [ - -60, - 44 - ], - [ - -30, - 15 - ], - [ - -60, - -21 - ] - ], - [ - [ - 15529, - 12108 - ], - [ - -15, - -42 - ], - [ - 26, - -66 - ], - [ - 26, - -58 - ], - [ - 26, - -43 - ], - [ - 228, - -142 - ], - [ - 59, - 0 - ] - ], - [ - [ - 15879, - 11757 - ], - [ - -197, - -360 - ], - [ - -91, - -5 - ], - [ - -62, - -85 - ], - [ - -45, - -2 - ], - [ - -19, - -38 - ] - ], - [ - [ - 15465, - 11267 - ], - [ - -47, - 0 - ], - [ - -29, - 41 - ], - [ - -63, - -50 - ], - [ - -21, - -50 - ], - [ - -46, - 9 - ], - [ - -16, - 14 - ], - [ - -16, - -3 - ], - [ - -22, - 1 - ], - [ - -88, - 102 - ], - [ - -49, - 0 - ], - [ - -24, - 39 - ], - [ - 0, - 68 - ], - [ - -36, - 20 - ] - ], - [ - [ - 15008, - 11458 - ], - [ - -41, - 130 - ], - [ - -32, - 28 - ], - [ - -12, - 48 - ], - [ - -36, - 59 - ], - [ - -42, - 8 - ], - [ - 23, - 68 - ], - [ - 37, - 3 - ], - [ - 11, - 37 - ] - ], - [ - [ - 14916, - 11839 - ], - [ - -1, - 108 - ], - [ - 21, - 125 - ], - [ - 33, - 34 - ], - [ - 7, - 49 - ], - [ - 29, - 92 - ], - [ - 42, - 59 - ], - [ - 29, - 118 - ], - [ - 11, - 103 - ] - ], - [ - [ - 14214, - 18716 - ], - [ - -24, - 47 - ], - [ - -2, - 184 - ], - [ - -108, - 82 - ], - [ - -93, - 59 - ] - ], - [ - [ - 13987, - 19088 - ], - [ - 41, - 31 - ], - [ - 78, - -63 - ], - [ - 91, - 6 - ], - [ - 75, - -29 - ], - [ - 66, - 53 - ], - [ - 34, - 88 - ], - [ - 109, - 41 - ], - [ - 89, - -48 - ], - [ - -29, - -84 - ] - ], - [ - [ - 14541, - 19083 - ], - [ - -11, - -84 - ], - [ - 107, - -80 - ], - [ - -64, - -91 - ], - [ - 81, - -136 - ], - [ - -47, - -103 - ], - [ - 63, - -89 - ], - [ - -29, - -78 - ], - [ - 103, - -83 - ], - [ - -26, - -61 - ], - [ - -65, - -69 - ], - [ - -149, - -153 - ] - ], - [ - [ - 14504, - 18056 - ], - [ - -126, - -10 - ], - [ - -123, - -44 - ], - [ - -113, - -25 - ], - [ - -41, - 65 - ], - [ - -67, - 40 - ], - [ - 15, - 118 - ], - [ - -33, - 108 - ], - [ - 33, - 70 - ], - [ - 63, - 75 - ], - [ - 159, - 130 - ], - [ - 47, - 26 - ], - [ - -7, - 50 - ], - [ - -97, - 57 - ] - ], - [ - [ - 24982, - 8717 - ], - [ - 24, - -35 - ], - [ - -12, - -62 - ], - [ - -43, - -17 - ], - [ - -39, - 15 - ], - [ - -6, - 53 - ], - [ - 27, - 41 - ], - [ - 31, - -15 - ], - [ - 18, - 20 - ] - ], - [ - [ - 25051, - 8782 - ], - [ - -45, - -26 - ], - [ - -9, - 45 - ], - [ - 35, - 25 - ], - [ - 22, - 6 - ], - [ - 41, - 38 - ], - [ - 0, - -59 - ], - [ - -44, - -29 - ] - ], - [ - [ - 6, - 8817 - ], - [ - -6, - -6 - ], - [ - 0, - 59 - ], - [ - 14, - 5 - ], - [ - -8, - -58 - ] - ], - [ - [ - 8281, - 4577 - ], - [ - 84, - 72 - ], - [ - 59, - -30 - ], - [ - 42, - 48 - ], - [ - 56, - -54 - ], - [ - -21, - -42 - ], - [ - -94, - -36 - ], - [ - -32, - 42 - ], - [ - -59, - -54 - ], - [ - -35, - 54 - ] - ], - [ - [ - 12943, - 16739 - ], - [ - 16, - -10 - ], - [ - 20, - 2 - ] - ], - [ - [ - 13025, - 16315 - ], - [ - -3, - -34 - ], - [ - 20, - -45 - ], - [ - -24, - -37 - ], - [ - 18, - -93 - ], - [ - 38, - -15 - ], - [ - -8, - -52 - ] - ], - [ - [ - 13066, - 16039 - ], - [ - -63, - -68 - ], - [ - -138, - 33 - ], - [ - -101, - -39 - ], - [ - -8, - -72 - ] - ], - [ - [ - 12415, - 16007 - ], - [ - 36, - 72 - ], - [ - 13, - 239 - ], - [ - -72, - 125 - ], - [ - -51, - 61 - ], - [ - -107, - 46 - ], - [ - -7, - 88 - ], - [ - 91, - 26 - ], - [ - 117, - -31 - ], - [ - -22, - 136 - ], - [ - 66, - -52 - ], - [ - 162, - 94 - ], - [ - 21, - 98 - ], - [ - 61, - 24 - ] - ], - [ - [ - 8747, - 11075 - ], - [ - 17, - 51 - ], - [ - 6, - 54 - ], - [ - 12, - 52 - ], - [ - -27, - 71 - ], - [ - -5, - 82 - ], - [ - 36, - 103 - ] - ], - [ - [ - 8786, - 11488 - ], - [ - 24, - -13 - ], - [ - 51, - -29 - ], - [ - 74, - -101 - ], - [ - 12, - -49 - ] - ], - [ - [ - 13214, - 15854 - ], - [ - -23, - -92 - ], - [ - -32, - 24 - ], - [ - -16, - 81 - ], - [ - 14, - 44 - ], - [ - 45, - 46 - ], - [ - 12, - -103 - ] - ], - [ - [ - 13321, - 10320 - ], - [ - -72, - 121 - ], - [ - -46, - 99 - ], - [ - -42, - 124 - ], - [ - 2, - 40 - ], - [ - 15, - 38 - ], - [ - 17, - 87 - ], - [ - 14, - 89 - ] - ], - [ - [ - 13209, - 10918 - ], - [ - 24, - 7 - ], - [ - 101, - -1 - ], - [ - 0, - 144 - ] - ], - [ - [ - 12115, - 17260 - ], - [ - -52, - 24 - ], - [ - -43, - -1 - ], - [ - 14, - 64 - ], - [ - -14, - 64 - ] - ], - [ - [ - 12020, - 17411 - ], - [ - 58, - 5 - ], - [ - 75, - -74 - ], - [ - -38, - -82 - ] - ], - [ - [ - 12338, - 17832 - ], - [ - -74, - -130 - ], - [ - 71, - 16 - ], - [ - 76, - 0 - ], - [ - -18, - -98 - ], - [ - -63, - -108 - ], - [ - 72, - -7 - ], - [ - 6, - -13 - ], - [ - 62, - -142 - ], - [ - 47, - -19 - ], - [ - 43, - -136 - ], - [ - 20, - -48 - ], - [ - 85, - -23 - ], - [ - -9, - -76 - ], - [ - -35, - -36 - ], - [ - 28, - -62 - ], - [ - -63, - -63 - ], - [ - -93, - 2 - ], - [ - -119, - -33 - ], - [ - -33, - 23 - ], - [ - -46, - -56 - ], - [ - -64, - 14 - ], - [ - -49, - -46 - ], - [ - -37, - 24 - ], - [ - 102, - 126 - ], - [ - 62, - 26 - ], - [ - 0, - 0 - ], - [ - -109, - 20 - ], - [ - -20, - 48 - ], - [ - 73, - 37 - ], - [ - -38, - 64 - ], - [ - 13, - 79 - ], - [ - 104, - -11 - ], - [ - 10, - 70 - ], - [ - -46, - 74 - ], - [ - -2, - 1 - ], - [ - -84, - 21 - ], - [ - -17, - 33 - ], - [ - 26, - 53 - ], - [ - -23, - 34 - ], - [ - -38, - -57 - ], - [ - -4, - 115 - ], - [ - -35, - 62 - ], - [ - 25, - 124 - ], - [ - 54, - 97 - ], - [ - 56, - -10 - ], - [ - 84, - 11 - ] - ], - [ - [ - 15586, - 15727 - ], - [ - -68, - 59 - ], - [ - -74, - -6 - ] - ], - [ - [ - 15444, - 15780 - ], - [ - 11, - 51 - ], - [ - -18, - 82 - ], - [ - -40, - 44 - ], - [ - -39, - 14 - ], - [ - -25, - 37 - ] - ], - [ - [ - 15333, - 16008 - ], - [ - 8, - 14 - ], - [ - 59, - -20 - ], - [ - 103, - -20 - ], - [ - 95, - -57 - ], - [ - 12, - -23 - ], - [ - 42, - 19 - ], - [ - 65, - -25 - ], - [ - 21, - -49 - ], - [ - 44, - -28 - ] - ], - [ - [ - 12549, - 12119 - ], - [ - -5, - -37 - ], - [ - 29, - -62 - ], - [ - 0, - -87 - ], - [ - 7, - -95 - ], - [ - 17, - -44 - ], - [ - -15, - -108 - ], - [ - 5, - -59 - ], - [ - 19, - -76 - ], - [ - 15, - -43 - ] - ], - [ - [ - 12621, - 11508 - ], - [ - -109, - -70 - ], - [ - -39, - -41 - ], - [ - -62, - -35 - ], - [ - -63, - 34 - ] - ], - [ - [ - 11959, - 11719 - ], - [ - -20, - 3 - ], - [ - -14, - -48 - ], - [ - -19, - 1 - ], - [ - -14, - 25 - ], - [ - 5, - 48 - ], - [ - -30, - 74 - ], - [ - -18, - -14 - ], - [ - -15, - -2 - ] - ], - [ - [ - 11834, - 11806 - ], - [ - -19, - -7 - ], - [ - 1, - 44 - ], - [ - -11, - 31 - ], - [ - 2, - 35 - ], - [ - -15, - 50 - ], - [ - -19, - 43 - ], - [ - -56, - 1 - ], - [ - -16, - -23 - ], - [ - -20, - -3 - ], - [ - -12, - -26 - ], - [ - -8, - -33 - ], - [ - -37, - -53 - ] - ], - [ - [ - 11624, - 11865 - ], - [ - -30, - 71 - ], - [ - -28, - 47 - ], - [ - -17, - 16 - ], - [ - -18, - 24 - ], - [ - -8, - 53 - ], - [ - -10, - 26 - ], - [ - -20, - 20 - ] - ], - [ - [ - 11493, - 12122 - ], - [ - 31, - 58 - ], - [ - 21, - -2 - ], - [ - 18, - 20 - ], - [ - 15, - 0 - ], - [ - 11, - 16 - ], - [ - -5, - 40 - ], - [ - 7, - 12 - ], - [ - 1, - 41 - ] - ], - [ - [ - 11592, - 12307 - ], - [ - 34, - -1 - ], - [ - 50, - -29 - ], - [ - 16, - 2 - ], - [ - 5, - 14 - ], - [ - 38, - -10 - ], - [ - 10, - 7 - ] - ], - [ - [ - 11745, - 12290 - ], - [ - 4, - -44 - ], - [ - 11, - 0 - ], - [ - 18, - 16 - ], - [ - 12, - -4 - ], - [ - 19, - -30 - ], - [ - 30, - -10 - ], - [ - 19, - 26 - ], - [ - 23, - 16 - ], - [ - 16, - 17 - ], - [ - 14, - -3 - ], - [ - 16, - -27 - ], - [ - 8, - -33 - ], - [ - 29, - -50 - ], - [ - -15, - -31 - ], - [ - -2, - -39 - ], - [ - 14, - 12 - ], - [ - 9, - -14 - ], - [ - -4, - -36 - ], - [ - 22, - -34 - ] - ], - [ - [ - 11374, - 12375 - ], - [ - 8, - 53 - ] - ], - [ - [ - 11382, - 12428 - ], - [ - 76, - 4 - ], - [ - 16, - 28 - ], - [ - 22, - 2 - ], - [ - 28, - -30 - ], - [ - 21, - 0 - ], - [ - 23, - 20 - ], - [ - 14, - -35 - ], - [ - -30, - -27 - ], - [ - -30, - 3 - ], - [ - -30, - 25 - ], - [ - -26, - -28 - ], - [ - -12, - -1 - ], - [ - -17, - -17 - ], - [ - -63, - 3 - ] - ], - [ - [ - 11493, - 12122 - ], - [ - -37, - 50 - ], - [ - -30, - 8 - ], - [ - -16, - 34 - ], - [ - 1, - 18 - ], - [ - -22, - 25 - ], - [ - -4, - 26 - ] - ], - [ - [ - 11385, - 12283 - ], - [ - 37, - 20 - ], - [ - 23, - -4 - ], - [ - 19, - 13 - ], - [ - 128, - -5 - ] - ], - [ - [ - 13209, - 10918 - ], - [ - -13, - 18 - ], - [ - 24, - 135 - ] - ], - [ - [ - 14013, - 15697 - ], - [ - 45, - 11 - ], - [ - 27, - 26 - ], - [ - 38, - -2 - ], - [ - 11, - 20 - ], - [ - 13, - 4 - ] - ], - [ - [ - 14368, - 15815 - ], - [ - 34, - -32 - ], - [ - -22, - -75 - ], - [ - -16, - -13 - ] - ], - [ - [ - 14364, - 15695 - ], - [ - -43, - 3 - ], - [ - -36, - 12 - ], - [ - -84, - -32 - ], - [ - 48, - -67 - ], - [ - -35, - -20 - ], - [ - -39, - 0 - ], - [ - -37, - 62 - ], - [ - -13, - -26 - ], - [ - 15, - -72 - ], - [ - 35, - -56 - ], - [ - -26, - -27 - ], - [ - 39, - -55 - ], - [ - 34, - -35 - ], - [ - 1, - -67 - ], - [ - -64, - 31 - ], - [ - 20, - -61 - ], - [ - -44, - -12 - ], - [ - 27, - -106 - ], - [ - -47, - -2 - ], - [ - -57, - 52 - ], - [ - -26, - 96 - ], - [ - -12, - 80 - ], - [ - -27, - 55 - ], - [ - -36, - 69 - ], - [ - -5, - 34 - ] - ], - [ - [ - 14200, - 15081 - ], - [ - 38, - -41 - ], - [ - 54, - 7 - ], - [ - 52, - -8 - ], - [ - -2, - -21 - ], - [ - 38, - 14 - ], - [ - -9, - -35 - ], - [ - -100, - -10 - ], - [ - 1, - 19 - ], - [ - -85, - 24 - ], - [ - 13, - 51 - ] - ], - [ - [ - 9288, - 20710 - ], - [ - 234, - 72 - ], - [ - 244, - -6 - ], - [ - 89, - 44 - ], - [ - 247, - 12 - ], - [ - 556, - -15 - ], - [ - 436, - -95 - ], - [ - -128, - -46 - ], - [ - -267, - -6 - ], - [ - -375, - -11 - ], - [ - 35, - -22 - ], - [ - 247, - 13 - ], - [ - 210, - -41 - ], - [ - 135, - 37 - ], - [ - 58, - -43 - ], - [ - -77, - -70 - ], - [ - 178, - 45 - ], - [ - 338, - 46 - ], - [ - 209, - -23 - ], - [ - 39, - -51 - ], - [ - -284, - -86 - ], - [ - -39, - -27 - ], - [ - -223, - -21 - ], - [ - 162, - -6 - ], - [ - -82, - -87 - ], - [ - -56, - -78 - ], - [ - 2, - -134 - ], - [ - 84, - -78 - ], - [ - -109, - -5 - ], - [ - -115, - -38 - ], - [ - 129, - -63 - ], - [ - 16, - -102 - ], - [ - -74, - -11 - ], - [ - 90, - -104 - ], - [ - -155, - -8 - ], - [ - 81, - -49 - ], - [ - -23, - -42 - ], - [ - -98, - -19 - ], - [ - -97, - 0 - ], - [ - 87, - -82 - ], - [ - 1, - -53 - ], - [ - -138, - 50 - ], - [ - -36, - -32 - ], - [ - 94, - -30 - ], - [ - 92, - -74 - ], - [ - 26, - -96 - ], - [ - -124, - -23 - ], - [ - -54, - 46 - ], - [ - -86, - 69 - ], - [ - 24, - -82 - ], - [ - -81, - -63 - ], - [ - 184, - -5 - ], - [ - 96, - -6 - ], - [ - -187, - -105 - ], - [ - -190, - -94 - ], - [ - -204, - -42 - ], - [ - -77, - 0 - ], - [ - -72, - -47 - ], - [ - -97, - -126 - ], - [ - -150, - -84 - ], - [ - -48, - -5 - ], - [ - -93, - -30 - ], - [ - -100, - -28 - ], - [ - -59, - -74 - ], - [ - -1, - -84 - ], - [ - -36, - -79 - ], - [ - -113, - -96 - ], - [ - 28, - -94 - ], - [ - -32, - -99 - ], - [ - -35, - -117 - ], - [ - -99, - -7 - ], - [ - -102, - 98 - ], - [ - -140, - 0 - ], - [ - -67, - 66 - ], - [ - -47, - 117 - ], - [ - -121, - 149 - ], - [ - -35, - 79 - ], - [ - -10, - 107 - ], - [ - -96, - 111 - ], - [ - 25, - 88 - ], - [ - -47, - 43 - ], - [ - 69, - 140 - ], - [ - 105, - 45 - ], - [ - 28, - 50 - ], - [ - 14, - 94 - ], - [ - -79, - -43 - ], - [ - -38, - -18 - ], - [ - -63, - -17 - ], - [ - -85, - 39 - ], - [ - -5, - 82 - ], - [ - 27, - 64 - ], - [ - 65, - 1 - ], - [ - 142, - -32 - ], - [ - -120, - 77 - ], - [ - -62, - 41 - ], - [ - -69, - -17 - ], - [ - -59, - 29 - ], - [ - 78, - 112 - ], - [ - -42, - 45 - ], - [ - -56, - 83 - ], - [ - -83, - 127 - ], - [ - -89, - 47 - ], - [ - 1, - 50 - ], - [ - -187, - 70 - ], - [ - -148, - 9 - ], - [ - -187, - -5 - ], - [ - -170, - -9 - ], - [ - -81, - 38 - ], - [ - -121, - 76 - ], - [ - 183, - 38 - ], - [ - 140, - 6 - ], - [ - -298, - 31 - ], - [ - -157, - 49 - ], - [ - 10, - 47 - ], - [ - 264, - 57 - ], - [ - 255, - 58 - ], - [ - 27, - 44 - ], - [ - -188, - 43 - ], - [ - 60, - 48 - ], - [ - 242, - 83 - ], - [ - 101, - 13 - ], - [ - -29, - 54 - ], - [ - 165, - 32 - ], - [ - 215, - 19 - ], - [ - 214, - 1 - ], - [ - 76, - -38 - ], - [ - 185, - 66 - ], - [ - 166, - -45 - ], - [ - 98, - -9 - ], - [ - 145, - -39 - ], - [ - -166, - 65 - ], - [ - 10, - 51 - ] - ], - [ - [ - 6348, - 12703 - ], - [ - 23, - -22 - ], - [ - 6, - 18 - ], - [ - 20, - -15 - ] - ], - [ - [ - 6397, - 12684 - ], - [ - -31, - -46 - ], - [ - -33, - -33 - ], - [ - -5, - -23 - ], - [ - 5, - -24 - ], - [ - -14, - -30 - ] - ], - [ - [ - 6319, - 12528 - ], - [ - -16, - -8 - ], - [ - 3, - -14 - ], - [ - -13, - -13 - ], - [ - -24, - -30 - ], - [ - -2, - -18 - ] - ], - [ - [ - 6267, - 12445 - ], - [ - -36, - 21 - ], - [ - -43, - 2 - ], - [ - -32, - 24 - ], - [ - -38, - 49 - ] - ], - [ - [ - 6118, - 12541 - ], - [ - 2, - 35 - ], - [ - 8, - 28 - ], - [ - -10, - 23 - ], - [ - 34, - 98 - ], - [ - 89, - 0 - ], - [ - 2, - 41 - ], - [ - -11, - 7 - ], - [ - -8, - 26 - ], - [ - -26, - 28 - ], - [ - -26, - 40 - ], - [ - 32, - 0 - ], - [ - 0, - 68 - ], - [ - 65, - 0 - ], - [ - 64, - -1 - ] - ], - [ - [ - 8314, - 11421 - ], - [ - -47, - 91 - ], - [ - 19, - 33 - ], - [ - -2, - 56 - ], - [ - 43, - 19 - ], - [ - 17, - 22 - ], - [ - -23, - 45 - ], - [ - 6, - 44 - ], - [ - 55, - 70 - ] - ], - [ - [ - 8382, - 11801 - ], - [ - 46, - -44 - ], - [ - 43, - -78 - ], - [ - 2, - -62 - ], - [ - 26, - -3 - ], - [ - 37, - -58 - ], - [ - 28, - -42 - ] - ], - [ - [ - 8564, - 11514 - ], - [ - -11, - -108 - ], - [ - -43, - -31 - ], - [ - 4, - -29 - ], - [ - -13, - -62 - ], - [ - 31, - -87 - ], - [ - 23, - 0 - ], - [ - 9, - -68 - ], - [ - 42, - -104 - ] - ], - [ - [ - 6397, - 12684 - ], - [ - 8, - -5 - ], - [ - 15, - 21 - ], - [ - 20, - 2 - ], - [ - 6, - -10 - ], - [ - 11, - 6 - ], - [ - 33, - -10 - ], - [ - 32, - 3 - ], - [ - 22, - 13 - ], - [ - 8, - 13 - ], - [ - 23, - -6 - ], - [ - 16, - -8 - ], - [ - 19, - 3 - ], - [ - 13, - 10 - ], - [ - 32, - -16 - ], - [ - 11, - -3 - ], - [ - 22, - -23 - ], - [ - 20, - -26 - ], - [ - 25, - -19 - ], - [ - 18, - -33 - ] - ], - [ - [ - 6751, - 12596 - ], - [ - -23, - 3 - ], - [ - -10, - -17 - ], - [ - -24, - -15 - ], - [ - -18, - 0 - ], - [ - -15, - -16 - ], - [ - -14, - 6 - ], - [ - -12, - 18 - ], - [ - -7, - -3 - ], - [ - -9, - -29 - ], - [ - -7, - 1 - ], - [ - -1, - -25 - ], - [ - -25, - -33 - ], - [ - -12, - -14 - ], - [ - -8, - -15 - ], - [ - -20, - 24 - ], - [ - -15, - -32 - ], - [ - -15, - 1 - ], - [ - -16, - -3 - ], - [ - 1, - -59 - ], - [ - -10, - -1 - ], - [ - -9, - -27 - ], - [ - -21, - -5 - ] - ], - [ - [ - 6461, - 12355 - ], - [ - -12, - 37 - ], - [ - -21, - 11 - ] - ], - [ - [ - 6428, - 12403 - ], - [ - 4, - 48 - ], - [ - -9, - 13 - ], - [ - -14, - 9 - ], - [ - -31, - -15 - ], - [ - -3, - 16 - ], - [ - -21, - 20 - ], - [ - -15, - 24 - ], - [ - -20, - 10 - ] - ], - [ - [ - 13841, - 15914 - ], - [ - -7, - -21 - ] - ], - [ - [ - 13834, - 15893 - ], - [ - -66, - 45 - ], - [ - -40, - 43 - ], - [ - -64, - 36 - ], - [ - -59, - 88 - ], - [ - 14, - 9 - ], - [ - -31, - 50 - ], - [ - -2, - 41 - ], - [ - -45, - 19 - ], - [ - -21, - -52 - ], - [ - -20, - 40 - ], - [ - 1, - 42 - ], - [ - 3, - 2 - ] - ], - [ - [ - 13504, - 16256 - ], - [ - 48, - -4 - ], - [ - 13, - 20 - ], - [ - 24, - -20 - ], - [ - 27, - -2 - ], - [ - 0, - 34 - ], - [ - 24, - 12 - ], - [ - 7, - 48 - ], - [ - 55, - 32 - ] - ], - [ - [ - 13702, - 16376 - ], - [ - 22, - -15 - ], - [ - 52, - -51 - ], - [ - 58, - -23 - ], - [ - 26, - 18 - ] - ], - [ - [ - 13860, - 16305 - ], - [ - 17, - -47 - ], - [ - 22, - -34 - ], - [ - -27, - -45 - ] - ], - [ - [ - 7549, - 12962 - ], - [ - -46, - 20 - ], - [ - -33, - -8 - ], - [ - -43, - 9 - ], - [ - -33, - -23 - ], - [ - -37, - 38 - ], - [ - 6, - 38 - ], - [ - 64, - -16 - ], - [ - 53, - -10 - ], - [ - 25, - 27 - ], - [ - -32, - 52 - ], - [ - 1, - 46 - ], - [ - -44, - 18 - ], - [ - 16, - 33 - ], - [ - 42, - -5 - ], - [ - 61, - -19 - ] - ], - [ - [ - 13731, - 16571 - ], - [ - 36, - -31 - ], - [ - 25, - -13 - ], - [ - 59, - 14 - ], - [ - 5, - 25 - ], - [ - 28, - 3 - ], - [ - 34, - 19 - ], - [ - 8, - -8 - ], - [ - 32, - 15 - ], - [ - 17, - 28 - ], - [ - 23, - 8 - ], - [ - 74, - -37 - ], - [ - 15, - 12 - ] - ], - [ - [ - 14087, - 16606 - ], - [ - 39, - -32 - ], - [ - 5, - -32 - ] - ], - [ - [ - 14131, - 16542 - ], - [ - -43, - -26 - ], - [ - -33, - -81 - ], - [ - -42, - -81 - ], - [ - -56, - -23 - ] - ], - [ - [ - 13957, - 16331 - ], - [ - -43, - 5 - ], - [ - -54, - -31 - ] - ], - [ - [ - 13702, - 16376 - ], - [ - -13, - 41 - ], - [ - -12, - 1 - ] - ], - [ - [ - 20962, - 9569 - ], - [ - -29, - -3 - ], - [ - -92, - 85 - ], - [ - 65, - 23 - ], - [ - 36, - -36 - ], - [ - 25, - -37 - ], - [ - -5, - -32 - ] - ], - [ - [ - 21259, - 9730 - ], - [ - 7, - -23 - ], - [ - 1, - -37 - ] - ], - [ - [ - 21267, - 9670 - ], - [ - -45, - -89 - ], - [ - -60, - -27 - ], - [ - -8, - 15 - ], - [ - 6, - 40 - ], - [ - 30, - 74 - ], - [ - 69, - 47 - ] - ], - [ - [ - 20766, - 9826 - ], - [ - 25, - -32 - ], - [ - 43, - 10 - ], - [ - 18, - -51 - ], - [ - -81, - -24 - ], - [ - -48, - -16 - ], - [ - -38, - 1 - ], - [ - 24, - 69 - ], - [ - 38, - 1 - ], - [ - 19, - 42 - ] - ], - [ - [ - 21115, - 9826 - ], - [ - -10, - -67 - ], - [ - -105, - -34 - ], - [ - -93, - 15 - ], - [ - 0, - 44 - ], - [ - 55, - 25 - ], - [ - 44, - -36 - ], - [ - 46, - 9 - ], - [ - 63, - 44 - ] - ], - [ - [ - 20119, - 9984 - ], - [ - 134, - -12 - ], - [ - 15, - 50 - ], - [ - 130, - -58 - ], - [ - 25, - -78 - ], - [ - 105, - -22 - ], - [ - 85, - -71 - ], - [ - -79, - -46 - ], - [ - -77, - 49 - ], - [ - -63, - -4 - ], - [ - -72, - 9 - ], - [ - -66, - 22 - ], - [ - -80, - 46 - ], - [ - -52, - 11 - ], - [ - -29, - -15 - ], - [ - -127, - 50 - ], - [ - -12, - 51 - ], - [ - -64, - 9 - ], - [ - 48, - 115 - ], - [ - 85, - -7 - ], - [ - 56, - -47 - ], - [ - 29, - -9 - ], - [ - 9, - -43 - ] - ], - [ - [ - 21939, - 10052 - ], - [ - -36, - -82 - ], - [ - -7, - 90 - ], - [ - 13, - 43 - ], - [ - 14, - 41 - ], - [ - 16, - -35 - ], - [ - 0, - -57 - ] - ], - [ - [ - 21418, - 10382 - ], - [ - -26, - -40 - ], - [ - -48, - 22 - ], - [ - -14, - 52 - ], - [ - 71, - 6 - ], - [ - 17, - -40 - ] - ], - [ - [ - 21642, - 10426 - ], - [ - 26, - -92 - ], - [ - -59, - 50 - ], - [ - -58, - 10 - ], - [ - -40, - -8 - ], - [ - -48, - 4 - ], - [ - 17, - 66 - ], - [ - 86, - 5 - ], - [ - 76, - -35 - ] - ], - [ - [ - 22376, - 10485 - ], - [ - 2, - -391 - ], - [ - 1, - -391 - ] - ], - [ - [ - 22379, - 9703 - ], - [ - -62, - 99 - ], - [ - -71, - 24 - ], - [ - -17, - -34 - ], - [ - -89, - -4 - ], - [ - 30, - 98 - ], - [ - 44, - 33 - ], - [ - -18, - 130 - ], - [ - -34, - 101 - ], - [ - -135, - 102 - ], - [ - -57, - 10 - ], - [ - -105, - 111 - ], - [ - -21, - -59 - ], - [ - -26, - -10 - ], - [ - -16, - 44 - ], - [ - 0, - 52 - ], - [ - -54, - 59 - ], - [ - 75, - 43 - ], - [ - 50, - -2 - ], - [ - -6, - 32 - ], - [ - -102, - 0 - ], - [ - -27, - 71 - ], - [ - -63, - 22 - ], - [ - -29, - 60 - ], - [ - 94, - 29 - ], - [ - 35, - 39 - ], - [ - 112, - -49 - ], - [ - 11, - -45 - ], - [ - 20, - -194 - ], - [ - 72, - -72 - ], - [ - 58, - 127 - ], - [ - 80, - 73 - ], - [ - 62, - 0 - ], - [ - 60, - -42 - ], - [ - 52, - -43 - ], - [ - 74, - -23 - ] - ], - [ - [ - 21278, - 10968 - ], - [ - -56, - -119 - ], - [ - -53, - -24 - ], - [ - -67, - 24 - ], - [ - -116, - -6 - ], - [ - -61, - -17 - ], - [ - -10, - -91 - ], - [ - 63, - -107 - ], - [ - 37, - 55 - ], - [ - 130, - 40 - ], - [ - -5, - -55 - ], - [ - -31, - 18 - ], - [ - -30, - -71 - ], - [ - -61, - -46 - ], - [ - 66, - -154 - ], - [ - -13, - -41 - ], - [ - 63, - -139 - ], - [ - -1, - -79 - ], - [ - -37, - -35 - ], - [ - -28, - 42 - ], - [ - 34, - 99 - ], - [ - -68, - -47 - ], - [ - -18, - 33 - ], - [ - 9, - 47 - ], - [ - -50, - 70 - ], - [ - 5, - 117 - ], - [ - -46, - -37 - ], - [ - 6, - -139 - ], - [ - 3, - -172 - ], - [ - -45, - -17 - ], - [ - -30, - 35 - ], - [ - 20, - 110 - ], - [ - -10, - 116 - ], - [ - -30, - 1 - ], - [ - -21, - 82 - ], - [ - 28, - 79 - ], - [ - 10, - 95 - ], - [ - 35, - 181 - ], - [ - 15, - 49 - ], - [ - 59, - 89 - ], - [ - 55, - -35 - ], - [ - 88, - -17 - ], - [ - 80, - 5 - ], - [ - 69, - 87 - ], - [ - 12, - -26 - ] - ], - [ - [ - 21518, - 10933 - ], - [ - -4, - -105 - ], - [ - -35, - 12 - ], - [ - -11, - -73 - ], - [ - 29, - -63 - ], - [ - -20, - -15 - ], - [ - -28, - 76 - ], - [ - -21, - 154 - ], - [ - 14, - 95 - ], - [ - 23, - 44 - ], - [ - 5, - -65 - ], - [ - 42, - -11 - ], - [ - 6, - -49 - ] - ], - [ - [ - 20192, - 11038 - ], - [ - 12, - -80 - ], - [ - 47, - -68 - ], - [ - 45, - 24 - ], - [ - 45, - -8 - ], - [ - 40, - 60 - ], - [ - 34, - 11 - ], - [ - 66, - -34 - ], - [ - 57, - 26 - ], - [ - 35, - 167 - ], - [ - 27, - 41 - ], - [ - 24, - 137 - ], - [ - 80, - 0 - ], - [ - 61, - -20 - ] - ], - [ - [ - 20765, - 11294 - ], - [ - -40, - -109 - ], - [ - 51, - -113 - ], - [ - -12, - -56 - ], - [ - 79, - -111 - ], - [ - -83, - -14 - ], - [ - -23, - -82 - ], - [ - 3, - -108 - ], - [ - -67, - -82 - ], - [ - -2, - -120 - ], - [ - -27, - -183 - ], - [ - -10, - 42 - ], - [ - -79, - -54 - ], - [ - -28, - 74 - ], - [ - -50, - 7 - ], - [ - -35, - 38 - ], - [ - -82, - -43 - ], - [ - -26, - 58 - ], - [ - -46, - -7 - ], - [ - -57, - 14 - ], - [ - -11, - 161 - ], - [ - -34, - 33 - ], - [ - -34, - 103 - ], - [ - -10, - 105 - ], - [ - 9, - 111 - ], - [ - 41, - 80 - ] - ], - [ - [ - 19924, - 10095 - ], - [ - -77, - -2 - ], - [ - -59, - 100 - ], - [ - -90, - 98 - ], - [ - -29, - 73 - ], - [ - -53, - 97 - ], - [ - -35, - 90 - ], - [ - -53, - 168 - ], - [ - -61, - 100 - ], - [ - -20, - 103 - ], - [ - -26, - 94 - ], - [ - -63, - 75 - ], - [ - -36, - 103 - ], - [ - -53, - 67 - ], - [ - -73, - 133 - ], - [ - -6, - 61 - ], - [ - 45, - -5 - ], - [ - 108, - -23 - ], - [ - 62, - -118 - ], - [ - 54, - -81 - ], - [ - 38, - -50 - ], - [ - 66, - -129 - ], - [ - 71, - -2 - ], - [ - 58, - -82 - ], - [ - 41, - -100 - ], - [ - 53, - -55 - ], - [ - -28, - -98 - ], - [ - 40, - -42 - ], - [ - 25, - -3 - ], - [ - 12, - -84 - ], - [ - 24, - -67 - ], - [ - 51, - -10 - ], - [ - 34, - -76 - ], - [ - -17, - -149 - ], - [ - -3, - -186 - ] - ], - [ - [ - 18754, - 13443 - ], - [ - -10, - -44 - ], - [ - -48, - 2 - ], - [ - -86, - -25 - ], - [ - 4, - -90 - ], - [ - -37, - -71 - ], - [ - -100, - -81 - ], - [ - -78, - -141 - ], - [ - -53, - -76 - ], - [ - -69, - -78 - ], - [ - 0, - -56 - ], - [ - -35, - -29 - ], - [ - -63, - -43 - ], - [ - -32, - -6 - ], - [ - -21, - -92 - ], - [ - 14, - -156 - ], - [ - 4, - -99 - ], - [ - -29, - -114 - ], - [ - -1, - -204 - ], - [ - -36, - -6 - ], - [ - -32, - -92 - ], - [ - 22, - -39 - ], - [ - -64, - -34 - ], - [ - -23, - -82 - ], - [ - -28, - -34 - ], - [ - -66, - 112 - ], - [ - -33, - 168 - ], - [ - -26, - 121 - ], - [ - -25, - 57 - ], - [ - -37, - 115 - ], - [ - -17, - 150 - ], - [ - -12, - 75 - ], - [ - -64, - 165 - ], - [ - -28, - 232 - ], - [ - -21, - 154 - ], - [ - 0, - 145 - ], - [ - -14, - 112 - ], - [ - -101, - -72 - ], - [ - -49, - 15 - ], - [ - -91, - 145 - ], - [ - 33, - 44 - ], - [ - -20, - 47 - ], - [ - -82, - 101 - ] - ], - [ - [ - 17300, - 13639 - ], - [ - 46, - 81 - ], - [ - 154, - -1 - ], - [ - -14, - 103 - ], - [ - -39, - 61 - ], - [ - -8, - 92 - ], - [ - -46, - 54 - ], - [ - 77, - 126 - ], - [ - 81, - -9 - ], - [ - 73, - 126 - ], - [ - 44, - 121 - ], - [ - 67, - 121 - ], - [ - -1, - 85 - ], - [ - 60, - 70 - ], - [ - -57, - 59 - ], - [ - -24, - 81 - ], - [ - -25, - 105 - ], - [ - 35, - 52 - ], - [ - 105, - -29 - ], - [ - 78, - 18 - ], - [ - 67, - 100 - ] - ], - [ - [ - 18202, - 14418 - ], - [ - -45, - -54 - ], - [ - -27, - -112 - ], - [ - 68, - -46 - ], - [ - 66, - -59 - ], - [ - 91, - -67 - ], - [ - 95, - -15 - ], - [ - 40, - -61 - ], - [ - 54, - -12 - ], - [ - 84, - -28 - ], - [ - 58, - 2 - ], - [ - 8, - 48 - ], - [ - -9, - 76 - ], - [ - 5, - 52 - ] - ], - [ - [ - 19332, - 14188 - ], - [ - 5, - -46 - ], - [ - -24, - -22 - ], - [ - 6, - -74 - ], - [ - -50, - 22 - ], - [ - -91, - -83 - ], - [ - 3, - -68 - ], - [ - -39, - -101 - ], - [ - -3, - -59 - ], - [ - -31, - -98 - ], - [ - -55, - 27 - ], - [ - -3, - -124 - ], - [ - -15, - -41 - ], - [ - 7, - -51 - ], - [ - -34, - -29 - ] - ], - [ - [ - 12115, - 17260 - ], - [ - 12, - -86 - ], - [ - -53, - -107 - ], - [ - -123, - -71 - ], - [ - -99, - 18 - ], - [ - 57, - 125 - ], - [ - -37, - 122 - ], - [ - 95, - 94 - ], - [ - 53, - 56 - ] - ], - [ - [ - 16791, - 14376 - ], - [ - 34, - -63 - ], - [ - 29, - -73 - ], - [ - 66, - -53 - ], - [ - 2, - -105 - ], - [ - 33, - -20 - ], - [ - 6, - -55 - ], - [ - -100, - -62 - ], - [ - -27, - -139 - ] - ], - [ - [ - 16834, - 13806 - ], - [ - -131, - 36 - ], - [ - -76, - 28 - ], - [ - -78, - 15 - ], - [ - -30, - 147 - ], - [ - -34, - 22 - ], - [ - -53, - -22 - ], - [ - -70, - -58 - ], - [ - -86, - 40 - ], - [ - -70, - 92 - ], - [ - -67, - 34 - ], - [ - -47, - 114 - ], - [ - -51, - 160 - ], - [ - -38, - -19 - ], - [ - -44, - 39 - ], - [ - -26, - -47 - ] - ], - [ - [ - 15933, - 14387 - ], - [ - -38, - 64 - ], - [ - -1, - 63 - ], - [ - -22, - 0 - ], - [ - 11, - 87 - ], - [ - -36, - 91 - ], - [ - -85, - 66 - ], - [ - -49, - 114 - ], - [ - 17, - 94 - ], - [ - 35, - 41 - ], - [ - -6, - 70 - ], - [ - -45, - 36 - ], - [ - -45, - 143 - ] - ], - [ - [ - 15669, - 15256 - ], - [ - -39, - 97 - ], - [ - 14, - 37 - ], - [ - -22, - 137 - ], - [ - 48, - 35 - ] - ], - [ - [ - 15955, - 15394 - ], - [ - 22, - -88 - ], - [ - 66, - -25 - ], - [ - 49, - -60 - ], - [ - 99, - -21 - ], - [ - 109, - 32 - ], - [ - 6, - 28 - ] - ], - [ - [ - 16306, - 15260 - ], - [ - 62, - 23 - ], - [ - 49, - 69 - ], - [ - 47, - -4 - ], - [ - 30, - 23 - ], - [ - 50, - -11 - ], - [ - 77, - -61 - ], - [ - 56, - -13 - ], - [ - 79, - -107 - ], - [ - 52, - -4 - ], - [ - 6, - -101 - ] - ], - [ - [ - 15933, - 14387 - ], - [ - -41, - 6 - ] - ], - [ - [ - 15892, - 14393 - ], - [ - -47, - 10 - ], - [ - -51, - -115 - ] - ], - [ - [ - 15794, - 14288 - ], - [ - -130, - 10 - ], - [ - -196, - 241 - ], - [ - -104, - 84 - ], - [ - -84, - 33 - ] - ], - [ - [ - 15280, - 14656 - ], - [ - -28, - 146 - ] - ], - [ - [ - 15252, - 14802 - ], - [ - 154, - 124 - ], - [ - 26, - 145 - ], - [ - -6, - 88 - ], - [ - 38, - 30 - ], - [ - 36, - 75 - ] - ], - [ - [ - 15500, - 15264 - ], - [ - 30, - 18 - ], - [ - 81, - -15 - ], - [ - 24, - -31 - ], - [ - 34, - 20 - ] - ], - [ - [ - 11536, - 18770 - ], - [ - -16, - -78 - ], - [ - 79, - -82 - ], - [ - -91, - -91 - ], - [ - -201, - -82 - ], - [ - -60, - -22 - ], - [ - -92, - 17 - ], - [ - -194, - 38 - ], - [ - 68, - 53 - ], - [ - -151, - 59 - ], - [ - 123, - 23 - ], - [ - -3, - 36 - ], - [ - -146, - 27 - ], - [ - 47, - 79 - ], - [ - 106, - 17 - ], - [ - 108, - -81 - ], - [ - 106, - 65 - ], - [ - 88, - -34 - ], - [ - 113, - 64 - ], - [ - 116, - -8 - ] - ], - [ - [ - 14936, - 14543 - ], - [ - 20, - 39 - ], - [ - -4, - 7 - ], - [ - 18, - 56 - ], - [ - 14, - 90 - ], - [ - 10, - 31 - ], - [ - 2, - 1 - ] - ], - [ - [ - 14996, - 14767 - ], - [ - 23, - 0 - ], - [ - 7, - 21 - ], - [ - 19, - 1 - ] - ], - [ - [ - 15045, - 14789 - ], - [ - 1, - -49 - ], - [ - -10, - -18 - ], - [ - 1, - -1 - ] - ], - [ - [ - 15037, - 14721 - ], - [ - -12, - -38 - ] - ], - [ - [ - 15025, - 14683 - ], - [ - -25, - 17 - ], - [ - -14, - -80 - ], - [ - 17, - -13 - ], - [ - -18, - -17 - ], - [ - -3, - -31 - ], - [ - 33, - 16 - ] - ], - [ - [ - 15015, - 14575 - ], - [ - 2, - -47 - ], - [ - -35, - -192 - ] - ], - [ - [ - 13510, - 16377 - ], - [ - -8, - -59 - ], - [ - 17, - -51 - ] - ], - [ - [ - 13519, - 16267 - ], - [ - -55, - 17 - ], - [ - -57, - -42 - ], - [ - 4, - -60 - ], - [ - -9, - -34 - ], - [ - 23, - -61 - ], - [ - 65, - -61 - ], - [ - 35, - -99 - ], - [ - 78, - -96 - ], - [ - 55, - 0 - ], - [ - 17, - -26 - ], - [ - -20, - -24 - ], - [ - 63, - -44 - ], - [ - 51, - -36 - ], - [ - 60, - -62 - ], - [ - 7, - -23 - ], - [ - -13, - -43 - ], - [ - -39, - 56 - ], - [ - -61, - 20 - ], - [ - -29, - -78 - ], - [ - 50, - -44 - ], - [ - -8, - -63 - ], - [ - -29, - -7 - ], - [ - -37, - -103 - ], - [ - -29, - -9 - ], - [ - 0, - 37 - ], - [ - 14, - 64 - ], - [ - 15, - 26 - ], - [ - -27, - 69 - ], - [ - -21, - 61 - ], - [ - -29, - 15 - ], - [ - -21, - 51 - ], - [ - -44, - 22 - ], - [ - -31, - 49 - ], - [ - -51, - 7 - ], - [ - -55, - 54 - ], - [ - -63, - 79 - ], - [ - -48, - 69 - ], - [ - -21, - 118 - ], - [ - -35, - 14 - ], - [ - -57, - 40 - ], - [ - -32, - -16 - ], - [ - -40, - -56 - ], - [ - -29, - -9 - ] - ], - [ - [ - 13629, - 15384 - ], - [ - -25, - -95 - ], - [ - 11, - -37 - ], - [ - -15, - -62 - ], - [ - -53, - 46 - ], - [ - -36, - 13 - ], - [ - -97, - 61 - ], - [ - 10, - 61 - ], - [ - 81, - -11 - ], - [ - 71, - 13 - ], - [ - 53, - 11 - ] - ], - [ - [ - 13190, - 15741 - ], - [ - 41, - -85 - ], - [ - -9, - -159 - ], - [ - -32, - 8 - ], - [ - -29, - -40 - ], - [ - -26, - 32 - ], - [ - -3, - 144 - ], - [ - -16, - 69 - ], - [ - 39, - -6 - ], - [ - 35, - 37 - ] - ], - [ - [ - 7140, - 13015 - ], - [ - 47, - -10 - ], - [ - 37, - -29 - ], - [ - 12, - -33 - ], - [ - -49, - -2 - ], - [ - -21, - -20 - ], - [ - -39, - 19 - ], - [ - -40, - 44 - ], - [ - 8, - 27 - ], - [ - 29, - 9 - ], - [ - 16, - -5 - ] - ], - [ - [ - 15280, - 14656 - ], - [ - -14, - -19 - ], - [ - -139, - -60 - ], - [ - 69, - -120 - ], - [ - -23, - -20 - ], - [ - -11, - -40 - ], - [ - -53, - -17 - ], - [ - -17, - -43 - ], - [ - -30, - -37 - ], - [ - -78, - 19 - ] - ], - [ - [ - 14984, - 14319 - ], - [ - -2, - 17 - ] - ], - [ - [ - 15015, - 14575 - ], - [ - 10, - 35 - ], - [ - 0, - 73 - ] - ], - [ - [ - 15037, - 14721 - ], - [ - 78, - -47 - ], - [ - 137, - 128 - ] - ], - [ - [ - 21933, - 14894 - ], - [ - 9, - -41 - ], - [ - -39, - -73 - ], - [ - -29, - 39 - ], - [ - -36, - -28 - ], - [ - -18, - -70 - ], - [ - -46, - 34 - ], - [ - 1, - 57 - ], - [ - 38, - 71 - ], - [ - 40, - -14 - ], - [ - 29, - 51 - ], - [ - 51, - -26 - ] - ], - [ - [ - 22375, - 15253 - ], - [ - -27, - -96 - ], - [ - 13, - -60 - ], - [ - -37, - -84 - ], - [ - -89, - -57 - ], - [ - -122, - -7 - ], - [ - -100, - -137 - ], - [ - -46, - 46 - ], - [ - -3, - 90 - ], - [ - -122, - -27 - ], - [ - -82, - -56 - ], - [ - -82, - -3 - ], - [ - 71, - -88 - ], - [ - -47, - -204 - ], - [ - -45, - -50 - ], - [ - -33, - 46 - ], - [ - 17, - 109 - ], - [ - -44, - 34 - ], - [ - -29, - 83 - ], - [ - 66, - 37 - ], - [ - 37, - 75 - ], - [ - 70, - 62 - ], - [ - 51, - 82 - ], - [ - 139, - 36 - ], - [ - 74, - -25 - ], - [ - 73, - 214 - ], - [ - 47, - -58 - ], - [ - 102, - 120 - ], - [ - 40, - 47 - ], - [ - 43, - 147 - ], - [ - -11, - 135 - ], - [ - 29, - 75 - ], - [ - 74, - 22 - ], - [ - 38, - -166 - ], - [ - -2, - -97 - ], - [ - -64, - -121 - ], - [ - 1, - -124 - ] - ], - [ - [ - 22579, - 16097 - ], - [ - 49, - -26 - ], - [ - 50, - 51 - ], - [ - 15, - -135 - ], - [ - -103, - -33 - ], - [ - -61, - -119 - ], - [ - -110, - 82 - ], - [ - -38, - -131 - ], - [ - -77, - -2 - ], - [ - -10, - 120 - ], - [ - 34, - 92 - ], - [ - 75, - 6 - ], - [ - 20, - 166 - ], - [ - 21, - 94 - ], - [ - 82, - -125 - ], - [ - 53, - -40 - ] - ], - [ - [ - 18142, - 15878 - ], - [ - -43, - 17 - ], - [ - -35, - 44 - ], - [ - -103, - 12 - ], - [ - -116, - 3 - ], - [ - -25, - -13 - ], - [ - -99, - 51 - ], - [ - -40, - -25 - ], - [ - -11, - -71 - ], - [ - -114, - 41 - ], - [ - -46, - -17 - ], - [ - -16, - -52 - ] - ], - [ - [ - 17494, - 15868 - ], - [ - -40, - -22 - ], - [ - -92, - -84 - ], - [ - -30, - -86 - ], - [ - -26, - -1 - ], - [ - -19, - 57 - ], - [ - -89, - 4 - ], - [ - -14, - 98 - ], - [ - -34, - 1 - ], - [ - 5, - 121 - ], - [ - -83, - 87 - ], - [ - -120, - -9 - ], - [ - -82, - -18 - ], - [ - -66, - 109 - ], - [ - -57, - 45 - ], - [ - -108, - 86 - ], - [ - -13, - 10 - ], - [ - -180, - -71 - ], - [ - 3, - -442 - ] - ], - [ - [ - 16449, - 15753 - ], - [ - -36, - -6 - ], - [ - -49, - 94 - ], - [ - -47, - 34 - ], - [ - -79, - -25 - ], - [ - -31, - -40 - ] - ], - [ - [ - 16207, - 15810 - ], - [ - -4, - 29 - ], - [ - 18, - 50 - ], - [ - -14, - 42 - ], - [ - -81, - 41 - ], - [ - -31, - 108 - ], - [ - -38, - 30 - ], - [ - -3, - 39 - ], - [ - 68, - -11 - ], - [ - 3, - 87 - ], - [ - 59, - 20 - ], - [ - 61, - -18 - ], - [ - 12, - 117 - ], - [ - -12, - 74 - ], - [ - -70, - -6 - ], - [ - -59, - 30 - ], - [ - -81, - -53 - ], - [ - -65, - -25 - ] - ], - [ - [ - 15970, - 16364 - ], - [ - -35, - 19 - ], - [ - 7, - 62 - ], - [ - -45, - 80 - ], - [ - -51, - -3 - ], - [ - -59, - 81 - ], - [ - 40, - 91 - ], - [ - -21, - 24 - ], - [ - 56, - 132 - ], - [ - 72, - -69 - ], - [ - 8, - 87 - ], - [ - 144, - 131 - ], - [ - 109, - 3 - ], - [ - 154, - -83 - ], - [ - 82, - -49 - ], - [ - 74, - 51 - ], - [ - 111, - 2 - ], - [ - 89, - -62 - ], - [ - 20, - 36 - ], - [ - 98, - -6 - ], - [ - 18, - 57 - ], - [ - -113, - 83 - ], - [ - 67, - 58 - ], - [ - -13, - 33 - ], - [ - 67, - 31 - ], - [ - -51, - 82 - ], - [ - 32, - 41 - ], - [ - 261, - 42 - ], - [ - 34, - 30 - ], - [ - 174, - 44 - ], - [ - 63, - 50 - ], - [ - 125, - -26 - ], - [ - 22, - -125 - ], - [ - 73, - 30 - ], - [ - 90, - -41 - ], - [ - -6, - -66 - ], - [ - 67, - 7 - ], - [ - 174, - 113 - ], - [ - -25, - -37 - ], - [ - 89, - -93 - ], - [ - 156, - -305 - ], - [ - 37, - 63 - ], - [ - 96, - -69 - ], - [ - 100, - 31 - ], - [ - 38, - -22 - ], - [ - 34, - -69 - ], - [ - 49, - -23 - ], - [ - 29, - -51 - ], - [ - 90, - 16 - ], - [ - 37, - -74 - ] - ], - [ - [ - 15465, - 11267 - ], - [ - -61, - -136 - ], - [ - 1, - -437 - ], - [ - 41, - -99 - ] - ], - [ - [ - 15446, - 10595 - ], - [ - -48, - -48 - ], - [ - -18, - -50 - ], - [ - -26, - -8 - ], - [ - -10, - -85 - ], - [ - -22, - -48 - ], - [ - -14, - -80 - ], - [ - -28, - -40 - ] - ], - [ - [ - 15280, - 10236 - ], - [ - -100, - 120 - ], - [ - -5, - 70 - ], - [ - -252, - 244 - ], - [ - -12, - 13 - ] - ], - [ - [ - 14911, - 10683 - ], - [ - -1, - 127 - ], - [ - 20, - 49 - ], - [ - 34, - 79 - ], - [ - 26, - 88 - ], - [ - -31, - 138 - ], - [ - -8, - 60 - ], - [ - -33, - 83 - ] - ], - [ - [ - 14918, - 11307 - ], - [ - 43, - 72 - ], - [ - 47, - 79 - ] - ], - [ - [ - 17683, - 15528 - ], - [ - -132, - -18 - ], - [ - -86, - 38 - ], - [ - -75, - -9 - ], - [ - 6, - 69 - ], - [ - 76, - -20 - ], - [ - 26, - 37 - ] - ], - [ - [ - 17498, - 15625 - ], - [ - 53, - -12 - ], - [ - 89, - 87 - ], - [ - -83, - 63 - ], - [ - -49, - -30 - ], - [ - -52, - 45 - ], - [ - 59, - 78 - ], - [ - -21, - 12 - ] - ], - [ - [ - 19699, - 12259 - ], - [ - -17, - 145 - ], - [ - 45, - 100 - ], - [ - 90, - 23 - ], - [ - 65, - -17 - ] - ], - [ - [ - 19882, - 12510 - ], - [ - 58, - -48 - ], - [ - 31, - 83 - ], - [ - 62, - -44 - ] - ], - [ - [ - 20033, - 12501 - ], - [ - 16, - -80 - ], - [ - -8, - -144 - ], - [ - -118, - -92 - ], - [ - 31, - -73 - ], - [ - -73, - -8 - ], - [ - -61, - -49 - ] - ], - [ - [ - 19820, - 12055 - ], - [ - -58, - 18 - ], - [ - -28, - 62 - ], - [ - -35, - 124 - ] - ], - [ - [ - 21495, - 15429 - ], - [ - 60, - -141 - ], - [ - 17, - -78 - ], - [ - 1, - -138 - ], - [ - -27, - -66 - ], - [ - -63, - -23 - ], - [ - -56, - -50 - ], - [ - -62, - -10 - ], - [ - -8, - 65 - ], - [ - 13, - 90 - ], - [ - -31, - 125 - ], - [ - 52, - 20 - ], - [ - -48, - 103 - ] - ], - [ - [ - 21343, - 15326 - ], - [ - 4, - 11 - ], - [ - 31, - -4 - ], - [ - 28, - 54 - ], - [ - 49, - 6 - ], - [ - 30, - 7 - ], - [ - 10, - 29 - ] - ], - [ - [ - 13947, - 15907 - ], - [ - 13, - 26 - ] - ], - [ - [ - 13960, - 15933 - ], - [ - 16, - 9 - ], - [ - 10, - 40 - ], - [ - 12, - 6 - ], - [ - 10, - -16 - ], - [ - 13, - -8 - ], - [ - 9, - -19 - ], - [ - 12, - -6 - ], - [ - 14, - -22 - ], - [ - 9, - 1 - ], - [ - -7, - -29 - ], - [ - -9, - -15 - ], - [ - 3, - -9 - ] - ], - [ - [ - 14052, - 15865 - ], - [ - -16, - -4 - ], - [ - -41, - -19 - ], - [ - -3, - -24 - ], - [ - -9, - 1 - ] - ], - [ - [ - 15892, - 14393 - ], - [ - 14, - -53 - ], - [ - -6, - -27 - ], - [ - 23, - -90 - ] - ], - [ - [ - 15923, - 14223 - ], - [ - -50, - -4 - ], - [ - -17, - 58 - ], - [ - -62, - 11 - ] - ], - [ - [ - 19670, - 13492 - ], - [ - 40, - -94 - ], - [ - 32, - -109 - ], - [ - 85, - -1 - ], - [ - 28, - -105 - ], - [ - -45, - -31 - ], - [ - -20, - -44 - ], - [ - 83, - -71 - ], - [ - 58, - -142 - ], - [ - 44, - -106 - ], - [ - 53, - -83 - ], - [ - 18, - -85 - ], - [ - -13, - -120 - ] - ], - [ - [ - 19882, - 12510 - ], - [ - 23, - 54 - ], - [ - 3, - 101 - ], - [ - -57, - 105 - ], - [ - -4, - 118 - ], - [ - -53, - 98 - ], - [ - -53, - 8 - ], - [ - -14, - -42 - ], - [ - -40, - -3 - ], - [ - -21, - 21 - ], - [ - -74, - -72 - ], - [ - -1, - 108 - ], - [ - 17, - 126 - ], - [ - -47, - 6 - ], - [ - -4, - 72 - ], - [ - -31, - 37 - ] - ], - [ - [ - 19526, - 13247 - ], - [ - 15, - 44 - ], - [ - 60, - 78 - ] - ], - [ - [ - 14996, - 14767 - ], - [ - 25, - 98 - ], - [ - 35, - 84 - ], - [ - 1, - 5 - ] - ], - [ - [ - 15057, - 14954 - ], - [ - 31, - -7 - ], - [ - 12, - -47 - ], - [ - -38, - -45 - ], - [ - -17, - -66 - ] - ], - [ - [ - 12010, - 11321 - ], - [ - -18, - -1 - ], - [ - -72, - 57 - ], - [ - -64, - 91 - ], - [ - -59, - 66 - ], - [ - -47, - 77 - ] - ], - [ - [ - 11750, - 11611 - ], - [ - 17, - 39 - ], - [ - 3, - 35 - ], - [ - 32, - 65 - ], - [ - 32, - 56 - ] - ], - [ - [ - 13208, - 14433 - ], - [ - 34, - 28 - ], - [ - 7, - 51 - ], - [ - -8, - 49 - ], - [ - 48, - 47 - ], - [ - 21, - 38 - ], - [ - 34, - 34 - ], - [ - 4, - 93 - ] - ], - [ - [ - 13348, - 14773 - ], - [ - 82, - -42 - ], - [ - 30, - 11 - ], - [ - 58, - -20 - ], - [ - 92, - -54 - ], - [ - 33, - -107 - ], - [ - 62, - -23 - ], - [ - 99, - -50 - ], - [ - 74, - -60 - ], - [ - 34, - 31 - ], - [ - 33, - 56 - ], - [ - -16, - 91 - ], - [ - 22, - 59 - ], - [ - 50, - 56 - ], - [ - 48, - 16 - ], - [ - 95, - -24 - ], - [ - 23, - -54 - ], - [ - 26, - 0 - ], - [ - 22, - -21 - ], - [ - 70, - -14 - ], - [ - 17, - -39 - ] - ], - [ - [ - 14290, - 13437 - ], - [ - 0, - -240 - ], - [ - -80, - 0 - ], - [ - -1, - -51 - ] - ], - [ - [ - 14209, - 13146 - ], - [ - -278, - 230 - ], - [ - -278, - 230 - ], - [ - -70, - -66 - ] - ], - [ - [ - 13583, - 13540 - ], - [ - -50, - -45 - ], - [ - -39, - 66 - ], - [ - -110, - 52 - ] - ], - [ - [ - 18249, - 11700 - ], - [ - -11, - -125 - ], - [ - -29, - -34 - ], - [ - -61, - -28 - ], - [ - -33, - 96 - ], - [ - -12, - 172 - ], - [ - 31, - 195 - ], - [ - 49, - -67 - ], - [ - 32, - -84 - ], - [ - 34, - -125 - ] - ], - [ - [ - 14568, - 7323 - ], - [ - 24, - -36 - ], - [ - -22, - -58 - ], - [ - -12, - -39 - ], - [ - -38, - -19 - ], - [ - -13, - -38 - ], - [ - -25, - -12 - ], - [ - -52, - 92 - ], - [ - 37, - 76 - ], - [ - 38, - 47 - ], - [ - 32, - 24 - ], - [ - 31, - -37 - ] - ], - [ - [ - 14185, - 17265 - ], - [ - -17, - 37 - ], - [ - -36, - 13 - ] - ], - [ - [ - 14132, - 17315 - ], - [ - -6, - 30 - ], - [ - 8, - 33 - ], - [ - -31, - 19 - ], - [ - -73, - 21 - ] - ], - [ - [ - 14030, - 17418 - ], - [ - -15, - 101 - ] - ], - [ - [ - 14015, - 17519 - ], - [ - 80, - 37 - ], - [ - 117, - -8 - ], - [ - 68, - 12 - ], - [ - 10, - -25 - ], - [ - 37, - -8 - ], - [ - 67, - -58 - ] - ], - [ - [ - 14015, - 17519 - ], - [ - 3, - 90 - ], - [ - 34, - 76 - ], - [ - 66, - 41 - ], - [ - 55, - -90 - ], - [ - 56, - 2 - ], - [ - 13, - 93 - ] - ], - [ - [ - 14450, - 17692 - ], - [ - 33, - -27 - ], - [ - 6, - -58 - ], - [ - 23, - -71 - ] - ], - [ - [ - 11943, - 14115 - ], - [ - -10, - 0 - ], - [ - 1, - -64 - ], - [ - -43, - -4 - ], - [ - -22, - -27 - ], - [ - -32, - 0 - ], - [ - -25, - 15 - ], - [ - -59, - -13 - ], - [ - -22, - -93 - ], - [ - -22, - -9 - ], - [ - -33, - -151 - ], - [ - -97, - -130 - ], - [ - -23, - -165 - ], - [ - -28, - -54 - ], - [ - -9, - -43 - ], - [ - -157, - -10 - ], - [ - -1, - 0 - ] - ], - [ - [ - 11361, - 13367 - ], - [ - 3, - 56 - ], - [ - 27, - 32 - ], - [ - 23, - 63 - ], - [ - -5, - 41 - ], - [ - 24, - 84 - ], - [ - 39, - 77 - ], - [ - 24, - 19 - ], - [ - 18, - 70 - ], - [ - 2, - 64 - ], - [ - 25, - 74 - ], - [ - 46, - 44 - ], - [ - 45, - 122 - ], - [ - 1, - 2 - ], - [ - 35, - 46 - ], - [ - 65, - 13 - ], - [ - 55, - 82 - ], - [ - 35, - 32 - ], - [ - 58, - 100 - ], - [ - -18, - 150 - ], - [ - 27, - 103 - ], - [ - 9, - 63 - ], - [ - 45, - 81 - ], - [ - 70, - 55 - ], - [ - 52, - 49 - ], - [ - 46, - 125 - ], - [ - 22, - 73 - ], - [ - 51, - 0 - ], - [ - 42, - -51 - ], - [ - 67, - 8 - ], - [ - 72, - -26 - ], - [ - 30, - -2 - ] - ], - [ - [ - 14403, - 16582 - ], - [ - 17, - 18 - ], - [ - 46, - 12 - ], - [ - 51, - -38 - ], - [ - 29, - -4 - ], - [ - 32, - -32 - ], - [ - -5, - -41 - ], - [ - 25, - -20 - ], - [ - 10, - -50 - ], - [ - 24, - -30 - ], - [ - -5, - -18 - ], - [ - 13, - -12 - ], - [ - -18, - -9 - ], - [ - -41, - 3 - ], - [ - -7, - 17 - ], - [ - -15, - -10 - ], - [ - 5, - -21 - ], - [ - -19, - -38 - ], - [ - -12, - -42 - ], - [ - -17, - -13 - ] - ], - [ - [ - 14516, - 16254 - ], - [ - -13, - 55 - ], - [ - 7, - 51 - ], - [ - -2, - 53 - ], - [ - -40, - 71 - ], - [ - -22, - 51 - ], - [ - -22, - 35 - ], - [ - -21, - 12 - ] - ], - [ - [ - 16001, - 9301 - ], - [ - 19, - -51 - ], - [ - 17, - -79 - ], - [ - 11, - -144 - ], - [ - 18, - -57 - ], - [ - -7, - -57 - ], - [ - -12, - -35 - ], - [ - -24, - 70 - ], - [ - -13, - -36 - ], - [ - 13, - -88 - ], - [ - -6, - -51 - ], - [ - -19, - -28 - ], - [ - -4, - -102 - ], - [ - -28, - -139 - ], - [ - -34, - -166 - ], - [ - -43, - -227 - ], - [ - -27, - -167 - ], - [ - -32, - -139 - ], - [ - -56, - -28 - ], - [ - -61, - -51 - ], - [ - -40, - 30 - ], - [ - -56, - 43 - ], - [ - -19, - 64 - ], - [ - -4, - 106 - ], - [ - -25, - 96 - ], - [ - -6, - 86 - ], - [ - 12, - 86 - ], - [ - 32, - 21 - ], - [ - 0, - 40 - ], - [ - 34, - 91 - ], - [ - 6, - 77 - ], - [ - -16, - 56 - ], - [ - -13, - 76 - ], - [ - -6, - 111 - ], - [ - 24, - 67 - ], - [ - 10, - 76 - ], - [ - 35, - 4 - ], - [ - 38, - 25 - ], - [ - 26, - 21 - ], - [ - 31, - 2 - ], - [ - 40, - 68 - ], - [ - 57, - 74 - ], - [ - 21, - 61 - ], - [ - -10, - 51 - ], - [ - 30, - -14 - ], - [ - 38, - 83 - ], - [ - 2, - 72 - ], - [ - 23, - 54 - ], - [ - 24, - -52 - ] - ], - [ - [ - 6118, - 12541 - ], - [ - -78, - 130 - ], - [ - -36, - 39 - ], - [ - -57, - 31 - ], - [ - -39, - -9 - ], - [ - -56, - -45 - ], - [ - -35, - -12 - ], - [ - -50, - 32 - ], - [ - -52, - 23 - ], - [ - -65, - 55 - ], - [ - -52, - 16 - ], - [ - -79, - 56 - ], - [ - -58, - 58 - ], - [ - -18, - 32 - ], - [ - -39, - 7 - ], - [ - -71, - 38 - ], - [ - -29, - 54 - ], - [ - -75, - 69 - ], - [ - -35, - 75 - ], - [ - -17, - 59 - ], - [ - 23, - 11 - ], - [ - -7, - 35 - ], - [ - 16, - 31 - ], - [ - 1, - 41 - ], - [ - -24, - 54 - ], - [ - -6, - 48 - ], - [ - -24, - 60 - ], - [ - -61, - 120 - ], - [ - -70, - 93 - ], - [ - -34, - 75 - ], - [ - -60, - 49 - ], - [ - -13, - 29 - ], - [ - 11, - 75 - ], - [ - -36, - 28 - ], - [ - -41, - 58 - ], - [ - -17, - 84 - ], - [ - -38, - 9 - ], - [ - -40, - 63 - ], - [ - -33, - 59 - ], - [ - -3, - 37 - ], - [ - -37, - 91 - ], - [ - -25, - 92 - ], - [ - 1, - 46 - ], - [ - -50, - 47 - ], - [ - -24, - -5 - ], - [ - -39, - 33 - ], - [ - -12, - -49 - ], - [ - 12, - -57 - ], - [ - 7, - -90 - ], - [ - 24, - -50 - ], - [ - 51, - -82 - ], - [ - 12, - -29 - ], - [ - 10, - -8 - ], - [ - 10, - -41 - ], - [ - 12, - 1 - ], - [ - 14, - -77 - ], - [ - 21, - -31 - ], - [ - 15, - -42 - ], - [ - 44, - -61 - ], - [ - 23, - -112 - ], - [ - 21, - -52 - ], - [ - 19, - -56 - ], - [ - 4, - -64 - ], - [ - 34, - -4 - ], - [ - 27, - -54 - ], - [ - 26, - -54 - ], - [ - -2, - -21 - ], - [ - -29, - -44 - ], - [ - -13, - 0 - ], - [ - -18, - 73 - ], - [ - -46, - 69 - ], - [ - -50, - 58 - ], - [ - -36, - 30 - ], - [ - 3, - 88 - ], - [ - -11, - 65 - ], - [ - -33, - 37 - ], - [ - -48, - 54 - ], - [ - -9, - -16 - ], - [ - -18, - 31 - ], - [ - -43, - 29 - ], - [ - -41, - 70 - ], - [ - 5, - 9 - ], - [ - 29, - -7 - ], - [ - 26, - 45 - ], - [ - 2, - 54 - ], - [ - -53, - 86 - ], - [ - -41, - 33 - ], - [ - -26, - 75 - ], - [ - -26, - 79 - ], - [ - -32, - 95 - ], - [ - -28, - 108 - ] - ], - [ - [ - 4383, - 14700 - ], - [ - 79, - 10 - ], - [ - 88, - 13 - ], - [ - -6, - -24 - ], - [ - 105, - -58 - ], - [ - 159, - -85 - ], - [ - 139, - 1 - ], - [ - 55, - 0 - ], - [ - 0, - 50 - ], - [ - 121, - 0 - ], - [ - 25, - -43 - ], - [ - 36, - -38 - ], - [ - 42, - -52 - ], - [ - 23, - -63 - ], - [ - 17, - -66 - ], - [ - 36, - -36 - ], - [ - 58, - -36 - ], - [ - 44, - 94 - ], - [ - 57, - 3 - ], - [ - 49, - -48 - ], - [ - 35, - -82 - ], - [ - 24, - -70 - ], - [ - 41, - -69 - ], - [ - 15, - -84 - ], - [ - 20, - -56 - ], - [ - 54, - -37 - ], - [ - 50, - -27 - ], - [ - 27, - 4 - ] - ], - [ - [ - 5776, - 13901 - ], - [ - -27, - -106 - ], - [ - -12, - -86 - ], - [ - -5, - -161 - ], - [ - -7, - -58 - ], - [ - 12, - -66 - ], - [ - 22, - -58 - ], - [ - 14, - -93 - ], - [ - 46, - -90 - ], - [ - 16, - -68 - ], - [ - 27, - -59 - ], - [ - 74, - -32 - ], - [ - 29, - -50 - ], - [ - 61, - 33 - ], - [ - 54, - 13 - ], - [ - 52, - 21 - ], - [ - 44, - 21 - ], - [ - 44, - 49 - ], - [ - 17, - 70 - ], - [ - 5, - 100 - ], - [ - 12, - 36 - ], - [ - 48, - 31 - ], - [ - 73, - 28 - ], - [ - 62, - -4 - ], - [ - 42, - 10 - ], - [ - 17, - -26 - ], - [ - -2, - -57 - ], - [ - -38, - -72 - ], - [ - -16, - -73 - ], - [ - 12, - -21 - ], - [ - -10, - -52 - ], - [ - -17, - -93 - ], - [ - -18, - 31 - ], - [ - -15, - -2 - ] - ], - [ - [ - 14052, - 15865 - ], - [ - 23, - 7 - ], - [ - 33, - 2 - ] - ], - [ - [ - 11745, - 12290 - ], - [ - 3, - 37 - ], - [ - -6, - 47 - ], - [ - -26, - 33 - ], - [ - -14, - 69 - ], - [ - -3, - 75 - ] - ], - [ - [ - 11699, - 12551 - ], - [ - 24, - 22 - ], - [ - 11, - 70 - ], - [ - 22, - 3 - ], - [ - 49, - -33 - ], - [ - 39, - 23 - ], - [ - 27, - -8 - ], - [ - 11, - 27 - ], - [ - 279, - 2 - ], - [ - 16, - 84 - ], - [ - -12, - 15 - ], - [ - -34, - 517 - ], - [ - -33, - 518 - ], - [ - 106, - 2 - ] - ], - [ - [ - 12845, - 13095 - ], - [ - 0, - -276 - ], - [ - -38, - -80 - ], - [ - -6, - -74 - ], - [ - -62, - -19 - ], - [ - -95, - -10 - ], - [ - -26, - -43 - ], - [ - -44, - -5 - ] - ], - [ - [ - 19526, - 13247 - ], - [ - -40, - -28 - ], - [ - -40, - -52 - ], - [ - -49, - -5 - ], - [ - -32, - -130 - ], - [ - -30, - -22 - ], - [ - 34, - -105 - ], - [ - 44, - -88 - ], - [ - 29, - -79 - ], - [ - -26, - -104 - ], - [ - -24, - -22 - ], - [ - 17, - -61 - ], - [ - 46, - -95 - ], - [ - 8, - -67 - ], - [ - -1, - -56 - ], - [ - 28, - -109 - ], - [ - -39, - -112 - ], - [ - -33, - -123 - ] - ], - [ - [ - 19418, - 11989 - ], - [ - -7, - 89 - ], - [ - 21, - 92 - ], - [ - -23, - 71 - ], - [ - 5, - 130 - ], - [ - -28, - 63 - ], - [ - -23, - 143 - ], - [ - -12, - 152 - ], - [ - -30, - 99 - ], - [ - -46, - -60 - ], - [ - -79, - -86 - ], - [ - -40, - 11 - ], - [ - -43, - 28 - ], - [ - 24, - 149 - ], - [ - -14, - 112 - ], - [ - -55, - 139 - ], - [ - 9, - 43 - ], - [ - -41, - 15 - ], - [ - -50, - 98 - ] - ], - [ - [ - 13898, - 15821 - ], - [ - -15, - 9 - ], - [ - -19, - 40 - ], - [ - -30, - 23 - ] - ], - [ - [ - 13887, - 16019 - ], - [ - 19, - -21 - ], - [ - 10, - -17 - ], - [ - 23, - -12 - ], - [ - 26, - -25 - ], - [ - -5, - -11 - ] - ], - [ - [ - 18664, - 16711 - ], - [ - 74, - 21 - ], - [ - 133, - 103 - ], - [ - 106, - 57 - ], - [ - 61, - -37 - ], - [ - 72, - -2 - ], - [ - 47, - -56 - ], - [ - 70, - -4 - ], - [ - 100, - -30 - ], - [ - 68, - 83 - ], - [ - -28, - 71 - ], - [ - 72, - 124 - ], - [ - 78, - -49 - ], - [ - 63, - -14 - ], - [ - 82, - -31 - ], - [ - 14, - -90 - ], - [ - 99, - -51 - ], - [ - 65, - 23 - ], - [ - 89, - 15 - ], - [ - 70, - -15 - ], - [ - 68, - -58 - ], - [ - 42, - -61 - ], - [ - 65, - 1 - ], - [ - 88, - -20 - ], - [ - 64, - 30 - ], - [ - 91, - 20 - ], - [ - 103, - 84 - ], - [ - 41, - -13 - ], - [ - 37, - -40 - ], - [ - 83, - 10 - ] - ], - [ - [ - 14957, - 9415 - ], - [ - 52, - 10 - ], - [ - 84, - -34 - ], - [ - 18, - 15 - ], - [ - 49, - 3 - ], - [ - 24, - 36 - ], - [ - 42, - -2 - ], - [ - 76, - 47 - ], - [ - 56, - 69 - ] - ], - [ - [ - 15358, - 9559 - ], - [ - 11, - -53 - ], - [ - -3, - -120 - ], - [ - 9, - -105 - ], - [ - 3, - -188 - ], - [ - 12, - -58 - ], - [ - -21, - -86 - ], - [ - -27, - -83 - ], - [ - -44, - -75 - ], - [ - -64, - -45 - ], - [ - -79, - -59 - ], - [ - -78, - -128 - ], - [ - -27, - -22 - ], - [ - -49, - -86 - ], - [ - -29, - -27 - ], - [ - -5, - -86 - ], - [ - 33, - -91 - ], - [ - 13, - -70 - ], - [ - 1, - -36 - ], - [ - 13, - 6 - ], - [ - -2, - -118 - ], - [ - -12, - -55 - ], - [ - 17, - -21 - ], - [ - -11, - -50 - ], - [ - -29, - -42 - ], - [ - -57, - -41 - ], - [ - -84, - -65 - ], - [ - -31, - -44 - ], - [ - 6, - -51 - ], - [ - 18, - -8 - ], - [ - -6, - -63 - ] - ], - [ - [ - 14836, - 7589 - ], - [ - -53, - 1 - ] - ], - [ - [ - 14783, - 7590 - ], - [ - -6, - 53 - ], - [ - -10, - 54 - ] - ], - [ - [ - 14767, - 7697 - ], - [ - -6, - 43 - ], - [ - 12, - 134 - ], - [ - -18, - 85 - ], - [ - -33, - 169 - ] - ], - [ - [ - 14722, - 8128 - ], - [ - 73, - 136 - ], - [ - 19, - 86 - ], - [ - 10, - 11 - ], - [ - 8, - 71 - ], - [ - -11, - 35 - ], - [ - 3, - 90 - ], - [ - 13, - 83 - ], - [ - 0, - 152 - ], - [ - -36, - 39 - ], - [ - -33, - 8 - ], - [ - -15, - 30 - ], - [ - -32, - 25 - ], - [ - -59, - -2 - ], - [ - -4, - 45 - ] - ], - [ - [ - 14658, - 8937 - ], - [ - -7, - 85 - ], - [ - 212, - 99 - ] - ], - [ - [ - 14863, - 9121 - ], - [ - 40, - -58 - ], - [ - 19, - 11 - ], - [ - 28, - -30 - ], - [ - 4, - -48 - ], - [ - -15, - -56 - ], - [ - 5, - -84 - ], - [ - 46, - -74 - ], - [ - 21, - 83 - ], - [ - 30, - 25 - ], - [ - -6, - 154 - ], - [ - -29, - 87 - ], - [ - -25, - 39 - ], - [ - -24, - -2 - ], - [ - -20, - 156 - ], - [ - 20, - 91 - ] - ], - [ - [ - 11699, - 12551 - ], - [ - -46, - 82 - ], - [ - -42, - 88 - ], - [ - -46, - 32 - ], - [ - -34, - 35 - ], - [ - -39, - -1 - ], - [ - -34, - -26 - ], - [ - -34, - 10 - ], - [ - -24, - -38 - ] - ], - [ - [ - 11400, - 12733 - ], - [ - -6, - 65 - ], - [ - 19, - 59 - ], - [ - 9, - 113 - ], - [ - -8, - 118 - ], - [ - -8, - 60 - ], - [ - 7, - 60 - ], - [ - -18, - 57 - ], - [ - -37, - 52 - ] - ], - [ - [ - 11358, - 13317 - ], - [ - 15, - 40 - ], - [ - 273, - -1 - ], - [ - -13, - 173 - ], - [ - 17, - 62 - ], - [ - 65, - 10 - ], - [ - -2, - 307 - ], - [ - 229, - -6 - ], - [ - 0, - 182 - ] - ], - [ - [ - 14863, - 9121 - ], - [ - -37, - 31 - ], - [ - 21, - 112 - ], - [ - 22, - 41 - ], - [ - -13, - 100 - ], - [ - 14, - 97 - ], - [ - 12, - 32 - ], - [ - -18, - 102 - ], - [ - -33, - 54 - ] - ], - [ - [ - 14831, - 9690 - ], - [ - 68, - -23 - ], - [ - 14, - -33 - ], - [ - 24, - -56 - ], - [ - 20, - -163 - ] - ], - [ - [ - 20595, - 11451 - ], - [ - 54, - 83 - ], - [ - 35, - 94 - ], - [ - 28, - 0 - ], - [ - 36, - -60 - ], - [ - 3, - -52 - ], - [ - 46, - -34 - ], - [ - 58, - -36 - ], - [ - -4, - -47 - ], - [ - -47, - -6 - ], - [ - 12, - -59 - ], - [ - -51, - -40 - ] - ], - [ - [ - 20192, - 11038 - ], - [ - 51, - -41 - ], - [ - 54, - 22 - ], - [ - 14, - 102 - ], - [ - 30, - 22 - ], - [ - 83, - 26 - ], - [ - 50, - 95 - ], - [ - 34, - 76 - ] - ], - [ - [ - 19668, - 11544 - ], - [ - 16, - -12 - ], - [ - 41, - -72 - ], - [ - 29, - -80 - ], - [ - 4, - -81 - ], - [ - -7, - -55 - ], - [ - 6, - -41 - ], - [ - 5, - -71 - ], - [ - 25, - -33 - ], - [ - 27, - -106 - ], - [ - -1, - -41 - ], - [ - -49, - -8 - ], - [ - -66, - 89 - ], - [ - -83, - 95 - ], - [ - -8, - 62 - ], - [ - -40, - 80 - ], - [ - -10, - 99 - ], - [ - -25, - 66 - ], - [ - 8, - 87 - ], - [ - -16, - 51 - ] - ], - [ - [ - 19524, - 11573 - ], - [ - 12, - 21 - ], - [ - 57, - -52 - ], - [ - 6, - -62 - ], - [ - 46, - 14 - ], - [ - 23, - 50 - ] - ], - [ - [ - 14166, - 8695 - ], - [ - 57, - 27 - ], - [ - 45, - -7 - ], - [ - 28, - -27 - ], - [ - 0, - -10 - ] - ], - [ - [ - 13934, - 7826 - ], - [ - 0, - -443 - ], - [ - -62, - -62 - ], - [ - -37, - -8 - ], - [ - -44, - 22 - ], - [ - -31, - 9 - ], - [ - -12, - 51 - ], - [ - -28, - 33 - ], - [ - -33, - -59 - ] - ], - [ - [ - 13687, - 7369 - ], - [ - -52, - 91 - ], - [ - -27, - 87 - ], - [ - -16, - 117 - ], - [ - -17, - 87 - ], - [ - -23, - 185 - ], - [ - -2, - 143 - ], - [ - -9, - 66 - ], - [ - -27, - 49 - ], - [ - -36, - 99 - ], - [ - -36, - 144 - ], - [ - -16, - 75 - ], - [ - -56, - 117 - ], - [ - -5, - 93 - ] - ], - [ - [ - 24104, - 8268 - ], - [ - 57, - -74 - ], - [ - 36, - -55 - ], - [ - -26, - -29 - ], - [ - -39, - 32 - ], - [ - -50, - 54 - ], - [ - -44, - 64 - ], - [ - -47, - 84 - ], - [ - -9, - 41 - ], - [ - 30, - -2 - ], - [ - 39, - -40 - ], - [ - 30, - -41 - ], - [ - 23, - -34 - ] - ], - [ - [ - 13583, - 13540 - ], - [ - 17, - -186 - ], - [ - 26, - -32 - ], - [ - 1, - -38 - ], - [ - 29, - -41 - ], - [ - -15, - -52 - ], - [ - -27, - -243 - ], - [ - -4, - -156 - ], - [ - -89, - -113 - ], - [ - -30, - -158 - ], - [ - 29, - -45 - ], - [ - 0, - -77 - ], - [ - 45, - -3 - ], - [ - -7, - -56 - ] - ], - [ - [ - 13536, - 12295 - ], - [ - -13, - -3 - ], - [ - -47, - 132 - ], - [ - -16, - 4 - ], - [ - -55, - -67 - ], - [ - -54, - 35 - ], - [ - -37, - 7 - ], - [ - -21, - -17 - ], - [ - -40, - 4 - ], - [ - -42, - -51 - ], - [ - -35, - -3 - ], - [ - -84, - 62 - ], - [ - -33, - -29 - ], - [ - -36, - 2 - ], - [ - -26, - 45 - ], - [ - -70, - 45 - ], - [ - -75, - -15 - ], - [ - -18, - -25 - ], - [ - -10, - -69 - ], - [ - -20, - -49 - ], - [ - -5, - -107 - ] - ], - [ - [ - 13140, - 11370 - ], - [ - -72, - -43 - ], - [ - -27, - 6 - ], - [ - -27, - -27 - ], - [ - -55, - 3 - ], - [ - -38, - 75 - ], - [ - -23, - 86 - ], - [ - -49, - 79 - ], - [ - -52, - -1 - ], - [ - -62, - 0 - ] - ], - [ - [ - 6573, - 12127 - ], - [ - -24, - 38 - ], - [ - -33, - 49 - ], - [ - -15, - 40 - ], - [ - -30, - 38 - ], - [ - -35, - 54 - ], - [ - 8, - 19 - ], - [ - 12, - -19 - ], - [ - 5, - 9 - ] - ], - [ - [ - 6751, - 12596 - ], - [ - -6, - -11 - ], - [ - -3, - -27 - ], - [ - 7, - -44 - ], - [ - -16, - -41 - ], - [ - -8, - -48 - ], - [ - -2, - -53 - ], - [ - 4, - -31 - ], - [ - 2, - -54 - ], - [ - -11, - -12 - ], - [ - -6, - -51 - ], - [ - 4, - -32 - ], - [ - -14, - -30 - ], - [ - 3, - -33 - ], - [ - 11, - -19 - ] - ], - [ - [ - 12779, - 16957 - ], - [ - 36, - 33 - ], - [ - 61, - 177 - ], - [ - 95, - 50 - ], - [ - 58, - -4 - ] - ], - [ - [ - 13987, - 19088 - ], - [ - -44, - -5 - ], - [ - -10, - -79 - ], - [ - -131, - 19 - ], - [ - -19, - -67 - ], - [ - -67, - 1 - ], - [ - -46, - -86 - ], - [ - -69, - -133 - ], - [ - -109, - -168 - ], - [ - 26, - -41 - ], - [ - -24, - -48 - ], - [ - -70, - 2 - ], - [ - -45, - -112 - ], - [ - 4, - -160 - ], - [ - 45, - -60 - ], - [ - -23, - -142 - ], - [ - -58, - -82 - ], - [ - -31, - -69 - ] - ], - [ - [ - 13316, - 17858 - ], - [ - -47, - 74 - ], - [ - -137, - -139 - ], - [ - -93, - -28 - ], - [ - -97, - 61 - ], - [ - -24, - 129 - ], - [ - -23, - 277 - ], - [ - 65, - 77 - ], - [ - 184, - 101 - ], - [ - 137, - 124 - ], - [ - 128, - 167 - ], - [ - 167, - 231 - ], - [ - 117, - 91 - ], - [ - 192, - 150 - ], - [ - 153, - 53 - ], - [ - 114, - -7 - ], - [ - 107, - 100 - ], - [ - 127, - -6 - ], - [ - 125, - 24 - ], - [ - 218, - -88 - ], - [ - -90, - -32 - ], - [ - 77, - -75 - ] - ], - [ - [ - 14716, - 19142 - ], - [ - -119, - -48 - ], - [ - -56, - -11 - ] - ], - [ - [ - 14271, - 20137 - ], - [ - -156, - -49 - ], - [ - -123, - 28 - ], - [ - 48, - 31 - ], - [ - -42, - 38 - ], - [ - 145, - 24 - ], - [ - 27, - -45 - ], - [ - 101, - -27 - ] - ], - [ - [ - 13820, - 20359 - ], - [ - 229, - -90 - ], - [ - -175, - -47 - ], - [ - -39, - -88 - ], - [ - -61, - -23 - ], - [ - -33, - -99 - ], - [ - -84, - -5 - ], - [ - -150, - 73 - ], - [ - 63, - 43 - ], - [ - -104, - 35 - ], - [ - -136, - 101 - ], - [ - -54, - 94 - ], - [ - 190, - 43 - ], - [ - 38, - -42 - ], - [ - 99, - 2 - ], - [ - 27, - 41 - ], - [ - 102, - 4 - ], - [ - 88, - -42 - ] - ], - [ - [ - 14321, - 20444 - ], - [ - 137, - -43 - ], - [ - -103, - -64 - ], - [ - -203, - -14 - ], - [ - -205, - 20 - ], - [ - -12, - 33 - ], - [ - -101, - 2 - ], - [ - -76, - 55 - ], - [ - 215, - 33 - ], - [ - 102, - -28 - ], - [ - 70, - 36 - ], - [ - 176, - -30 - ] - ], - [ - [ - 24608, - 5888 - ], - [ - 16, - -49 - ], - [ - 50, - 48 - ], - [ - 20, - -50 - ], - [ - 0, - -51 - ], - [ - -26, - -55 - ], - [ - -45, - -89 - ], - [ - -36, - -48 - ], - [ - 26, - -58 - ], - [ - -54, - -1 - ], - [ - -60, - -46 - ], - [ - -18, - -78 - ], - [ - -40, - -121 - ], - [ - -55, - -54 - ], - [ - -35, - -34 - ], - [ - -64, - 2 - ], - [ - -45, - 40 - ], - [ - -76, - 8 - ], - [ - -11, - 44 - ], - [ - 37, - 89 - ], - [ - 88, - 119 - ], - [ - 45, - 22 - ], - [ - 50, - 46 - ], - [ - 60, - 63 - ], - [ - 41, - 62 - ], - [ - 31, - 89 - ], - [ - 27, - 31 - ], - [ - 10, - 67 - ], - [ - 49, - 55 - ], - [ - 15, - -51 - ] - ], - [ - [ - 24719, - 6460 - ], - [ - 51, - -127 - ], - [ - 1, - 82 - ], - [ - 32, - -33 - ], - [ - 10, - -90 - ], - [ - 56, - -39 - ], - [ - 47, - -10 - ], - [ - 40, - 46 - ], - [ - 36, - -14 - ], - [ - -17, - -107 - ], - [ - -21, - -70 - ], - [ - -54, - 3 - ], - [ - -18, - -37 - ], - [ - 6, - -51 - ], - [ - -10, - -22 - ], - [ - -26, - -65 - ], - [ - -35, - -82 - ], - [ - -54, - -48 - ], - [ - -12, - 31 - ], - [ - -29, - 18 - ], - [ - 40, - 98 - ], - [ - -23, - 66 - ], - [ - -75, - 48 - ], - [ - 2, - 44 - ], - [ - 51, - 42 - ], - [ - 12, - 92 - ], - [ - -4, - 78 - ], - [ - -28, - 80 - ], - [ - 2, - 21 - ], - [ - -33, - 50 - ], - [ - -55, - 106 - ], - [ - -29, - 85 - ], - [ - 26, - 9 - ], - [ - 37, - -66 - ], - [ - 55, - -32 - ], - [ - 19, - -106 - ] - ], - [ - [ - 16456, - 13923 - ], - [ - 20, - 41 - ], - [ - 9, - -11 - ], - [ - -7, - -49 - ], - [ - -9, - -22 - ] - ], - [ - [ - 16479, - 13787 - ], - [ - 31, - -82 - ], - [ - 39, - -43 - ], - [ - 51, - -16 - ], - [ - 41, - -22 - ], - [ - 32, - -68 - ], - [ - 19, - -40 - ], - [ - 25, - -15 - ], - [ - -1, - -27 - ], - [ - -25, - -72 - ], - [ - -11, - -33 - ], - [ - -29, - -39 - ], - [ - -26, - -82 - ], - [ - -32, - 6 - ], - [ - -15, - -28 - ], - [ - -11, - -61 - ], - [ - 9, - -80 - ], - [ - -7, - -15 - ], - [ - -32, - 0 - ], - [ - -43, - -44 - ], - [ - -7, - -59 - ], - [ - -16, - -25 - ], - [ - -43, - 1 - ], - [ - -28, - -30 - ], - [ - 1, - -49 - ], - [ - -34, - -33 - ], - [ - -39, - 11 - ], - [ - -46, - -40 - ], - [ - -32, - -7 - ] - ], - [ - [ - 16250, - 12795 - ], - [ - -23, - 84 - ], - [ - -55, - 198 - ] - ], - [ - [ - 16172, - 13077 - ], - [ - 209, - 120 - ], - [ - 47, - 240 - ], - [ - -32, - 84 - ] - ], - [ - [ - 17300, - 13639 - ], - [ - -51, - 31 - ], - [ - -21, - 86 - ], - [ - -54, - 91 - ], - [ - -128, - -22 - ], - [ - -113, - -2 - ], - [ - -99, - -17 - ] - ], - [ - [ - 7119, - 11664 - ], - [ - -24, - 34 - ], - [ - -15, - 65 - ], - [ - 18, - 32 - ], - [ - -18, - 8 - ], - [ - -13, - 40 - ], - [ - -35, - 33 - ], - [ - -30, - -7 - ], - [ - -14, - -42 - ], - [ - -29, - -30 - ], - [ - -15, - -4 - ], - [ - -7, - -25 - ], - [ - 34, - -65 - ], - [ - -19, - -16 - ], - [ - -11, - -17 - ], - [ - -32, - -7 - ], - [ - -12, - 72 - ], - [ - -9, - -20 - ], - [ - -23, - 7 - ], - [ - -14, - 48 - ], - [ - -29, - 8 - ], - [ - -18, - 14 - ], - [ - -30, - 0 - ], - [ - -2, - -26 - ], - [ - -8, - 18 - ] - ], - [ - [ - 6793, - 11945 - ], - [ - 25, - -43 - ], - [ - -1, - -26 - ], - [ - 28, - -5 - ], - [ - 6, - 10 - ], - [ - 20, - -30 - ], - [ - 34, - 9 - ], - [ - 29, - 30 - ], - [ - 43, - 24 - ], - [ - 24, - 36 - ], - [ - 38, - -7 - ], - [ - -3, - -12 - ], - [ - 39, - -4 - ], - [ - 31, - -20 - ], - [ - 23, - -36 - ], - [ - 26, - -34 - ] - ], - [ - [ - 7642, - 8596 - ], - [ - -70, - 69 - ], - [ - -6, - 49 - ], - [ - -138, - 121 - ], - [ - -125, - 131 - ], - [ - -54, - 74 - ], - [ - -29, - 99 - ], - [ - 12, - 34 - ], - [ - -59, - 158 - ], - [ - -69, - 221 - ], - [ - -66, - 239 - ], - [ - -29, - 55 - ], - [ - -21, - 88 - ], - [ - -55, - 78 - ], - [ - -49, - 49 - ], - [ - 22, - 54 - ], - [ - -34, - 114 - ], - [ - 22, - 84 - ], - [ - 56, - 76 - ] - ], - [ - [ - 21357, - 11807 - ], - [ - 7, - -80 - ], - [ - 4, - -67 - ], - [ - -24, - -110 - ], - [ - -25, - 122 - ], - [ - -33, - -61 - ], - [ - 23, - -88 - ], - [ - -20, - -56 - ], - [ - -82, - 69 - ], - [ - -20, - 87 - ], - [ - 21, - 57 - ], - [ - -44, - 57 - ], - [ - -22, - -50 - ], - [ - -33, - 5 - ], - [ - -51, - -67 - ], - [ - -12, - 35 - ], - [ - 28, - 101 - ], - [ - 44, - 34 - ], - [ - 38, - 45 - ], - [ - 24, - -54 - ], - [ - 53, - 33 - ], - [ - 12, - 53 - ], - [ - 49, - 3 - ], - [ - -4, - 93 - ], - [ - 56, - -57 - ], - [ - 6, - -60 - ], - [ - 5, - -44 - ] - ], - [ - [ - 21190, - 12030 - ], - [ - -25, - -39 - ], - [ - -22, - -76 - ], - [ - -22, - -35 - ], - [ - -43, - 82 - ], - [ - 15, - 33 - ], - [ - 17, - 33 - ], - [ - 8, - 75 - ], - [ - 38, - 7 - ], - [ - -11, - -81 - ], - [ - 52, - 116 - ], - [ - -7, - -115 - ] - ], - [ - [ - 20808, - 11915 - ], - [ - -92, - -114 - ], - [ - 34, - 84 - ], - [ - 50, - 74 - ], - [ - 42, - 83 - ], - [ - 36, - 119 - ], - [ - 13, - -98 - ], - [ - -46, - -66 - ], - [ - -37, - -82 - ] - ], - [ - [ - 21044, - 12224 - ], - [ - 42, - -37 - ], - [ - 44, - 0 - ], - [ - -1, - -50 - ], - [ - -33, - -51 - ], - [ - -44, - -36 - ], - [ - -2, - 56 - ], - [ - 5, - 61 - ], - [ - -11, - 57 - ] - ], - [ - [ - 21296, - 12256 - ], - [ - 20, - -134 - ], - [ - -54, - 32 - ], - [ - 1, - -40 - ], - [ - 17, - -74 - ], - [ - -33, - -27 - ], - [ - -3, - 84 - ], - [ - -21, - 7 - ], - [ - -11, - 72 - ], - [ - 41, - -9 - ], - [ - 0, - 45 - ], - [ - -43, - 92 - ], - [ - 67, - -3 - ], - [ - 19, - -45 - ] - ], - [ - [ - 21019, - 12365 - ], - [ - -19, - -104 - ], - [ - -29, - 60 - ], - [ - -36, - 92 - ], - [ - 60, - -5 - ], - [ - 24, - -43 - ] - ], - [ - [ - 21005, - 13017 - ], - [ - 43, - -34 - ], - [ - 21, - 31 - ], - [ - 6, - -30 - ], - [ - -11, - -50 - ], - [ - 24, - -86 - ], - [ - -18, - -100 - ], - [ - -42, - -40 - ], - [ - -11, - -96 - ], - [ - 16, - -96 - ], - [ - 37, - -13 - ], - [ - 31, - 14 - ], - [ - 87, - -66 - ], - [ - -7, - -66 - ], - [ - 23, - -29 - ], - [ - -7, - -55 - ], - [ - -55, - 59 - ], - [ - -25, - 63 - ], - [ - -18, - -44 - ], - [ - -45, - 72 - ], - [ - -63, - -18 - ], - [ - -35, - 27 - ], - [ - 4, - 49 - ], - [ - 22, - 31 - ], - [ - -21, - 28 - ], - [ - -9, - -44 - ], - [ - -35, - 69 - ], - [ - -10, - 52 - ], - [ - -3, - 115 - ], - [ - 28, - -39 - ], - [ - 8, - 188 - ], - [ - 22, - 108 - ], - [ - 43, - 0 - ] - ], - [ - [ - 22376, - 10485 - ], - [ - 121, - -82 - ], - [ - 129, - -69 - ], - [ - 48, - -62 - ], - [ - 39, - -60 - ], - [ - 11, - -71 - ], - [ - 116, - -74 - ], - [ - 17, - -63 - ], - [ - -64, - -13 - ], - [ - 15, - -80 - ], - [ - 62, - -79 - ], - [ - 46, - -127 - ], - [ - 39, - 4 - ], - [ - -2, - -53 - ], - [ - 53, - -21 - ], - [ - -20, - -22 - ], - [ - 74, - -51 - ], - [ - -8, - -34 - ], - [ - -46, - -9 - ], - [ - -17, - 31 - ], - [ - -60, - 14 - ], - [ - -71, - 18 - ], - [ - -54, - 76 - ], - [ - -39, - 66 - ], - [ - -37, - 105 - ], - [ - -91, - 53 - ], - [ - -59, - -34 - ], - [ - -42, - -40 - ], - [ - 9, - -88 - ], - [ - -55, - -42 - ], - [ - -39, - 20 - ], - [ - -72, - 5 - ] - ], - [ - [ - 23414, - 9979 - ], - [ - -20, - -12 - ], - [ - -30, - 46 - ], - [ - -31, - 76 - ], - [ - -15, - 92 - ], - [ - 10, - 11 - ], - [ - 8, - -35 - ], - [ - 21, - -28 - ], - [ - 33, - -76 - ], - [ - 33, - -40 - ], - [ - -9, - -34 - ] - ], - [ - [ - 23142, - 10140 - ], - [ - -37, - -10 - ], - [ - -11, - -34 - ], - [ - -38, - -29 - ], - [ - -35, - -28 - ], - [ - -37, - 0 - ], - [ - -58, - 35 - ], - [ - -39, - 34 - ], - [ - 5, - 37 - ], - [ - 63, - -18 - ], - [ - 38, - 10 - ], - [ - 10, - 57 - ], - [ - 10, - 3 - ], - [ - 7, - -64 - ], - [ - 40, - 10 - ], - [ - 20, - 41 - ], - [ - 39, - 42 - ], - [ - -8, - 71 - ], - [ - 42, - 2 - ], - [ - 14, - -19 - ], - [ - -2, - -67 - ], - [ - -23, - -73 - ] - ], - [ - [ - 23223, - 10257 - ], - [ - -22, - -32 - ], - [ - -13, - 71 - ], - [ - -17, - 47 - ], - [ - -31, - 39 - ], - [ - -40, - 51 - ], - [ - -50, - 35 - ], - [ - 19, - 29 - ], - [ - 38, - -33 - ], - [ - 24, - -27 - ], - [ - 29, - -29 - ], - [ - 28, - -50 - ], - [ - 26, - -38 - ], - [ - 9, - -63 - ] - ], - [ - [ - 14188, - 16985 - ], - [ - 35, - -105 - ], - [ - -8, - -33 - ], - [ - -34, - -14 - ], - [ - -64, - -100 - ], - [ - 18, - -54 - ], - [ - -15, - 7 - ] - ], - [ - [ - 14120, - 16686 - ], - [ - -66, - 46 - ], - [ - -50, - -17 - ], - [ - -33, - 12 - ], - [ - -42, - -25 - ], - [ - -35, - 42 - ], - [ - -28, - -16 - ], - [ - -4, - 7 - ] - ], - [ - [ - 13532, - 17246 - ], - [ - 47, - 36 - ], - [ - 109, - 55 - ], - [ - 88, - 41 - ], - [ - 70, - -21 - ], - [ - 5, - -29 - ], - [ - 67, - -1 - ] - ], - [ - [ - 13918, - 17327 - ], - [ - 86, - -14 - ], - [ - 128, - 2 - ] - ], - [ - [ - 7927, - 13018 - ], - [ - 36, - -10 - ], - [ - 12, - -24 - ], - [ - -18, - -30 - ], - [ - -52, - 0 - ], - [ - -41, - -4 - ], - [ - -4, - 52 - ], - [ - 10, - 17 - ], - [ - 57, - -1 - ] - ], - [ - [ - 21654, - 15883 - ], - [ - 10, - -21 - ] - ], - [ - [ - 21664, - 15862 - ], - [ - -27, - 7 - ], - [ - -30, - -40 - ], - [ - -21, - -41 - ], - [ - 3, - -86 - ], - [ - -36, - -27 - ], - [ - -12, - -21 - ], - [ - -27, - -35 - ], - [ - -46, - -20 - ], - [ - -30, - -32 - ], - [ - -3, - -52 - ], - [ - -8, - -13 - ], - [ - 28, - -20 - ], - [ - 40, - -53 - ] - ], - [ - [ - 21343, - 15326 - ], - [ - -34, - 23 - ], - [ - -8, - -23 - ], - [ - -21, - -10 - ], - [ - -2, - 23 - ], - [ - -18, - 11 - ], - [ - -19, - 19 - ], - [ - 19, - 53 - ], - [ - 17, - 14 - ], - [ - -7, - 22 - ], - [ - 18, - 65 - ], - [ - -5, - 19 - ], - [ - -40, - 13 - ], - [ - -33, - 32 - ] - ], - [ - [ - 12028, - 15248 - ], - [ - -28, - -31 - ], - [ - -37, - 17 - ], - [ - -36, - -14 - ], - [ - 11, - 94 - ], - [ - -7, - 74 - ], - [ - -31, - 11 - ], - [ - -17, - 45 - ], - [ - 6, - 79 - ], - [ - 28, - 44 - ], - [ - 5, - 48 - ], - [ - 14, - 72 - ], - [ - -1, - 51 - ], - [ - -14, - 43 - ], - [ - -3, - 41 - ] - ], - [ - [ - 16089, - 13767 - ], - [ - -4, - 87 - ], - [ - 19, - 63 - ], - [ - 19, - 13 - ], - [ - 21, - -37 - ], - [ - 1, - -71 - ], - [ - -15, - -70 - ] - ], - [ - [ - 16130, - 13752 - ], - [ - -20, - -9 - ], - [ - -21, - 24 - ] - ], - [ - [ - 14127, - 16104 - ], - [ - -13, - 21 - ], - [ - 16, - 20 - ], - [ - -17, - 15 - ], - [ - -22, - -27 - ], - [ - -40, - 35 - ], - [ - -6, - 50 - ], - [ - -42, - 28 - ], - [ - -8, - 38 - ], - [ - -38, - 47 - ] - ], - [ - [ - 14131, - 16542 - ], - [ - 30, - 25 - ], - [ - 43, - -13 - ], - [ - 45, - 0 - ], - [ - 32, - -30 - ], - [ - 24, - 19 - ], - [ - 51, - 11 - ], - [ - 18, - 28 - ], - [ - 29, - 0 - ] - ], - [ - [ - 14516, - 16254 - ], - [ - 31, - -22 - ], - [ - 32, - 20 - ], - [ - 32, - -21 - ] - ], - [ - [ - 14611, - 16231 - ], - [ - 2, - -31 - ], - [ - -34, - -26 - ], - [ - -21, - 11 - ], - [ - -20, - -144 - ] - ], - [ - [ - 15333, - 16008 - ], - [ - -89, - 101 - ], - [ - -80, - 46 - ], - [ - -60, - 70 - ], - [ - 51, - 19 - ], - [ - 58, - 101 - ], - [ - -39, - 47 - ], - [ - 102, - 49 - ], - [ - -1, - 26 - ], - [ - -63, - -19 - ] - ], - [ - [ - 15212, - 16448 - ], - [ - 2, - 53 - ], - [ - 36, - 34 - ], - [ - 68, - 9 - ], - [ - 11, - 40 - ], - [ - -16, - 66 - ], - [ - 28, - 63 - ], - [ - 0, - 35 - ], - [ - -103, - 39 - ], - [ - -41, - -1 - ], - [ - -43, - 56 - ], - [ - -53, - -19 - ], - [ - -89, - 42 - ], - [ - 2, - 23 - ], - [ - -25, - 53 - ], - [ - -56, - 5 - ], - [ - -6, - 38 - ], - [ - 18, - 24 - ], - [ - -45, - 68 - ], - [ - -72, - -12 - ], - [ - -21, - 6 - ], - [ - -18, - -27 - ], - [ - -26, - 5 - ] - ], - [ - [ - 14498, - 17932 - ], - [ - 79, - 67 - ], - [ - -73, - 57 - ] - ], - [ - [ - 14716, - 19142 - ], - [ - 71, - 42 - ], - [ - 115, - -73 - ], - [ - 191, - -28 - ], - [ - 263, - -136 - ], - [ - 54, - -57 - ], - [ - 4, - -80 - ], - [ - -77, - -63 - ], - [ - -114, - -32 - ], - [ - -311, - 91 - ], - [ - -51, - -15 - ], - [ - 113, - -88 - ], - [ - 5, - -56 - ], - [ - 4, - -122 - ], - [ - 90, - -37 - ], - [ - 55, - -31 - ], - [ - 9, - 58 - ], - [ - -42, - 52 - ], - [ - 44, - 45 - ], - [ - 168, - -74 - ], - [ - 59, - 29 - ], - [ - -47, - 88 - ], - [ - 163, - 117 - ], - [ - 64, - -7 - ], - [ - 65, - -42 - ], - [ - 41, - 83 - ], - [ - -58, - 71 - ], - [ - 34, - 72 - ], - [ - -51, - 75 - ], - [ - 195, - -39 - ], - [ - 39, - -67 - ], - [ - -88, - -15 - ], - [ - 1, - -67 - ], - [ - 54, - -41 - ], - [ - 108, - 26 - ], - [ - 17, - 77 - ], - [ - 146, - 57 - ], - [ - 243, - 103 - ], - [ - 53, - -6 - ], - [ - -69, - -73 - ], - [ - 86, - -12 - ], - [ - 50, - 41 - ], - [ - 131, - 3 - ], - [ - 103, - 50 - ], - [ - 80, - -73 - ], - [ - 79, - 80 - ], - [ - -73, - 69 - ], - [ - 36, - 40 - ], - [ - 206, - -36 - ], - [ - 97, - -38 - ], - [ - 252, - -137 - ], - [ - 47, - 63 - ], - [ - -71, - 63 - ], - [ - -2, - 26 - ], - [ - -84, - 12 - ], - [ - 23, - 56 - ], - [ - -37, - 94 - ], - [ - -2, - 38 - ], - [ - 128, - 109 - ], - [ - 46, - 109 - ], - [ - 52, - 24 - ], - [ - 184, - -32 - ], - [ - 15, - -67 - ], - [ - -66, - -97 - ], - [ - 43, - -38 - ], - [ - 23, - -84 - ], - [ - -16, - -164 - ], - [ - 77, - -74 - ], - [ - -30, - -80 - ], - [ - -137, - -170 - ], - [ - 80, - -18 - ], - [ - 28, - 43 - ], - [ - 76, - 31 - ], - [ - 19, - 59 - ], - [ - 60, - 57 - ], - [ - -40, - 69 - ], - [ - 32, - 79 - ], - [ - -76, - 10 - ], - [ - -17, - 66 - ], - [ - 56, - 121 - ], - [ - -91, - 98 - ], - [ - 125, - 80 - ], - [ - -16, - 86 - ], - [ - 35, - 3 - ], - [ - 36, - -67 - ], - [ - -27, - -116 - ], - [ - 74, - -22 - ], - [ - -31, - 87 - ], - [ - 116, - 47 - ], - [ - 145, - 6 - ], - [ - 129, - -68 - ], - [ - -62, - 100 - ], - [ - -7, - 128 - ], - [ - 121, - 24 - ], - [ - 168, - -5 - ], - [ - 151, - 15 - ], - [ - -57, - 63 - ], - [ - 81, - 79 - ], - [ - 80, - 3 - ], - [ - 135, - 60 - ], - [ - 184, - 16 - ], - [ - 24, - 32 - ], - [ - 183, - 12 - ], - [ - 57, - -27 - ], - [ - 156, - 63 - ], - [ - 128, - -2 - ], - [ - 20, - 52 - ], - [ - 66, - 51 - ], - [ - 165, - 50 - ], - [ - 119, - -39 - ], - [ - -95, - -30 - ], - [ - 158, - -18 - ], - [ - 19, - -60 - ], - [ - 64, - 30 - ], - [ - 204, - -2 - ], - [ - 157, - -59 - ], - [ - 56, - -44 - ], - [ - -18, - -63 - ], - [ - -77, - -35 - ], - [ - -183, - -67 - ], - [ - -52, - -36 - ], - [ - 86, - -16 - ], - [ - 103, - -31 - ], - [ - 63, - 23 - ], - [ - 35, - -77 - ], - [ - 31, - 31 - ], - [ - 112, - 19 - ], - [ - 223, - -20 - ], - [ - 17, - -56 - ], - [ - 292, - -18 - ], - [ - 4, - 92 - ], - [ - 148, - -21 - ], - [ - 111, - 1 - ], - [ - 112, - -63 - ], - [ - 32, - -77 - ], - [ - -41, - -50 - ], - [ - 88, - -95 - ], - [ - 109, - -49 - ], - [ - 68, - 126 - ], - [ - 111, - -54 - ], - [ - 119, - 33 - ], - [ - 135, - -37 - ], - [ - 52, - 33 - ], - [ - 114, - -16 - ], - [ - -51, - 111 - ], - [ - 92, - 52 - ], - [ - 630, - -78 - ], - [ - 59, - -71 - ], - [ - 183, - -92 - ], - [ - 281, - 23 - ], - [ - 139, - -20 - ], - [ - 58, - -50 - ], - [ - -8, - -87 - ], - [ - 85, - -34 - ], - [ - 94, - 24 - ], - [ - 123, - 3 - ], - [ - 132, - -23 - ], - [ - 132, - 13 - ], - [ - 121, - -107 - ], - [ - 87, - 39 - ], - [ - -57, - 76 - ], - [ - 32, - 54 - ], - [ - 222, - -34 - ], - [ - 145, - 7 - ], - [ - 200, - -57 - ], - [ - 98, - -52 - ], - [ - 0, - -478 - ], - [ - -1, - -1 - ], - [ - -89, - -53 - ], - [ - -90, - 9 - ], - [ - 62, - -64 - ], - [ - 42, - -99 - ], - [ - 32, - -32 - ], - [ - 8, - -49 - ], - [ - -18, - -32 - ], - [ - -130, - 26 - ], - [ - -195, - -90 - ], - [ - -62, - -14 - ], - [ - -106, - -85 - ], - [ - -101, - -73 - ], - [ - -26, - -55 - ], - [ - -100, - 83 - ], - [ - -181, - -94 - ], - [ - -32, - 45 - ], - [ - -67, - -52 - ], - [ - -93, - 17 - ], - [ - -23, - -79 - ], - [ - -84, - -116 - ], - [ - 3, - -49 - ], - [ - 79, - -27 - ], - [ - -9, - -174 - ], - [ - -65, - -5 - ], - [ - -30, - -100 - ], - [ - 29, - -52 - ], - [ - -121, - -61 - ], - [ - -25, - -137 - ], - [ - -104, - -29 - ], - [ - -20, - -122 - ], - [ - -101, - -112 - ], - [ - -26, - 83 - ], - [ - -30, - 175 - ], - [ - -38, - 266 - ], - [ - 33, - 167 - ], - [ - 59, - 71 - ], - [ - 3, - 56 - ], - [ - 109, - 27 - ], - [ - 124, - 151 - ], - [ - 120, - 123 - ], - [ - 126, - 96 - ], - [ - 56, - 169 - ], - [ - -85, - -10 - ], - [ - -42, - -99 - ], - [ - -177, - -131 - ], - [ - -57, - 147 - ], - [ - -180, - -41 - ], - [ - -174, - -201 - ], - [ - 57, - -73 - ], - [ - -155, - -32 - ], - [ - -108, - -12 - ], - [ - 5, - 87 - ], - [ - -108, - 18 - ], - [ - -87, - -59 - ], - [ - -213, - 21 - ], - [ - -229, - -36 - ], - [ - -226, - -234 - ], - [ - -267, - -283 - ], - [ - 110, - -15 - ], - [ - 34, - -75 - ], - [ - 68, - -27 - ], - [ - 44, - 60 - ], - [ - 77, - -8 - ], - [ - 100, - -132 - ], - [ - 3, - -102 - ], - [ - -55, - -120 - ], - [ - -6, - -143 - ], - [ - -31, - -192 - ], - [ - -105, - -173 - ], - [ - -23, - -83 - ], - [ - -95, - -140 - ], - [ - -94, - -138 - ], - [ - -45, - -71 - ], - [ - -93, - -71 - ], - [ - -44, - -1 - ], - [ - -44, - 58 - ], - [ - -93, - -88 - ], - [ - -11, - -40 - ] - ], - [ - [ - 15970, - 16364 - ], - [ - -32, - -71 - ], - [ - -67, - -20 - ], - [ - -69, - -124 - ], - [ - 63, - -114 - ], - [ - -7, - -81 - ], - [ - 76, - -141 - ] - ], - [ - [ - 13918, - 17327 - ], - [ - 16, - 52 - ], - [ - 96, - 39 - ] - ], - [ - [ - 14878, - 16312 - ], - [ - 19, - 30 - ], - [ - 49, - -26 - ], - [ - 23, - -4 - ], - [ - 9, - -24 - ], - [ - 10, - -4 - ] - ], - [ - [ - 14988, - 16284 - ], - [ - 1, - -10 - ], - [ - 34, - -29 - ], - [ - 71, - 7 - ], - [ - -14, - -43 - ], - [ - -76, - -20 - ], - [ - -95, - -70 - ], - [ - -38, - 25 - ], - [ - 15, - 56 - ], - [ - -76, - 35 - ], - [ - 12, - 23 - ], - [ - 67, - 40 - ], - [ - -11, - 14 - ] - ], - [ - [ - 22561, - 16885 - ], - [ - 70, - -212 - ], - [ - -103, - 39 - ], - [ - -43, - -173 - ], - [ - 68, - -123 - ], - [ - -2, - -84 - ], - [ - -53, - 73 - ], - [ - -46, - -93 - ], - [ - -12, - 100 - ], - [ - 7, - 117 - ], - [ - -8, - 130 - ], - [ - 17, - 90 - ], - [ - 3, - 161 - ], - [ - -41, - 118 - ], - [ - 6, - 164 - ], - [ - 64, - 55 - ], - [ - -27, - 56 - ], - [ - 31, - 16 - ], - [ - 18, - -79 - ], - [ - 24, - -116 - ], - [ - -2, - -118 - ], - [ - 29, - -121 - ] - ], - [ - [ - 348, - 18785 - ], - [ - 47, - -30 - ], - [ - -17, - 88 - ], - [ - 190, - -18 - ], - [ - 136, - -113 - ], - [ - -69, - -52 - ], - [ - -114, - -12 - ], - [ - -2, - -118 - ], - [ - -28, - -24 - ], - [ - -65, - 3 - ], - [ - -53, - 42 - ], - [ - -93, - 35 - ], - [ - -16, - 52 - ], - [ - -70, - 20 - ], - [ - -80, - -16 - ], - [ - -38, - 42 - ], - [ - 16, - 45 - ], - [ - -84, - -29 - ], - [ - 32, - -56 - ], - [ - -40, - -51 - ], - [ - 0, - 478 - ], - [ - 171, - -92 - ], - [ - 183, - -119 - ], - [ - -6, - -75 - ] - ], - [ - [ - 25095, - 19295 - ], - [ - -76, - -6 - ], - [ - -13, - 38 - ], - [ - 89, - 50 - ], - [ - 0, - -82 - ] - ], - [ - [ - 91, - 19302 - ], - [ - -91, - -7 - ], - [ - 0, - 82 - ], - [ - 9, - 5 - ], - [ - 59, - 0 - ], - [ - 101, - -35 - ], - [ - -6, - -16 - ], - [ - -72, - -29 - ] - ], - [ - [ - 22558, - 19580 - ], - [ - -106, - 0 - ], - [ - -143, - 13 - ], - [ - -12, - 6 - ], - [ - 66, - 48 - ], - [ - 87, - 11 - ], - [ - 99, - -46 - ], - [ - 9, - -32 - ] - ], - [ - [ - 23055, - 19805 - ], - [ - -81, - -47 - ], - [ - -111, - 10 - ], - [ - -130, - 48 - ], - [ - 17, - 38 - ], - [ - 130, - -18 - ], - [ - 175, - -31 - ] - ], - [ - [ - 22661, - 19862 - ], - [ - -55, - -89 - ], - [ - -257, - 4 - ], - [ - -115, - -29 - ], - [ - -138, - 78 - ], - [ - 37, - 83 - ], - [ - 92, - 22 - ], - [ - 184, - -5 - ], - [ - 252, - -64 - ] - ], - [ - [ - 16558, - 19281 - ], - [ - -41, - -10 - ], - [ - -228, - 16 - ], - [ - -18, - 53 - ], - [ - -126, - 32 - ], - [ - -11, - 65 - ], - [ - 72, - 25 - ], - [ - -3, - 66 - ], - [ - 139, - 102 - ], - [ - -65, - 15 - ], - [ - 167, - 105 - ], - [ - -18, - 55 - ], - [ - 155, - 63 - ], - [ - 231, - 77 - ], - [ - 232, - 22 - ], - [ - 119, - 45 - ], - [ - 136, - 16 - ], - [ - 48, - -48 - ], - [ - -47, - -37 - ], - [ - -247, - -60 - ], - [ - -213, - -57 - ], - [ - -216, - -114 - ], - [ - -104, - -117 - ], - [ - -109, - -116 - ], - [ - 14, - -99 - ], - [ - 133, - -99 - ] - ], - [ - [ - 19872, - 20192 - ], - [ - -393, - -47 - ], - [ - 128, - 158 - ], - [ - 57, - 13 - ], - [ - 52, - -8 - ], - [ - 177, - -68 - ], - [ - -21, - -48 - ] - ], - [ - [ - 16112, - 20460 - ], - [ - -93, - -15 - ], - [ - -63, - -10 - ], - [ - -10, - -19 - ], - [ - -81, - -20 - ], - [ - -76, - 28 - ], - [ - 40, - 38 - ], - [ - -155, - 3 - ], - [ - 136, - 22 - ], - [ - 106, - 2 - ], - [ - 14, - -33 - ], - [ - 40, - 29 - ], - [ - 66, - 20 - ], - [ - 103, - -26 - ], - [ - -27, - -19 - ] - ], - [ - [ - 19514, - 20260 - ], - [ - -152, - -15 - ], - [ - -194, - 35 - ], - [ - -116, - 46 - ], - [ - -53, - 86 - ], - [ - -95, - 24 - ], - [ - 181, - 82 - ], - [ - 150, - 27 - ], - [ - 136, - -61 - ], - [ - 160, - -116 - ], - [ - -17, - -108 - ] - ], - [ - [ - 14609, - 10636 - ], - [ - 17, - -12 - ], - [ - 42, - 37 - ] - ], - [ - [ - 14668, - 10661 - ], - [ - 28, - -68 - ], - [ - -4, - -70 - ], - [ - -21, - -15 - ] - ], - [ - [ - 11358, - 13317 - ], - [ - 3, - 50 - ] - ], - [ - [ - 16172, - 13077 - ], - [ - -201, - -46 - ], - [ - -65, - -54 - ], - [ - -50, - -126 - ], - [ - -32, - -20 - ], - [ - -18, - 40 - ], - [ - -26, - -6 - ], - [ - -68, - 12 - ], - [ - -13, - 12 - ], - [ - -80, - -3 - ], - [ - -19, - -11 - ], - [ - -28, - 31 - ], - [ - -19, - -59 - ], - [ - 7, - -50 - ], - [ - -30, - -39 - ] - ], - [ - [ - 15530, - 12758 - ], - [ - -9, - 52 - ], - [ - -21, - 36 - ], - [ - -6, - 48 - ], - [ - -36, - 43 - ], - [ - -37, - 100 - ], - [ - -20, - 98 - ], - [ - -48, - 83 - ], - [ - -31, - 19 - ], - [ - -46, - 115 - ], - [ - -8, - 83 - ], - [ - 3, - 71 - ], - [ - -40, - 133 - ], - [ - -33, - 47 - ], - [ - -38, - 25 - ], - [ - -22, - 68 - ], - [ - 3, - 28 - ], - [ - -19, - 62 - ], - [ - -20, - 27 - ], - [ - -28, - 89 - ], - [ - -42, - 97 - ], - [ - -36, - 82 - ], - [ - -34, - -1 - ], - [ - 10, - 66 - ], - [ - 4, - 42 - ], - [ - 8, - 48 - ] - ], - [ - [ - 15923, - 14223 - ], - [ - 27, - -104 - ], - [ - 34, - -27 - ], - [ - 12, - -42 - ], - [ - 48, - -51 - ], - [ - 4, - -49 - ], - [ - -7, - -40 - ], - [ - 9, - -41 - ], - [ - 20, - -33 - ], - [ - 9, - -40 - ], - [ - 10, - -29 - ] - ], - [ - [ - 16130, - 13752 - ], - [ - 13, - -46 - ] - ], - [ - [ - 14141, - 12134 - ], - [ - 1, - 29 - ], - [ - -25, - 35 - ], - [ - -1, - 70 - ], - [ - -15, - 46 - ], - [ - -24, - -7 - ], - [ - 7, - 44 - ], - [ - 18, - 50 - ], - [ - -8, - 50 - ], - [ - 23, - 37 - ], - [ - -15, - 28 - ], - [ - 19, - 74 - ], - [ - 32, - 88 - ], - [ - 60, - -8 - ], - [ - -4, - 476 - ] - ], - [ - [ - 15117, - 13437 - ], - [ - 23, - -118 - ], - [ - -15, - -22 - ], - [ - 10, - -123 - ], - [ - 25, - -144 - ], - [ - 27, - -29 - ], - [ - 38, - -45 - ] - ], - [ - [ - 14916, - 11839 - ], - [ - -1, - 94 - ], - [ - -10, - 2 - ], - [ - 2, - 60 - ], - [ - -9, - 41 - ], - [ - -36, - 47 - ], - [ - -8, - 87 - ], - [ - 8, - 88 - ], - [ - -32, - 9 - ], - [ - -5, - -27 - ], - [ - -42, - -6 - ], - [ - 17, - -35 - ], - [ - 6, - -72 - ], - [ - -38, - -66 - ], - [ - -35, - -87 - ], - [ - -36, - -12 - ], - [ - -58, - 70 - ], - [ - -27, - -25 - ], - [ - -7, - -35 - ], - [ - -36, - -23 - ], - [ - -2, - -24 - ], - [ - -70, - 0 - ], - [ - -9, - 24 - ], - [ - -51, - 5 - ], - [ - -25, - -21 - ], - [ - -19, - 10 - ], - [ - -36, - 70 - ], - [ - -12, - 33 - ], - [ - -50, - -16 - ], - [ - -19, - -56 - ], - [ - -18, - -107 - ], - [ - -24, - -23 - ], - [ - -21, - -13 - ], - [ - 47, - -47 - ] - ], - [ - [ - 14918, - 11307 - ], - [ - -43, - -55 - ], - [ - -49, - 0 - ], - [ - -56, - -28 - ], - [ - -44, - 27 - ], - [ - -29, - -33 - ] - ], - [ - [ - 11385, - 12283 - ], - [ - -11, - 92 - ] - ], - [ - [ - 11382, - 12428 - ], - [ - -28, - 94 - ], - [ - -35, - 42 - ], - [ - 31, - 23 - ], - [ - 33, - 84 - ], - [ - 17, - 62 - ] - ], - [ - [ - 23849, - 9540 - ], - [ - 19, - -42 - ], - [ - -49, - 1 - ], - [ - -26, - 74 - ], - [ - 41, - -29 - ], - [ - 15, - -4 - ] - ], - [ - [ - 23760, - 9613 - ], - [ - -27, - -3 - ], - [ - -43, - 12 - ], - [ - -14, - 19 - ], - [ - 4, - 47 - ], - [ - 46, - -19 - ], - [ - 23, - -25 - ], - [ - 11, - -31 - ] - ], - [ - [ - 23818, - 9645 - ], - [ - -11, - -22 - ], - [ - -51, - 104 - ], - [ - -15, - 72 - ], - [ - 24, - 0 - ], - [ - 25, - -96 - ], - [ - 28, - -58 - ] - ], - [ - [ - 23692, - 9797 - ], - [ - 3, - -24 - ], - [ - -55, - 51 - ], - [ - -38, - 43 - ], - [ - -26, - 40 - ], - [ - 11, - 12 - ], - [ - 32, - -29 - ], - [ - 57, - -55 - ], - [ - 16, - -38 - ] - ], - [ - [ - 23529, - 9916 - ], - [ - -14, - -7 - ], - [ - -30, - 27 - ], - [ - -29, - 49 - ], - [ - 4, - 20 - ], - [ - 41, - -50 - ], - [ - 28, - -39 - ] - ], - [ - [ - 11750, - 11611 - ], - [ - -19, - 9 - ], - [ - -50, - 49 - ], - [ - -36, - 64 - ], - [ - -12, - 44 - ], - [ - -9, - 88 - ] - ], - [ - [ - 6428, - 12403 - ], - [ - -8, - -28 - ], - [ - -41, - 1 - ], - [ - -25, - 12 - ], - [ - -28, - 24 - ], - [ - -39, - 7 - ], - [ - -20, - 26 - ] - ], - [ - [ - 15555, - 12172 - ], - [ - 23, - -22 - ], - [ - 13, - -49 - ], - [ - 32, - -51 - ], - [ - 34, - 0 - ], - [ - 66, - 31 - ], - [ - 76, - 14 - ], - [ - 61, - 37 - ], - [ - 35, - 8 - ], - [ - 25, - 22 - ], - [ - 40, - 4 - ] - ], - [ - [ - 15960, - 12166 - ], - [ - -1, - -2 - ], - [ - 0, - -49 - ], - [ - 0, - -121 - ], - [ - 0, - -63 - ], - [ - -32, - -74 - ], - [ - -48, - -100 - ] - ], - [ - [ - 15960, - 12166 - ], - [ - 22, - 2 - ], - [ - 32, - 18 - ], - [ - 37, - 12 - ], - [ - 33, - 41 - ], - [ - 26, - 1 - ], - [ - 2, - -33 - ], - [ - -6, - -70 - ], - [ - 0, - -63 - ], - [ - -15, - -44 - ], - [ - -20, - -129 - ], - [ - -33, - -134 - ], - [ - -43, - -153 - ], - [ - -60, - -176 - ], - [ - -60, - -135 - ], - [ - -82, - -163 - ], - [ - -69, - -97 - ], - [ - -105, - -120 - ], - [ - -65, - -91 - ], - [ - -76, - -145 - ], - [ - -16, - -63 - ], - [ - -16, - -29 - ] - ], - [ - [ - 8564, - 11514 - ], - [ - 83, - -24 - ], - [ - 8, - 21 - ], - [ - 56, - 9 - ], - [ - 75, - -32 - ] - ], - [ - [ - 14120, - 16686 - ], - [ - -19, - -31 - ], - [ - -14, - -49 - ] - ], - [ - [ - 13504, - 16256 - ], - [ - 15, - 11 - ] - ], - [ - [ - 14214, - 18716 - ], - [ - -120, - -34 - ], - [ - -68, - -84 - ], - [ - 11, - -73 - ], - [ - -111, - -97 - ], - [ - -134, - -103 - ], - [ - -51, - -169 - ], - [ - 49, - -84 - ], - [ - 67, - -67 - ], - [ - -64, - -135 - ], - [ - -72, - -28 - ], - [ - -27, - -202 - ], - [ - -40, - -112 - ], - [ - -84, - 12 - ], - [ - -40, - -96 - ], - [ - -80, - -5 - ], - [ - -22, - 113 - ], - [ - -59, - 136 - ], - [ - -53, - 170 - ] - ], - [ - [ - 14783, - 7590 - ], - [ - -14, - -53 - ], - [ - -41, - -13 - ], - [ - -41, - 65 - ], - [ - -1, - 41 - ], - [ - 19, - 45 - ], - [ - 7, - 35 - ], - [ - 20, - 9 - ], - [ - 35, - -22 - ] - ], - [ - [ - 15057, - 14954 - ], - [ - -7, - 91 - ], - [ - 17, - 50 - ] - ], - [ - [ - 15067, - 15095 - ], - [ - 19, - 26 - ], - [ - 19, - 26 - ], - [ - 4, - 67 - ], - [ - 22, - -23 - ], - [ - 77, - 33 - ], - [ - 37, - -22 - ], - [ - 58, - 0 - ], - [ - 80, - 45 - ], - [ - 37, - -2 - ], - [ - 80, - 19 - ] - ], - [ - [ - 12678, - 11534 - ], - [ - -57, - -26 - ] - ], - [ - [ - 19699, - 12259 - ], - [ - -63, - 55 - ], - [ - -60, - -2 - ], - [ - 11, - 94 - ], - [ - -62, - 0 - ], - [ - -5, - -132 - ], - [ - -38, - -176 - ], - [ - -23, - -106 - ], - [ - 5, - -86 - ], - [ - 46, - -4 - ], - [ - 28, - -110 - ], - [ - 12, - -103 - ], - [ - 39, - -69 - ], - [ - 42, - -14 - ], - [ - 37, - -62 - ] - ], - [ - [ - 19524, - 11573 - ], - [ - -27, - 46 - ], - [ - -12, - 59 - ], - [ - -37, - 68 - ], - [ - -34, - 57 - ], - [ - -11, - -71 - ], - [ - -14, - 67 - ], - [ - 8, - 75 - ], - [ - 21, - 115 - ] - ], - [ - [ - 17276, - 15253 - ], - [ - 39, - 122 - ], - [ - -15, - 89 - ], - [ - -51, - 29 - ], - [ - 18, - 53 - ], - [ - 58, - -6 - ], - [ - 33, - 66 - ], - [ - 22, - 77 - ], - [ - 94, - 28 - ], - [ - -15, - -55 - ], - [ - 10, - -34 - ], - [ - 29, - 3 - ] - ], - [ - [ - 16306, - 15260 - ], - [ - -13, - 85 - ], - [ - 10, - 125 - ], - [ - -54, - 41 - ], - [ - 18, - 82 - ], - [ - -46, - 7 - ], - [ - 15, - 101 - ], - [ - 66, - -29 - ], - [ - 61, - 38 - ], - [ - -51, - 72 - ], - [ - -20, - 69 - ], - [ - -56, - -31 - ], - [ - -7, - -88 - ], - [ - -22, - 78 - ] - ], - [ - [ - 16449, - 15753 - ], - [ - 79, - 2 - ], - [ - -12, - 60 - ], - [ - 60, - 41 - ], - [ - 58, - 70 - ], - [ - 94, - -63 - ], - [ - 8, - -96 - ], - [ - 26, - -25 - ], - [ - 76, - 6 - ], - [ - 23, - -22 - ], - [ - 35, - -124 - ], - [ - 79, - -82 - ], - [ - 46, - -57 - ], - [ - 73, - -59 - ], - [ - 92, - -51 - ], - [ - -2, - -73 - ] - ], - [ - [ - 21259, - 9730 - ], - [ - 8, - 29 - ], - [ - 60, - 27 - ], - [ - 49, - 4 - ], - [ - 21, - 15 - ], - [ - 27, - -15 - ], - [ - -26, - -33 - ], - [ - -72, - -52 - ], - [ - -59, - -35 - ] - ], - [ - [ - 8248, - 12088 - ], - [ - 40, - 16 - ], - [ - 15, - -5 - ], - [ - -3, - -89 - ], - [ - -58, - -13 - ], - [ - -13, - 11 - ], - [ - 20, - 33 - ], - [ - -1, - 47 - ] - ], - [ - [ - 13135, - 15230 - ], - [ - 75, - 48 - ], - [ - 49, - -14 - ], - [ - -2, - -61 - ], - [ - 59, - 44 - ], - [ - 5, - -23 - ], - [ - -35, - -59 - ], - [ - 0, - -55 - ], - [ - 24, - -30 - ], - [ - -9, - -104 - ], - [ - -46, - -60 - ], - [ - 13, - -66 - ], - [ - 36, - -2 - ], - [ - 18, - -57 - ], - [ - 26, - -18 - ] - ], - [ - [ - 15067, - 15095 - ], - [ - -25, - 54 - ], - [ - 26, - 45 - ], - [ - -42, - -10 - ], - [ - -59, - 28 - ], - [ - -48, - -70 - ], - [ - -105, - -13 - ], - [ - -57, - 64 - ], - [ - -75, - 4 - ], - [ - -16, - -49 - ], - [ - -48, - -15 - ], - [ - -68, - 64 - ], - [ - -76, - -2 - ], - [ - -41, - 119 - ], - [ - -51, - 67 - ], - [ - 34, - 93 - ], - [ - -44, - 58 - ], - [ - 77, - 114 - ], - [ - 107, - 5 - ], - [ - 30, - 91 - ], - [ - 133, - -16 - ], - [ - 83, - 78 - ], - [ - 82, - 34 - ], - [ - 115, - 3 - ], - [ - 122, - -85 - ], - [ - 100, - -46 - ], - [ - 81, - 18 - ], - [ - 60, - -10 - ], - [ - 82, - 62 - ] - ], - [ - [ - 14499, - 15837 - ], - [ - 8, - -46 - ], - [ - 61, - -39 - ], - [ - -12, - -29 - ], - [ - -83, - -7 - ], - [ - -30, - -37 - ], - [ - -58, - -65 - ], - [ - -22, - 56 - ], - [ - 1, - 25 - ] - ], - [ - [ - 21036, - 13724 - ], - [ - -42, - -193 - ], - [ - -29, - -98 - ], - [ - -37, - 101 - ], - [ - -8, - 89 - ], - [ - 41, - 118 - ], - [ - 56, - 91 - ], - [ - 32, - -36 - ], - [ - -13, - -72 - ] - ], - [ - [ - 14668, - 10661 - ], - [ - 24, - 14 - ], - [ - 77, - -1 - ], - [ - 142, - 9 - ] - ], - [ - [ - 15280, - 10236 - ], - [ - -32, - -148 - ], - [ - 4, - -68 - ], - [ - 45, - -43 - ], - [ - 2, - -32 - ], - [ - -19, - -72 - ], - [ - 4, - -36 - ], - [ - -5, - -58 - ], - [ - 24, - -75 - ], - [ - 29, - -118 - ], - [ - 26, - -27 - ] - ], - [ - [ - 14831, - 9690 - ], - [ - -39, - 36 - ], - [ - -45, - 20 - ], - [ - -28, - 20 - ], - [ - -29, - 31 - ] - ], - [ - [ - 15212, - 16448 - ], - [ - -56, - -10 - ], - [ - -46, - -38 - ], - [ - -65, - -7 - ], - [ - -60, - -44 - ], - [ - 3, - -65 - ] - ], - [ - [ - 14878, - 16312 - ], - [ - -9, - 13 - ], - [ - -109, - 31 - ], - [ - -4, - 44 - ], - [ - -65, - -14 - ], - [ - -26, - -66 - ], - [ - -54, - -89 - ] - ], - [ - [ - 8827, - 6746 - ], - [ - -30, - -75 - ], - [ - -79, - -67 - ], - [ - -51, - 24 - ], - [ - -38, - -13 - ], - [ - -65, - 52 - ], - [ - -47, - -4 - ], - [ - -42, - 66 - ] - ], - [ - [ - 7867, - 16212 - ], - [ - 13, - -39 - ], - [ - -75, - -58 - ], - [ - -72, - -42 - ], - [ - -73, - -35 - ], - [ - -37, - -71 - ], - [ - -12, - -27 - ], - [ - -1, - -64 - ], - [ - 23, - -64 - ], - [ - 29, - -3 - ], - [ - -7, - 44 - ], - [ - 21, - -26 - ], - [ - -6, - -35 - ], - [ - -47, - -19 - ], - [ - -33, - 2 - ], - [ - -52, - -21 - ], - [ - -30, - -6 - ], - [ - -41, - -6 - ], - [ - -58, - -34 - ], - [ - 103, - 22 - ], - [ - 20, - -22 - ], - [ - -97, - -36 - ], - [ - -45, - -1 - ], - [ - 2, - 15 - ], - [ - -21, - -33 - ], - [ - 21, - -6 - ], - [ - -15, - -86 - ], - [ - -51, - -92 - ], - [ - -5, - 31 - ], - [ - -16, - 6 - ], - [ - -22, - 30 - ], - [ - 14, - -65 - ], - [ - 17, - -21 - ], - [ - 1, - -46 - ], - [ - -22, - -46 - ], - [ - -39, - -96 - ], - [ - -7, - 5 - ], - [ - 22, - 81 - ], - [ - -36, - 46 - ], - [ - -8, - 100 - ], - [ - -13, - -52 - ], - [ - 15, - -76 - ], - [ - -46, - 19 - ], - [ - 48, - -39 - ], - [ - 3, - -114 - ], - [ - 20, - -8 - ], - [ - 7, - -42 - ], - [ - 10, - -120 - ], - [ - -45, - -89 - ], - [ - -72, - -35 - ], - [ - -46, - -71 - ], - [ - -34, - -8 - ], - [ - -36, - -44 - ], - [ - -10, - -40 - ], - [ - -76, - -78 - ], - [ - -39, - -57 - ], - [ - -33, - -71 - ], - [ - -11, - -85 - ], - [ - 12, - -83 - ], - [ - 24, - -103 - ], - [ - 30, - -85 - ], - [ - 1, - -52 - ], - [ - 33, - -139 - ], - [ - -2, - -81 - ], - [ - -3, - -47 - ], - [ - -18, - -73 - ], - [ - -21, - -15 - ], - [ - -34, - 15 - ], - [ - -11, - 52 - ], - [ - -26, - 28 - ], - [ - -37, - 103 - ], - [ - -33, - 92 - ], - [ - -10, - 47 - ], - [ - 14, - 79 - ], - [ - -19, - 66 - ], - [ - -55, - 101 - ], - [ - -27, - 18 - ], - [ - -70, - -54 - ], - [ - -13, - 6 - ], - [ - -34, - 56 - ], - [ - -43, - 29 - ], - [ - -79, - -15 - ], - [ - -62, - 13 - ], - [ - -53, - -8 - ], - [ - -29, - -19 - ], - [ - 13, - -31 - ], - [ - -2, - -49 - ], - [ - 15, - -24 - ], - [ - -13, - -16 - ], - [ - -26, - 18 - ], - [ - -26, - -23 - ], - [ - -51, - 4 - ], - [ - -52, - 64 - ], - [ - -60, - -15 - ], - [ - -51, - 27 - ], - [ - -44, - -8 - ], - [ - -58, - -28 - ], - [ - -64, - -89 - ], - [ - -69, - -52 - ], - [ - -38, - -57 - ], - [ - -16, - -54 - ], - [ - -1, - -83 - ], - [ - 4, - -57 - ], - [ - 13, - -41 - ] - ], - [ - [ - 4383, - 14700 - ], - [ - -12, - 62 - ], - [ - -45, - 69 - ], - [ - -33, - 14 - ], - [ - -7, - 34 - ], - [ - -39, - 6 - ], - [ - -25, - 33 - ], - [ - -65, - 12 - ], - [ - -18, - 19 - ], - [ - -8, - 66 - ], - [ - -68, - 120 - ], - [ - -58, - 167 - ], - [ - 2, - 28 - ], - [ - -30, - 40 - ], - [ - -54, - 100 - ], - [ - -10, - 98 - ], - [ - -37, - 66 - ], - [ - 15, - 99 - ], - [ - -2, - 103 - ], - [ - -22, - 92 - ], - [ - 27, - 113 - ], - [ - 8, - 109 - ], - [ - 9, - 109 - ], - [ - -13, - 161 - ], - [ - -22, - 102 - ], - [ - -20, - 56 - ], - [ - 8, - 23 - ], - [ - 101, - -41 - ], - [ - 37, - -113 - ], - [ - 17, - 32 - ], - [ - -11, - 98 - ], - [ - -23, - 99 - ] - ], - [ - [ - 3448, - 17372 - ], - [ - -38, - 45 - ], - [ - -62, - 38 - ], - [ - -19, - 105 - ], - [ - -90, - 97 - ], - [ - -38, - 113 - ], - [ - -67, - 8 - ], - [ - -111, - 3 - ], - [ - -81, - 34 - ], - [ - -144, - 125 - ], - [ - -67, - 23 - ], - [ - -122, - 42 - ], - [ - -97, - -10 - ], - [ - -137, - 55 - ], - [ - -83, - 51 - ], - [ - -77, - -25 - ], - [ - 14, - -83 - ], - [ - -38, - -8 - ], - [ - -81, - -25 - ], - [ - -61, - -40 - ], - [ - -77, - -26 - ], - [ - -10, - 71 - ], - [ - 31, - 117 - ], - [ - 74, - 37 - ], - [ - -19, - 30 - ], - [ - -89, - -66 - ], - [ - -47, - -80 - ], - [ - -101, - -86 - ], - [ - 51, - -58 - ], - [ - -66, - -86 - ], - [ - -75, - -50 - ], - [ - -69, - -37 - ], - [ - -18, - -53 - ], - [ - -109, - -62 - ], - [ - -22, - -56 - ], - [ - -81, - -52 - ], - [ - -48, - 10 - ], - [ - -65, - -34 - ], - [ - -71, - -41 - ], - [ - -58, - -40 - ], - [ - -119, - -34 - ], - [ - -11, - 20 - ], - [ - 76, - 56 - ], - [ - 68, - 37 - ], - [ - 74, - 66 - ], - [ - 87, - 13 - ], - [ - 34, - 50 - ], - [ - 97, - 71 - ], - [ - 15, - 24 - ], - [ - 52, - 43 - ], - [ - 12, - 91 - ], - [ - 35, - 71 - ], - [ - -80, - -37 - ], - [ - -22, - 21 - ], - [ - -38, - -44 - ], - [ - -46, - 61 - ], - [ - -19, - -43 - ], - [ - -26, - 60 - ], - [ - -69, - -48 - ], - [ - -43, - 0 - ], - [ - -6, - 71 - ], - [ - 13, - 44 - ], - [ - -45, - 43 - ], - [ - -91, - -23 - ], - [ - -59, - 56 - ], - [ - -48, - 29 - ], - [ - 0, - 68 - ], - [ - -54, - 51 - ], - [ - 27, - 69 - ], - [ - 57, - 67 - ], - [ - 25, - 62 - ], - [ - 57, - 9 - ], - [ - 47, - -20 - ], - [ - 57, - 58 - ], - [ - 50, - -10 - ], - [ - 53, - 37 - ], - [ - -13, - 55 - ], - [ - -39, - 22 - ], - [ - 52, - 46 - ], - [ - -43, - -2 - ], - [ - -74, - -26 - ], - [ - -21, - -26 - ], - [ - -55, - 26 - ], - [ - -99, - -13 - ], - [ - -102, - 29 - ], - [ - -29, - 48 - ], - [ - -88, - 70 - ], - [ - 98, - 50 - ], - [ - 155, - 58 - ], - [ - 58, - 0 - ], - [ - -10, - -60 - ], - [ - 147, - 5 - ], - [ - -56, - 74 - ], - [ - -86, - 46 - ], - [ - -50, - 60 - ], - [ - -67, - 51 - ], - [ - -95, - 38 - ], - [ - 39, - 63 - ], - [ - 123, - 4 - ], - [ - 88, - 55 - ], - [ - 17, - 58 - ], - [ - 71, - 57 - ], - [ - 68, - 14 - ], - [ - 132, - 53 - ], - [ - 64, - -8 - ], - [ - 108, - 64 - ], - [ - 105, - -25 - ], - [ - 50, - -54 - ], - [ - 31, - 23 - ], - [ - 118, - -7 - ], - [ - -4, - -28 - ], - [ - 107, - -20 - ], - [ - 71, - 12 - ], - [ - 147, - -38 - ], - [ - 134, - -12 - ], - [ - 53, - -15 - ], - [ - 93, - 19 - ], - [ - 106, - -36 - ], - [ - 76, - -17 - ] - ], - [ - [ - 1705, - 13087 - ], - [ - -10, - -20 - ], - [ - -18, - 17 - ], - [ - 2, - 33 - ], - [ - -11, - 44 - ], - [ - 3, - 13 - ], - [ - 12, - 20 - ], - [ - -4, - 23 - ], - [ - 4, - 12 - ], - [ - 5, - -3 - ], - [ - 27, - -20 - ], - [ - 12, - -10 - ], - [ - 11, - -16 - ], - [ - 18, - -42 - ], - [ - -2, - -7 - ], - [ - -27, - -26 - ], - [ - -22, - -18 - ] - ], - [ - [ - 1667, - 13274 - ], - [ - -23, - -9 - ], - [ - -12, - 26 - ], - [ - -8, - 9 - ], - [ - -1, - 8 - ], - [ - 7, - 10 - ], - [ - 25, - -11 - ], - [ - 18, - -19 - ], - [ - -6, - -14 - ] - ], - [ - [ - 1620, - 13338 - ], - [ - -2, - -13 - ], - [ - -37, - 3 - ], - [ - 5, - 15 - ], - [ - 34, - -5 - ] - ], - [ - [ - 1558, - 13355 - ], - [ - -4, - -7 - ], - [ - -5, - 2 - ], - [ - -24, - 4 - ], - [ - -9, - 27 - ], - [ - -3, - 5 - ], - [ - 19, - 17 - ], - [ - 6, - -8 - ], - [ - 20, - -40 - ] - ], - [ - [ - 1440, - 13434 - ], - [ - -8, - -12 - ], - [ - -24, - 22 - ], - [ - 4, - 9 - ], - [ - 10, - 12 - ], - [ - 16, - -3 - ], - [ - 2, - -28 - ] - ], - [ - [ - 1882, - 17649 - ], - [ - -70, - -45 - ], - [ - -36, - 31 - ], - [ - -10, - 56 - ], - [ - 63, - 42 - ], - [ - 37, - 19 - ], - [ - 46, - -8 - ], - [ - 30, - -38 - ], - [ - -60, - -57 - ] - ], - [ - [ - 1005, - 17985 - ], - [ - -43, - -19 - ], - [ - -45, - 22 - ], - [ - -43, - 33 - ], - [ - 69, - 20 - ], - [ - 56, - -10 - ], - [ - 6, - -46 - ] - ], - [ - [ - 576, - 18449 - ], - [ - 43, - -23 - ], - [ - 44, - 13 - ], - [ - 56, - -32 - ], - [ - 69, - -16 - ], - [ - -5, - -13 - ], - [ - -53, - -26 - ], - [ - -53, - 27 - ], - [ - -27, - 21 - ], - [ - -61, - -7 - ], - [ - -17, - 11 - ], - [ - 4, - 45 - ] - ], - [ - [ - 7575, - 12210 - ], - [ - -2, - -28 - ], - [ - -41, - -14 - ], - [ - 23, - -55 - ], - [ - -1, - -63 - ], - [ - -31, - -69 - ], - [ - 27, - -95 - ], - [ - 30, - 7 - ], - [ - 15, - 87 - ], - [ - -21, - 42 - ], - [ - -4, - 91 - ], - [ - 87, - 49 - ], - [ - -10, - 56 - ], - [ - 25, - 38 - ], - [ - 25, - -84 - ], - [ - 49, - -2 - ], - [ - 45, - -67 - ], - [ - 3, - -40 - ], - [ - 62, - -1 - ], - [ - 75, - 13 - ], - [ - 40, - -54 - ], - [ - 53, - -15 - ], - [ - 39, - 38 - ], - [ - 1, - 30 - ], - [ - 86, - 7 - ], - [ - 84, - 2 - ], - [ - -59, - -36 - ], - [ - 24, - -56 - ], - [ - 55, - -9 - ], - [ - 53, - -59 - ], - [ - 11, - -96 - ], - [ - 37, - 2 - ], - [ - 27, - -28 - ] - ], - [ - [ - 20079, - 13383 - ], - [ - -93, - -103 - ], - [ - -58, - -113 - ], - [ - -15, - -83 - ], - [ - 53, - -127 - ], - [ - 66, - -157 - ], - [ - 63, - -74 - ], - [ - 42, - -96 - ], - [ - 32, - -222 - ], - [ - -9, - -211 - ], - [ - -58, - -79 - ], - [ - -80, - -77 - ], - [ - -57, - -100 - ], - [ - -87, - -112 - ], - [ - -25, - 77 - ], - [ - 19, - 81 - ], - [ - -52, - 68 - ] - ], - [ - [ - 24248, - 8822 - ], - [ - -23, - -16 - ], - [ - -24, - 52 - ], - [ - 3, - 33 - ], - [ - 44, - -69 - ] - ], - [ - [ - 24196, - 9006 - ], - [ - 12, - -97 - ], - [ - -19, - 15 - ], - [ - -15, - -7 - ], - [ - -10, - 34 - ], - [ - -1, - 91 - ], - [ - 33, - -36 - ] - ], - [ - [ - 16250, - 12795 - ], - [ - -51, - -32 - ], - [ - -13, - -54 - ], - [ - -2, - -41 - ], - [ - -69, - -50 - ], - [ - -112, - -56 - ], - [ - -62, - -85 - ], - [ - -31, - -6 - ], - [ - -21, - 7 - ], - [ - -40, - -50 - ], - [ - -45, - -23 - ], - [ - -58, - -6 - ], - [ - -18, - -7 - ], - [ - -15, - -32 - ], - [ - -19, - -9 - ], - [ - -10, - -30 - ], - [ - -35, - 2 - ], - [ - -22, - -16 - ], - [ - -48, - 6 - ], - [ - -19, - 70 - ], - [ - 2, - 66 - ], - [ - -11, - 35 - ], - [ - -14, - 89 - ], - [ - -20, - 49 - ], - [ - 14, - 6 - ], - [ - -7, - 55 - ], - [ - 9, - 23 - ], - [ - -3, - 52 - ] - ], - [ - [ - 14599, - 8147 - ], - [ - 29, - -1 - ], - [ - 33, - -21 - ], - [ - 24, - 15 - ], - [ - 37, - -12 - ] - ], - [ - [ - 14836, - 7589 - ], - [ - -17, - -87 - ], - [ - -9, - -100 - ], - [ - -18, - -54 - ], - [ - -47, - -61 - ], - [ - -14, - -17 - ], - [ - -29, - -61 - ], - [ - -20, - -62 - ], - [ - -39, - -86 - ], - [ - -79, - -123 - ], - [ - -49, - -72 - ], - [ - -53, - -55 - ], - [ - -73, - -47 - ], - [ - -35, - -6 - ], - [ - -9, - -33 - ], - [ - -43, - 18 - ], - [ - -34, - -23 - ], - [ - -76, - 23 - ], - [ - -42, - -15 - ], - [ - -29, - 7 - ], - [ - -72, - -48 - ], - [ - -59, - -19 - ], - [ - -43, - -45 - ], - [ - -32, - -3 - ], - [ - -30, - 43 - ], - [ - -23, - 2 - ], - [ - -30, - 54 - ], - [ - -3, - -17 - ], - [ - -10, - 32 - ], - [ - 1, - 70 - ], - [ - -23, - 81 - ], - [ - 23, - 22 - ], - [ - -2, - 92 - ], - [ - -46, - 112 - ], - [ - -35, - 102 - ], - [ - 0, - 0 - ], - [ - -50, - 156 - ] - ], - [ - [ - 14658, - 8937 - ], - [ - -53, - -17 - ], - [ - -40, - -47 - ], - [ - -8, - -42 - ], - [ - -25, - -10 - ], - [ - -61, - -98 - ], - [ - -38, - -78 - ], - [ - -24, - -3 - ], - [ - -22, - 14 - ], - [ - -78, - 13 - ] - ] - ], - "transform": { - "scale": [ - 0.01434548714883443, - 0.008335499711981569 - ], - "translate": [ - -180, - -90 - ] - }, - "objects": { - "ne_110m_admin_0_countries": { - "type": "GeometryCollection", - "geometries": [ - { - "arcs": [ - [ - 0, - 1, - 2, - 3, - 4, - 5 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Afghanistan", - "NAME_LONG": "Afghanistan", - "ABBREV": "Afg.", - "FORMAL_EN": "Islamic State of Afghanistan", - "POP_EST": 34124811, - "POP_RANK": 15, - "GDP_MD_EST": 64080, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AF", - "ISO_A3": "AFG", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - [ - 6, - 7, - 8, - 9 - ] - ], - [ - [ - 10, - 11, - 12 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Angola", - "NAME_LONG": "Angola", - "ABBREV": "Ang.", - "FORMAL_EN": "People's Republic of Angola", - "POP_EST": 29310273, - "POP_RANK": 15, - "GDP_MD_EST": 189000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AO", - "ISO_A3": "AGO", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - 13, - 14, - 15, - 16, - 17 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Albania", - "NAME_LONG": "Albania", - "ABBREV": "Alb.", - "FORMAL_EN": "Republic of Albania", - "POP_EST": 3047987, - "POP_RANK": 12, - "GDP_MD_EST": 33900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AL", - "ISO_A3": "ALB", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - 18, - 19, - 20, - 21, - 22 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "United Arab Emirates", - "NAME_LONG": "United Arab Emirates", - "ABBREV": "U.A.E.", - "FORMAL_EN": "United Arab Emirates", - "POP_EST": 6072475, - "POP_RANK": 13, - "GDP_MD_EST": 667200, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AE", - "ISO_A3": "ARE", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - [ - 23, - 24 - ] - ], - [ - [ - 25, - 26, - 27, - 28, - 29, - 30 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Argentina", - "NAME_LONG": "Argentina", - "ABBREV": "Arg.", - "FORMAL_EN": "Argentine Republic", - "POP_EST": 44293293, - "POP_RANK": 15, - "GDP_MD_EST": 879400, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AR", - "ISO_A3": "ARG", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - 31, - 32, - 33, - 34, - 35 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Armenia", - "NAME_LONG": "Armenia", - "ABBREV": "Arm.", - "FORMAL_EN": "Republic of Armenia", - "POP_EST": 3045191, - "POP_RANK": 12, - "GDP_MD_EST": 26300, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AM", - "ISO_A3": "ARM", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - [ - 36 - ] - ], - [ - [ - 37 - ] - ], - [ - [ - 38 - ] - ], - [ - [ - 39 - ] - ], - [ - [ - 40 - ] - ], - [ - [ - 41 - ] - ], - [ - [ - 42 - ] - ], - [ - [ - 43 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Antarctica", - "NAME_LONG": "Antarctica", - "ABBREV": "Ant.", - "FORMAL_EN": "", - "POP_EST": 4050, - "POP_RANK": 4, - "GDP_MD_EST": 810, - "POP_YEAR": 2013, - "GDP_YEAR": 2013, - "ISO_A2": "AQ", - "ISO_A3": "ATA", - "CONTINENT": "Antarctica", - "REGION_UN": "Antarctica", - "SUBREGION": "Antarctica" - } - }, - { - "arcs": [ - [ - 44 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Fr. S. Antarctic Lands", - "NAME_LONG": "French Southern and Antarctic Lands", - "ABBREV": "Fr. S.A.L.", - "FORMAL_EN": "Territory of the French Southern and Antarctic Lands", - "POP_EST": 140, - "POP_RANK": 1, - "GDP_MD_EST": 16, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TF", - "ISO_A3": "ATF", - "CONTINENT": "Seven seas (open ocean)", - "REGION_UN": "Seven seas (open ocean)", - "SUBREGION": "Seven seas (open ocean)" - } - }, - { - "arcs": [ - [ - [ - 45 - ] - ], - [ - [ - 46 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Australia", - "NAME_LONG": "Australia", - "ABBREV": "Auz.", - "FORMAL_EN": "Commonwealth of Australia", - "POP_EST": 23232413, - "POP_RANK": 15, - "GDP_MD_EST": 1189000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AU", - "ISO_A3": "AUS", - "CONTINENT": "Oceania", - "REGION_UN": "Oceania", - "SUBREGION": "Australia and New Zealand" - } - }, - { - "arcs": [ - [ - 47, - 48, - 49, - 50, - 51, - 52, - 53 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Austria", - "NAME_LONG": "Austria", - "ABBREV": "Aust.", - "FORMAL_EN": "Republic of Austria", - "POP_EST": 8754413, - "POP_RANK": 13, - "GDP_MD_EST": 416600, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AT", - "ISO_A3": "AUT", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Western Europe" - } - }, - { - "arcs": [ - [ - [ - -33, - 54, - 55, - 56, - 57 - ] - ], - [ - [ - -35, - 58 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Azerbaijan", - "NAME_LONG": "Azerbaijan", - "ABBREV": "Aze.", - "FORMAL_EN": "Republic of Azerbaijan", - "POP_EST": 9961396, - "POP_RANK": 13, - "GDP_MD_EST": 167900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "AZ", - "ISO_A3": "AZE", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - 59, - 60, - 61 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Burundi", - "NAME_LONG": "Burundi", - "ABBREV": "Bur.", - "FORMAL_EN": "Republic of Burundi", - "POP_EST": 11466756, - "POP_RANK": 14, - "GDP_MD_EST": 7892, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BI", - "ISO_A3": "BDI", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - 62, - 63, - 64, - 65, - 66 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Belgium", - "NAME_LONG": "Belgium", - "ABBREV": "Belg.", - "FORMAL_EN": "Kingdom of Belgium", - "POP_EST": 11491346, - "POP_RANK": 14, - "GDP_MD_EST": 508600, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BE", - "ISO_A3": "BEL", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Western Europe" - } - }, - { - "arcs": [ - [ - 67, - 68, - 69, - 70, - 71 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Benin", - "NAME_LONG": "Benin", - "ABBREV": "Benin", - "FORMAL_EN": "Republic of Benin", - "POP_EST": 11038805, - "POP_RANK": 14, - "GDP_MD_EST": 24310, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BJ", - "ISO_A3": "BEN", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -70, - 72, - 73, - 74, - 75, - 76 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Burkina Faso", - "NAME_LONG": "Burkina Faso", - "ABBREV": "B.F.", - "FORMAL_EN": "Burkina Faso", - "POP_EST": 20107509, - "POP_RANK": 15, - "GDP_MD_EST": 32990, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BF", - "ISO_A3": "BFA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - 77, - 78, - 79 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Bangladesh", - "NAME_LONG": "Bangladesh", - "ABBREV": "Bang.", - "FORMAL_EN": "People's Republic of Bangladesh", - "POP_EST": 157826578, - "POP_RANK": 17, - "GDP_MD_EST": 628400, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BD", - "ISO_A3": "BGD", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - 80, - 81, - 82, - 83, - 84, - 85 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Bulgaria", - "NAME_LONG": "Bulgaria", - "ABBREV": "Bulg.", - "FORMAL_EN": "Republic of Bulgaria", - "POP_EST": 7101510, - "POP_RANK": 13, - "GDP_MD_EST": 143100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BG", - "ISO_A3": "BGR", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - [ - 86 - ] - ], - [ - [ - 87 - ] - ], - [ - [ - 88 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Bahamas", - "NAME_LONG": "Bahamas", - "ABBREV": "Bhs.", - "FORMAL_EN": "Commonwealth of the Bahamas", - "POP_EST": 329988, - "POP_RANK": 10, - "GDP_MD_EST": 9066, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BS", - "ISO_A3": "BHS", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Caribbean" - } - }, - { - "arcs": [ - [ - 89, - 90, - 91 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Bosnia and Herz.", - "NAME_LONG": "Bosnia and Herzegovina", - "ABBREV": "B.H.", - "FORMAL_EN": "Bosnia and Herzegovina", - "POP_EST": 3856181, - "POP_RANK": 12, - "GDP_MD_EST": 42530, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BA", - "ISO_A3": "BIH", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - 92, - 93, - 94, - 95, - 96 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Belarus", - "NAME_LONG": "Belarus", - "ABBREV": "Bela.", - "FORMAL_EN": "Republic of Belarus", - "POP_EST": 9549747, - "POP_RANK": 13, - "GDP_MD_EST": 165400, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BY", - "ISO_A3": "BLR", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - 97, - 98, - 99 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Belize", - "NAME_LONG": "Belize", - "ABBREV": "Belize", - "FORMAL_EN": "Belize", - "POP_EST": 360346, - "POP_RANK": 10, - "GDP_MD_EST": 3088, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BZ", - "ISO_A3": "BLZ", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - -27, - 100, - 101, - 102, - 103 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Bolivia", - "NAME_LONG": "Bolivia", - "ABBREV": "Bolivia", - "FORMAL_EN": "Plurinational State of Bolivia", - "POP_EST": 11138234, - "POP_RANK": 14, - "GDP_MD_EST": 78350, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BO", - "ISO_A3": "BOL", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - -29, - 104, - -103, - 105, - 106, - 107, - 108, - 109, - 110, - 111, - 112 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Brazil", - "NAME_LONG": "Brazil", - "ABBREV": "Brazil", - "FORMAL_EN": "Federative Republic of Brazil", - "POP_EST": 207353391, - "POP_RANK": 17, - "GDP_MD_EST": 3081000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BR", - "ISO_A3": "BRA", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - 113, - 114 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Brunei", - "NAME_LONG": "Brunei Darussalam", - "ABBREV": "Brunei", - "FORMAL_EN": "Negara Brunei Darussalam", - "POP_EST": 443593, - "POP_RANK": 10, - "GDP_MD_EST": 33730, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BN", - "ISO_A3": "BRN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - 115, - 116 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Bhutan", - "NAME_LONG": "Bhutan", - "ABBREV": "Bhutan", - "FORMAL_EN": "Kingdom of Bhutan", - "POP_EST": 758288, - "POP_RANK": 11, - "GDP_MD_EST": 6432, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BT", - "ISO_A3": "BTN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - 117, - 118, - 119, - 120 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Botswana", - "NAME_LONG": "Botswana", - "ABBREV": "Bwa.", - "FORMAL_EN": "Republic of Botswana", - "POP_EST": 2214858, - "POP_RANK": 12, - "GDP_MD_EST": 35900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "BW", - "ISO_A3": "BWA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Southern Africa" - } - }, - { - "arcs": [ - [ - 121, - 122, - 123, - 124, - 125, - 126 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Central African Rep.", - "NAME_LONG": "Central African Republic", - "ABBREV": "C.A.R.", - "FORMAL_EN": "Central African Republic", - "POP_EST": 5625118, - "POP_RANK": 13, - "GDP_MD_EST": 3206, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CF", - "ISO_A3": "CAF", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - [ - 127 - ] - ], - [ - [ - 128 - ] - ], - [ - [ - 129 - ] - ], - [ - [ - 130 - ] - ], - [ - [ - 131 - ] - ], - [ - [ - 132 - ] - ], - [ - [ - 133 - ] - ], - [ - [ - 134 - ] - ], - [ - [ - 135 - ] - ], - [ - [ - 136 - ] - ], - [ - [ - 137, - 138, - 139, - 140 - ] - ], - [ - [ - 141 - ] - ], - [ - [ - 142 - ] - ], - [ - [ - 143 - ] - ], - [ - [ - 144 - ] - ], - [ - [ - 145 - ] - ], - [ - [ - 146 - ] - ], - [ - [ - 147 - ] - ], - [ - [ - 148 - ] - ], - [ - [ - 149 - ] - ], - [ - [ - 150 - ] - ], - [ - [ - 151 - ] - ], - [ - [ - 152 - ] - ], - [ - [ - 153 - ] - ], - [ - [ - 154 - ] - ], - [ - [ - 155 - ] - ], - [ - [ - 156 - ] - ], - [ - [ - 157 - ] - ], - [ - [ - 158 - ] - ], - [ - [ - 159 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Canada", - "NAME_LONG": "Canada", - "ABBREV": "Can.", - "FORMAL_EN": "Canada", - "POP_EST": 35623680, - "POP_RANK": 15, - "GDP_MD_EST": 1674000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CA", - "ISO_A3": "CAN", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Northern America" - } - }, - { - "arcs": [ - [ - -51, - 160, - 161, - 162 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Switzerland", - "NAME_LONG": "Switzerland", - "ABBREV": "Switz.", - "FORMAL_EN": "Swiss Confederation", - "POP_EST": 8236303, - "POP_RANK": 13, - "GDP_MD_EST": 496300, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CH", - "ISO_A3": "CHE", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Western Europe" - } - }, - { - "arcs": [ - [ - [ - -24, - 163 - ] - ], - [ - [ - -26, - 164, - 165, - -101 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Chile", - "NAME_LONG": "Chile", - "ABBREV": "Chile", - "FORMAL_EN": "Republic of Chile", - "POP_EST": 17789267, - "POP_RANK": 14, - "GDP_MD_EST": 436100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CL", - "ISO_A3": "CHL", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - [ - -4, - 166, - 167, - 168, - 169, - 170, - 171, - 172, - 173, - 174, - 175, - 176, - 177, - -117, - 178, - 179, - 180, - 181 - ] - ], - [ - [ - 182 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "China", - "NAME_LONG": "China", - "ABBREV": "China", - "FORMAL_EN": "People's Republic of China", - "POP_EST": 1379302771, - "POP_RANK": 18, - "GDP_MD_EST": 21140000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CN", - "ISO_A3": "CHN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Eastern Asia" - } - }, - { - "arcs": [ - [ - -75, - 183, - 184, - 185, - 186, - 187 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Côte d'Ivoire", - "NAME_LONG": "Côte d'Ivoire", - "ABBREV": "I.C.", - "FORMAL_EN": "Republic of Ivory Coast", - "POP_EST": 24184810, - "POP_RANK": 15, - "GDP_MD_EST": 87120, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CI", - "ISO_A3": "CIV", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -127, - 188, - 189, - 190, - 191, - 192, - 193, - 194 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Cameroon", - "NAME_LONG": "Cameroon", - "ABBREV": "Cam.", - "FORMAL_EN": "Republic of Cameroon", - "POP_EST": 24994885, - "POP_RANK": 15, - "GDP_MD_EST": 77240, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CM", - "ISO_A3": "CMR", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - -9, - 195, - -13, - 196, - -125, - 197, - 198, - 199, - -60, - 200, - 201 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Dem. Rep. Congo", - "NAME_LONG": "Democratic Republic of the Congo", - "ABBREV": "D.R.C.", - "FORMAL_EN": "Democratic Republic of the Congo", - "POP_EST": 83301151, - "POP_RANK": 16, - "GDP_MD_EST": 66010, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CD", - "ISO_A3": "COD", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - -12, - 202, - 203, - -189, - -126, - -197 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Congo", - "NAME_LONG": "Republic of the Congo", - "ABBREV": "Rep. Congo", - "FORMAL_EN": "Republic of the Congo", - "POP_EST": 4954674, - "POP_RANK": 12, - "GDP_MD_EST": 30270, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CG", - "ISO_A3": "COG", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - -107, - 204, - 205, - 206, - 207, - 208, - 209 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Colombia", - "NAME_LONG": "Colombia", - "ABBREV": "Col.", - "FORMAL_EN": "Republic of Colombia", - "POP_EST": 47698524, - "POP_RANK": 15, - "GDP_MD_EST": 688000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CO", - "ISO_A3": "COL", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - 210, - 211, - 212, - 213 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Costa Rica", - "NAME_LONG": "Costa Rica", - "ABBREV": "C.R.", - "FORMAL_EN": "Republic of Costa Rica", - "POP_EST": 4930258, - "POP_RANK": 12, - "GDP_MD_EST": 79260, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CR", - "ISO_A3": "CRI", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - 214 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Cuba", - "NAME_LONG": "Cuba", - "ABBREV": "Cuba", - "FORMAL_EN": "Republic of Cuba", - "POP_EST": 11147407, - "POP_RANK": 14, - "GDP_MD_EST": 132900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CU", - "ISO_A3": "CUB", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Caribbean" - } - }, - { - "arcs": [ - [ - 215, - 216 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "N. Cyprus", - "NAME_LONG": "Northern Cyprus", - "ABBREV": "N. Cy.", - "FORMAL_EN": "Turkish Republic of Northern Cyprus", - "POP_EST": 265100, - "POP_RANK": 10, - "GDP_MD_EST": 3600, - "POP_YEAR": 2013, - "GDP_YEAR": 2013, - "ISO_A2": "-99", - "ISO_A3": "-99", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -217, - 217 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Cyprus", - "NAME_LONG": "Cyprus", - "ABBREV": "Cyp.", - "FORMAL_EN": "Republic of Cyprus", - "POP_EST": 1221549, - "POP_RANK": 12, - "GDP_MD_EST": 29260, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CY", - "ISO_A3": "CYP", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -53, - 218, - 219, - 220 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Czechia", - "NAME_LONG": "Czech Republic", - "ABBREV": "Cz.", - "FORMAL_EN": "Czech Republic", - "POP_EST": 10674723, - "POP_RANK": 14, - "GDP_MD_EST": 350900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "CZ", - "ISO_A3": "CZE", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - -52, - -163, - 221, - 222, - -63, - 223, - 224, - 225, - 226, - 227, - -219 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Germany", - "NAME_LONG": "Germany", - "ABBREV": "Ger.", - "FORMAL_EN": "Federal Republic of Germany", - "POP_EST": 80594017, - "POP_RANK": 16, - "GDP_MD_EST": 3979000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "DE", - "ISO_A3": "DEU", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Western Europe" - } - }, - { - "arcs": [ - [ - 228, - 229, - 230, - 231 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Djibouti", - "NAME_LONG": "Djibouti", - "ABBREV": "Dji.", - "FORMAL_EN": "Republic of Djibouti", - "POP_EST": 865267, - "POP_RANK": 11, - "GDP_MD_EST": 3345, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "DJ", - "ISO_A3": "DJI", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - [ - -226, - 232 - ] - ], - [ - [ - 233 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Denmark", - "NAME_LONG": "Denmark", - "ABBREV": "Den.", - "FORMAL_EN": "Kingdom of Denmark", - "POP_EST": 5605948, - "POP_RANK": 13, - "GDP_MD_EST": 264800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "DK", - "ISO_A3": "DNK", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - 234, - 235 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Dominican Rep.", - "NAME_LONG": "Dominican Republic", - "ABBREV": "Dom. Rep.", - "FORMAL_EN": "Dominican Republic", - "POP_EST": 10734247, - "POP_RANK": 14, - "GDP_MD_EST": 161900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "DO", - "ISO_A3": "DOM", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Caribbean" - } - }, - { - "arcs": [ - [ - 236, - 237, - 238, - 239, - 240, - 241, - 242, - 243 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Algeria", - "NAME_LONG": "Algeria", - "ABBREV": "Alg.", - "FORMAL_EN": "People's Democratic Republic of Algeria", - "POP_EST": 40969443, - "POP_RANK": 15, - "GDP_MD_EST": 609400, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "DZ", - "ISO_A3": "DZA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Northern Africa" - } - }, - { - "arcs": [ - [ - -206, - 244, - 245 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Ecuador", - "NAME_LONG": "Ecuador", - "ABBREV": "Ecu.", - "FORMAL_EN": "Republic of Ecuador", - "POP_EST": 16290913, - "POP_RANK": 14, - "GDP_MD_EST": 182400, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "EC", - "ISO_A3": "ECU", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - 246, - 247, - 248, - 249, - 250 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Egypt", - "NAME_LONG": "Egypt", - "ABBREV": "Egypt", - "FORMAL_EN": "Arab Republic of Egypt", - "POP_EST": 97041072, - "POP_RANK": 16, - "GDP_MD_EST": 1105000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "EG", - "ISO_A3": "EGY", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Northern Africa" - } - }, - { - "arcs": [ - [ - -232, - 251, - 252, - 253 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Eritrea", - "NAME_LONG": "Eritrea", - "ABBREV": "Erit.", - "FORMAL_EN": "State of Eritrea", - "POP_EST": 5918919, - "POP_RANK": 13, - "GDP_MD_EST": 9169, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ER", - "ISO_A3": "ERI", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - 254, - 255, - 256, - 257 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Spain", - "NAME_LONG": "Spain", - "ABBREV": "Sp.", - "FORMAL_EN": "Kingdom of Spain", - "POP_EST": 48958159, - "POP_RANK": 15, - "GDP_MD_EST": 1690000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ES", - "ISO_A3": "ESP", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - 258, - 259, - 260 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Estonia", - "NAME_LONG": "Estonia", - "ABBREV": "Est.", - "FORMAL_EN": "Republic of Estonia", - "POP_EST": 1251581, - "POP_RANK": 12, - "GDP_MD_EST": 38700, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "EE", - "ISO_A3": "EST", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - -231, - 261, - 262, - 263, - 264, - 265, - -252 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Ethiopia", - "NAME_LONG": "Ethiopia", - "ABBREV": "Eth.", - "FORMAL_EN": "Federal Democratic Republic of Ethiopia", - "POP_EST": 105350020, - "POP_RANK": 17, - "GDP_MD_EST": 174700, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ET", - "ISO_A3": "ETH", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - 266, - 267, - 268, - 269 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Finland", - "NAME_LONG": "Finland", - "ABBREV": "Fin.", - "FORMAL_EN": "Republic of Finland", - "POP_EST": 5491218, - "POP_RANK": 13, - "GDP_MD_EST": 224137, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "FI", - "ISO_A3": "FIN", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - [ - 270 - ] - ], - [ - [ - 271 - ] - ], - [ - [ - 272 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Fiji", - "NAME_LONG": "Fiji", - "ABBREV": "Fiji", - "FORMAL_EN": "Republic of Fiji", - "POP_EST": 920938, - "POP_RANK": 11, - "GDP_MD_EST": 8374, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "FJ", - "ISO_A3": "FJI", - "CONTINENT": "Oceania", - "REGION_UN": "Oceania", - "SUBREGION": "Melanesia" - } - }, - { - "arcs": [ - [ - 273 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Falkland Is.", - "NAME_LONG": "Falkland Islands", - "ABBREV": "Flk. Is.", - "FORMAL_EN": "Falkland Islands", - "POP_EST": 2931, - "POP_RANK": 4, - "GDP_MD_EST": 281.8, - "POP_YEAR": 2014, - "GDP_YEAR": 2012, - "ISO_A2": "FK", - "ISO_A3": "FLK", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - [ - -65, - 274, - -222, - -162, - 275, - 276, - -256, - 277 - ] - ], - [ - [ - -111, - 278, - 279 - ] - ], - [ - [ - 280 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "France", - "NAME_LONG": "France", - "ABBREV": "Fr.", - "FORMAL_EN": "French Republic", - "POP_EST": 67106161, - "POP_RANK": 16, - "GDP_MD_EST": 2699000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "FR", - "ISO_A3": "FRA", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Western Europe" - } - }, - { - "arcs": [ - [ - -190, - -204, - 281, - 282 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Gabon", - "NAME_LONG": "Gabon", - "ABBREV": "Gabon", - "FORMAL_EN": "Gabonese Republic", - "POP_EST": 1772255, - "POP_RANK": 12, - "GDP_MD_EST": 35980, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GA", - "ISO_A3": "GAB", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - [ - 283, - 284 - ] - ], - [ - [ - 285 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "United Kingdom", - "NAME_LONG": "United Kingdom", - "ABBREV": "U.K.", - "FORMAL_EN": "United Kingdom of Great Britain and Northern Ireland", - "POP_EST": 64769452, - "POP_RANK": 16, - "GDP_MD_EST": 2788000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GB", - "ISO_A3": "GBR", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - -32, - 286, - 287, - 288, - -55 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Georgia", - "NAME_LONG": "Georgia", - "ABBREV": "Geo.", - "FORMAL_EN": "Georgia", - "POP_EST": 4926330, - "POP_RANK": 12, - "GDP_MD_EST": 37270, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GE", - "ISO_A3": "GEO", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -74, - 289, - 290, - -184 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Ghana", - "NAME_LONG": "Ghana", - "ABBREV": "Ghana", - "FORMAL_EN": "Republic of Ghana", - "POP_EST": 27499924, - "POP_RANK": 15, - "GDP_MD_EST": 120800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GH", - "ISO_A3": "GHA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -187, - 291, - 292, - 293, - 294, - 295, - 296 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Guinea", - "NAME_LONG": "Guinea", - "ABBREV": "Gin.", - "FORMAL_EN": "Republic of Guinea", - "POP_EST": 12413867, - "POP_RANK": 14, - "GDP_MD_EST": 16080, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GN", - "ISO_A3": "GIN", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - 297, - 298 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Gambia", - "NAME_LONG": "The Gambia", - "ABBREV": "Gambia", - "FORMAL_EN": "Republic of the Gambia", - "POP_EST": 2051363, - "POP_RANK": 12, - "GDP_MD_EST": 3387, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GM", - "ISO_A3": "GMB", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -295, - 299, - 300 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Guinea-Bissau", - "NAME_LONG": "Guinea-Bissau", - "ABBREV": "GnB.", - "FORMAL_EN": "Republic of Guinea-Bissau", - "POP_EST": 1792338, - "POP_RANK": 12, - "GDP_MD_EST": 2851, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GW", - "ISO_A3": "GNB", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -191, - -283, - 301 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Eq. Guinea", - "NAME_LONG": "Equatorial Guinea", - "ABBREV": "Eq. G.", - "FORMAL_EN": "Republic of Equatorial Guinea", - "POP_EST": 778358, - "POP_RANK": 11, - "GDP_MD_EST": 31770, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GQ", - "ISO_A3": "GNQ", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - [ - -14, - 302, - -84, - 303, - 304 - ] - ], - [ - [ - 305 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Greece", - "NAME_LONG": "Greece", - "ABBREV": "Greece", - "FORMAL_EN": "Hellenic Republic", - "POP_EST": 10768477, - "POP_RANK": 14, - "GDP_MD_EST": 290500, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GR", - "ISO_A3": "GRC", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - 306 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Greenland", - "NAME_LONG": "Greenland", - "ABBREV": "Grlnd.", - "FORMAL_EN": "Greenland", - "POP_EST": 57713, - "POP_RANK": 8, - "GDP_MD_EST": 2173, - "POP_YEAR": 2017, - "GDP_YEAR": 2015, - "ISO_A2": "GL", - "ISO_A3": "GRL", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Northern America" - } - }, - { - "arcs": [ - [ - -100, - 307, - 308, - 309, - 310, - 311 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Guatemala", - "NAME_LONG": "Guatemala", - "ABBREV": "Guat.", - "FORMAL_EN": "Republic of Guatemala", - "POP_EST": 15460732, - "POP_RANK": 14, - "GDP_MD_EST": 131800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GT", - "ISO_A3": "GTM", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - -109, - 312, - 313, - 314 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Guyana", - "NAME_LONG": "Guyana", - "ABBREV": "Guy.", - "FORMAL_EN": "Co-operative Republic of Guyana", - "POP_EST": 737718, - "POP_RANK": 11, - "GDP_MD_EST": 6093, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "GY", - "ISO_A3": "GUY", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - -309, - 315, - 316, - 317, - 318 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Honduras", - "NAME_LONG": "Honduras", - "ABBREV": "Hond.", - "FORMAL_EN": "Republic of Honduras", - "POP_EST": 9038741, - "POP_RANK": 13, - "GDP_MD_EST": 43190, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "HN", - "ISO_A3": "HND", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - -91, - 319, - 320, - 321, - 322, - 323 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Croatia", - "NAME_LONG": "Croatia", - "ABBREV": "Cro.", - "FORMAL_EN": "Republic of Croatia", - "POP_EST": 4292095, - "POP_RANK": 12, - "GDP_MD_EST": 94240, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "HR", - "ISO_A3": "HRV", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - -236, - 324 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Haiti", - "NAME_LONG": "Haiti", - "ABBREV": "Haiti", - "FORMAL_EN": "Republic of Haiti", - "POP_EST": 10646714, - "POP_RANK": 14, - "GDP_MD_EST": 19340, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "HT", - "ISO_A3": "HTI", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Caribbean" - } - }, - { - "arcs": [ - [ - -48, - 325, - 326, - 327, - 328, - -323, - 329 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Hungary", - "NAME_LONG": "Hungary", - "ABBREV": "Hun.", - "FORMAL_EN": "Republic of Hungary", - "POP_EST": 9850845, - "POP_RANK": 13, - "GDP_MD_EST": 267600, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "HU", - "ISO_A3": "HUN", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - [ - 330 - ] - ], - [ - [ - 331, - 332 - ] - ], - [ - [ - 333 - ] - ], - [ - [ - 334 - ] - ], - [ - [ - 335 - ] - ], - [ - [ - 336 - ] - ], - [ - [ - 337 - ] - ], - [ - [ - 338 - ] - ], - [ - [ - 339, - 340 - ] - ], - [ - [ - 341 - ] - ], - [ - [ - 342 - ] - ], - [ - [ - 343, - 344 - ] - ], - [ - [ - 345 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Indonesia", - "NAME_LONG": "Indonesia", - "ABBREV": "Indo.", - "FORMAL_EN": "Republic of Indonesia", - "POP_EST": 260580739, - "POP_RANK": 17, - "GDP_MD_EST": 3028000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ID", - "ISO_A3": "IDN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - -80, - 346, - 347, - -181, - 348, - -179, - -116, - -178, - 349 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "India", - "NAME_LONG": "India", - "ABBREV": "India", - "FORMAL_EN": "Republic of India", - "POP_EST": 1281935911, - "POP_RANK": 18, - "GDP_MD_EST": 8721000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "IN", - "ISO_A3": "IND", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - -284, - 350 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Ireland", - "NAME_LONG": "Ireland", - "ABBREV": "Ire.", - "FORMAL_EN": "Ireland", - "POP_EST": 5011102, - "POP_RANK": 13, - "GDP_MD_EST": 322000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "IE", - "ISO_A3": "IRL", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - -6, - 351, - 352, - 353, - 354, - -59, - -34, - -58, - 355, - 356 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Iran", - "NAME_LONG": "Iran", - "ABBREV": "Iran", - "FORMAL_EN": "Islamic Republic of Iran", - "POP_EST": 82021564, - "POP_RANK": 16, - "GDP_MD_EST": 1459000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "IR", - "ISO_A3": "IRN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - -354, - 357, - 358, - 359, - 360, - 361, - 362 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Iraq", - "NAME_LONG": "Iraq", - "ABBREV": "Iraq", - "FORMAL_EN": "Republic of Iraq", - "POP_EST": 39192111, - "POP_RANK": 15, - "GDP_MD_EST": 596700, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "IQ", - "ISO_A3": "IRQ", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - 363 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Iceland", - "NAME_LONG": "Iceland", - "ABBREV": "Iceland", - "FORMAL_EN": "Republic of Iceland", - "POP_EST": 339747, - "POP_RANK": 10, - "GDP_MD_EST": 16150, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "IS", - "ISO_A3": "ISL", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - 364, - 365, - 366, - 367, - 368, - 369, - -250 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Israel", - "NAME_LONG": "Israel", - "ABBREV": "Isr.", - "FORMAL_EN": "State of Israel", - "POP_EST": 8299706, - "POP_RANK": 13, - "GDP_MD_EST": 297000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "IL", - "ISO_A3": "ISR", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - [ - -50, - 370, - 371, - -276, - -161 - ] - ], - [ - [ - 372 - ] - ], - [ - [ - 373 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Italy", - "NAME_LONG": "Italy", - "ABBREV": "Italy", - "FORMAL_EN": "Italian Republic", - "POP_EST": 62137802, - "POP_RANK": 16, - "GDP_MD_EST": 2221000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "IT", - "ISO_A3": "ITA", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - 374 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Jamaica", - "NAME_LONG": "Jamaica", - "ABBREV": "Jam.", - "FORMAL_EN": "Jamaica", - "POP_EST": 2990561, - "POP_RANK": 12, - "GDP_MD_EST": 25390, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "JM", - "ISO_A3": "JAM", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Caribbean" - } - }, - { - "arcs": [ - [ - -361, - 375, - 376, - -370, - 377, - -368, - 378 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Jordan", - "NAME_LONG": "Jordan", - "ABBREV": "Jord.", - "FORMAL_EN": "Hashemite Kingdom of Jordan", - "POP_EST": 10248069, - "POP_RANK": 14, - "GDP_MD_EST": 86190, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "JO", - "ISO_A3": "JOR", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - [ - 379 - ] - ], - [ - [ - 380 - ] - ], - [ - [ - 381 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Japan", - "NAME_LONG": "Japan", - "ABBREV": "Japan", - "FORMAL_EN": "Japan", - "POP_EST": 126451398, - "POP_RANK": 17, - "GDP_MD_EST": 4932000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "JP", - "ISO_A3": "JPN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Eastern Asia" - } - }, - { - "arcs": [ - [ - -169, - 382, - 383, - 384, - 385, - 386 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Kazakhstan", - "NAME_LONG": "Kazakhstan", - "ABBREV": "Kaz.", - "FORMAL_EN": "Republic of Kazakhstan", - "POP_EST": 18556698, - "POP_RANK": 14, - "GDP_MD_EST": 460700, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "KZ", - "ISO_A3": "KAZ", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Central Asia" - } - }, - { - "arcs": [ - [ - -264, - 387, - 388, - 389, - 390, - 391 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Kenya", - "NAME_LONG": "Kenya", - "ABBREV": "Ken.", - "FORMAL_EN": "Republic of Kenya", - "POP_EST": 47615739, - "POP_RANK": 15, - "GDP_MD_EST": 152700, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "KE", - "ISO_A3": "KEN", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -168, - 392, - 393, - -383 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Kyrgyzstan", - "NAME_LONG": "Kyrgyzstan", - "ABBREV": "Kgz.", - "FORMAL_EN": "Kyrgyz Republic", - "POP_EST": 5789122, - "POP_RANK": 13, - "GDP_MD_EST": 21010, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "KG", - "ISO_A3": "KGZ", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Central Asia" - } - }, - { - "arcs": [ - [ - 394, - 395, - 396, - 397 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Cambodia", - "NAME_LONG": "Cambodia", - "ABBREV": "Camb.", - "FORMAL_EN": "Kingdom of Cambodia", - "POP_EST": 16204486, - "POP_RANK": 14, - "GDP_MD_EST": 58940, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "KH", - "ISO_A3": "KHM", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - 398, - 399 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "South Korea", - "NAME_LONG": "Republic of Korea", - "ABBREV": "S.K.", - "FORMAL_EN": "Republic of Korea", - "POP_EST": 51181299, - "POP_RANK": 16, - "GDP_MD_EST": 1929000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "KR", - "ISO_A3": "KOR", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Eastern Asia" - } - }, - { - "arcs": [ - [ - -17, - 400, - 401, - 402 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Kosovo", - "NAME_LONG": "Kosovo", - "ABBREV": "Kos.", - "FORMAL_EN": "Republic of Kosovo", - "POP_EST": 1895250, - "POP_RANK": 12, - "GDP_MD_EST": 18490, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "XK", - "ISO_A3": "-99", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - -359, - 403, - 404 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Kuwait", - "NAME_LONG": "Kuwait", - "ABBREV": "Kwt.", - "FORMAL_EN": "State of Kuwait", - "POP_EST": 2875422, - "POP_RANK": 12, - "GDP_MD_EST": 301100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "KW", - "ISO_A3": "KWT", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -176, - 405, - -396, - 406, - 407 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Laos", - "NAME_LONG": "Lao PDR", - "ABBREV": "Laos", - "FORMAL_EN": "Lao People's Democratic Republic", - "POP_EST": 7126706, - "POP_RANK": 13, - "GDP_MD_EST": 40960, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LA", - "ISO_A3": "LAO", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - -366, - 408, - 409 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Lebanon", - "NAME_LONG": "Lebanon", - "ABBREV": "Leb.", - "FORMAL_EN": "Lebanese Republic", - "POP_EST": 6229794, - "POP_RANK": 13, - "GDP_MD_EST": 85160, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LB", - "ISO_A3": "LBN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -186, - 410, - 411, - -292 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Liberia", - "NAME_LONG": "Liberia", - "ABBREV": "Liberia", - "FORMAL_EN": "Republic of Liberia", - "POP_EST": 4689021, - "POP_RANK": 12, - "GDP_MD_EST": 3881, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LR", - "ISO_A3": "LBR", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -243, - 412, - 413, - -248, - 414, - 415, - 416 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Libya", - "NAME_LONG": "Libya", - "ABBREV": "Libya", - "FORMAL_EN": "Libya", - "POP_EST": 6653210, - "POP_RANK": 13, - "GDP_MD_EST": 90890, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LY", - "ISO_A3": "LBY", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Northern Africa" - } - }, - { - "arcs": [ - [ - 417 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Sri Lanka", - "NAME_LONG": "Sri Lanka", - "ABBREV": "Sri L.", - "FORMAL_EN": "Democratic Socialist Republic of Sri Lanka", - "POP_EST": 22409381, - "POP_RANK": 15, - "GDP_MD_EST": 236700, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LK", - "ISO_A3": "LKA", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - 418 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Lesotho", - "NAME_LONG": "Lesotho", - "ABBREV": "Les.", - "FORMAL_EN": "Kingdom of Lesotho", - "POP_EST": 1958042, - "POP_RANK": 12, - "GDP_MD_EST": 6019, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LS", - "ISO_A3": "LSO", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Southern Africa" - } - }, - { - "arcs": [ - [ - -93, - 419, - 420, - 421, - 422 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Lithuania", - "NAME_LONG": "Lithuania", - "ABBREV": "Lith.", - "FORMAL_EN": "Republic of Lithuania", - "POP_EST": 2823859, - "POP_RANK": 12, - "GDP_MD_EST": 85620, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LT", - "ISO_A3": "LTU", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - -64, - -223, - -275 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Luxembourg", - "NAME_LONG": "Luxembourg", - "ABBREV": "Lux.", - "FORMAL_EN": "Grand Duchy of Luxembourg", - "POP_EST": 594130, - "POP_RANK": 11, - "GDP_MD_EST": 58740, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LU", - "ISO_A3": "LUX", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Western Europe" - } - }, - { - "arcs": [ - [ - -94, - -423, - 423, - -261, - 424 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Latvia", - "NAME_LONG": "Latvia", - "ABBREV": "Lat.", - "FORMAL_EN": "Republic of Latvia", - "POP_EST": 1944643, - "POP_RANK": 12, - "GDP_MD_EST": 50650, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "LV", - "ISO_A3": "LVA", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - -240, - 425, - 426 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Morocco", - "NAME_LONG": "Morocco", - "ABBREV": "Mor.", - "FORMAL_EN": "Kingdom of Morocco", - "POP_EST": 33986655, - "POP_RANK": 15, - "GDP_MD_EST": 282800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MA", - "ISO_A3": "MAR", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Northern Africa" - } - }, - { - "arcs": [ - [ - 427, - 428 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Moldova", - "NAME_LONG": "Moldova", - "ABBREV": "Mda.", - "FORMAL_EN": "Republic of Moldova", - "POP_EST": 3474121, - "POP_RANK": 12, - "GDP_MD_EST": 18540, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MD", - "ISO_A3": "MDA", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - 429 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Madagascar", - "NAME_LONG": "Madagascar", - "ABBREV": "Mad.", - "FORMAL_EN": "Republic of Madagascar", - "POP_EST": 25054161, - "POP_RANK": 15, - "GDP_MD_EST": 36860, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MG", - "ISO_A3": "MDG", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -98, - -312, - 430, - 431, - 432 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Mexico", - "NAME_LONG": "Mexico", - "ABBREV": "Mex.", - "FORMAL_EN": "United Mexican States", - "POP_EST": 124574795, - "POP_RANK": 17, - "GDP_MD_EST": 2307000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MX", - "ISO_A3": "MEX", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - -18, - -403, - 433, - -85, - -303 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Macedonia", - "NAME_LONG": "Macedonia", - "ABBREV": "Mkd.", - "FORMAL_EN": "Former Yugoslav Republic of Macedonia", - "POP_EST": 2103721, - "POP_RANK": 12, - "GDP_MD_EST": 29520, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MK", - "ISO_A3": "MKD", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - -76, - -188, - -297, - 434, - 435, - -237, - 436 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Mali", - "NAME_LONG": "Mali", - "ABBREV": "Mali", - "FORMAL_EN": "Republic of Mali", - "POP_EST": 17885245, - "POP_RANK": 14, - "GDP_MD_EST": 38090, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ML", - "ISO_A3": "MLI", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -78, - -350, - -177, - -408, - 437, - 438 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Myanmar", - "NAME_LONG": "Myanmar", - "ABBREV": "Myan.", - "FORMAL_EN": "Republic of the Union of Myanmar", - "POP_EST": 55123814, - "POP_RANK": 16, - "GDP_MD_EST": 311100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MM", - "ISO_A3": "MMR", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - -16, - 439, - -320, - -90, - 440, - -401 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Montenegro", - "NAME_LONG": "Montenegro", - "ABBREV": "Mont.", - "FORMAL_EN": "Montenegro", - "POP_EST": 642550, - "POP_RANK": 11, - "GDP_MD_EST": 10610, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ME", - "ISO_A3": "MNE", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - -171, - 441 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Mongolia", - "NAME_LONG": "Mongolia", - "ABBREV": "Mong.", - "FORMAL_EN": "Mongolia", - "POP_EST": 3068243, - "POP_RANK": 12, - "GDP_MD_EST": 37000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MN", - "ISO_A3": "MNG", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Eastern Asia" - } - }, - { - "arcs": [ - [ - 442, - 443, - 444, - 445, - 446, - 447, - 448, - 449 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Mozambique", - "NAME_LONG": "Mozambique", - "ABBREV": "Moz.", - "FORMAL_EN": "Republic of Mozambique", - "POP_EST": 26573706, - "POP_RANK": 15, - "GDP_MD_EST": 35010, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MZ", - "ISO_A3": "MOZ", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -238, - -436, - 450, - 451, - 452 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Mauritania", - "NAME_LONG": "Mauritania", - "ABBREV": "Mrt.", - "FORMAL_EN": "Islamic Republic of Mauritania", - "POP_EST": 3758571, - "POP_RANK": 12, - "GDP_MD_EST": 16710, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MR", - "ISO_A3": "MRT", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -450, - 453, - 454 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Malawi", - "NAME_LONG": "Malawi", - "ABBREV": "Mal.", - "FORMAL_EN": "Republic of Malawi", - "POP_EST": 19196246, - "POP_RANK": 14, - "GDP_MD_EST": 21200, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MW", - "ISO_A3": "MWI", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - [ - -115, - 455, - -344, - 456 - ] - ], - [ - [ - 457, - 458 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Malaysia", - "NAME_LONG": "Malaysia", - "ABBREV": "Malay.", - "FORMAL_EN": "Malaysia", - "POP_EST": 31381992, - "POP_RANK": 15, - "GDP_MD_EST": 863000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "MY", - "ISO_A3": "MYS", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - -7, - 459, - -119, - 460, - 461 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Namibia", - "NAME_LONG": "Namibia", - "ABBREV": "Nam.", - "FORMAL_EN": "Republic of Namibia", - "POP_EST": 2484780, - "POP_RANK": 12, - "GDP_MD_EST": 25990, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NA", - "ISO_A3": "NAM", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Southern Africa" - } - }, - { - "arcs": [ - [ - 462 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "New Caledonia", - "NAME_LONG": "New Caledonia", - "ABBREV": "New C.", - "FORMAL_EN": "New Caledonia", - "POP_EST": 279070, - "POP_RANK": 10, - "GDP_MD_EST": 10770, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NC", - "ISO_A3": "NCL", - "CONTINENT": "Oceania", - "REGION_UN": "Oceania", - "SUBREGION": "Melanesia" - } - }, - { - "arcs": [ - [ - -71, - -77, - -437, - -244, - -417, - 463, - -194, - 464 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Niger", - "NAME_LONG": "Niger", - "ABBREV": "Niger", - "FORMAL_EN": "Republic of Niger", - "POP_EST": 19245344, - "POP_RANK": 14, - "GDP_MD_EST": 20150, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NE", - "ISO_A3": "NER", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -72, - -465, - -193, - 465 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Nigeria", - "NAME_LONG": "Nigeria", - "ABBREV": "Nigeria", - "FORMAL_EN": "Federal Republic of Nigeria", - "POP_EST": 190632261, - "POP_RANK": 17, - "GDP_MD_EST": 1089000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NG", - "ISO_A3": "NGA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -212, - 466, - -317, - 467 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Nicaragua", - "NAME_LONG": "Nicaragua", - "ABBREV": "Nic.", - "FORMAL_EN": "Republic of Nicaragua", - "POP_EST": 6025951, - "POP_RANK": 13, - "GDP_MD_EST": 33550, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NI", - "ISO_A3": "NIC", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - -67, - 468, - -224 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Netherlands", - "NAME_LONG": "Netherlands", - "ABBREV": "Neth.", - "FORMAL_EN": "Kingdom of the Netherlands", - "POP_EST": 17084719, - "POP_RANK": 14, - "GDP_MD_EST": 870800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NL", - "ISO_A3": "NLD", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Western Europe" - } - }, - { - "arcs": [ - [ - [ - -268, - 469, - 470, - 471 - ] - ], - [ - [ - 472 - ] - ], - [ - [ - 473 - ] - ], - [ - [ - 474 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Norway", - "NAME_LONG": "Norway", - "ABBREV": "Nor.", - "FORMAL_EN": "Kingdom of Norway", - "POP_EST": 5320045, - "POP_RANK": 13, - "GDP_MD_EST": 364700, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NO", - "ISO_A3": "NOR", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - -180, - -349 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Nepal", - "NAME_LONG": "Nepal", - "ABBREV": "Nepal", - "FORMAL_EN": "Nepal", - "POP_EST": 29384297, - "POP_RANK": 15, - "GDP_MD_EST": 71520, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NP", - "ISO_A3": "NPL", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - [ - 475 - ] - ], - [ - [ - 476 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "New Zealand", - "NAME_LONG": "New Zealand", - "ABBREV": "N.Z.", - "FORMAL_EN": "New Zealand", - "POP_EST": 4510327, - "POP_RANK": 12, - "GDP_MD_EST": 174800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "NZ", - "ISO_A3": "NZL", - "CONTINENT": "Oceania", - "REGION_UN": "Oceania", - "SUBREGION": "Australia and New Zealand" - } - }, - { - "arcs": [ - [ - [ - -20, - 477 - ] - ], - [ - [ - -22, - 478, - 479, - 480 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Oman", - "NAME_LONG": "Oman", - "ABBREV": "Oman", - "FORMAL_EN": "Sultanate of Oman", - "POP_EST": 3424386, - "POP_RANK": 12, - "GDP_MD_EST": 173100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "OM", - "ISO_A3": "OMN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -5, - -182, - -348, - 481, - -352 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Pakistan", - "NAME_LONG": "Pakistan", - "ABBREV": "Pak.", - "FORMAL_EN": "Islamic Republic of Pakistan", - "POP_EST": 204924861, - "POP_RANK": 17, - "GDP_MD_EST": 988200, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PK", - "ISO_A3": "PAK", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Southern Asia" - } - }, - { - "arcs": [ - [ - -208, - 482, - -214, - 483 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Panama", - "NAME_LONG": "Panama", - "ABBREV": "Pan.", - "FORMAL_EN": "Republic of Panama", - "POP_EST": 3753142, - "POP_RANK": 12, - "GDP_MD_EST": 93120, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PA", - "ISO_A3": "PAN", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - -102, - -166, - 484, - -245, - -205, - -106 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Peru", - "NAME_LONG": "Peru", - "ABBREV": "Peru", - "FORMAL_EN": "Republic of Peru", - "POP_EST": 31036656, - "POP_RANK": 15, - "GDP_MD_EST": 410400, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PE", - "ISO_A3": "PER", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - [ - 485 - ] - ], - [ - [ - 486 - ] - ], - [ - [ - 487 - ] - ], - [ - [ - 488 - ] - ], - [ - [ - 489 - ] - ], - [ - [ - 490 - ] - ], - [ - [ - 491 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Philippines", - "NAME_LONG": "Philippines", - "ABBREV": "Phil.", - "FORMAL_EN": "Republic of the Philippines", - "POP_EST": 104256076, - "POP_RANK": 17, - "GDP_MD_EST": 801900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PH", - "ISO_A3": "PHL", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - [ - -340, - 492 - ] - ], - [ - [ - 493 - ] - ], - [ - [ - 494 - ] - ], - [ - [ - 495 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Papua New Guinea", - "NAME_LONG": "Papua New Guinea", - "ABBREV": "P.N.G.", - "FORMAL_EN": "Independent State of Papua New Guinea", - "POP_EST": 6909701, - "POP_RANK": 13, - "GDP_MD_EST": 28020, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PG", - "ISO_A3": "PNG", - "CONTINENT": "Oceania", - "REGION_UN": "Oceania", - "SUBREGION": "Melanesia" - } - }, - { - "arcs": [ - [ - -97, - 496, - 497, - -220, - -228, - 498, - 499, - -420 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Poland", - "NAME_LONG": "Poland", - "ABBREV": "Pol.", - "FORMAL_EN": "Republic of Poland", - "POP_EST": 38476269, - "POP_RANK": 15, - "GDP_MD_EST": 1052000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PL", - "ISO_A3": "POL", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - 500 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Puerto Rico", - "NAME_LONG": "Puerto Rico", - "ABBREV": "P.R.", - "FORMAL_EN": "Commonwealth of Puerto Rico", - "POP_EST": 3351827, - "POP_RANK": 12, - "GDP_MD_EST": 131000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PR", - "ISO_A3": "PRI", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Caribbean" - } - }, - { - "arcs": [ - [ - -173, - 501, - 502, - -400, - 503 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "North Korea", - "NAME_LONG": "Dem. Rep. Korea", - "ABBREV": "N.K.", - "FORMAL_EN": "Democratic People's Republic of Korea", - "POP_EST": 25248140, - "POP_RANK": 15, - "GDP_MD_EST": 40000, - "POP_YEAR": 2013, - "GDP_YEAR": 2016, - "ISO_A2": "KP", - "ISO_A3": "PRK", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Eastern Asia" - } - }, - { - "arcs": [ - [ - -258, - 504 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Portugal", - "NAME_LONG": "Portugal", - "ABBREV": "Port.", - "FORMAL_EN": "Portuguese Republic", - "POP_EST": 10839514, - "POP_RANK": 14, - "GDP_MD_EST": 297100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PT", - "ISO_A3": "PRT", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - -28, - -104, - -105 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Paraguay", - "NAME_LONG": "Paraguay", - "ABBREV": "Para.", - "FORMAL_EN": "Republic of Paraguay", - "POP_EST": 6943739, - "POP_RANK": 13, - "GDP_MD_EST": 64670, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PY", - "ISO_A3": "PRY", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - -369, - -378 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Palestine", - "NAME_LONG": "Palestine", - "ABBREV": "Pal.", - "FORMAL_EN": "West Bank and Gaza", - "POP_EST": 4543126, - "POP_RANK": 12, - "GDP_MD_EST": 21220.77, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "PS", - "ISO_A3": "PSE", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - 505, - 506 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Qatar", - "NAME_LONG": "Qatar", - "ABBREV": "Qatar", - "FORMAL_EN": "State of Qatar", - "POP_EST": 2314307, - "POP_RANK": 12, - "GDP_MD_EST": 334500, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "QA", - "ISO_A3": "QAT", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -81, - 507, - -328, - 508, - -429, - 509, - 510 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Romania", - "NAME_LONG": "Romania", - "ABBREV": "Rom.", - "FORMAL_EN": "Romania", - "POP_EST": 21529967, - "POP_RANK": 15, - "GDP_MD_EST": 441000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "RO", - "ISO_A3": "ROU", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - [ - -56, - -289, - 511, - 512, - -95, - -425, - -260, - 513, - -269, - -472, - 514, - -502, - -172, - -442, - -170, - -387, - 515 - ] - ], - [ - [ - -421, - -500, - 516 - ] - ], - [ - [ - 519 - ] - ], - [ - [ - 520 - ] - ], - [ - [ - 521 - ] - ], - [ - [ - 522 - ] - ], - [ - [ - 523 - ] - ], - [ - [ - 524 - ] - ], - [ - [ - 525 - ] - ], - [ - [ - 526 - ] - ], - [ - [ - 527 - ] - ], - [ - [ - 528 - ] - ], - [ - [ - 529 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Russia", - "NAME_LONG": "Russian Federation", - "ABBREV": "Rus.", - "FORMAL_EN": "Russian Federation", - "POP_EST": 142257519, - "POP_RANK": 17, - "GDP_MD_EST": 3745000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "RU", - "ISO_A3": "RUS", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - -61, - -200, - 530, - 531 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Rwanda", - "NAME_LONG": "Rwanda", - "ABBREV": "Rwa.", - "FORMAL_EN": "Republic of Rwanda", - "POP_EST": 11901484, - "POP_RANK": 14, - "GDP_MD_EST": 21970, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "RW", - "ISO_A3": "RWA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -239, - -453, - 532, - -426 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "W. Sahara", - "NAME_LONG": "Western Sahara", - "ABBREV": "W. Sah.", - "FORMAL_EN": "Sahrawi Arab Democratic Republic", - "POP_EST": 603253, - "POP_RANK": 11, - "GDP_MD_EST": 906.5, - "POP_YEAR": 2017, - "GDP_YEAR": 2007, - "ISO_A2": "EH", - "ISO_A3": "ESH", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Northern Africa" - } - }, - { - "arcs": [ - [ - -23, - -481, - 533, - 534, - -376, - -360, - -405, - 535, - -507, - 536 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Saudi Arabia", - "NAME_LONG": "Saudi Arabia", - "ABBREV": "Saud.", - "FORMAL_EN": "Kingdom of Saudi Arabia", - "POP_EST": 28571770, - "POP_RANK": 15, - "GDP_MD_EST": 1731000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SA", - "ISO_A3": "SAU", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -123, - 537, - -415, - -247, - 538, - -253, - -266, - 539 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Sudan", - "NAME_LONG": "Sudan", - "ABBREV": "Sudan", - "FORMAL_EN": "Republic of the Sudan", - "POP_EST": 37345935, - "POP_RANK": 15, - "GDP_MD_EST": 176300, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SD", - "ISO_A3": "SDN", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Northern Africa" - } - }, - { - "arcs": [ - [ - -124, - -540, - -265, - -392, - 540, - -198 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "S. Sudan", - "NAME_LONG": "South Sudan", - "ABBREV": "S. Sud.", - "FORMAL_EN": "Republic of South Sudan", - "POP_EST": 13026129, - "POP_RANK": 14, - "GDP_MD_EST": 20880, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SS", - "ISO_A3": "SSD", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -296, - -301, - 541, - -299, - 542, - -451, - -435 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Senegal", - "NAME_LONG": "Senegal", - "ABBREV": "Sen.", - "FORMAL_EN": "Republic of Senegal", - "POP_EST": 14668522, - "POP_RANK": 14, - "GDP_MD_EST": 39720, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SN", - "ISO_A3": "SEN", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - [ - 543 - ] - ], - [ - [ - 544 - ] - ], - [ - [ - 545 - ] - ], - [ - [ - 546 - ] - ], - [ - [ - 547 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Solomon Is.", - "NAME_LONG": "Solomon Islands", - "ABBREV": "S. Is.", - "FORMAL_EN": "", - "POP_EST": 647581, - "POP_RANK": 11, - "GDP_MD_EST": 1198, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SB", - "ISO_A3": "SLB", - "CONTINENT": "Oceania", - "REGION_UN": "Oceania", - "SUBREGION": "Melanesia" - } - }, - { - "arcs": [ - [ - -293, - -412, - 548 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Sierra Leone", - "NAME_LONG": "Sierra Leone", - "ABBREV": "S.L.", - "FORMAL_EN": "Republic of Sierra Leone", - "POP_EST": 6163195, - "POP_RANK": 13, - "GDP_MD_EST": 10640, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SL", - "ISO_A3": "SLE", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -310, - -319, - 549 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "El Salvador", - "NAME_LONG": "El Salvador", - "ABBREV": "El. S.", - "FORMAL_EN": "Republic of El Salvador", - "POP_EST": 6172011, - "POP_RANK": 13, - "GDP_MD_EST": 54790, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SV", - "ISO_A3": "SLV", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Central America" - } - }, - { - "arcs": [ - [ - -230, - 550, - 551, - -262 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Somaliland", - "NAME_LONG": "Somaliland", - "ABBREV": "Solnd.", - "FORMAL_EN": "Republic of Somaliland", - "POP_EST": 3500000, - "POP_RANK": 12, - "GDP_MD_EST": 12250, - "POP_YEAR": 2013, - "GDP_YEAR": 2013, - "ISO_A2": "-99", - "ISO_A3": "-99", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -263, - -552, - 552, - -388 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Somalia", - "NAME_LONG": "Somalia", - "ABBREV": "Som.", - "FORMAL_EN": "Federal Republic of Somalia", - "POP_EST": 7531386, - "POP_RANK": 13, - "GDP_MD_EST": 4719, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SO", - "ISO_A3": "SOM", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -86, - -434, - -402, - -441, - -92, - -324, - -329, - -508 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Serbia", - "NAME_LONG": "Serbia", - "ABBREV": "Serb.", - "FORMAL_EN": "Republic of Serbia", - "POP_EST": 7111024, - "POP_RANK": 13, - "GDP_MD_EST": 101800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "RS", - "ISO_A3": "SRB", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - -110, - -315, - 553, - -279 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Suriname", - "NAME_LONG": "Suriname", - "ABBREV": "Sur.", - "FORMAL_EN": "Republic of Suriname", - "POP_EST": 591919, - "POP_RANK": 11, - "GDP_MD_EST": 8547, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SR", - "ISO_A3": "SUR", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - -54, - -221, - -498, - 554, - -326 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Slovakia", - "NAME_LONG": "Slovakia", - "ABBREV": "Svk.", - "FORMAL_EN": "Slovak Republic", - "POP_EST": 5445829, - "POP_RANK": 13, - "GDP_MD_EST": 168800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SK", - "ISO_A3": "SVK", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - -49, - -330, - -322, - 555, - -371 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Slovenia", - "NAME_LONG": "Slovenia", - "ABBREV": "Slo.", - "FORMAL_EN": "Republic of Slovenia", - "POP_EST": 1972126, - "POP_RANK": 12, - "GDP_MD_EST": 68350, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SI", - "ISO_A3": "SVN", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Southern Europe" - } - }, - { - "arcs": [ - [ - -267, - 556, - -470 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Sweden", - "NAME_LONG": "Sweden", - "ABBREV": "Swe.", - "FORMAL_EN": "Kingdom of Sweden", - "POP_EST": 9960487, - "POP_RANK": 13, - "GDP_MD_EST": 498100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SE", - "ISO_A3": "SWE", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Northern Europe" - } - }, - { - "arcs": [ - [ - -446, - 557 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Swaziland", - "NAME_LONG": "Swaziland", - "ABBREV": "Swz.", - "FORMAL_EN": "Kingdom of Swaziland", - "POP_EST": 1467152, - "POP_RANK": 12, - "GDP_MD_EST": 11060, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "SZ", - "ISO_A3": "SWZ", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Southern Africa" - } - }, - { - "arcs": [ - [ - -362, - -379, - -367, - -410, - 558, - 559 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Syria", - "NAME_LONG": "Syria", - "ABBREV": "Syria", - "FORMAL_EN": "Syrian Arab Republic", - "POP_EST": 18028549, - "POP_RANK": 14, - "GDP_MD_EST": 50280, - "POP_YEAR": 2017, - "GDP_YEAR": 2015, - "ISO_A2": "SY", - "ISO_A3": "SYR", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -122, - -195, - -464, - -416, - -538 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Chad", - "NAME_LONG": "Chad", - "ABBREV": "Chad", - "FORMAL_EN": "Republic of Chad", - "POP_EST": 12075985, - "POP_RANK": 14, - "GDP_MD_EST": 30590, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TD", - "ISO_A3": "TCD", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Middle Africa" - } - }, - { - "arcs": [ - [ - -69, - 560, - -290, - -73 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Togo", - "NAME_LONG": "Togo", - "ABBREV": "Togo", - "FORMAL_EN": "Togolese Republic", - "POP_EST": 7965055, - "POP_RANK": 13, - "GDP_MD_EST": 11610, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TG", - "ISO_A3": "TGO", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Western Africa" - } - }, - { - "arcs": [ - [ - -395, - 561, - -459, - 562, - -438, - -407 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Thailand", - "NAME_LONG": "Thailand", - "ABBREV": "Thai.", - "FORMAL_EN": "Kingdom of Thailand", - "POP_EST": 68414135, - "POP_RANK": 16, - "GDP_MD_EST": 1161000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TH", - "ISO_A3": "THA", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - -3, - 563, - -393, - -167 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Tajikistan", - "NAME_LONG": "Tajikistan", - "ABBREV": "Tjk.", - "FORMAL_EN": "Republic of Tajikistan", - "POP_EST": 8468555, - "POP_RANK": 13, - "GDP_MD_EST": 25810, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TJ", - "ISO_A3": "TJK", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Central Asia" - } - }, - { - "arcs": [ - [ - -1, - -357, - 564, - -385, - 565 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Turkmenistan", - "NAME_LONG": "Turkmenistan", - "ABBREV": "Turkm.", - "FORMAL_EN": "Turkmenistan", - "POP_EST": 5351277, - "POP_RANK": 13, - "GDP_MD_EST": 94720, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TM", - "ISO_A3": "TKM", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Central Asia" - } - }, - { - "arcs": [ - [ - -332, - 566 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Timor-Leste", - "NAME_LONG": "Timor-Leste", - "ABBREV": "T.L.", - "FORMAL_EN": "Democratic Republic of Timor-Leste", - "POP_EST": 1291358, - "POP_RANK": 12, - "GDP_MD_EST": 4975, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TL", - "ISO_A3": "TLS", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - 567 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Trinidad and Tobago", - "NAME_LONG": "Trinidad and Tobago", - "ABBREV": "Tr.T.", - "FORMAL_EN": "Republic of Trinidad and Tobago", - "POP_EST": 1218208, - "POP_RANK": 12, - "GDP_MD_EST": 43570, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TT", - "ISO_A3": "TTO", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Caribbean" - } - }, - { - "arcs": [ - [ - -242, - 568, - -413 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Tunisia", - "NAME_LONG": "Tunisia", - "ABBREV": "Tun.", - "FORMAL_EN": "Republic of Tunisia", - "POP_EST": 11403800, - "POP_RANK": 14, - "GDP_MD_EST": 130800, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TN", - "ISO_A3": "TUN", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Northern Africa" - } - }, - { - "arcs": [ - [ - [ - -36, - -355, - -363, - -560, - 569, - -287 - ] - ], - [ - [ - -83, - 570, - -304 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Turkey", - "NAME_LONG": "Turkey", - "ABBREV": "Tur.", - "FORMAL_EN": "Republic of Turkey", - "POP_EST": 80845215, - "POP_RANK": 16, - "GDP_MD_EST": 1670000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TR", - "ISO_A3": "TUR", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - 571 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Taiwan", - "NAME_LONG": "Taiwan", - "ABBREV": "Taiwan", - "FORMAL_EN": "", - "POP_EST": 23508428, - "POP_RANK": 15, - "GDP_MD_EST": 1127000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TW", - "ISO_A3": "TWN", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Eastern Asia" - } - }, - { - "arcs": [ - [ - -62, - -532, - 572, - -390, - 573, - -443, - -455, - 574, - -201 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Tanzania", - "NAME_LONG": "Tanzania", - "ABBREV": "Tanz.", - "FORMAL_EN": "United Republic of Tanzania", - "POP_EST": 53950935, - "POP_RANK": 16, - "GDP_MD_EST": 150600, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "TZ", - "ISO_A3": "TZA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -199, - -541, - -391, - -573, - -531 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Uganda", - "NAME_LONG": "Uganda", - "ABBREV": "Uga.", - "FORMAL_EN": "Republic of Uganda", - "POP_EST": 39570125, - "POP_RANK": 15, - "GDP_MD_EST": 84930, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "UG", - "ISO_A3": "UGA", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -96, - -513, - 575, - -518, - 576, - -510, - -428, - -509, - -327, - -555, - -497 - ], - [ - 517, - 518 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Ukraine", - "NAME_LONG": "Ukraine", - "ABBREV": "Ukr.", - "FORMAL_EN": "Ukraine", - "POP_EST": 44033874, - "POP_RANK": 15, - "GDP_MD_EST": 352600, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "UA", - "ISO_A3": "UKR", - "CONTINENT": "Europe", - "REGION_UN": "Europe", - "SUBREGION": "Eastern Europe" - } - }, - { - "arcs": [ - [ - -30, - -113, - 577 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Uruguay", - "NAME_LONG": "Uruguay", - "ABBREV": "Ury.", - "FORMAL_EN": "Oriental Republic of Uruguay", - "POP_EST": 3360148, - "POP_RANK": 12, - "GDP_MD_EST": 73250, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "UY", - "ISO_A3": "URY", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - [ - -141, - 578, - -432, - 579 - ] - ], - [ - [ - -139, - 580 - ] - ], - [ - [ - 581 - ] - ], - [ - [ - 582 - ] - ], - [ - [ - 583 - ] - ], - [ - [ - 584 - ] - ], - [ - [ - 585 - ] - ], - [ - [ - 586 - ] - ], - [ - [ - 587 - ] - ], - [ - [ - 588 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "United States of America", - "NAME_LONG": "United States", - "ABBREV": "U.S.A.", - "FORMAL_EN": "United States of America", - "POP_EST": 326625791, - "POP_RANK": 17, - "GDP_MD_EST": 18560000, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "US", - "ISO_A3": "USA", - "CONTINENT": "North America", - "REGION_UN": "Americas", - "SUBREGION": "Northern America" - } - }, - { - "arcs": [ - [ - -2, - -566, - -384, - -394, - -564 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Uzbekistan", - "NAME_LONG": "Uzbekistan", - "ABBREV": "Uzb.", - "FORMAL_EN": "Republic of Uzbekistan", - "POP_EST": 29748859, - "POP_RANK": 15, - "GDP_MD_EST": 202300, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "UZ", - "ISO_A3": "UZB", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Central Asia" - } - }, - { - "arcs": [ - [ - -108, - -210, - 589, - -313 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Venezuela", - "NAME_LONG": "Venezuela", - "ABBREV": "Ven.", - "FORMAL_EN": "Bolivarian Republic of Venezuela", - "POP_EST": 31304016, - "POP_RANK": 15, - "GDP_MD_EST": 468600, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "VE", - "ISO_A3": "VEN", - "CONTINENT": "South America", - "REGION_UN": "Americas", - "SUBREGION": "South America" - } - }, - { - "arcs": [ - [ - -175, - 590, - -397, - -406 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Vietnam", - "NAME_LONG": "Vietnam", - "ABBREV": "Viet.", - "FORMAL_EN": "Socialist Republic of Vietnam", - "POP_EST": 96160163, - "POP_RANK": 16, - "GDP_MD_EST": 594900, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "VN", - "ISO_A3": "VNM", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "South-Eastern Asia" - } - }, - { - "arcs": [ - [ - [ - 591 - ] - ], - [ - [ - 592 - ] - ] - ], - "type": "MultiPolygon", - "properties": { - "NAME": "Vanuatu", - "NAME_LONG": "Vanuatu", - "ABBREV": "Van.", - "FORMAL_EN": "Republic of Vanuatu", - "POP_EST": 282814, - "POP_RANK": 10, - "GDP_MD_EST": 723, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "VU", - "ISO_A3": "VUT", - "CONTINENT": "Oceania", - "REGION_UN": "Oceania", - "SUBREGION": "Melanesia" - } - }, - { - "arcs": [ - [ - -480, - 593, - -534 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Yemen", - "NAME_LONG": "Yemen", - "ABBREV": "Yem.", - "FORMAL_EN": "Republic of Yemen", - "POP_EST": 28036829, - "POP_RANK": 15, - "GDP_MD_EST": 73450, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "YE", - "ISO_A3": "YEM", - "CONTINENT": "Asia", - "REGION_UN": "Asia", - "SUBREGION": "Western Asia" - } - }, - { - "arcs": [ - [ - -118, - 594, - -447, - -558, - -445, - 595, - -461 - ], - [ - -419 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "South Africa", - "NAME_LONG": "South Africa", - "ABBREV": "S.Af.", - "FORMAL_EN": "Republic of South Africa", - "POP_EST": 54841552, - "POP_RANK": 16, - "GDP_MD_EST": 739100, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ZA", - "ISO_A3": "ZAF", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Southern Africa" - } - }, - { - "arcs": [ - [ - -10, - -202, - -575, - -454, - -449, - 596, - -120, - -460 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Zambia", - "NAME_LONG": "Zambia", - "ABBREV": "Zambia", - "FORMAL_EN": "Republic of Zambia", - "POP_EST": 15972000, - "POP_RANK": 14, - "GDP_MD_EST": 65170, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ZM", - "ISO_A3": "ZMB", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - }, - { - "arcs": [ - [ - -121, - -597, - -448, - -595 - ] - ], - "type": "Polygon", - "properties": { - "NAME": "Zimbabwe", - "NAME_LONG": "Zimbabwe", - "ABBREV": "Zimb.", - "FORMAL_EN": "Republic of Zimbabwe", - "POP_EST": 13805084, - "POP_RANK": 14, - "GDP_MD_EST": 28330, - "POP_YEAR": 2017, - "GDP_YEAR": 2016, - "ISO_A2": "ZW", - "ISO_A3": "ZWE", - "CONTINENT": "Africa", - "REGION_UN": "Africa", - "SUBREGION": "Eastern Africa" - } - } - ] - } - } -} diff --git a/explorer/src/components/ComponentError.tsx b/explorer/src/components/ComponentError.tsx deleted file mode 100644 index 00b448fb9eb..00000000000 --- a/explorer/src/components/ComponentError.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Typography } from '@mui/material'; -import * as React from 'react'; - -export const ComponentError: FCWithChildren<{ text: string }> = ({ text }) => ( - <Typography - sx={{ marginTop: 2, color: 'primary.main', fontSize: 10 }} - variant="body1" - data-testid="delegation-total-amount" - > - {text} - </Typography> -); diff --git a/explorer/src/components/ContentCard.tsx b/explorer/src/components/ContentCard.tsx deleted file mode 100644 index c78c719ca70..00000000000 --- a/explorer/src/components/ContentCard.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Card, CardHeader, CardContent, Typography } from '@mui/material'; -import React, { ReactEventHandler } from 'react'; - -type ContentCardProps = { - title?: React.ReactNode; - subtitle?: string; - Icon?: React.ReactNode; - Action?: React.ReactNode; - errorMsg?: string; - onClick?: ReactEventHandler; -}; - -export const ContentCard: FCWithChildren<ContentCardProps> = ({ - title, - Icon, - Action, - subtitle, - errorMsg, - children, - onClick, -}) => ( - <Card onClick={onClick} sx={{ height: '100%' }}> - {title && <CardHeader title={title || ''} avatar={Icon} action={Action} subheader={subtitle} />} - {children && <CardContent>{children}</CardContent>} - {errorMsg && ( - <Typography variant="body2" sx={{ color: 'danger', padding: 2 }}> - {errorMsg} - </Typography> - )} - </Card> -); - -ContentCard.defaultProps = { - title: undefined, - subtitle: undefined, - Icon: null, - Action: null, - errorMsg: undefined, - onClick: () => null, -}; diff --git a/explorer/src/components/CustomColumnHeading.tsx b/explorer/src/components/CustomColumnHeading.tsx deleted file mode 100644 index 1f85806fa2d..00000000000 --- a/explorer/src/components/CustomColumnHeading.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import * as React from 'react'; -import { Box, Typography } from '@mui/material'; -import { useTheme } from '@mui/material/styles'; -import { Tooltip } from '@nymproject/react/tooltip/Tooltip'; - -export const CustomColumnHeading: FCWithChildren<{ headingTitle: string; tooltipInfo?: string }> = ({ - headingTitle, - tooltipInfo, -}) => { - const theme = useTheme(); - - return ( - <Box alignItems="center" display="flex"> - {tooltipInfo && ( - <Tooltip - title={tooltipInfo} - id={headingTitle} - placement="top-start" - textColor={theme.palette.nym.networkExplorer.tooltip.color} - bgColor={theme.palette.nym.networkExplorer.tooltip.background} - maxWidth={230} - arrow - /> - )} - <Typography variant="body2" fontWeight={600} data-testid={headingTitle}> - {headingTitle} - </Typography> - </Box> - ); -}; diff --git a/explorer/src/components/Delegations/ConfirmationModal.tsx b/explorer/src/components/Delegations/ConfirmationModal.tsx deleted file mode 100644 index 8e859f5eba3..00000000000 --- a/explorer/src/components/Delegations/ConfirmationModal.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import React from 'react'; -import { - Breakpoint, - Button, - Paper, - Dialog, - DialogActions, - DialogContent, - DialogTitle, - SxProps, - Typography, -} from '@mui/material'; - -export interface ConfirmationModalProps { - open: boolean; - onConfirm: () => void; - onClose?: () => void; - children?: React.ReactNode; - title: React.ReactNode | string; - subTitle?: React.ReactNode | string; - confirmButton: React.ReactNode | string; - disabled?: boolean; - sx?: SxProps; - fullWidth?: boolean; - maxWidth?: Breakpoint; - backdropProps?: object; -} - -export const ConfirmationModal = ({ - open, - onConfirm, - onClose, - children, - title, - subTitle, - confirmButton, - disabled, - sx, - fullWidth, - maxWidth, - backdropProps, -}: ConfirmationModalProps) => { - const Title = ( - <DialogTitle id="responsive-dialog-title" sx={{ pb: 2 }}> - {title} - {subTitle && - (typeof subTitle === 'string' ? ( - <Typography fontWeight={400} variant="subtitle1" fontSize={12} color="grey"> - {subTitle} - </Typography> - ) : ( - subTitle - ))} - </DialogTitle> - ); - const ConfirmButton = - typeof confirmButton === 'string' ? ( - <Button onClick={onConfirm} variant="contained" fullWidth disabled={disabled} sx={{ py: 1.6 }}> - <Typography variant="button" fontSize="large"> - {confirmButton} - </Typography> - </Button> - ) : ( - confirmButton - ); - return ( - <Dialog - open={open} - onClose={onClose} - aria-labelledby="responsive-dialog-title" - maxWidth={maxWidth || 'sm'} - sx={{ textAlign: 'center', ...sx }} - fullWidth={fullWidth} - BackdropProps={backdropProps} - PaperComponent={Paper} - PaperProps={{ elevation: 0 }} - > - {Title} - <DialogContent>{children}</DialogContent> - <DialogActions sx={{ px: 3, pb: 3 }}>{ConfirmButton}</DialogActions> - </Dialog> - ); -}; diff --git a/explorer/src/components/Delegations/DelegateIconButton.tsx b/explorer/src/components/Delegations/DelegateIconButton.tsx deleted file mode 100644 index 36b581a010d..00000000000 --- a/explorer/src/components/Delegations/DelegateIconButton.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import * as React from 'react'; -import { Button, IconButton } from '@mui/material'; -import { SxProps } from '@mui/system'; -import { useIsMobile } from '@src/hooks'; -import { DelegateIcon } from '@src/icons/DelevateSVG'; - -export const DelegateIconButton: FCWithChildren<{ - size?: 'small' | 'medium'; - disabled?: boolean; - tooltip?: React.ReactNode; - sx?: SxProps; - onDelegate: () => void; -}> = ({ onDelegate, sx, disabled, size = 'medium' }) => { - const isMobile = useIsMobile(); - - const handleOnDelegate = () => { - onDelegate(); - }; - - if (isMobile) { - return ( - <IconButton size="small" disabled={disabled} onClick={handleOnDelegate}> - <DelegateIcon fontSize="small" /> - </IconButton> - ); - } - - return ( - <Button variant="outlined" size={size} disabled={disabled} onClick={handleOnDelegate} sx={sx}> - Delegate - </Button> - ); -}; diff --git a/explorer/src/components/Delegations/DelegateModal.tsx b/explorer/src/components/Delegations/DelegateModal.tsx deleted file mode 100644 index 3bafd1888ff..00000000000 --- a/explorer/src/components/Delegations/DelegateModal.tsx +++ /dev/null @@ -1,166 +0,0 @@ -import React, { useState } from 'react'; -import { Box, SxProps } from '@mui/material'; -import { IdentityKeyFormField } from '@nymproject/react/mixnodes/IdentityKeyFormField'; -import { CurrencyFormField } from '@nymproject/react/currency/CurrencyFormField'; -import { CurrencyDenom, DecCoin } from '@nymproject/types'; -import { useWalletContext } from '@src/context/wallet'; -import { useDelegationsContext } from '@src/context/delegations'; -import { SimpleModal } from './SimpleModal'; -import { ModalListItem } from './ModalListItem'; -import { DelegationModalProps } from './DelegationModal'; -import { validateAmount } from '../../utils/currency'; -import { urls } from '../../utils'; - -const MIN_AMOUNT_TO_DELEGATE = 10; - -export const DelegateModal: FCWithChildren<{ - mixId: number; - identityKey: string; - header?: string; - buttonText?: string; - rewardInterval?: string; - estimatedReward?: number; - profitMarginPercentage?: string | null; - nodeUptimePercentage?: number | null; - denom: CurrencyDenom; - sx?: SxProps; - backdropProps?: object; - onClose: () => void; - onOk?: (delegationModalProps: DelegationModalProps) => void; -}> = ({ mixId, identityKey, onClose, onOk, denom, sx }) => { - const [amount, setAmount] = useState<DecCoin | undefined>({ amount: '10', denom: 'nym' }); - const [isValidated, setValidated] = useState<boolean>(false); - const [errorAmount, setErrorAmount] = useState<string | undefined>(); - - const { address, balance } = useWalletContext(); - const { handleDelegate } = useDelegationsContext(); - - const validate = async () => { - let newValidatedValue = true; - let errorAmountMessage; - - if (amount && !(await validateAmount(amount.amount, '0'))) { - newValidatedValue = false; - errorAmountMessage = 'Please enter a valid amount'; - } - - if (amount && +amount.amount < MIN_AMOUNT_TO_DELEGATE) { - errorAmountMessage = `Min. delegation amount: ${MIN_AMOUNT_TO_DELEGATE} ${denom.toUpperCase()}`; - newValidatedValue = false; - } - - if (!amount?.amount.length) { - newValidatedValue = false; - } - - if (amount && balance.data && +balance.data - +amount.amount <= 0) { - errorAmountMessage = 'Not enough funds'; - newValidatedValue = false; - } - - setErrorAmount(errorAmountMessage); - setValidated(newValidatedValue); - }; - - const delegateToMixnode = async ({ - delegationMixId, - delegationAmount, - }: { - delegationMixId: number; - delegationAmount: string; - }) => { - try { - const tx = await handleDelegate(delegationMixId, delegationAmount); - return tx; - } catch (e) { - console.error('Failed to delegate to mixnode', e); - throw e; - } - }; - - const handleConfirm = async () => { - if (mixId && amount && onOk) { - onOk({ - status: 'loading', - }); - try { - if (!address) { - throw new Error('Please connect your wallet'); - } - - const tx = await delegateToMixnode({ - delegationMixId: mixId, - delegationAmount: amount.amount, - }); - - if (!tx) { - throw new Error('Failed to delegate'); - } - - onOk({ - status: 'success', - message: 'Delegation can take up to one hour to process', - transactions: [ - { url: `${urls('MAINNET').blockExplorer}/tx/${tx.transactionHash}`, hash: tx.transactionHash }, - ], - }); - } catch (e) { - console.error('Failed to delegate', e); - onOk({ - status: 'error', - message: (e as Error).message, - }); - } - } - }; - - const handleAmountChanged = (newAmount: DecCoin) => { - setAmount(newAmount); - }; - - React.useEffect(() => { - validate(); - }, [amount, identityKey, mixId]); - - return ( - <SimpleModal - open - onClose={onClose} - onOk={handleConfirm} - header="Delegate" - okLabel="Delegate" - okDisabled={!isValidated} - sx={sx} - > - <Box sx={{ mt: 3 }} gap={2}> - <IdentityKeyFormField - required - fullWidth - label="Node identity key" - onChanged={() => undefined} - initialValue={identityKey} - readOnly - showTickOnValid={false} - /> - </Box> - - <Box display="flex" gap={2} alignItems="center" sx={{ mt: 3 }}> - <CurrencyFormField - required - fullWidth - autoFocus - label="Amount" - initialValue={amount?.amount || '10'} - onChanged={handleAmountChanged} - denom={denom} - validationError={errorAmount} - /> - </Box> - <Box sx={{ mt: 3 }}> - <ModalListItem label="Account balance" value={`${balance.data} NYM`} divider fontWeight={600} /> - </Box> - - <ModalListItem label="Est. fee for this transaction will be calculated in your connected wallet" /> - </SimpleModal> - ); -}; diff --git a/explorer/src/components/Delegations/DelegationModal.tsx b/explorer/src/components/Delegations/DelegationModal.tsx deleted file mode 100644 index db5b51aefee..00000000000 --- a/explorer/src/components/Delegations/DelegationModal.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import React from 'react'; -import { Typography, SxProps, Stack } from '@mui/material'; -import { Link } from '@nymproject/react/link/Link'; -import { LoadingModal } from './LoadingModal'; -import { ConfirmationModal } from './ConfirmationModal'; -import { ErrorModal } from './ErrorModal'; - -export type DelegationModalProps = { - status: 'loading' | 'success' | 'error' | 'info'; - message?: string; - transactions?: { - url: string; - hash: string; - }[]; -}; - -export const DelegationModal: FCWithChildren< - DelegationModalProps & { - open: boolean; - onClose: () => void; - sx?: SxProps; - backdropProps?: object; - children?: React.ReactNode; - } -> = ({ status, message, transactions, open, onClose, children, sx, backdropProps }) => { - if (status === 'loading') return <LoadingModal sx={sx} backdropProps={backdropProps} />; - - if (status === 'error') { - return ( - <ErrorModal message={message} sx={sx} open={open} onClose={onClose}> - {children} - </ErrorModal> - ); - } - - if (status === 'info') { - return ( - <ConfirmationModal open={open} title="Connect wallet" confirmButton="OK" onConfirm={onClose}> - <Typography>{message}</Typography> - </ConfirmationModal> - ); - } - - return ( - <ConfirmationModal - open={open} - onConfirm={onClose || (() => {})} - title="Transaction successful" - confirmButton="Done" - > - <Stack alignItems="center" spacing={2} mb={0}> - {message && <Typography>{message}</Typography>} - {transactions?.length === 1 && ( - <Link href={transactions[0].url} target="_blank" sx={{ ml: 1 }} text="View on blockchain" noIcon /> - )} - {transactions && transactions.length > 1 && ( - <Stack alignItems="center" spacing={1}> - <Typography>View the transactions on blockchain:</Typography> - {transactions.map(({ url, hash }) => ( - <Link href={url} target="_blank" sx={{ ml: 1 }} text={hash.slice(0, 6)} key={hash} noIcon /> - ))} - </Stack> - )} - </Stack> - </ConfirmationModal> - ); -}; diff --git a/explorer/src/components/Delegations/ErrorModal.tsx b/explorer/src/components/Delegations/ErrorModal.tsx deleted file mode 100644 index b9218d1e1ea..00000000000 --- a/explorer/src/components/Delegations/ErrorModal.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; -import { Box, Button, Modal, SxProps, Typography } from '@mui/material'; -import { modalStyle } from './SimpleModal'; - -export const ErrorModal: FCWithChildren<{ - open: boolean; - title?: string; - message?: string; - sx?: SxProps; - backdropProps?: object; - onClose: () => void; - children?: React.ReactNode; -}> = ({ children, open, title, message, sx, backdropProps, onClose }) => ( - <Modal open={open} onClose={onClose} BackdropProps={backdropProps}> - <Box sx={{ ...modalStyle(), ...sx }} textAlign="center"> - <Typography color={(theme) => theme.palette.error.main} mb={1}> - {title || 'Oh no! Something went wrong...'} - </Typography> - <Typography my={5} color="text.primary" sx={{ textOverflow: 'wrap', overflowWrap: 'break-word' }}> - {message} - </Typography> - {children} - <Button variant="contained" onClick={onClose}> - Close - </Button> - </Box> - </Modal> -); diff --git a/explorer/src/components/Delegations/LoadingModal.tsx b/explorer/src/components/Delegations/LoadingModal.tsx deleted file mode 100644 index eda13938d44..00000000000 --- a/explorer/src/components/Delegations/LoadingModal.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import { Box, CircularProgress, Modal, Stack, Typography, SxProps } from '@mui/material'; -import { modalStyle } from './SimpleModal'; - -export const LoadingModal: FCWithChildren<{ - text?: string; - sx?: SxProps; - backdropProps?: object; -}> = ({ sx, text = 'Please wait...' }) => ( - <Modal open> - <Box sx={{ ...modalStyle(), ...sx }} textAlign="center"> - <Stack spacing={4} direction="row" alignItems="center"> - <CircularProgress /> - <Typography sx={{ color: 'text.primary' }}>{text}</Typography> - </Stack> - </Box> - </Modal> -); diff --git a/explorer/src/components/Delegations/ModalDivider.tsx b/explorer/src/components/Delegations/ModalDivider.tsx deleted file mode 100644 index 6258e0bfac9..00000000000 --- a/explorer/src/components/Delegations/ModalDivider.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react'; -import { Box, SxProps } from '@mui/material'; - -export const ModalDivider: FCWithChildren<{ - sx?: SxProps; -}> = ({ sx }) => <Box borderTop="1px solid" borderColor="rgba(141, 147, 153, 0.2)" my={1} sx={sx} />; diff --git a/explorer/src/components/Delegations/ModalListItem.tsx b/explorer/src/components/Delegations/ModalListItem.tsx deleted file mode 100644 index 830c25705ed..00000000000 --- a/explorer/src/components/Delegations/ModalListItem.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import { Box, Stack, SxProps, Typography, TypographyProps } from '@mui/material'; -import { ModalDivider } from './ModalDivider'; - -export const ModalListItem: FCWithChildren<{ - label: string; - divider?: boolean; - hidden?: boolean; - fontWeight?: TypographyProps['fontWeight']; - fontSize?: TypographyProps['fontSize']; - light?: boolean; - value?: React.ReactNode; - sxValue?: SxProps; -}> = ({ label, value, hidden, fontWeight, fontSize, divider, sxValue }) => ( - <Box sx={{ display: hidden ? 'none' : 'block' }}> - <Stack direction="row" justifyContent="space-between" alignItems="center"> - <Typography fontSize="smaller" fontWeight={fontWeight} sx={{ color: 'text.primary', fontSize: 14 }}> - {label} - </Typography> - {value && ( - <Typography - fontSize="smaller" - fontWeight={fontWeight} - sx={{ color: 'text.primary', fontSize: fontSize || 14, ...sxValue }} - > - {value} - </Typography> - )} - </Stack> - {divider && <ModalDivider />} - </Box> -); diff --git a/explorer/src/components/Delegations/SimpleModal.tsx b/explorer/src/components/Delegations/SimpleModal.tsx deleted file mode 100644 index 88dff4d9d78..00000000000 --- a/explorer/src/components/Delegations/SimpleModal.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import React from 'react'; -import { Box, Button, Modal, Stack, SxProps, Typography } from '@mui/material'; -import CloseIcon from '@mui/icons-material/Close'; -import ErrorOutline from '@mui/icons-material/ErrorOutline'; -import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'; -import ArrowBackIosNewIcon from '@mui/icons-material/ArrowBackIosNew'; -import { useIsMobile } from '../../hooks/useIsMobile'; - -export const modalStyle = (width: number | string = 600) => ({ - position: 'absolute' as 'absolute', - top: '50%', - left: '50%', - width, - transform: 'translate(-50%, -50%)', - bgcolor: 'background.paper', - boxShadow: 24, - borderRadius: '16px', - p: 4, -}); - -export const StyledBackButton = ({ - onBack, - label, - fullWidth, - sx, -}: { - onBack: () => void; - label?: string; - fullWidth?: boolean; - sx?: SxProps; -}) => ( - <Button disableFocusRipple size="large" fullWidth={fullWidth} variant="outlined" onClick={onBack} sx={sx}> - {label || <ArrowBackIosNewIcon fontSize="small" />} - </Button> -); - -export const SimpleModal: FCWithChildren<{ - open: boolean; - hideCloseIcon?: boolean; - displayErrorIcon?: boolean; - displayInfoIcon?: boolean; - headerStyles?: SxProps; - subHeaderStyles?: SxProps; - buttonFullWidth?: boolean; - onClose?: () => void; - onOk?: () => Promise<void>; - onBack?: () => void; - header: string | React.ReactNode; - subHeader?: string; - okLabel: string; - backLabel?: string; - backButtonFullWidth?: boolean; - okDisabled?: boolean; - sx?: SxProps; - children?: React.ReactNode; -}> = ({ - open, - hideCloseIcon, - displayErrorIcon, - displayInfoIcon, - headerStyles, - buttonFullWidth, - onClose, - okDisabled, - onOk, - onBack, - header, - subHeader, - okLabel, - backLabel, - backButtonFullWidth, - sx, - children, -}) => { - const isMobile = useIsMobile(); - - return ( - <Modal open={open} onClose={onClose}> - <Box sx={{ ...modalStyle(isMobile ? '90%' : 600), ...sx }}> - {displayErrorIcon && <ErrorOutline color="error" sx={{ mb: 3 }} />} - {displayInfoIcon && <InfoOutlinedIcon sx={{ mb: 2, color: 'blue' }} />} - <Stack direction="row" justifyContent="space-between" alignItems="center"> - {typeof header === 'string' ? ( - <Typography fontSize={20} fontWeight={600} sx={{ color: 'text.primary', ...headerStyles }}> - {header} - </Typography> - ) : ( - header - )} - {!hideCloseIcon && <CloseIcon onClick={onClose} cursor="pointer" />} - </Stack> - - <Typography mt={subHeader ? 0.5 : 0} mb={3} fontSize={12} color={(theme) => theme.palette.text.secondary}> - {subHeader} - </Typography> - - {children} - - {(onOk || onBack) && ( - <Box sx={{ display: 'flex', alignItems: 'center', gap: 2, mt: 2, width: buttonFullWidth ? '100%' : null }}> - {onBack && <StyledBackButton onBack={onBack} label={backLabel} fullWidth={backButtonFullWidth} />} - {onOk && ( - <Button variant="contained" fullWidth size="large" onClick={onOk} disabled={okDisabled}> - {okLabel} - </Button> - )} - </Box> - )} - </Box> - </Modal> - ); -}; diff --git a/explorer/src/components/Delegations/index.ts b/explorer/src/components/Delegations/index.ts deleted file mode 100644 index da51de9bd90..00000000000 --- a/explorer/src/components/Delegations/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -export * from './ConfirmationModal'; -export * from './DelegateIconButton'; -export * from './DelegationModal'; -export * from './DelegateModal'; -export * from './ErrorModal'; -export * from './LoadingModal'; -export * from './ModalDivider'; -export * from './ModalListItem'; -export * from './SimpleModal'; -export * from './styles'; diff --git a/explorer/src/components/Delegations/styles.ts b/explorer/src/components/Delegations/styles.ts deleted file mode 100644 index 9b265517670..00000000000 --- a/explorer/src/components/Delegations/styles.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Theme } from '@mui/material/styles'; - -export const backDropStyles = (theme: Theme) => { - const { mode } = theme.palette; - return { - style: { - left: mode === 'light' ? '0' : '50%', - width: '50%', - }, - }; -}; - -export const modalStyles = (theme: Theme) => { - const { mode } = theme.palette; - return { left: mode === 'light' ? '25%' : '75%' }; -}; - -export const dialogStyles = (theme: Theme) => { - const { mode } = theme.palette; - return { left: mode === 'light' ? '-50%' : '50%' }; -}; diff --git a/explorer/src/components/DetailTable.tsx b/explorer/src/components/DetailTable.tsx deleted file mode 100644 index 39355d06078..00000000000 --- a/explorer/src/components/DetailTable.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import * as React from 'react'; -import { - Link, - Paper, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, - TableCellProps, -} from '@mui/material'; -import { useTheme } from '@mui/material/styles'; -import { Tooltip } from '@nymproject/react/tooltip/Tooltip'; -import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard'; -import { Box } from '@mui/system'; -import { unymToNym } from '../utils/currency'; -import { GatewayEnrichedRowType } from './Gateways'; -import { MixnodeRowType } from './MixNodes'; -import { StakeSaturationProgressBar } from './MixNodes/Economics/StakeSaturationProgressBar'; - -export type ColumnsType = { - field: string; - title: string; - headerAlign?: TableCellProps['align']; - width?: string | number; - tooltipInfo?: string; -}; - -export interface UniversalTableProps<T = any> { - tableName: string; - columnsData: ColumnsType[]; - rows: T[]; -} - -function formatCellValues(val: string | number, field: string) { - if (field === 'identity_key' && typeof val === 'string') { - return ( - <Box display="flex" justifyContent="flex-end"> - <CopyToClipboard - sx={{ mr: 1, mt: 0.5, fontSize: '18px' }} - value={val} - tooltip={`Copy identity key ${val} to clipboard`} - /> - <span>{val}</span> - </Box> - ); - } - - if (field === 'bond') { - return unymToNym(val, 6); - } - - if (field === 'owner') { - return ( - <Link underline="none" color="inherit" target="_blank" href={`https://mixnet.explorers.guru/account/${val}`}> - {val} - </Link> - ); - } - - if (field === 'stake_saturation') { - return <StakeSaturationProgressBar value={Number(val)} threshold={100} />; - } - - return val; -} - -export const DetailTable: FCWithChildren<{ - tableName: string; - columnsData: ColumnsType[]; - rows: MixnodeRowType[] | GatewayEnrichedRowType[]; -}> = ({ tableName, columnsData, rows }: UniversalTableProps) => { - const theme = useTheme(); - return ( - <TableContainer component={Paper}> - <Table sx={{ minWidth: 1080 }} aria-label={tableName}> - <TableHead> - <TableRow> - {columnsData?.map(({ field, title, width, tooltipInfo }) => ( - <TableCell key={field} sx={{ fontSize: 14, fontWeight: 600, width }}> - <Box sx={{ display: 'flex', alignItems: 'center' }}> - {tooltipInfo && ( - <Box sx={{ display: 'flex', alignItems: 'center' }}> - <Tooltip - title={tooltipInfo} - id={field} - placement="top-start" - textColor={theme.palette.nym.networkExplorer.tooltip.color} - bgColor={theme.palette.nym.networkExplorer.tooltip.background} - maxWidth={230} - arrow - /> - </Box> - )} - {title} - </Box> - </TableCell> - ))} - </TableRow> - </TableHead> - <TableBody> - {rows.map((eachRow) => ( - <TableRow key={eachRow.id} sx={{ '&:last-child td, &:last-child th': { border: 0 } }}> - {columnsData?.map((data, index) => ( - <TableCell - key={data.title} - component="th" - scope="row" - variant="body" - sx={{ - padding: 2, - width: 200, - fontSize: 14, - }} - data-testid={`${data.title.replace(/ /g, '-')}-value`} - > - {formatCellValues(eachRow[columnsData[index].field], columnsData[index].field)} - </TableCell> - ))} - </TableRow> - ))} - </TableBody> - </Table> - </TableContainer> - ); -}; diff --git a/explorer/src/components/Filters/Filters.tsx b/explorer/src/components/Filters/Filters.tsx deleted file mode 100644 index 0823ef65790..00000000000 --- a/explorer/src/components/Filters/Filters.tsx +++ /dev/null @@ -1,172 +0,0 @@ -import React, { useState, useEffect, useRef, useCallback } from 'react'; -import { - Button, - Dialog, - DialogContent, - DialogActions, - DialogTitle, - Slider, - Typography, - Box, - Snackbar, - Slide, - Alert, -} from '@mui/material'; -import { useParams } from 'react-router-dom'; -import { useMainContext } from '../../context/main'; -import { MixnodeStatusWithAll, toMixnodeStatus } from '../../typeDefs/explorer-api'; -import { EnumFilterKey, TFilterItem, TFilters } from '../../typeDefs/filters'; -import { formatOnSave, generateFilterSchema } from './filterSchema'; -import { Api } from '../../api'; -import { useIsMobile } from '../../hooks/useIsMobile'; -import FiltersButton from './FiltersButton'; - -const FilterItem = ({ - label, - id, - tooltipInfo, - value, - isSmooth, - marks, - scale, - min, - max, - onChange, -}: TFilterItem & { - onChange: (id: EnumFilterKey, newValue: number[]) => void; -}) => ( - <Box sx={{ p: 2 }}> - <Typography gutterBottom>{label}</Typography> - <Typography fontSize={12}>{tooltipInfo}</Typography> - <Slider - value={value} - onChange={(e: Event, newValue: number | number[]) => onChange(id, newValue as number[])} - valueLabelDisplay={isSmooth ? 'auto' : 'off'} - marks={marks} - step={isSmooth ? 1 : null} - scale={scale} - min={min} - max={max} - valueLabelFormat={(val: number) => (val === 100 && id === 'stakeSaturation' ? '>100' : val)} - /> - </Box> -); - -export const Filters = () => { - const { filterMixnodes, fetchMixnodes, mixnodes } = useMainContext(); - const { status } = useParams<{ status: MixnodeStatusWithAll | undefined }>(); - const isMobile = useIsMobile(); - - const [showFilters, setShowFilters] = useState(false); - const [isFiltered, setIsFiltered] = useState(false); - const [filters, setFilters] = React.useState<TFilters>(); - const [upperSaturationValue, setUpperSaturationValue] = React.useState<number>(100); - - const baseFilters = useRef<TFilters>(); - const prevFilters = useRef<TFilters>(); - - const handleToggleShowFilters = () => setShowFilters(!showFilters); - - const initialiseFilters = useCallback(async () => { - const allMixnodes = await Api.fetchMixnodes(); - if (allMixnodes) { - setUpperSaturationValue(Math.round(Math.max(...allMixnodes.map((m) => m.stake_saturation)) * 100 + 1)); - const initFilters = generateFilterSchema(); - baseFilters.current = initFilters; - prevFilters.current = initFilters; - setFilters(initFilters); - } - }, []); - - const handleOnChange = (id: EnumFilterKey, newValue: number[]) => { - if (id === 'stakeSaturation' && newValue[1] === 100) { - newValue.splice(1, 1, upperSaturationValue); - } - setFilters((ftrs) => { - if (ftrs) - return { - ...ftrs, - [id]: { - ...ftrs[id], - value: newValue, - }, - }; - return undefined; - }); - }; - - const handleOnSave = async () => { - setShowFilters(false); - await filterMixnodes(formatOnSave(filters!), status); - setIsFiltered(true); - prevFilters.current = filters; - }; - - const handleOnCancel = () => { - setShowFilters(false); - setFilters(prevFilters.current); - }; - - const resetFilters = () => { - setFilters(baseFilters.current); - setIsFiltered(false); - prevFilters.current = baseFilters.current; - }; - - const onClearFilters = async () => { - await fetchMixnodes(toMixnodeStatus(status)); - resetFilters(); - }; - - useEffect(() => { - initialiseFilters(); - }, [initialiseFilters]); - - useEffect(() => { - resetFilters(); - }, [status]); - - if (!filters) return null; - - return ( - <> - <Snackbar - open={isFiltered} - anchorOrigin={{ vertical: 'top', horizontal: 'center' }} - message="Filters applied" - TransitionComponent={Slide} - transitionDuration={250} - > - <Alert - severity="info" - variant={isMobile ? 'standard' : 'outlined'} - sx={{ color: (t) => t.palette.info.light }} - action={ - <Button size="small" onClick={onClearFilters}> - CLEAR FILTERS - </Button> - } - > - {mixnodes?.data?.length} mixnodes matched your criteria - </Alert> - </Snackbar> - <FiltersButton onClick={handleToggleShowFilters} fullWidth /> - <Dialog open={showFilters} onClose={handleToggleShowFilters} maxWidth="md" fullWidth> - <DialogTitle>Mixnode filters</DialogTitle> - <DialogContent dividers> - {Object.values(filters).map((v) => ( - <FilterItem {...v} key={v.id} onChange={handleOnChange} /> - ))} - </DialogContent> - <DialogActions> - <Button size="large" onClick={handleOnCancel}> - Cancel - </Button> - <Button variant="contained" size="large" onClick={handleOnSave}> - Save - </Button> - </DialogActions> - </Dialog> - </> - ); -}; diff --git a/explorer/src/components/Filters/FiltersButton.tsx b/explorer/src/components/Filters/FiltersButton.tsx deleted file mode 100644 index 1e6d3e29405..00000000000 --- a/explorer/src/components/Filters/FiltersButton.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { Button, IconButton } from '@mui/material'; -import { Tune } from '@mui/icons-material'; - -type FiltersButtonProps = { - iconOnly?: boolean; - fullWidth?: boolean; - onClick: () => void; -}; - -const FiltersButton = ({ iconOnly, fullWidth, onClick }: FiltersButtonProps) => { - if (iconOnly) { - return ( - <IconButton onClick={onClick} color="primary"> - <Tune /> - </IconButton> - ); - } - - return ( - <Button - fullWidth={fullWidth} - size="large" - variant="contained" - endIcon={<Tune />} - onClick={onClick} - sx={{ textTransform: 'none' }} - > - Filters - </Button> - ); -}; - -export default FiltersButton; diff --git a/explorer/src/components/Filters/filterSchema.ts b/explorer/src/components/Filters/filterSchema.ts deleted file mode 100644 index c5011114b19..00000000000 --- a/explorer/src/components/Filters/filterSchema.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { EnumFilterKey, TFilters } from '../../typeDefs/filters'; - -export const generateFilterSchema = () => ({ - profitMargin: { - label: 'Profit margin (%)', - id: EnumFilterKey.profitMargin, - value: [0, 100], - isSmooth: true, - marks: [ - { label: '0', value: 0 }, - { label: '10', value: 10 }, - { label: '20', value: 20 }, - { label: '30', value: 30 }, - { label: '40', value: 40 }, - { label: '50', value: 50 }, - { label: '60', value: 60 }, - { label: '70', value: 70 }, - { label: '80', value: 80 }, - { label: '90', value: 90 }, - { label: '100', value: 100 }, - ], - tooltipInfo: - 'As a delegator you want to chose nodes with lower profit margin, meaning more payout for their delegators', - }, - stakeSaturation: { - label: 'Stake saturation (%)', - id: EnumFilterKey.stakeSaturation, - value: [0, 100], - isSmooth: true, - marks: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100].map((value) => ({ - value: value < 100 ? value : 100, - label: value < 100 ? value : '>100', - })), - tooltipInfo: "Select nodes with <100% saturation. Any additional stake above 100% saturation won't get rewards", - }, - routingScore: { - label: 'Routing score (%)', - id: EnumFilterKey.routingScore, - value: [0, 100], - isSmooth: true, - marks: [ - { label: '0', value: 0 }, - { label: '10', value: 10 }, - { label: '20', value: 20 }, - { label: '30', value: 30 }, - { label: '40', value: 40 }, - { label: '50', value: 50 }, - { label: '60', value: 60 }, - { label: '70', value: 70 }, - { label: '80', value: 80 }, - { label: '90', value: 90 }, - { label: '100', value: 100 }, - ], - tooltipInfo: 'The higher the routing score the better the performance of the node and so its rewards', - }, -}); - -const formatStakeSaturationValues = ([value_1, value_2]: number[]) => { - const lowerValue = value_1 / 100; - const upperValue = value_2 / 100; - - return [lowerValue, upperValue]; -}; - -export const formatOnSave = (filters: TFilters) => ({ - routingScore: filters.routingScore.value, - profitMargin: filters.profitMargin.value, - stakeSaturation: formatStakeSaturationValues(filters.stakeSaturation.value), -}); diff --git a/explorer/src/components/Footer.tsx b/explorer/src/components/Footer.tsx deleted file mode 100644 index 375b5c9b1a6..00000000000 --- a/explorer/src/components/Footer.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import React from 'react'; -import Box from '@mui/material/Box'; -import MuiLink from '@mui/material/Link'; -import { Link } from 'react-router-dom'; -import Typography from '@mui/material/Typography'; -import { Socials } from './Socials'; -import { useIsMobile } from '../hooks/useIsMobile'; -import { NymVpnIcon } from '../icons/NymVpn'; - -export const Footer: FCWithChildren = () => { - const isMobile = useIsMobile(); - - return ( - <Box - sx={{ - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - width: '100%', - height: 'auto', - mt: 3, - pt: 3, - pb: 3, - }} - > - <Box - sx={{ - display: 'flex', - flexDirection: 'row', - width: 'auto', - justifyContent: 'center', - alignItems: 'center', - mb: 2, - }} - > - <MuiLink component={Link} to="http://nymvpn.com" target="_blank" underline="none" marginRight={1}> - <NymVpnIcon /> - </MuiLink> - <Socials isFooter /> - </Box> - - <Typography - sx={{ - fontSize: 12, - textAlign: isMobile ? 'center' : 'end', - color: 'nym.muted.onDarkBg', - }} - > - © {new Date().getFullYear()} Nym Technologies SA, all rights reserved - </Typography> - </Box> - ); -}; diff --git a/explorer/src/components/Gateways.ts b/explorer/src/components/Gateways.ts deleted file mode 100644 index 966a3c987e5..00000000000 --- a/explorer/src/components/Gateways.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { GatewayResponse, GatewayBond, GatewayReportResponse } from '../typeDefs/explorer-api'; -import { toPercentInteger } from '../utils'; - -export type GatewayRowType = { - id: string; - owner: string; - identity_key: string; - bond: number; - host: string; - location: string; - version: string; - node_performance: number; -}; - -export type GatewayEnrichedRowType = GatewayRowType & { - routingScore: string; - avgUptime: string; - clientsPort: number; - mixPort: number; -}; - -export function gatewayToGridRow(arrayOfGateways: GatewayResponse): GatewayRowType[] { - return !arrayOfGateways - ? [] - : arrayOfGateways.map((gw) => ({ - id: gw.owner, - owner: gw.owner, - identity_key: gw.gateway.identity_key || '', - location: gw.location?.country_name.toUpperCase() || '', - bond: gw.pledge_amount.amount || 0, - host: gw.gateway.host || '', - version: gw.gateway.version || '', - node_performance: toPercentInteger(gw.node_performance.last_24h), - })); -} - -export function gatewayEnrichedToGridRow(gateway: GatewayBond, report: GatewayReportResponse): GatewayEnrichedRowType { - return { - id: gateway.owner, - owner: gateway.owner, - identity_key: gateway.gateway.identity_key || '', - location: gateway.location?.country_name.toUpperCase() || '', - bond: gateway.pledge_amount.amount || 0, - host: gateway.gateway.host || '', - version: gateway.gateway.version || '', - clientsPort: gateway.gateway.clients_port || 0, - mixPort: gateway.gateway.mix_port || 0, - routingScore: `${report.most_recent}%`, - avgUptime: `${report.last_day || report.last_hour}%`, - node_performance: toPercentInteger(gateway.node_performance.most_recent), - }; -} diff --git a/explorer/src/components/Gateways/VersionDisplaySelector.tsx b/explorer/src/components/Gateways/VersionDisplaySelector.tsx deleted file mode 100644 index e9be02b419f..00000000000 --- a/explorer/src/components/Gateways/VersionDisplaySelector.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -import { FormControl, MenuItem, Select } from '@mui/material'; -import { useIsMobile } from '../../hooks/useIsMobile'; - -export enum VersionSelectOptions { - latestVersion = 'Latest versions', - olderVersions = 'Older versions', - all = 'All', -} -export const VersionDisplaySelector = ({ - selected, - handleChange, -}: { - selected: VersionSelectOptions; - handleChange: (option: VersionSelectOptions) => void; -}) => { - const isMobile = useIsMobile(); - - return ( - <FormControl size="small"> - <Select - value={selected} - onChange={(e) => handleChange(e.target.value as VersionSelectOptions)} - labelId="simple-select-label" - id="simple-select" - sx={{ - marginRight: isMobile ? 0 : 2, - }} - > - <MenuItem value={VersionSelectOptions.latestVersion} data-testid="show-gateway-latest-version"> - {VersionSelectOptions.latestVersion} - </MenuItem> - <MenuItem value={VersionSelectOptions.olderVersions} data-testid="show-gateway-old-versions"> - {VersionSelectOptions.olderVersions} - </MenuItem> - <MenuItem value={VersionSelectOptions.all} data-testid="show-gateway-all-versions"> - {VersionSelectOptions.all} - </MenuItem> - </Select> - </FormControl> - ); -}; diff --git a/explorer/src/components/Icons.ts b/explorer/src/components/Icons.ts deleted file mode 100644 index 88761b9d215..00000000000 --- a/explorer/src/components/Icons.ts +++ /dev/null @@ -1,28 +0,0 @@ -import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'; -import PauseCircleOutlineIcon from '@mui/icons-material/PauseCircleOutline'; -import CircleOutlinedIcon from '@mui/icons-material/CircleOutlined'; -import { MixnodeStatus } from '../typeDefs/explorer-api'; - -export const Icons = { - Mixnodes: { - Status: { - Active: CheckCircleOutlineIcon, - Standby: PauseCircleOutlineIcon, - Inactive: CircleOutlinedIcon, - }, - }, -}; - -export const getMixNodeIcon = (value: any) => { - if (value && typeof value === 'string') { - switch (value) { - case MixnodeStatus.active: - return Icons.Mixnodes.Status.Active; - case MixnodeStatus.standby: - return Icons.Mixnodes.Status.Standby; - default: - return Icons.Mixnodes.Status.Inactive; - } - } - return Icons.Mixnodes.Status.Inactive; -}; diff --git a/explorer/src/components/MixNodes/BondBreakdown.tsx b/explorer/src/components/MixNodes/BondBreakdown.tsx deleted file mode 100644 index 7fd66efb24d..00000000000 --- a/explorer/src/components/MixNodes/BondBreakdown.tsx +++ /dev/null @@ -1,206 +0,0 @@ -import * as React from 'react'; -import { Alert, Box, CircularProgress, Typography } from '@mui/material'; -import { useTheme } from '@mui/material/styles'; -import Table from '@mui/material/Table'; -import TableBody from '@mui/material/TableBody'; -import TableCell from '@mui/material/TableCell'; -import TableContainer from '@mui/material/TableContainer'; -import TableHead from '@mui/material/TableHead'; -import TableRow from '@mui/material/TableRow'; -import Paper from '@mui/material/Paper'; -import { ExpandMore } from '@mui/icons-material'; -import { currencyToString } from '../../utils/currency'; -import { useMixnodeContext } from '../../context/mixnode'; -import { useIsMobile } from '../../hooks/useIsMobile'; - -export const BondBreakdownTable: FCWithChildren = () => { - const { mixNode, delegations, uniqDelegations } = useMixnodeContext(); - const [showDelegations, toggleShowDelegations] = React.useState<boolean>(false); - - const [bonds, setBonds] = React.useState({ - delegations: '0', - pledges: '0', - bondsTotal: '0', - hasLoaded: false, - }); - const theme = useTheme(); - const isMobile = useIsMobile(); - - React.useEffect(() => { - if (mixNode?.data) { - // delegations - const decimalisedDelegations = currencyToString({ - amount: mixNode.data.total_delegation.amount.toString(), - denom: mixNode.data.total_delegation.denom, - }); - - // pledges - const decimalisedPledges = currencyToString({ - amount: mixNode.data.pledge_amount.amount.toString(), - denom: mixNode.data.pledge_amount.denom, - }); - - // bonds total (del + pledges) - const pledgesSum = Number(mixNode.data.pledge_amount.amount); - const delegationsSum = Number(mixNode.data.total_delegation.amount); - const bondsTotal = currencyToString({ - amount: (pledgesSum + delegationsSum).toString(), - }); - - setBonds({ - delegations: decimalisedDelegations, - pledges: decimalisedPledges, - bondsTotal, - hasLoaded: true, - }); - } - }, [mixNode]); - - const expandDelegations = () => { - if (delegations?.data && delegations.data.length > 0) { - toggleShowDelegations(!showDelegations); - } - }; - const calcBondPercentage = (num: number) => { - if (mixNode?.data) { - const rawDelegationAmount = Number(mixNode.data.total_delegation.amount); - const rawPledgeAmount = Number(mixNode.data.pledge_amount.amount); - const rawTotalBondsAmount = rawDelegationAmount + rawPledgeAmount; - return ((num * 100) / rawTotalBondsAmount).toFixed(1); - } - return 0; - }; - - if (mixNode?.isLoading || delegations?.isLoading) { - return <CircularProgress />; - } - - if (mixNode?.error) { - return <Alert severity="error">Mixnode not found</Alert>; - } - if (delegations?.error) { - return <Alert severity="error">Unable to get delegations for mixnode</Alert>; - } - - return ( - <TableContainer component={Paper}> - <Table sx={{ minWidth: 650 }} aria-label="bond breakdown totals"> - <TableBody> - <TableRow sx={isMobile ? { minWidth: '70vw' } : null}> - <TableCell - sx={{ - fontWeight: 400, - width: '150px', - }} - align="left" - > - Stake total - </TableCell> - <TableCell align="left" data-testid="bond-total-amount"> - {bonds.bondsTotal} - </TableCell> - </TableRow> - <TableRow> - <TableCell align="left">Bond</TableCell> - <TableCell align="left" data-testid="pledge-total-amount"> - {bonds.pledges} - </TableCell> - </TableRow> - <TableRow> - <TableCell onClick={expandDelegations} align="left"> - <Box - sx={{ - display: 'flex', - alignItems: 'center', - }} - > - Delegation total {'\u00A0'} - {delegations?.data && delegations?.data?.length > 0 && <ExpandMore />} - </Box> - </TableCell> - <TableCell align="left" data-testid="delegation-total-amount"> - {bonds.delegations} - </TableCell> - </TableRow> - </TableBody> - </Table> - - {showDelegations && ( - <Box - sx={{ - maxHeight: 400, - overflowY: 'scroll', - p: 2, - background: theme.palette.background.paper, - }} - > - <Box - sx={{ - display: 'flex', - alignItems: 'baseline', - width: '100%', - p: 2, - borderBottom: `1px solid ${theme.palette.divider}`, - }} - data-testid="delegations-total-amount" - > - <Typography - sx={{ - fontSize: 16, - fontWeight: 600, - }} - > - Delegations   - </Typography> - </Box> - <Table stickyHeader> - <TableHead> - <TableRow> - <TableCell - sx={{ - fontWeight: 600, - background: theme.palette.background.paper, - }} - align="left" - > - Delegators - </TableCell> - <TableCell - sx={{ - fontWeight: 600, - background: theme.palette.background.paper, - }} - align="left" - > - Amount - </TableCell> - <TableCell - sx={{ - fontWeight: 600, - background: theme.palette.background.paper, - width: '200px', - }} - align="left" - > - Share of stake - </TableCell> - </TableRow> - </TableHead> - - <TableBody> - {uniqDelegations?.data?.map(({ owner, amount: { amount } }) => ( - <TableRow key={owner}> - <TableCell sx={isMobile ? { width: 190 } : null} align="left"> - {owner} - </TableCell> - <TableCell align="left">{currencyToString({ amount: amount.toString() })}</TableCell> - <TableCell align="left">{calcBondPercentage(amount)}%</TableCell> - </TableRow> - ))} - </TableBody> - </Table> - </Box> - )} - </TableContainer> - ); -}; diff --git a/explorer/src/components/MixNodes/DetailSection.tsx b/explorer/src/components/MixNodes/DetailSection.tsx deleted file mode 100644 index 6becf5efe44..00000000000 --- a/explorer/src/components/MixNodes/DetailSection.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import * as React from 'react'; -import { Box, Button, Grid, Typography, useTheme } from '@mui/material'; -import Identicon from 'react-identicons'; -import { useIsMobile } from '@src/hooks/useIsMobile'; -import { MixnodeRowType } from '.'; -import { getMixNodeStatusText, MixNodeStatus } from './Status'; -import { MixNodeDescriptionResponse } from '../../typeDefs/explorer-api'; - -interface MixNodeDetailProps { - mixNodeRow: MixnodeRowType; - mixnodeDescription: MixNodeDescriptionResponse; -} - -export const MixNodeDetailSection: FCWithChildren<MixNodeDetailProps> = ({ mixNodeRow, mixnodeDescription }) => { - const theme = useTheme(); - const palette = [theme.palette.text.primary]; - const isMobile = useIsMobile(); - const statusText = React.useMemo(() => getMixNodeStatusText(mixNodeRow.status), [mixNodeRow.status]); - - return ( - <Grid container> - <Grid item xs={12} md={6}> - <Box display="flex" flexDirection={isMobile ? 'column' : 'row'} width="100%"> - <Box - width={72} - height={72} - sx={{ - minWidth: 72, - minHeight: 72, - borderWidth: 1, - borderColor: theme.palette.text.primary, - borderStyle: 'solid', - borderRadius: '50%', - display: 'grid', - placeItems: 'center', - }} - > - <Identicon size={43} string={mixNodeRow.identity_key} palette={palette} /> - </Box> - <Box ml={isMobile ? 0 : 2} mt={isMobile ? 2 : 0}> - <Typography fontSize={21}>{mixnodeDescription.name}</Typography> - <Typography>{(mixnodeDescription.description || '').slice(0, 1000)}</Typography> - <Button - component="a" - variant="text" - sx={{ - mt: isMobile ? 2 : 4, - borderRadius: '30px', - fontWeight: 600, - padding: 0, - }} - href={mixnodeDescription.link} - target="_blank" - > - <Typography - component="span" - textOverflow="ellipsis" - whiteSpace="nowrap" - overflow="hidden" - maxWidth="250px" - > - {mixnodeDescription.link} - </Typography> - </Button> - </Box> - </Box> - </Grid> - <Grid - item - xs={12} - md={6} - display="flex" - justifyContent={isMobile ? 'start' : 'end'} - mt={isMobile ? 3 : undefined} - > - <Box display="flex" flexDirection="column"> - <Typography fontWeight="600" alignSelf={isMobile ? 'start' : 'self-end'}> - Node status: - </Typography> - <Box mt={2} alignSelf={isMobile ? 'start' : 'self-end'}> - <MixNodeStatus status={mixNodeRow.status} /> - </Box> - <Typography - mt={1} - alignSelf={isMobile ? 'start' : 'self-end'} - color={theme.palette.text.secondary} - fontSize="smaller" - > - This node is {statusText} in this epoch - </Typography> - </Box> - </Grid> - </Grid> - ); -}; diff --git a/explorer/src/components/MixNodes/Economics/Columns.ts b/explorer/src/components/MixNodes/Economics/Columns.ts deleted file mode 100644 index b2115c0749c..00000000000 --- a/explorer/src/components/MixNodes/Economics/Columns.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { ColumnsType } from '../../DetailTable'; - -export const EconomicsInfoColumns: ColumnsType[] = [ - { - field: 'estimatedTotalReward', - title: 'Estimated Total Reward', - width: '15%', - tooltipInfo: - 'Estimated node reward (total for the operator and delegators) in the current epoch. There are roughly 24 epochs in a day.', - }, - { - field: 'estimatedOperatorReward', - title: 'Estimated Operator Reward', - width: '15%', - tooltipInfo: - "Estimated operator's reward (including PM and Operating Cost) in the current epoch. There are roughly 24 epochs in a day.", - }, - { - field: 'selectionChance', - title: 'Active Set Probability', - width: '12.5%', - tooltipInfo: - 'Probability of getting selected in the reward set (active and standby nodes) in the next epoch. The more your stake, the higher the chances to be selected.', - }, - { - field: 'profitMargin', - title: 'Profit Margin', - width: '12.5%', - tooltipInfo: - 'Percentage of the delegators rewards that the operator takes as fee before rewards are distributed to the delegators.', - }, - { - field: 'operatingCost', - title: 'Operating Cost', - width: '10%', - tooltipInfo: - 'Monthly operational cost of running this node. This cost is set by the operator and it influences how the rewards are split between the operator and delegators.', - }, - { - field: 'nodePerformance', - title: 'Routing Score', - width: '10%', - tooltipInfo: - "Mixnode's most recent score (measured in the last 15 minutes). Routing score is relative to that of the network. Each time a gateway is tested, the test packets have to go through the full path of the network (gateway + 3 nodes). If a node in the path drop packets it will affect the score of the gateway and other nodes in the test.", - }, - { - field: 'avgUptime', - title: 'Avg. Score', - tooltipInfo: "Mixnode's average routing score in the last 24 hour", - }, -]; diff --git a/explorer/src/components/MixNodes/Economics/EconomicsProgress.stories.tsx b/explorer/src/components/MixNodes/Economics/EconomicsProgress.stories.tsx deleted file mode 100644 index aef36113df8..00000000000 --- a/explorer/src/components/MixNodes/Economics/EconomicsProgress.stories.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import * as React from 'react'; -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { EconomicsProgress } from './EconomicsProgress'; - -export default { - title: 'Mix Node Detail/Economics/ProgressBar', - component: EconomicsProgress, -} as ComponentMeta<typeof EconomicsProgress>; - -const Template: ComponentStory<typeof EconomicsProgress> = (args) => <EconomicsProgress {...args} />; - -export const Empty = Template.bind({}); -Empty.args = {}; - -export const OverThreshold = Template.bind({}); -OverThreshold.args = { - threshold: 100, - value: 120, -}; - -export const UnderThreshold = Template.bind({}); -UnderThreshold.args = { - threshold: 100, - value: 80, -}; - -export const OnThreshold = Template.bind({}); -OnThreshold.args = { - threshold: 100, - value: 100, -}; diff --git a/explorer/src/components/MixNodes/Economics/EconomicsProgress.tsx b/explorer/src/components/MixNodes/Economics/EconomicsProgress.tsx deleted file mode 100644 index 24db62d1673..00000000000 --- a/explorer/src/components/MixNodes/Economics/EconomicsProgress.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import * as React from 'react'; -import LinearProgress, { LinearProgressProps } from '@mui/material/LinearProgress'; -import { useTheme } from '@mui/material/styles'; -import { Box } from '@mui/system'; - -const parseToNumber = (value: number | undefined | string) => - typeof value === 'string' ? parseInt(value || '', 10) : value || 0; - -export const EconomicsProgress: FCWithChildren< - LinearProgressProps & { - threshold?: number; - color: string; - } -> = ({ threshold, color, ...props }) => { - const theme = useTheme(); - const { value } = props; - - const valueNumber: number = parseToNumber(value); - const thresholdNumber: number = parseToNumber(threshold); - const percentageToDisplay = Math.min(valueNumber, thresholdNumber); - - return ( - <Box - sx={{ - width: 6 / 10, - color: valueNumber > (threshold || 100) ? theme.palette.warning.main : theme.palette.nym.wallet.fee, - }} - > - <LinearProgress - {...props} - variant="determinate" - color={color} - value={percentageToDisplay} - sx={{ width: '100%', borderRadius: '5px' }} - /> - </Box> - ); -}; diff --git a/explorer/src/components/MixNodes/Economics/MixNodeEconomics.stories.tsx b/explorer/src/components/MixNodes/Economics/MixNodeEconomics.stories.tsx deleted file mode 100644 index c9c82c0438f..00000000000 --- a/explorer/src/components/MixNodes/Economics/MixNodeEconomics.stories.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import * as React from 'react'; -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { DelegatorsInfoTable } from './Table'; -import { EconomicsInfoColumns } from './Columns'; -import { EconomicsInfoRowWithIndex } from './types'; - -export default { - title: 'Mix Node Detail/Economics', - component: DelegatorsInfoTable, -} as ComponentMeta<typeof DelegatorsInfoTable>; - -const row: EconomicsInfoRowWithIndex = { - id: 1, - selectionChance: { - value: 'High', - }, - - estimatedOperatorReward: { - value: '80000.123456 NYM', - }, - estimatedTotalReward: { - value: '80000.123456 NYM', - }, - profitMargin: { - value: '10 %', - }, - operatingCost: { - value: '11121 NYM', - }, - avgUptime: { - value: '-', - }, - nodePerformance: { - value: '-', - }, -}; - -const rowGoodProbabilitySelection: EconomicsInfoRowWithIndex = { - ...row, - selectionChance: { - value: 'Good', - }, -}; - -const rowLowProbabilitySelection: EconomicsInfoRowWithIndex = { - ...row, - selectionChance: { - value: 'Low', - }, -}; - -const emptyRow: EconomicsInfoRowWithIndex = { - id: 1, - selectionChance: { - value: '-', - progressBarValue: 0, - }, - - estimatedOperatorReward: { - value: '-', - }, - estimatedTotalReward: { - value: '-', - }, - profitMargin: { - value: '-', - }, - operatingCost: { - value: '-', - }, - avgUptime: { - value: '-', - }, - nodePerformance: { - value: '-', - }, -}; - -const Template: ComponentStory<typeof DelegatorsInfoTable> = (args) => <DelegatorsInfoTable {...args} />; - -export const Empty = Template.bind({}); -Empty.args = { - rows: [emptyRow], - columnsData: EconomicsInfoColumns, - tableName: 'storybook', -}; - -export const selectionChanceHigh = Template.bind({}); -selectionChanceHigh.args = { - rows: [row], - columnsData: EconomicsInfoColumns, - tableName: 'storybook', -}; - -export const selectionChanceGood = Template.bind({}); -selectionChanceGood.args = { - rows: [rowGoodProbabilitySelection], - columnsData: EconomicsInfoColumns, - tableName: 'storybook', -}; - -export const selectionChanceLow = Template.bind({}); -selectionChanceLow.args = { - rows: [rowLowProbabilitySelection], - columnsData: EconomicsInfoColumns, - tableName: 'storybook', -}; diff --git a/explorer/src/components/MixNodes/Economics/Rows.ts b/explorer/src/components/MixNodes/Economics/Rows.ts deleted file mode 100644 index ce947b0a4fe..00000000000 --- a/explorer/src/components/MixNodes/Economics/Rows.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { currencyToString, unymToNym } from '../../../utils/currency'; -import { useMixnodeContext } from '../../../context/mixnode'; -import { ApiState, MixNodeEconomicDynamicsStatsResponse } from '../../../typeDefs/explorer-api'; -import { EconomicsInfoRowWithIndex } from './types'; -import { toPercentIntegerString } from '../../../utils'; - -const selectionChance = (economicDynamicsStats: ApiState<MixNodeEconomicDynamicsStatsResponse> | undefined) => - economicDynamicsStats?.data?.active_set_inclusion_probability || '-'; - -export const EconomicsInfoRows = (): EconomicsInfoRowWithIndex => { - const { economicDynamicsStats, mixNode } = useMixnodeContext(); - - const estimatedNodeRewards = - currencyToString({ - amount: economicDynamicsStats?.data?.estimated_total_node_reward.toString() || '', - }) || '-'; - const estimatedOperatorRewards = - currencyToString({ - amount: economicDynamicsStats?.data?.estimated_operator_reward.toString() || '', - }) || '-'; - const profitMargin = mixNode?.data?.profit_margin_percent - ? toPercentIntegerString(mixNode?.data?.profit_margin_percent) - : '-'; - const avgUptime = mixNode?.data?.node_performance - ? toPercentIntegerString(mixNode?.data?.node_performance.last_24h) - : '-'; - const nodePerformance = mixNode?.data?.node_performance - ? toPercentIntegerString(mixNode?.data?.node_performance.most_recent) - : '-'; - - const opCost = mixNode?.data?.operating_cost; - - return { - id: 1, - estimatedTotalReward: { - value: estimatedNodeRewards, - }, - estimatedOperatorReward: { - value: estimatedOperatorRewards, - }, - selectionChance: { - value: selectionChance(economicDynamicsStats), - }, - profitMargin: { - value: profitMargin ? `${profitMargin} %` : '-', - }, - operatingCost: { - value: opCost ? `${unymToNym(opCost.amount, 6)} NYM` : '-', - }, - avgUptime: { - value: avgUptime ? `${avgUptime} %` : '-', - }, - nodePerformance: { - value: nodePerformance, - }, - }; -}; diff --git a/explorer/src/components/MixNodes/Economics/StakeSaturationProgressBar.tsx b/explorer/src/components/MixNodes/Economics/StakeSaturationProgressBar.tsx deleted file mode 100644 index 918d0246438..00000000000 --- a/explorer/src/components/MixNodes/Economics/StakeSaturationProgressBar.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import { Box, Typography } from '@mui/material'; -import { useIsMobile } from '../../../hooks/useIsMobile'; -import { EconomicsProgress } from './EconomicsProgress'; - -export const StakeSaturationProgressBar = ({ value, threshold }: { value: number; threshold: number }) => { - const isTablet = useIsMobile('lg'); - const percentageColor = value > (threshold || 100) ? 'warning' : 'inherit'; - const textColor = percentageColor === 'warning' ? 'warning.main' : 'nym.wallet.fee'; - - return ( - <Box - sx={{ display: 'flex', alignItems: 'center', flexDirection: isTablet ? 'column' : 'row' }} - id="field" - color={percentageColor} - > - <Typography - sx={{ - mr: isTablet ? 0 : 1, - mb: isTablet ? 1 : 0, - fontWeight: '600', - fontSize: '12px', - color: textColor, - }} - id="stake-saturation-progress-bar" - > - {value}% - </Typography> - <EconomicsProgress value={value} threshold={threshold} color={percentageColor} /> - </Box> - ); -}; diff --git a/explorer/src/components/MixNodes/Economics/Table.tsx b/explorer/src/components/MixNodes/Economics/Table.tsx deleted file mode 100644 index e6630334dbe..00000000000 --- a/explorer/src/components/MixNodes/Economics/Table.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import * as React from 'react'; -import { Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography } from '@mui/material'; -import { Box } from '@mui/system'; -import { useTheme } from '@mui/material/styles'; -import { Tooltip } from '@nymproject/react/tooltip/Tooltip'; -import { EconomicsRowsType, EconomicsInfoRowWithIndex } from './types'; -import { UniversalTableProps } from '../../DetailTable'; -import { textColour } from '../../../utils'; - -const formatCellValues = (value: EconomicsRowsType, field: string) => ( - <Box sx={{ display: 'flex', alignItems: 'center' }} id="field"> - <Typography sx={{ mr: 1, fontWeight: '600', fontSize: '12px' }} id={field}> - {value.value} - </Typography> - </Box> -); - -export const DelegatorsInfoTable: FCWithChildren<UniversalTableProps<EconomicsInfoRowWithIndex>> = ({ - tableName, - columnsData, - rows, -}) => { - const theme = useTheme(); - - return ( - <TableContainer component={Paper}> - <Table sx={{ minWidth: 650 }} aria-label={tableName}> - <TableHead> - <TableRow> - {columnsData?.map(({ field, title, tooltipInfo, width }) => ( - <TableCell key={field} sx={{ fontSize: 14, fontWeight: 600, width }}> - <Box sx={{ display: 'flex', alignItems: 'center' }}> - {tooltipInfo && ( - <Tooltip - title={tooltipInfo} - id={field} - placement="top-start" - textColor={theme.palette.nym.networkExplorer.tooltip.color} - bgColor={theme.palette.nym.networkExplorer.tooltip.background} - maxWidth={230} - arrow - /> - )} - {title} - </Box> - </TableCell> - ))} - </TableRow> - </TableHead> - <TableBody> - {rows?.map((eachRow) => ( - <TableRow key={eachRow.id} sx={{ '&:last-child td, &:last-child th': { border: 0 } }}> - {columnsData?.map((_, index: number) => { - const { field } = columnsData[index]; - const value: EconomicsRowsType = (eachRow as any)[field]; - return ( - <TableCell - key={_.title} - sx={{ - color: textColour(value, field, theme), - }} - data-testid={`${_.title.replace(/ /g, '-')}-value`} - > - {formatCellValues(value, columnsData[index].field)} - </TableCell> - ); - })} - </TableRow> - ))} - </TableBody> - </Table> - </TableContainer> - ); -}; diff --git a/explorer/src/components/MixNodes/Economics/index.ts b/explorer/src/components/MixNodes/Economics/index.ts deleted file mode 100644 index 6dec7522464..00000000000 --- a/explorer/src/components/MixNodes/Economics/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { DelegatorsInfoTable } from './Table'; -export { EconomicsInfoColumns } from './Columns'; -export { EconomicsInfoRows } from './Rows'; diff --git a/explorer/src/components/MixNodes/Economics/types.ts b/explorer/src/components/MixNodes/Economics/types.ts deleted file mode 100644 index 0bc550253f7..00000000000 --- a/explorer/src/components/MixNodes/Economics/types.ts +++ /dev/null @@ -1,20 +0,0 @@ -export type EconomicsRowsType = { - progressBarValue?: number; - value: string; -}; - -type TEconomicsInfoProperties = - | 'estimatedTotalReward' - | 'estimatedOperatorReward' - | 'estimatedOperatorReward' - | 'selectionChance' - | 'profitMargin' - | 'avgUptime' - | 'nodePerformance' - | 'operatingCost'; - -export type EconomicsInfoRow = { - [k in TEconomicsInfoProperties]: EconomicsRowsType; -}; - -export type EconomicsInfoRowWithIndex = EconomicsInfoRow & { id: number }; diff --git a/explorer/src/components/MixNodes/Status.tsx b/explorer/src/components/MixNodes/Status.tsx deleted file mode 100644 index 627b1f5964c..00000000000 --- a/explorer/src/components/MixNodes/Status.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Typography } from '@mui/material'; -import * as React from 'react'; -import { getMixNodeIcon } from '@src/components/Icons'; -import { MixnodeStatus } from '@src/typeDefs/explorer-api'; -import { useGetMixNodeStatusColor } from '@src/hooks/useGetMixnodeStatusColor'; - -interface MixNodeStatusProps { - status: MixnodeStatus; -} -// TODO: should be done with i18n -export const getMixNodeStatusText = (status: MixnodeStatus) => { - switch (status) { - case MixnodeStatus.active: - return 'active'; - case MixnodeStatus.standby: - return 'on standby'; - default: - return 'inactive'; - } -}; - -export const MixNodeStatus: FCWithChildren<MixNodeStatusProps> = ({ status }) => { - const Icon = React.useMemo(() => getMixNodeIcon(status), [status]); - const color = useGetMixNodeStatusColor(status); - - return ( - <Typography color={color} display="flex" alignItems="center"> - <Icon /> - <Typography ml={1} component="span" color="inherit"> - {`${status[0].toUpperCase()}${status.slice(1)}`} - </Typography> - </Typography> - ); -}; diff --git a/explorer/src/components/MixNodes/StatusDropdown.tsx b/explorer/src/components/MixNodes/StatusDropdown.tsx deleted file mode 100644 index 9cb34a2f0c9..00000000000 --- a/explorer/src/components/MixNodes/StatusDropdown.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import * as React from 'react'; -import { MenuItem } from '@mui/material'; -import Select from '@mui/material/Select'; -import { SelectChangeEvent } from '@mui/material/Select/SelectInput'; -import { SxProps } from '@mui/system'; -import { MixNodeStatus } from './Status'; -import { MixnodeStatus, MixnodeStatusWithAll } from '../../typeDefs/explorer-api'; -import { useIsMobile } from '../../hooks/useIsMobile'; - -// TODO: replace with i18n -const ALL_NODES = 'All nodes'; - -interface MixNodeStatusDropdownProps { - status?: MixnodeStatusWithAll; - sx?: SxProps; - onSelectionChanged?: (status?: MixnodeStatusWithAll) => void; -} - -export const MixNodeStatusDropdown: FCWithChildren<MixNodeStatusDropdownProps> = ({ - status, - onSelectionChanged, - sx, -}) => { - const isMobile = useIsMobile(); - const [statusValue, setStatusValue] = React.useState<MixnodeStatusWithAll>(status || MixnodeStatusWithAll.all); - const onChange = React.useCallback( - (event: SelectChangeEvent) => { - setStatusValue(event.target.value as MixnodeStatusWithAll); - if (onSelectionChanged) { - onSelectionChanged(event.target.value as MixnodeStatusWithAll); - } - }, - [onSelectionChanged], - ); - - return ( - <Select - labelId="mixnodeStatusSelect_label" - id="mixnodeStatusSelect" - value={statusValue} - onChange={onChange} - renderValue={(value) => { - switch (value) { - case MixnodeStatusWithAll.active: - case MixnodeStatusWithAll.standby: - case MixnodeStatusWithAll.inactive: - return <MixNodeStatus status={value as unknown as MixnodeStatus} />; - default: - return ALL_NODES; - } - }} - sx={{ - width: isMobile ? '50%' : 200, - ...sx, - }} - > - <MenuItem value={MixnodeStatus.active} data-testid="mixnodeStatusSelectOption_active"> - <MixNodeStatus status={MixnodeStatus.active} /> - </MenuItem> - <MenuItem value={MixnodeStatus.standby} data-testid="mixnodeStatusSelectOption_standby"> - <MixNodeStatus status={MixnodeStatus.standby} /> - </MenuItem> - <MenuItem value={MixnodeStatus.inactive} data-testid="mixnodeStatusSelectOption_inactive"> - <MixNodeStatus status={MixnodeStatus.inactive} /> - </MenuItem> - <MenuItem value={MixnodeStatusWithAll.all} data-testid="mixnodeStatusSelectOption_allNodes"> - {ALL_NODES} - </MenuItem> - </Select> - ); -}; - -MixNodeStatusDropdown.defaultProps = { - onSelectionChanged: undefined, - status: undefined, - sx: undefined, -}; diff --git a/explorer/src/components/MixNodes/index.ts b/explorer/src/components/MixNodes/index.ts deleted file mode 100644 index ccb6c5a8b3f..00000000000 --- a/explorer/src/components/MixNodes/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './Status'; -export * from './StatusDropdown'; -export * from './mappings'; diff --git a/explorer/src/components/MixNodes/mappings.ts b/explorer/src/components/MixNodes/mappings.ts deleted file mode 100644 index aba4c6fdca2..00000000000 --- a/explorer/src/components/MixNodes/mappings.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* eslint-disable camelcase */ -import { MixNodeResponse, MixNodeResponseItem, MixnodeStatus } from '../../typeDefs/explorer-api'; -import { toPercentInteger, toPercentIntegerString } from '../../utils'; -import { unymToNym } from '../../utils/currency'; - -export type MixnodeRowType = { - mix_id: number; - id: string; - status: MixnodeStatus; - owner: string; - location: string; - identity_key: string; - bond: number; - self_percentage: string; - pledge_amount: number; - host: string; - layer: string; - profit_percentage: number; - avg_uptime: string; - stake_saturation: React.ReactNode; - operating_cost: number; - node_performance: number; - blacklisted: boolean; -}; - -export function mixnodeToGridRow(arrayOfMixnodes?: MixNodeResponse): MixnodeRowType[] { - return (arrayOfMixnodes || []).map(mixNodeResponseItemToMixnodeRowType); -} - -export function mixNodeResponseItemToMixnodeRowType(item: MixNodeResponseItem): MixnodeRowType { - const pledge = Number(item.pledge_amount.amount) || 0; - const delegations = Number(item.total_delegation.amount) || 0; - const totalBond = pledge + delegations; - const selfPercentage = ((pledge * 100) / totalBond).toFixed(2); - const profitPercentage = toPercentInteger(item.profit_margin_percent) || 0; - const uncappedSaturation = typeof item.uncapped_saturation === 'number' ? item.uncapped_saturation * 100 : 0; - - return { - mix_id: item.mix_id, - id: item.owner, - status: item.status, - owner: item.owner, - identity_key: item.mix_node.identity_key || '', - bond: totalBond || 0, - location: item?.location?.country_name || '', - self_percentage: selfPercentage, - pledge_amount: pledge, - host: item?.mix_node?.host || '', - layer: item?.layer || '', - profit_percentage: profitPercentage, - avg_uptime: `${toPercentIntegerString(item.node_performance.last_24h)}%`, - stake_saturation: Number(uncappedSaturation.toFixed(2)), - operating_cost: Number(unymToNym(item.operating_cost?.amount, 6)) || 0, - node_performance: toPercentInteger(item.node_performance.most_recent), - blacklisted: item.blacklisted, - }; -} diff --git a/explorer/src/components/MobileNav.tsx b/explorer/src/components/MobileNav.tsx deleted file mode 100644 index ac4b3134670..00000000000 --- a/explorer/src/components/MobileNav.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; -import { AppBar, Box, Drawer, IconButton, List, ListItem, ListItemButton, ListItemIcon, Toolbar } from '@mui/material'; -import { Menu } from '@mui/icons-material'; -import { MaintenanceBanner } from '@nymproject/react/banners/MaintenanceBanner'; -import { useIsMobile } from '@src/hooks/useIsMobile'; -import { useMainContext } from '../context/main'; -import { MobileDrawerClose } from '../icons/MobileDrawerClose'; -import { Footer } from './Footer'; -import { ExpandableButton } from './Nav'; -import { ConnectKeplrWallet } from './Wallet/ConnectKeplrWallet'; -import NetworkTitle from './NetworkTitle'; - -export const MobileNav: FCWithChildren = ({ children }) => { - const theme = useTheme(); - const { navState, updateNavState } = useMainContext(); - const [drawerOpen, setDrawerOpen] = React.useState(false); - // Set maintenance banner to false by default to don't display it - const [openMaintenance, setOpenMaintenance] = React.useState(false); - const isSmallMobile = useIsMobile(400); - - const toggleDrawer = () => { - setDrawerOpen(!drawerOpen); - }; - - const handleClick = (url: string) => { - updateNavState(url); - toggleDrawer(); - }; - - const openDrawer = () => { - setDrawerOpen(true); - }; - - return ( - <Box sx={{ display: 'flex', flexDirection: 'column' }}> - <AppBar - sx={{ - background: theme.palette.nym.networkExplorer.topNav.appBar, - borderRadius: 0, - }} - > - <MaintenanceBanner open={openMaintenance} onClick={() => setOpenMaintenance(false)} /> - <Toolbar - sx={{ - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - width: '100%', - }} - > - <Box - sx={{ - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - }} - > - <IconButton onClick={toggleDrawer}> - <Menu sx={{ color: 'primary.contrastText' }} /> - </IconButton> - {!isSmallMobile && <NetworkTitle />} - </Box> - <ConnectKeplrWallet /> - </Toolbar> - </AppBar> - <Drawer - anchor="left" - open={drawerOpen} - onClose={toggleDrawer} - PaperProps={{ - style: { - background: theme.palette.nym.networkExplorer.nav.background, - }, - }} - > - <Box role="presentation"> - <List sx={{ pt: 0, pb: 0 }}> - <ListItem - disablePadding - disableGutters - sx={{ - height: 64, - background: theme.palette.nym.networkExplorer.nav.background, - borderBottom: '1px solid rgba(255, 255, 255, 0.1)', - }} - > - <ListItemButton - onClick={toggleDrawer} - sx={{ - pt: 2, - pb: 2, - background: theme.palette.nym.networkExplorer.nav.background, - display: 'flex', - justifyContent: 'flex-start', - }} - > - <ListItemIcon> - <MobileDrawerClose /> - </ListItemIcon> - </ListItemButton> - </ListItem> - {navState.map((props) => ( - <ExpandableButton - key={props.url} - title={props.title} - openDrawer={openDrawer} - url={props.url} - drawIsTempOpen={drawerOpen === true} - drawIsFixed={false} - Icon={props.Icon} - setToActive={handleClick} - nested={props.nested} - isMobile - isActive={props.isActive} - /> - ))} - </List> - </Box> - </Drawer> - - <Box sx={{ width: '100%', p: 4, mt: 7 }}> - {children} - <Footer /> - </Box> - </Box> - ); -}; diff --git a/explorer/src/components/Nav.tsx b/explorer/src/components/Nav.tsx deleted file mode 100644 index a0f5b16fecc..00000000000 --- a/explorer/src/components/Nav.tsx +++ /dev/null @@ -1,401 +0,0 @@ -import * as React from 'react'; -import { Link } from 'react-router-dom'; -import { ExpandLess, ExpandMore, Menu } from '@mui/icons-material'; -import { CSSObject, styled, Theme, useTheme } from '@mui/material/styles'; -import Button from '@mui/material/Button'; -import MuiLink from '@mui/material/Link'; -import Box from '@mui/material/Box'; -import ListItem from '@mui/material/ListItem'; -import MuiDrawer from '@mui/material/Drawer'; -import AppBar from '@mui/material/AppBar'; -import Toolbar from '@mui/material/Toolbar'; -import List from '@mui/material/List'; -import Typography from '@mui/material/Typography'; -import IconButton from '@mui/material/IconButton'; -import ListItemButton from '@mui/material/ListItemButton'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import ListItemText from '@mui/material/ListItemText'; -import { NymLogo } from '@nymproject/react/logo/NymLogo'; -import { MaintenanceBanner } from '@nymproject/react/banners/MaintenanceBanner'; -import { NYM_WEBSITE } from '../api/constants'; -import { useMainContext } from '../context/main'; -import { MobileDrawerClose } from '../icons/MobileDrawerClose'; -import { Footer } from './Footer'; -import { DarkLightSwitchDesktop } from './Switch'; -import { NavOptionType } from '../context/nav'; -import { ConnectKeplrWallet } from './Wallet/ConnectKeplrWallet'; - -const drawerWidth = 255; -const bannerHeight = 80; - -const openedMixin = (theme: Theme): CSSObject => ({ - width: drawerWidth, - transition: theme.transitions.create('width', { - easing: theme.transitions.easing.sharp, - duration: theme.transitions.duration.enteringScreen, - }), - overflowX: 'hidden', -}); - -const closedMixin = (theme: Theme): CSSObject => ({ - transition: theme.transitions.create('width', { - easing: theme.transitions.easing.sharp, - duration: theme.transitions.duration.leavingScreen, - }), - overflowX: 'hidden', - width: `calc(${theme.spacing(7)} + 1px)`, -}); - -const DrawerHeader = styled('div')(({ theme }) => ({ - display: 'flex', - alignItems: 'center', - justifyContent: 'flex-end', - padding: theme.spacing(0, 1), - height: 64, -})); - -const Drawer = styled(MuiDrawer, { - shouldForwardProp: (prop) => prop !== 'open', -})(({ theme, open }) => ({ - width: drawerWidth, - flexShrink: 0, - whiteSpace: 'nowrap', - boxSizing: 'border-box', - ...(open && { - ...openedMixin(theme), - '& .MuiDrawer-paper': openedMixin(theme), - }), - ...(!open && { - ...closedMixin(theme), - '& .MuiDrawer-paper': closedMixin(theme), - }), -})); - -type ExpandableButtonType = { - title: string; - url: string; - isActive?: boolean; - Icon?: React.ReactNode; - nested?: NavOptionType[]; - isChild?: boolean; - openDrawer: () => void; - closeDrawer?: () => void; - drawIsTempOpen: boolean; - drawIsFixed: boolean; - fixDrawerClose?: () => void; - isMobile: boolean; - setToActive: (url: string) => void; -}; - -export const ExpandableButton: FCWithChildren<ExpandableButtonType> = ({ - url, - setToActive, - isActive, - openDrawer, - closeDrawer, - drawIsTempOpen, - drawIsFixed, - fixDrawerClose, - Icon, - title, - nested, - isMobile, - isChild, -}) => { - const [dynamicStyle, setDynamicStyle] = React.useState({}); - const [nestedOptions, toggleNestedOptions] = React.useState(false); - const [isExternal, setIsExternal] = React.useState<boolean>(false); - const { palette } = useTheme(); - - const handleClick = () => { - setToActive(url); - if (title === 'Network Components' && nested) { - openDrawer(); - toggleNestedOptions(!nestedOptions); - } - if (!nested && !drawIsFixed) { - closeDrawer?.(); - } - if (!nested && isMobile) { - fixDrawerClose?.(); - } - }; - - React.useEffect(() => { - if (url) { - setIsExternal(url.includes('http')); - } - if (nested) { - setDynamicStyle({ - background: palette.nym.networkExplorer.nav.selected.main, - borderRight: `3px solid ${palette.nym.highlight}`, - }); - } - if (isChild) { - setDynamicStyle({ - background: palette.nym.networkExplorer.nav.selected.nested, - fontWeight: 600, - }); - } - if (!nested && !isChild) { - setDynamicStyle({ - background: palette.nym.networkExplorer.nav.selected.main, - borderRight: `3px solid ${palette.nym.highlight}`, - }); - } - }, [url]); - - React.useEffect(() => { - if (!drawIsTempOpen && nestedOptions) { - toggleNestedOptions(false); - } - }, [drawIsTempOpen]); - - const linkProps = isExternal - ? { - component: 'a', - href: url, - target: '_blank', - } - : { component: !nested ? Link : 'div', to: url }; - - return ( - <> - <ListItem - disablePadding - disableGutters - {...linkProps} - sx={{ - borderBottom: isChild ? 'none' : '1px solid rgba(255, 255, 255, 0.1)', - ...(isActive - ? dynamicStyle - : { - background: palette.nym.networkExplorer.nav.background, - borderRight: 'none', - }), - }} - > - <ListItemButton - onClick={handleClick} - sx={{ - pt: 2, - pb: 2, - background: isChild ? palette.nym.networkExplorer.nav.selected.nested : 'none', - }} - > - <ListItemIcon sx={{ minWidth: '39px' }}>{Icon}</ListItemIcon> - <ListItemText - primary={title} - sx={{ - color: palette.nym.networkExplorer.nav.text, - }} - primaryTypographyProps={{ - style: { - fontWeight: isActive ? 600 : 400, - }, - }} - /> - {nested && nestedOptions && <ExpandLess />} - {nested && !nestedOptions && <ExpandMore />} - </ListItemButton> - </ListItem> - {nestedOptions && - nested?.map((each) => ( - <ExpandableButton - url={each.url} - key={each.title} - title={each.title} - openDrawer={openDrawer} - drawIsTempOpen={drawIsTempOpen} - closeDrawer={closeDrawer} - setToActive={setToActive} - drawIsFixed={drawIsFixed} - fixDrawerClose={fixDrawerClose} - isMobile={isMobile} - isChild - /> - ))} - </> - ); -}; - -ExpandableButton.defaultProps = { - Icon: null, - nested: undefined, - isChild: false, - isActive: false, - fixDrawerClose: undefined, - closeDrawer: undefined, -}; - -export const Nav: FCWithChildren = ({ children }) => { - const { updateNavState, navState, environment } = useMainContext(); - const [drawerIsOpen, setDrawerToOpen] = React.useState(false); - const [fixedOpen, setFixedOpen] = React.useState(false); - // Set maintenance banner to false by default to don't display it - const [openMaintenance, setOpenMaintenance] = React.useState(false); - const theme = useTheme(); - - const explorerName = - `${environment && environment.charAt(0).toUpperCase() + environment.slice(1)} Explorer` || 'Mainnet Explorer'; - - const switchNetworkText = environment === 'mainnet' ? 'Switch to Testnet' : 'Switch to Mainnet'; - const switchNetworkLink = - environment === 'mainnet' ? 'https://sandbox-explorer.nymtech.net' : 'https://explorer.nymtech.net'; - - const setToActive = (url: string) => { - updateNavState(url); - }; - - const fixDrawerOpen = () => { - setFixedOpen(true); - setDrawerToOpen(true); - }; - - const fixDrawerClose = () => { - setFixedOpen(false); - setDrawerToOpen(false); - }; - - const tempDrawerOpen = () => { - if (!fixedOpen) { - setDrawerToOpen(true); - } - }; - - const tempDrawerClose = () => { - if (!fixedOpen) { - setDrawerToOpen(false); - } - }; - - return ( - <Box sx={{ display: 'flex' }}> - <AppBar - sx={{ - background: theme.palette.nym.networkExplorer.topNav.appBar, - borderRadius: 0, - }} - > - <MaintenanceBanner open={openMaintenance} onClick={() => setOpenMaintenance(false)} height={bannerHeight} /> - <Toolbar - disableGutters - sx={{ - display: 'flex', - justifyContent: 'space-between', - }} - > - <Box - sx={{ - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - ml: 0.5, - }} - > - <IconButton component="a" href={NYM_WEBSITE} target="_blank"> - <NymLogo height="40px" width="40px" /> - </IconButton> - <Typography - variant="h6" - noWrap - sx={{ - color: theme.palette.nym.networkExplorer.nav.text, - fontSize: '18px', - fontWeight: 600, - }} - > - <MuiLink component={Link} to="/" underline="none" color="inherit"> - {explorerName} - </MuiLink> - <Button - size="small" - variant="outlined" - color="inherit" - href={switchNetworkLink} - sx={{ borderRadius: 2, textTransform: 'none', width: 150, ml: 4, fontSize: 14, fontWeight: 600 }} - > - {switchNetworkText} - </Button> - </Typography> - </Box> - <Box - sx={{ - mr: 2, - alignItems: 'center', - display: 'flex', - }} - > - <Box - sx={{ - display: 'flex', - flexDirection: 'row', - width: 'auto', - pr: 0, - pl: 2, - justifyContent: 'flex-end', - alignItems: 'center', - }} - > - <Box sx={{ mr: 1 }}> - <ConnectKeplrWallet /> - </Box> - <DarkLightSwitchDesktop defaultChecked /> - </Box> - </Box> - </Toolbar> - </AppBar> - <Drawer - variant="permanent" - open={drawerIsOpen} - PaperProps={{ - style: { - background: theme.palette.nym.networkExplorer.nav.background, - borderRadius: 0, - top: openMaintenance ? bannerHeight : 0, - }, - }} - > - <DrawerHeader - sx={{ - borderBottom: '1px solid rgba(255, 255, 255, 0.1)', - justifyContent: 'flex-start', - paddingLeft: 0, - }} - > - <IconButton - onClick={drawerIsOpen ? fixDrawerClose : fixDrawerOpen} - sx={{ - padding: 1, - ml: 1, - color: theme.palette.nym.networkExplorer.nav.text, - }} - > - {drawerIsOpen ? <MobileDrawerClose /> : <Menu />} - </IconButton> - </DrawerHeader> - - <List sx={{ pt: 0, pb: 0 }} onMouseEnter={tempDrawerOpen} onMouseLeave={tempDrawerClose}> - {navState.map((props) => ( - <ExpandableButton - key={props.url} - closeDrawer={tempDrawerClose} - drawIsTempOpen={drawerIsOpen} - drawIsFixed={fixedOpen} - fixDrawerClose={fixDrawerClose} - openDrawer={tempDrawerOpen} - setToActive={setToActive} - isMobile={false} - {...props} - /> - ))} - </List> - </Drawer> - <Box sx={{ width: '100%', py: 5, px: 6, mt: 7 }}> - {children} - <Footer /> - </Box> - </Box> - ); -}; diff --git a/explorer/src/components/NetworkTitle.tsx b/explorer/src/components/NetworkTitle.tsx deleted file mode 100644 index 7dd87d7e42f..00000000000 --- a/explorer/src/components/NetworkTitle.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from 'react'; -import { Button, Typography } from '@mui/material'; -import { Link } from 'react-router-dom'; -import MuiLink from '@mui/material/Link'; -import { useMainContext } from '@src/context/main'; - -type NetworkTitleProps = { - showToggleNetwork?: boolean; -}; - -const NetworkTitle = ({ showToggleNetwork }: NetworkTitleProps) => { - const { environment } = useMainContext(); - - const explorerName = - `${environment && environment.charAt(0).toUpperCase() + environment.slice(1)} Explorer` || 'Mainnet Explorer'; - - const switchNetworkText = environment === 'mainnet' ? 'Switch to Testnet' : 'Switch to Mainnet'; - const switchNetworkLink = - environment === 'mainnet' ? 'https://sandbox-explorer.nymtech.net' : 'https://explorer.nymtech.net'; - return ( - <Typography - variant="h6" - noWrap - sx={{ - color: 'nym.networkExplorer.nav.text', - fontSize: '18px', - fontWeight: 600, - }} - > - <MuiLink component={Link} to="/overview" underline="none" color="inherit" fontWeight={700}> - {explorerName} - </MuiLink> - {showToggleNetwork && ( - <Button - variant="outlined" - color="inherit" - href={switchNetworkLink} - sx={{ textTransform: 'none', width: 114, fontSize: '12px', fontWeight: 600, ml: 1 }} - > - {switchNetworkText} - </Button> - )} - </Typography> - ); -}; - -export default NetworkTitle; diff --git a/explorer/src/components/Socials.tsx b/explorer/src/components/Socials.tsx deleted file mode 100644 index e1bb33970b7..00000000000 --- a/explorer/src/components/Socials.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import * as React from 'react'; -import { Box, IconButton } from '@mui/material'; -import { useTheme } from '@mui/material/styles'; -import { TelegramIcon } from '../icons/socials/TelegramIcon'; -import { GitHubIcon } from '../icons/socials/GitHubIcon'; -import { TwitterIcon } from '../icons/socials/TwitterIcon'; -import { DiscordIcon } from '../icons/socials/DiscordIcon'; - -// socials -export const TELEGRAM_LINK = 'https://nymtech.net/go/telegram'; -export const TWITTER_LINK = 'https://nymtech.net/go/x'; -export const GITHUB_LINK = 'https://nymtech.net/go/github'; -export const DISCORD_LINK = 'https://nymtech.net/go/discord'; - -export const Socials: FCWithChildren<{ isFooter?: boolean }> = ({ isFooter }) => { - const theme = useTheme(); - const color = isFooter - ? theme.palette.nym.networkExplorer.footer.socialIcons - : theme.palette.nym.networkExplorer.topNav.socialIcons; - return ( - <Box> - <IconButton component="a" href={TELEGRAM_LINK} target="_blank" data-testid="telegram"> - <TelegramIcon color={color} size={24} /> - </IconButton> - <IconButton component="a" href={DISCORD_LINK} target="_blank" data-testid="discord"> - <DiscordIcon color={color} size={24} /> - </IconButton> - <IconButton component="a" href={TWITTER_LINK} target="_blank" data-testid="twitter"> - <TwitterIcon color={color} size={24} /> - </IconButton> - <IconButton component="a" href={GITHUB_LINK} target="_blank" data-testid="github"> - <GitHubIcon color={color} size={24} /> - </IconButton> - </Box> - ); -}; - -Socials.defaultProps = { - isFooter: false, -}; diff --git a/explorer/src/components/StatsCard.tsx b/explorer/src/components/StatsCard.tsx deleted file mode 100644 index 36355b17598..00000000000 --- a/explorer/src/components/StatsCard.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import * as React from 'react'; -import { Box, Card, CardContent, IconButton, Typography } from '@mui/material'; -import { useTheme } from '@mui/material/styles'; -import EastIcon from '@mui/icons-material/East'; - -interface StatsCardProps { - icon: React.ReactNode; - title: string; - count?: string | number; - errorMsg?: Error | string; - onClick?: () => void; - color?: string; -} -export const StatsCard: FCWithChildren<StatsCardProps> = ({ - icon, - title, - count, - onClick, - errorMsg, - color: colorProp, -}) => { - const theme = useTheme(); - const color = colorProp || theme.palette.text.primary; - return ( - <Card onClick={onClick} sx={{ height: '100%' }}> - <CardContent - sx={{ - padding: 1.5, - paddingLeft: 3, - '&:last-child': { - paddingBottom: 1.5, - }, - cursor: 'pointer', - fontSize: 14, - fontWeight: 600, - }} - > - <Box display="flex" alignItems="center" color={color}> - <Box display="flex"> - {icon} - <Typography ml={3} mr={0.75} fontSize="inherit" fontWeight="inherit" data-testid={`${title}-amount`}> - {count === undefined || count === null ? '' : count} - </Typography> - <Typography mr={1} fontSize="inherit" fontWeight="inherit" data-testid={title}> - {title} - </Typography> - </Box> - <IconButton color="inherit" sx={{ fontSize: '16px' }}> - <EastIcon fontSize="inherit" /> - </IconButton> - </Box> - {errorMsg && ( - <Typography variant="body2" sx={{ color: 'danger', padding: 2 }}> - {typeof errorMsg === 'string' ? errorMsg : errorMsg.message || 'Oh no! An error occurred'} - </Typography> - )} - </CardContent> - </Card> - ); -}; - -StatsCard.defaultProps = { - onClick: undefined, - errorMsg: undefined, - color: undefined, - count: undefined, -}; diff --git a/explorer/src/components/StyledLink.tsx b/explorer/src/components/StyledLink.tsx deleted file mode 100644 index fd101e5b4a3..00000000000 --- a/explorer/src/components/StyledLink.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; -import { Link as MuiLink, SxProps } from '@mui/material'; -import { Link as RRDL } from 'react-router-dom'; - -type StyledLinkProps = { - to: string; - children: string; - target?: React.HTMLAttributeAnchorTarget; - dataTestId?: string; - color?: string; - sx?: SxProps; -}; - -const StyledLink = ({ to, children, dataTestId, target, color = 'inherit', sx }: StyledLinkProps) => ( - <MuiLink - sx={{ ...sx }} - color={color} - target={target} - underline="none" - component={RRDL} - to={to} - data-testid={dataTestId} - > - {children} - </MuiLink> -); - -export default StyledLink; diff --git a/explorer/src/components/Switch.tsx b/explorer/src/components/Switch.tsx deleted file mode 100644 index 840530a3277..00000000000 --- a/explorer/src/components/Switch.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import * as React from 'react'; -import { styled } from '@mui/material/styles'; -import Switch from '@mui/material/Switch'; -import { Button } from '@mui/material'; -import { useMainContext } from '../context/main'; -import { LightSwitchSVG } from '../icons/LightSwitchSVG'; - -export const DarkLightSwitch = styled(Switch)(({ theme }) => ({ - width: 55, - height: 34, - padding: 7, - '& .MuiSwitch-switchBase': { - margin: 1, - padding: 2, - transform: 'translateX(4px)', - '&.Mui-checked': { - color: '#fff', - transform: 'translateX(22px)', - '& .MuiSwitch-thumb:before': { - backgroundImage: - 'url(\'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 20 20"><path fill="black" d="M4.2 2.5l-.7 1.8-1.8.7 1.8.7.7 1.8.6-1.8L6.7 5l-1.9-.7-.6-1.8zm15 8.3a6.7 6.7 0 11-6.6-6.6 5.8 5.8 0 006.6 6.6z"/></svg>\')', - }, - '& + .MuiSwitch-track': { - opacity: 1, - backgroundColor: theme.palette.mode === 'dark' ? '#8796A5' : '#aab4be', - }, - }, - }, - '& .MuiSwitch-thumb': { - backgroundColor: theme.palette.nym.networkExplorer.nav.text, - width: 25, - height: 25, - marginTop: '2px', - '&:before': { - content: "''", - position: 'absolute', - width: '100%', - height: '100%', - left: 0, - top: 0, - backgroundRepeat: 'no-repeat', - backgroundPosition: 'center', - backgroundImage: - 'url(\'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 20 20"><path fill="black" d="M9.305 1.667V3.75h1.389V1.667h-1.39zm-4.707 1.95l-.982.982L5.09 6.072l.982-.982-1.473-1.473zm10.802 0L13.927 5.09l.982.982 1.473-1.473-.982-.982zM10 5.139a4.872 4.872 0 00-4.862 4.86A4.872 4.872 0 0010 14.862 4.872 4.872 0 0014.86 10 4.872 4.872 0 0010 5.139zm0 1.389A3.462 3.462 0 0113.471 10a3.462 3.462 0 01-3.473 3.472A3.462 3.462 0 016.527 10 3.462 3.462 0 0110 6.528zM1.665 9.305v1.39h2.083v-1.39H1.666zm14.583 0v1.39h2.084v-1.39h-2.084zM5.09 13.928L3.616 15.4l.982.982 1.473-1.473-.982-.982zm9.82 0l-.982.982 1.473 1.473.982-.982-1.473-1.473zM9.305 16.25v2.083h1.389V16.25h-1.39z"/></svg>\')', - }, - }, - '& .MuiSwitch-track': { - opacity: 1, - backgroundColor: theme.palette.mode === 'dark' ? '#8796A5' : '#aab4be', - borderRadius: 20 / 2, - }, -})); - -export const DarkLightSwitchMobile: FCWithChildren = () => { - const { toggleMode } = useMainContext(); - return ( - <Button onClick={() => toggleMode()} data-testid="switch-button" sx={{ p: 0, minWidth: 0 }}> - <LightSwitchSVG /> - </Button> - ); -}; - -export const DarkLightSwitchDesktop: FCWithChildren<{ defaultChecked: boolean }> = ({ defaultChecked }) => { - const { toggleMode } = useMainContext(); - return ( - <Button sx={{ paddingLeft: 0 }} onClick={() => toggleMode()} data-testid="switch-button"> - <DarkLightSwitch defaultChecked={defaultChecked} /> - </Button> - ); -}; diff --git a/explorer/src/components/TableToolbar.tsx b/explorer/src/components/TableToolbar.tsx deleted file mode 100644 index d3af5221686..00000000000 --- a/explorer/src/components/TableToolbar.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import React from 'react'; -import { Box, TextField, MenuItem, FormControl, IconButton, Select, SelectChangeEvent } from '@mui/material'; -import { Close } from '@mui/icons-material'; -import { Filters } from './Filters/Filters'; -import { useIsMobile } from '../hooks/useIsMobile'; - -const fieldsHeight = '42.25px'; - -type TableToolBarProps = { - onChangeSearch?: (arg: string) => void; - onChangePageSize: (event: SelectChangeEvent<string>) => void; - pageSize: string; - searchTerm?: string; - withFilters?: boolean; - childrenBefore?: React.ReactNode; - childrenAfter?: React.ReactNode; -}; - -export const TableToolbar: FCWithChildren<TableToolBarProps> = ({ - searchTerm, - onChangeSearch, - onChangePageSize, - pageSize, - childrenBefore, - childrenAfter, - withFilters, -}) => { - const isMobile = useIsMobile(); - return ( - <Box - sx={{ - width: '100%', - marginBottom: 2, - display: 'flex', - flexDirection: isMobile ? 'column' : 'row', - justifyContent: 'space-between', - }} - > - <Box sx={{ display: 'flex', flexDirection: isMobile ? 'column-reverse' : 'row', alignItems: 'middle' }}> - <Box sx={{ display: 'flex', justifyContent: 'space-between', height: fieldsHeight }}> - {childrenBefore} - <FormControl size="small"> - <Select - value={pageSize} - onChange={onChangePageSize} - sx={{ - width: isMobile ? '100%' : 200, - marginRight: isMobile ? 0 : 2, - }} - > - <MenuItem value={10} data-testid="ten"> - 10 - </MenuItem> - <MenuItem value={30} data-testid="thirty"> - 30 - </MenuItem> - <MenuItem value={50} data-testid="fifty"> - 50 - </MenuItem> - <MenuItem value={100} data-testid="hundred"> - 100 - </MenuItem> - </Select> - </FormControl> - </Box> - {!!onChangeSearch && ( - <TextField - sx={{ - width: isMobile ? '100%' : 200, - marginBottom: isMobile ? 2 : 0, - }} - size="small" - value={searchTerm} - data-testid="search-box" - placeholder="Search" - InputProps={{ - endAdornment: searchTerm?.length ? ( - <IconButton size="small" onClick={() => onChangeSearch('')}> - <Close fontSize="small" /> - </IconButton> - ) : undefined, - }} - onChange={(event) => onChangeSearch(event.target.value)} - /> - )} - </Box> - - <Box - sx={{ - display: 'flex', - alignItems: 'center', - justifyContent: 'end', - gap: 1, - marginTop: isMobile ? 2 : 0, - }} - > - {withFilters && <Filters />} - {childrenAfter} - </Box> - </Box> - ); -}; diff --git a/explorer/src/components/Title.tsx b/explorer/src/components/Title.tsx deleted file mode 100644 index 032837d3c85..00000000000 --- a/explorer/src/components/Title.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from 'react'; -import { Typography } from '@mui/material'; - -export const Title: FCWithChildren<{ text: string }> = ({ text }) => ( - <Typography - variant="h5" - sx={{ - fontWeight: 600, - }} - data-testid={text} - > - {text} - </Typography> -); diff --git a/explorer/src/components/Tooltip.tsx b/explorer/src/components/Tooltip.tsx deleted file mode 100644 index 0febd9f8914..00000000000 --- a/explorer/src/components/Tooltip.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React, { ReactElement } from 'react'; -import { Tooltip as MUITooltip, TooltipComponentsPropsOverrides, TooltipProps } from '@mui/material'; - -type ValueType<T> = T[keyof T]; - -type Props = { - text: string; - id: string; - placement?: ValueType<Pick<TooltipProps, 'placement'>>; - tooltipSx?: TooltipComponentsPropsOverrides; - children: React.ReactNode; -}; - -export const Tooltip = ({ text, id, placement, tooltipSx, children }: Props) => ( - <MUITooltip - title={text} - id={id} - placement={placement || 'top-start'} - componentsProps={{ - tooltip: { - sx: { - maxWidth: 200, - background: (t) => t.palette.nym.networkExplorer.tooltip.background, - color: (t) => t.palette.nym.networkExplorer.tooltip.color, - '& .MuiTooltip-arrow': { - color: (t) => t.palette.nym.networkExplorer.tooltip.background, - }, - }, - ...tooltipSx, - }, - }} - arrow - > - {children as ReactElement<any, any>} - </MUITooltip> -); diff --git a/explorer/src/components/TwoColSmallTable.tsx b/explorer/src/components/TwoColSmallTable.tsx deleted file mode 100644 index a211c29bdd7..00000000000 --- a/explorer/src/components/TwoColSmallTable.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import * as React from 'react'; -import { CircularProgress, Typography } from '@mui/material'; -import Table from '@mui/material/Table'; -import TableBody from '@mui/material/TableBody'; -import TableCell from '@mui/material/TableCell'; -import TableContainer from '@mui/material/TableContainer'; -import TableRow from '@mui/material/TableRow'; -import Paper from '@mui/material/Paper'; -import CheckCircleSharpIcon from '@mui/icons-material/CheckCircleSharp'; -import ErrorIcon from '@mui/icons-material/Error'; - -interface TableProps { - title?: string; - icons?: boolean[]; - keys: string[]; - values: number[]; - marginBottom?: boolean; - error?: string; - loading: boolean; -} - -export const TwoColSmallTable: FCWithChildren<TableProps> = ({ - loading, - title, - icons, - keys, - values, - marginBottom, - error, -}) => ( - <> - {title && <Typography sx={{ marginTop: 2 }}>{title}</Typography>} - - <TableContainer component={Paper} sx={marginBottom ? { marginBottom: 4, marginTop: 2 } : { marginTop: 2 }}> - <Table aria-label="two col small table"> - <TableBody> - {keys.map((each: string, i: number) => ( - <TableRow key={each}> - {icons && <TableCell>{icons[i] ? <CheckCircleSharpIcon /> : <ErrorIcon />}</TableCell>} - <TableCell sx={error ? { opacity: 0.4 } : null} data-testid={each.replace(/ /g, '')}> - {each} - </TableCell> - <TableCell - sx={error ? { opacity: 0.4 } : null} - align="right" - data-testid={`${each.replace(/ /g, '-')}-value`} - > - {values[i]} - </TableCell> - {error && ( - <TableCell align="right" sx={{ opacity: 0.4 }}> - {values[i]} - </TableCell> - )} - {!error && loading && ( - <TableCell align="right"> - <CircularProgress /> - </TableCell> - )} - {error && !icons && ( - <TableCell sx={{ opacity: 0.2 }} align="right"> - <ErrorIcon /> - </TableCell> - )} - </TableRow> - ))} - </TableBody> - </Table> - </TableContainer> - </> -); - -TwoColSmallTable.defaultProps = { - title: undefined, - icons: undefined, - marginBottom: false, - error: undefined, -}; diff --git a/explorer/src/components/Universal-DataGrid.tsx b/explorer/src/components/Universal-DataGrid.tsx deleted file mode 100644 index 6598dfb4855..00000000000 --- a/explorer/src/components/Universal-DataGrid.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import * as React from 'react'; -import { makeStyles } from '@mui/styles'; -import { DataGrid, GridColDef, GridEventListener, useGridApiContext, useGridState } from '@mui/x-data-grid'; -import Pagination from '@mui/material/Pagination'; -import { LinearProgress } from '@mui/material'; -import { GridInitialStateCommunity } from '@mui/x-data-grid/models/gridStateCommunity'; - -const useStyles = makeStyles({ - root: { - display: 'flex', - }, -}); - -const CustomPagination = () => { - const apiRef = useGridApiContext(); - const [state] = useGridState(apiRef); - - const classes = useStyles(); - - return ( - <Pagination - className={classes.root} - sx={{ mt: 2 }} - color="primary" - count={state.pagination.pageCount} - page={state.pagination.page + 1} - onChange={(_, value) => apiRef.current.setPage(value - 1)} - /> - ); -}; - -type DataGridProps = { - columns: GridColDef[]; - pagination?: true | undefined; - pageSize?: string | undefined; - rows: any; - loading?: boolean; - initialState?: GridInitialStateCommunity; - onRowClick?: GridEventListener<'rowClick'> | undefined; -}; -export const UniversalDataGrid: FCWithChildren<DataGridProps> = ({ - rows, - columns, - loading, - pagination, - pageSize, - initialState, - onRowClick, -}) => { - if (loading) return <LinearProgress />; - - return ( - <DataGrid - onRowClick={onRowClick} - pagination={pagination} - rows={rows} - components={{ - Pagination: CustomPagination, - }} - columns={columns} - pageSize={Number(pageSize)} - disableSelectionOnClick - autoHeight - hideFooter={!pagination} - initialState={initialState} - style={{ - width: '100%', - border: 'none', - }} - sx={{ - '*::-webkit-scrollbar': { - width: '1em', - }, - '*::-webkit-scrollbar-track': { - background: (t) => t.palette.nym.networkExplorer.scroll.backgroud, - outline: (t) => `1px solid ${t.palette.nym.networkExplorer.scroll.border}`, - boxShadow: 'auto', - borderRadius: 'auto', - }, - '*::-webkit-scrollbar-thumb': { - backgroundColor: (t) => t.palette.nym.networkExplorer.scroll.color, - borderRadius: '20px', - width: '.4em', - border: (t) => `3px solid ${t.palette.nym.networkExplorer.scroll.backgroud}`, - shadow: 'auto', - }, - }} - /> - ); -}; - -UniversalDataGrid.defaultProps = { - loading: false, - pagination: undefined, - pageSize: '10', -}; diff --git a/explorer/src/components/UptimeChart.tsx b/explorer/src/components/UptimeChart.tsx deleted file mode 100644 index 00a981a3afc..00000000000 --- a/explorer/src/components/UptimeChart.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import * as React from 'react'; -import { CircularProgress, Typography } from '@mui/material'; -import { useTheme } from '@mui/material/styles'; -import { Chart } from 'react-google-charts'; -import { format } from 'date-fns'; -import { ApiState, UptimeStoryResponse } from '../typeDefs/explorer-api'; - -interface ChartProps { - title?: string; - xLabel: string; - yLabel?: string; - uptimeStory: ApiState<UptimeStoryResponse>; - loading: boolean; -} - -type FormattedDateRecord = [string, number]; -type FormattedChartHeadings = string[]; -type FormattedChartData = [FormattedChartHeadings | FormattedDateRecord]; - -export const UptimeChart: FCWithChildren<ChartProps> = ({ title, xLabel, yLabel, uptimeStory, loading }) => { - const [formattedChartData, setFormattedChartData] = React.useState<FormattedChartData>(); - const theme = useTheme(); - const color = theme.palette.text.primary; - React.useEffect(() => { - if (uptimeStory.data?.history) { - const allFormattedChartData: FormattedChartData = [['Date', 'Score']]; - uptimeStory.data.history.forEach((eachDate) => { - const formattedDateUptimeRecord: FormattedDateRecord = [ - format(new Date(eachDate.date), 'MMM dd'), - eachDate.uptime, - ]; - allFormattedChartData.push(formattedDateUptimeRecord); - }); - setFormattedChartData(allFormattedChartData); - } else { - const emptyData: any = [ - ['Date', 'Score'], - ['Jul 27', 10], - ]; - setFormattedChartData(emptyData); - } - }, [uptimeStory]); - - return ( - <> - {title && <Typography>{title}</Typography>} - {loading && <CircularProgress />} - - {!loading && uptimeStory && ( - <Chart - style={{ minHeight: 480 }} - chartType="LineChart" - loader={<p>...</p>} - data={ - uptimeStory.data - ? formattedChartData - : [ - ['Date', 'Routing Score'], - [format(new Date(Date.now()), 'MMM dd'), 0], - ] - } - options={{ - backgroundColor: - theme.palette.mode === 'dark' ? theme.palette.nym.networkExplorer.background.tertiary : undefined, - color: uptimeStory.error ? 'rgba(255, 255, 255, 0.4)' : 'rgba(255, 255, 255, 1)', - colors: ['#FB7A21'], - legend: { - textStyle: { - color, - opacity: uptimeStory.error ? 0.4 : 1, - }, - }, - - intervals: { style: 'sticks' }, - hAxis: { - // horizontal / date - title: xLabel, - titleTextStyle: { - color, - }, - textStyle: { - color, - // fontSize: 11 - }, - gridlines: { - count: -1, - }, - }, - vAxis: { - // vertical / % Routing Score - viewWindow: { - min: 0, - max: 100, - }, - title: yLabel, - titleTextStyle: { - color, - opacity: uptimeStory.error ? 0.4 : 1, - }, - textStyle: { - color, - fontSize: 11, - opacity: uptimeStory.error ? 0.4 : 1, - }, - }, - }} - /> - )} - </> - ); -}; - -UptimeChart.defaultProps = { - title: undefined, -}; diff --git a/explorer/src/components/Wallet/ConnectKeplrWallet.tsx b/explorer/src/components/Wallet/ConnectKeplrWallet.tsx deleted file mode 100644 index ff5d2691c69..00000000000 --- a/explorer/src/components/Wallet/ConnectKeplrWallet.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import React from 'react'; -import { Button, IconButton, Stack, CircularProgress } from '@mui/material'; -import CloseIcon from '@mui/icons-material/Close'; -import { useIsMobile } from '@src/hooks/useIsMobile'; -import { useWalletContext } from '@src/context/wallet'; -import { WalletAddress, WalletBalance } from '@src/components/Wallet'; - -export const ConnectKeplrWallet = () => { - const { connectWallet, disconnectWallet, isWalletConnected, isWalletConnecting } = useWalletContext(); - const isMobile = useIsMobile(1200); - - if (!connectWallet || !disconnectWallet) { - return null; - } - - if (isWalletConnected) { - return ( - <Stack direction="row" spacing={1}> - <WalletBalance /> - <WalletAddress /> - <IconButton - size="small" - onClick={async () => { - await disconnectWallet(); - }} - > - <CloseIcon fontSize="small" sx={{ color: 'white' }} /> - </IconButton> - </Stack> - ); - } - - return ( - <Button - variant="outlined" - onClick={() => connectWallet()} - disabled={isWalletConnecting} - endIcon={isWalletConnecting && <CircularProgress size={14} color="inherit" />} - > - Connect {isMobile ? '' : ' Wallet'} - </Button> - ); -}; diff --git a/explorer/src/components/Wallet/WalletAddress.tsx b/explorer/src/components/Wallet/WalletAddress.tsx deleted file mode 100644 index 8be6c9f2910..00000000000 --- a/explorer/src/components/Wallet/WalletAddress.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; -import { Box, Typography } from '@mui/material'; -import { ElipsSVG } from '@src/icons/ElipsSVG'; -import { trimAddress } from '@src/utils'; -import { useWalletContext } from '@src/context/wallet'; - -export const WalletAddress = () => { - const { address } = useWalletContext(); - - const displayAddress = trimAddress(address, 7); - - return ( - <Box display="flex" alignItems="center" gap={0.5}> - <ElipsSVG /> - <Typography variant="body1" fontWeight={600}> - {displayAddress} - </Typography> - </Box> - ); -}; diff --git a/explorer/src/components/Wallet/WalletBalance.tsx b/explorer/src/components/Wallet/WalletBalance.tsx deleted file mode 100644 index f94935ac235..00000000000 --- a/explorer/src/components/Wallet/WalletBalance.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; -import { Box, Typography } from '@mui/material'; -import { useWalletContext } from '@src/context/wallet'; -import { useIsMobile } from '@src/hooks'; -import { TokenSVG } from '@src/icons/TokenSVG'; - -export const WalletBalance = () => { - const { balance } = useWalletContext(); - const isMobile = useIsMobile(1200); - - const showBalance = !isMobile && balance.status === 'success'; - - if (!showBalance) { - return null; - } - - return ( - <Box display="flex" alignItems="center" gap={1}> - <TokenSVG /> - <Typography variant="body1" fontWeight={600}> - {balance.data} NYM - </Typography> - </Box> - ); -}; diff --git a/explorer/src/components/Wallet/index.ts b/explorer/src/components/Wallet/index.ts deleted file mode 100644 index 645c8b4ffb1..00000000000 --- a/explorer/src/components/Wallet/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './WalletBalance'; -export * from './WalletAddress'; diff --git a/explorer/src/components/WorldMap.tsx b/explorer/src/components/WorldMap.tsx deleted file mode 100644 index 7a86f340959..00000000000 --- a/explorer/src/components/WorldMap.tsx +++ /dev/null @@ -1,113 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -import * as React from 'react'; -import { scaleLinear } from 'd3-scale'; -import { ComposableMap, Geographies, Geography, Marker, ZoomableGroup } from 'react-simple-maps'; -import ReactTooltip from 'react-tooltip'; -import { CircularProgress } from '@mui/material'; -import { useTheme } from '@mui/material/styles'; -import { ApiState, CountryDataResponse } from '../typeDefs/explorer-api'; -import MAP_TOPOJSON from '../assets/world-110m.json'; - -type MapProps = { - userLocation?: [number, number]; - countryData?: ApiState<CountryDataResponse>; - loading: boolean; -}; - -export const WorldMap: FCWithChildren<MapProps> = ({ countryData, userLocation, loading }) => { - const { palette } = useTheme(); - - const colorScale = React.useMemo(() => { - if (countryData?.data) { - const heighestNumberOfNodes = Math.max(...Object.values(countryData.data).map((country) => country.nodes)); - return scaleLinear<string, string>() - .domain([0, 1, heighestNumberOfNodes / 4, heighestNumberOfNodes / 2, heighestNumberOfNodes]) - .range(palette.nym.networkExplorer.map.fills) - .unknown(palette.nym.networkExplorer.map.fills[0]); - } - return () => palette.nym.networkExplorer.map.fills[0]; - }, [countryData, palette]); - - const [tooltipContent, setTooltipContent] = React.useState<string | null>(null); - - if (loading) { - return <CircularProgress />; - } - - return ( - <> - <ComposableMap - data-tip="" - style={{ - backgroundColor: palette.nym.networkExplorer.background.tertiary, - width: '100%', - height: 'auto', - }} - viewBox="0, 50, 800, 350" - projection="geoMercator" - projectionConfig={{ - scale: userLocation ? 200 : 100, - center: userLocation, - }} - > - <ZoomableGroup> - <Geographies geography={MAP_TOPOJSON}> - {({ geographies }) => - geographies.map((geo) => { - const d = (countryData?.data || {})[geo.properties.ISO_A3]; - return ( - <Geography - key={geo.rsmKey} - geography={geo} - fill={colorScale(d?.nodes || 0)} - stroke={palette.nym.networkExplorer.map.stroke} - strokeWidth={0.2} - onMouseEnter={() => { - const { NAME_LONG } = geo.properties; - if (!userLocation) { - setTooltipContent(`${NAME_LONG} | ${d?.nodes || 0}`); - } - }} - onMouseLeave={() => { - setTooltipContent(''); - }} - style={{ - hover: - !userLocation && countryData - ? { - fill: palette.nym.highlight, - outline: 'white', - } - : undefined, - }} - /> - ); - }) - } - </Geographies> - - {userLocation && ( - <Marker coordinates={userLocation}> - <g - fill="grey" - stroke="#FF5533" - strokeWidth="2" - strokeLinecap="round" - strokeLinejoin="round" - transform="translate(-12, -10)" - > - <circle cx="12" cy="10" r="5" /> - </g> - </Marker> - )} - </ZoomableGroup> - </ComposableMap> - <ReactTooltip>{tooltipContent}</ReactTooltip> - </> - ); -}; - -WorldMap.defaultProps = { - userLocation: undefined, - countryData: undefined, -}; diff --git a/explorer/src/components/delegatorsInfo/types.ts b/explorer/src/components/delegatorsInfo/types.ts deleted file mode 100644 index b0e3fd6e996..00000000000 --- a/explorer/src/components/delegatorsInfo/types.ts +++ /dev/null @@ -1,15 +0,0 @@ -export type RowsType = { - value?: string | number; - visualProgressValue?: number; -}; - -export interface DelegatorsInfoRow { - estimated_total_reward: RowsType; - estimated_operator_reward: RowsType; - active_set_probability: RowsType; - stake_saturation: RowsType; - profit_margin: RowsType; - avg_uptime: RowsType; -} - -export type DelegatorsInfoRowWithIndex = DelegatorsInfoRow & { id: number }; diff --git a/explorer/src/components/index.ts b/explorer/src/components/index.ts deleted file mode 100644 index 92eeebd0102..00000000000 --- a/explorer/src/components/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export * from './CustomColumnHeading'; -export * from './Title'; -export * from './Universal-DataGrid'; -export * from './Tooltip'; -export { default as StyledLink } from './StyledLink'; -export * from './Delegations'; -export * from './MixNodes'; -export * from './TableToolbar'; -export * from './Icons'; diff --git a/explorer/src/context/cosmos-kit.tsx b/explorer/src/context/cosmos-kit.tsx deleted file mode 100644 index ce82b21a179..00000000000 --- a/explorer/src/context/cosmos-kit.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import React from 'react'; -import { ChainProvider } from '@cosmos-kit/react'; -import { wallets as keplr } from '@cosmos-kit/keplr-extension'; -import { assets, chains } from 'chain-registry'; -import { Chain, AssetList } from '@chain-registry/types'; -import { VALIDATOR_BASE_URL } from '@src/api/constants'; - -const nymSandbox: Chain = { - chain_name: 'sandbox', - chain_id: 'sandbox', - bech32_prefix: 'n', - network_type: 'devnet', - pretty_name: 'Nym Sandbox', - status: 'active', - slip44: 118, - apis: { - rpc: [ - { - address: 'https://rpc.sandbox.nymtech.net', - }, - ], - }, -}; - -const nymSandboxAssets = { - chain_name: 'sandbox', - assets: [ - { - name: 'Nym', - base: 'unym', - symbol: 'NYM', - display: 'NYM', - denom_units: [], - }, - ], -}; - -const CosmosKitProvider = ({ children }: { children: React.ReactNode }) => { - // Only use the nyx chains - const chainsFixedUp = React.useMemo(() => { - const nyx = chains.find((chain) => chain.chain_id === 'nyx'); - - return nyx ? [nymSandbox, nyx] : [nymSandbox]; - }, [chains]); - - // Only use the nyx assets - const assetsFixedUp = React.useMemo(() => { - const nyx = assets.find((asset) => asset.chain_name === 'nyx'); - - return nyx ? [nyx] : [nymSandboxAssets]; - }, [assets]) as AssetList[]; - - return ( - <ChainProvider - chains={chainsFixedUp} - assetLists={assetsFixedUp} - wallets={[...keplr]} - endpointOptions={{ - endpoints: { - nyx: { - rpc: [VALIDATOR_BASE_URL], - }, - }, - }} - > - {children} - </ChainProvider> - ); -}; - -export default CosmosKitProvider; diff --git a/explorer/src/context/delegations.tsx b/explorer/src/context/delegations.tsx deleted file mode 100644 index 28a50345e06..00000000000 --- a/explorer/src/context/delegations.tsx +++ /dev/null @@ -1,200 +0,0 @@ -import React, { createContext, useCallback, useContext, useMemo, useState } from 'react'; -import { Delegation, PendingEpochEvent, PendingEpochEventKind } from '@nymproject/contract-clients/Mixnet.types'; -import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'; -import { useWalletContext } from './wallet'; -import { useMainContext } from './main'; - -const fee = { gas: '1000000', amount: [{ amount: '1000000', denom: 'unym' }] }; - -export type PendingEvent = ReturnType<typeof getEventsByAddress>; - -export type DelegationWithRewards = Delegation & { - rewards: string; - identityKey: string; - pending: PendingEvent; -}; - -const getEventsByAddress = (kind: PendingEpochEventKind, address: String) => { - if ('delegate' in kind && kind.delegate.owner === address) { - return { - kind: 'delegate' as const, - mixId: kind.delegate.mix_id, - amount: kind.delegate.amount, - }; - } - - if ('undelegate' in kind && kind.undelegate.owner === address) { - return { - kind: 'undelegate' as const, - mixId: kind.undelegate.mix_id, - }; - } - - return undefined; -}; - -interface DelegationsState { - delegations?: DelegationWithRewards[]; - handleGetDelegations: () => Promise<void>; - handleDelegate: (mixId: number, amount: string) => Promise<ExecuteResult | undefined>; - handleUndelegate: (mixId: number) => Promise<ExecuteResult | undefined>; -} - -export const DelegationsContext = createContext<DelegationsState>({ - delegations: undefined, - handleGetDelegations: async () => { - throw new Error('Please connect your wallet'); - }, - handleDelegate: async () => { - throw new Error('Please connect your wallet'); - }, - handleUndelegate: async () => { - throw new Error('Please connect your wallet'); - }, -}); - -export const DelegationsProvider = ({ children }: { children: React.ReactNode }) => { - const [delegations, setDelegations] = useState<DelegationWithRewards[]>(); - const { address, nymQueryClient, nymClient } = useWalletContext(); - const { fetchMixnodes } = useMainContext(); - - const handleGetPendingEvents = async () => { - if (!nymQueryClient) { - return undefined; - } - - if (!address) { - return undefined; - } - - const response = await nymQueryClient.getPendingEpochEvents({}); - const pendingEvents: PendingEvent[] = []; - - response.events.forEach((e: PendingEpochEvent) => { - const event = getEventsByAddress(e.event.kind, address); - if (event) { - pendingEvents.push(event); - } - }); - - return pendingEvents; - }; - - const handleGetDelegationRewards = async (mixId: number) => { - if (!nymQueryClient) { - return undefined; - } - - if (!address) { - return undefined; - } - - const response = await nymQueryClient.getPendingDelegatorReward({ address, mixId }); - - return response; - }; - - const handleGetDelegations = useCallback(async () => { - if (!nymQueryClient) { - setDelegations(undefined); - return undefined; - } - - if (!address) { - setDelegations(undefined); - return undefined; - } - - // Get all mixnodes - Required to get the identity key for each delegation - const mixnodes = await fetchMixnodes(); - - // Get delegations - const delegationsResponse = await nymQueryClient.getDelegatorDelegations({ delegator: address }); - - // Get rewards for each delegation - const rewardsResponse = await Promise.all( - delegationsResponse.delegations.map((d: Delegation) => handleGetDelegationRewards(d.mix_id)), - ); - - // Get all pending events - const pendingEvents = await handleGetPendingEvents(); - - const delegationsWithRewards: DelegationWithRewards[] = []; - - // Merge delegations with rewards and pending events - delegationsResponse.delegations.forEach((d: Delegation, index: number) => { - delegationsWithRewards.push({ - ...d, - pending: pendingEvents?.find((e: PendingEvent) => (e?.mixId === d.mix_id ? e.kind : undefined)), - identityKey: mixnodes?.find((m) => m.mix_id === d.mix_id)?.mix_node.identity_key || '', - rewards: rewardsResponse[index]?.amount_earned_detailed || '0', - }); - }); - - // Add pending events that are not in the delegations list - pendingEvents?.forEach((e) => { - if (e && !delegationsWithRewards.find((d: DelegationWithRewards) => d.mix_id === e.mixId)) { - delegationsWithRewards.push({ - mix_id: e.mixId, - height: 0, - cumulative_reward_ratio: '0', - owner: address, - amount: { - amount: '0', - denom: 'unym', - }, - rewards: '0', - identityKey: mixnodes?.find((m) => m.mix_id === e.mixId)?.mix_node.identity_key || '', - pending: e, - }); - } - }); - - setDelegations(delegationsWithRewards); - - return undefined; - }, [address, nymQueryClient]); - - const handleDelegate = async (mixId: number, amount: string) => { - if (!address) { - throw new Error('Please connect your wallet'); - } - - const amountToDelegate = (Number(amount) * 1000000).toString(); - const uNymFunds = [{ amount: amountToDelegate, denom: 'unym' }]; - try { - const tx = await nymClient?.delegateToMixnode({ mixId }, fee, 'Delegation from Nym Explorer', uNymFunds); - - return tx as unknown as ExecuteResult; - } catch (e) { - console.error('Failed to delegate to mixnode', e); - throw e; - } - }; - - const handleUndelegate = async (mixId: number) => { - const tx = await nymClient?.undelegateFromMixnode({ mixId }, fee, 'Undelegation from Nym Explorer'); - - return tx as unknown as ExecuteResult; - }; - - const contextValue: DelegationsState = useMemo( - () => ({ - delegations, - handleGetDelegations, - handleDelegate, - handleUndelegate, - }), - [delegations, handleGetDelegations], - ); - - return <DelegationsContext.Provider value={contextValue}>{children}</DelegationsContext.Provider>; -}; - -export const useDelegationsContext = () => { - const context = useContext(DelegationsContext); - if (!context) { - throw new Error('useDelegationsContext must be used within a DelegationsProvider'); - } - return context; -}; diff --git a/explorer/src/context/gateway.tsx b/explorer/src/context/gateway.tsx deleted file mode 100644 index dd966345181..00000000000 --- a/explorer/src/context/gateway.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import * as React from 'react'; -import { ApiState, GatewayReportResponse, UptimeStoryResponse } from '../typeDefs/explorer-api'; -import { Api } from '../api'; -import { useApiState } from './hooks'; - -/** - * This context provides the state for a single gateway by identity key. - */ - -interface GatewayState { - uptimeReport?: ApiState<GatewayReportResponse>; - uptimeStory?: ApiState<UptimeStoryResponse>; -} - -export const GatewayContext = React.createContext<GatewayState>({}); - -export const useGatewayContext = (): React.ContextType<typeof GatewayContext> => - React.useContext<GatewayState>(GatewayContext); - -/** - * Provides a state context for a gateway by identity - * @param gatewayIdentityKey The identity key of the gateway - */ -export const GatewayContextProvider = ({ - gatewayIdentityKey, - children, -}: { - gatewayIdentityKey: string; - children: JSX.Element; -}) => { - const [uptimeReport, fetchUptimeReportById, clearUptimeReportById] = useApiState<GatewayReportResponse>( - gatewayIdentityKey, - Api.fetchGatewayReportById, - 'Failed to fetch gateway uptime report by id', - ); - - const [uptimeStory, fetchUptimeHistory, clearUptimeHistory] = useApiState<UptimeStoryResponse>( - gatewayIdentityKey, - Api.fetchGatewayUptimeStoryById, - 'Failed to fetch gateway uptime history', - ); - - React.useEffect(() => { - // when the identity key changes, remove all previous data - clearUptimeReportById(); - clearUptimeHistory(); - Promise.all([fetchUptimeReportById(), fetchUptimeHistory()]); - }, [gatewayIdentityKey]); - - const state = React.useMemo<GatewayState>( - () => ({ - uptimeReport, - uptimeStory, - }), - [uptimeReport, uptimeStory], - ); - - return <GatewayContext.Provider value={state}>{children}</GatewayContext.Provider>; -}; diff --git a/explorer/src/context/hooks.ts b/explorer/src/context/hooks.ts deleted file mode 100644 index 9c5579c899a..00000000000 --- a/explorer/src/context/hooks.ts +++ /dev/null @@ -1,47 +0,0 @@ -import * as React from 'react'; -import { ApiState } from '../typeDefs/explorer-api'; - -/** - * Custom hook to get data from the API by passing an id to a delegate method that fetches the data asynchronously - * @param id The id to fetch - * @param fn Delegate the fetching to this method (must take `(id: string)` as a parameter) - * @param errorMessage A static error message, to use when no dynamic error message is returned - */ -export const useApiState = <T>( - id: string, - fn: (argId: string) => Promise<T>, - errorMessage: string, -): [ApiState<T> | undefined, () => Promise<ApiState<T>>, () => void] => { - // stores the state - const [value, setValue] = React.useState<ApiState<T>>(); - - // clear the value - const clearValueFn = () => setValue(undefined); - - // this provides a method to trigger the delegate to fetch data - const wrappedFetchFn = React.useCallback(async () => { - setValue({ isLoading: true }); - try { - // keep previous state and set to loading - setValue((prevState) => ({ ...prevState, isLoading: true })); - - // delegate to user function to get data and set if successful - const data = await fn(id); - const newValue: ApiState<T> = { - isLoading: false, - data, - }; - setValue(newValue); - return newValue; - } catch (error) { - // return the caught error or create a new error with the static error message - const newValue: ApiState<T> = { - error: error instanceof Error ? error : new Error(errorMessage), - isLoading: false, - }; - setValue(newValue); - return newValue; - } - }, [setValue, fn, id, errorMessage]); - return [value, wrappedFetchFn, clearValueFn]; -}; diff --git a/explorer/src/context/main.tsx b/explorer/src/context/main.tsx deleted file mode 100644 index c7a74a3d0d3..00000000000 --- a/explorer/src/context/main.tsx +++ /dev/null @@ -1,241 +0,0 @@ -import * as React from 'react'; -import { PaletteMode } from '@mui/material'; -import { - ApiState, - BlockResponse, - CountryDataResponse, - GatewayResponse, - MixNodeResponse, - MixnodeStatus, - SummaryOverviewResponse, - ValidatorsResponse, - Environment, - DirectoryServiceProvider, -} from '../typeDefs/explorer-api'; -import { EnumFilterKey } from '../typeDefs/filters'; -import { Api, getEnvironment } from '../api'; -import { NavOptionType, originalNavOptions } from './nav'; -import { toPercentIntegerString } from '../utils'; - -interface StateData { - summaryOverview?: ApiState<SummaryOverviewResponse>; - block?: ApiState<BlockResponse>; - countryData?: ApiState<CountryDataResponse>; - gateways?: ApiState<GatewayResponse>; - globalError?: string | undefined; - mixnodes?: ApiState<MixNodeResponse>; - mode: PaletteMode; - navState: NavOptionType[]; - validators?: ApiState<ValidatorsResponse>; - environment?: Environment; - serviceProviders?: ApiState<DirectoryServiceProvider[]>; -} - -interface StateApi { - fetchMixnodes: (status?: MixnodeStatus) => Promise<MixNodeResponse | undefined>; - filterMixnodes: (filters: any, status: any) => void; - toggleMode: () => void; - updateNavState: (title: string) => void; -} - -type State = StateData & StateApi; - -export const MainContext = React.createContext<State>({ - mode: 'dark', - updateNavState: () => null, - navState: originalNavOptions, - toggleMode: () => undefined, - filterMixnodes: () => null, - fetchMixnodes: () => Promise.resolve(undefined), -}); - -export const useMainContext = (): React.ContextType<typeof MainContext> => React.useContext<State>(MainContext); - -export const MainContextProvider: FCWithChildren = ({ children }) => { - // network explorer environment - const [environment, setEnvironment] = React.useState<Environment>(); - - // light/dark mode - const [mode, setMode] = React.useState<PaletteMode>('dark'); - - // nav state - const [navState, updateNav] = React.useState<NavOptionType[]>(originalNavOptions); - - // global / banner error messaging - const [globalError] = React.useState<string>(); - - // various APIs for Overview page - const [summaryOverview, setSummaryOverview] = React.useState<ApiState<SummaryOverviewResponse>>(); - const [mixnodes, setMixnodes] = React.useState<ApiState<MixNodeResponse>>(); - const [gateways, setGateways] = React.useState<ApiState<GatewayResponse>>(); - const [validators, setValidators] = React.useState<ApiState<ValidatorsResponse>>(); - const [block, setBlock] = React.useState<ApiState<BlockResponse>>(); - const [countryData, setCountryData] = React.useState<ApiState<CountryDataResponse>>(); - const [serviceProviders, setServiceProviders] = React.useState<ApiState<DirectoryServiceProvider[]>>(); - - const toggleMode = () => setMode((m) => (m !== 'light' ? 'light' : 'dark')); - - const fetchOverviewSummary = async () => { - try { - const data = await Api.fetchOverviewSummary(); - setSummaryOverview({ data, isLoading: false }); - } catch (error) { - setSummaryOverview({ - error: error instanceof Error ? error : new Error('Overview summary api fail'), - isLoading: false, - }); - } - }; - - const fetchMixnodes = async (status?: MixnodeStatus) => { - let data; - setMixnodes((d) => ({ ...d, isLoading: true })); - try { - data = status ? await Api.fetchMixnodesActiveSetByStatus(status) : await Api.fetchMixnodes(); - setMixnodes({ data, isLoading: false }); - } catch (error) { - setMixnodes({ - error: error instanceof Error ? error : new Error('Mixnode api fail'), - isLoading: false, - }); - } - return data; - }; - - const filterMixnodes = async (filters: { [key in EnumFilterKey]: number[] }, status?: MixnodeStatus) => { - setMixnodes((d) => ({ ...d, isLoading: true })); - const mxns = status ? await Api.fetchMixnodesActiveSetByStatus(status) : await Api.fetchMixnodes(); - - const filtered = mxns?.filter( - (m) => - +m.profit_margin_percent >= filters.profitMargin[0] / 100 && - +m.profit_margin_percent <= filters.profitMargin[1] / 100 && - m.stake_saturation >= filters.stakeSaturation[0] && - m.stake_saturation <= filters.stakeSaturation[1] && - m.avg_uptime >= filters.routingScore[0] && - m.avg_uptime <= filters.routingScore[1], - ); - - setMixnodes({ data: filtered, isLoading: false }); - }; - - const fetchGateways = async () => { - setGateways((d) => ({ ...d, isLoading: true })); - try { - const data = await Api.fetchGateways(); - setGateways({ data, isLoading: false }); - } catch (error) { - setGateways({ - error: error instanceof Error ? error : new Error('Gateways api fail'), - isLoading: false, - }); - } - }; - const fetchValidators = async () => { - try { - const data = await Api.fetchValidators(); - setValidators({ data, isLoading: false }); - } catch (error) { - setValidators({ - error: error instanceof Error ? error : new Error('Validators api fail'), - isLoading: false, - }); - } - }; - const fetchBlock = async () => { - try { - const data = await Api.fetchBlock(); - setBlock({ data, isLoading: false }); - } catch (error) { - setBlock({ - error: error instanceof Error ? error : new Error('Block api fail'), - isLoading: false, - }); - } - }; - const fetchCountryData = async () => { - setCountryData({ data: undefined, isLoading: true }); - try { - const res = await Api.fetchCountryData(); - setCountryData({ data: res, isLoading: false }); - } catch (error) { - setCountryData({ - error: error instanceof Error ? error : new Error('Country Data api fail'), - isLoading: false, - }); - } - }; - - const fetchServiceProviders = async () => { - setServiceProviders({ data: undefined, isLoading: true }); - try { - const res = await Api.fetchServiceProviders(); - const resWithRoutingScorePercentage = res.map((item) => ({ - ...item, - routing_score: item.routing_score - ? `${toPercentIntegerString(item.routing_score.toString())}%` - : item.routing_score, - })); - setServiceProviders({ data: resWithRoutingScorePercentage, isLoading: false }); - } catch (error) { - setServiceProviders({ - error: error instanceof Error ? error : new Error('Service provider api fail'), - isLoading: false, - }); - } - }; - - const updateNavState = (url: string) => { - const updated = navState.map((option) => ({ - ...option, - isActive: option.url === url, - })); - updateNav(updated); - }; - - React.useEffect(() => { - if (environment === 'mainnet') { - fetchServiceProviders(); - } - }, [environment]); - - React.useEffect(() => { - setEnvironment(getEnvironment()); - Promise.all([fetchOverviewSummary(), fetchGateways(), fetchValidators(), fetchBlock(), fetchCountryData()]); - }, []); - - const state = React.useMemo<State>( - () => ({ - environment, - block, - countryData, - fetchMixnodes, - filterMixnodes, - gateways, - globalError, - mixnodes, - mode, - navState, - summaryOverview, - toggleMode, - updateNavState, - validators, - serviceProviders, - }), - [ - environment, - block, - countryData, - gateways, - globalError, - mixnodes, - mode, - navState, - summaryOverview, - validators, - serviceProviders, - ], - ); - - return <MainContext.Provider value={state}>{children}</MainContext.Provider>; -}; diff --git a/explorer/src/context/mixnode.tsx b/explorer/src/context/mixnode.tsx deleted file mode 100644 index 36e43d568b8..00000000000 --- a/explorer/src/context/mixnode.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import * as React from 'react'; -import { - ApiState, - DelegationsResponse, - UniqDelegationsResponse, - MixNodeDescriptionResponse, - MixNodeEconomicDynamicsStatsResponse, - MixNodeResponseItem, - StatsResponse, - StatusResponse, - UptimeStoryResponse, -} from '../typeDefs/explorer-api'; -import { Api } from '../api'; -import { useApiState } from './hooks'; -import { mixNodeResponseItemToMixnodeRowType, MixnodeRowType } from '../components/MixNodes'; - -/** - * This context provides the state for a single mixnode by identity key. - */ - -interface MixnodeState { - delegations?: ApiState<DelegationsResponse>; - uniqDelegations?: ApiState<UniqDelegationsResponse>; - description?: ApiState<MixNodeDescriptionResponse>; - economicDynamicsStats?: ApiState<MixNodeEconomicDynamicsStatsResponse>; - mixNode?: ApiState<MixNodeResponseItem | undefined>; - mixNodeRow?: MixnodeRowType; - stats?: ApiState<StatsResponse>; - status?: ApiState<StatusResponse>; - uptimeStory?: ApiState<UptimeStoryResponse>; -} - -export const MixnodeContext = React.createContext<MixnodeState>({}); - -export const useMixnodeContext = (): React.ContextType<typeof MixnodeContext> => - React.useContext<MixnodeState>(MixnodeContext); - -interface MixnodeContextProviderProps { - mixId: string; - children: React.ReactNode; -} - -/** - * Provides a state context for a mixnode by identity - * @param mixId The mixID of the mixnode - */ -export const MixnodeContextProvider: FCWithChildren<MixnodeContextProviderProps> = ({ mixId, children }) => { - const [mixNode, fetchMixnodeById, clearMixnodeById] = useApiState<MixNodeResponseItem | undefined>( - mixId, - Api.fetchMixnodeByID, - 'Failed to fetch mixnode by id', - ); - - const [mixNodeRow, setMixnodeRow] = React.useState<MixnodeRowType | undefined>(); - - const [delegations, fetchDelegations, clearDelegations] = useApiState<DelegationsResponse>( - mixId, - Api.fetchDelegationsById, - 'Failed to fetch delegations for mixnode', - ); - - const [uniqDelegations, fetchUniqDelegations, clearUniqDelegations] = useApiState<UniqDelegationsResponse>( - mixId, - Api.fetchUniqDelegationsById, - 'Failed to fetch delegations for mixnode', - ); - - const [status, fetchStatus, clearStatus] = useApiState<StatusResponse>( - mixId, - Api.fetchStatusById, - 'Failed to fetch mixnode status', - ); - - const [stats, fetchStats, clearStats] = useApiState<StatsResponse>( - mixId, - Api.fetchStatsById, - 'Failed to fetch mixnode stats', - ); - - const [description, fetchDescription, clearDescription] = useApiState<MixNodeDescriptionResponse>( - mixId, - Api.fetchMixnodeDescriptionById, - 'Failed to fetch mixnode description', - ); - - const [economicDynamicsStats, fetchEconomicDynamicsStats, clearEconomicDynamicsStats] = - useApiState<MixNodeEconomicDynamicsStatsResponse>( - mixId, - Api.fetchMixnodeEconomicDynamicsStatsById, - 'Failed to fetch mixnode dynamics stats by id', - ); - - const [uptimeStory, fetchUptimeHistory, clearUptimeHistory] = useApiState<UptimeStoryResponse>( - mixId, - Api.fetchUptimeStoryById, - 'Failed to fetch mixnode uptime history', - ); - - React.useEffect(() => { - // when the identity key changes, remove all previous data - clearMixnodeById(); - clearDelegations(); - clearUniqDelegations(); - clearStatus(); - clearStats(); - clearDescription(); - clearEconomicDynamicsStats(); - clearUptimeHistory(); - - // fetch the mixnode, then get all the other stuff - fetchMixnodeById().then((value) => { - if (!value.data || value.error) { - setMixnodeRow(undefined); - return; - } - setMixnodeRow(mixNodeResponseItemToMixnodeRowType(value.data)); - Promise.all([ - fetchDelegations(), - fetchUniqDelegations(), - fetchStatus(), - fetchStats(), - fetchDescription(), - fetchEconomicDynamicsStats(), - fetchUptimeHistory(), - ]); - }); - }, [mixId]); - - const state = React.useMemo<MixnodeState>( - () => ({ - delegations, - uniqDelegations, - mixNode, - mixNodeRow, - description, - economicDynamicsStats, - stats, - status, - uptimeStory, - }), - [ - { - delegations, - uniqDelegations, - mixNode, - mixNodeRow, - description, - economicDynamicsStats, - stats, - status, - uptimeStory, - }, - ], - ); - - return <MixnodeContext.Provider value={state}>{children}</MixnodeContext.Provider>; -}; diff --git a/explorer/src/context/nav.tsx b/explorer/src/context/nav.tsx deleted file mode 100644 index 6df749f5850..00000000000 --- a/explorer/src/context/nav.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import * as React from 'react'; -import { DelegateIcon } from '@src/icons/DelevateSVG'; -import { BIG_DIPPER } from '../api/constants'; -import { OverviewSVG } from '../icons/OverviewSVG'; -import { NodemapSVG } from '../icons/NodemapSVG'; -import { NetworkComponentsSVG } from '../icons/NetworksSVG'; - -export type NavOptionType = { - isActive?: boolean; - url: string; - title: string; - Icon?: React.ReactNode; - nested?: NavOptionType[]; - isExpandedChild?: boolean; -}; - -export const originalNavOptions: NavOptionType[] = [ - { - isActive: false, - url: '/', - title: 'Overview', - Icon: <OverviewSVG />, - }, - { - isActive: false, - url: '/network-components', - title: 'Network Components', - Icon: <NetworkComponentsSVG />, - nested: [ - { - url: '/network-components/mixnodes', - title: 'Mixnodes', - }, - { - url: '/network-components/gateways', - title: 'Gateways', - }, - { - url: `${BIG_DIPPER}/validators`, - title: 'Validators', - }, - { - url: 'network-components/service-providers', - title: 'Service Providers', - }, - ], - }, - { - isActive: false, - url: '/nodemap', - title: 'Nodemap', - Icon: <NodemapSVG />, - }, - { - isActive: false, - url: '/delegations', - title: 'Delegations', - Icon: <DelegateIcon />, - }, -]; diff --git a/explorer/src/context/wallet.tsx b/explorer/src/context/wallet.tsx deleted file mode 100644 index 8ac26ee7cab..00000000000 --- a/explorer/src/context/wallet.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React, { createContext, useContext, useEffect, useMemo, useState } from 'react'; -import { useChain } from '@cosmos-kit/react'; -import { Wallet } from '@cosmos-kit/core'; -import { unymToNym } from '@src/utils/currency'; -import { useNymClient } from '@src/hooks'; -import { MixnetClient, MixnetQueryClient } from '@nymproject/contract-clients/Mixnet.client'; -import { COSMOS_KIT_USE_CHAIN } from '@src/api/constants'; - -interface WalletState { - balance: { status: 'loading' | 'success'; data?: string }; - address?: string; - isWalletConnected: boolean; - isWalletConnecting: boolean; - wallet?: Wallet; - nymClient?: MixnetClient; - nymQueryClient?: MixnetQueryClient; - connectWallet: () => Promise<void>; - disconnectWallet: () => Promise<void>; -} - -export const WalletContext = createContext<WalletState>({ - address: undefined, - balance: { status: 'loading', data: undefined }, - isWalletConnected: false, - isWalletConnecting: false, - nymClient: undefined, - nymQueryClient: undefined, - connectWallet: async () => { - throw new Error('Please connect your wallet'); - }, - disconnectWallet: async () => { - throw new Error('Please connect your wallet'); - }, -}); - -export const WalletProvider = ({ children }: { children: React.ReactNode }) => { - const [balance, setBalance] = useState<WalletState['balance']>({ status: 'loading', data: undefined }); - - const { connect, disconnect, wallet, address, isWalletConnected, isWalletConnecting, getCosmWasmClient } = - useChain(COSMOS_KIT_USE_CHAIN); - - const { nymClient, nymQueryClient } = useNymClient(address); - - const getBalance = async (walletAddress: string) => { - const account = await getCosmWasmClient(); - const uNYMBalance = await account.getBalance(walletAddress, 'unym'); - const NYMBalance = unymToNym(uNYMBalance.amount); - - return NYMBalance; - }; - - const init = async (walletAddress: string) => { - const walletBalance = await getBalance(walletAddress); - setBalance({ status: 'success', data: walletBalance }); - }; - - useEffect(() => { - if (isWalletConnected && address) { - init(address); - } - }, [address, isWalletConnected]); - - const handleConnectWallet = async () => { - await connect(); - }; - - const handleDisconnectWallet = async () => { - await disconnect(); - setBalance({ status: 'loading', data: undefined }); - }; - - const contextValue: WalletState = useMemo( - () => ({ - address, - balance, - wallet, - isWalletConnected, - isWalletConnecting, - nymClient, - nymQueryClient, - connectWallet: handleConnectWallet, - disconnectWallet: handleDisconnectWallet, - }), - [address, balance, wallet, isWalletConnected, isWalletConnecting, nymClient, nymQueryClient], - ); - - return <WalletContext.Provider value={contextValue}>{children}</WalletContext.Provider>; -}; - -export const useWalletContext = () => useContext(WalletContext); diff --git a/explorer/src/errors/ErrorBoundaryContent.tsx b/explorer/src/errors/ErrorBoundaryContent.tsx deleted file mode 100644 index 0389588e268..00000000000 --- a/explorer/src/errors/ErrorBoundaryContent.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import * as React from 'react'; -import { FallbackProps } from 'react-error-boundary'; -import { Alert, AlertTitle, Container } from '@mui/material'; -import { NymThemeProvider } from '@nymproject/mui-theme'; -import { NymLogo } from '@nymproject/react/logo/NymLogo'; - -export const ErrorBoundaryContent: FCWithChildren<FallbackProps> = ({ error }) => ( - <NymThemeProvider mode="dark"> - <Container sx={{ py: 4 }}> - <NymLogo height="75px" width="75px" /> - <h1>Oh no! Sorry, something went wrong</h1> - <Alert severity="error" data-testid="error-message"> - <AlertTitle>{error.name}</AlertTitle> - {error.message} - </Alert> - {process.env.NODE_ENV === 'development' && ( - <Alert severity="info" sx={{ mt: 2 }} data-testid="stack-trace"> - <AlertTitle>Stack trace</AlertTitle> - {error.stack} - </Alert> - )} - </Container> - </NymThemeProvider> -); diff --git a/explorer/src/hooks/index.ts b/explorer/src/hooks/index.ts deleted file mode 100644 index ba04855f779..00000000000 --- a/explorer/src/hooks/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './useIsMobile'; -export * from './useIsMounted'; -export * from './useGetMixnodeStatusColor'; -export * from './useNymClient'; diff --git a/explorer/src/hooks/useGetMixnodeStatusColor.ts b/explorer/src/hooks/useGetMixnodeStatusColor.ts deleted file mode 100644 index d9d71fe7e1c..00000000000 --- a/explorer/src/hooks/useGetMixnodeStatusColor.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { useTheme } from '@mui/material'; -import { MixnodeStatus } from '@src/typeDefs/explorer-api'; - -export const useGetMixNodeStatusColor = (status: MixnodeStatus) => { - const theme = useTheme(); - - switch (status) { - case MixnodeStatus.active: - return theme.palette.nym.networkExplorer.mixnodes.status.active; - - case MixnodeStatus.standby: - return theme.palette.nym.networkExplorer.mixnodes.status.standby; - - default: - return theme.palette.nym.networkExplorer.mixnodes.status.inactive; - } -}; diff --git a/explorer/src/hooks/useIsMobile.ts b/explorer/src/hooks/useIsMobile.ts deleted file mode 100644 index 225964b464b..00000000000 --- a/explorer/src/hooks/useIsMobile.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Breakpoint, useMediaQuery } from '@mui/material'; -import { useTheme } from '@mui/material/styles'; - -export const useIsMobile = (queryInput: number | Breakpoint = 'md') => { - const theme = useTheme(); - const isMobile = useMediaQuery(theme.breakpoints.down(queryInput)); - - return isMobile; -}; diff --git a/explorer/src/hooks/useIsMounted.ts b/explorer/src/hooks/useIsMounted.ts deleted file mode 100644 index b18f3a72b77..00000000000 --- a/explorer/src/hooks/useIsMounted.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { useRef, useEffect, useCallback } from 'react'; - -export function useIsMounted(): () => boolean { - const ref = useRef(false); - - useEffect(() => { - ref.current = true; - return () => { - ref.current = false; - }; - }, []); - - return useCallback(() => ref.current, [ref]); -} diff --git a/explorer/src/hooks/useNymClient.tsx b/explorer/src/hooks/useNymClient.tsx deleted file mode 100644 index 26b2f529db9..00000000000 --- a/explorer/src/hooks/useNymClient.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { useEffect, useState } from 'react'; -import { useChain } from '@cosmos-kit/react'; -import { contracts } from '@nymproject/contract-clients'; -import { MixnetClient, MixnetQueryClient } from '@nymproject/contract-clients/Mixnet.client'; -import { COSMOS_KIT_USE_CHAIN, NYM_MIXNET_CONTRACT } from '@src/api/constants'; - -export const useNymClient = (address?: string) => { - const [nymClient, setNymClient] = useState<MixnetClient>(); - const [nymQueryClient, setNymQueryClient] = useState<MixnetQueryClient>(); - - const { getCosmWasmClient, getSigningCosmWasmClient } = useChain(COSMOS_KIT_USE_CHAIN); - - useEffect(() => { - if (address) { - const init = async () => { - const cosmWasmSigningClient = await getSigningCosmWasmClient(); - const cosmWasmClient = await getCosmWasmClient(); - - const client = new contracts.Mixnet.MixnetClient(cosmWasmSigningClient as any, address, NYM_MIXNET_CONTRACT); - const queryClient = new contracts.Mixnet.MixnetQueryClient(cosmWasmClient as any, NYM_MIXNET_CONTRACT); - - setNymClient(client); - setNymQueryClient(queryClient); - }; - - init(); - } - }, [address, getCosmWasmClient, getSigningCosmWasmClient]); - - return { nymClient, nymQueryClient }; -}; diff --git a/explorer/src/icons/DelevateSVG.tsx b/explorer/src/icons/DelevateSVG.tsx deleted file mode 100644 index 56180d1b8ad..00000000000 --- a/explorer/src/icons/DelevateSVG.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import { SvgIcon, SvgIconProps } from '@mui/material'; - -export const DelegateIcon = (props: SvgIconProps) => ( - <SvgIcon {...props}> - <path d="M4 12V15H6V12H4ZM16 7L14.59 5.59L13 7.17V2H11V7.19L9.39 5.61L8 7L12 11L16 7ZM4 17H20V15H4V17Z" /> - <path d="M20 21C20 21.5523 19.5523 22 19 22H5C4.44772 22 4 21.5523 4 21V20H20V21Z" /> - <rect x="18" y="12" width="2" height="3" /> - <rect x="18" y="17" width="2" height="3" /> - <rect x="4" y="17" width="2" height="3" /> - </SvgIcon> -); diff --git a/explorer/src/icons/ElipsSVG.tsx b/explorer/src/icons/ElipsSVG.tsx deleted file mode 100644 index 4a430d6cb6a..00000000000 --- a/explorer/src/icons/ElipsSVG.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import * as React from 'react'; - -export const ElipsSVG: FCWithChildren = () => ( - <svg xmlns="http://www.w3.org/2000/svg" width="24" height="25" viewBox="0 0 24 25" fill="none"> - <circle cx="12" cy="12.5" r="10" fill="url(#paint0_angular_2549_7570)" /> - <defs> - <radialGradient - id="paint0_angular_2549_7570" - cx="0" - cy="0" - r="1" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(12 12.5) rotate(90) scale(12)" - > - <stop stopColor="#22D27E" /> - <stop offset="1" stopColor="#9002FF" /> - </radialGradient> - </defs> - </svg> -); diff --git a/explorer/src/icons/GatewaysSVG.tsx b/explorer/src/icons/GatewaysSVG.tsx deleted file mode 100644 index 00e4a21198e..00000000000 --- a/explorer/src/icons/GatewaysSVG.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -export const GatewaysSVG: FCWithChildren = () => { - const theme = useTheme(); - const color = theme.palette.text.primary; - return ( - <svg width="24" height="24" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M16.2 12H22.7" stroke={color} strokeWidth="1.3" strokeMiterlimit="10" strokeLinecap="round" /> - <path d="M1.30005 12H12" stroke={color} strokeWidth="1.3" strokeMiterlimit="10" strokeLinecap="round" /> - <path - d="M20.1 9.40015L22.7 12.0001L20.1 14.6001" - stroke={color} - strokeWidth="1.3" - strokeMiterlimit="10" - strokeLinecap="round" - strokeLinejoin="round" - /> - <path - d="M13.2 22.7001H8.59998C6.89998 22.7001 5.59998 21.4001 5.59998 19.7001V4.30005C5.59998 2.60005 6.89998 1.30005 8.59998 1.30005H13.2C14.9 1.30005 16.2 2.60005 16.2 4.30005V19.6C16.2 21.3001 14.8 22.7001 13.2 22.7001Z" - stroke={color} - strokeWidth="1.3" - strokeMiterlimit="10" - strokeLinecap="round" - /> - </svg> - ); -}; diff --git a/explorer/src/icons/LightSwitchSVG.tsx b/explorer/src/icons/LightSwitchSVG.tsx deleted file mode 100644 index 7a32590dfc8..00000000000 --- a/explorer/src/icons/LightSwitchSVG.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -export const LightSwitchSVG: FCWithChildren = () => { - const { palette } = useTheme(); - return ( - <svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path - d="M12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C17.5 22 22 17.5 22 12C22 6.5 17.5 2 12 2Z" - fill={palette.background.default} - /> - <path d="M12 20C7.6 20 4 16.4 4 12C4 7.6 7.6 4 12 4V20Z" fill={palette.text.primary} /> - </svg> - ); -}; diff --git a/explorer/src/icons/MixnodesSVG.tsx b/explorer/src/icons/MixnodesSVG.tsx deleted file mode 100644 index 56902cb0dec..00000000000 --- a/explorer/src/icons/MixnodesSVG.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -export const MixnodesSVG: FCWithChildren = () => { - const theme = useTheme(); - const color = theme.palette.text.primary; - - return ( - <svg width="24" height="24" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M23.0437 13.0291H2.97681" stroke={color} strokeMiterlimit="10" /> - <path d="M23.0437 2.99512H2.97681" stroke={color} strokeMiterlimit="10" /> - <path d="M23.0437 23.0625H2.97681" stroke={color} strokeMiterlimit="10" /> - <path d="M2.97681 23.0621L23.0437 2.99512" stroke={color} strokeMiterlimit="10" /> - <path d="M23.0437 23.0621L2.97681 2.99512" stroke={color} strokeMiterlimit="10" /> - <path d="M13.0103 23.0621L23.0437 2.99512" stroke={color} strokeMiterlimit="10" /> - <path d="M2.97681 2.99512L13.0103 23.0621" stroke={color} strokeMiterlimit="10" /> - <path - d="M13.0099 13.0289L23.0437 23.0621L13.0099 2.99512L2.97681 23.0621L13.0099 2.99512" - stroke={color} - strokeMiterlimit="10" - /> - <path - d="M23.097 12.9846L13.0892 2.97681L3.08142 12.9846L13.0892 22.9924L23.097 12.9846Z" - stroke={color} - strokeMiterlimit="10" - /> - <path - d="M23.0232 4.9536C24.1149 4.9536 25 4.06856 25 2.9768C25 1.88504 24.1149 1 23.0232 1C21.9314 1 21.0464 1.88504 21.0464 2.9768C21.0464 4.06856 21.9314 4.9536 23.0232 4.9536Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M12.9731 4.9536C14.0648 4.9536 14.9499 4.06856 14.9499 2.9768C14.9499 1.88504 14.0648 1 12.9731 1C11.8813 1 10.9963 1.88504 10.9963 2.9768C10.9963 4.06856 11.8813 4.9536 12.9731 4.9536Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M2.9768 4.9536C4.06856 4.9536 4.9536 4.06856 4.9536 2.9768C4.9536 1.88504 4.06856 1 2.9768 1C1.88504 1 1 1.88504 1 2.9768C1 4.06856 1.88504 4.9536 2.9768 4.9536Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M23.0232 15.0029C24.1149 15.0029 25 14.1179 25 13.0261C25 11.9344 24.1149 11.0493 23.0232 11.0493C21.9314 11.0493 21.0464 11.9344 21.0464 13.0261C21.0464 14.1179 21.9314 15.0029 23.0232 15.0029Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M12.9731 15.0029C14.0648 15.0029 14.9499 14.1179 14.9499 13.0261C14.9499 11.9344 14.0648 11.0493 12.9731 11.0493C11.8813 11.0493 10.9963 11.9344 10.9963 13.0261C10.9963 14.1179 11.8813 15.0029 12.9731 15.0029Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M2.9768 15.0029C4.06856 15.0029 4.9536 14.1179 4.9536 13.0261C4.9536 11.9344 4.06856 11.0493 2.9768 11.0493C1.88504 11.0493 1 11.9344 1 13.0261C1 14.1179 1.88504 15.0029 2.9768 15.0029Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M23.0232 25C24.1149 25 25 24.1149 25 23.0232C25 21.9314 24.1149 21.0464 23.0232 21.0464C21.9314 21.0464 21.0464 21.9314 21.0464 23.0232C21.0464 24.1149 21.9314 25 23.0232 25Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M12.9731 25C14.0648 25 14.9499 24.1149 14.9499 23.0232C14.9499 21.9314 14.0648 21.0464 12.9731 21.0464C11.8813 21.0464 10.9963 21.9314 10.9963 23.0232C10.9963 24.1149 11.8813 25 12.9731 25Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - <path - d="M2.9768 25C4.06856 25 4.9536 24.1149 4.9536 23.0232C4.9536 21.9314 4.06856 21.0464 2.9768 21.0464C1.88504 21.0464 1 21.9314 1 23.0232C1 24.1149 1.88504 25 2.9768 25Z" - fill="#242C3D" - stroke={color} - strokeWidth="1.2" - strokeMiterlimit="10" - /> - </svg> - ); -}; diff --git a/explorer/src/icons/MobileDrawerClose.tsx b/explorer/src/icons/MobileDrawerClose.tsx deleted file mode 100644 index 6c8ecfacbc0..00000000000 --- a/explorer/src/icons/MobileDrawerClose.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import * as React from 'react'; - -export const MobileDrawerClose: FCWithChildren = (props) => ( - <svg xmlns="http://www.w3.org/2000/svg" viewBox="-3 -5 24 24" width="25" height="25" {...props}> - <path - d="M0 12H13V10H0V12ZM0 7H10V5H0V7ZM0 0V2H13V0H0ZM18 9.59L14.42 6L18 2.41L16.59 1L11.59 6L16.59 11L18 9.59Z" - fill="#F2F2F2" - /> - </svg> -); diff --git a/explorer/src/icons/NetworksSVG.tsx b/explorer/src/icons/NetworksSVG.tsx deleted file mode 100644 index 0db2b9bdfb8..00000000000 --- a/explorer/src/icons/NetworksSVG.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -export const NetworkComponentsSVG: FCWithChildren = () => { - const theme = useTheme(); - const color = theme.palette.nym.networkExplorer.nav.text; - return ( - <svg width="25" height="25" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path - d="M17.2 10.5V4.40002L12 1.40002L6.8 4.40002V10.5L12 13.5L17.2 10.5Z" - stroke={color} - strokeMiterlimit="10" - /> - <path d="M12 19.6V13.5L6.8 10.5L1.5 13.5V19.6L6.8 22.6L12 19.6Z" stroke={color} strokeMiterlimit="10" /> - <path d="M22.5 19.6V13.5L17.2 10.5L12 13.5V19.6L17.2 22.6L22.5 19.6Z" stroke={color} strokeMiterlimit="10" /> - </svg> - ); -}; diff --git a/explorer/src/icons/NodemapSVG.tsx b/explorer/src/icons/NodemapSVG.tsx deleted file mode 100644 index 9486d64dcc1..00000000000 --- a/explorer/src/icons/NodemapSVG.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -export const NodemapSVG: FCWithChildren = () => { - const theme = useTheme(); - const color = theme.palette.nym.networkExplorer.nav.text; - return ( - <svg width="25" height="25" viewBox="0 0 19 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path - d="M1 9.6999C1 5.0999 4.7 1.3999 9.3 1.3999C13.9 1.3999 17.6 5.0999 17.6 9.6999C17.6 14.2999 9.3 21.5999 9.3 21.5999C9.3 21.5999 1 14.2999 1 9.6999Z" - stroke={color} - strokeMiterlimit="10" - /> - <path - d="M9.30005 12C11.233 12 12.8 10.433 12.8 8.5C12.8 6.567 11.233 5 9.30005 5C7.36705 5 5.80005 6.567 5.80005 8.5C5.80005 10.433 7.36705 12 9.30005 12Z" - stroke={color} - strokeMiterlimit="10" - /> - <path d="M1.5 22.5999H17.1" stroke={color} strokeMiterlimit="10" strokeLinecap="round" /> - </svg> - ); -}; diff --git a/explorer/src/icons/NymVpn.tsx b/explorer/src/icons/NymVpn.tsx deleted file mode 100644 index 788b78a4f96..00000000000 --- a/explorer/src/icons/NymVpn.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import * as React from 'react'; - -interface DiscordIconProps { - size?: { width: number; height: number }; -} - -export const NymVpnIcon: FCWithChildren<DiscordIconProps> = ({ size }) => ( - <svg width={size?.width} height={size?.height} viewBox="0 0 170 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path - d="M19.6118 0.128906H19.5405V0.187854V20.7961L10.7849 0.164277L10.773 0.128906H10.7255H5.75959H0.187819H0.128418V0.187854V23.8142V23.8732H0.187819H5.75959H5.81899V23.8142V3.17063L14.6103 23.8378L14.6222 23.8732H14.6697H19.6118H25.1717H25.2311V23.8142V0.187854V0.128906H25.1717H19.6118Z" - fill="white" - /> - <path - fillRule="evenodd" - clipRule="evenodd" - d="M19.4121 0H25.3603V24H14.5297L14.4901 23.8819L5.94824 3.80121V24H0V0H10.8663L10.906 0.118132L19.4121 20.1621V0ZM19.5409 20.7951L10.7853 0.163225L10.7734 0.127854H0.128835V23.8721H5.81941V3.16958L14.6107 23.8368L14.6226 23.8721H25.2315V0.127854H19.5409V20.7951Z" - fill="white" - /> - <path - d="M89.8116 0.128906H79.1908H79.1314L79.1195 0.176068L73.6784 20.8904L68.2255 0.176068L68.2136 0.128906H68.1661H57.5215H57.4502V0.187854V23.8142V23.8732H57.5215H63.0814H63.1408V23.8142V3.33568L68.5225 23.826L68.5343 23.8732H68.5937H78.7394H78.7869L78.7988 23.826L84.1804 3.33568V23.8142V23.8732H84.2398H89.8116H89.871V23.8142V0.187854V0.128906H89.8116Z" - fill="white" - /> - <path - fillRule="evenodd" - clipRule="evenodd" - d="M79.0312 0H90.0003V24H84.052V4.33208L78.9242 23.856L78.9238 23.8572L78.8879 24H68.4342L68.3982 23.8572L68.3979 23.856L63.27 4.33208V24H57.3218V0H68.3146L68.3505 0.142699L68.3509 0.144015L73.6787 20.383L78.9949 0.144015L78.9953 0.142765L79.0312 0ZM73.6788 20.8894L68.2259 0.175015L68.214 0.127854H57.4506V23.8721H63.1412V3.33463L68.5229 23.825L68.5348 23.8721H78.7873L78.7992 23.825L84.1809 3.33463V23.8721H89.8714V0.127854H79.1318L79.1199 0.175015L73.6788 20.8894Z" - fill="white" - /> - <path - d="M48.2909 0.128906H48.2553L48.2434 0.152487L41.4836 11.8124L34.6882 0.152487L34.6763 0.128906H34.6407H28.2135H28.0947L28.1541 0.223225L38.6205 18.2142V23.8142V23.8732H38.6799H44.2517H44.3111V23.8142V18.2142L54.7775 0.223225L54.8369 0.128906H54.7181H48.2909Z" - fill="white" - /> - <path - fillRule="evenodd" - clipRule="evenodd" - d="M48.1757 0H55.0693L54.8879 0.288036L44.4399 18.2474V24H38.4917V18.2474L28.0437 0.288036L27.8623 0H34.756L34.8017 0.0907854L41.4833 11.5555L48.1299 0.0909153L48.1757 0ZM48.2434 0.151434L41.4836 11.8114L34.6882 0.151434L34.6763 0.127854H28.0948L28.1542 0.222173L38.6205 18.2131V23.8721H44.3111V18.2131L54.7775 0.222173L54.8369 0.127854H48.2553L48.2434 0.151434Z" - fill="white" - /> - <path - d="M169.238 0V24H166.422C166.006 24 165.654 23.9341 165.366 23.8023C165.088 23.6596 164.811 23.418 164.534 23.0776L153.542 8.76321C153.584 9.19149 153.611 9.60878 153.622 10.0151C153.643 10.4104 153.654 10.7838 153.654 11.1352V24H148.886V0H151.734C151.968 0 152.166 0.0109813 152.326 0.032944C152.486 0.0549066 152.63 0.0988326 152.758 0.164722C152.886 0.219629 153.008 0.30199 153.126 0.411805C153.243 0.521619 153.376 0.669869 153.526 0.856553L164.614 15.2697C164.56 14.8085 164.523 14.3638 164.502 13.9355C164.48 13.4962 164.47 13.0844 164.47 12.7001V0H169.238Z" - fill="#A8A6A6" - /> - <path - d="M134.206 11.7776C135.614 11.7776 136.627 11.4317 137.246 10.7399C137.865 10.048 138.174 9.08167 138.174 7.84077C138.174 7.29169 138.094 6.79204 137.934 6.3418C137.774 5.89156 137.529 5.50721 137.198 5.18874C136.878 4.8593 136.467 4.60673 135.966 4.43102C135.475 4.25532 134.889 4.16747 134.206 4.16747H131.39V11.7776H134.206ZM134.206 0C135.849 0 137.257 0.203157 138.43 0.609471C139.614 1.0048 140.585 1.55388 141.342 2.25669C142.11 2.95951 142.675 3.78861 143.038 4.74399C143.401 5.69938 143.582 6.73164 143.582 7.84077C143.582 9.03775 143.395 10.1359 143.022 11.1352C142.649 12.1345 142.078 12.9911 141.31 13.7049C140.542 14.4187 139.566 14.9787 138.382 15.385C137.209 15.7804 135.817 15.978 134.206 15.978H131.39V24H125.982V0H134.206Z" - fill="#A8A6A6" - /> - <path - d="M121.584 0L112.24 24H107.344L98 0H102.352C102.821 0 103.2 0.115305 103.488 0.345915C103.776 0.565545 103.995 0.851064 104.144 1.20247L108.656 14.0508C108.869 14.6108 109.077 15.2258 109.28 15.8957C109.483 16.5546 109.675 17.2464 109.856 17.9712C110.005 17.2464 110.171 16.5546 110.352 15.8957C110.544 15.2258 110.747 14.6108 110.96 14.0508L115.44 1.20247C115.557 0.894989 115.765 0.620452 116.064 0.378861C116.373 0.126287 116.752 0 117.2 0H121.584Z" - fill="#A8A6A6" - /> - </svg> -); - -NymVpnIcon.defaultProps = { - size: { width: 80, height: 12 }, -}; diff --git a/explorer/src/icons/OverviewSVG.tsx b/explorer/src/icons/OverviewSVG.tsx deleted file mode 100644 index 2ced0bb17b4..00000000000 --- a/explorer/src/icons/OverviewSVG.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -export const OverviewSVG: FCWithChildren = () => { - const theme = useTheme(); - const color = theme.palette.nym.networkExplorer.nav.text; - - return ( - <svg width="25" height="25" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M1.4 21.6H22.6" stroke={color} strokeMiterlimit="10" strokeLinecap="round" /> - <path d="M14.1 2.40002H9.9V21.5H14.1V2.40002Z" stroke={color} strokeMiterlimit="10" strokeLinecap="round" /> - <path d="M20.8 6.59998H16.6V21.5H20.8V6.59998Z" stroke={color} strokeMiterlimit="10" strokeLinecap="round" /> - <path d="M7.4 11.8H3.2V21.6H7.4V11.8Z" stroke={color} strokeMiterlimit="10" strokeLinecap="round" /> - </svg> - ); -}; diff --git a/explorer/src/icons/TokenSVG.tsx b/explorer/src/icons/TokenSVG.tsx deleted file mode 100644 index 94ab1468c92..00000000000 --- a/explorer/src/icons/TokenSVG.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from 'react'; - -export const TokenSVG: FCWithChildren = () => { - const color = 'white'; - - return ( - <svg xmlns="http://www.w3.org/2000/svg" width="24" height="25" viewBox="0 0 24 25" fill="none"> - <g clipPath="url(#clip0_2549_7563)"> - <path - d="M20.4841 4.01607C15.8041 -0.67593 8.19607 -0.67593 3.51607 4.01607C-1.17593 8.70807 -1.17593 16.3041 3.51607 20.9841C8.20807 25.6761 15.8041 25.6761 20.4841 20.9841C25.1761 16.3041 25.1761 8.69607 20.4841 4.01607ZM19.4521 19.9521C15.3361 24.0681 8.65207 24.0681 4.53607 19.9521C0.42007 15.8361 0.42007 9.15207 4.53607 5.03607C8.65207 0.92007 15.3361 0.92007 19.4521 5.03607C23.5801 9.16407 23.5801 15.8361 19.4521 19.9521Z" - fill={color} - /> - <path - d="M18.48 19.4965V5.50447C17.868 4.92847 17.184 4.42447 16.452 4.02847V17.4085L7.62002 3.98047C6.85202 4.38847 6.14402 4.89247 5.52002 5.49247V19.4965C6.13202 20.0725 6.81602 20.5765 7.54802 20.9725V7.59247L16.38 21.0205C17.148 20.6125 17.856 20.0965 18.48 19.4965Z" - fill={color} - /> - </g> - <defs> - <clipPath id="clip0_2549_7563"> - <rect width="24" height="24" fill="white" transform="translate(0 0.5)" /> - </clipPath> - </defs> - </svg> - ); -}; diff --git a/explorer/src/icons/ValidatorsSVG.tsx b/explorer/src/icons/ValidatorsSVG.tsx deleted file mode 100644 index cf03f1c3304..00000000000 --- a/explorer/src/icons/ValidatorsSVG.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -export const ValidatorsSVG: FCWithChildren = () => { - const theme = useTheme(); - const color = theme.palette.text.primary; - return ( - <svg width="24" height="24" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> - <g clipPath="url(#clip0)"> - <path - d="M18.2001 18.4V19.7001C18.2001 21.4001 16.9 22.7001 15.2 22.7001H4.30005C2.60005 22.7001 1.30005 21.4001 1.30005 19.7001V4.30005C1.30005 2.60005 2.60005 1.30005 4.30005 1.30005H15.1C16.8 1.30005 18.1 2.60005 18.1 4.30005V5.60005V18.4H18.2001Z" - stroke={color} - strokeWidth="1.3" - strokeMiterlimit="10" - strokeLinecap="round" - /> - <path - d="M13.4 22.7001H17.4C19.1 22.7001 20.4 21.4001 20.4 19.7001V18.4V5.60005V4.30005C20.4 2.60005 19.1 1.30005 17.4 1.30005H11.5" - stroke={color} - strokeWidth="1.3" - strokeMiterlimit="10" - strokeLinecap="round" - /> - <path - d="M15.2 22.7001H19.7C21.4 22.7001 22.7 21.4001 22.7 19.7001V18.4V5.60005V4.30005C22.7 2.60005 21.4 1.30005 19.7 1.30005H13.8" - stroke={color} - strokeWidth="1.3" - strokeMiterlimit="10" - strokeLinecap="round" - /> - <path - d="M5 12.3L7.9 15.3L14.5 8.69995" - stroke={color} - strokeWidth="2" - strokeMiterlimit="10" - strokeLinecap="round" - strokeLinejoin="round" - /> - </g> - <defs> - <clipPath id="clip0"> - <rect width="24" height="24" fill="white" /> - </clipPath> - </defs> - </svg> - ); -}; diff --git a/explorer/src/icons/socials/DiscordIcon.tsx b/explorer/src/icons/socials/DiscordIcon.tsx deleted file mode 100644 index 11a9fd1c670..00000000000 --- a/explorer/src/icons/socials/DiscordIcon.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -interface DiscordIconProps { - size?: number | string; - color?: string; -} - -export const DiscordIcon: FCWithChildren<DiscordIconProps> = ({ size, color: colorProp }) => { - const theme = useTheme(); - const color = colorProp || theme.palette.text.primary; - return ( - <svg width={size} height={size} viewBox="0 0 24 24" fill="none"> - <g clipPath="url(#clip0_1223_2296)"> - <path - d="M12.4 0C5.80002 0 0.400024 5.4 0.400024 12C0.400024 18.6 5.80002 24 12.4 24C19 24 24.4 18.6 24.4 12C24.4 5.4 19 0 12.4 0ZM20.1 15.9C18.8 16.9 17.5 17.5 16.2 17.9C16.2 17.9 16.2 17.9 16.1 17.9C15.8 17.5 15.5 17.1 15.3 16.6V16.5C15.7 16.3 16.1 16.1 16.5 15.9V15.8C16.4 15.7 16.3 15.7 16.3 15.6C16.3 15.6 16.3 15.6 16.2 15.6C13.7 16.8 10.9 16.8 8.40002 15.6C8.40002 15.6 8.40002 15.6 8.30002 15.6C8.20002 15.7 8.10002 15.7 8.10002 15.8V15.9C8.50002 16.1 8.90002 16.3 9.30002 16.5C9.30002 16.5 9.30002 16.5 9.30002 16.6C9.10002 17.1 8.80002 17.5 8.50002 17.9C8.50002 17.9 8.50002 17.9 8.40002 17.9C7.10002 17.5 5.90002 16.9 4.50002 15.9C4.40002 13 5.00002 10.1 7.00002 7.1C8.00002 6.6 9.00002 6.3 10.2 6.1C10.2 6.1 10.2 6.1 10.3 6.1C10.4 6.3 10.6 6.7 10.7 6.9C11.9 6.7 13.1 6.7 14.2 6.9C14.3 6.7 14.5 6.3 14.6 6.1C14.6 6.1 14.6 6.1 14.7 6.1C15.8 6.3 16.9 6.6 17.9 7.1C19.5 9.7 20.4 12.6 20.1 15.9Z" - fill={color} - /> - <path - d="M15 11C14.2 11 13.6 11.7 13.6 12.6C13.6 13.5 14.2 14.2 15 14.2C15.8 14.2 16.4 13.5 16.4 12.6C16.4 11.7 15.8 11 15 11Z" - fill={color} - /> - <path - d="M9.80002 11C9.10002 11 8.40002 11.7 8.40002 12.6C8.40002 13.5 9.00002 14.2 9.80002 14.2C10.6 14.2 11.2 13.5 11.2 12.6C11.2 11.7 10.6 11 9.80002 11Z" - fill={color} - /> - </g> - <defs> - <clipPath id="clip0_1223_2296"> - <rect width="24" height="24" transform="translate(0.400024)" /> - </clipPath> - </defs> - </svg> - ); -}; - -DiscordIcon.defaultProps = { - size: 24, - color: undefined, -}; diff --git a/explorer/src/icons/socials/GitHubIcon.tsx b/explorer/src/icons/socials/GitHubIcon.tsx deleted file mode 100644 index a8fde9b0a91..00000000000 --- a/explorer/src/icons/socials/GitHubIcon.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -interface GitHubIconProps { - size?: number | string; - color?: string; -} - -export const GitHubIcon: FCWithChildren<GitHubIconProps> = ({ size, color: colorProp }) => { - const theme = useTheme(); - const color = colorProp || theme.palette.text.primary; - return ( - <svg width={size} height={size} viewBox="0 0 24 24" fill="none"> - <g clipPath="url(#clip0_1223_2302)"> - <path - fillRule="evenodd" - clipRule="evenodd" - d="M12.7 0C5.90002 0 0.400024 5.5 0.400024 12.3C0.400024 17.7 3.90002 22.3 8.80002 24C9.40002 24.1 9.60002 23.7 9.60002 23.4C9.60002 23.1 9.60002 22.1 9.60002 21.1C6.50002 21.7 5.70002 20.3 5.50002 19.7C5.40002 19.3 4.80002 18.3 4.20002 18C3.80002 17.8 3.20002 17.2 4.20002 17.2C5.20002 17.2 5.90002 18.1 6.10002 18.5C7.20002 20.4 9.00002 19.8 9.70002 19.5C9.80002 18.7 10.1 18.2 10.5 17.9C7.80002 17.6 4.90002 16.5 4.90002 11.8C4.90002 10.5 5.40002 9.4 6.20002 8.5C6.00002 8 5.60002 6.8 6.30002 5.1C6.30002 5.1 7.30002 4.8 9.70002 6.4C10.7 6.1 11.7 6 12.8 6C13.8 6 14.9 6.1 15.9 6.4C18.3 4.8 19.3 5.1 19.3 5.1C20 6.8 19.5 8.1 19.4 8.4C20.2 9.3 20.7 10.4 20.7 11.7C20.7 16.4 17.8 17.5 15.1 17.8C15.5 18.2 15.9 18.9 15.9 20.1C15.9 21.7 15.9 23.1 15.9 23.5C15.9 23.8 16.1 24.2 16.7 24.1C21.6 22.5 25.1 17.9 25.1 12.4C25 5.5 19.5 0 12.7 0Z" - fill={color} - /> - </g> - <defs> - <clipPath id="clip0_1223_2302"> - <rect width="24" height="24" transform="translate(0.400024)" /> - </clipPath> - </defs> - </svg> - ); -}; - -GitHubIcon.defaultProps = { - size: 24, - color: undefined, -}; diff --git a/explorer/src/icons/socials/TelegramIcon.tsx b/explorer/src/icons/socials/TelegramIcon.tsx deleted file mode 100644 index cf150a4a2f3..00000000000 --- a/explorer/src/icons/socials/TelegramIcon.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -interface TelegramIconProps { - size?: number | string; - color?: string; -} - -export const TelegramIcon: FCWithChildren<TelegramIconProps> = ({ size, color: colorProp }) => { - const theme = useTheme(); - const color = colorProp || theme.palette.text.primary; - return ( - <svg width={size} height={size} viewBox="0 0 24 24" fill="none"> - <path - d="M12.4 24C19.029 24 24.4 18.629 24.4 12C24.4 5.371 19.029 0 12.4 0C5.77102 0 0.400024 5.371 0.400024 12C0.400024 18.629 5.77102 24 12.4 24ZM5.89102 11.74L17.461 7.279C17.998 7.085 18.467 7.41 18.293 8.222L18.294 8.221L16.324 17.502C16.178 18.16 15.787 18.32 15.24 18.01L12.24 15.799L10.793 17.193C10.633 17.353 10.498 17.488 10.188 17.488L10.401 14.435L15.961 9.412C16.203 9.199 15.907 9.079 15.588 9.291L8.71702 13.617L5.75502 12.693C5.11202 12.489 5.09802 12.05 5.89102 11.74Z" - fill={color} - /> - </svg> - ); -}; - -TelegramIcon.defaultProps = { - size: 24, - color: undefined, -}; diff --git a/explorer/src/icons/socials/TwitterIcon.tsx b/explorer/src/icons/socials/TwitterIcon.tsx deleted file mode 100644 index 6f0b545f562..00000000000 --- a/explorer/src/icons/socials/TwitterIcon.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; - -interface TwitterIconProps { - size?: number | string; - color?: string; -} - -export const TwitterIcon: FCWithChildren<TwitterIconProps> = ({ size, color: colorProp }) => { - const theme = useTheme(); - const color = colorProp || theme.palette.text.primary; - return ( - <svg width={size} height={size} viewBox="0 0 24 24" fill="none"> - <g clipPath="url(#clip0_1223_2294)"> - <path - d="M12.4 0C5.77362 0 0.400024 5.3736 0.400024 12C0.400024 18.6264 5.77362 24 12.4 24C19.0264 24 24.4 18.6264 24.4 12C24.4 5.3736 19.0264 0 12.4 0ZM17.8791 9.35632C17.8844 9.47443 17.887 9.59308 17.887 9.71228C17.887 13.3519 15.1166 17.5488 10.0502 17.549H10.0504H10.0502C8.49475 17.549 7.0473 17.0931 5.82837 16.3118C6.04388 16.3372 6.26324 16.3499 6.48535 16.3499C7.77588 16.3499 8.9635 15.9097 9.90631 15.1708C8.70056 15.1485 7.68396 14.3522 7.33313 13.2578C7.50104 13.29 7.67371 13.3076 7.85077 13.3076C8.10217 13.3076 8.3457 13.2737 8.57715 13.2105C7.31683 12.9582 6.36743 11.8444 6.36743 10.5106C6.36743 10.4982 6.36743 10.487 6.3678 10.4755C6.73895 10.6818 7.16339 10.806 7.6153 10.8199C6.87573 10.3264 6.38959 9.48285 6.38959 8.52722C6.38959 8.02258 6.526 7.5498 6.76257 7.14276C8.12085 8.80939 10.1508 9.90546 12.4399 10.0206C12.3927 9.81885 12.3683 9.60864 12.3683 9.39258C12.3683 7.87207 13.6019 6.63849 15.123 6.63849C15.9153 6.63849 16.6309 6.97339 17.1335 7.50879C17.761 7.38501 18.3502 7.15576 18.8825 6.84027C18.6765 7.48315 18.24 8.02258 17.6713 8.36371C18.2285 8.29706 18.7595 8.14929 19.2529 7.92993C18.8843 8.48236 18.4169 8.96759 17.8791 9.35632V9.35632Z" - fill={color} - /> - </g> - <defs> - <clipPath id="clip0_1223_2294"> - <rect width="24" height="24" transform="translate(0.400024)" /> - </clipPath> - </defs> - </svg> - ); -}; - -TwitterIcon.defaultProps = { - size: 24, - color: undefined, -}; diff --git a/explorer/src/index.html b/explorer/src/index.html deleted file mode 100644 index dd5a4761ee2..00000000000 --- a/explorer/src/index.html +++ /dev/null @@ -1,14 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - -<head> - <meta charset="utf-8" /> - <title>Nym Network Explorer - - - - -
- - - diff --git a/explorer/src/index.tsx b/explorer/src/index.tsx deleted file mode 100644 index 0b76be7ab11..00000000000 --- a/explorer/src/index.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import * as React from 'react'; -import { createRoot } from 'react-dom/client'; -import { BrowserRouter as Router } from 'react-router-dom'; -import { ErrorBoundary } from 'react-error-boundary'; -import { MainContextProvider } from './context/main'; -import { NetworkExplorerThemeProvider } from './theme'; -import { ErrorBoundaryContent } from './errors/ErrorBoundaryContent'; -import CosmosKitProvider from './context/cosmos-kit'; -import '@interchain-ui/react/styles'; -import { App } from './App'; -import { WalletProvider } from './context/wallet'; -import './styles.css'; - -const elem = document.getElementById('app'); - -if (elem) { - const root = createRoot(elem); - root.render( - - - - - - - - - - - - - , - ); -} diff --git a/explorer/src/pages/404/index.tsx b/explorer/src/pages/404/index.tsx deleted file mode 100644 index 02f4247fc50..00000000000 --- a/explorer/src/pages/404/index.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import * as React from 'react'; -import { Box, Button, Grid, Paper, Typography } from '@mui/material'; -import { useTheme } from '@mui/material/styles'; -import { useNavigate } from 'react-router-dom'; -import { NymLogo } from '@nymproject/react/logo/NymLogo'; -import { useMainContext } from '../../context/main'; - -export const Page404 = () => { - const navigate = useNavigate(); - const { mode } = useMainContext(); - const theme = useTheme(); - return ( - - - - - - Oh No! - It looks like you might be lost. - - Please try the link again or navigate back to{' '} - - - - - - - ); -}; diff --git a/explorer/src/pages/Delegations/index.tsx b/explorer/src/pages/Delegations/index.tsx deleted file mode 100644 index 32e178f2fc6..00000000000 --- a/explorer/src/pages/Delegations/index.tsx +++ /dev/null @@ -1,264 +0,0 @@ -import React, { useEffect } from 'react'; -import { Alert, AlertTitle, Box, Button, Card, Chip, IconButton, Tooltip, Typography } from '@mui/material'; -import { Link, useNavigate } from 'react-router-dom'; -import { DelegationModal, DelegationModalProps, Title, UniversalDataGrid } from '@src/components'; -import { useWalletContext } from '@src/context/wallet'; -import { GridColDef } from '@mui/x-data-grid'; -import { unymToNym } from '@src/utils/currency'; -import { - DelegationWithRewards, - DelegationsProvider, - PendingEvent, - useDelegationsContext, -} from '@src/context/delegations'; -import { urls } from '@src/utils'; -import { useClipboard } from 'use-clipboard-copy'; -import { Close } from '@mui/icons-material'; - -const mapToDelegationsRow = (delegation: DelegationWithRewards, index: number) => ({ - identity: delegation.identityKey, - mix_id: delegation.mix_id, - amount: `${unymToNym(delegation.amount.amount)} NYM`, - rewards: `${unymToNym(delegation.rewards)} NYM`, - id: index, - pending: delegation.pending, -}); - -const Banner = ({ onClose }: { onClose: () => void }) => { - const { copy } = useClipboard(); - - return ( - - - - } - > - Mobile Delegations Beta - - - This is a beta release for mobile delegations If you have any feedback or feature suggestions contact us at - support@nymte.ch - - - - - ); -}; - -const DelegationsPage = () => { - const [confirmationModalProps, setConfirmationModalProps] = React.useState(); - const [isLoading, setIsLoading] = React.useState(false); - const [showBanner, setShowBanner] = React.useState(true); - - const { isWalletConnected } = useWalletContext(); - const { handleGetDelegations, handleUndelegate, delegations } = useDelegationsContext(); - const navigate = useNavigate(); - - useEffect(() => { - let timeoutId: NodeJS.Timeout; - - const fetchDelegations = async () => { - setIsLoading(true); - try { - await handleGetDelegations(); - } catch (error) { - setConfirmationModalProps({ - status: 'error', - message: "Couldn't fetch delegations. Please try again later.", - }); - } finally { - setIsLoading(false); - - timeoutId = setTimeout(() => { - fetchDelegations(); - }, 60_000); - } - }; - - fetchDelegations(); - - return () => { - clearTimeout(timeoutId); - }; - }, [handleGetDelegations]); - - const getTooltipTitle = (pending: PendingEvent) => { - if (pending?.kind === 'undelegate') { - return 'You have an undelegation pending'; - } - - if (pending?.kind === 'delegate') { - return `You have a delegation pending worth ${unymToNym(pending.amount.amount)} NYM`; - } - - return undefined; - }; - - const onUndelegate = async (mixId: number) => { - setConfirmationModalProps({ status: 'loading' }); - - try { - const tx = await handleUndelegate(mixId); - - if (tx) { - setConfirmationModalProps({ - status: 'success', - message: 'Undelegation can take up to one hour to process', - transactions: [ - { url: `${urls('MAINNET').blockExplorer}/transaction/${tx.transactionHash}`, hash: tx.transactionHash }, - ], - }); - } - } catch (error) { - if (error instanceof Error) { - setConfirmationModalProps({ status: 'error', message: error.message }); - } - } - }; - - const columns: GridColDef[] = [ - { - field: 'identity', - headerName: 'Identity Key', - width: 400, - disableColumnMenu: true, - disableReorder: true, - sortable: false, - headerAlign: 'left', - }, - { - field: 'mix_id', - headerName: 'Mix ID', - width: 150, - disableColumnMenu: true, - disableReorder: true, - sortable: false, - headerAlign: 'left', - }, - { - field: 'amount', - headerName: 'Amount', - width: 150, - disableColumnMenu: true, - disableReorder: true, - sortable: false, - headerAlign: 'left', - }, - { - field: 'rewards', - headerName: 'Rewards', - width: 150, - disableColumnMenu: true, - disableReorder: true, - sortable: false, - headerAlign: 'left', - }, - { - field: 'undelegate', - headerName: '', - minWidth: 150, - flex: 1, - disableColumnMenu: true, - disableReorder: true, - sortable: false, - headerAlign: 'right', - renderCell: (params) => { - const { pending } = params.row; - - return ( - - {pending ? ( - e.stopPropagation()} - PopperProps={{}} - > - - - ) : ( - - )} - - ); - }, - }, - ]; - - const handleRowClick = (params: any) => { - navigate(`/network-components/mixnode/${params.row.mix_id}`); - }; - - return ( - - {confirmationModalProps && ( - { - if (confirmationModalProps.status === 'success') { - await handleGetDelegations(); - } - setConfirmationModalProps(undefined); - }} - sx={{ - width: { - xs: '90%', - sm: 600, - }, - }} - /> - )} - {showBanner && setShowBanner(false)} />} - - - <Button variant="contained" color="primary" component={Link} to="/network-components/mixnodes"> - Delegate - </Button> - </Box> - {!isWalletConnected ? ( - <Box> - <Typography mb={2} variant="h6"> - Connect your wallet to view your delegations. - </Typography> - </Box> - ) : null} - - <Card - sx={{ - mt: 2, - padding: 2, - height: '100%', - }} - > - <UniversalDataGrid - onRowClick={handleRowClick} - rows={delegations?.map(mapToDelegationsRow) || []} - columns={columns} - loading={isLoading} - /> - </Card> - </Box> - ); -}; - -export const Delegations = () => ( - <DelegationsProvider> - <DelegationsPage /> - </DelegationsProvider> -); diff --git a/explorer/src/pages/GatewayDetail/index.tsx b/explorer/src/pages/GatewayDetail/index.tsx deleted file mode 100644 index 3382947512b..00000000000 --- a/explorer/src/pages/GatewayDetail/index.tsx +++ /dev/null @@ -1,184 +0,0 @@ -import * as React from 'react'; -import { Alert, AlertTitle, Box, CircularProgress, Grid } from '@mui/material'; -import { useParams } from 'react-router-dom'; -import { GatewayBond } from '../../typeDefs/explorer-api'; -import { ColumnsType, DetailTable } from '../../components/DetailTable'; -import { gatewayEnrichedToGridRow, GatewayEnrichedRowType } from '../../components/Gateways'; -import { ComponentError } from '../../components/ComponentError'; -import { ContentCard } from '../../components/ContentCard'; -import { TwoColSmallTable } from '../../components/TwoColSmallTable'; -import { UptimeChart } from '../../components/UptimeChart'; -import { GatewayContextProvider, useGatewayContext } from '../../context/gateway'; -import { useMainContext } from '../../context/main'; -import { Title } from '../../components/Title'; - -const columns: ColumnsType[] = [ - { - field: 'identity_key', - title: 'Identity Key', - headerAlign: 'left', - width: 230, - }, - { - field: 'bond', - title: 'Bond', - headerAlign: 'left', - }, - { - field: 'node_performance', - title: 'Routing Score', - headerAlign: 'left', - tooltipInfo: - "Gateway's most recent score (measured in the last 15 minutes). Routing score is relative to that of the network. Each time a gateway is tested, the test packets have to go through the full path of the network (gateway + 3 nodes). If a node in the path drop packets it will affect the score of the gateway and other nodes in the test", - }, - { - field: 'avgUptime', - title: 'Avg. Score', - headerAlign: 'left', - tooltipInfo: "Gateway's average routing score in the last 24 hours", - }, - { - field: 'host', - title: 'IP', - headerAlign: 'left', - width: 99, - }, - { - field: 'location', - title: 'Location', - headerAlign: 'left', - }, - { - field: 'owner', - title: 'Owner', - headerAlign: 'left', - }, - { - field: 'version', - title: 'Version', - headerAlign: 'left', - }, -]; - -/** - * Shows gateway details - */ -const PageGatewayDetailsWithState = ({ selectedGateway }: { selectedGateway: GatewayBond | undefined }) => { - const [enrichGateway, setEnrichGateway] = React.useState<GatewayEnrichedRowType>(); - const [status, setStatus] = React.useState<number[] | undefined>(); - const { uptimeReport, uptimeStory } = useGatewayContext(); - - React.useEffect(() => { - if (uptimeReport?.data && selectedGateway) { - setEnrichGateway(gatewayEnrichedToGridRow(selectedGateway, uptimeReport.data)); - } - }, [uptimeReport, selectedGateway]); - - React.useEffect(() => { - if (enrichGateway) { - setStatus([enrichGateway.mixPort, enrichGateway.clientsPort]); - } - }, [enrichGateway]); - - return ( - <Box component="main"> - <Title text="Gateway Detail" /> - - <Grid container> - <Grid item xs={12}> - <DetailTable - columnsData={columns} - tableName="Gateway detail table" - rows={enrichGateway ? [enrichGateway] : []} - /> - </Grid> - </Grid> - - <Grid container spacing={2} mt={0}> - <Grid item xs={12} md={4}> - {status && ( - <ContentCard title="Gateway Status"> - <TwoColSmallTable - loading={false} - keys={['Mix port', 'Client WS API Port']} - values={status.map((each) => each)} - icons={status.map((elem) => !!elem)} - /> - </ContentCard> - )} - </Grid> - <Grid item xs={12} md={8}> - {uptimeStory && ( - <ContentCard title="Routing Score"> - {uptimeStory.error && <ComponentError text="There was a problem retrieving routing score." />} - <UptimeChart - loading={uptimeStory.isLoading} - xLabel="Date" - yLabel="Daily average" - uptimeStory={uptimeStory} - /> - </ContentCard> - )} - </Grid> - </Grid> - </Box> - ); -}; - -/** - * Guard component to handle loading and not found states - */ -const PageGatewayDetailGuard: FCWithChildren = () => { - const [selectedGateway, setSelectedGateway] = React.useState<GatewayBond>(); - const { gateways } = useMainContext(); - const { id } = useParams<{ id: string | undefined }>(); - - React.useEffect(() => { - if (gateways?.data) { - setSelectedGateway(gateways.data.find((g) => g.gateway.identity_key === id)); - } - }, [gateways, id]); - - if (gateways?.isLoading) { - return <CircularProgress />; - } - - if (gateways?.error) { - // eslint-disable-next-line no-console - console.error(gateways?.error); - return ( - <Alert severity="error"> - Oh no! Could not load mixnode <code>{id || ''}</code> - </Alert> - ); - } - - // loaded, but not found - if (gateways && !gateways.isLoading && !gateways.data) { - return ( - <Alert severity="warning"> - <AlertTitle>Gateway not found</AlertTitle> - Sorry, we could not find a mixnode with id <code>{id || ''}</code> - </Alert> - ); - } - - return <PageGatewayDetailsWithState selectedGateway={selectedGateway} />; -}; - -/** - * Wrapper component that adds the mixnode content based on the `id` in the address URL - */ -export const PageGatewayDetail: FCWithChildren = () => { - const { id } = useParams<{ id: string | undefined }>(); - - if (!id) { - return <Alert severity="error">Oh no! No mixnode identity key specified</Alert>; - } - - return ( - <GatewayContextProvider gatewayIdentityKey={id}> - <PageGatewayDetailGuard /> - </GatewayContextProvider> - ); -}; diff --git a/explorer/src/pages/Gateways/index.tsx b/explorer/src/pages/Gateways/index.tsx deleted file mode 100644 index c04b7eaf405..00000000000 --- a/explorer/src/pages/Gateways/index.tsx +++ /dev/null @@ -1,271 +0,0 @@ -import * as React from 'react'; -import { Box, Card, Grid, Stack } from '@mui/material'; -import { useTheme } from '@mui/material/styles'; -import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard'; -import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid'; -import { SelectChangeEvent } from '@mui/material/Select'; -import { diff, gte, rcompare } from 'semver'; -import { Tooltip as InfoTooltip } from '@nymproject/react/tooltip/Tooltip'; -import { useMainContext } from '../../context/main'; -import { gatewayToGridRow } from '../../components/Gateways'; -import { GatewayResponse } from '../../typeDefs/explorer-api'; -import { TableToolbar } from '../../components/TableToolbar'; -import { CustomColumnHeading } from '../../components/CustomColumnHeading'; -import { Title } from '../../components/Title'; -import { UniversalDataGrid } from '../../components/Universal-DataGrid'; -import { unymToNym } from '../../utils/currency'; -import { Tooltip } from '../../components/Tooltip'; -import { NYM_BIG_DIPPER } from '../../api/constants'; -import { splice } from '../../utils'; -import { VersionDisplaySelector, VersionSelectOptions } from '../../components/Gateways/VersionDisplaySelector'; -import StyledLink from '../../components/StyledLink'; - -export const PageGateways: FCWithChildren = () => { - const { gateways } = useMainContext(); - const [filteredGateways, setFilteredGateways] = React.useState<GatewayResponse>([]); - const [pageSize, setPageSize] = React.useState<string>('50'); - const [searchTerm, setSearchTerm] = React.useState<string>(''); - const [versionFilter, setVersionFilter] = React.useState<VersionSelectOptions>(VersionSelectOptions.all); - - const theme = useTheme(); - - const handleSearch = (str: string) => { - setSearchTerm(str.toLowerCase()); - }; - - const highestVersion = React.useMemo(() => { - if (gateways?.data) { - const versions = gateways.data.reduce((a: string[], b) => [...a, b.gateway.version], []); - const [lastestVersion] = versions.sort(rcompare); - return lastestVersion; - } - // fallback value - return '2.0.0'; - }, [gateways]); - - const filterByLatestVersions = React.useMemo(() => { - const filtered = gateways?.data?.filter((gw) => { - const versionDiff = diff(highestVersion, gw.gateway.version); - return versionDiff === 'patch' || versionDiff === null; - }); - if (filtered) return filtered; - return []; - }, [gateways]); - - const filterByOlderVersions = React.useMemo(() => { - const filtered = gateways?.data?.filter((gw) => { - const versionDiff = diff(highestVersion, gw.gateway.version); - return versionDiff === 'major' || versionDiff === 'minor'; - }); - if (filtered) return filtered; - return []; - }, [gateways]); - - const filteredByVersion = React.useMemo(() => { - switch (versionFilter) { - case VersionSelectOptions.latestVersion: - return filterByLatestVersions; - case VersionSelectOptions.olderVersions: - return filterByOlderVersions; - case VersionSelectOptions.all: - return gateways?.data || []; - default: - return []; - } - }, [versionFilter, gateways]); - - React.useEffect(() => { - if (searchTerm === '') { - setFilteredGateways(filteredByVersion); - } else { - const filtered = filteredByVersion.filter((g) => { - if ( - g.gateway.location.toLowerCase().includes(searchTerm) || - g.gateway.identity_key.toLocaleLowerCase().includes(searchTerm) || - g.owner.toLowerCase().includes(searchTerm) - ) { - return g; - } - return null; - }); - - if (filtered) { - setFilteredGateways(filtered); - } - } - }, [searchTerm, gateways?.data, versionFilter]); - - const columns: GridColDef[] = [ - { - field: 'identity_key', - renderHeader: () => <CustomColumnHeading headingTitle="Identity Key" />, - headerClassName: 'MuiDataGrid-header-override', - width: 400, - disableColumnMenu: true, - headerAlign: 'center', - renderCell: (params: GridRenderCellParams) => ( - <Stack direction="row" gap={1}> - <CopyToClipboard smallIcons value={params.value} tooltip={`Copy identity key ${params.value} to clipboard`} /> - <StyledLink to={`/network-components/gateway/${params.row.identity_key}`}>{params.value}</StyledLink> - </Stack> - ), - }, - { - field: 'node_performance', - align: 'center', - renderHeader: () => ( - <> - <InfoTooltip - id="gateways-list-routing-score" - title="Gateway's most recent score (measured in the last 15 minutes). Routing score is relative to that of the network. Each time a gateway is tested, the test packets have to go through the full path of the network (gateway + 3 nodes). If a node in the path drop packets it will affect the score of the gateway and other nodes in the test" - placement="top-start" - textColor={theme.palette.nym.networkExplorer.tooltip.color} - bgColor={theme.palette.nym.networkExplorer.tooltip.background} - maxWidth={230} - arrow - /> - <CustomColumnHeading headingTitle="Routing Score" /> - </> - ), - width: 120, - disableColumnMenu: true, - headerAlign: 'center', - headerClassName: 'MuiDataGrid-header-override', - renderCell: (params: GridRenderCellParams) => ( - <StyledLink to={`/network-components/gateway/${params.row.identity_key}`} data-testid="pledge-amount"> - {`${params.value}%`} - </StyledLink> - ), - }, - { - field: 'version', - align: 'center', - renderHeader: () => <CustomColumnHeading headingTitle="Version" />, - width: 150, - disableColumnMenu: true, - headerAlign: 'center', - headerClassName: 'MuiDataGrid-header-override', - renderCell: (params: GridRenderCellParams) => ( - <StyledLink to={`/network-components/gateway/${params.row.identity_key}`} data-testid="version"> - {params.value} - </StyledLink> - ), - sortComparator: (a, b) => { - if (gte(a, b)) return 1; - return -1; - }, - }, - { - field: 'location', - renderHeader: () => <CustomColumnHeading headingTitle="Location" />, - width: 180, - disableColumnMenu: true, - headerAlign: 'left', - headerClassName: 'MuiDataGrid-header-override', - renderCell: (params: GridRenderCellParams) => ( - <Box - onClick={() => handleSearch(params.value as string)} - sx={{ justifyContent: 'flex-start', cursor: 'pointer' }} - data-testid="location-button" - > - <Tooltip text={params.value} id="gateway-location-text"> - <Box - sx={{ - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - }} - > - {params.value} - </Box> - </Tooltip> - </Box> - ), - }, - { - field: 'host', - renderHeader: () => <CustomColumnHeading headingTitle="IP:Port" />, - width: 180, - disableColumnMenu: true, - headerAlign: 'left', - headerClassName: 'MuiDataGrid-header-override', - renderCell: (params: GridRenderCellParams) => ( - <StyledLink to={`/network-components/gateway/${params.row.identity_key}`} data-testid="host"> - {params.value} - </StyledLink> - ), - }, - { - field: 'owner', - headerName: 'Owner', - renderHeader: () => <CustomColumnHeading headingTitle="Owner" />, - width: 180, - disableColumnMenu: true, - headerAlign: 'left', - headerClassName: 'MuiDataGrid-header-override', - renderCell: (params: GridRenderCellParams) => ( - <StyledLink to={`${NYM_BIG_DIPPER}/account/${params.value}`} target="_blank" data-testid="owner"> - {splice(7, 29, params.value)} - </StyledLink> - ), - }, - { - field: 'bond', - width: 150, - disableColumnMenu: true, - type: 'number', - renderHeader: () => <CustomColumnHeading headingTitle="Bond" />, - headerClassName: 'MuiDataGrid-header-override', - headerAlign: 'left', - renderCell: (params: GridRenderCellParams) => ( - <StyledLink to={`/network-components/gateway/${params.row.identity_key}`} data-testid="pledge-amount"> - {`${unymToNym(params.value, 6)}`} - </StyledLink> - ), - }, - ]; - - const handlePageSize = (event: SelectChangeEvent<string>) => { - setPageSize(event.target.value); - }; - - if (gateways?.data) { - return ( - <> - <Box mb={2}> - <Title text="Gateways" /> - </Box> - <Grid container> - <Grid item xs={12}> - <Card - sx={{ - padding: 2, - height: '100%', - }} - > - <TableToolbar - onChangeSearch={handleSearch} - onChangePageSize={handlePageSize} - pageSize={pageSize} - searchTerm={searchTerm} - childrenBefore={ - <VersionDisplaySelector - handleChange={(option) => setVersionFilter(option)} - selected={versionFilter} - /> - } - /> - <UniversalDataGrid - pagination - rows={gatewayToGridRow(filteredGateways)} - columns={columns} - pageSize={pageSize} - /> - </Card> - </Grid> - </Grid> - </> - ); - } - return null; -}; diff --git a/explorer/src/pages/MixnodeDetail/index.tsx b/explorer/src/pages/MixnodeDetail/index.tsx deleted file mode 100644 index 5ceaa368670..00000000000 --- a/explorer/src/pages/MixnodeDetail/index.tsx +++ /dev/null @@ -1,236 +0,0 @@ -import * as React from 'react'; -import { Alert, AlertTitle, Box, CircularProgress, Grid, Typography } from '@mui/material'; -import { useParams } from 'react-router-dom'; -import { ColumnsType, DetailTable } from '../../components/DetailTable'; -import { BondBreakdownTable } from '../../components/MixNodes/BondBreakdown'; -import { DelegatorsInfoTable, EconomicsInfoColumns, EconomicsInfoRows } from '../../components/MixNodes/Economics'; -import { ComponentError } from '../../components/ComponentError'; -import { ContentCard } from '../../components/ContentCard'; -import { TwoColSmallTable } from '../../components/TwoColSmallTable'; -import { UptimeChart } from '../../components/UptimeChart'; -import { WorldMap } from '../../components/WorldMap'; -import { MixNodeDetailSection } from '../../components/MixNodes/DetailSection'; -import { MixnodeContextProvider, useMixnodeContext } from '../../context/mixnode'; -import { Title } from '../../components/Title'; -import { useIsMobile } from '../../hooks/useIsMobile'; - -const columns: ColumnsType[] = [ - { - field: 'owner', - title: 'Owner', - width: '15%', - }, - { - field: 'identity_key', - title: 'Identity Key', - width: '15%', - }, - - { - field: 'bond', - title: 'Stake', - width: '12.5%', - }, - { - field: 'stake_saturation', - title: 'Stake Saturation', - width: '12.5%', - tooltipInfo: - 'Level of stake saturation for this node. Nodes receive more rewards the higher their saturation level, up to 100%. Beyond 100% no additional rewards are granted. The current stake saturation level is 940k NYMs, computed as S/K where S is target amount of tokens staked in the network and K is the number of nodes in the reward set.', - }, - { - field: 'self_percentage', - width: '10%', - title: 'Bond %', - tooltipInfo: "Percentage of the operator's bond to the total stake on the node", - }, - - { - field: 'host', - width: '10%', - title: 'Host', - }, - { - field: 'location', - title: 'Location', - }, - - { - field: 'layer', - title: 'Layer', - }, -]; - -/** - * Shows mix node details - */ -const PageMixnodeDetailWithState: FCWithChildren = () => { - const { mixNode, mixNodeRow, description, stats, status, uptimeStory, uniqDelegations } = useMixnodeContext(); - const isMobile = useIsMobile(); - return ( - <Box component="main"> - <Title text="Mixnode Detail" /> - <Grid container spacing={2} mt={1} mb={6}> - <Grid item xs={12}> - {mixNodeRow && description?.data && ( - <MixNodeDetailSection mixNodeRow={mixNodeRow} mixnodeDescription={description.data} /> - )} - {mixNodeRow?.blacklisted && ( - <Typography textAlign={isMobile ? 'left' : 'right'} fontSize="smaller" sx={{ color: 'error.main' }}> - This node is having a poor performance - </Typography> - )} - </Grid> - </Grid> - <Grid container> - <Grid item xs={12}> - <DetailTable columnsData={columns} tableName="Mixnode detail table" rows={mixNodeRow ? [mixNodeRow] : []} /> - </Grid> - </Grid> - <Grid container spacing={2} mt={0}> - <Grid item xs={12}> - <DelegatorsInfoTable - columnsData={EconomicsInfoColumns} - tableName="Delegators info table" - rows={[EconomicsInfoRows()]} - /> - </Grid> - </Grid> - <Grid container spacing={2} mt={0}> - <Grid item xs={12}> - <ContentCard title={`Stake Breakdown (${uniqDelegations?.data?.length} delegators)`}> - <BondBreakdownTable /> - </ContentCard> - </Grid> - </Grid> - <Grid container spacing={2} mt={0}> - <Grid item xs={12} md={4}> - <ContentCard title="Mixnode Stats"> - {stats && ( - <> - {stats.error && <ComponentError text="There was a problem retrieving this nodes stats." />} - <TwoColSmallTable - loading={stats.isLoading} - error={stats?.error?.message} - title="Since startup" - keys={['Received', 'Sent', 'Explicitly dropped']} - values={[ - stats?.data?.packets_received_since_startup || 0, - stats?.data?.packets_sent_since_startup || 0, - stats?.data?.packets_explicitly_dropped_since_startup || 0, - ]} - /> - <TwoColSmallTable - loading={stats.isLoading} - error={stats?.error?.message} - title="Since last update" - keys={['Received', 'Sent', 'Explicitly dropped']} - values={[ - stats?.data?.packets_received_since_last_update || 0, - stats?.data?.packets_sent_since_last_update || 0, - stats?.data?.packets_explicitly_dropped_since_last_update || 0, - ]} - marginBottom - /> - </> - )} - {!stats && <Typography>No stats information</Typography>} - </ContentCard> - </Grid> - <Grid item xs={12} md={8}> - {uptimeStory && ( - <ContentCard title="Routing Score"> - {uptimeStory.error && <ComponentError text="There was a problem retrieving routing score." />} - <UptimeChart - loading={uptimeStory.isLoading} - xLabel="Date" - yLabel="Daily average" - uptimeStory={uptimeStory} - /> - </ContentCard> - )} - </Grid> - </Grid> - <Grid container spacing={2} mt={0}> - <Grid item xs={12} md={4}> - {status && ( - <ContentCard title="Mixnode Status"> - {status.error && <ComponentError text="There was a problem retrieving port information" />} - <TwoColSmallTable - loading={status.isLoading} - error={status?.error?.message} - keys={['Mix port', 'Verloc port', 'HTTP port']} - values={[1789, 1790, 8000].map((each) => each)} - icons={(status?.data?.ports && Object.values(status.data.ports)) || [false, false, false]} - /> - </ContentCard> - )} - </Grid> - <Grid item xs={12} md={8}> - {mixNode && ( - <ContentCard title="Location"> - {mixNode?.error && <ComponentError text="There was a problem retrieving this mixnode location" />} - {mixNode?.data?.location?.latitude && mixNode?.data?.location?.longitude && ( - <WorldMap - loading={mixNode.isLoading} - userLocation={[mixNode.data.location.longitude, mixNode.data.location.latitude]} - /> - )} - </ContentCard> - )} - </Grid> - </Grid> - </Box> - ); -}; - -/** - * Guard component to handle loading and not found states - */ -const PageMixnodeDetailGuard: FCWithChildren = () => { - const { mixNode } = useMixnodeContext(); - const { id } = useParams<{ id: string | undefined }>(); - - if (mixNode?.isLoading) { - return <CircularProgress />; - } - - if (mixNode?.error) { - // eslint-disable-next-line no-console - console.error(mixNode?.error); - return ( - <Alert severity="error"> - Oh no! Could not load mixnode <code>{id || ''}</code> - </Alert> - ); - } - - // loaded, but not found - if (mixNode && !mixNode.isLoading && !mixNode.data) { - return ( - <Alert severity="warning"> - <AlertTitle>Mixnode not found</AlertTitle> - Sorry, we could not find a mixnode with id <code>{id || ''}</code> - </Alert> - ); - } - - return <PageMixnodeDetailWithState />; -}; - -/** - * Wrapper component that adds the mixnode content based on the `id` in the address URL - */ -export const PageMixnodeDetail: FCWithChildren = () => { - const { id } = useParams<{ id: string | undefined }>(); - - if (!id) { - return <Alert severity="error">Oh no! No mixnode identity key specified</Alert>; - } - - return ( - <MixnodeContextProvider mixId={id}> - <PageMixnodeDetailGuard /> - </MixnodeContextProvider> - ); -}; diff --git a/explorer/src/pages/Mixnodes/index.tsx b/explorer/src/pages/Mixnodes/index.tsx deleted file mode 100644 index 79a88f7053a..00000000000 --- a/explorer/src/pages/Mixnodes/index.tsx +++ /dev/null @@ -1,427 +0,0 @@ -import * as React from 'react'; -import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid'; -import { Stack, Card, Grid, Box, Button } from '@mui/material'; -import { useParams, useNavigate, Link } from 'react-router-dom'; -import { SelectChangeEvent } from '@mui/material/Select'; -import { CopyToClipboard } from '@nymproject/react/clipboard/CopyToClipboard'; -import { useMainContext } from '@src/context/main'; -import { - DelegateIconButton, - DelegationModal, - DelegationModalProps, - DelegateModal, - CustomColumnHeading, - StyledLink, - Title, - UniversalDataGrid, - TableToolbar, - Tooltip, - MixNodeStatusDropdown, - mixnodeToGridRow, -} from '@src/components'; -import { MixNodeResponse, MixnodeStatusWithAll, toMixnodeStatus } from '@src/typeDefs/explorer-api'; -import { NYM_BIG_DIPPER } from '@src/api/constants'; -import { currencyToString } from '@src/utils/currency'; -import { splice } from '@src/utils'; -import { useGetMixNodeStatusColor, useIsMobile } from '@src/hooks'; -import { useWalletContext } from '@src/context/wallet'; -import { DelegationsProvider } from '@src/context/delegations'; - -export const PageMixnodes: FCWithChildren = () => { - const { mixnodes, fetchMixnodes } = useMainContext(); - const [filteredMixnodes, setFilteredMixnodes] = React.useState<MixNodeResponse>([]); - const [pageSize, setPageSize] = React.useState<string>('10'); - const [searchTerm, setSearchTerm] = React.useState<string>(''); - const [itemSelectedForDelegation, setItemSelectedForDelegation] = React.useState<{ - mixId: number; - identityKey: string; - }>(); - const [confirmationModalProps, setConfirmationModalProps] = React.useState<DelegationModalProps | undefined>(); - const { status } = useParams<{ status: MixnodeStatusWithAll | undefined }>(); - - const navigate = useNavigate(); - const { isWalletConnected } = useWalletContext(); - const isMobile = useIsMobile(); - - const handleNewDelegation = (delegationModalProps: DelegationModalProps) => { - setItemSelectedForDelegation(undefined); - setConfirmationModalProps(delegationModalProps); - }; - - const handleSearch = (str: string) => { - setSearchTerm(str.toLowerCase()); - }; - - React.useEffect(() => { - if (searchTerm === '' && mixnodes?.data) { - setFilteredMixnodes(mixnodes?.data); - } else { - const filtered = mixnodes?.data?.filter((m) => { - if ( - m.location?.country_name.toLowerCase().includes(searchTerm) || - m.mix_node.identity_key.toLocaleLowerCase().includes(searchTerm) || - m.owner.toLowerCase().includes(searchTerm) - ) { - return m; - } - return null; - }); - if (filtered) { - setFilteredMixnodes(filtered); - } - } - }, [searchTerm, mixnodes?.data, mixnodes?.isLoading]); - - React.useEffect(() => { - // when the status changes, get the mixnodes - fetchMixnodes(toMixnodeStatus(status)); - }, [status]); - - const handleMixnodeStatusChanged = (newStatus?: MixnodeStatusWithAll) => { - navigate( - newStatus && newStatus !== MixnodeStatusWithAll.all - ? `/network-components/mixnodes/${newStatus}` - : '/network-components/mixnodes', - ); - }; - - const handleOnDelegate = ({ identityKey, mixId }: { identityKey: string; mixId: number }) => { - if (!isWalletConnected) { - setConfirmationModalProps({ - status: 'info', - message: 'Please connect your wallet to delegate', - }); - } else { - setItemSelectedForDelegation({ identityKey, mixId }); - } - }; - - const columns: GridColDef[] = [ - { - field: 'delegate', - disableColumnMenu: true, - disableReorder: true, - sortable: false, - width: isMobile ? 25 : 100, - headerAlign: 'left', - headerClassName: 'MuiDataGrid-header-override', - renderHeader: () => null, - renderCell: (params: GridRenderCellParams) => ( - <DelegateIconButton - size="small" - onDelegate={() => handleOnDelegate({ identityKey: params.row.identity_key, mixId: params.row.mix_id })} - /> - ), - }, - { - field: 'identity_key', - width: 325, - headerName: 'Identity Key', - headerAlign: 'left', - headerClassName: 'MuiDataGrid-header-override', - disableColumnMenu: true, - renderHeader: () => <CustomColumnHeading headingTitle="Identity Key" />, - renderCell: (params: GridRenderCellParams) => ( - <Stack direction="row" alignItems="center" gap={1}> - <CopyToClipboard - sx={{ mr: 0.5, color: 'grey.400' }} - smallIcons - value={params.value} - tooltip={`Copy identity key ${params.value} to clipboard`} - /> - <StyledLink - to={`/network-components/mixnode/${params.row.mix_id}`} - color={useGetMixNodeStatusColor(params.row.status)} - dataTestId="identity-link" - > - {splice(7, 29, params.value)} - </StyledLink> - </Stack> - ), - }, - { - field: 'mix_id', - width: 85, - align: 'center', - hide: true, - headerName: 'Mix ID', - headerAlign: 'center', - headerClassName: 'MuiDataGrid-header-override', - disableColumnMenu: true, - renderHeader: () => <CustomColumnHeading headingTitle="Mix ID" />, - renderCell: (params: GridRenderCellParams) => ( - <StyledLink - to={`/network-components/mixnode/${params.value}`} - color={useGetMixNodeStatusColor(params.row.status)} - data-testid="mix-id" - > - {params.value} - </StyledLink> - ), - }, - - { - field: 'bond', - width: 150, - align: 'left', - type: 'number', - disableColumnMenu: true, - headerName: 'Stake', - headerAlign: 'left', - headerClassName: 'MuiDataGrid-header-override', - renderHeader: () => <CustomColumnHeading headingTitle="Stake" />, - renderCell: (params: GridRenderCellParams) => ( - <StyledLink - to={`/network-components/mixnode/${params.row.mix_id}`} - color={useGetMixNodeStatusColor(params.row.status)} - > - {currencyToString({ amount: params.value })} - </StyledLink> - ), - }, - { - field: 'stake_saturation', - width: 185, - align: 'center', - headerName: 'Stake Saturation', - headerAlign: 'center', - headerClassName: 'MuiDataGrid-header-override', - disableColumnMenu: true, - renderHeader: () => ( - <CustomColumnHeading - headingTitle="Stake Saturation" - tooltipInfo="Level of stake saturation for this node. Nodes receive more rewards the higher their saturation level, up to 100%. Beyond 100% no additional rewards are granted. The current stake saturation level is 940k NYMs, computed as S/K where S is target amount of tokens staked in the network and K is the number of nodes in the reward set." - /> - ), - renderCell: (params: GridRenderCellParams) => ( - <StyledLink - to={`/network-components/mixnode/${params.row.mix_id}`} - color={useGetMixNodeStatusColor(params.row.status)} - >{`${params.value} %`}</StyledLink> - ), - }, - { - field: 'pledge_amount', - width: 150, - align: 'left', - type: 'number', - headerName: 'Bond', - headerAlign: 'left', - headerClassName: 'MuiDataGrid-header-override', - disableColumnMenu: true, - renderHeader: () => <CustomColumnHeading headingTitle="Bond" tooltipInfo="Node operator's share of stake." />, - renderCell: (params: GridRenderCellParams) => ( - <StyledLink - to={`/network-components/mixnode/${params.row.mix_id}`} - color={useGetMixNodeStatusColor(params.row.status)} - > - {currencyToString({ amount: params.value })} - </StyledLink> - ), - }, - { - field: 'profit_percentage', - width: 145, - align: 'center', - headerName: 'Profit Margin', - headerAlign: 'center', - headerClassName: 'MuiDataGrid-header-override', - disableColumnMenu: true, - renderHeader: () => ( - <CustomColumnHeading - headingTitle="Profit Margin" - tooltipInfo="Percentage of the delegators rewards that the operator takes as fee before rewards are distributed to the delegators." - /> - ), - renderCell: (params: GridRenderCellParams) => ( - <StyledLink - to={`/network-components/mixnode/${params.row.mix_id}`} - color={useGetMixNodeStatusColor(params.row.status)} - >{`${params.value}%`}</StyledLink> - ), - }, - { - field: 'operating_cost', - width: 170, - align: 'center', - headerName: 'Operating Cost', - headerAlign: 'center', - headerClassName: 'MuiDataGrid-header-override', - disableColumnMenu: true, - renderHeader: () => ( - <CustomColumnHeading - headingTitle="Operating Cost" - tooltipInfo="Monthly operational cost of running this node. This cost is set by the operator and it influences how the rewards are split between the operator and delegators." - /> - ), - renderCell: (params: GridRenderCellParams) => ( - <StyledLink - to={`/network-components/mixnode/${params.row.mix_id}`} - color={useGetMixNodeStatusColor(params.row.status)} - >{`${params.value} NYM`}</StyledLink> - ), - }, - { - field: 'node_performance', - width: 165, - align: 'center', - headerName: 'Routing Score', - headerAlign: 'center', - headerClassName: 'MuiDataGrid-header-override', - disableColumnMenu: true, - renderHeader: () => ( - <CustomColumnHeading - headingTitle="Routing Score" - tooltipInfo="Mixnode's most recent score (measured in the last 15 minutes). Routing score is relative to that of the network. Each time a gateway is tested, the test packets have to go through the full path of the network (gateway + 3 nodes). If a node in the path drop packets it will affect the score of the gateway and other nodes in the test." - /> - ), - renderCell: (params: GridRenderCellParams) => ( - <StyledLink - to={`/network-components/mixnode/${params.row.mix_id}`} - color={useGetMixNodeStatusColor(params.row.status)} - >{`${params.value}%`}</StyledLink> - ), - }, - { - field: 'owner', - width: 120, - headerName: 'Owner', - headerAlign: 'left', - headerClassName: 'MuiDataGrid-header-override', - disableColumnMenu: true, - renderHeader: () => <CustomColumnHeading headingTitle="Owner" />, - renderCell: (params: GridRenderCellParams) => ( - <StyledLink - to={`${NYM_BIG_DIPPER}/account/${params.value}`} - color={useGetMixNodeStatusColor(params.row.status)} - target="_blank" - data-testid="big-dipper-link" - > - {splice(7, 29, params.value)} - </StyledLink> - ), - }, - { - field: 'location', - width: 150, - headerName: 'Location', - headerAlign: 'left', - headerClassName: 'MuiDataGrid-header-override', - disableColumnMenu: true, - renderHeader: () => <CustomColumnHeading headingTitle="Location" />, - renderCell: (params: GridRenderCellParams) => ( - <Tooltip text={params.value} id="mixnode-location-text"> - <Box - sx={{ - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - cursor: 'pointer', - color: useGetMixNodeStatusColor(params.row.status), - }} - onClick={() => handleSearch(params.value)} - > - {params.value} - </Box> - </Tooltip> - ), - }, - { - field: 'host', - width: 130, - headerName: 'Host', - headerAlign: 'left', - headerClassName: 'MuiDataGrid-header-override', - disableColumnMenu: true, - renderHeader: () => <CustomColumnHeading headingTitle="Host" />, - renderCell: (params: GridRenderCellParams) => ( - <StyledLink - color={useGetMixNodeStatusColor(params.row.status)} - to={`/network-components/mixnode/${params.row.mix_id}`} - > - {params.value} - </StyledLink> - ), - }, - ]; - - const handlePageSize = (event: SelectChangeEvent<string>) => { - setPageSize(event.target.value); - }; - - return ( - <DelegationsProvider> - <Box mb={2}> - <Title text="Mixnodes" /> - </Box> - <Grid container> - <Grid item xs={12}> - <Card - sx={{ - padding: 2, - height: '100%', - }} - > - <TableToolbar - childrenBefore={ - <MixNodeStatusDropdown sx={{ mr: 2 }} status={status} onSelectionChanged={handleMixnodeStatusChanged} /> - } - childrenAfter={ - isWalletConnected && ( - <Button fullWidth size="large" variant="outlined" color="primary" component={Link} to="/delegations"> - Delegations - </Button> - ) - } - onChangeSearch={handleSearch} - onChangePageSize={handlePageSize} - pageSize={pageSize} - searchTerm={searchTerm} - withFilters - /> - <UniversalDataGrid - pagination - loading={Boolean(mixnodes?.isLoading)} - rows={mixnodeToGridRow(filteredMixnodes)} - columns={columns} - pageSize={pageSize} - /> - </Card> - </Grid> - </Grid> - - {itemSelectedForDelegation && ( - <DelegateModal - onClose={() => { - setItemSelectedForDelegation(undefined); - }} - header="Delegate" - buttonText="Delegate stake" - denom="nym" - onOk={(delegationModalProps: DelegationModalProps) => handleNewDelegation(delegationModalProps)} - identityKey={itemSelectedForDelegation.identityKey} - mixId={itemSelectedForDelegation.mixId} - /> - )} - - {confirmationModalProps && ( - <DelegationModal - {...confirmationModalProps} - open={Boolean(confirmationModalProps)} - onClose={async () => { - setConfirmationModalProps(undefined); - if (confirmationModalProps.status === 'success') { - navigate('/delegations'); - } - }} - sx={{ - width: { - xs: '90%', - sm: 600, - }, - }} - /> - )} - </DelegationsProvider> - ); -}; diff --git a/explorer/src/pages/MixnodesMap/index.tsx b/explorer/src/pages/MixnodesMap/index.tsx deleted file mode 100644 index a7c0048a111..00000000000 --- a/explorer/src/pages/MixnodesMap/index.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import * as React from 'react'; -import { Alert, Box, CircularProgress, Grid, SelectChangeEvent, Typography } from '@mui/material'; -import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid'; -import { ContentCard } from '../../components/ContentCard'; -import { CustomColumnHeading } from '../../components/CustomColumnHeading'; -import { TableToolbar } from '../../components/TableToolbar'; -import { Title } from '../../components/Title'; -import { UniversalDataGrid } from '../../components/Universal-DataGrid'; -import { WorldMap } from '../../components/WorldMap'; -import { useMainContext } from '../../context/main'; -import { CountryDataRowType, countryDataToGridRow } from '../../utils'; - -export const PageMixnodesMap: FCWithChildren = () => { - const { countryData } = useMainContext(); - const [pageSize, setPageSize] = React.useState<string>('10'); - const [formattedCountries, setFormattedCountries] = React.useState<CountryDataRowType[]>([]); - const [searchTerm, setSearchTerm] = React.useState<string>(''); - - const handleSearch = (str: string) => { - setSearchTerm(str.toLowerCase()); - }; - - const handlePageSize = (event: SelectChangeEvent<string>) => { - setPageSize(event.target.value); - }; - - const columns: GridColDef[] = [ - { - field: 'countryName', - renderHeader: () => <CustomColumnHeading headingTitle="Location" />, - flex: 1, - headerAlign: 'left', - headerClassName: 'MuiDataGrid-header-override', - renderCell: (params: GridRenderCellParams) => <Typography data-testid="country-name">{params.value}</Typography>, - }, - { - field: 'nodes', - renderHeader: () => <CustomColumnHeading headingTitle="Number of Nodes" />, - flex: 1, - headerAlign: 'left', - headerClassName: 'MuiDataGrid-header-override', - renderCell: (params: GridRenderCellParams) => ( - <Typography data-testid="number-of-nodes">{params.value}</Typography> - ), - }, - { - field: 'percentage', - renderHeader: () => <CustomColumnHeading headingTitle="Percentage %" />, - flex: 1, - headerAlign: 'left', - headerClassName: 'MuiDataGrid-header-override', - renderCell: (params: GridRenderCellParams) => <Typography data-testid="percentage">{params.value}</Typography>, - }, - ]; - - React.useEffect(() => { - if (countryData?.data && searchTerm === '') { - setFormattedCountries(countryDataToGridRow(Object.values(countryData.data))); - } else if (countryData?.data !== undefined && searchTerm !== '') { - const formatted = countryDataToGridRow(Object.values(countryData?.data)); - const filtered = formatted.filter( - (m) => m?.countryName?.toLowerCase().includes(searchTerm) || m?.ISO3?.toLowerCase().includes(searchTerm), - ); - if (filtered) { - setFormattedCountries(filtered); - } - } - }, [searchTerm, countryData?.data]); - - if (countryData?.isLoading) { - return <CircularProgress />; - } - - if (countryData?.data && !countryData.isLoading) { - return ( - <Box component="main" sx={{ flexGrow: 1 }}> - <Grid> - <Grid item data-testid="mixnodes-globe"> - <Title text="Mixnodes Around the Globe" /> - </Grid> - <Grid item> - <Grid container spacing={2}> - <Grid item xs={12}> - <ContentCard title="Distribution of nodes"> - <WorldMap loading={false} countryData={countryData} /> - <Box sx={{ marginTop: 2 }} /> - <TableToolbar - onChangeSearch={handleSearch} - onChangePageSize={handlePageSize} - pageSize={pageSize} - searchTerm={searchTerm} - /> - <UniversalDataGrid - pagination - loading={countryData?.isLoading} - columns={columns} - rows={formattedCountries} - pageSize={pageSize} - /> - </ContentCard> - </Grid> - </Grid> - </Grid> - </Grid> - </Box> - ); - } - - if (countryData?.error) { - return <Alert severity="error">{countryData.error.message}</Alert>; - } - - return null; -}; diff --git a/explorer/src/pages/Overview/index.tsx b/explorer/src/pages/Overview/index.tsx deleted file mode 100644 index 9bc2ebade7a..00000000000 --- a/explorer/src/pages/Overview/index.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import * as React from 'react'; -import { Box, Grid, Link, Typography } from '@mui/material'; -import OpenInNewIcon from '@mui/icons-material/OpenInNew'; -import { useTheme } from '@mui/material/styles'; -import { useNavigate } from 'react-router-dom'; -import { PeopleAlt } from '@mui/icons-material'; -import { WorldMap } from '../../components/WorldMap'; -import { useMainContext } from '../../context/main'; -import { formatNumber } from '../../utils'; -import { BIG_DIPPER } from '../../api/constants'; -import { ValidatorsSVG } from '../../icons/ValidatorsSVG'; -import { GatewaysSVG } from '../../icons/GatewaysSVG'; -import { MixnodesSVG } from '../../icons/MixnodesSVG'; -import { Title } from '../../components/Title'; -import { ContentCard } from '../../components/ContentCard'; -import { StatsCard } from '../../components/StatsCard'; -import { Icons } from '../../components/Icons'; - -export const PageOverview: FCWithChildren = () => { - const theme = useTheme(); - const navigate = useNavigate(); - const { summaryOverview, gateways, validators, block, countryData, serviceProviders } = useMainContext(); - return ( - <Box component="main" sx={{ flexGrow: 1 }}> - <Grid> - <Grid item paddingBottom={3}> - <Title text="Overview" /> - </Grid> - <Grid item> - <Grid container spacing={3}> - {summaryOverview && ( - <> - <Grid item xs={12} md={4}> - <StatsCard - onClick={() => navigate('/network-components/mixnodes')} - title="Mixnodes" - icon={<MixnodesSVG />} - count={summaryOverview.data?.mixnodes.count || ''} - errorMsg={summaryOverview?.error} - /> - </Grid> - <Grid item xs={12} md={4}> - <StatsCard - onClick={() => navigate('/network-components/mixnodes/active')} - title="Active nodes" - icon={<Icons.Mixnodes.Status.Active />} - color={theme.palette.nym.networkExplorer.mixnodes.status.active} - count={summaryOverview.data?.mixnodes.activeset.active} - errorMsg={summaryOverview?.error} - /> - </Grid> - <Grid item xs={12} md={4}> - <StatsCard - onClick={() => navigate('/network-components/mixnodes/standby')} - title="Standby nodes" - color={theme.palette.nym.networkExplorer.mixnodes.status.standby} - icon={<Icons.Mixnodes.Status.Standby />} - count={summaryOverview.data?.mixnodes.activeset.standby} - errorMsg={summaryOverview?.error} - /> - </Grid> - </> - )} - {gateways && ( - <Grid item xs={12} md={4}> - <StatsCard - onClick={() => navigate('/network-components/gateways')} - title="Gateways" - count={gateways?.data?.length || ''} - errorMsg={gateways?.error} - icon={<GatewaysSVG />} - /> - </Grid> - )} - {serviceProviders && ( - <Grid item xs={12} md={4}> - <StatsCard - onClick={() => navigate('/network-components/service-providers')} - title="Service providers" - icon={<PeopleAlt />} - count={serviceProviders.data?.length} - errorMsg={summaryOverview?.error} - /> - </Grid> - )} - {validators && ( - <Grid item xs={12} md={4}> - <StatsCard - onClick={() => window.open(`${BIG_DIPPER}/validators`)} - title="Validators" - count={validators?.data?.count || ''} - errorMsg={validators?.error} - icon={<ValidatorsSVG />} - /> - </Grid> - )} - {block?.data && ( - <Grid item xs={12}> - <Link - href={`${BIG_DIPPER}/blocks`} - target="_blank" - rel="noreferrer" - underline="none" - color="inherit" - marginY={2} - paddingX={3} - paddingY={0.25} - fontSize={14} - fontWeight={600} - display="flex" - alignItems="center" - > - <Typography fontWeight="inherit" fontSize="inherit"> - Current block height is {formatNumber(block.data)} - </Typography> - <OpenInNewIcon fontWeight="inherit" fontSize="inherit" sx={{ ml: 0.5 }} /> - </Link> - </Grid> - )} - <Grid item xs={12}> - <ContentCard title="Distribution of nodes around the world"> - <WorldMap loading={false} countryData={countryData} /> - </ContentCard> - </Grid> - </Grid> - </Grid> - </Grid> - </Box> - ); -}; diff --git a/explorer/src/pages/ServiceProviders/index.tsx b/explorer/src/pages/ServiceProviders/index.tsx deleted file mode 100644 index 618aa729245..00000000000 --- a/explorer/src/pages/ServiceProviders/index.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import React from 'react'; -import { Box, Button, Card, FormControl, Grid, ListItem, Menu, SelectChangeEvent, Typography } from '@mui/material'; -import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid'; -import { TableToolbar } from '../../components/TableToolbar'; -import { Title } from '../../components/Title'; -import { UniversalDataGrid } from '../../components/Universal-DataGrid'; -import { useMainContext } from '../../context/main'; -import { CustomColumnHeading } from '../../components/CustomColumnHeading'; - -const columns: GridColDef[] = [ - { - headerName: 'Client ID', - field: 'address', - disableColumnMenu: true, - flex: 3, - }, - { - headerName: 'Type', - field: 'service_type', - disableColumnMenu: true, - flex: 1, - }, - { - headerName: 'Routing score', - field: 'routing_score', - disableColumnMenu: true, - flex: 2, - sortingOrder: ['asc', 'desc'], - sortComparator: (a?: string, b?: string) => { - if (!a) return -1; // Place undefined values at the end - if (!b) return 1; // Place undefined values at the end - - const aToNum = parseInt(a, 10); - const bToNum = parseInt(b, 10); - - if (aToNum > bToNum) return 1; - - return -1; // Sort numbers in ascending order - }, - renderCell: (params: GridRenderCellParams) => (!params.value ? '-' : params.value), - renderHeader: () => ( - <CustomColumnHeading - headingTitle="Routing score" - tooltipInfo="Routing score is only displayed for the service providers that had a successful ping within the last two hours" - /> - ), - }, -]; - -const SupportedApps = () => { - const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); - const open = Boolean(anchorEl); - const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => { - setAnchorEl(event.currentTarget); - }; - const handleClose = () => { - setAnchorEl(null); - }; - const anchorRef = React.useRef<HTMLButtonElement>(null); - - return ( - <FormControl size="small"> - <Button - ref={anchorRef} - onClick={handleClick} - size="large" - variant="outlined" - color="inherit" - sx={{ mr: 2, textTransform: 'capitalize' }} - > - Supported Apps - </Button> - <Menu anchorEl={anchorEl} open={open} onClose={handleClose}> - <ListItem>Keybase</ListItem> - <ListItem>Telegram</ListItem> - <ListItem>Electrum</ListItem> - <ListItem>Blockstream Green</ListItem> - </Menu> - </FormControl> - ); -}; - -export const ServiceProviders = () => { - const { serviceProviders } = useMainContext(); - const [pageSize, setPageSize] = React.useState('10'); - - const handleOnPageSizeChange = (event: SelectChangeEvent<string>) => { - setPageSize(event.target.value); - }; - - return ( - <> - <Box mb={2}> - <Title text="Service Providers" /> - </Box> - <Grid container> - <Grid item xs={12}> - <Card - sx={{ - padding: 2, - }} - > - {serviceProviders?.data ? ( - <> - <TableToolbar - onChangePageSize={handleOnPageSizeChange} - pageSize={pageSize} - childrenBefore={<SupportedApps />} - /> - <UniversalDataGrid - pagination - rows={serviceProviders.data} - columns={columns} - pageSize={pageSize} - initialState={{ - sorting: { - sortModel: [ - { - field: 'routing_score', - sort: 'desc', - }, - ], - }, - }} - /> - </> - ) : ( - <Typography>No service providers to display</Typography> - )} - </Card> - </Grid> - </Grid> - </> - ); -}; diff --git a/explorer/src/routes/index.tsx b/explorer/src/routes/index.tsx deleted file mode 100644 index 67ef8b46219..00000000000 --- a/explorer/src/routes/index.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react'; -import { Routes as ReactRouterRoutes, Route } from 'react-router-dom'; -import { Delegations } from '@src/pages/Delegations'; -import { PageOverview } from '../pages/Overview'; -import { PageMixnodesMap } from '../pages/MixnodesMap'; -import { Page404 } from '../pages/404'; -import { NetworkComponentsRoutes } from './network-components'; - -export const Routes: FCWithChildren = () => ( - <ReactRouterRoutes> - <Route path="/" element={<PageOverview />} /> - <Route path="/network-components/*" element={<NetworkComponentsRoutes />} /> - <Route path="/nodemap" element={<PageMixnodesMap />} /> - <Route path="/delegations" element={<Delegations />} /> - <Route path="*" element={<Page404 />} /> - </ReactRouterRoutes> -); diff --git a/explorer/src/routes/network-components.tsx b/explorer/src/routes/network-components.tsx deleted file mode 100644 index 266a75aa2f0..00000000000 --- a/explorer/src/routes/network-components.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import * as React from 'react'; -import { Routes as ReactRouterRoutes, Route, useNavigate } from 'react-router-dom'; -import { BIG_DIPPER } from '../api/constants'; -import { PageGateways } from '../pages/Gateways'; -import { PageGatewayDetail } from '../pages/GatewayDetail'; -import { PageMixnodeDetail } from '../pages/MixnodeDetail'; -import { PageMixnodes } from '../pages/Mixnodes'; -import { ServiceProviders } from '../pages/ServiceProviders'; - -const ValidatorRoute: FCWithChildren = () => { - const navigate = useNavigate(); - window.open(`${BIG_DIPPER}/validators`); - navigate(-1); - return null; -}; - -export const NetworkComponentsRoutes: FCWithChildren = () => ( - <ReactRouterRoutes> - <Route path="mixnodes/:status" element={<PageMixnodes />} /> - <Route path="mixnodes" element={<PageMixnodes />} /> - <Route path="mixnode/:id" element={<PageMixnodeDetail />} /> - <Route path="gateways" element={<PageGateways />} /> - <Route path="gateway/:id" element={<PageGatewayDetail />} /> - <Route path="validators" element={<ValidatorRoute />} /> - <Route path="service-providers" element={<ServiceProviders />} /> - </ReactRouterRoutes> -); diff --git a/explorer/src/stories/Introduction.stories.mdx b/explorer/src/stories/Introduction.stories.mdx deleted file mode 100644 index dafab13de07..00000000000 --- a/explorer/src/stories/Introduction.stories.mdx +++ /dev/null @@ -1,7 +0,0 @@ -import { Meta } from '@storybook/addon-docs'; - -<Meta title="Introduction" /> - -# Nym Network Explorer Storybook - -This is the Storybook for the Nym Network Explorer. diff --git a/explorer/src/styles.css b/explorer/src/styles.css deleted file mode 100644 index 818211cceab..00000000000 --- a/explorer/src/styles.css +++ /dev/null @@ -1,30 +0,0 @@ -/* last resort for styles that cannot be handled by Material UI and Emotion JS */ - -/* TODO - this override should take place in either -the theme declaration in index.tsx or the style prop -in <DataGrid /> */ - -.MuiDataGrid-columnSeparator { - visibility: hidden; -} - -/* TODO - this should be managed somehow in MUI DataGrid -but documentation doesnt offer a way to do it. Possibly only -included in Data Grid Pro package */ -.MuiDataGrid-header-override { - height: 55px; - min-height: 55px; -} - -/* Again, no offered way to add sx to this specific div to kill the padding -which puts it out of sync with other (sx styled) cells */ -div div.MuiDataGrid-root .MuiDataGrid-columnHeaderTitleContainer { - padding-left: 0; -} - -@media screen and (max-width: 900px) { - .MuiDrawer-paperAnchorLeft { - min-width: 100vw; - margin-top: 58px; - } -} diff --git a/explorer/src/tests/Nav.test.tsx b/explorer/src/tests/Nav.test.tsx deleted file mode 100644 index c3e5e949d03..00000000000 --- a/explorer/src/tests/Nav.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React, { render } from '@testing-library/react'; -import '@testing-library/jest-dom/extend-expect'; -import { Nav } from '../components/Nav'; - -describe('Nav', () => { - beforeEach(() => { - render(<Nav />); - }); - it('should render without exploding', () => { - const { container } = render(<Nav />); - expect(container.firstChild).toBeInTheDocument(); - }); -}); diff --git a/explorer/src/tests/WorldMap.test.tsx b/explorer/src/tests/WorldMap.test.tsx deleted file mode 100644 index 1a5b37d25d3..00000000000 --- a/explorer/src/tests/WorldMap.test.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React, { render, screen } from '@testing-library/react'; -import '@testing-library/jest-dom/extend-expect'; -import { WorldMap } from '../components/WorldMap'; - -describe('WorldMap', () => { - beforeEach(() => { - render(<WorldMap loading={false} />); - }); - it('should render without exploding', () => { - const { container } = render(<WorldMap loading={false} />); - expect(container.firstChild).toBeInTheDocument(); - }); - it('should render the expected container/child element', () => { - expect(screen.getByTestId('worldMap__container')).toBeInTheDocument(); - }); - it('should render the title', () => { - expect(screen.getByText('mix-nodes around the globe')).toBeTruthy(); - }); - it('should render the map/SVG', () => { - expect(screen.getByTestId('svg')).toBeInTheDocument(); - }); - it('should render map at correct size/dims', () => { - const expectedWidth = '1000'; - const expectedHeight = '800'; - expect(screen.getByTestId('svg')).toHaveAttribute('width', expectedWidth); - expect(screen.getByTestId('svg')).toHaveAttribute('height', expectedHeight); - }); -}); diff --git a/explorer/src/tests/todo.test.ts b/explorer/src/tests/todo.test.ts deleted file mode 100644 index 0580a22ccc5..00000000000 --- a/explorer/src/tests/todo.test.ts +++ /dev/null @@ -1,7 +0,0 @@ -describe('testing jest config', () => { - test('jest works with typescript', () => { - const foo = () => 42; - - expect(foo()).toBe(42); - }); -}); diff --git a/explorer/src/theme/index.tsx b/explorer/src/theme/index.tsx deleted file mode 100644 index 3542bd9c9ab..00000000000 --- a/explorer/src/theme/index.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import * as React from 'react'; -import { NymNetworkExplorerThemeProvider } from '@nymproject/mui-theme'; -import { useMainContext } from '../context/main'; - -export const NetworkExplorerThemeProvider: FCWithChildren = ({ children }) => { - const { mode } = useMainContext(); - return <NymNetworkExplorerThemeProvider mode={mode}>{children}</NymNetworkExplorerThemeProvider>; -}; diff --git a/explorer/src/theme/mui-theme.d.ts b/explorer/src/theme/mui-theme.d.ts deleted file mode 100644 index fc1f856f915..00000000000 --- a/explorer/src/theme/mui-theme.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* eslint-disable no-shadow,@typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-interface,import/no-extraneous-dependencies */ -import { Theme, ThemeOptions, Palette, PaletteOptions } from '@mui/material/styles'; -import { NymTheme, NymPaletteWithExtensions, NymPaletteWithExtensionsOptions } from '@nymproject/mui-theme'; - -/** - * If you are unfamiliar with Material UI theming, please read the following first: - * - https://mui.com/customization/theming/ - * - https://mui.com/customization/palette/ - * - https://mui.com/customization/dark-mode/#dark-mode-with-custom-palette - * - * This file adds typings to the theme using Typescript's module augmentation. - * - * Read the following if you are unfamiliar with module augmentation and declaration merging. Then - * look at the recommendations from Material UI docs for implementation: - * - https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation - * - https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces - * - https://mui.com/customization/palette/#adding-new-colors - * - * - * IMPORTANT: - * - * The type augmentation must match MUI's definitions. So, notice the use of `interface` rather than - * `type Foo = { ... }` - this is necessary to merge the definitions. - */ - -declare module '@mui/material/styles' { - /** - * This augments the definitions of the MUI Theme with the Nym theme, as well as - * a partial `ThemeOptions` type used by `createTheme` - * - * IMPORTANT: only add extensions to the interfaces above, do not modify the lines below - */ - interface Theme extends NymTheme {} - interface ThemeOptions extends Partial<NymTheme> {} - interface Palette extends NymPaletteWithExtensions {} - interface PaletteOptions extends NymPaletteWithExtensionsOptions {} -} diff --git a/explorer/src/typeDefs/explorer-api.ts b/explorer/src/typeDefs/explorer-api.ts deleted file mode 100644 index 9319c33952e..00000000000 --- a/explorer/src/typeDefs/explorer-api.ts +++ /dev/null @@ -1,277 +0,0 @@ -/* eslint-disable camelcase */ - -export interface ClientConfig { - url: string; - version: string; -} - -export interface SummaryOverviewResponse { - mixnodes: { - count: number; - activeset: { - active: number; - standby: number; - inactive: number; - }; - }; - gateways: { - count: number; - }; - validators: { - count: number; - }; -} - -export interface MixNode { - host: string; - mix_port: number; - http_api_port: number; - verloc_port: number; - sphinx_key: string; - identity_key: string; - version: string; - location: string; -} - -export interface Gateway { - host: string; - mix_port: number; - clients_port: number; - location: string; - sphinx_key: string; - identity_key: string; - version: string; -} - -export interface Amount { - denom: string; - amount: number; -} - -export enum MixnodeStatus { - active = 'active', // in both the active set and the rewarded set - standby = 'standby', // only in the rewarded set - inactive = 'inactive', // in neither the rewarded set nor the active set -} - -export enum MixnodeStatusWithAll { - active = 'active', // in both the active set and the rewarded set - standby = 'standby', // only in the rewarded set - inactive = 'inactive', // in neither the rewarded set nor the active set - all = 'all', // any status -} - -export const toMixnodeStatus = (status?: MixnodeStatusWithAll): MixnodeStatus | undefined => { - if (!status || status === MixnodeStatusWithAll.all) { - return undefined; - } - return status as unknown as MixnodeStatus; -}; - -export interface MixNodeResponseItem { - mix_id: number; - pledge_amount: Amount; - total_delegation: Amount; - owner: string; - layer: string; - status: MixnodeStatus; - location: { - country_name: string; - latitude?: number; - longitude?: number; - three_letter_iso_country_code: string; - two_letter_iso_country_code: string; - }; - mix_node: MixNode; - avg_uptime: number; - node_performance: NodePerformance; - stake_saturation: number; - uncapped_saturation: number; - operating_cost: Amount; - profit_margin_percent: string; - blacklisted: boolean; -} - -export type MixNodeResponse = MixNodeResponseItem[]; - -export interface MixNodeReportResponse { - identity: string; - owner: string; - most_recent_ipv4: boolean; - most_recent_ipv6: boolean; - last_hour_ipv4: number; - last_hour_ipv6: number; - last_day_ipv4: number; - last_day_ipv6: number; -} - -export interface StatsResponse { - update_time: Date; - previous_update_time: Date; - packets_received_since_startup: number; - packets_sent_since_startup: number; - packets_explicitly_dropped_since_startup: number; - packets_received_since_last_update: number; - packets_sent_since_last_update: number; - packets_explicitly_dropped_since_last_update: number; -} - -export interface NodePerformance { - most_recent: string; - last_hour: string; - last_24h: string; -} - -export type MixNodeHistoryResponse = StatsResponse; - -export interface GatewayBond { - block_height: number; - pledge_amount: Amount; - total_delegation: Amount; - owner: string; - gateway: Gateway; - node_performance: NodePerformance; - location?: Location; -} - -export interface GatewayBondAnnotated { - gateway_bond: GatewayBond; - node_performance: NodePerformance; -} - -export interface Location { - two_letter_iso_country_code: string; - three_letter_iso_country_code: string; - country_name: string; - latitude?: number; - longitude?: number; -} - -export interface LocatedGateway { - pledge_amount: Amount; - owner: string; - block_height: number; - gateway: Gateway; - proxy?: string; - location?: Location; -} - -export type GatewayResponse = GatewayBond[]; - -export interface GatewayReportResponse { - identity: string; - owner: string; - most_recent: number; - last_hour: number; - last_day: number; -} - -export type GatewayHistoryResponse = StatsResponse; - -export interface MixNodeDescriptionResponse { - name: string; - description: string; - link: string; - location: string; -} - -export type MixNodeStatsResponse = StatsResponse; - -export interface Validator { - address: string; - proposer_priority: string; - pub_key: { - type: string; - value: string; - }; -} -export interface ValidatorsResponse { - block_height: number; - count: string; - total: string; - validators: Validator[]; -} - -export type CountryData = { - ISO3: string; - nodes: number; -}; - -export type Delegation = { - owner: string; - amount: Amount; - block_height: number; -}; - -export type DelegationUniq = { - owner: string; - amount: Amount; -}; - -export type DelegationsResponse = Delegation[]; - -export type UniqDelegationsResponse = DelegationUniq[]; - -export interface CountryDataResponse { - [threeLetterCountryCode: string]: CountryData; -} - -export type BlockType = number; -export type BlockResponse = BlockType; - -export interface ApiState<RESPONSE> { - isLoading: boolean; - data?: RESPONSE; - error?: Error; -} - -export type StatusResponse = { - pending: boolean; - ports: { - 1789: boolean; - 1790: boolean; - 8000: boolean; - }; -}; - -export type UptimeTime = { - date: string; - uptime: number; -}; - -export type UptimeStoryResponse = { - history: UptimeTime[]; - identity: string; - owner: string; -}; - -export type MixNodeEconomicDynamicsStatsResponse = { - stake_saturation: number; - uncapped_saturation: number; - // TODO: when v2 will be deployed, remove cases: VeryHigh, Moderate and VeryLow - active_set_inclusion_probability: 'High' | 'Good' | 'Low'; - reserve_set_inclusion_probability: 'High' | 'Good' | 'Low'; - estimated_total_node_reward: number; - estimated_operator_reward: number; - estimated_delegators_reward: number; - current_interval_uptime: number; -}; - -export type Environment = 'mainnet' | 'sandbox' | 'qa'; - -export type ServiceProviderType = 'Network Requester'; - -export type DirectoryServiceProvider = { - id: string; - description: string; - address: string; - gateway: string; - routing_score: string | null; - service_type: ServiceProviderType; -}; - -export type DirectoryService = { - id: string; - description: string; - items: DirectoryServiceProvider[]; -}; diff --git a/explorer/src/typeDefs/filters.ts b/explorer/src/typeDefs/filters.ts deleted file mode 100644 index 53de60cb87a..00000000000 --- a/explorer/src/typeDefs/filters.ts +++ /dev/null @@ -1,22 +0,0 @@ -// eslint-disable-next-line import/no-extraneous-dependencies -import { Mark } from '@mui/base'; - -export enum EnumFilterKey { - profitMargin = 'profitMargin', - stakeSaturation = 'stakeSaturation', - routingScore = 'routingScore', -} - -export type TFilterItem = { - label: string; - id: EnumFilterKey; - value: number[]; - isSmooth?: boolean; - marks: Mark[]; - min?: number; - max?: number; - scale?: (value: number) => number; - tooltipInfo?: string; -}; - -export type TFilters = { [key in EnumFilterKey]: TFilterItem }; diff --git a/explorer/src/typeDefs/network.ts b/explorer/src/typeDefs/network.ts deleted file mode 100644 index f8615cd9928..00000000000 --- a/explorer/src/typeDefs/network.ts +++ /dev/null @@ -1 +0,0 @@ -export type Network = 'QA' | 'SANDBOX' | 'MAINNET'; diff --git a/explorer/src/typeDefs/tables.ts b/explorer/src/typeDefs/tables.ts deleted file mode 100644 index 1ab2ffead48..00000000000 --- a/explorer/src/typeDefs/tables.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type TableHeading = { - id: string; - numeric: boolean; - disablePadding: boolean; - label: string; -}; - -export type TableHeadingsType = TableHeading[]; diff --git a/explorer/src/typings/FC.d.ts b/explorer/src/typings/FC.d.ts deleted file mode 100644 index 08ebdfa298a..00000000000 --- a/explorer/src/typings/FC.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare type FCWithChildren<P = {}> = React.FC<React.PropsWithChildren<P>>; diff --git a/explorer/src/typings/jpeg.d.ts b/explorer/src/typings/jpeg.d.ts deleted file mode 100644 index af2ed729133..00000000000 --- a/explorer/src/typings/jpeg.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -declare module '*.jpeg' { - const value: any; - export default value; -} - -declare module '*.jpg' { - const value: any; - export default value; -} diff --git a/explorer/src/typings/json.d.ts b/explorer/src/typings/json.d.ts deleted file mode 100644 index b72dd46ee5d..00000000000 --- a/explorer/src/typings/json.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.json' { - const content: any; - export default content; -} diff --git a/explorer/src/typings/png.d.ts b/explorer/src/typings/png.d.ts deleted file mode 100644 index dd84df40a48..00000000000 --- a/explorer/src/typings/png.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.png' { - const content: any; - export default content; -} diff --git a/explorer/src/typings/react-identicons.d.ts b/explorer/src/typings/react-identicons.d.ts deleted file mode 100644 index 6c460eff998..00000000000 --- a/explorer/src/typings/react-identicons.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -declare module 'react-identicons' { - import * as React from 'react'; - - interface IdenticonProps { - string: string; - size?: number; - padding?: number; - bg?: string; - fg?: string; - palette?: string[]; - count?: number; - // getColor: Function; - } - - declare function Identicon(props: IdenticonProps): React.ReactElement<IdenticonProps>; - - export default Identicon; -} diff --git a/explorer/src/typings/react-tooltip.d.ts b/explorer/src/typings/react-tooltip.d.ts deleted file mode 100644 index 98cb6d592d2..00000000000 --- a/explorer/src/typings/react-tooltip.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'react-tooltip'; diff --git a/explorer/src/typings/svg.d.ts b/explorer/src/typings/svg.d.ts deleted file mode 100644 index 091d25e2101..00000000000 --- a/explorer/src/typings/svg.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.svg' { - const content: any; - export default content; -} diff --git a/explorer/src/utils/currency.ts b/explorer/src/utils/currency.ts deleted file mode 100644 index ad6ed1f1656..00000000000 --- a/explorer/src/utils/currency.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { printableCoin } from '@nymproject/nym-validator-client'; -import Big from 'big.js'; -import { DecCoin, isValidRawCoin } from '@nymproject/types'; - -const DENOM = process.env.CURRENCY_DENOM || 'unym'; -const DENOM_STAKING = process.env.CURRENCY_STAKING_DENOM || 'unyx'; - -export const toDisplay = (val: string | number | Big, dp = 4) => { - let displayValue; - try { - displayValue = Big(val).toFixed(dp); - } catch (e: any) { - console.warn(`${displayValue} not a valid decimal number: ${e}`); - } - return displayValue; -}; - -export const currencyToString = ({ amount, dp, denom = DENOM }: { amount: string; dp?: number; denom?: string }) => { - if (!dp) { - printableCoin({ - amount, - denom, - }); - } - - const [printableAmount, printableDenom] = printableCoin({ - amount, - denom, - }).split(/\s+/); - - return `${toDisplay(printableAmount, dp)} ${printableDenom}`; -}; - -export const stakingCurrencyToString = (amount: string, denom: string = DENOM_STAKING) => - printableCoin({ - amount, - denom, - }); - -/** - * Converts a decimal number to a pretty representation - * with fixed decimal places. - * - * @param val - a decimal number of string form - * @param dp - number of decimal places (4 by default ie. 0.0000) - * @returns A prettyfied decimal number - */ - -/** - * Converts a decimal number of μNYM (micro NYM) to NYM. - * - * @param unym - a decimal number of μNYM - * @param dp - number of decimal places (4 by default ie. 0.0000) - * @returns The corresponding decimal number in NYM - */ -export const unymToNym = (unym: string | number | Big, dp = 4) => { - let nym; - try { - nym = Big(unym).div(1_000_000).toFixed(dp); - } catch (e: any) { - console.warn(`${unym} not a valid decimal number: ${e}`); - } - return nym; -}; - -export const validateAmount = async ( - majorAmountAsString: DecCoin['amount'], - minimumAmountAsString: DecCoin['amount'], -): Promise<boolean> => { - // tests basic coin value requirements, like no more than 6 decimal places, value lower than total supply, etc - if (!Number(majorAmountAsString)) { - return false; - } - - if (!isValidRawCoin(majorAmountAsString)) { - return false; - } - - const majorValueFloat = parseInt(majorAmountAsString, Number(10)); - - return majorValueFloat >= parseInt(minimumAmountAsString, Number(10)); -}; - -/** - * Takes a DecCoin and prettify its amount to a representation - * with fixed decimal places. - * - * @param coin - a DecCoin - * @param dp - number of decimal places to apply to amount (4 by default ie. 0.0000) - * @returns A DecCoin with prettified amount - */ -export const decCoinToDisplay = (coin: DecCoin, dp = 4) => { - const displayCoin = { ...coin }; - try { - displayCoin.amount = Big(coin.amount).toFixed(dp); - } catch (e: any) { - console.warn(`${coin.amount} not a valid decimal number: ${e}`); - } - return displayCoin; -}; diff --git a/explorer/src/utils/index.ts b/explorer/src/utils/index.ts deleted file mode 100644 index 91b082c5cac..00000000000 --- a/explorer/src/utils/index.ts +++ /dev/null @@ -1,123 +0,0 @@ -/* eslint-disable camelcase */ -import { MutableRefObject } from 'react'; -import { Theme } from '@mui/material/styles'; -import { registerLocale, getName } from 'i18n-iso-countries'; -import Big from 'big.js'; -import { CountryData } from '../typeDefs/explorer-api'; -import { EconomicsRowsType } from '../components/MixNodes/Economics/types'; -import { Network } from '../typeDefs/network'; - -registerLocale(require('i18n-iso-countries/langs/en.json')); - -export function formatNumber(num: number): string { - return new Intl.NumberFormat().format(num); -} - -export function scrollToRef(ref: MutableRefObject<HTMLDivElement | undefined>): void { - if (ref?.current) ref.current.scrollIntoView(); -} - -export type CountryDataRowType = { - id: number; - ISO3: string; - nodes: number; - countryName: string; - percentage: string; -}; - -export function countryDataToGridRow(countriesData: CountryData[]): CountryDataRowType[] { - const totalNodes = countriesData.reduce((acc, obj) => acc + obj.nodes, 0); - const formatted = countriesData.map((each: CountryData, index: number) => { - const updatedCountryRecord: CountryDataRowType = { - ...each, - id: index, - countryName: getName(each.ISO3, 'en', { select: 'alias' }), - percentage: ((each.nodes * 100) / totalNodes).toFixed(1), - }; - return updatedCountryRecord; - }); - - const sorted = formatted.sort((a, b) => (a.nodes < b.nodes ? 1 : -1)); - return sorted; -} - -export const splice = (start: number, deleteCount: number, address?: string): string => { - if (address) { - const array = address.split(''); - array.splice(start, deleteCount, '...'); - return array.join(''); - } - return ''; -}; - -export const trimAddress = (address = '', trimBy = 6) => `${address.slice(0, trimBy)}...${address.slice(-trimBy)}`; - -/** - * Converts a stringified percentage float (0.0-1.0) to a stringified integer (0-100). - * - * @param value - the percentage to convert - * @returns A stringified integer - */ -export const toPercentIntegerString = (value: string) => Math.round(Number(value) * 100).toString(); -export const toPercentInteger = (value: string) => Math.round(Number(value) * 100); - -export const textColour = (value: EconomicsRowsType, field: string, theme: Theme) => { - const progressBarValue = value?.progressBarValue || 0; - const fieldValue = value.value; - - if (progressBarValue > 100) { - return theme.palette.warning.main; - } - if (field === 'selectionChance') { - // TODO: when v2 will be deployed, remove cases: VeryHigh, Moderate and VeryLow - switch (fieldValue) { - case 'High': - case 'VeryHigh': - return theme.palette.nym.networkExplorer.selectionChance.overModerate; - case 'Good': - case 'Moderate': - return theme.palette.nym.networkExplorer.selectionChance.moderate; - case 'Low': - case 'VeryLow': - return theme.palette.nym.networkExplorer.selectionChance.underModerate; - default: - return theme.palette.nym.wallet.fee; - } - } - return theme.palette.nym.wallet.fee; -}; - -export const isGreaterThan = (a: number, b: number) => a > b; - -export const isLessThan = (a: number, b: number) => a < b; - -/** - * - * Checks if the user's balance is enough to pay the fee - * @param balance - The user's current balance - * @param fee - The fee for the tx - * @param tx - The amount of the tx - * @returns boolean - * - */ - -export const isBalanceEnough = (fee: string, tx: string = '0', balance: string = '0') => { - try { - return Big(balance).gte(Big(fee).plus(Big(tx))); - } catch (e) { - console.log(e); - return false; - } -}; - -export const urls = (networkName?: Network) => - networkName === 'MAINNET' - ? { - mixnetExplorer: 'https://mixnet.explorers.guru/', - blockExplorer: 'https://blocks.nymtech.net', - networkExplorer: 'https://explorer.nymtech.net', - } - : { - blockExplorer: `https://${networkName}-blocks.nymtech.net`, - networkExplorer: `https://${networkName}-explorer.nymtech.net`, - }; diff --git a/explorer/src/x-data-grid/LICENSE b/explorer/src/x-data-grid/LICENSE deleted file mode 100644 index 126bc57eaa2..00000000000 --- a/explorer/src/x-data-grid/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 Material-UI SAS - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/explorer/src/x-data-grid/README.md b/explorer/src/x-data-grid/README.md deleted file mode 100644 index c163d7ceeb1..00000000000 --- a/explorer/src/x-data-grid/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# @mui/x-data-grid - -This package is the community edition of the data grid component. -It's part of Material-UI X, an open core extension of Material-UI, with advanced components. - -## Installation - -Install the package in your project directory with: - -```sh -// with npm -npm install @mui/x-data-grid - -// with yarn -yarn add @mui/x-data-grid -``` - -This component has two peer dependencies that you will need to install as well. - -```json -"peerDependencies": { - "@material-ui/core": "^4.12.0 || ^5.0.0-beta.0", - "react": "^17.0.0" -}, -``` - -## Documentation - -[The documentation](https://material-ui.com/components/data-grid/) diff --git a/explorer/src/x-data-grid/package.json b/explorer/src/x-data-grid/package.json deleted file mode 100644 index 46225fa760c..00000000000 --- a/explorer/src/x-data-grid/package.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "_from": "@mui/x-data-grid", - "_id": "@mui/x-data-grid@4.0.0", - "_inBundle": false, - "_integrity": "sha512-BYn7uLx5tJbMarcWltjjVArWNBdC22/2xOpq3Azhltbb3TRx3h2RLUeKwZI685xmGHmzvtu6QqaoYqQgFe/h+g==", - "_location": "/@mui/x-data-grid", - "_phantomChildren": {}, - "_requested": { - "type": "tag", - "registry": true, - "raw": "@mui/x-data-grid", - "name": "@mui/x-data-grid", - "escapedName": "@mui%2fx-data-grid", - "scope": "@mui", - "rawSpec": "", - "saveSpec": null, - "fetchSpec": "latest" - }, - "_requiredBy": [ - "#USER", - "/" - ], - "_resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-4.0.0.tgz", - "_shasum": "e9e9c33a8b86e85872c48f30f4a8de72ee819153", - "_spec": "@mui/x-data-grid", - "_where": "/Users/adrianthompson/Documents/nym/explorer", - "author": { - "name": "MUI Team" - }, - "bugs": { - "url": "https://github.com/mui-org/material-ui-x/issues" - }, - "bundleDependencies": false, - "dependencies": { - "@material-ui/utils": "^5.0.0-beta.4", - "clsx": "^1.1.1", - "prop-types": "^15.7.2", - "reselect": "^4.0.0" - }, - "deprecated": false, - "description": "The community edition of the data grid component (Material-UI X).", - "engines": { - "node": ">=12.0.0" - }, - "files": [ - "dist/*" - ], - "gitHead": "940d6238fe499f027ee27e818d714f79ca40e9a5", - "homepage": "https://material-ui.com/components/data-grid/", - "keywords": [ - "react", - "react-component", - "material-ui", - "mui", - "react-table", - "table", - "datatable", - "data-table", - "datagrid", - "data-grid" - ], - "license": "MIT", - "main": "dist/index-cjs.js", - "module": "dist/index-esm.js", - "name": "@mui/x-data-grid", - "peerDependencies": { - "@material-ui/core": "^4.12.0 || ^5.0.0-beta.0", - "@mui/styles": "^4.11.4 || ^5.0.0-beta.0", - "react": "^17.0.0" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/mui-org/material-ui-x.git", - "directory": "packages/grid/data-grid" - }, - "scripts": { - "build": "cd ../ && rollup --config rollup.data-grid.config.js", - "typescript": "tsc -p tsconfig.json" - }, - "setupFiles": [ - "<rootDir>/src/setupTests.js" - ], - "sideEffects": false, - "types": "dist/data-grid.d.ts", - "version": "4.0.0" -} \ No newline at end of file diff --git a/explorer/tsconfig.json b/explorer/tsconfig.json deleted file mode 100644 index 093340052dd..00000000000 --- a/explorer/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "../ts-packages/tsconfig.json", - "compilerOptions": { - "jsx": "react-jsx", - "outDir": "./dist", - "module": "CommonJS", - "baseUrl": ".", - "paths": { - "@src/*": ["./src/*"], - "@assets/*": ["../assets/*"] - } - }, - "include": ["./src/**/*.ts", "./src/**/*.tsx"], - "exclude": ["node_modules", "build", "dist"] -} diff --git a/explorer/webpack.common.js b/explorer/webpack.common.js deleted file mode 100644 index 7bb9cb9032b..00000000000 --- a/explorer/webpack.common.js +++ /dev/null @@ -1,32 +0,0 @@ -const path = require('path'); -const { mergeWithRules } = require('webpack-merge'); -const { webpackCommon } = require('@nymproject/webpack'); - -module.exports = mergeWithRules({ - module: { - rules: { - test: 'match', - use: 'replace', - }, - }, -})(webpackCommon(__dirname), { - entry: path.resolve(__dirname, 'src/index.tsx'), - output: { - path: path.resolve(__dirname, 'dist'), - publicPath: '/', - }, - resolve: { - fallback: { - fs: false, - tls: false, - path: false, - http: false, - https: false, - stream: false, - crypto: false, - net: false, - zlib: false, - buffer: require.resolve('buffer'), - }, - }, -}); diff --git a/explorer/webpack.config.js b/explorer/webpack.config.js deleted file mode 100644 index 550951cb528..00000000000 --- a/explorer/webpack.config.js +++ /dev/null @@ -1,76 +0,0 @@ -const { mergeWithRules } = require('webpack-merge'); -const webpack = require('webpack'); -const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); -const ReactRefreshTypeScript = require('react-refresh-typescript'); -const commonConfig = require('./webpack.common'); - -module.exports = mergeWithRules({ - module: { - rules: { - test: 'match', - use: 'replace', - }, - }, -})(commonConfig, { - mode: 'development', - devtool: 'inline-source-map', - module: { - rules: [ - { - test: /\.m?js/, - resolve: { - fullySpecified: false, - }, - }, - { - test: /\.tsx?$/, - use: 'ts-loader', - exclude: /node_modules/, - options: { - getCustomTransformers: () => ({ - before: [ReactRefreshTypeScript()], - }), - // `ts-loader` does not work with HMR unless `transpileOnly` is used. - // If you need type checking, `ForkTsCheckerWebpackPlugin` is an alternative. - transpileOnly: true, - }, - }, - ], - }, - plugins: [ - new ReactRefreshWebpackPlugin(), - - // this can be included automatically by the dev server, however build mode fails if missing - new webpack.HotModuleReplacementPlugin(), - new webpack.ProvidePlugin({ - Buffer: ['buffer', 'Buffer'], - }), - ], - - target: 'web', - - devServer: { - headers: { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS', - 'Access-Control-Allow-Headers': 'Content-Type, Authorization', - }, - historyApiFallback: true, - }, - - // recommended for faster rebuild - optimization: { - runtimeChunk: true, - removeAvailableModules: false, - removeEmptyChunks: false, - splitChunks: false, - }, - - cache: { - type: 'filesystem', - buildDependencies: { - // restart on config change - config: ['./webpack.config.js'], - }, - }, -}); diff --git a/explorer/webpack.prod.js b/explorer/webpack.prod.js deleted file mode 100644 index 259c32a4af9..00000000000 --- a/explorer/webpack.prod.js +++ /dev/null @@ -1,52 +0,0 @@ -const webpack = require('webpack'); -const { mergeWithRules } = require('webpack-merge'); -const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); -const commonConfig = require('./webpack.common'); - -module.exports = mergeWithRules({ - module: { - rules: { - test: 'match', - use: 'replace', - }, - }, -})(commonConfig, { - mode: 'production', - - // TODO: no source maps, add back - devtool: false, - - module: { - rules: [ - { - test: /\.m?js/, - resolve: { - fullySpecified: false, - }, - }, - { - test: /\.css$/, - use: [MiniCssExtractPlugin.loader, 'css-loader'], - }, - ], - }, - optimization: { - minimizer: [`...`, new CssMinimizerPlugin()], - splitChunks: { - chunks: 'all', - }, - }, - plugins: [ - new MiniCssExtractPlugin({ - filename: '[name].[contenthash].css', - }), - new webpack.ProvidePlugin({ - Buffer: ['buffer', 'Buffer'], - }), - ], - output: { - pathinfo: false, - filename: '[name].[contenthash].js', - }, -}); diff --git a/nym-node-status-api/nym-node-status-api/src/cli/mod.rs b/nym-node-status-api/nym-node-status-api/src/cli/mod.rs index e9d76a1f755..0a487afe860 100644 --- a/nym-node-status-api/nym-node-status-api/src/cli/mod.rs +++ b/nym-node-status-api/nym-node-status-api/src/cli/mod.rs @@ -16,10 +16,6 @@ pub(crate) struct Cli { #[clap(long, env = "NETWORK_NAME")] pub(crate) network_name: String, - /// Explorer api url. - #[clap(short, long, env = "EXPLORER_API")] - pub(crate) explorer_api: String, - /// Nym api url. #[clap(short, long, env = "NYM_API")] pub(crate) nym_api: String, diff --git a/nym-wallet/nym-wallet-types/src/network/qa.rs b/nym-wallet/nym-wallet-types/src/network/qa.rs index 761d08f6145..8f1fe1277a7 100644 --- a/nym-wallet/nym-wallet-types/src/network/qa.rs +++ b/nym-wallet/nym-wallet-types/src/network/qa.rs @@ -34,8 +34,6 @@ pub(crate) fn validators() -> Vec<ValidatorDetails> { )] } -pub(crate) const EXPLORER_API: &str = "https://qa-network-explorer.qa.nymte.ch/api/"; - pub(crate) fn network_details() -> nym_network_defaults::NymNetworkDetails { nym_network_defaults::NymNetworkDetails { network_name: NETWORK_NAME.into(), @@ -53,7 +51,6 @@ pub(crate) fn network_details() -> nym_network_defaults::NymNetworkDetails { multisig_contract_address: parse_optional_str(MULTISIG_CONTRACT_ADDRESS), coconut_dkg_contract_address: parse_optional_str(COCONUT_DKG_CONTRACT_ADDRESS), }, - explorer_api: parse_optional_str(EXPLORER_API), nym_vpn_api_url: None, } } diff --git a/nym-wallet/nym-wallet-types/src/network/sandbox.rs b/nym-wallet/nym-wallet-types/src/network/sandbox.rs index c436c9f09e1..cae0140cf84 100644 --- a/nym-wallet/nym-wallet-types/src/network/sandbox.rs +++ b/nym-wallet/nym-wallet-types/src/network/sandbox.rs @@ -34,8 +34,6 @@ pub(crate) fn validators() -> Vec<ValidatorDetails> { )] } -pub(crate) const EXPLORER_API: &str = "https://sandbox-explorer.nymtech.net/api/"; - pub(crate) fn network_details() -> nym_network_defaults::NymNetworkDetails { nym_network_defaults::NymNetworkDetails { network_name: NETWORK_NAME.into(), @@ -53,7 +51,6 @@ pub(crate) fn network_details() -> nym_network_defaults::NymNetworkDetails { multisig_contract_address: parse_optional_str(MULTISIG_CONTRACT_ADDRESS), coconut_dkg_contract_address: parse_optional_str(COCONUT_DKG_CONTRACT_ADDRESS), }, - explorer_api: parse_optional_str(EXPLORER_API), nym_vpn_api_url: None, } } diff --git a/tools/internal/testnet-manager/src/manager/network.rs b/tools/internal/testnet-manager/src/manager/network.rs index 6c65eda06cb..4615be274c1 100644 --- a/tools/internal/testnet-manager/src/manager/network.rs +++ b/tools/internal/testnet-manager/src/manager/network.rs @@ -81,7 +81,6 @@ impl<'a> From<&'a LoadedNetwork> for nym_config::defaults::NymNetworkDetails { api_url: None, }], contracts, - explorer_api: None, nym_vpn_api_url: None, } } diff --git a/tools/internal/testnet-manager/src/manager/network_init.rs b/tools/internal/testnet-manager/src/manager/network_init.rs index 8e978e4fc6a..ec7bf8992ab 100644 --- a/tools/internal/testnet-manager/src/manager/network_init.rs +++ b/tools/internal/testnet-manager/src/manager/network_init.rs @@ -38,7 +38,6 @@ impl InitCtx { network_name: "foomp".to_string(), // does this matter? endpoints: vec![], contracts: Default::default(), - explorer_api: None, nym_vpn_api_url: None, }; Ok(Config::try_from_nym_network_details(&network_details)?)