Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>SecureVPN - Fast & Secure Virtual Private Network</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <!-- Leaflet CSS --> | |
| <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> | |
| <style> | |
| .gradient-bg { | |
| background: linear-gradient(135deg, #6B73FF 0%, #000DFF 100%); | |
| } | |
| .server-marker { | |
| width: 16px; | |
| height: 16px; | |
| background-color: #4F46E5; | |
| border-radius: 50%; | |
| border: 2px solid white; | |
| position: relative; | |
| z-index: 1000; | |
| } | |
| .server-marker.active { | |
| background-color: #10B981; | |
| box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.3); | |
| } | |
| .connection-animation { | |
| animation: pulse 2s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { opacity: 0.7; } | |
| 50% { opacity: 1; } | |
| 100% { opacity: 0.7; } | |
| } | |
| .vpn-toggle { | |
| transition: all 0.3s ease; | |
| } | |
| .vpn-toggle.active { | |
| background-color: #10B981; | |
| } | |
| .speedometer { | |
| position: relative; | |
| width: 150px; | |
| height: 150px; | |
| } | |
| .speedometer-circle { | |
| position: absolute; | |
| width: 100%; | |
| height: 100%; | |
| border-radius: 50%; | |
| border: 10px solid #E5E7EB; | |
| } | |
| .speedometer-fill { | |
| position: absolute; | |
| width: 100%; | |
| height: 100%; | |
| border-radius: 50%; | |
| border: 10px solid transparent; | |
| border-top-color: #4F46E5; | |
| border-right-color: #4F46E5; | |
| transform: rotate(45deg); | |
| transition: transform 0.5s ease; | |
| } | |
| #server-map { | |
| height: 400px; | |
| width: 100%; | |
| border-radius: 0.75rem; | |
| z-index: 1; | |
| } | |
| .country-flag { | |
| width: 16px; | |
| height: 12px; | |
| display: inline-block; | |
| margin-right: 6px; | |
| background-size: cover; | |
| border: 1px solid #e5e7eb; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 font-sans"> | |
| <!-- Header --> | |
| <header class="gradient-bg text-white shadow-lg"> | |
| <div class="container mx-auto px-4 py-4 flex justify-between items-center"> | |
| <div class="flex items-center space-x-2"> | |
| <i class="fas fa-lock text-2xl"></i> | |
| <h1 class="text-2xl font-bold">SecureVPN</h1> | |
| </div> | |
| <nav class="hidden md:flex space-x-8"> | |
| <a href="#" class="hover:text-gray-200 transition">Features</a> | |
| <a href="#" class="hover:text-gray-200 transition">Pricing</a> | |
| <a href="#" class="hover:text-gray-200 transition">Servers</a> | |
| <a href="#" class="hover:text-gray-200 transition">Support</a> | |
| </nav> | |
| <div class="flex items-center space-x-4"> | |
| <button class="px-4 py-2 rounded-full bg-white text-blue-600 font-medium hover:bg-gray-100 transition">Sign In</button> | |
| <button class="md:hidden text-2xl"> | |
| <i class="fas fa-bars"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Main Content --> | |
| <main class="container mx-auto px-4 py-8"> | |
| <!-- Connection Dashboard --> | |
| <div class="bg-white rounded-xl shadow-md overflow-hidden mb-8"> | |
| <div class="p-6 md:p-8"> | |
| <div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-6"> | |
| <div> | |
| <h2 class="text-2xl font-bold text-gray-800">VPN Connection</h2> | |
| <p class="text-gray-600">Secure your internet connection with one click</p> | |
| </div> | |
| <div class="mt-4 md:mt-0 flex items-center space-x-4"> | |
| <div class="flex items-center space-x-2"> | |
| <div class="w-3 h-3 rounded-full bg-gray-300"></div> | |
| <span class="text-sm text-gray-600" id="connection-status">Disconnected</span> | |
| </div> | |
| <div class="relative"> | |
| <div class="vpn-toggle w-16 h-8 bg-gray-300 rounded-full flex items-center cursor-pointer" id="vpn-toggle"> | |
| <div class="w-6 h-6 bg-white rounded-full shadow-md transform translate-x-1 transition"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="flex flex-col lg:flex-row gap-8"> | |
| <!-- Server Map --> | |
| <div class="flex-1 relative"> | |
| <div id="server-map" class="bg-gray-100 rounded-xl"></div> | |
| <div class="mt-4 flex flex-wrap gap-2" id="server-buttons-container"> | |
| <!-- Server buttons will be added dynamically --> | |
| </div> | |
| </div> | |
| <!-- Connection Details --> | |
| <div class="flex-1"> | |
| <div class="bg-gray-50 rounded-xl p-6 h-full"> | |
| <div class="flex flex-col h-full"> | |
| <div class="mb-6"> | |
| <h3 class="text-lg font-semibold text-gray-800 mb-2">Current Connection</h3> | |
| <div class="flex items-center space-x-3"> | |
| <div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center"> | |
| <i class="fas fa-shield-alt text-blue-600"></i> | |
| </div> | |
| <div> | |
| <p class="font-medium" id="current-server">Australia #23</p> | |
| <p class="text-sm text-gray-600" id="server-ip">192.168.23.45</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="mb-6"> | |
| <h3 class="text-lg font-semibold text-gray-800 mb-4">Connection Speed</h3> | |
| <div class="flex justify-around items-center"> | |
| <div class="text-center"> | |
| <div class="speedometer mx-auto mb-2"> | |
| <div class="speedometer-circle"></div> | |
| <div class="speedometer-fill" id="download-speedometer"></div> | |
| </div> | |
| <p class="text-sm text-gray-600">Download</p> | |
| <p class="font-bold" id="download-speed">0 Mbps</p> | |
| </div> | |
| <div class="text-center"> | |
| <div class="speedometer mx-auto mb-2"> | |
| <div class="speedometer-circle"></div> | |
| <div class="speedometer-fill" id="upload-speedometer"></div> | |
| </div> | |
| <p class="text-sm text-gray-600">Upload</p> | |
| <p class="font-bold" id="upload-speed">0 Mbps</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="mt-auto"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <span class="text-sm text-gray-600">Data Transferred</span> | |
| <span class="text-sm font-medium" id="data-transferred">0 MB</span> | |
| </div> | |
| <div class="w-full bg-gray-200 rounded-full h-2"> | |
| <div class="bg-blue-600 h-2 rounded-full" id="data-progress" style="width: 0%"></div> | |
| </div> | |
| <div class="flex justify-between items-center mt-4"> | |
| <span class="text-sm text-gray-600">Connection Time</span> | |
| <span class="text-sm font-medium" id="connection-time">00:00:00</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Features Section --> | |
| <div class="mb-12"> | |
| <h2 class="text-2xl font-bold text-gray-800 mb-6">Why Choose SecureVPN?</h2> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-6"> | |
| <div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition"> | |
| <div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center text-white mb-4"> | |
| <i class="fas fa-bolt text-xl"></i> | |
| </div> | |
| <h3 class="text-xl font-semibold mb-2">Lightning Fast</h3> | |
| <p class="text-gray-600">Our high-speed servers ensure you can stream, download, and browse without any lag or buffering.</p> | |
| </div> | |
| <div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition"> | |
| <div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center text-white mb-4"> | |
| <i class="fas fa-user-shield text-xl"></i> | |
| </div> | |
| <h3 class="text-xl font-semibold mb-2">Military Grade Encryption</h3> | |
| <p class="text-gray-600">256-bit AES encryption protects your data from hackers, ISPs, and government surveillance.</p> | |
| </div> | |
| <div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition"> | |
| <div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center text-white mb-4"> | |
| <i class="fas fa-globe-americas text-xl"></i> | |
| </div> | |
| <h3 class="text-xl font-semibold mb-2">Global Network</h3> | |
| <p class="text-gray-600">Access content from anywhere with our network of 1000+ servers in 50+ countries worldwide.</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Testimonials --> | |
| <div class="mb-12"> | |
| <h2 class="text-2xl font-bold text-gray-800 mb-6">What Our Users Say</h2> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6"> | |
| <div class="bg-white p-6 rounded-xl shadow-sm"> | |
| <div class="flex items-center mb-4"> | |
| <div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center mr-3"> | |
| <i class="fas fa-user text-blue-600"></i> | |
| </div> | |
| <div> | |
| <p class="font-medium">Sarah Johnson</p> | |
| <div class="flex text-yellow-400"> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <p class="text-gray-600">"I've tried several VPN services before, but SecureVPN is by far the fastest and most reliable. It's become an essential tool for my remote work."</p> | |
| </div> | |
| <div class="bg-white p-6 rounded-xl shadow-sm"> | |
| <div class="flex items-center mb-4"> | |
| <div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center mr-3"> | |
| <i class="fas fa-user text-blue-600"></i> | |
| </div> | |
| <div> | |
| <p class="font-medium">Michael Chen</p> | |
| <div class="flex text-yellow-400"> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star"></i> | |
| <i class="fas fa-star-half-alt"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <p class="text-gray-600">"As a frequent traveler, SecureVPN allows me to access my favorite shows and websites no matter where I am. The connection is always stable."</p> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Footer --> | |
| <footer class="bg-gray-800 text-white py-12"> | |
| <div class="container mx-auto px-4"> | |
| <div class="grid grid-cols-1 md:grid-cols-4 gap-8 mb-8"> | |
| <div> | |
| <h3 class="text-xl font-bold mb-4 flex items-center"> | |
| <i class="fas fa-lock mr-2"></i> SecureVPN | |
| </h3> | |
| <p class="text-gray-400">Protecting your digital life since 2015 with fast, secure, and private VPN services.</p> | |
| </div> | |
| <div> | |
| <h4 class="font-semibold mb-4">Product</h4> | |
| <ul class="space-y-2"> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Features</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Pricing</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Servers</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Apps</a></li> | |
| </ul> | |
| </div> | |
| <div> | |
| <h4 class="font-semibold mb-4">Support</h4> | |
| <ul class="space-y-2"> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Help Center</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Tutorials</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Contact Us</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Status</a></li> | |
| </ul> | |
| </div> | |
| <div> | |
| <h4 class="font-semibold mb-4">Legal</h4> | |
| <ul class="space-y-2"> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Privacy Policy</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Terms of Service</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">DMCA</a></li> | |
| <li><a href="#" class="text-gray-400 hover:text-white transition">Refund Policy</a></li> | |
| </ul> | |
| </div> | |
| </div> | |
| <div class="pt-6 border-t border-gray-700 flex flex-col md:flex-row justify-between items-center"> | |
| <p class="text-gray-400 mb-4 md:mb-0">© 2023 SecureVPN. All rights reserved.</p> | |
| <div class="flex space-x-4"> | |
| <a href="#" class="text-gray-400 hover:text-white transition"><i class="fab fa-twitter"></i></a> | |
| <a href="#" class="text-gray-400 hover:text-white transition"><i class="fab fa-facebook"></i></a> | |
| <a href="#" class="text-gray-400 hover:text-white transition"><i class="fab fa-instagram"></i></a> | |
| <a href="#" class="text-gray-400 hover:text-white transition"><i class="fab fa-linkedin"></i></a> | |
| </div> | |
| </div> | |
| </div> | |
| </footer> | |
| <!-- Leaflet JS --> | |
| <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> | |
| <script> | |
| // DOM Elements | |
| const vpnToggle = document.getElementById('vpn-toggle'); | |
| const connectionStatus = document.getElementById('connection-status'); | |
| const currentServer = document.getElementById('current-server'); | |
| const serverIp = document.getElementById('server-ip'); | |
| const downloadSpeed = document.getElementById('download-speed'); | |
| const uploadSpeed = document.getElementById('upload-speed'); | |
| const downloadSpeedometer = document.getElementById('download-speedometer'); | |
| const uploadSpeedometer = document.getElementById('upload-speedometer'); | |
| const dataTransferred = document.getElementById('data-transferred'); | |
| const dataProgress = document.getElementById('data-progress'); | |
| const connectionTime = document.getElementById('connection-time'); | |
| const serverButtonsContainer = document.getElementById('server-buttons-container'); | |
| // Variables | |
| let isConnected = false; | |
| let connectionStartTime = null; | |
| let connectionInterval = null; | |
| let dataUsage = 0; | |
| let currentLocation = 'au'; | |
| let map; | |
| let markers = []; | |
| let activeMarker = null; | |
| let connectionCircle = null; | |
| // Server details with coordinates and flags | |
| const serverDetails = { | |
| 'us': { | |
| name: 'United States #12', | |
| ip: '104.18.23.156', | |
| coords: [37.0902, -95.7129], | |
| flag: 'https://flagcdn.com/us.svg' | |
| }, | |
| 'eu': { | |
| name: 'Europe #7', | |
| ip: '185.143.223.41', | |
| coords: [50.1109, 8.6821], | |
| flag: 'https://flagcdn.com/eu.svg' | |
| }, | |
| 'au': { | |
| name: 'Australia #23', | |
| ip: '192.168.23.45', | |
| coords: [-25.2744, 133.7751], | |
| flag: 'https://flagcdn.com/au.svg' | |
| }, | |
| 'asia': { | |
| name: 'Asia #9', | |
| ip: '45.67.89.123', | |
| coords: [35.8617, 104.1954], | |
| flag: 'https://flagcdn.com/cn.svg' | |
| }, | |
| 'ca': { | |
| name: 'Canada #5', | |
| ip: '172.16.31.90', | |
| coords: [56.1304, -106.3468], | |
| flag: 'https://flagcdn.com/ca.svg' | |
| }, | |
| 'uk': { | |
| name: 'UK #8', | |
| ip: '78.141.211.34', | |
| coords: [55.3781, -3.4360], | |
| flag: 'https://flagcdn.com/gb.svg' | |
| }, | |
| 'jp': { | |
| name: 'Japan #15', | |
| ip: '210.140.92.183', | |
| coords: [36.2048, 138.2529], | |
| flag: 'https://flagcdn.com/jp.svg' | |
| }, | |
| 'br': { | |
| name: 'Brazil #3', | |
| ip: '191.32.56.201', | |
| coords: [-14.2350, -51.9253], | |
| flag: 'https://flagcdn.com/br.svg' | |
| }, | |
| 'in': { | |
| name: 'India #11', | |
| ip: '115.241.91.12', | |
| coords: [20.5937, 78.9629], | |
| flag: 'https://flagcdn.com/in.svg' | |
| }, | |
| 'sg': { | |
| name: 'Singapore #6', | |
| ip: '203.116.223.15', | |
| coords: [1.3521, 103.8198], | |
| flag: 'https://flagcdn.com/sg.svg' | |
| }, | |
| 'de': { | |
| name: 'Germany #9', | |
| ip: '217.172.190.47', | |
| coords: [51.1657, 10.4515], | |
| flag: 'https://flagcdn.com/de.svg' | |
| }, | |
| 'fr': { | |
| name: 'France #4', | |
| ip: '176.31.128.1', | |
| coords: [46.2276, 2.2137], | |
| flag: 'https://flagcdn.com/fr.svg' | |
| }, | |
| 'nl': { | |
| name: 'Netherlands #7', | |
| ip: '82.192.84.116', | |
| coords: [52.1326, 5.2913], | |
| flag: 'https://flagcdn.com/nl.svg' | |
| }, | |
| 'se': { | |
| name: 'Sweden #2', | |
| ip: '31.15.32.10', | |
| coords: [60.1282, 18.6435], | |
| flag: 'https://flagcdn.com/se.svg' | |
| }, | |
| 'nz': { | |
| name: 'New Zealand #5', | |
| ip: '203.109.129.2', | |
| coords: [-40.9006, 174.8860], | |
| flag: 'https://flagcdn.com/nz.svg' | |
| } | |
| }; | |
| // Initialize map | |
| function initMap() { | |
| map = L.map('server-map').setView([20, 0], 2); | |
| L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { | |
| attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' | |
| }).addTo(map); | |
| // Add markers for each server location | |
| for (const [code, details] of Object.entries(serverDetails)) { | |
| const marker = L.circleMarker(details.coords, { | |
| radius: 8, | |
| fillColor: code === currentLocation ? '#10B981' : '#4F46E5', | |
| color: '#fff', | |
| weight: 2, | |
| opacity: 1, | |
| fillOpacity: 0.8 | |
| }).addTo(map); | |
| marker.on('click', () => { | |
| changeServerLocation(code); | |
| }); | |
| markers.push({ code, marker }); | |
| if (code === currentLocation) { | |
| activeMarker = marker; | |
| map.setView(details.coords, 4); | |
| } | |
| } | |
| // Create connection animation circle (hidden initially) | |
| connectionCircle = L.circle(serverDetails[currentLocation].coords, { | |
| color: '#3B82F6', | |
| fillColor: '#3B82F6', | |
| fillOpacity: 0.2, | |
| radius: 1000000 | |
| }).addTo(map); | |
| connectionCircle.setStyle({ opacity: 0 }); | |
| } | |
| // Initialize server buttons | |
| function initServerButtons() { | |
| for (const [code, details] of Object.entries(serverDetails)) { | |
| const button = document.createElement('button'); | |
| button.className = `px-4 py-2 bg-gray-100 rounded-full text-sm font-medium hover:bg-gray-200 transition server-btn ${code === currentLocation ? 'bg-blue-100 text-blue-700 hover:bg-blue-200' : ''}`; | |
| button.dataset.location = code; | |
| const flagSpan = document.createElement('span'); | |
| flagSpan.className = 'country-flag'; | |
| flagSpan.style.backgroundImage = `url(${details.flag})`; | |
| const textSpan = document.createElement('span'); | |
| textSpan.textContent = details.name.split(' #')[0]; | |
| button.appendChild(flagSpan); | |
| button.appendChild(textSpan); | |
| button.addEventListener('click', () => { | |
| changeServerLocation(code); | |
| }); | |
| serverButtonsContainer.appendChild(button); | |
| } | |
| } | |
| // Change server location | |
| function changeServerLocation(code) { | |
| currentLocation = code; | |
| const details = serverDetails[code]; | |
| // Update active marker | |
| markers.forEach(({ code: markerCode, marker }) => { | |
| if (markerCode === code) { | |
| marker.setStyle({ fillColor: '#10B981' }); | |
| activeMarker = marker; | |
| map.setView(details.coords, 4); | |
| } else { | |
| marker.setStyle({ fillColor: '#4F46E5' }); | |
| } | |
| }); | |
| // Update server details | |
| currentServer.textContent = details.name; | |
| serverIp.textContent = details.ip; | |
| // Update active button | |
| document.querySelectorAll('.server-btn').forEach(btn => { | |
| if (btn.dataset.location === code) { | |
| btn.classList.remove('bg-gray-100', 'hover:bg-gray-200'); | |
| btn.classList.add('bg-blue-100', 'text-blue-700', 'hover:bg-blue-200'); | |
| } else { | |
| btn.classList.remove('bg-blue-100', 'text-blue-700', 'hover:bg-blue-200'); | |
| btn.classList.add('bg-gray-100', 'hover:bg-gray-200'); | |
| } | |
| }); | |
| // If connected, show reconnecting animation | |
| if (isConnected) { | |
| connectionCircle.setStyle({ opacity: 0 }); | |
| setTimeout(() => { | |
| connectionCircle.setLatLng(details.coords); | |
| connectionCircle.setStyle({ opacity: 0.7 }); | |
| }, 300); | |
| } | |
| } | |
| // Toggle VPN Connection | |
| vpnToggle.addEventListener('click', () => { | |
| isConnected = !isConnected; | |
| if (isConnected) { | |
| // Connect | |
| vpnToggle.classList.add('active'); | |
| vpnToggle.querySelector('div').classList.add('translate-x-8'); | |
| connectionStatus.textContent = 'Connected'; | |
| connectionStatus.previousElementSibling.classList.remove('bg-gray-300'); | |
| connectionStatus.previousElementSibling.classList.add('bg-green-500'); | |
| // Show connection animation | |
| connectionCircle.setStyle({ opacity: 0.7 }); | |
| // Start connection timer | |
| connectionStartTime = new Date(); | |
| connectionInterval = setInterval(updateConnectionTime, 1000); | |
| // Simulate connection speeds | |
| simulateConnection(); | |
| } else { | |
| // Disconnect | |
| vpnToggle.classList.remove('active'); | |
| vpnToggle.querySelector('div').classList.remove('translate-x-8'); | |
| connectionStatus.textContent = 'Disconnected'; | |
| connectionStatus.previousElementSibling.classList.remove('bg-green-500'); | |
| connectionStatus.previousElementSibling.classList.add('bg-gray-300'); | |
| // Hide connection animation | |
| connectionCircle.setStyle({ opacity: 0 }); | |
| // Stop timers | |
| clearInterval(connectionInterval); | |
| connectionTime.textContent = '00:00:00'; | |
| // Reset speeds | |
| downloadSpeed.textContent = '0 Mbps'; | |
| uploadSpeed.textContent = '0 Mbps'; | |
| downloadSpeedometer.style.transform = 'rotate(45deg)'; | |
| uploadSpeedometer.style.transform = 'rotate(45deg)'; | |
| } | |
| }); | |
| // Update connection time | |
| function updateConnectionTime() { | |
| const now = new Date(); | |
| const diff = Math.floor((now - connectionStartTime) / 1000); | |
| const hours = Math.floor(diff / 3600); | |
| const minutes = Math.floor((diff % 3600) / 60); | |
| const seconds = diff % 60; | |
| connectionTime.textContent = | |
| `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; | |
| } | |
| // Simulate connection speeds and data transfer | |
| function simulateConnection() { | |
| let download = 0; | |
| let upload = 0; | |
| dataUsage = 0; | |
| const speedInterval = setInterval(() => { | |
| if (!isConnected) { | |
| clearInterval(speedInterval); | |
| return; | |
| } | |
| // Random speed fluctuations | |
| download = Math.min(100, Math.max(10, download + (Math.random() * 4 - 2))); | |
| upload = Math.min(40, Math.max(5, upload + (Math.random() * 2 - 1))); | |
| // Update speed displays | |
| downloadSpeed.textContent = `${download.toFixed(1)} Mbps`; | |
| uploadSpeed.textContent = `${upload.toFixed(1)} Mbps`; | |
| // Update speedometer visuals | |
| const downloadRotation = 45 + (download / 100 * 270); | |
| const uploadRotation = 45 + (upload / 40 * 270); | |
| downloadSpeedometer.style.transform = `rotate(${downloadRotation}deg)`; | |
| uploadSpeedometer.style.transform = `rotate(${uploadRotation}deg)`; | |
| // Update data transferred | |
| dataUsage += (download + upload) / 8 / 10; // Convert to MB | |
| dataTransferred.textContent = `${dataUsage.toFixed(1)} MB`; | |
| const progressPercent = Math.min(100, (dataUsage / 100) * 100); | |
| dataProgress.style.width = `${progressPercent}%`; | |
| }, 100); | |
| } | |
| // Initialize the app | |
| document.addEventListener('DOMContentLoaded', () => { | |
| initMap(); | |
| initServerButtons(); | |
| // Set initial server details | |
| currentServer.textContent = serverDetails[currentLocation].name; | |
| serverIp.textContent = serverDetails[currentLocation].ip; | |
| }); | |
| </script> | |
| </html> |