// Currencies with placeholder rates anchored to USD = 1.0 // We'll derive any base pair on the fly. const CURRENCIES = [ { code: "USD", name: "US Dollar", symbol: "$", flag: "US", rate: 1.0000 }, { code: "EUR", name: "Euro", symbol: "€", flag: "EU", rate: 0.9210 }, { code: "GBP", name: "British Pound", symbol: "£", flag: "GB", rate: 0.7830 }, { code: "CAD", name: "Canadian Dollar", symbol: "C$", flag: "CA", rate: 1.3680 }, { code: "AUD", name: "Australian Dollar", symbol: "A$", flag: "AU", rate: 1.5240 }, { code: "NZD", name: "NZ Dollar", symbol: "NZ$", flag: "NZ", rate: 1.6510 }, { code: "JPY", name: "Japanese Yen", symbol: "¥", flag: "JP", rate: 151.20 }, { code: "CNY", name: "Chinese Yuan", symbol: "¥", flag: "CN", rate: 7.2400 }, { code: "HKD", name: "Hong Kong Dollar", symbol: "HK$", flag: "HK", rate: 7.8200 }, { code: "KRW", name: "South Korean Won", symbol: "₩", flag: "KR", rate: 1350.00 }, { code: "INR", name: "Indian Rupee", symbol: "₹", flag: "IN", rate: 83.40 }, { code: "IDR", name: "Indonesian Rupiah", symbol: "Rp", flag: "ID", rate: 15820.0 }, { code: "THB", name: "Thai Baht", symbol: "฿", flag: "TH", rate: 36.10 }, { code: "SGD", name: "Singapore Dollar", symbol: "S$", flag: "SG", rate: 1.3520 }, { code: "MYR", name: "Malaysian Ringgit", symbol: "RM", flag: "MY", rate: 4.7200 }, { code: "PHP", name: "Philippine Peso", symbol: "₱", flag: "PH", rate: 56.40 }, { code: "VND", name: "Vietnamese Dong", symbol: "₫", flag: "VN", rate: 25100.0 }, { code: "CHF", name: "Swiss Franc", symbol: "Fr", flag: "CH", rate: 0.9060 }, { code: "SEK", name: "Swedish Krona", symbol: "kr", flag: "SE", rate: 10.82 }, { code: "NOK", name: "Norwegian Krone", symbol: "kr", flag: "NO", rate: 10.95 }, { code: "DKK", name: "Danish Krone", symbol: "kr", flag: "DK", rate: 6.8700 }, { code: "PLN", name: "Polish Zloty", symbol: "zł", flag: "PL", rate: 3.9600 }, { code: "CZK", name: "Czech Koruna", symbol: "Kč", flag: "CZ", rate: 23.00 }, { code: "HUF", name: "Hungarian Forint", symbol: "Ft", flag: "HU", rate: 363.00 }, { code: "RON", name: "Romanian Leu", symbol: "lei", flag: "RO", rate: 4.5800 }, { code: "TRY", name: "Turkish Lira", symbol: "₺", flag: "TR", rate: 32.40 }, { code: "RUB", name: "Russian Ruble", symbol: "₽", flag: "RU", rate: 92.50 }, { code: "UAH", name: "Ukrainian Hryvnia", symbol: "₴", flag: "UA", rate: 39.10 }, { code: "MXN", name: "Mexican Peso", symbol: "$", flag: "MX", rate: 17.12 }, { code: "BRL", name: "Brazilian Real", symbol: "R$", flag: "BR", rate: 5.0600 }, { code: "ARS", name: "Argentine Peso", symbol: "$", flag: "AR", rate: 870.00 }, { code: "CLP", name: "Chilean Peso", symbol: "$", flag: "CL", rate: 965.00 }, { code: "COP", name: "Colombian Peso", symbol: "$", flag: "CO", rate: 3940.0 }, { code: "PEN", name: "Peruvian Sol", symbol: "S/", flag: "PE", rate: 3.7500 }, { code: "ZAR", name: "South African Rand", symbol: "R", flag: "ZA", rate: 18.90 }, { code: "EGP", name: "Egyptian Pound", symbol: "E£", flag: "EG", rate: 47.80 }, { code: "NGN", name: "Nigerian Naira", symbol: "₦", flag: "NG", rate: 1510.0 }, { code: "KES", name: "Kenyan Shilling", symbol: "KSh", flag: "KE", rate: 130.50 }, { code: "MAD", name: "Moroccan Dirham", symbol: "DH", flag: "MA", rate: 9.9800 }, { code: "AED", name: "UAE Dirham", symbol: "د.إ", flag: "AE", rate: 3.6720 }, { code: "SAR", name: "Saudi Riyal", symbol: "﷼", flag: "SA", rate: 3.7500 }, { code: "ILS", name: "Israeli Shekel", symbol: "₪", flag: "IL", rate: 3.7200 }, { code: "QAR", name: "Qatari Riyal", symbol: "﷼", flag: "QA", rate: 3.6400 }, { code: "PKR", name: "Pakistani Rupee", symbol: "₨", flag: "PK", rate: 278.50 }, { code: "BDT", name: "Bangladeshi Taka", symbol: "৳", flag: "BD", rate: 110.20 }, { code: "ISK", name: "Icelandic Krona", symbol: "kr", flag: "IS", rate: 138.00 }, ]; // EU member states share EUR const EU_COUNTRIES = ["DE","FR","IT","ES","PT","NL","BE","AT","IE","FI","GR","SK","SI","EE","LV","LT","LU","MT","CY","HR","BG"]; // Country placements on a 1000×500 equirectangular map (lat/lon → x,y). // We'll compute x = (lon+180)/360 * 1000; y = (90 - lat)/180 * 500. function project(lon, lat) { return { x: (lon + 180) / 360 * 1000, y: (90 - lat) / 180 * 500 }; } // Curated set of labeled countries with approx capital/centroid coords and their currency const COUNTRIES = [ // North America { code: "US", name: "United States", ccy: "USD", lon: -98, lat: 39.5 }, { code: "CA", name: "Canada", ccy: "CAD", lon: -106, lat: 56 }, { code: "MX", name: "Mexico", ccy: "MXN", lon: -102, lat: 23.5 }, // Central / Caribbean { code: "CU", name: "Cuba", ccy: "USD", lon: -79, lat: 22 }, // South America { code: "BR", name: "Brazil", ccy: "BRL", lon: -52, lat: -10 }, { code: "AR", name: "Argentina", ccy: "ARS", lon: -64, lat: -35 }, { code: "CL", name: "Chile", ccy: "CLP", lon: -71, lat: -33 }, { code: "CO", name: "Colombia", ccy: "COP", lon: -74, lat: 4 }, { code: "PE", name: "Peru", ccy: "PEN", lon: -75, lat: -10 }, // Europe { code: "GB", name: "United Kingdom",ccy: "GBP", lon: -2, lat: 54 }, { code: "IS", name: "Iceland", ccy: "ISK", lon: -19, lat: 65 }, { code: "IE", name: "Ireland", ccy: "EUR", lon: -8, lat: 53 }, { code: "FR", name: "France", ccy: "EUR", lon: 2.5, lat: 46.5 }, { code: "DE", name: "Germany", ccy: "EUR", lon: 10.5, lat: 51 }, { code: "ES", name: "Spain", ccy: "EUR", lon: -3.5, lat: 40 }, { code: "PT", name: "Portugal", ccy: "EUR", lon: -8, lat: 39.5 }, { code: "IT", name: "Italy", ccy: "EUR", lon: 12.5, lat: 42.5 }, { code: "NL", name: "Netherlands", ccy: "EUR", lon: 5.5, lat: 52.2 }, { code: "CH", name: "Switzerland", ccy: "CHF", lon: 8, lat: 46.8 }, { code: "SE", name: "Sweden", ccy: "SEK", lon: 16, lat: 62 }, { code: "NO", name: "Norway", ccy: "NOK", lon: 10, lat: 62 }, { code: "DK", name: "Denmark", ccy: "DKK", lon: 10, lat: 56 }, { code: "PL", name: "Poland", ccy: "PLN", lon: 19, lat: 52 }, { code: "CZ", name: "Czechia", ccy: "CZK", lon: 15.5, lat: 49.8 }, { code: "HU", name: "Hungary", ccy: "HUF", lon: 19.5, lat: 47.2 }, { code: "RO", name: "Romania", ccy: "RON", lon: 25, lat: 46 }, { code: "TR", name: "Türkiye", ccy: "TRY", lon: 35, lat: 39 }, { code: "UA", name: "Ukraine", ccy: "UAH", lon: 32, lat: 49 }, { code: "RU", name: "Russia", ccy: "RUB", lon: 95, lat: 62 }, // Africa { code: "EG", name: "Egypt", ccy: "EGP", lon: 30, lat: 27 }, { code: "MA", name: "Morocco", ccy: "MAD", lon: -6, lat: 32 }, { code: "NG", name: "Nigeria", ccy: "NGN", lon: 8, lat: 9.5 }, { code: "KE", name: "Kenya", ccy: "KES", lon: 38, lat: 0.5 }, { code: "ZA", name: "South Africa", ccy: "ZAR", lon: 25, lat: -29 }, // Middle East { code: "IL", name: "Israel", ccy: "ILS", lon: 35, lat: 31.5 }, { code: "SA", name: "Saudi Arabia", ccy: "SAR", lon: 45, lat: 24 }, { code: "AE", name: "UAE", ccy: "AED", lon: 54, lat: 24 }, { code: "QA", name: "Qatar", ccy: "QAR", lon: 51, lat: 25.3 }, // Asia { code: "IN", name: "India", ccy: "INR", lon: 79, lat: 22 }, { code: "PK", name: "Pakistan", ccy: "PKR", lon: 69, lat: 30 }, { code: "BD", name: "Bangladesh", ccy: "BDT", lon: 90, lat: 24 }, { code: "CN", name: "China", ccy: "CNY", lon: 104, lat: 35 }, { code: "HK", name: "Hong Kong", ccy: "HKD", lon: 114, lat: 22.3 }, { code: "JP", name: "Japan", ccy: "JPY", lon: 138, lat: 36 }, { code: "KR", name: "South Korea", ccy: "KRW", lon: 128, lat: 36.5 }, { code: "TH", name: "Thailand", ccy: "THB", lon: 101, lat: 15 }, { code: "VN", name: "Vietnam", ccy: "VND", lon: 108, lat: 16 }, { code: "MY", name: "Malaysia", ccy: "MYR", lon: 102, lat: 4 }, { code: "SG", name: "Singapore", ccy: "SGD", lon: 103.8, lat: 1.3 }, { code: "ID", name: "Indonesia", ccy: "IDR", lon: 113, lat: -2 }, { code: "PH", name: "Philippines", ccy: "PHP", lon: 122, lat: 13 }, // Oceania { code: "AU", name: "Australia", ccy: "AUD", lon: 134, lat: -25 }, { code: "NZ", name: "New Zealand", ccy: "NZD", lon: 172, lat: -41 }, ]; // Extra country names for map labels (no chips, no currency — display-only). // Shown at zoom ≥ 5.4 (50%+) alongside tier-3 chip countries. const EXTRA_LABELS = [ // Central America / Caribbean { name:"Guatemala", lon:-90.5, lat:15.5 }, { name:"Belize", lon:-88.5, lat:17.2 }, { name:"Honduras", lon:-86.5, lat:14.5 }, { name:"El Salvador", lon:-88.9, lat:13.8 }, { name:"Nicaragua", lon:-85, lat:12.8 }, { name:"Costa Rica", lon:-84, lat:9.7 }, { name:"Panama", lon:-80, lat:8.5 }, { name:"Jamaica", lon:-77.3, lat:18.1 }, { name:"Haiti", lon:-72.5, lat:19 }, { name:"Dominican Rep.",lon:-70.5, lat:18.7 }, { name:"Puerto Rico", lon:-66.5, lat:18.2 }, { name:"Trinidad", lon:-61.3, lat:10.7 }, // South America { name:"Venezuela", lon:-66, lat:7 }, { name:"Guyana", lon:-58.9, lat:5 }, { name:"Suriname", lon:-56, lat:4 }, { name:"Ecuador", lon:-78, lat:-1.5 }, { name:"Bolivia", lon:-64, lat:-17 }, { name:"Paraguay", lon:-58, lat:-23.5 }, { name:"Uruguay", lon:-56, lat:-33 }, // Europe (extras) { name:"Finland", lon:26, lat:64.5 }, { name:"Estonia", lon:26, lat:58.8 }, { name:"Latvia", lon:25, lat:56.9 }, { name:"Lithuania", lon:24, lat:55.3 }, { name:"Belarus", lon:28, lat:53.8 }, { name:"Slovakia", lon:19.6, lat:48.7 }, { name:"Austria", lon:14.5, lat:47.6 }, { name:"Belgium", lon:4.5, lat:50.6 }, { name:"Luxembourg", lon:6.1, lat:49.8 }, { name:"Slovenia", lon:14.8, lat:46.1 }, { name:"Croatia", lon:16, lat:45.5 }, { name:"Bosnia", lon:17.8, lat:44 }, { name:"Serbia", lon:21, lat:44 }, { name:"Montenegro", lon:19.3, lat:42.7 }, { name:"Kosovo", lon:21, lat:42.6 }, { name:"North Macedonia",lon:21.8, lat:41.6 }, { name:"Albania", lon:20, lat:41.1 }, { name:"Bulgaria", lon:25, lat:42.8 }, { name:"Greece", lon:22.5, lat:39 }, { name:"Moldova", lon:28.6, lat:47.2 }, { name:"Cyprus", lon:33.2, lat:35.1 }, { name:"Malta", lon:14.4, lat:35.9 }, // Middle East { name:"Syria", lon:38, lat:35 }, { name:"Lebanon", lon:35.8, lat:33.9 }, { name:"Jordan", lon:36, lat:31.3 }, { name:"Iraq", lon:44, lat:33 }, { name:"Iran", lon:53, lat:32.5 }, { name:"Kuwait", lon:47.5, lat:29.3 }, { name:"Bahrain", lon:50.6, lat:26.1 }, { name:"Oman", lon:56, lat:21 }, { name:"Yemen", lon:48, lat:15.5 }, // Central Asia { name:"Afghanistan", lon:66, lat:34 }, { name:"Turkmenistan", lon:59, lat:39 }, { name:"Uzbekistan", lon:64, lat:41.5 }, { name:"Tajikistan", lon:71, lat:38.8 }, { name:"Kyrgyzstan", lon:74.5, lat:41.5 }, { name:"Kazakhstan", lon:68, lat:48 }, { name:"Mongolia", lon:105, lat:46.5 }, { name:"Georgia", lon:43.5, lat:42 }, { name:"Armenia", lon:45, lat:40.3 }, { name:"Azerbaijan", lon:47.5, lat:40.3 }, // South Asia { name:"Nepal", lon:84, lat:28.3 }, { name:"Bhutan", lon:90.5, lat:27.5 }, { name:"Sri Lanka", lon:80.7, lat:7.9 }, { name:"Maldives", lon:73.2, lat:3.2 }, // SE Asia extras { name:"Myanmar", lon:96, lat:21 }, { name:"Laos", lon:103, lat:19.9 }, { name:"Cambodia", lon:105, lat:12.5 }, { name:"Taiwan", lon:121, lat:23.7 }, { name:"Brunei", lon:114.7, lat:4.5 }, { name:"Timor-Leste", lon:125.5, lat:-8.8 }, { name:"Papua New Guinea",lon:144, lat:-6 }, // North Africa { name:"Libya", lon:17, lat:27 }, { name:"Tunisia", lon:9.5, lat:34 }, { name:"Algeria", lon:2.6, lat:28 }, { name:"Sudan", lon:30, lat:15 }, { name:"South Sudan", lon:30.5, lat:7.5 }, { name:"Mauritania", lon:-10, lat:20 }, { name:"Western Sahara",lon:-13, lat:24.5 }, // West Africa { name:"Senegal", lon:-14.5, lat:14.5 }, { name:"Mali", lon:-4, lat:17.5 }, { name:"Niger", lon:8, lat:17 }, { name:"Chad", lon:18.5, lat:15 }, { name:"Burkina Faso", lon:-1.5, lat:12.5 }, { name:"Guinea", lon:-11, lat:10.5 }, { name:"Sierra Leone", lon:-11.8, lat:8.5 }, { name:"Liberia", lon:-9.4, lat:6.5 }, { name:"Ivory Coast", lon:-5.5, lat:7.5 }, { name:"Ghana", lon:-1.2, lat:7.9 }, { name:"Togo", lon:1, lat:8 }, { name:"Benin", lon:2.3, lat:9.5 }, { name:"Cameroon", lon:12.5, lat:6 }, { name:"Central African Rep.",lon:20, lat:6.5 }, { name:"Gabon", lon:11.8, lat:-0.8 }, { name:"Congo", lon:15.5, lat:-1 }, { name:"DR Congo", lon:23, lat:-2 }, // East Africa { name:"Ethiopia", lon:40, lat:9 }, { name:"Eritrea", lon:39, lat:15.5 }, { name:"Somalia", lon:46, lat:5 }, { name:"Djibouti", lon:43, lat:11.7 }, { name:"Uganda", lon:32.5, lat:1.5 }, { name:"Tanzania", lon:35, lat:-6.3 }, { name:"Rwanda", lon:30, lat:-2 }, { name:"Burundi", lon:30, lat:-3.4 }, // Southern Africa { name:"Angola", lon:17.8, lat:-12.5 }, { name:"Zambia", lon:27.5, lat:-13.5 }, { name:"Zimbabwe", lon:29.8, lat:-19 }, { name:"Mozambique", lon:36, lat:-18 }, { name:"Malawi", lon:34, lat:-13.3 }, { name:"Namibia", lon:18, lat:-22 }, { name:"Botswana", lon:24, lat:-22.5 }, { name:"Lesotho", lon:28.3, lat:-29.6 }, { name:"Eswatini", lon:31.5, lat:-26.5 }, { name:"Madagascar", lon:47, lat:-19.5 }, // Pacific { name:"Fiji", lon:178, lat:-17.8 }, { name:"Solomon Is.", lon:160, lat:-9.5 }, { name:"Vanuatu", lon:167.5, lat:-16 }, { name:"New Caledonia",lon:165.5, lat:-21.5 }, { name:"Samoa", lon:-172, lat:-13.8 }, // Greenland { name:"Greenland", lon:-40, lat:72 }, ]; window.EXTRA_LABELS = EXTRA_LABELS; // Attach projected map coords COUNTRIES.forEach(c => { const p = project(c.lon, c.lat); c.x = p.x; c.y = p.y; }); // Given a base currency and target, convert 1 unit of base → target function convert(baseCode, targetCode) { const base = CURRENCIES.find(c => c.code === baseCode); const tgt = CURRENCIES.find(c => c.code === targetCode); if (!base || !tgt) return 0; // rate is to USD: 1 base = 1/base.rate USD = (1/base.rate)*tgt.rate target return (1 / base.rate) * tgt.rate; } function formatRate(n) { if (!isFinite(n)) return "—"; if (n >= 1000) return n.toLocaleString("en-US", { maximumFractionDigits: 0 }); if (n >= 100) return n.toLocaleString("en-US", { maximumFractionDigits: 1 }); if (n >= 10) return n.toLocaleString("en-US", { maximumFractionDigits: 2 }); if (n >= 1) return n.toLocaleString("en-US", { maximumFractionDigits: 3 }); return n.toLocaleString("en-US", { maximumFractionDigits: 4 }); } Object.assign(window, { CURRENCIES, COUNTRIES, EU_COUNTRIES, convert, formatRate, project });