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

counter.gno

3.68 Kb · 143 lines
  1// Package counter implements "Counter Club": a single shared integer counter
  2// with a rolling history of the last 20 mutations. Anyone may Inc, Dec, or
  3// Reset the value; every change records the caller, the delta applied, the
  4// resulting value, and the block height it happened at.
  5package counter
  6
  7import (
  8	"chain"
  9	"chain/runtime"
 10	"chain/runtime/unsafe"
 11	"strconv"
 12	"strings"
 13)
 14
 15// maxHistory is the number of recent changes kept in the log.
 16const maxHistory = 20
 17
 18// change is a single recorded mutation of the counter.
 19type change struct {
 20	caller address // who triggered the change
 21	delta  int     // how much the value moved (+1, -1, or reset amount)
 22	value  int     // the resulting counter value after the change
 23	height int64   // block height at which it occurred
 24}
 25
 26// value is the current shared counter.
 27var value int
 28
 29// total counts every mutation ever applied (not capped, unlike history).
 30var total int
 31
 32// history holds the last maxHistory changes, oldest first.
 33var history []change
 34
 35// record appends a change to the history, trimming to the last maxHistory.
 36func record(delta, newValue int) {
 37	c := change{
 38		caller: unsafe.PreviousRealm().Address(),
 39		delta:  delta,
 40		value:  newValue,
 41		height: runtime.ChainHeight(),
 42	}
 43	history = append(history, c)
 44	if len(history) > maxHistory {
 45		history = history[len(history)-maxHistory:]
 46	}
 47	total++
 48	chain.Emit(
 49		"CounterChange",
 50		"delta", strconv.Itoa(delta),
 51		"value", strconv.Itoa(newValue),
 52	)
 53}
 54
 55// Inc adds one to the shared counter and logs the change.
 56func Inc(cur realm) int {
 57	value++
 58	record(1, value)
 59	return value
 60}
 61
 62// Dec subtracts one from the shared counter and logs the change.
 63func Dec(cur realm) int {
 64	value--
 65	record(-1, value)
 66	return value
 67}
 68
 69// Reset sets the shared counter back to zero and logs the change. The recorded
 70// delta is the amount required to bring the previous value to zero.
 71func Reset(cur realm) int {
 72	delta := -value
 73	value = 0
 74	record(delta, value)
 75	return value
 76}
 77
 78// Value returns the current counter value (read-only helper).
 79func Value() int {
 80	return value
 81}
 82
 83// Total returns the total number of mutations ever applied.
 84func Total() int {
 85	return total
 86}
 87
 88// Render produces a Markdown view: the big current value, the total number of
 89// changes, and a table of the most recent changes (newest first).
 90func Render(path string) string {
 91	var b strings.Builder
 92
 93	b.WriteString("# Counter Club\n\n")
 94	b.WriteString("A shared counter anyone can Inc, Dec, or Reset. ")
 95	b.WriteString("The last ")
 96	b.WriteString(strconv.Itoa(maxHistory))
 97	b.WriteString(" changes are logged below.\n\n")
 98
 99	// Big current value.
100	b.WriteString("## Current value\n\n")
101	b.WriteString("# ")
102	b.WriteString(strconv.Itoa(value))
103	b.WriteString("\n\n")
104
105	b.WriteString("**Total changes:** ")
106	b.WriteString(strconv.Itoa(total))
107	b.WriteString("\n\n")
108
109	// Recent history, newest first.
110	b.WriteString("## Recent history\n\n")
111	if len(history) == 0 {
112		b.WriteString("_No changes yet — be the first to count!_\n")
113		return b.String()
114	}
115
116	b.WriteString("| # | Caller | Delta | New value | Height |\n")
117	b.WriteString("|---|--------|-------|-----------|--------|\n")
118	n := len(history)
119	for i := n - 1; i >= 0; i-- {
120		c := history[i]
121		b.WriteString("| ")
122		b.WriteString(strconv.Itoa(n - i))
123		b.WriteString(" | ")
124		b.WriteString(c.caller.String())
125		b.WriteString(" | ")
126		b.WriteString(signed(c.delta))
127		b.WriteString(" | ")
128		b.WriteString(strconv.Itoa(c.value))
129		b.WriteString(" | ")
130		b.WriteString(strconv.FormatInt(c.height, 10))
131		b.WriteString(" |\n")
132	}
133
134	return b.String()
135}
136
137// signed formats an int with an explicit leading sign for non-negative values.
138func signed(n int) string {
139	if n >= 0 {
140		return "+" + strconv.Itoa(n)
141	}
142	return strconv.Itoa(n)
143}