json.gno
2.08 Kb · 91 lines
1package profiles
2
3import (
4 "strconv"
5 "strings"
6)
7
8// ProfileJSON is the profile of an address, or null when it has none yet:
9//
10// {"addr","name","rank","gamesPlayed","victoryPoints","createdAt"}
11//
12// name is the address's name in gno.land/r/sys/users, "" if none.
13func ProfileJSON(addr string) string {
14 v := profiles.Get(addr)
15 if v == nil {
16 return "null"
17 }
18 p := v.(*Profile)
19 var b strings.Builder
20 writeProfile(&b, p, rankOf(p))
21 return b.String()
22}
23
24// PlayersJSON is one page of the ranking, best first, count at most
25// MaxPage:
26//
27// {"total","offset","players":[profile...]}
28func PlayersJSON(offset, count int) string {
29 if offset < 0 {
30 offset = 0
31 }
32 if count < 0 {
33 count = 0
34 }
35 if count > MaxPage {
36 count = MaxPage
37 }
38 var b strings.Builder
39 b.WriteString(`{"total":` + strconv.Itoa(ranking.Size()))
40 b.WriteString(`,"offset":` + strconv.Itoa(offset))
41 b.WriteString(`,"players":[`)
42 i := 0
43 ranking.IterateByOffset(offset, count, func(_ string, v any) bool {
44 if i > 0 {
45 b.WriteByte(',')
46 }
47 writeProfile(&b, v.(*Profile), offset+i+1)
48 i++
49 return false
50 })
51 b.WriteString("]}")
52 return b.String()
53}
54
55func writeProfile(b *strings.Builder, p *Profile, rank int) {
56 b.WriteString(`{"addr":` + quote(p.Addr.String()))
57 b.WriteString(`,"name":` + quote(Name(p.Addr)))
58 b.WriteString(`,"rank":` + strconv.Itoa(rank))
59 b.WriteString(`,"gamesPlayed":` + strconv.Itoa(p.GamesPlayed))
60 b.WriteString(`,"victoryPoints":` + strconv.Itoa(p.VictoryPoints))
61 b.WriteString(`,"createdAt":` + strconv.FormatInt(p.CreatedAt.Unix(), 10))
62 b.WriteByte('}')
63}
64
65// quote encodes s as a JSON string.
66func quote(s string) string {
67 var b strings.Builder
68 b.WriteByte('"')
69 for i := 0; i < len(s); i++ {
70 c := s[i]
71 switch {
72 case c == '"' || c == '\\':
73 b.WriteByte('\\')
74 b.WriteByte(c)
75 case c == '\n':
76 b.WriteString(`\n`)
77 case c == '\r':
78 b.WriteString(`\r`)
79 case c == '\t':
80 b.WriteString(`\t`)
81 case c < 0x20:
82 b.WriteString(`\u00`)
83 b.WriteByte("0123456789abcdef"[c>>4])
84 b.WriteByte("0123456789abcdef"[c&0xf])
85 default:
86 b.WriteByte(c)
87 }
88 }
89 b.WriteByte('"')
90 return b.String()
91}