make plootxt draw an empty grid - ploot - simple plotting tools HTML git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ploot DIR Log DIR Files DIR Refs DIR Tags DIR README DIR LICENSE --- DIR commit 97913fd518557ed58a07f52204fef1271af2bb32 DIR parent 817580dbf249b75e747cc81f56f930d80600c59e HTML Author: Josuah Demangeon <mail@josuah.net> Date: Mon, 7 May 2018 01:10:39 +0200 make plootxt draw an empty grid Diffstat: M ploot.c | 2 ++ M plootxt.c | 199 +++++++++++++++++++------------ A test.csv | 30 ++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 74 deletions(-) --- DIR diff --git a/ploot.c b/ploot.c @@ -110,6 +110,8 @@ read_values(Vlist *v, int ncol) bufsize = 0; for (nval = 0; esfgets(line, sizeof(line), stdin) != NULL; nval++) bufsize = add_row(v, bufsize, ncol, nval, line); + if (nval == 0) + fputs("no value could be read\n", stderr), exit(1); } static void DIR diff --git a/plootxt.c b/plootxt.c @@ -12,72 +12,46 @@ #define LEN(x) (sizeof(x) / sizeof(*x)) #define WIDTH_MAX 1024 +#define BRAILLE_START 10240 -int screenwidth = 80; +int wflag = 80; char *argv0; -static void -usage(void) -{ - fprintf(stderr, "usage: %s <csv\n", argv0); - exit(1); -} - -void -fmt_labels(char out[LINE_MAX], int ncol, char *labels[LINE_MAX / 2]) -{ - int i, w; - - w = screenwidth / ncol; - for (i = 0; i < ncol; labels++, i++) - out += snprintf(out, w - 1, " %.*s", w - 1, *labels); -} - /* - * Label must be able to store all pointers to token buf has to - * offer: sizeof(*buf / 2). + * Turn the bit at position (row, col) on in the . */ -static int -read_labels(char out[LINE_MAX]) +static void +plot_dot(long *out, int row, int col) { - int ncol; - char *l, line[LINE_MAX], *labels[LINE_MAX / 2], *tok; - - l = line; - if (esfgets(line, LINE_MAX, stdin) == NULL) - fputs("missing label line\n", stderr), exit(1); - - if (strcmp(strsep(&l, ","), "epoch") != 0) - fputs("first label must be \"epoch\"\n", stderr), exit(1); - - for (ncol = 1; (tok = strsep(&l, ",")) != NULL; ncol++) - *labels = tok; - *labels = NULL; - - if (ncol < 2) - fputs("no label found\n", stderr), exit(1); - - fmt_labels(out, ncol, labels); - - return ncol; + long flags[4][2] = { + { 0x01, 0x08 }, + { 0x02, 0x10 }, + { 0x04, 0x20 }, + { 0x40, 0x80 }, + }, f; + + f = flags[row][col]; + puts("."), fflush(stdout); + *out |= f; } -void -plot_val(char *out, double val, int nrow, int width) +static void +plot_val(long *out, double val, double max, int row, int width) { - (void)val; - (void)out; - (void)nrow; - (void)width; + int col; + + col = (int)((double)(val * width * 2) / max); + for (; col > 0; out++, col--) + plot_dot(out + col / 2, row, col % 2); } /* * Change the braille characters on a whole row, this for all the * values line. */ -time_t -plot_row(char *out, char *line, int nrow, int ncol, int width) +static time_t +plot_row(long *out, char *line, double *max, int nrow, int ncol, int width) { time_t epoch; double val; @@ -88,11 +62,11 @@ plot_row(char *out, char *line, int nrow, int ncol, int width) fputs("*** missing epoch value\n", stderr), exit(1); epoch = eatol(tok); - for (n = 1; (tok = strsep(&line, ",")) != NULL; n++) { + for (n = 0; (tok = strsep(&line, ",")) != NULL; n++) { if (n >= ncol) fputs("too many values\n", stderr), exit(1); val = eatof(tok); - plot_val(out + n * width, nrow, val, width); + plot_val(out + n * width, max[n - 1], nrow, val, width); } if (n < ncol) fputs("not enough values\n", stderr), exit(1); @@ -103,23 +77,27 @@ plot_row(char *out, char *line, int nrow, int ncol, int width) /* * Read enough input in order to print one line and plot it into 'out'. */ -time_t -plot_line(char *out, int ncol, int width) +static time_t +plot_line(long *out, double *max, int ncol, int width) { time_t epoch; - int nrow; + int n, nrow; + long *o, rune; char line[LINE_MAX]; + for (rune = BRAILLE_START, o = out, n = ncol * width; n > 0; o++, n--) + memcpy(o, &rune, sizeof(rune)); + *o = '\0'; for (nrow = 0; nrow < 4; nrow++) { if ((esfgets(line, LINE_MAX, stdin)) == NULL) exit(0); - epoch = plot_row(out, line, nrow, ncol, width); + epoch = plot_row(out, line, max, nrow, ncol, width); } return epoch; } -void +static void put_time(time_t epoch, time_t last, int nline) { char *out, buf[sizeof("XXxXXxXX |")]; @@ -141,48 +119,121 @@ put_time(time_t epoch, time_t last, int nline) fputs(out, stdout); } -void -plot(char labels[LINE_MAX], int ncol) +static void +print_utf8_3bytes(long rune) +{ + putchar((char)(0xe0 | (0x0f & (rune >> 12)))); /* 1110xxxx */ + putchar((char)(0x80 | (0x3f & (rune >> 6)))); /* 10xxxxxx */ + putchar((char)(0x80 | (0x3f & (rune)))); /* 10xxxxxx */ +} + +static void +put_line(long *out) +{ + for (; *out != '\0'; out++) + print_utf8_3bytes(*out); + putchar('|'); + putchar('\n'); +} + +static void +plot(char labels[LINE_MAX], double *max, int ncol) { time_t epoch, last_epoch; + long out[WIDTH_MAX + 1]; int n, width; - char out[WIDTH_MAX * 3 + 1]; - width = screenwidth / ncol; + width = (wflag - sizeof("XXxXXxXX _|")) / ncol - sizeof("|"); last_epoch = epoch = 0; - for (n = 0;; n++) { - if (n >= 20) { - puts(labels); - n = 0; - } + for (n = 0;; n = n == 20 ? 0 : n + 1) { + if (n == 0) + put_time(0, 0, 2), puts(labels); - epoch = plot_line(out, ncol, width); + epoch = plot_line(out, max, ncol, width); put_time(epoch, last_epoch, n); last_epoch = epoch; - puts(out); + put_line(out); fflush(stdout); } } -void -parse_args(int argc, char **argv) +static void +fmt_labels(char out[LINE_MAX], int ncol, char *labels[LINE_MAX / 2]) +{ + int i, w; + + w = wflag / ncol; + for (i = 0; i < ncol; labels++, i++) + out += snprintf(out, w - 1, " %.*s", w - 1, *labels); +} + +/* + * Label must be able to store all pointers to token buf has to + * offer: sizeof(*buf / 2). + */ +static int +read_labels(char out[LINE_MAX]) +{ + int ncol; + char *l, line[LINE_MAX], **lab, *labels[LINE_MAX / 2], *tok; + + if ((l = esfgets(line, LINE_MAX, stdin)) == NULL) + fputs("missing label line\n", stderr), exit(1); + + if (strcmp(strsep(&l, ","), "epoch") != 0) + fputs("first label must be \"epoch\"\n", stderr), exit(1); + + lab = labels; + for (ncol = 0; (tok = strsep(&l, ",")) != NULL; ncol++, lab++) + *lab = tok; + *lab = NULL; + + if (ncol < 1) + fputs("no label found\n", stderr), exit(1); + + fmt_labels(out, ncol, labels); + + return ncol; +} + +static void +usage(void) { + fprintf(stderr, "usage: %s maxval... <csv\n", argv0); + exit(1); +} + +static int +parse_args(int argc, char **argv, double *max) +{ + int n; + argv0 = *argv; - if (argc != 1) + argv++, argc--; + + if (argc == 0) usage(); + + for (n = argc; n > 0; n--, argv++, max++) + *max = eatof(*argv); + + return argc; } int main(int argc, char **argv) { + double max[LINE_MAX / 2]; + int ncol, nmax; char labels[LINE_MAX]; - int ncol; - parse_args(argc, argv); + nmax = parse_args(argc, argv, max); ncol = read_labels(labels); - plot(labels, ncol); + if (ncol != nmax) + fputs("not as many labels and arguments\n", stderr), exit(0); + plot(labels, max, ncol); return 0; } DIR diff --git a/test.csv b/test.csv @@ -0,0 +1,30 @@ +epoch,value +1525186140,34.691934 +1525187040,34.405857 +1525187940,32.498299 +1525188840,27.619718 +1525189740,30.942743 +1525190640,32.813887 +1525191540,32.230595 +1525192440,30.917799 +1525193340,31.829373 +1525194240,30.912565 +1525195140,32.899966 +1525196040,31.234834 +1525196940,31.196973 +1525197840,30.626265 +1525198740,30.734170 +1525199640,29.900881 +1525200540,28.375837 +1525201440,28.976500 +1525202340,27.949893 +1525203240,26.158816 +1525204140,23.383114 +1525205040,26.615605 +1525205940,30.636621 +1525206840,28.831401 +1525207740,29.878943 +1525208640,22.641583 +1525209540,30.158785 +1525210440,30.718469 +1525211340,30.369028