Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

sparklinedemo.gno

3.81 Kb · 97 lines
 1// Package sparklinedemo is a small gnoweb demo of the block-character series
 2// renderer provided by the [p/moul/x/daily/sparkline](/p/moul/x/daily/sparkline/v0)
 3// library: it sparks a few fixed series and shows the three behaviours worth
 4// knowing before using it in a realm — flat series, clamping, and floor
 5// rounding.
 6//
 7// It contains no rendering logic of its own. Stateless, so Render is
 8// deterministic.
 9package sparklinedemo
10
11import (
12	"strconv"
13	"strings"
14
15	"gno.land/p/moul/x/daily/sparkline/v0"
16)
17
18// series are fixed rather than derived from chain state: a demo whose output
19// moved with the block height could not be pinned by an example test.
20var (
21	traffic = []int{3, 5, 9, 14, 12, 18, 25, 21, 16, 11, 7, 4}
22	flat    = []int{1000, 1000, 1000, 1000}
23	swing   = []int{-8, -3, 0, 4, 9, 2, -5}
24	pct     = []int{-20, 0, 25, 50, 75, 100, 140}
25)
26
27// Render renders the demo for gnoweb.
28//
29//	Render("") / Render("/") -> the full demo
30func Render(path string) string {
31	var b strings.Builder
32
33	b.WriteString("# Sparklines\n\n")
34	b.WriteString("A numeric series as one line of block characters, demoing the ")
35	b.WriteString("[`p/moul/x/daily/sparkline`](/p/moul/x/daily/sparkline/v0) library.\n\n")
36
37	b.WriteString("## A series\n\n")
38	lo, hi, _ := sparkline.Bounds(traffic)
39	b.WriteString("`" + sparkline.Ints(traffic) + "`\n\n")
40	b.WriteString(ints(traffic) + "\n\n")
41	b.WriteString("Scaled between its own bounds, `" + strconv.Itoa(lo) + "` and `" +
42		strconv.Itoa(hi) + "`. The shape is the point; the axis is not.\n\n")
43
44	b.WriteString("## The ramp\n\n")
45	b.WriteString("`" + sparkline.Levels + "` — eight levels, low to high.\n\n")
46	b.WriteString("| value | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |\n")
47	b.WriteString("|---|---|---|---|---|---|---|---|---|\n")
48	b.WriteString("| level |")
49	for v := 0; v <= 7; v++ {
50		b.WriteString(" `" + sparkline.Scaled([]int{v}, 0, 7) + "` |")
51	}
52	b.WriteString("\n\n")
53
54	b.WriteString("## A flat series\n\n")
55	b.WriteString("`" + sparkline.Ints(flat) + "` — " + ints(flat) + "\n\n")
56	b.WriteString("Mid-ramp, not along the floor. A series that never moves has no ")
57	b.WriteString("shape, but drawing it at the bottom would claim it was *zero*, ")
58	b.WriteString("which is a different thing and a wrong one.\n\n")
59
60	b.WriteString("## Negatives\n\n")
61	b.WriteString("`" + sparkline.Ints(swing) + "` — " + ints(swing) + "\n\n")
62	b.WriteString("Nothing special: the window is the minimum and maximum, wherever ")
63	b.WriteString("zero happens to fall.\n\n")
64
65	b.WriteString("## A fixed window clamps\n\n")
66	b.WriteString(ints(pct) + " against `0..100`:\n\n")
67	b.WriteString("`" + sparkline.Scaled(pct, 0, 100) + "`\n\n")
68	b.WriteString("`-20` pins to the floor and `140` to the ceiling. Choosing the ")
69	b.WriteString("window keeps a percentage readable, and one outlier cannot flatten ")
70	b.WriteString("the rest of the picture — or break the realm that drew it.\n\n")
71
72	b.WriteString("## Rounding is floor\n\n")
73	b.WriteString("| value in `0..100` | level |\n")
74	b.WriteString("|---|---|\n")
75	for _, v := range []int{0, 14, 50, 85, 99, 100} {
76		b.WriteString("| " + strconv.Itoa(v) + " | `" +
77			sparkline.Scaled([]int{v}, 0, 100) + "` |\n")
78	}
79	b.WriteString("\nOnly the maximum itself reaches the top of the ramp, so the peak ")
80	b.WriteString("of a series is always visually distinct.\n\n")
81
82	b.WriteString("## Why integers\n\n")
83	b.WriteString("Scaling is integer division throughout. Render output has to be ")
84	b.WriteString("byte-identical on every validating node, and floating point is the ")
85	b.WriteString("usual way that quietly stops being true.\n")
86
87	return b.String()
88}
89
90// ints formats a series as `a, b, c` for the prose around each sparkline.
91func ints(values []int) string {
92	parts := make([]string, len(values))
93	for i, v := range values {
94		parts[i] = strconv.Itoa(v)
95	}
96	return "`" + strings.Join(parts, ", ") + "`"
97}