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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

electionrender.gno

5.42 Kb · 129 lines
  1package kourtv3
  2import (
  3	"strconv"
  4	"strings"
  5	sanitize "gno.land/p/nt/markdown/sanitize/v0"
  6)
  7const electionPath = "election"
  8func renderElection(slug string) string {
  9	if !Exists(slug) {
 10		return "## Not found\nNo court by that slug."
 11	}
 12	c := mustCourt(slug)
 13	base := "/r/g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr/kourtv3:" + slug
 14	var b strings.Builder
 15	b.WriteString("# Electing the moderators of " + courtNameFor(c) + "\n\n")
 16	b.WriteString("[← " + courtNameFor(c) + "](" + base + ") · [moderation log](" +
 17		base + "/mod)\n\n")
 18	b.WriteString("A court's moderators answer claims, curate its folders, and can " +
 19		"hide a claim, hide a comment, slash somebody's standing, or freeze an " +
 20		"address out of the boards. **This ballot is the only way the court's " +
 21		"holders replace them.**\n\n")
 22	cm := c.mod
 23	if cm == nil || cm.election == nil || cm.election.resolved {
 24		writeNoElection(&b, c, cm)
 25		b.WriteString("\n" + helpLink + "\n")
 26		return b.String()
 27	}
 28	writeOpenElection(&b, c, cm, base)
 29	b.WriteString("\n" + helpLink + "\n")
 30	return b.String()
 31}
 32func writeNoElection(b *strings.Builder, c *Court, cm *courtMod) {
 33	b.WriteString("## No election is open\n\n")
 34	if cm == nil || cm.n == 0 {
 35		b.WriteString("This court has no moderator set yet — its creator holds the " +
 36			"seat until an election or an appointment changes that.\n")
 37	} else {
 38		b.WriteString("- seats held now: **" + strconv.Itoa(cm.n) + "**, " +
 39			strconv.Itoa(cm.m) + " of whom must agree for a moderation act\n")
 40	}
 41	now := heightNow()
 42	if cm != nil && electionCooldownOpen(cm) {
 43		b.WriteString("- this court is in its post-election cooldown until block **" +
 44			strconv.FormatInt(cm.electionCooldownUntil, 10) + "** (now " +
 45			strconv.FormatInt(now, 10) + "); no ballot can open before then\n\n")
 46		return
 47	}
 48	b.WriteString("- a ballot **can be opened now**\n\n")
 49	b.WriteString("Opening one takes two calls: `RegisterModCandidate` records a " +
 50		"proposed set of moderators and returns its id, and `OpenElection` puts " +
 51		"that id on a ballot. Any holder may do both.\n\n")
 52}
 53func writeOpenElection(b *strings.Builder, c *Court, cm *courtMod, base string) {
 54	e := cm.election
 55	now := heightNow()
 56	b.WriteString("## A ballot is open\n\n")
 57	switch {
 58	case !nominationClosed(e):
 59		b.WriteString("**Nominating.** Candidate sets may be added until block **" +
 60			strconv.FormatInt(e.nominateEnd, 10) + "**; voting runs from then " +
 61			"until block **" + strconv.FormatInt(e.voteEnd, 10) + "**.\n\n")
 62	case !votingClosed(e):
 63		b.WriteString("**Voting.** Nominations closed at block " +
 64			strconv.FormatInt(e.nominateEnd, 10) + "; the ballot closes at block **" +
 65			strconv.FormatInt(e.voteEnd, 10) + "**.\n\n")
 66	default:
 67		b.WriteString("**Closed and awaiting resolution.** The ballot shut at block " +
 68			strconv.FormatInt(e.voteEnd, 10) + ". Anyone may call `ResolveElection` " +
 69			"to apply the result below.\n\n")
 70	}
 71	b.WriteString("- now: block " + strconv.FormatInt(now, 10) + "\n")
 72	b.WriteString("- a candidate set costs a bond of **" +
 73		strconv.FormatInt(e.bond, 10) + " " + qualifiedSymbol(c) + "**\n")
 74	b.WriteString("- weights are pinned at the epoch the ballot opened, so buying " +
 75		"coin now does not add voting weight to it\n\n")
 76	writeBallotLines(b, c, e)
 77	writeTurnoutBar(b, c, e)
 78}
 79func writeBallotLines(b *strings.Builder, c *Court, e *election) {
 80	b.WriteString("## On the ballot\n\n")
 81	rows := 0
 82	e.lines.Iterate("", "", func(_ string, v any) bool {
 83		l, ok := v.(*ballotLine)
 84		if !ok {
 85			return false
 86		}
 87		rows++
 88		b.WriteString("- **set #" + strconv.FormatUint(l.candID, 10) + "** — " +
 89			strconv.FormatInt(l.weight, 10) + " " + qualifiedSymbol(c) + " approving\n")
 90		if cv := c.mod.candidates.Get(beClaimKey(l.candID)); cv != nil {
 91			cand := cv.(*modCandidate)
 92			b.WriteString("  - would seat " + strconv.Itoa(len(cand.members)) +
 93				", " + strconv.Itoa(cand.m) + " of whom must agree\n")
 94			for _, m := range cand.members {
 95				b.WriteString("  - `" + sanitize.InlineText(m.String()) + "`\n")
 96			}
 97		}
 98		return rows >= renderPageSize
 99	})
100	if rows == 0 {
101		b.WriteString("_No candidate sets yet._ Until one is nominated there is " +
102			"nothing to elect, and the current moderators stay.\n\n")
103	} else {
104		b.WriteString("\n")
105	}
106	b.WriteString("- **keep the current moderators** — " +
107		strconv.FormatInt(e.retainW, 10) + " " + qualifiedSymbol(c) + " approving\n\n")
108}
109func writeTurnoutBar(b *strings.Builder, c *Court, e *election) {
110	b.WriteString("## Turnout\n\n")
111	b.WriteString("- cast so far: **" + strconv.FormatInt(e.turnout, 10) + " " +
112		qualifiedSymbol(c) + "**\n")
113	b.WriteString("- the bar: **" + strconv.FormatInt(e.floor, 10) + " " +
114		qualifiedSymbol(c) + "**, fixed when the ballot opened\n")
115	if e.turnout < e.floor {
116		b.WriteString("- still needed: **" + strconv.FormatInt(e.floor-e.turnout, 10) +
117			" " + qualifiedSymbol(c) + "**\n\n")
118	} else {
119		b.WriteString("- the bar is cleared\n\n")
120	}
121	b.WriteString("> **Falling short is not a draw.** If the ballot closes with less " +
122		"than the bar cast, nothing is installed and the current moderators keep " +
123		"their seats — the same outcome as a vote to retain them.\n>\n" +
124		"> And the bar is a share of this court's coin **including coin that " +
125		"cannot vote**: it nets out only the court's own escrow, so coin held at " +
126		"a wrapper's address counts toward the pool the bar was measured against " +
127		"while no key can cast it. The share of actually-castable weight you need " +
128		"is therefore larger than the bar looks.\n\n")
129}