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/trivia/v0

Realm
Open in gnoweb ↗

Overview

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

Files (3)

  • README.mdmarkdown
  • gnomod.tomltoml
  • trivia.gnogno
trivia.gnogno
1// Package trivia is a rotating multiple-choice trivia quiz realm.2//3// One question is live at a time. Anyone can call Answer with a choice4// index; the first caller to answer correctly scores a point and the quiz5// advances to the next question. The starting question is picked6// deterministically from the block height at deploy time so repeated7// deploys don't always open on question one.8package trivia910import (11	"strconv"12	"strings"1314	"chain"15	"chain/runtime"1617	"gno.land/p/nt/avl/v0"18)1920// question is one fixed trivia entry.21type question struct {22	text       string23	choices    [4]string24	correctIdx int25}2627// round holds the mutable state of the currently open question.28type round struct {29	number   int // 1-based round counter, increments forever30	qIdx     int // index into questions for this round31	attempts int // guesses made against this round so far32	solved   bool33	winner   string34}3536var (37	questions = []question{38		{"What is the smallest prime number?", [4]string{"0", "1", "2", "3"}, 2},39		{"Which gas does a plant primarily absorb for photosynthesis?", [4]string{"Oxygen", "Nitrogen", "Carbon dioxide", "Hydrogen"}, 2},40		{"How many continents are there on Earth?", [4]string{"5", "6", "7", "8"}, 2},41		{"In binary, what is 1 + 1?", [4]string{"2", "10", "11", "0"}, 1},42		{"What does 'HTTP' stand for?", [4]string{"HyperText Transfer Protocol", "High Transfer Text Protocol", "Home Tool Transfer Protocol", "HyperText Transmission Path"}, 0},43		{"Which planet is known as the Red Planet?", [4]string{"Venus", "Jupiter", "Mars", "Saturn"}, 2},44		{"What is the time complexity of binary search?", [4]string{"O(n)", "O(log n)", "O(n^2)", "O(1)"}, 1},45		{"Who wrote the original Go proverb 'Don't communicate by sharing memory'?", [4]string{"Linus Torvalds", "Rob Pike", "Guido van Rossum", "Brendan Eich"}, 1},46	}4748	current *round49	scores  = avl.NewTree() // addr(string) -> *int, points across all rounds5051	totalCorrect int // lifetime count of correctly-answered questions52)5354func init() {55	current = newRound(1, runtime.ChainHeight())56}5758// newRound builds a fresh round. The question index cycles through the fixed59// list, offset by a height-derived starting point so consecutive deploys60// don't all open on the same question.61func newRound(number int, height int64) *round {62	return &round{63		number: number,64		qIdx:   questionIndex(number, height),65	}66}6768// questionIndex maps a round number and a height (entropy source for the69// starting offset) to a slot in the questions slice. Deterministic and pure70// so it's easy to unit test.71func questionIndex(number int, height int64) int {72	if height < 0 {73		height = -height74	}75	n := len(questions)76	offset := int(height % int64(n))77	return (offset + number - 1) % n78}7980// Answer submits a choice (0..3) for the current question. Crossing81// function: caller invokes as Answer(cross(cur), choiceIdx).82func Answer(cur realm, choiceIdx int) string {83	if !cur.IsCurrent() {84		panic("spoofed realm")85	}86	q := questions[current.qIdx]87	if choiceIdx < 0 || choiceIdx >= len(q.choices) {88		panic("choice must be in 0.." + strconv.Itoa(len(q.choices)-1))89	}90	if current.solved {91		panic("this question is already solved; the next one is already live")92	}9394	current.attempts++95	caller := cur.Previous().Address().String()9697	if choiceIdx != q.correctIdx {98		return "Wrong — try again."99	}100101	current.solved = true102	current.winner = caller103	addScore(caller)104	totalCorrect++105106	chain.Emit("QuestionSolved",107		"round", strconv.Itoa(current.number),108		"winner", caller,109		"answer", q.choices[choiceIdx],110	)111112	solvedRound := current.number113	current = newRound(solvedRound+1, runtime.ChainHeight())114115	return "Correct! The answer was \"" + q.choices[choiceIdx] + "\". A new question is now live."116}117118// addScore bumps addr's lifetime point count.119func addScore(addr string) {120	if v := scores.Get(addr); v != nil {121		p := v.(*int)122		*p++123		return124	}125	one := 1126	scores.Set(addr, &one)127}128129func scoreOf(addr string) int {130	if v := scores.Get(addr); v != nil {131		return *(v.(*int))132	}133	return 0134}135136// leaderboardEntry is a snapshot row used only for rendering, sorted by137// score descending.138type leaderboardEntry struct {139	addr  string140	score int141}142143func leaderboard() []leaderboardEntry {144	var rows []leaderboardEntry145	scores.Iterate("", "", func(addr string, v any) bool {146		rows = append(rows, leaderboardEntry{addr: addr, score: *(v.(*int))})147		return false148	})149	// simple insertion sort by score desc; leaderboards here stay small.150	for i := 1; i < len(rows); i++ {151		j := i152		for j > 0 && rows[j-1].score < rows[j].score {153			rows[j-1], rows[j] = rows[j], rows[j-1]154			j--155		}156	}157	return rows158}159160// Render produces the gnoweb Markdown view of the quiz.161func Render(path string) string {162	var b strings.Builder163164	b.WriteString("# Trivia Quiz\n\n")165	b.WriteString("A rotating on-chain trivia quiz. Call `Answer(choiceIdx)` with 0-3 ")166	b.WriteString("to answer the current question — first correct answer scores the point ")167	b.WriteString("and a new question goes live.\n\n")168169	q := questions[current.qIdx]170	b.WriteString("## Round " + strconv.Itoa(current.number) + "\n\n")171	b.WriteString("**" + q.text + "**\n\n")172	letters := [4]string{"A", "B", "C", "D"}173	for i, c := range q.choices {174		b.WriteString("- **" + letters[i] + "** (" + strconv.Itoa(i) + "): " + c + "\n")175	}176	b.WriteString("\n- Attempts so far this round: " + strconv.Itoa(current.attempts) + "\n\n")177178	b.WriteString("## Leaderboard\n\n")179	rows := leaderboard()180	if len(rows) == 0 {181		b.WriteString("_No one has scored yet — be the first!_\n\n")182	} else {183		b.WriteString("| Player | Points |\n|---|---|\n")184		for _, r := range rows {185			b.WriteString("| `" + r.addr + "` | " + strconv.Itoa(r.score) + " |\n")186		}187		b.WriteString("\n")188	}189190	b.WriteString("Total questions answered correctly across all rounds: " + strconv.Itoa(totalCorrect) + "\n\n")191192	b.WriteString("## How to play\n\n")193	b.WriteString("```\n")194	b.WriteString("gnokey maketx call -pkgpath gno.land/r/g12cs4cehujpffpjpywmkqj43m6u5ya53nj69sjz/trivia \\\n")195	b.WriteString("  -func Answer -args <0|1|2|3> ...\n")196	b.WriteString("```\n")197198	return b.String()199}200

Functions

  • Answer(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}, choiceIdx int) string

  • Render(path string) string

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.