diff --git a/assets/icons.json b/assets/icons.json index 93d7aa61..9c18c3c5 100644 --- a/assets/icons.json +++ b/assets/icons.json @@ -202,6 +202,8 @@ "bar-chart": "M3,22V8H7V22H3M10,22V2H14V22H10M17,22V14H21V22H17Z", "gantt-chart": "M2,5H10V2H12V22H10V18H6V15H10V13H4V10H10V8H2V5M14,5H17V8H14V5M14,10H19V13H14V10M14,15H22V18H14V15Z", "crown": "M5 16L3 5L8.5 10L12 4L15.5 10L21 5L19 16H5M19 19C19 19.6 18.6 20 18 20H6C5.4 20 5 19.6 5 19V18H19V19Z", + "earth": "M17.9,17.39C17.64,16.59 16.89,16 16,16H15V13A1,1 0 0,0 14,12H8V10H10A1,1 0 0,0 11,9V7H13A2,2 0 0,0 15,5V4.59C17.93,5.77 20,8.64 20,12C20,14.08 19.2,15.97 17.9,17.39M11,19.93C7.05,19.44 4,16.08 4,12C4,11.38 4.08,10.78 4.21,10.21L9,15V16A2,2 0 0,0 11,18M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z", + "city": "M15,23H13V21H15V23M19,21H17V23H19V21M15,17H13V19H15V17M7,21H5V23H7V21M7,17H5V19H7V17M19,17H17V19H19V17M15,13H13V15H15V13M19,13H17V15H19V13M21,9A2,2 0 0,1 23,11V23H21V11H11V23H9V15H3V23H1V15A2,2 0 0,1 3,13H9V11A2,2 0 0,1 11,9V7A2,2 0 0,1 13,5H15V1H17V5H19A2,2 0 0,1 21,7V9M19,9V7H13V9H19Z" "drop": "M12 18C12 18.7 12.12 19.36 12.34 20C12.23 20 12.12 20 12 20C8.69 20 6 17.31 6 14C6 10 12 3.25 12 3.25S16.31 8.1 17.62 12C16.93 12.06 16.28 12.22 15.67 12.47C15 10.68 13.5 8.33 12 6.39C10 8.96 8 12.23 8 14C8 16.21 9.79 18 12 18M19 17V14H17V17H14V19H17V22H19V19H22V17H19Z", "faucet": "M21 21H3C3 19.9 3.9 19 5 19H19C20.11 19 21 19.89 21 21M19 7C19 5.39 17.93 3 15 3S11 5.39 11 7V18H13V7C13 6.54 13.17 5 15 5S17 6.54 17 7H16.5V9H19.5V7H19M7 12C6.45 12 6 12.45 6 13V14H3V15H6V18H8V13C8 12.45 7.55 12 7 12M21 14H18V13C18 12.45 17.55 12 17 12S16 12.45 16 13V18H18V15H21V14Z" } diff --git a/assets/styles/base.scss b/assets/styles/base.scss index 8151e013..4c4a465a 100644 --- a/assets/styles/base.scss +++ b/assets/styles/base.scss @@ -78,6 +78,7 @@ $grayscale: ( // --supply: #65c7f8; --supply: #1ca7ed; --staking: #85f891; + --geo-map: #8B8C8D; } [theme="dimmed"] { @@ -139,6 +140,7 @@ $grayscale: ( --block-progress-fill-background: #33a853; --logo-name: var(--txt-primary); --bar-fill: rgb(243, 147, 45); + --geo-map: #8B8C8D; } [theme="light"] { @@ -200,6 +202,7 @@ $grayscale: ( --block-progress-fill-background: #33a853; --logo-name: var(--txt-primary); --bar-fill: rgb(243, 147, 45); + --geo-map: #8B8C8D; } @font-face { diff --git a/components/LeftSidebar.vue b/components/LeftSidebar.vue index 19b8d3a5..035119e3 100644 --- a/components/LeftSidebar.vue +++ b/components/LeftSidebar.vue @@ -85,6 +85,11 @@ const mainLinks = reactive([ path: "/stats?tab=rollups", queryParam: {tab: "rollups"}, }, + { + name: "Ecosystem", + path: "/stats?tab=ecosystem", + queryParam: {tab: "ecosystem"}, + }, ], }, ]) diff --git a/components/modules/stats/BarplotChartCard.vue b/components/modules/stats/BarplotChartCard.vue new file mode 100644 index 00000000..7da2f42b --- /dev/null +++ b/components/modules/stats/BarplotChartCard.vue @@ -0,0 +1,290 @@ + + + + + + {{ `By ${series.title}` }} + + + + + + + Amount: + {{ tooltip.amount }} + + + + + + + + + + diff --git a/components/modules/stats/GeoMap.vue b/components/modules/stats/GeoMap.vue new file mode 100644 index 00000000..e5635186 --- /dev/null +++ b/components/modules/stats/GeoMap.vue @@ -0,0 +1,632 @@ + + + + + + + + + + + + + + + + + Somewhere in.. + + means that it was not possible to determine the exact location. + + + + + + + + + + + + + + + Loading map.. + + + + + diff --git a/components/modules/stats/InsightCard.vue b/components/modules/stats/InsightCard.vue index 1108a0b5..277e205e 100644 --- a/components/modules/stats/InsightCard.vue +++ b/components/modules/stats/InsightCard.vue @@ -10,7 +10,7 @@ import DiffChip from "@/components/modules/stats/DiffChip.vue" import { abbreviate, capitilize, comma, formatBytes, shareOfTotal, shareOfTotalString } from "@/services/utils" /** API */ -import { fetch24hDiffs, fetchSummary } from "@/services/api/stats" +import { fetchGeneralStats, fetchSummary } from "@/services/api/stats" const props = defineProps({ series: { @@ -67,7 +67,7 @@ const getSeries = async () => { }, ] } else { - data = await fetch24hDiffs({ name: props.series.name }) + data = await fetchGeneralStats({ name: props.series.name }) } switch (props.series.name) { diff --git a/components/modules/stats/RollupsActivityGraph.vue b/components/modules/stats/RollupsActivityGraph.vue index ad4b5b72..edb5a248 100644 --- a/components/modules/stats/RollupsActivityGraph.vue +++ b/components/modules/stats/RollupsActivityGraph.vue @@ -19,9 +19,15 @@ const metrics = ref([ - + + + No activity + + There has been no rollup activity in the last 24 hours + + \ No newline at end of file diff --git a/components/modules/stats/tabs/EcosystemTab.vue b/components/modules/stats/tabs/EcosystemTab.vue new file mode 100644 index 00000000..fe0feba9 --- /dev/null +++ b/components/modules/stats/tabs/EcosystemTab.vue @@ -0,0 +1,146 @@ + + + + + + Light Node Distribution + + + + + + + + + + + \ No newline at end of file diff --git a/components/modules/stats/tabs/GeneralTab.vue b/components/modules/stats/tabs/GeneralTab.vue index a15ba6a7..6c5508bc 100644 --- a/components/modules/stats/tabs/GeneralTab.vue +++ b/components/modules/stats/tabs/GeneralTab.vue @@ -14,7 +14,7 @@ import InsightCard from "@/components/modules/stats/InsightCard.vue" import { getInsightsByGroup, getSeriesByGroupAndType, STATS_PERIODS } from "@/services/constants/stats.js" /** API */ -import { fetch24hDiffs } from "@/services/api/stats.js" +import { fetchGeneralStats } from "@/services/api/stats.js" /** Store */ import { useAppStore } from "@/store/app" @@ -62,7 +62,7 @@ const insights = computed(() => getInsightsByGroup('General')) const get24hDiffs = async () => { isLoading.value = true - const data = await fetch24hDiffs({ name: 'changes_24h' }) + const data = await fetchGeneralStats({ name: 'changes_24h' }) diffs24h.value = data isLoading.value = false diff --git a/components/modules/stats/tabs/RollupsTab.vue b/components/modules/stats/tabs/RollupsTab.vue index 5a8c99fa..c2c21d04 100644 --- a/components/modules/stats/tabs/RollupsTab.vue +++ b/components/modules/stats/tabs/RollupsTab.vue @@ -17,7 +17,7 @@ import Popover from "@/components/ui/Popover.vue" import { getSeriesByGroupAndType } from "@/services/constants/stats.js" /** Services */ -import { capitilize, capitalizeAndReplaceUnderscore } from "@/services/utils" +import { capitilize, capitalizeAndReplaceUnderscore, isMainnet } from "@/services/utils" /** API */ import { fetchRollups, fetchRollupsDailyStats } from "@/services/api/rollup.js" @@ -266,7 +266,7 @@ watch( - + Economics diff --git a/package.json b/package.json index 127f34db..c25ede42 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "codemirror": "^6.0.1", "crypto-js": "^4.2.0", "d3": "^7.8.5", + "d3-geo": "^3.1.1", "d3-hierarchy": "^3.1.2", "focus-trap": "7.5.2", "iconv-lite": "^0.6.3", diff --git a/pages/stats/index.vue b/pages/stats/index.vue index e37841ce..ab47e717 100644 --- a/pages/stats/index.vue +++ b/pages/stats/index.vue @@ -5,10 +5,11 @@ import Button from "@/components/ui/Button.vue" /** Stats Tabs */ import BlocksTab from "@/components/modules/stats/tabs/BlocksTab.vue" import GeneralTab from "@/components/modules/stats/tabs/GeneralTab.vue" +import EcosystemTab from "@/components/modules/stats/tabs/EcosystemTab.vue" import RollupsTab from "@/components/modules/stats/tabs/RollupsTab.vue" /** Services */ -import { capitilize } from "@/services/utils" +import { capitilize, isMainnet } from "@/services/utils" useHead({ title: "Statistics - Celestia Explorer", @@ -61,8 +62,25 @@ useHead({ const route = useRoute() const router = useRouter() -const tabs = ref(['general', 'blocks', 'rollups']) -const activeTab = ref(route.query.tab && tabs.value.includes(route.query.tab) ? route.query.tab : tabs.value[0]) +const tabs = ref([ + { + name: "general", + visible: true, + }, + { + name: "blocks", + visible: true, + }, + { + name: "rollups", + visible: true, + }, + { + name: "ecosystem", + visible: isMainnet(), + }, +]) +const activeTab = ref(route.query.tab && tabs.value.filter(t => t.visible).map(t => t.name).includes(route.query.tab) ? route.query.tab : tabs.value[0].name) const updateRouteQuery = () => { router.replace({ @@ -117,8 +135,8 @@ watch( - - {{ capitilize(t) }} + + {{ capitilize(t.name) }} @@ -133,6 +151,7 @@ watch( + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 166bbc19..7d3711f7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -78,6 +78,116 @@ dependencies: specifier: ^0.21.0 version: 0.21.0(vite@5.4.14) +<<<<<<< HEAD + .: + dependencies: + '@amplitude/analytics-browser': + specifier: ^2.3.3 + version: 2.6.1 + '@codemirror/lang-json': + specifier: ^6.0.1 + version: 6.0.1 + '@keplr-wallet/cosmos': + specifier: ^0.12.70 + version: 0.12.76 + '@openzeppelin/merkle-tree': + specifier: ^1.0.6 + version: 1.0.6 + '@pinia/nuxt': + specifier: 0.4.11 + version: 0.4.11(rollup@4.21.0)(vue@3.4.38) + '@sentry/vue': + specifier: ^8.50.0 + version: 8.50.0(pinia@2.1.6(vue@3.4.38))(vue@3.4.38) + '@vueuse/core': + specifier: ^10.9.0 + version: 10.9.0(vue@3.4.38) + buffer: + specifier: ^6.0.3 + version: 6.0.3 + codemirror: + specifier: ^6.0.1 + version: 6.0.1(@lezer/common@1.2.1) + crypto-js: + specifier: ^4.2.0 + version: 4.2.0 + d3: + specifier: ^7.8.5 + version: 7.9.0 + d3-geo: + specifier: ^3.1.1 + version: 3.1.1 + d3-hierarchy: + specifier: ^3.1.2 + version: 3.1.2 + focus-trap: + specifier: 7.5.2 + version: 7.5.2 + iconv-lite: + specifier: ^0.6.3 + version: 0.6.3 + js-sha256: + specifier: ^0.11.0 + version: 0.11.0 + lean-qr: + specifier: ^2.3.2 + version: 2.3.4 + long: + specifier: ^5.2.3 + version: 5.2.3 + luxon: + specifier: 3.4.3 + version: 3.4.3 + nuxt-site-config: + specifier: ^2.1.2 + version: 2.2.11(@nuxt/devtools@1.6.0(rollup@4.21.0)(vite@5.4.2(@types/node@20.12.2)(sass@1.66.1)(terser@5.30.1))(vue@3.4.38)(webpack-sources@3.2.3))(@unocss/webpack@0.58.9(rollup@4.21.0)(webpack@5.91.0))(@vue/compiler-core@3.4.38)(magicast@0.3.5)(nuxt@3.12.4(@parcel/watcher@2.4.1)(@types/node@20.12.2)(ioredis@5.4.1)(magicast@0.3.5)(rollup@4.21.0)(sass@1.66.1)(terser@5.30.1)(vite@5.4.2(@types/node@20.12.2)(sass@1.66.1)(terser@5.30.1))(webpack-sources@3.2.3))(postcss@8.4.41)(qrcode@1.5.3)(rollup@4.21.0)(vite@5.4.2(@types/node@20.12.2)(sass@1.66.1)(terser@5.30.1))(vue@3.4.38)(webpack-sources@3.2.3)(webpack@5.91.0) + pinia: + specifier: 2.1.6 + version: 2.1.6(vue@3.4.38) + protobufjs: + specifier: ^7.2.6 + version: 7.2.6 + qrcode: + specifier: ^1.5.3 + version: 1.5.3 + uuid: + specifier: 9.0.1 + version: 9.0.1 + vite-plugin-node-polyfills: + specifier: ^0.21.0 + version: 0.21.0(rollup@4.21.0)(vite@5.4.2(@types/node@20.12.2)(sass@1.66.1)(terser@5.30.1)) + devDependencies: + '@nuxt/devtools': + specifier: latest + version: 1.6.0(rollup@4.21.0)(vite@5.4.2(@types/node@20.12.2)(sass@1.66.1)(terser@5.30.1))(vue@3.4.38)(webpack-sources@3.2.3) + cross-env: + specifier: ^7.0.3 + version: 7.0.3 + nuxt: + specifier: 3.12.4 + version: 3.12.4(@parcel/watcher@2.4.1)(@types/node@20.12.2)(ioredis@5.4.1)(magicast@0.3.5)(rollup@4.21.0)(sass@1.66.1)(terser@5.30.1)(vite@5.4.2(@types/node@20.12.2)(sass@1.66.1)(terser@5.30.1))(webpack-sources@3.2.3) + nuxt-og-image: + specifier: 3.0.0-rc.52 + version: 3.0.0-rc.52(@lezer/common@1.2.1)(@nuxt/devtools@1.6.0(rollup@4.21.0)(vite@5.4.2(@types/node@20.12.2)(sass@1.66.1)(terser@5.30.1))(vue@3.4.38)(webpack-sources@3.2.3))(@unocss/webpack@0.58.9(rollup@4.21.0)(webpack@5.91.0))(@vue/compiler-core@3.4.38)(magicast@0.3.5)(nuxt@3.12.4(@parcel/watcher@2.4.1)(@types/node@20.12.2)(ioredis@5.4.1)(magicast@0.3.5)(rollup@4.21.0)(sass@1.66.1)(terser@5.30.1)(vite@5.4.2(@types/node@20.12.2)(sass@1.66.1)(terser@5.30.1))(webpack-sources@3.2.3))(postcss@8.4.41)(qrcode@1.5.3)(rollup@4.21.0)(vite@5.4.2(@types/node@20.12.2)(sass@1.66.1)(terser@5.30.1))(vue@3.4.38)(webpack-sources@3.2.3)(webpack@5.91.0) + nuxt-simple-sitemap: + specifier: ^4.2.0 + version: 4.4.1(@nuxt/devtools@1.6.0(rollup@4.21.0)(vite@5.4.2(@types/node@20.12.2)(sass@1.66.1)(terser@5.30.1))(vue@3.4.38)(webpack-sources@3.2.3))(@unocss/webpack@0.58.9(rollup@4.21.0)(webpack@5.91.0))(@vue/compiler-core@3.4.38)(h3@1.12.0)(magicast@0.3.5)(nuxt@3.12.4(@parcel/watcher@2.4.1)(@types/node@20.12.2)(ioredis@5.4.1)(magicast@0.3.5)(rollup@4.21.0)(sass@1.66.1)(terser@5.30.1)(vite@5.4.2(@types/node@20.12.2)(sass@1.66.1)(terser@5.30.1))(webpack-sources@3.2.3))(postcss@8.4.41)(qrcode@1.5.3)(rollup@4.21.0)(vite@5.4.2(@types/node@20.12.2)(sass@1.66.1)(terser@5.30.1))(vue@3.4.38)(webpack-sources@3.2.3)(webpack@5.91.0) + sass: + specifier: 1.66.1 + version: 1.66.1 + sass-loader: + specifier: 13.3.2 + version: 13.3.2(sass@1.66.1)(webpack@5.91.0) + unenv: + specifier: ^1.9.0 + version: 1.9.0 + vite-plugin-top-level-await: + specifier: ^1.4.4 + version: 1.4.4(rollup@4.21.0)(vite@5.4.2(@types/node@20.12.2)(sass@1.66.1)(terser@5.30.1)) + vite-plugin-wasm: + specifier: ^3.3.0 + version: 3.3.0(vite@5.4.2(@types/node@20.12.2)(sass@1.66.1)(terser@5.30.1)) +======= devDependencies: '@nuxt/devtools': specifier: latest @@ -109,6 +219,7 @@ devDependencies: vite-plugin-wasm: specifier: ^3.3.0 version: 3.4.1(vite@5.4.14) +>>>>>>> dev packages: diff --git a/services/api/stats.js b/services/api/stats.js index db99538e..8e184c77 100644 --- a/services/api/stats.js +++ b/services/api/stats.js @@ -1,7 +1,7 @@ /** Services */ -import { tvlServiceURL, useServerURL } from "@/services/config" +import { nodeStatsURL, tvlServiceURL, useServerURL } from "@/services/config" -export const fetch24hDiffs = async ({ name }) => { +export const fetchGeneralStats = async ({ name }) => { try { const data = await $fetch(`${useServerURL()}/stats/${name}`) return data @@ -175,3 +175,17 @@ export const fetchSquareSize = async (from) => { console.error(error) } } + +export const fetchNodeStats = async ({ name, from, to }) => { + try { + const url = new URL(`${nodeStatsURL}/stats/${name}`) + + if (from) url.searchParams.append("from", from) + if (to) url.searchParams.append("to", to) + + const data = await $fetch(url.href) + return data + } catch (error) { + console.error(error) + } +} \ No newline at end of file diff --git a/services/config.js b/services/config.js index 97280b7e..feadefd8 100644 --- a/services/config.js +++ b/services/config.js @@ -108,5 +108,6 @@ export const getStartChainDate = () => { } export const blockscoutURL = "https://celestia-l2-router.k8s-dev.blockscout.com/api/v1/celestia/l2BatchMetadata" +export const nodeStatsURL = "https://node-stats.celenium.io/v1" export const faucetURL = "https://api-faucet.celenium.io/v1" export const tvlServiceURL = "https://tvl.celenium.io/v1" diff --git a/services/constants/stats.js b/services/constants/stats.js index 0b0cf214..4a0f06d4 100644 --- a/services/constants/stats.js +++ b/services/constants/stats.js @@ -120,7 +120,19 @@ export const STATS_SERIES = [ }, ], }, -] + { + group: 'Ecosystem', + series: [ + { + name: 'nodetype', + title: 'node type', + }, + { + name: 'version', + title: 'version', + }, + ], + },] // TO DO: Replace forEach with for export function getSeriesByGroupAndType(group, type) { @@ -223,3 +235,316 @@ export const STATS_TIMEFRAMES = [ timeframe: 'month', }, ] + +const countryCodesMap = { + AF: 'AFG', + AL: 'ALB', + DZ: 'DZA', + AS: 'ASM', + AD: 'AND', + AO: 'AGO', + AI: 'AIA', + AQ: 'ATA', + AG: 'ATG', + AR: 'ARG', + AM: 'ARM', + AW: 'ABW', + AU: 'AUS', + AT: 'AUT', + AZ: 'AZE', + BS: 'BHS', + BH: 'BHR', + BD: 'BGD', + BB: 'BRB', + BY: 'BLR', + BE: 'BEL', + BZ: 'BLZ', + BJ: 'BEN', + BM: 'BMU', + BT: 'BTN', + BO: 'BOL', + BA: 'BIH', + BW: 'BWA', + BV: 'BVT', + BR: 'BRA', + IO: 'IOT', + BN: 'BRN', + BG: 'BGR', + BF: 'BFA', + BI: 'BDI', + KH: 'KHM', + CM: 'CMR', + CA: 'CAN', + CV: 'CPV', + KY: 'CYM', + CF: 'CAF', + TD: 'TCD', + CL: 'CHL', + CN: 'CHN', + CX: 'CXR', + CC: 'CCK', + CO: 'COL', + KM: 'COM', + CG: 'COG', + CD: 'COD', + CK: 'COK', + CR: 'CRI', + CI: 'CIV', + HR: 'HRV', + CU: 'CUB', + CY: 'CYP', + CZ: 'CZE', + DK: 'DNK', + DJ: 'DJI', + DM: 'DMA', + DO: 'DOM', + EC: 'ECU', + EG: 'EGY', + SV: 'SLV', + GQ: 'GNQ', + ER: 'ERI', + EE: 'EST', + ET: 'ETH', + FK: 'FLK', + FO: 'FRO', + FJ: 'FJI', + FI: 'FIN', + FR: 'FRA', + GF: 'GUF', + PF: 'PYF', + TF: 'ATF', + GA: 'GAB', + GM: 'GMB', + GE: 'GEO', + DE: 'DEU', + GH: 'GHA', + GI: 'GIB', + GR: 'GRC', + GL: 'GRL', + GD: 'GRD', + GP: 'GLP', + GU: 'GUM', + GT: 'GTM', + GN: 'GIN', + GW: 'GNB', + GY: 'GUY', + HT: 'HTI', + HM: 'HMD', + VA: 'VAT', + HN: 'HND', + HK: 'HKG', + HU: 'HUN', + IS: 'ISL', + IN: 'IND', + ID: 'IDN', + IR: 'IRN', + IQ: 'IRQ', + IE: 'IRL', + IL: 'ISR', + IT: 'ITA', + JM: 'JAM', + JP: 'JPN', + JO: 'JOR', + KZ: 'KAZ', + KE: 'KEN', + KI: 'KIR', + KP: 'PRK', + KR: 'KOR', + KW: 'KWT', + KG: 'KGZ', + LA: 'LAO', + LV: 'LVA', + LB: 'LBN', + LS: 'LSO', + LR: 'LBR', + LY: 'LBY', + LI: 'LIE', + LT: 'LTU', + LU: 'LUX', + MO: 'MAC', + MG: 'MDG', + MW: 'MWI', + MY: 'MYS', + MV: 'MDV', + ML: 'MLI', + MT: 'MLT', + MH: 'MHL', + MQ: 'MTQ', + MR: 'MRT', + MU: 'MUS', + YT: 'MYT', + MX: 'MEX', + FM: 'FSM', + MD: 'MDA', + MC: 'MCO', + MN: 'MNG', + MS: 'MSR', + MA: 'MAR', + MZ: 'MOZ', + MM: 'MMR', + NA: 'NAM', + NR: 'NRU', + NP: 'NPL', + NL: 'NLD', + NC: 'NCL', + NZ: 'NZL', + NI: 'NIC', + NE: 'NER', + NG: 'NGA', + NU: 'NIU', + NF: 'NFK', + MP: 'MNP', + MK: 'MKD', + NO: 'NOR', + OM: 'OMN', + PK: 'PAK', + PW: 'PLW', + PS: 'PSE', + PA: 'PAN', + PG: 'PNG', + PY: 'PRY', + PE: 'PER', + PH: 'PHL', + PN: 'PCN', + PL: 'POL', + PT: 'PRT', + PR: 'PRI', + QA: 'QAT', + RE: 'REU', + RO: 'ROU', + RU: 'RUS', + RW: 'RWA', + SH: 'SHN', + KN: 'KNA', + LC: 'LCA', + PM: 'SPM', + VC: 'VCT', + WS: 'WSM', + SM: 'SMR', + ST: 'STP', + SA: 'SAU', + SN: 'SEN', + SC: 'SYC', + SL: 'SLE', + SG: 'SGP', + SK: 'SVK', + SI: 'SVN', + SB: 'SLB', + SO: 'SOM', + ZA: 'ZAF', + GS: 'SGS', + ES: 'ESP', + LK: 'LKA', + SD: 'SDN', + SR: 'SUR', + SJ: 'SJM', + SZ: 'SWZ', + SE: 'SWE', + CH: 'CHE', + SY: 'SYR', + TW: 'TWN', + TJ: 'TJK', + TZ: 'TZA', + TH: 'THA', + TL: 'TLS', + TG: 'TGO', + TK: 'TKL', + TO: 'TON', + TT: 'TTO', + TN: 'TUN', + TR: 'TUR', + TM: 'TKM', + TC: 'TCA', + TV: 'TUV', + UG: 'UGA', + UA: 'UKR', + AE: 'ARE', + GB: 'GBR', + US: 'USA', + UM: 'UMI', + UY: 'URY', + UZ: 'UZB', + VU: 'VUT', + VE: 'VEN', + VN: 'VNM', + VG: 'VGB', + VI: 'VIR', + WF: 'WLF', + EH: 'ESH', + YE: 'YEM', + ZM: 'ZMB', + ZW: 'ZWE', + AX: 'ALA', + BQ: 'BES', + CW: 'CUW', + GG: 'GGY', + IM: 'IMN', + JE: 'JEY', + ME: 'MNE', + BL: 'BLM', + MF: 'MAF', + RS: 'SRB', + SX: 'SXM', + XK: 'XKK' +} +export const convertCountryCode = (alpha2) => countryCodesMap[alpha2.toUpperCase()] + +const countryCentroidMap = { + CAN: [-110, 60], + USA: [-100, 41], + FRA: [2.5, 47], + GBR: [-1.8, 53], + IDN: [114, -1], + // NOR: [12, 63], + NZL: [172.3, -42.5], +} +export const getCountryCentroid = (name) => countryCentroidMap[name] + +const cityCountryMap = { + sakaiminato: "JPN", + istanbul: "TUR", + imperia: "ITA", + ko_samui: "THA", + fatih: "TUR", + nicosia: "CYP", +} +export const getCountryByCity = (city) => cityCountryMap[city.toLowerCase().replace(" ", "_")] + +const loaderPathes = [ + { + name: "France", + path: "M283.4 19.83c-3.2 0-31.2 5.09-31.2 5.09c-1.3 41.61-30.4 78.48-90.3 84.88l-12.8-23.07l-25.1 2.48l11.3 60.09l-113.79-4.9l12.2 41.5C156.3 225.4 150.7 338.4 124 439.4c47 53 141.8 47.8 186 43.1c3.1-62.2 52.4-64.5 135.9-32.2c11.3-17.6 18.8-36 44.6-50.7l-46.6-139.5l-27.5 6.2c11-21.1 32.2-49.9 50.4-63.4l15.6-86.9c-88.6-6.3-146.4-46.36-199-96.17", + weight: 0.2, + }, + { + name: "Africa", + path: "m201.56 19.495l-87.79 9.131l-73.745 94.814v52.676l56.186 61.805l64.615-13.344l49.164 9.832l-10.535 37.926l33.711 61.103l-16.855 42.842l39.79 116.225l53.62-8.768l49.164-55.484l4.213-38.629l31.605-23.879l-6.322-69.531l83.594-106.994l-51.989 7.263l-79.363-138.359l-125.016-8.428z", + weight: 0.2, + }, + { + name: "Mongolia", + path: "m18.83 183.4l73.19-29.3L165.6 185c6.3-17 8.6-42.6 26.3-44.3c22.3-2.1 42.9 15.1 47.1 39.9l54-1.6l54.5 22.8l55-35.2l32.3 7.9s-20.3 32.6-9.7 42.4c9.1 8.5 35.5-10.9 35.5-10.9l32.6 22.1l-87.1 62.7c-6.7-4.7-16.4-13.5-27.1-5c-9.9 7.9-6 21.9 1 33.8c-32.9 31-71 43-109.8 51.7l-127.8-30l-92.59-70c9.92-34.7-14.36-61-30.98-87.9", + weight: 0.2, + }, + { + name: "Brazil", + path: "M292.8 41.71c16.1 58.89 125.3 78.19 197.9 116.19c1.6 35.2-14.4 72.6-56.7 102.3c2.9 70.2-41.8 110.2-114.3 132.4c-.3 33.2-12.7 64-47.3 90.3l-59-36.4l47.4-34.2c-1.8-25.6-9.6-52.3-55-67.3l-26.3-93.2c-54.5-10.4-51.9-31.3-56.3-50.9l-64.93 20.4c-49.154-31-51.902-75.4 6.26-83.4l6.99-72.78l51.18 9.12L133 37.03l49.6-7.9l20.7 37.33z", + weight: 0.2, + }, + { + name: "Australia", + path: "m380.37 28.839l-27.24 100.215l-64-48l17.405-34.46l-83.863 8.079l-13.541 42.38l-35.512-25.482l-67.16 85.62l-83.008 48.593l34.81 156.752l38.87 6.518l112-64l74.38 52.082l21.62-28.094l32 72.012L424 415.452l64.549-126.398l-6.014-64.703l-65.404-79.297l-36.762-116.215z", + weight: 0.2, + } +] +export function getRandomLoaderPath() { + const randomNum = Math.random() + + let cumWeight = 0 + for (let p of loaderPathes.filter(el => el.weight <= 1)) { + cumWeight += p.weight + if (randomNum <= cumWeight) { + return p.path + } + } +} \ No newline at end of file