const Levels
Levels is the ramp, lowest to highest. A string constant rather than a []rune so callers cannot mutate the ramp out from under other realms.
Package sparkline renders a numeric series as one line of Unicode block characters — ▁▂▃▄▅▆▇█ — so a realm's Render c...
gno.land/p/moul/x/daily/sparkline/v0Sparklines: a numeric series as one line of block characters — Ints,
Scaled, Level, Bounds, Levels, Steps.
1import "gno.land/p/moul/x/daily/sparkline/v0"
2
3sparkline.Ints([]int{3, 5, 9, 14, 12, 18, 25, 21, 16, 11, 7, 4})
4// ▁▁▂▄▃▅█▆▅▃▂▁ scaled between the series' own min and max
5
6sparkline.Scaled(pct, 0, 100) // fixed window; outliers clamp to the ends
A realm's Render returns markdown, so a trend normally means an image, a chart
library, or client-side code — none of which a realm has. Eight block runes and
one line of text do the job, and gnoweb needs nothing to display them.
Everything is integer math, deliberately. Render output has to be byte-identical on every validating node, and floating point is the usual way that quietly stops being true. Scaling is integer division with floor rounding.
Three behaviours worth knowing before you use it:
▅▅▅▅), not along the floor. A series
sitting unchanged at 1000 has no shape, but drawing it at the bottom would
claim it was zero — a different thing, and a wrong one.Scaled clamps instead of failing. A window is chosen for readability
(0..100 for a percentage), and one outlier should not be able to flatten the
rest of the picture or break the Render that drew it.█. The
peak of a series is always visually distinct.Level is total: every input maps into [0, Steps), including the extremes
where the scaling arithmetic would otherwise wrap. That matters because Scaled
indexes the ramp with it — an out-of-range result would panic the calling realm,
so it is tested against minInt/maxInt windows directly.
Rendering is O(len(values)). A realm should slice its series to a window
rather than sparking an unbounded, user-grown slice.
Live demo: r/moul/x/daily/sparklinedemo
· render it at /r/moul/x/daily/sparklinedemo/v0.
Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.
🧪 Highly experimental — potentially vibe-coded. Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: DISCLAIMER.
Package sparkline renders a numeric series as one line of Unicode block characters — ▁▂▃▄▅▆▇█ — so a realm's Render can show a trend inline, with no image, no chart library and no client-side code.
Everything is integer math, deliberately. A realm's Render must produce byte-identical output on every validating node, and floating point is the usual way that quietly stops being true. Scaling here is integer division with the rounding rule stated below, so a given series always yields exactly the same runes.
Rendering is O(len(values)) and allocates one builder; a realm should bound what it feeds in (slice to a window) rather than sparking an unbounded, user-grown slice.
A live demo of this package is at r/moul/x/daily/sparklinedemo(/r/moul/x/daily/sparklinedemo/v0).
Bounds returns the smallest and largest value in values. ok is false when values is empty, in which case lo and hi are zero.
Ints renders values scaled between their own smallest and largest element. An empty series renders as the empty string.
Level maps v within [lo, hi] to a ramp index in [0, Steps-1].
Rounding is floor, so only a value at hi itself reaches the top of the ramp; everything below it rounds down. That makes the maximum visually distinct, which is what a reader is looking for in a sparkline.
A flat window (hi <= lo) maps everything to the MIDDLE of the ramp, not the bottom: a series that sits unchanged at 1000 carries no shape, but drawing it along the floor would read as "zero", which is a different and wrong claim.
Scaled renders values against an explicit [lo, hi] window. Values outside it clamp to the ends rather than erroring: a window is chosen for readability (0..100 for a percentage, say), and one outlier should not be able to break a realm's Render.
A window with hi <= lo is treated as flat; see Level.