json.gno
4.43 Kb ยท 182 lines
1package chess
2
3import (
4 "bytes"
5 "errors"
6 "strconv"
7 "time"
8
9 "gno.land/p/morgan/chess"
10 "gno.land/p/morgan/chess/glicko2"
11 "gno.land/r/sys/users"
12)
13
14// This file contains a bunch of JSON marshalers.
15// These should disappear eventually!
16// https://github.com/gnolang/gno/issues/1655
17
18func (g Game) MarshalJSON() (retBytes []byte, err error) {
19 var b bytes.Buffer
20 b.WriteByte('{')
21
22 nilAddr := func(na *address) string {
23 if na == nil {
24 return `null`
25 }
26 return `"` + na.String() + `"`
27 }
28 mjson := func(s string, val interface{ MarshalJSON() ([]byte, error) }, comma bool) {
29 if err != nil {
30 return
31 }
32 var res []byte
33 res, err = val.MarshalJSON()
34 if err != nil {
35 return
36 }
37 b.WriteString(`"` + s + `":`)
38 b.Write(res)
39 if comma {
40 b.WriteByte(',')
41 }
42 }
43
44 b.WriteString(`"id":"` + g.ID + `",`)
45 b.WriteString(`"white":"` + g.White.String() + `",`)
46 b.WriteString(`"black":"` + g.Black.String() + `",`)
47
48 mjson("position", jsonPosition{g.Position}, true)
49 mjson("state", g.State, true)
50 mjson("winner", g.Winner, true)
51 if err != nil {
52 return
53 }
54
55 b.WriteString(`"creator":"` + g.Creator.String() + `",`)
56 b.WriteString(`"created_at":"` + g.CreatedAt.Format(time.RFC3339) + `",`)
57 b.WriteString(`"draw_offerer":` + nilAddr(g.DrawOfferer) + ",")
58 b.WriteString(`"concluder":` + nilAddr(g.Concluder) + ",")
59
60 mjson("time", g.Time, false)
61 if err != nil {
62 return
63 }
64
65 b.WriteByte('}')
66 return b.Bytes(), nil
67}
68
69type jsonPosition struct {
70 chess.Position
71}
72
73func (p jsonPosition) MarshalJSON() ([]byte, error) {
74 var b bytes.Buffer
75 b.WriteByte('{')
76
77 bfen := p.EncodeFEN()
78 b.WriteString(`"fen":"` + bfen + `",`)
79
80 b.WriteString(`"moves":[`)
81
82 for idx, m := range p.Moves {
83 b.WriteString(`"` + m.String() + `"`)
84 if idx != len(p.Moves)-1 {
85 b.WriteByte(',')
86 }
87 }
88
89 b.WriteByte(']')
90 b.WriteByte('}')
91 return b.Bytes(), nil
92}
93
94func (w Winner) MarshalJSON() ([]byte, error) {
95 if n := int(w); n < len(winnerString) {
96 return []byte(`"` + winnerString[n] + `"`), nil
97 }
98 return nil, errors.New("invalid winner value")
99}
100
101func (g GameState) MarshalJSON() ([]byte, error) {
102 if int(g) >= len(gameStatesSnake) {
103 return nil, errors.New("invalid game state")
104 }
105 return []byte(`"` + gameStatesSnake[g] + `"`), nil
106}
107
108func (tc *TimeControl) MarshalJSON() ([]byte, error) {
109 if tc == nil {
110 return []byte("null"), nil
111 }
112 var buf bytes.Buffer
113
114 buf.WriteByte('{')
115 buf.WriteString(`"seconds":` + strconv.Itoa(tc.Seconds) + `,`)
116 buf.WriteString(`"increment":` + strconv.Itoa(tc.Increment) + `,`)
117 buf.WriteString(`"started_at":"` + tc.StartedAt.Format(time.RFC3339) + `",`)
118
119 buf.WriteString(`"move_timestamps":[`)
120 for idx, mt := range tc.MoveTimestamps {
121 buf.WriteString(`"` + mt.Format(time.RFC3339) + `"`)
122 if idx != len(tc.MoveTimestamps)-1 {
123 buf.WriteByte(',')
124 }
125 }
126 buf.WriteString("],")
127
128 buf.WriteString(`"white_time":` + strconv.FormatInt(tc.WhiteTime.Milliseconds(), 10) + ",")
129 buf.WriteString(`"black_time":` + strconv.FormatInt(tc.BlackTime.Milliseconds(), 10))
130 buf.WriteByte('}')
131
132 return buf.Bytes(), nil
133}
134
135func (p Player) MarshalJSON() ([]byte, error) {
136 u := users.ResolveAddress(p.Address)
137
138 var buf bytes.Buffer
139 buf.WriteByte('{')
140
141 buf.WriteString(`"address":"` + p.Address.String() + `",`)
142 if u == nil {
143 buf.WriteString(`"username":"",`)
144 } else {
145 buf.WriteString(`"username":"` + u.Name() + `",`)
146 }
147
148 for idx, cat := range categoryList {
149 stat := p.CategoryInfo[cat]
150 buf.WriteString(`"` + cat.String() + `":{`)
151 buf.WriteString(`"wins":` + strconv.Itoa(stat.Wins) + ",")
152 buf.WriteString(`"losses":` + strconv.Itoa(stat.Losses) + ",")
153 buf.WriteString(`"draws":` + strconv.Itoa(stat.Draws) + ",")
154 buf.WriteString(`"rating":`)
155 if res, err := (jsonPlayerRating{stat.PlayerRating}).MarshalJSON(); err != nil {
156 return nil, err
157 } else {
158 buf.Write(res)
159 }
160 buf.WriteByte(',')
161 buf.WriteString(`"position":` + strconv.Itoa(p.LeaderboardPosition(cat)))
162 buf.WriteByte('}')
163 if idx != len(categoryList)-1 {
164 buf.WriteByte(',')
165 }
166 }
167
168 buf.WriteByte('}')
169 return buf.Bytes(), nil
170}
171
172type jsonPlayerRating struct{ *glicko2.PlayerRating }
173
174func (p jsonPlayerRating) MarshalJSON() ([]byte, error) {
175 var buf bytes.Buffer
176 buf.WriteByte('{')
177 buf.WriteString(`"rating":` + strconv.FormatFloat(p.Rating, 'f', 5, 64) + `,`)
178 buf.WriteString(`"deviation":` + strconv.FormatFloat(p.RatingDeviation, 'f', 5, 64) + `,`)
179 buf.WriteString(`"volatility":` + strconv.FormatFloat(p.RatingVolatility, 'f', 5, 64))
180 buf.WriteByte('}')
181 return buf.Bytes(), nil
182}