Transaction
C9E43F2A88843D…90D261F33CEE
Block 26,086 · index 0 · indexed
Summary
- Hash
- C9E43F2A88843D2FD0FF82DDC9384C1FC60DFCC5913B6365A02190D261F33CEE
- Block
- 26,086
- Size
- 6991 bytes
- Gas used
- 11,783,206 / 14,139,907
- Fee
- 1000000ugnot
- Memo
- gnopublish
- Status
- success
Messages
Arguments · 9
- #1markovdemo
- #2README.md
- #3# `gno.land/r/moul/x/daily/markovdemo/v0` Live demo of the [`p/moul/x/daily/markov`](https://github.com/moul/gno-contracts/tree/main/p/moul/x/daily/markov/v0) Markov-chain text generator. Holds one package-level `markov.Chain` as the on-chain corpus and wires it to the chain — babbling is seeded by `runtime.ChainHeight()`, so `Generate` stays a pure, reproducible query that still varies block to block. The realm ships pre-seeded with a couple of sentences, so a fresh deploy already babbles: - `Feed(cur, text)` — tokenize `text` and fold it into the corpus (the crossing function; any caller may enrich it). - `Generate(nWords) string` — babble ~`nWords` words, seeded by the block height. - `Stats() (int, int)` — returns `(totalWords, prefixCount)`. - `Render("/60")` — a fresh 60-word sample plus corpus stats and a sample of prefix → suffix rows; `Render("")` defaults to 40 words. All build/walk math lives in the library; this realm is just the wiring and the gnoweb view. Render it at [`/r/moul/x/daily/markovdemo/v0`](https://gno.land/r/moul/x/daily/markovdemo/v0). <!-- BEGIN GNOCONTRACTS FOOTER (generated by `make readmes`; do not edit below) --> --- Part of **[moul/gno-contracts](https://github.com/moul/gno-contracts)** — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage. **Dependency graph:**  > 🧪 **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](https://github.com/moul/gno-contracts/blob/main/DISCLAIMER.md). <!-- END GNOCONTRACTS FOOTER -->
- #4gnomod.toml
- #5module = "gno.land/r/moul/x/daily/markovdemo/v0" gno = "0.9"
- #6markovdemo.gno
- #7// Package markovdemo is a small on-chain demo of the Markov-chain text // generator provided by the [p/moul/x/daily/markov](/p/moul/x/daily/markov/v0) // library. // // It holds a single package-level [markov.Chain] as the corpus and wires it to // the chain: Feed appends words to that persistent chain (a crossing function, // since it mutates on-chain state), while Generate and Render walk it with a // seed derived from runtime.ChainHeight() — so babbling is a pure, reproducible // query that still varies block to block. It contains no Markov logic of its // own — build/walk math all lives in the library. package markovdemo import ( "chain" "chain/runtime" "strconv" "strings" "gno.land/p/moul/x/daily/markov/v0" ) // maxGen clamps Generate / Render so output stays bounded. const maxGen = 200 // mc is the single on-chain corpus, seeded at deploy time. var mc = markov.New() func init() { // Two seed sentences with heavy two-word-prefix overlap, so a fresh deploy // already babbles something recognizably chain-like. mc.Build("it was the best of times it was the worst of times " + "it was the age of wisdom it was the age of foolishness") mc.Build("i am a free man i am not a number " + "i am the master of my fate i am the captain of my soul") } // seedFor derives a Generate seed from the current chain height so the babble // changes block to block yet stays reproducible for anyone querying the same // height. func seedFor() uint64 { return uint64(runtime.ChainHeight())*2654435761 + 0x9e3779b97f4a7c15 } // Feed appends text to the on-chain corpus, extending the Markov chain. Any // caller may enrich the corpus — this is the open-membership demo model. func Feed(cur realm, text string) string { if strings.TrimSpace(text) == "" { panic("markov: empty text") } added := mc.Build(text) words, prefixes := mc.Stats() chain.Emit("Feed", "words", strconv.Itoa(added), "total", strconv.Itoa(words)) return "fed " + strconv.Itoa(added) + " words; corpus now " + strconv.Itoa(words) + " words across " + strconv.Itoa(prefixes) + " prefixes" } // Generate babbles up to nWords of Markov text from the current corpus, seeded // deterministically by the chain height. Read-only. func Generate(nWords int) string { if nWords <= 0 { nWords = 20 } if nWords > maxGen { nWords = maxGen } return strings.Join(mc.Generate(nWords, seedFor()), " ") } // Stats returns (totalWords, prefixCount) for the current corpus. func Stats() (int, int) { return mc.Stats() } // parseN pulls a trailing positive integer out of a Render path such as // "/40" or "gen/40"; it returns 0 when there is none. func parseN(path string) int { p := strings.Trim(path, "/") if i := strings.LastIndex(p, "/"); i >= 0 { p = p[i+1:] } n, err := strconv.Atoi(p) if err != nil || n < 0 { return 0 } return n } // Render shows a freshly generated sample plus corpus stats. The path may // carry a word count, e.g. Render("/60"). func Render(path string) string { n := parseN(path) if n == 0 { n = 40 } if n > maxGen { n = maxGen } words, prefixes := mc.Stats() var b strings.Builder b.WriteString("# Markov Babbler\n\n") b.WriteString("A demo of the [`p/moul/x/daily/markov`](/p/moul/x/daily/markov/v0) " + "library — an on-chain port of Go's classic *\"Generating arbitrary text: " + "a Markov chain algorithm\"* codewalk. Every two-word **prefix** maps to " + "the words that followed it; `Generate` walks that chain, picking suffixes " + "with a PRNG seeded by the block height — deterministic, yet different each " + "block.\n\n") b.WriteString("## Fresh sample (" + strconv.Itoa(n) + " words, height " + strconv.FormatInt(runtime.ChainHeight(), 10) + ")\n\n") sample := strings.Join(mc.Generate(n, seedFor()), " ") if sample == "" { sample = "_(empty corpus)_" } b.WriteString("> " + sample + "\n\n") b.WriteString("## Corpus\n\n") b.WriteString("- **Words:** " + strconv.Itoa(words) + "\n") b.WriteString("- **Distinct prefixes:** " + strconv.Itoa(prefixes) + "\n") b.WriteString("- **Prefix length:** " + strconv.Itoa(markov.PrefixLen) + " words\n\n") b.WriteString("## Some prefixes → suffixes\n\n") b.WriteString("| prefix | can be followed by |\n|---|---|\n") shown := 0 mc.Iterate(func(k string, suffixes []string) bool { disp := k if disp == " " || disp == "" { disp = "_(start)_" } b.WriteString("| `" + disp + "` | " + strings.Join(suffixes, ", ") + " |\n") shown++ return shown >= 12 // cap the table }) b.WriteString("\n_Call `Feed(\"your text here\")` to teach it new words, then " + "reload for a new sample._\n") return b.String() }
- #8/gno.MemPackageType
- #9 MPUserProd
Result log
msg:0,success:true,log:,events:[]