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

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}