Anomalies Detected
${anomalies.length}
Highest Risk Category
${highestRiskCat}
`;
}
function renderScatterPlot(data) {
const chartData = data.map(row => ({ x: row.timestamp, y: row.amount_usd, isAnomaly: row.isAnomaly }));
const renderChart = (id, type, chartData, options) => {
const ctx = document.getElementById(id)?.getContext('2d');
if(!ctx) return;
if(charts[id]) charts[id].destroy();
charts[id] = new Chart(ctx, { type, data: chartData, options });
};
renderChart('finanom-scatter-chart', 'scatter', {
datasets: [{
label: 'Transactions',
data: chartData,
backgroundColor: chartData.map(d => d.isAnomaly ? 'rgba(220, 38, 38, 0.7)' : 'rgba(37, 99, 235, 0.5)'),
radius: chartData.map(d => d.isAnomaly ? 8 : 4),
hoverRadius: chartData.map(d => d.isAnomaly ? 10 : 6),
}]
}, {
responsive: true, maintainAspectRatio: false,
plugins: { legend: { display: false } },
scales: {
x: { type: 'time', time: { unit: 'day' }, title: { display: true, text: 'Timestamp' } },
y: { type: 'logarithmic', title: { display: true, text: 'Transaction Amount (USD)' } }
}
});
}
function renderAnomaliesTable(anomalies) {
anomalies.sort((a,b) => b.zScore - a.zScore);
elements.anomaliesTbody.innerHTML = anomalies.map(row => `
| ${new Date(row.timestamp).toLocaleString()} |
${row.merchant_name} |
${row.merchant_category} |
${new Intl.NumberFormat('en-US',{style:'currency',currency:'USD'}).format(row.amount_usd)} |
${row.zScore.toFixed(2)} |
`).join('') || `
| No anomalies detected at this threshold. |
`;
}
window.finanomDownloadPDF = () => {
html2canvas(document.getElementById('finanom-pdf-content'), { scale: 2 }).then(canvas => {
const pdf = new jspdf.jsPDF({ orientation: 'landscape', unit: 'pt', format: 'a4' });
pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 40, 40, pdf.internal.pageSize.getWidth() - 80, 0);
pdf.save('Financial_Anomaly_Report.pdf');
});
};
loadSampleData();
});