Skip to content

Instantly share code, notes, and snippets.

@artisonian
Last active January 24, 2020 01:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save artisonian/eacfdf51e9b71e962bce1dfa225e4d8f to your computer and use it in GitHub Desktop.
Save artisonian/eacfdf51e9b71e962bce1dfa225e4d8f to your computer and use it in GitHub Desktop.
Deno port of spark - https://github.com/holman/spark
/**
* spark - https://github.com/holman/spark
*
* The MIT License
* Copyright (c) Zach Holman, https://zachholman.com
*/
import { parse } from "https://deno.land/std@v0.30.0/flags/mod.ts";
export function spark(...nums: number[]): string {
let min = Infinity;
let max = 0;
for (const n of nums) {
if (n < min) {
min = n;
}
if (n > max) {
max = n;
}
}
let ticks = ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"];
if (min === max) {
ticks = ["▅", "▆"];
}
let f = ((max - min) << 8) / (ticks.length - 1);
if (f < 1) {
f = 1;
}
return nums.map(n => ticks[(((n - min) << 8) / f) | 0]).join("");
}
if (import.meta.main) {
main();
}
async function main() {
const args = parse(Deno.args, {
boolean: ["help"],
alias: {
help: ["h"]
}
});
if ((Deno.isTTY().stdin && !args._.length) || args.h || args.help) {
printUsage();
Deno.exit(0);
}
if (!Deno.isTTY().stdin) {
const input = await Deno.readAll(Deno.stdin);
args._ = [new TextDecoder().decode(input)];
}
let nums = [] as number[];
for (const arg of args._) {
const ns = arg.split(/[\s,]+/).map(n => +n | 0);
nums = nums.concat(ns);
}
console.log(spark(...nums));
function printUsage() {
console.error(`USAGE:
spark [-h|--help] VALUE,...
EXAMPLES:
spark 1 5 22 13 53
▁▁▃▂█
spark 0,30,55,80,33,150
▁▂▃▄▂█
echo 9 13 5 17 1 | spark
▄▆▂█▁`);
}
}
import {
test,
assert,
assertEquals
} from "https://deno.land/std@v0.30.0/testing/mod.ts";
test(async function it_shows_help_with_no_argv() {
const { code, err } = await graph();
assertEquals(code, 0);
assert(err.includes("USAGE"));
});
test(async function it_graphs_argv_data() {
const { out } = await graph("1,5,22,13,5");
assertEquals(out, "▁▂█▅▂\n");
});
test(async function it_charts_pipe_data() {
const { out } = await graph("0,30,55,80,33,150", { pipe: true });
assertEquals(out, "▁▂▃▄▂█\n");
});
test(async function it_charts_spaced_data() {
const { out } = await graph("0 30 55 80 33 150");
assertEquals(out, "▁▂▃▄▂█\n");
});
test(async function it_charts_way_spaced_data() {
const { out } = await graph("0 30 55 80 33 150");
assertEquals(out, "▁▂▃▄▂█\n");
});
test(async function it_handles_decimals() {
const { out } = await graph("5.5,20");
assertEquals(out, "▁█\n");
});
test(async function it_charts_100_lt_300() {
const { out } = await graph("1,2,3,4,100,5,10,20,50,300");
assertEquals(out, "▁▁▁▁▃▁▁▁▂█\n");
});
test(async function it_charts_50_lt_100() {
const { out } = await graph("1,50,100");
assertEquals(out, "▁▄█\n");
});
test(async function it_charts_4_lt_8() {
const { out } = await graph("2,4,8");
assertEquals(out, "▁▃█\n");
});
test(async function it_charts_no_tier_0() {
const { out } = await graph("1,2,3,4,5");
assertEquals(out, "▁▂▄▆█\n");
});
test(async function it_equalizes_at_midtier_on_same_data() {
const { out } = await graph("1,1,1,1");
assertEquals(out, "▅▅▅▅\n");
});
// Test util
const __SCRIPT__ = import.meta.url.replace("_test", "");
const decoder = new TextDecoder();
const encoder = new TextEncoder();
async function graph(
data?: string,
{ pipe = false } = {}
): Promise<{ code: number; out: string; err: string }> {
const args = ["deno", "run", __SCRIPT__];
if (!pipe && data) {
args.push(data);
}
const p = Deno.run({
args,
stdin: pipe ? "piped" : "inherit",
stdout: "piped",
stderr: "piped"
});
if (pipe) {
await p.stdin.write(encoder.encode(data));
p.stdin.close();
}
const { code } = await p.status();
const out = decoder.decode(await p.output());
const err = decoder.decode(await p.stderrOutput());
p.close();
return { code, out, err };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment