Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}