URI: 
       ploot-braille.c - 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
       ---
       ploot-braille.c (4040B)
       ---
            1 #include <assert.h>
            2 #include <errno.h>
            3 #include <stdint.h>
            4 #include <stdio.h>
            5 #include <stdlib.h>
            6 #include <string.h>
            7 #include <time.h>
            8 #include <math.h>
            9 #include <unistd.h>
           10 #include "drawille.h"
           11 #include "util.h"
           12 #include "tsv.h"
           13 
           14 #ifndef __OpenBSD__
           15 #define pledge(...) 0
           16 #endif
           17 
           18 /*
           19  * Plot the body as an histogram interpolating the gaps and include
           20  * a vertical and horizontal axis.
           21  */
           22 static int
           23 braille_histogram(struct tsv *vl, struct drawille *drw,
           24         time_t tmin, time_t tmax, double vmin, double vmax)
           25 {
           26         int                x, xprev, y, yprev, zero;
           27         double                *v;
           28         time_t                *t;
           29         size_t                n;
           30 
           31 #define SHIFT (4 / 2)
           32 #define POSITION(val, min, max, sz) ((sz) * ((val) - (min)) / ((max) - (min)) + SHIFT)
           33 
           34         zero = POSITION(0, vmin, vmax, drw->row*4);
           35         v = vl->v;
           36         t = vl->t;
           37         n = vl->n;
           38         for (; n > 0; n--, t++, v++) {
           39                 if (isnan(*v)) /* XXX: better handling? */
           40                         continue;
           41                 y = POSITION(*v, vmin, vmax, drw->row * 4);
           42                 x = POSITION(*t, tmin, tmax, drw->col * 2);
           43                 if (n < vl->n) /* only plot when xprev, yprev are set */
           44                         drawille_histogram_line(drw, xprev, yprev, x, y, zero);
           45                 xprev = x;
           46                 yprev = y;
           47         }
           48 
           49 #undef POSITION
           50 
           51         return 0;
           52 }
           53 
           54 static int
           55 braille_axis_x(FILE *fp, time_t tmin, time_t tmax, time_t tstep, int col)
           56 {
           57         int x, o, prec;
           58         char tmp[sizeof("MM/DD HH:MM")], *fmt;
           59         size_t n;
           60         time_t t;
           61 
           62         fmt =
           63             (tstep < 3600 * 12) ? "^%H:%M:%S" :
           64             (tstep < 3600 * 24) ? "^%m/%d %H:%M" :
           65             "^%Y/%m/%d";
           66         n = x = 0;
           67 
           68         t = tmin + tstep - tmin % tstep;
           69         for (; t < tmax; t += tstep) {
           70                 x = (t - tmin) * col / (tmax - tmin);
           71                 strftime(tmp, sizeof tmp, fmt, localtime(&t));
           72                 prec = x - n + strlen(tmp);
           73                 if ((o = fprintf(fp, "%*s", prec, tmp)) < 0)
           74                         return -1;
           75                 n += o;
           76         }
           77         fprintf(fp, "\n");
           78         return 0;
           79 }
           80 
           81 /*
           82  * Plot a single line out of the y axis, at row <r> out of <rows>.
           83  */
           84 static void
           85 braille_axis_y(FILE *fp, double min, double max, int r, int rows)
           86 {
           87         char buf[10] = "";
           88 
           89         humanize(buf, (rows - 1 - r) * (max - min) / rows);
           90         fprintf(fp, "├%s ", buf);
           91 }
           92 
           93 static int
           94 braille_render(struct drawille *drw, FILE *fp, double min, double max)
           95 {
           96         int row;
           97 
           98         for (row = 0; row < drw->row; row++) {
           99                 drawille_put_row(fp, drw, row);
          100                 braille_axis_y(fp, min, max, row, drw->row);
          101                 fprintf(fp, "\n");
          102         }
          103         return 0;
          104 }
          105 
          106 static void
          107 plot(struct tsv *vl, size_t ncol, int rows, int cols, FILE *fp)
          108 {
          109         double vmin, vmax, vstep;
          110         time_t tmin, tmax, tstep;
          111         struct drawille *drw;
          112 
          113         rows = MAX(rows, 2);        /* readable */
          114 
          115         if (tsv_min_max(vl, ncol, &tmin, &tmax, &vmin, &vmax) < 0)
          116                 err(1, "invalid scale: tmin=%lld tmax=%lld vmin=%fd vmax=%fd",
          117                     (long long)tmin, (long long)tmax, vmin, vmax);
          118 
          119         tstep = scale_time_t(tmin, tmax, cols);
          120         vstep = scale_double(vmin, vmax, rows);
          121         vmin = (int)(vmin / vstep) * vstep;
          122         vmax = vmin + vstep * rows;
          123 
          124         for (; ncol > 0; vl++, ncol--) {
          125                 if ((drw = drawille_new(rows, cols)) == NULL)
          126                         err(1, "drawille_new: %s", strerror(errno));
          127                 fprintf(fp, " %s\n", vl->label);
          128                 if (braille_histogram(vl, drw, tmin, tmax, vmin, vmax) == -1)
          129                         err(1, "allocating drawille canvas");
          130                 if (braille_render(drw, fp, vmin, vmax) == -1)
          131                         err(1, "rendering braille canvas");
          132                 free(drw);
          133         }
          134         if (braille_axis_x(fp, tmin, tmax, tstep * 10, cols) == -1)
          135                 err(1, "printing x axis");;
          136 }
          137 
          138 static void
          139 usage(void)
          140 {
          141         fprintf(stderr, "usage: %s [-r rows] [-c cols]\n", arg0);
          142         exit(1);
          143 }
          144 
          145 int
          146 main(int argc, char **argv)
          147 {
          148         struct tsv *vl;
          149         size_t ncol;
          150         int c, rows, cols;
          151 
          152         if (pledge("stdio", "") < 0)
          153                 err(1, "pledge: %s", strerror(errno));
          154 
          155         rows = 4, cols = 60;
          156         arg0 = *argv;
          157         while ((c = getopt(argc, argv, "r:c:")) > -1) {
          158                 switch (c) {
          159                 case 'r':
          160                         rows = atoi(optarg);
          161                         if (rows < 1) {
          162                                 warn("invalid number of rows");
          163                                 usage();
          164                         }
          165                         break;
          166                 case 'c':
          167                         cols = atoi(optarg);
          168                         if (rows < 1) {
          169                                 warn("invalid number of columns");
          170                                 usage();
          171                         }
          172                         break;
          173 
          174                 default:
          175                         usage();
          176                 }
          177         }
          178         argc -= optind;
          179         argv += optind;
          180 
          181         if (argc > 0)
          182                 usage();
          183 
          184         tsv_labels(stdin, &vl, &ncol);
          185         tsv_values(stdin, vl, ncol);
          186 
          187         plot(vl, ncol, rows, cols, stdout);
          188 
          189         free(vl);
          190         return 0;
          191 }