| |
| let ecgData = []; |
| let bpmHistory = []; |
| let historyRecords = []; |
| let isPaused = false; |
| let updateInterval; |
| let ecgChart; |
|
|
| |
| document.addEventListener('DOMContentLoaded', function() { |
| initializeChart(); |
| startMonitoring(); |
| setupEventListeners(); |
| }); |
|
|
| function initializeChart() { |
| const ctx = document.getElementById('ecgChart').getContext('2d'); |
| |
| ecgChart = new Chart(ctx, { |
| type: 'line', |
| data: { |
| labels: Array(100).fill(''), |
| datasets: [{ |
| label: 'ECG', |
| data: Array(100).fill(0), |
| borderColor: '#EF4444', |
| borderWidth: 2, |
| tension: 0.1, |
| pointRadius: 0 |
| }] |
| }, |
| options: { |
| responsive: true, |
| maintainAspectRatio: false, |
| scales: { |
| y: { |
| min: -2, |
| max: 2, |
| display: false |
| }, |
| x: { |
| display: false |
| } |
| }, |
| animation: { |
| duration: 0 |
| }, |
| plugins: { |
| legend: { |
| display: false |
| } |
| } |
| } |
| }); |
| } |
|
|
| function startMonitoring() { |
| |
| generateInitialData(); |
| |
| |
| updateInterval = setInterval(updateECGData, 1000); |
| } |
|
|
| function generateInitialData() { |
| |
| for (let i = 0; i < 100; i++) { |
| ecgData.push(generateECGPoint(i)); |
| } |
| updateChart(); |
| } |
|
|
| function generateECGPoint(index) { |
| |
| const position = index % 100; |
| |
| |
| if (position > 90) { |
| return 0.2 + Math.random() * 0.1; |
| } else if (position > 80) { |
| return -0.5 - Math.random() * 0.2; |
| } else if (position > 70) { |
| return 1.5 + Math.random() * 0.3; |
| } else if (position > 60) { |
| return -0.8 - Math.random() * 0.2; |
| } else if (position > 50) { |
| return 0.3 + Math.random() * 0.1; |
| } else { |
| |
| return (Math.random() - 0.5) * 0.2; |
| } |
| } |
|
|
| function updateECGData() { |
| if (isPaused) return; |
| |
| |
| ecgData.shift(); |
| ecgData.push(generateECGPoint(Math.floor(Math.random() * 100))); |
| |
| |
| updateChart(); |
| |
| |
| const bpm = 60 + Math.floor(Math.random() * 60); |
| updateBPM(bpm); |
| |
| |
| const isIrregular = Math.random() < 0.1; |
| updateIrregularityStatus(isIrregular, bpm); |
| |
| |
| addToHistory(bpm, isIrregular); |
| |
| |
| updateStats(); |
| } |
|
|
| function updateChart() { |
| ecgChart.data.datasets[0].data = ecgData; |
| ecgChart.update(); |
| } |
|
|
| function updateBPM(bpm) { |
| document.getElementById('bpmDisplay').textContent = bpm; |
| document.getElementById('currentBpm').textContent = bpm; |
| bpmHistory.push(bpm); |
| |
| |
| if (bpmHistory.length > 100) { |
| bpmHistory.shift(); |
| } |
| } |
|
|
| function updateIrregularityStatus(isIrregular, bpm) { |
| const statusElement = document.getElementById('irregularityStatus'); |
| const heartStatus = document.getElementById('heartStatus'); |
| |
| if (isIrregular) { |
| statusElement.innerHTML = ` |
| <i data-feather="alert-circle" class="inline mr-2"></i> |
| <span>Irregular heartbeat detected (${bpm} BPM)</span> |
| `; |
| statusElement.className = 'text-center py-4 px-6 rounded-lg irregular mb-4'; |
| heartStatus.innerHTML = ` |
| <span class="h-4 w-4 rounded-full bg-yellow-500 animate-pulse mr-2"></span> |
| <span class="text-gray-600">Irregular</span> |
| `; |
| } else { |
| statusElement.innerHTML = ` |
| <i data-feather="check-circle" class="inline mr-2"></i> |
| <span>Regular heartbeat (${bpm} BPM)</span> |
| `; |
| statusElement.className = 'text-center py-4 px-6 rounded-lg regular mb-4'; |
| heartStatus.innerHTML = ` |
| <span class="h-4 w-4 rounded-full bg-green-500 animate-pulse mr-2"></span> |
| <span class="text-gray-600">Regular</span> |
| `; |
| } |
| feather.replace(); |
| } |
|
|
| function addToHistory(bpm, isIrregular) { |
| const now = new Date(); |
| const timeString = now.toLocaleTimeString(); |
| |
| historyRecords.unshift({ |
| time: timeString, |
| bpm: bpm, |
| isIrregular: isIrregular, |
| timestamp: now.getTime() |
| }); |
| |
| |
| if (historyRecords.length > 50) { |
| historyRecords.pop(); |
| } |
| |
| updateHistoryTable(); |
| } |
|
|
| function updateHistoryTable() { |
| const tableBody = document.getElementById('historyTable'); |
| tableBody.innerHTML = ''; |
| |
| historyRecords.forEach(record => { |
| const row = document.createElement('tr'); |
| |
| row.innerHTML = ` |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${record.time}</td> |
| <td class="px-6 py-4 whitespace-nowrap text-sm font-medium ${record.isIrregular ? 'text-yellow-600' : 'text-gray-900'}">${record.bpm}</td> |
| <td class="px-6 py-4 whitespace-nowrap text-sm"> |
| <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${record.isIrregular ? 'bg-yellow-100 text-yellow-800' : 'bg-green-100 text-green-800'}"> |
| ${record.isIrregular ? 'Irregular' : 'Regular'} |
| </span> |
| </td> |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"> |
| <button class="text-blue-500 hover:text-blue-700"> |
| <i data-feather="info" class="w-4 h-4"></i> |
| </button> |
| </td> |
| `; |
| |
| tableBody.appendChild(row); |
| }); |
| |
| feather.replace(); |
| } |
|
|
| function updateStats() { |
| if (bpmHistory.length === 0) return; |
| |
| const sum = bpmHistory.reduce((a, b) => a + b, 0); |
| const avg = Math.round(sum / bpmHistory.length); |
| const min = Math.min(...bpmHistory); |
| const max = Math.max(...bpmHistory); |
| |
| document.getElementById('averageBpm').textContent = avg; |
| document.getElementById('minBpm').textContent = min; |
| document.getElementById('maxBpm').textContent = max; |
| |
| |
| const irregularCount = historyRecords.filter(r => r.isIrregular).length; |
| document.getElementById('irregularBeats').textContent = irregularCount; |
| |
| |
| const lastIrregular = historyRecords.find(r => r.isIrregular); |
| if (lastIrregular) { |
| document.getElementById('lastIrregularity').textContent = lastIrregular.time; |
| } |
| } |
|
|
| function setupEventListeners() { |
| |
| document.getElementById('pauseBtn').addEventListener('click', function() { |
| isPaused = !isPaused; |
| this.innerHTML = isPaused ? |
| '<i data-feather="play"></i> Resume' : |
| '<i data-feather="pause"></i> Pause'; |
| feather.replace(); |
| }); |
| |
| |
| document.getElementById('exportBtn').addEventListener('click', function() { |
| alert('Data exported successfully!'); |
| }); |
| |
| |
| document.getElementById('clearBtn').addEventListener('click', function() { |
| if (confirm('Are you sure you want to clear all history?')) { |
| historyRecords = []; |
| bpmHistory = []; |
| updateHistoryTable(); |
| updateStats(); |
| } |
| }); |
| } |