UNPKG

agentscape

Version:

Agentscape is a library for creating agent-based simulations. It provides a simple API for defining agents and their behavior, and for defining the environment in which the agents interact. Agentscape is designed to be flexible and extensible, allowing

91 lines (78 loc) 2.96 kB
import ChartJS, { ChartConfiguration } from 'chart.js/auto' export interface HistogramConstructor { root: HTMLElement axisLabels?: { x: string, y: string } title?: string width?: number } export default class Histogram { private chart: ChartJS<'bar', number[]> private width: number constructor(opts: HistogramConstructor) { this.width = opts.width || 400 const title = opts.title || 'Histogram' const axisLabels = opts.axisLabels || { x: 'Bins', y: 'Frequency' } const canvas = document.createElement('canvas') const draggable = document.createElement('drag-pane') draggable.setAttribute('heading', title ) draggable.setAttribute('key', title) draggable.appendChild(canvas) opts.root.appendChild(draggable) canvas.width = this.width const defaultChartOptions: ChartConfiguration<'bar', number[]> = { type: 'bar', data: { labels: [], datasets: [{ label: title, data: [], backgroundColor: 'rgba(54, 162, 235, 0.2)', borderColor: 'rgba(54, 162, 235, 1)', borderWidth: 1 }] }, options: { scales: { x: { title: { display: true, text: axisLabels.x } }, y: { title: { display: true, text: axisLabels.y }, beginAtZero: true } } } } this.chart = new ChartJS<'bar', number[]>(canvas, defaultChartOptions) } public applyData(data: number[], binSize: number): void { const { bins, frequencies } = this.calculateBins(data, binSize) this.chart.data.labels = bins this.chart.data.datasets[0].data = frequencies this.chart.update() } private calculateBins(data: number[], binSize: number): { bins: number[], frequencies: number[] } { const max = Math.max(...data) const min = Math.min(...data) // `bins` used as labels for the chart const bins = [] const frequencies = [] // gets the precision of the bin size float const precision = binSize.toString().split('.')[1]?.length || 1 for (let start = min; start <= max; start += binSize) { bins.push(`${+(start).toFixed(precision)}-${ +(start + binSize).toFixed(precision)}`) frequencies.push(0) } data.forEach(value => { const binIndex = Math.floor((value - min) / binSize) frequencies[binIndex]++ }) return { bins, frequencies } } }