(times: number[])
| 1861 | } |
| 1862 | |
| 1863 | function generateResponseTimeHistogram(times: number[]): string { |
| 1864 | if (times.length === 0) return '<p class="empty">No response time data</p>' |
| 1865 | |
| 1866 | // Create buckets (matching Python reference) |
| 1867 | const buckets: Record<string, number> = { |
| 1868 | '2-10s': 0, |
| 1869 | '10-30s': 0, |
| 1870 | '30s-1m': 0, |
| 1871 | '1-2m': 0, |
| 1872 | '2-5m': 0, |
| 1873 | '5-15m': 0, |
| 1874 | '>15m': 0, |
| 1875 | } |
| 1876 | |
| 1877 | for (const t of times) { |
| 1878 | if (t < 10) buckets['2-10s'] = (buckets['2-10s'] ?? 0) + 1 |
| 1879 | else if (t < 30) buckets['10-30s'] = (buckets['10-30s'] ?? 0) + 1 |
| 1880 | else if (t < 60) buckets['30s-1m'] = (buckets['30s-1m'] ?? 0) + 1 |
| 1881 | else if (t < 120) buckets['1-2m'] = (buckets['1-2m'] ?? 0) + 1 |
| 1882 | else if (t < 300) buckets['2-5m'] = (buckets['2-5m'] ?? 0) + 1 |
| 1883 | else if (t < 900) buckets['5-15m'] = (buckets['5-15m'] ?? 0) + 1 |
| 1884 | else buckets['>15m'] = (buckets['>15m'] ?? 0) + 1 |
| 1885 | } |
| 1886 | |
| 1887 | const maxVal = Math.max(...Object.values(buckets)) |
| 1888 | if (maxVal === 0) return '<p class="empty">No response time data</p>' |
| 1889 | |
| 1890 | return Object.entries(buckets) |
| 1891 | .map(([label, count]) => { |
| 1892 | const pct = (count / maxVal) * 100 |
| 1893 | return `<div class="bar-row"> |
| 1894 | <div class="bar-label">${label}</div> |
| 1895 | <div class="bar-track"><div class="bar-fill" style="width:${pct}%;background:#6366f1"></div></div> |
| 1896 | <div class="bar-value">${count}</div> |
| 1897 | </div>` |
| 1898 | }) |
| 1899 | .join('\n') |
| 1900 | } |
| 1901 | |
| 1902 | function generateTimeOfDayChart(messageHours: number[]): string { |
| 1903 | if (messageHours.length === 0) return '<p class="empty">No time data</p>' |
no test coverage detected