document.addEventListener('DOMContentLoaded', function() { const radarCanvas = document.getElementById('radarCanvas'); if (radarCanvas) { updateRadarData(); setInterval(updateRadarData, 5000); // Update every 5 seconds } }); function updateRadarData() { fetch('api/get_radar_data.php') .then(response => response.json()) .then(data => { if (data && !data.error) { const feeds = data; checkProximity(feeds, 0.5); drawRadar(feeds); updateObjectsTable(feeds); } else { console.error('Error fetching radar data:', data ? data.error : 'No data received'); } }) .catch(error => { console.error('Failed to fetch or parse radar data:', error); }); } function toCartesian(angle, distance, canvas) { const centerX = canvas.width / 2; const centerY = canvas.height / 2; const maxCanvasDistance = Math.min(centerX, centerY) * 0.9; const MAX_REAL_WORLD_METERS = 5; const distanceInMeters = distance / 100; const normalizedDistance = (distanceInMeters / MAX_REAL_WORLD_METERS) * maxCanvasDistance; const angleRad = (angle - 90) * (Math.PI / 180); const x = centerX + normalizedDistance * Math.cos(angleRad); const y = centerY + normalizedDistance * Math.sin(angleRad); return { x, y }; } function updateObjectsTable(feeds) { const tableBody = document.getElementById('objectsTableBody'); if (!tableBody) return; tableBody.innerHTML = ''; feeds.forEach((feed, index) => { const row = document.createElement('tr'); row.style.animation = `fadeIn 0.5s ease-in-out ${index * 0.1}s both`; const idCell = document.createElement('td'); idCell.textContent = feed.entry_id; row.appendChild(idCell); const distanceCell = document.createElement('td'); const distanceInMeters = parseFloat(feed.field2) / 100; distanceCell.textContent = distanceInMeters.toFixed(2); row.appendChild(distanceCell); const angleCell = document.createElement('td'); angleCell.textContent = parseFloat(feed.field1).toFixed(2); row.appendChild(angleCell); const timeCell = document.createElement('td'); timeCell.textContent = new Date(feed.created_at).toLocaleTimeString(); row.appendChild(timeCell); tableBody.appendChild(row); }); } function checkProximity(feeds, distanceThreshold) { const alertElement = document.getElementById('proximityAlert'); const distanceElement = document.getElementById('closestDistance'); if (!alertElement || !distanceElement) return; let minDistance = Infinity; let isClose = false; feeds.forEach(feed => { const distanceInMeters = parseFloat(feed.field2) / 100; if (distanceInMeters < minDistance) { minDistance = distanceInMeters; } if (distanceInMeters < distanceThreshold) { isClose = true; } }); if (isClose) { distanceElement.textContent = minDistance.toFixed(2); alertElement.classList.remove('d-none'); } else { alertElement.classList.add('d-none'); } } function drawRadar(feeds) { const canvas = document.getElementById('radarCanvas'); if(!canvas) return; const ctx = canvas.getContext('2d'); const width = canvas.width; const height = canvas.height; const centerX = width / 2; const centerY = height / 2; const maxDistance = Math.min(centerX, centerY) * 0.9; ctx.fillStyle = '#0b1220'; ctx.fillRect(0, 0, width, height); ctx.strokeStyle = 'rgba(0, 255, 213, 0.3)'; ctx.lineWidth = 1; for (let i = 1; i <= 4; i++) { ctx.beginPath(); ctx.arc(centerX, centerY, maxDistance * (i / 4), 0, 2 * Math.PI); ctx.stroke(); } ctx.beginPath(); ctx.moveTo(centerX, 0); ctx.lineTo(centerX, height); ctx.moveTo(0, centerY); ctx.lineTo(width, centerY); ctx.stroke(); feeds.forEach((feed, index) => { const angle = parseFloat(feed.field1); const distance = parseFloat(feed.field2); if (!isNaN(angle) && !isNaN(distance)) { const { x, y } = toCartesian(angle, distance, canvas); // Animation let radius = 0; let alpha = 0; const targetRadius = 5; const animationDuration = 500; const startTime = Date.now(); function animateDot() { const elapsedTime = Date.now() - startTime; const progress = Math.min(elapsedTime / animationDuration, 1); radius = targetRadius * progress; alpha = progress; ctx.fillStyle = `rgba(33, 150, 243, ${alpha})`; ctx.beginPath(); ctx.arc(x, y, radius, 0, 2 * Math.PI); ctx.fill(); if (progress < 1) { requestAnimationFrame(animateDot); } } setTimeout(animateDot, index * 100); } }); } (function () { 'use strict' var forms = document.querySelectorAll('.needs-validation') Array.prototype.slice.call(forms) .forEach(function (form) { form.addEventListener('submit', function (event) { if (!form.checkValidity()) { event.preventDefault() event.stopPropagation() } form.classList.add('was-validated') }, false) }) })();