checkin.gno
1.71 Kb · 62 lines
1// Package checkin is a public check-in board: anyone can check in once,
2// the board records their address, and Render lists everyone so far.
3package checkin
4
5import (
6 "strconv"
7 "strings"
8
9 "chain"
10
11 "gno.land/p/nt/avl/v0"
12)
13
14var (
15 checkins avl.Tree // caller address (bech32 string) -> arrival number (int)
16 total int // check-ins so far; assigns arrival numbers
17)
18
19// CheckIn records the caller's address on the board. Anyone may check in —
20// an EOA or another realm — but only once; a second check-in reverts.
21func CheckIn(cur realm) {
22 if !cur.IsCurrent() {
23 panic("invalid realm")
24 }
25 caller := cur.Previous().Address().String()
26 if checkins.Has(caller) {
27 panic("already checked in")
28 }
29 total++
30 checkins.Set(caller, total)
31 chain.Emit("CheckIn", "address", caller, "n", strconv.Itoa(total))
32}
33
34// Total returns the number of addresses checked in so far.
35func Total() int {
36 return checkins.Size()
37}
38
39// HasCheckedIn reports whether addr has checked in.
40func HasCheckedIn(addr address) bool {
41 return checkins.Has(addr.String())
42}
43
44// Render lists everyone checked in so far, sorted by address, with each
45// entry's arrival number. Only the home path is served.
46func Render(path string) string {
47 if path != "" {
48 return "> [!WARNING]\n> Path not found. Only the home page exists.\n"
49 }
50 var b strings.Builder
51 b.WriteString("# Check-in board\n\n")
52 if checkins.Size() == 0 {
53 b.WriteString("Nobody has checked in yet. Call `CheckIn` to be the first.\n")
54 return b.String()
55 }
56 b.WriteString(strconv.Itoa(checkins.Size()) + " checked in so far:\n\n")
57 checkins.Iterate("", "", func(key string, value any) bool {
58 b.WriteString("- `" + key + "` (#" + strconv.Itoa(value.(int)) + ")\n")
59 return false
60 })
61 return b.String()
62}