master @ 43 LINES
[ HISTORY ] [ UP ]
┌─ TS ───────────────────────────────────────────────────────────────────────┐
│ // Horizontal bar chart: │
│ // ENTROPY ████████████████░░░░░░░░ 12 │
│ import { checkGrid, len, pad } from "../../lib/ascii"; │
│ │
│ export interface BarItem { │
│ label: string; │
│ value: number; │
│ } │
│ │
│ export interface Props { │
│ items: BarItem[]; │
│ /** Label column cells; longer labels truncate with .... */ │
│ labelW?: number; │
│ /** Scale ceiling; defaults to the largest value. */ │
│ max?: number; │
│ } │
│ │
│ export function buildBarChart( │
│ items: BarItem[], │
│ width: number, │
│ { labelW = 12, max }: Omit<Props, "items"> = {}, │
│ ): string { │
│ if (!items.length) return ""; │
│ const top = max ?? Math.max(...items.map((i) => i.value)); │
│ const valueW = Math.max(...items.map((i) => len(String(i.value)))); │
│ const barW = width - labelW - valueW - 2; │
│ if (barW < 4) { │
│ throw new Error(`[ascii] bar chart needs ${labelW + valueW + 6} cells, got ${w │
│ idth}`); │
│ } │
│ return items │
│ .map((it) => { │
│ const label = │
│ len(it.label) > labelW │
│ ? [...it.label].slice(0, labelW - 3).join("") + "..." │
│ : it.label; │
│ const filled = top <= 0 ? 0 : Math.round((Math.max(0, it.value) / top) * bar │
│ W); │
│ const bar = "█".repeat(filled) + "░".repeat(barW - filled); │
│ const line = pad(label, labelW) + bar + " " + pad(String(it.value), valueW, │
│ "start"); │
│ return checkGrid(line, width, "bar chart row"); │
│ }) │
│ .join("\n"); │
│ } │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─ TS ─────────────────────────────────┐
│ // Horizontal bar chart: │
│ // ENTROPY ████████████████░░░░░░░░ 12 │
│ import { checkGrid, len, pad } from "../../l │
│ ib/ascii"; │
│ │
│ export interface BarItem { │
│ label: string; │
│ value: number; │
│ } │
│ │
│ export interface Props { │
│ items: BarItem[]; │
│ /** Label column cells; longer labels trun │
│ cate with .... */ │
│ labelW?: number; │
│ /** Scale ceiling; defaults to the largest │
│ value. */ │
│ max?: number; │
│ } │
│ │
│ export function buildBarChart( │
│ items: BarItem[], │
│ width: number, │
│ { labelW = 12, max }: Omit<Props, "items"> │
│ = {}, │
│ ): string { │
│ if (!items.length) return ""; │
│ const top = max ?? Math.max(...items.map(( │
│ i) => i.value)); │
│ const valueW = Math.max(...items.map((i) = │
│ > len(String(i.value)))); │
│ const barW = width - labelW - valueW - 2; │
│ if (barW < 4) { │
│ throw new Error(`[ascii] bar chart needs │
│ ${labelW + valueW + 6} cells, got ${width}` │
│ ); │
│ } │
│ return items │
│ .map((it) => { │
│ const label = │
│ len(it.label) > labelW │
│ ? [...it.label].slice(0, labelW - │
│ 3).join("") + "..." │
│ : it.label; │
│ const filled = top <= 0 ? 0 : Math.rou │
│ nd((Math.max(0, it.value) / top) * barW); │
│ const bar = "█".repeat(filled) + "░".r │
│ epeat(barW - filled); │
│ const line = pad(label, labelW) + bar │
│ + " " + pad(String(it.value), valueW, "star │
│ t"); │
│ return checkGrid(line, width, "bar cha │
│ rt row"); │
│ }) │
│ .join("\n"); │
│ } │
└──────────────────────────────────────────────┘
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET