PathrockNetwork Gno Explorer
HomeBlocksTransactionsRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/moul/x/daily/markovdemo/v0

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v0
Namespace
moul / x / daily / markovdemo
Files
3 (README)(gnomod.toml)
Exported functions
4
Module
gno.land/r/moul/x/daily/markovdemo/v0
gno
0.9

Files (3)

  • README.mdmarkdown
  • gnomod.tomltoml
  • markovdemo.gnogno
markovdemo.gnogno
1// Package markovdemo is a small on-chain demo of the Markov-chain text2// generator provided by the [p/moul/x/daily/markov](/p/moul/x/daily/markov/v0)3// library.4//5// It holds a single package-level [markov.Chain] as the corpus and wires it to6// the chain: Feed appends words to that persistent chain (a crossing function,7// since it mutates on-chain state), while Generate and Render walk it with a8// seed derived from runtime.ChainHeight() — so babbling is a pure, reproducible9// query that still varies block to block. It contains no Markov logic of its10// own — build/walk math all lives in the library.11package markovdemo1213import (14	"chain"15	"chain/runtime"16	"strconv"17	"strings"1819	"gno.land/p/moul/x/daily/markov/v0"20)2122// maxGen clamps Generate / Render so output stays bounded.23const maxGen = 2002425// mc is the single on-chain corpus, seeded at deploy time.26var mc = markov.New()2728func init() {29	// Two seed sentences with heavy two-word-prefix overlap, so a fresh deploy30	// already babbles something recognizably chain-like.31	mc.Build("it was the best of times it was the worst of times " +32		"it was the age of wisdom it was the age of foolishness")33	mc.Build("i am a free man i am not a number " +34		"i am the master of my fate i am the captain of my soul")35}3637// seedFor derives a Generate seed from the current chain height so the babble38// changes block to block yet stays reproducible for anyone querying the same39// height.40func seedFor() uint64 {41	return uint64(runtime.ChainHeight())*2654435761 + 0x9e3779b97f4a7c1542}4344// Feed appends text to the on-chain corpus, extending the Markov chain. Any45// caller may enrich the corpus — this is the open-membership demo model.46func Feed(cur realm, text string) string {47	if strings.TrimSpace(text) == "" {48		panic("markov: empty text")49	}50	added := mc.Build(text)51	words, prefixes := mc.Stats()52	chain.Emit("Feed", "words", strconv.Itoa(added), "total", strconv.Itoa(words))53	return "fed " + strconv.Itoa(added) + " words; corpus now " +54		strconv.Itoa(words) + " words across " +55		strconv.Itoa(prefixes) + " prefixes"56}5758// Generate babbles up to nWords of Markov text from the current corpus, seeded59// deterministically by the chain height. Read-only.60func Generate(nWords int) string {61	if nWords <= 0 {62		nWords = 2063	}64	if nWords > maxGen {65		nWords = maxGen66	}67	return strings.Join(mc.Generate(nWords, seedFor()), " ")68}6970// Stats returns (totalWords, prefixCount) for the current corpus.71func Stats() (int, int) {72	return mc.Stats()73}7475// parseN pulls a trailing positive integer out of a Render path such as76// "/40" or "gen/40"; it returns 0 when there is none.77func parseN(path string) int {78	p := strings.Trim(path, "/")79	if i := strings.LastIndex(p, "/"); i >= 0 {80		p = p[i+1:]81	}82	n, err := strconv.Atoi(p)83	if err != nil || n < 0 {84		return 085	}86	return n87}8889// Render shows a freshly generated sample plus corpus stats. The path may90// carry a word count, e.g. Render("/60").91func Render(path string) string {92	n := parseN(path)93	if n == 0 {94		n = 4095	}96	if n > maxGen {97		n = maxGen98	}99100	words, prefixes := mc.Stats()101102	var b strings.Builder103	b.WriteString("# Markov Babbler\n\n")104	b.WriteString("A demo of the [`p/moul/x/daily/markov`](/p/moul/x/daily/markov/v0) " +105		"library — an on-chain port of Go's classic *\"Generating arbitrary text: " +106		"a Markov chain algorithm\"* codewalk. Every two-word **prefix** maps to " +107		"the words that followed it; `Generate` walks that chain, picking suffixes " +108		"with a PRNG seeded by the block height — deterministic, yet different each " +109		"block.\n\n")110111	b.WriteString("## Fresh sample (" + strconv.Itoa(n) + " words, height " +112		strconv.FormatInt(runtime.ChainHeight(), 10) + ")\n\n")113	sample := strings.Join(mc.Generate(n, seedFor()), " ")114	if sample == "" {115		sample = "_(empty corpus)_"116	}117	b.WriteString("> " + sample + "\n\n")118119	b.WriteString("## Corpus\n\n")120	b.WriteString("- **Words:** " + strconv.Itoa(words) + "\n")121	b.WriteString("- **Distinct prefixes:** " + strconv.Itoa(prefixes) + "\n")122	b.WriteString("- **Prefix length:** " + strconv.Itoa(markov.PrefixLen) + " words\n\n")123124	b.WriteString("## Some prefixes → suffixes\n\n")125	b.WriteString("| prefix | can be followed by |\n|---|---|\n")126	shown := 0127	mc.Iterate(func(k string, suffixes []string) bool {128		disp := k129		if disp == " " || disp == "" {130			disp = "_(start)_"131		}132		b.WriteString("| `" + disp + "` | " + strings.Join(suffixes, ", ") + " |\n")133		shown++134		return shown >= 12 // cap the table135	})136	b.WriteString("\n_Call `Feed(\"your text here\")` to teach it new words, then " +137		"reload for a new sample._\n")138139	return b.String()140}141

Functions

  • Feed(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, text string) string

  • Generate(nWords int) string

  • Render(path string) string

  • Stats() (int, int)

Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

Rendered

RenderedRawgnoweb ↗

vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.