summaryrefslogtreecommitdiff
path: root/src/chart.ml
diff options
context:
space:
mode:
Diffstat (limited to 'src/chart.ml')
-rw-r--r--src/chart.ml113
1 files changed, 59 insertions, 54 deletions
diff --git a/src/chart.ml b/src/chart.ml
index 0826092..de79082 100644
--- a/src/chart.ml
+++ b/src/chart.ml
@@ -1,61 +1,66 @@
1let to_string c = String.make 1 c 1let to_string c = String.make 1 c
2
2let space = to_string ' ' 3let space = to_string ' '
4
3let axis = "┬" 5let axis = "┬"
6
4let axis_spc = "─" 7let axis_spc = "─"
5 8
6type t = { vals: int list; opts: Options.t } 9type t = { vals : int list; opts : Options.t }
10
7let default = { vals = []; opts = Options.default } 11let default = { vals = []; opts = Options.default }
8let plot v c = { c with vals = v; } 12
9let with_options v c = { v with opts = c; } 13let plot v c = { c with vals = v }
10let pp channel {vals: int list; opts: Options.t } = 14
11 let open Utils in 15let with_options v c = { c with opts = v }
12 let height = opts.height in 16
13 let min_val = list_min vals in 17let pp formatter { vals : int list; opts : Options.t } =
14 let max_val = list_max vals in 18 let open Utils in
15 let range = max_val - min_val in 19 let height = opts.height in
16 let scale v = ((v - min_val) * height) / range in 20 let min_val = list_min vals in
17 let new_vals = List.map scale vals in 21 let max_val = list_max vals in
18 let rec pad left right s = 22 let range = max_val - min_val in
19 if left = 0 23 let scale v = (v - min_val) * height / range in
20 then s :: repeat right space 24 let new_vals = List.map scale vals in
21 else space :: pad (left - 1) right s 25 let rec pad left right s =
22 in 26 if left = 0 then s :: repeat right space
23 let new_vals' = zip new_vals (List.tl new_vals) in 27 else space :: pad (left - 1) right s
24 let make_marker prefix left right s = 28 in
25 prefix :: 29 let new_vals' = zip new_vals (List.tl new_vals) in
26 (if left = 0 30 let make_marker prefix left right s =
27 then s :: repeat right space 31 prefix
28 else space :: pad (left - 1) right s) 32 ::
29 in 33 (if left = 0 then s :: repeat right space
30 let make_connector s e = 34 else space :: pad (left - 1) right s)
31 match Stdlib.compare s e with 35 in
32 | 0 -> make_marker axis_spc s (height - s) "-" 36 let make_connector s e =
33 | x -> 37 match Stdlib.compare s e with
34 let (ltr_chr, rtl_chr) = 38 | 0 -> make_marker axis_spc s (height - s) "-"
35 match x with 39 | x ->
36 | 1 -> ("└", "┐") 40 let ltr_chr, rtl_chr =
37 | _ -> ("┘", "┌") 41 match x with 1 -> ("└", "┐") | _ -> ("┘", "┌")
38 in
39 let (st, en) = Stdlib.((min s e, max s e)) in
40 let l = en - st |> saturating_sub 1 in
41 let (left, right) = (repeat st space, repeat (height - l - st) space) in
42 List.flatten [[axis_spc]; left; [ltr_chr]; repeat l "│"; [rtl_chr]; right]
43 in 42 in
44 let m = Printf.sprintf opts.marker in 43 let st, en = Stdlib.(min s e, max s e) in
45 let rec make_graph = function 44 let l = en - st |> saturating_sub 1 in
46 | [] -> [] 45 let left, right = (repeat st space, repeat (height - l - st) space) in
47 | (s, e) :: [] -> 46 List.flatten
48 make_marker axis s (height - s) m 47 [
49 :: make_connector s e 48 [ axis_spc ]; left; [ ltr_chr ]; repeat l "│"; [ rtl_chr ]; right;
50 :: make_marker axis e (height - e) m 49 ]
51 :: [] 50 in
52 | (s, e) :: tl -> 51 let m = Format.asprintf "%a" Marker.pp opts.marker in
53 make_marker axis s (height - s) m 52 let rec make_graph = function
54 :: make_connector s e 53 | [] -> []
55 :: make_graph tl 54 | [ (s, e) ] ->
56 in 55 [
57 make_graph new_vals' 56 make_marker axis s (height - s) m;
58 |> rot_left 57 make_connector s e;
59 |> List.map (String.concat "") 58 make_marker axis e (height - e) m;
60 |> String.concat "\n" 59 ]
61 |> Printf.fprintf channel "%s" 60 | (s, e) :: tl ->
61 make_marker axis s (height - s) m :: make_connector s e :: make_graph tl
62 in
63 make_graph new_vals' |> rot_left
64 |> List.map (String.concat "")
65 |> String.concat "\n"
66 |> Format.fprintf formatter "%s"