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