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

json.gno

2.64 Kb · 108 lines
  1package connect4_v2
  2
  3import (
  4	"strconv"
  5	"strings"
  6	"time"
  7)
  8
  9// GameJSON returns {"now":<unix>,"game":<game>|null}. It is a read-only
 10// accessor for clients querying over vm/qeval; now is the block time.
 11func GameJSON(id int) string {
 12	var b strings.Builder
 13	writeNow(&b)
 14	b.WriteString(`,"game":`)
 15	if g := get(id); g != nil {
 16		writeGame(&b, g)
 17	} else {
 18		b.WriteString("null")
 19	}
 20	b.WriteString("}")
 21	return b.String()
 22}
 23
 24// ActiveJSON returns {"now":<unix>,"games":[...]}: Open and Playing games in
 25// id order, skipping offset and returning at most limit (clamped to 1-100).
 26func ActiveJSON(offset, limit int) string {
 27	if offset < 0 {
 28		offset = 0
 29	}
 30	if limit < 1 {
 31		limit = 1
 32	}
 33	if limit > 100 {
 34		limit = 100
 35	}
 36	var b strings.Builder
 37	writeNow(&b)
 38	b.WriteString(`,"games":[`)
 39	n := 0
 40	active.IterateByOffset(offset, limit, func(_ string, v any) bool {
 41		if n > 0 {
 42			b.WriteString(",")
 43		}
 44		writeGame(&b, v.(*Game))
 45		n++
 46		return false
 47	})
 48	b.WriteString("]}")
 49	return b.String()
 50}
 51
 52func writeNow(b *strings.Builder) {
 53	b.WriteString(`{"now":`)
 54	b.WriteString(strconv.FormatInt(time.Now().Unix(), 10))
 55}
 56
 57// writeGame emits one game. Every stored string is validated on write
 58// (addresses by IsValid, the commitment as hex), so Quote is defence in depth.
 59func writeGame(b *strings.Builder, g *Game) {
 60	turnPlayer := ""
 61	deadline := int64(0)
 62	if g.Status == Playing {
 63		deadline = g.deadline().Unix()
 64		if g.Turn != 0 {
 65			turnPlayer = g.player(g.Turn).String()
 66		}
 67	}
 68	b.WriteString(`{"id":`)
 69	b.WriteString(strconv.Itoa(g.ID))
 70	writeStr(b, "creator", g.Creator.String())
 71	writeStr(b, "opponent", g.Opponent.String())
 72	writeStr(b, "acceptor", g.Acceptor.String())
 73	writeNum(b, "stake", g.Stake)
 74	writeNum(b, "fee", g.Fee)
 75	writeNum(b, "expiresAt", g.ExpiresAt.Unix())
 76	writeStr(b, "commitment", g.Commitment)
 77	b.WriteString(`,"board":"`)
 78	for c := 0; c < cols; c++ {
 79		for r := 0; r < rows; r++ {
 80			b.WriteByte('0' + g.Board[c][r])
 81		}
 82	}
 83	b.WriteString(`"`)
 84	writeNum(b, "turn", int64(g.Turn))
 85	writeStr(b, "turnPlayer", turnPlayer)
 86	writeNum(b, "moves", int64(g.Moves))
 87	writeNum(b, "lastCol", int64(g.LastCol))
 88	writeNum(b, "lastRow", int64(g.LastRow))
 89	writeNum(b, "deadline", deadline)
 90	writeStr(b, "status", g.Status.String())
 91	writeStr(b, "winner", g.Winner.String())
 92	b.WriteString("}")
 93}
 94
 95// writeStr and writeNum append `,"k":v`; the caller writes the first field.
 96func writeStr(b *strings.Builder, k, v string) {
 97	b.WriteString(`,"`)
 98	b.WriteString(k)
 99	b.WriteString(`":`)
100	b.WriteString(strconv.Quote(v))
101}
102
103func writeNum(b *strings.Builder, k string, v int64) {
104	b.WriteString(`,"`)
105	b.WriteString(k)
106	b.WriteString(`":`)
107	b.WriteString(strconv.FormatInt(v, 10))
108}