▍ humdrum codex / sportsball v0.1.0
license AGPL-3.0
5.8 KB raw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
package espn

// These types mirror only the fields we consume from ESPN's public
// "site.api.espn.com" scoreboard JSON. Many fields are omitted on purpose;
// the payload is large and we map the rest away in client.go.

type scoreboard struct {
	Events []event `json:"events"`
}

type event struct {
	ID           string        `json:"id"`
	Date         string        `json:"date"`
	Name         string        `json:"name"`
	ShortName    string        `json:"shortName"`
	Status       status        `json:"status"`
	Competitions []competition `json:"competitions"`
}

type competition struct {
	Venue       venue         `json:"venue"`
	Competitors []competitor  `json:"competitors"`
	Status      status        `json:"status"`
	Headlines   []headline    `json:"headlines"`
	Situation   situationJSON `json:"situation"`
}

// situationJSON is the live play state ESPN ships on a baseball competition
// while in progress: the count, outs, occupied bases, and the current
// pitcher/batter (with one-line stat summaries).
type situationJSON struct {
	Balls    int             `json:"balls"`
	Strikes  int             `json:"strikes"`
	Outs     int             `json:"outs"`
	OnFirst  bool            `json:"onFirst"`
	OnSecond bool            `json:"onSecond"`
	OnThird  bool            `json:"onThird"`
	Pitcher  playerSituation `json:"pitcher"`
	Batter   playerSituation `json:"batter"`
	LastPlay lastPlayJSON    `json:"lastPlay"`
}

type playerSituation struct {
	Athlete athleteRef `json:"athlete"`
	Summary string     `json:"summary"`
}

type lastPlayJSON struct {
	Text string `json:"text"`
}

type venue struct {
	FullName string `json:"fullName"`
}

type headline struct {
	ShortText   string `json:"shortLinkText"`
	Description string `json:"description"`
}

type competitor struct {
	HomeAway string   `json:"homeAway"`
	Winner   bool     `json:"winner"`
	Score    string   `json:"score"` // ESPN sends score as a string
	Team     teamJSON `json:"team"`
	Records  []record `json:"records"`
}

type record struct {
	Type    string `json:"type"`
	Summary string `json:"summary"`
}

type teamJSON struct {
	ID               string `json:"id"`
	Abbreviation     string `json:"abbreviation"`
	Name             string `json:"name"`
	ShortDisplayName string `json:"shortDisplayName"`
	DisplayName      string `json:"displayName"`
	Color            string `json:"color"`
	AlternateColor   string `json:"alternateColor"`
}

type status struct {
	DisplayClock string     `json:"displayClock"`
	Period       int        `json:"period"`
	Type         statusType `json:"type"`
}

type statusType struct {
	State       string `json:"state"` // "pre" | "in" | "post"
	Completed   bool   `json:"completed"`
	Detail      string `json:"detail"`
	ShortDetail string `json:"shortDetail"`
}

// --- summary endpoint -------------------------------------------------------
// These mirror only the slices of the (large) summary payload we render in the
// detail view: soccer keyEvents and the per-team player box score.

type summary struct {
	KeyEvents []keyEvent `json:"keyEvents"`
	Plays     []play     `json:"plays"`
	Boxscore  boxscore   `json:"boxscore"`
}

// play is one entry in the summary's play-by-play. We consume only scoring
// plays (baseball scoring timeline); the array is large so the rest is ignored.
type play struct {
	Text            string     `json:"text"`
	ScoringPlay     bool       `json:"scoringPlay"`
	AwayScore       int        `json:"awayScore"`
	HomeScore       int        `json:"homeScore"`
	Period          playPeriod `json:"period"`
	Team            eventTeam  `json:"team"`
	AlternativeType altType    `json:"alternativeType"`
}

type playPeriod struct {
	Type         string `json:"type"`         // "Top" | "Bottom"
	Number       int    `json:"number"`       // inning number
	DisplayValue string `json:"displayValue"` // "4th Inning"
}

type altType struct {
	Abbreviation string `json:"abbreviation"` // "HR"
	Text         string `json:"text"`         // "Home Run"
}

type keyEvent struct {
	Type         eventType     `json:"type"`
	Text         string        `json:"text"`
	ShortText    string        `json:"shortText"`
	Period       eventPeriod   `json:"period"`
	Clock        eventClock    `json:"clock"`
	ScoringPlay  bool          `json:"scoringPlay"`
	Team         eventTeam     `json:"team"`
	Participants []participant `json:"participants"`
}

type eventType struct {
	Text string `json:"text"`
	Type string `json:"type"`
}

type eventPeriod struct {
	Number int `json:"number"`
}

type eventClock struct {
	DisplayValue string `json:"displayValue"`
}

type eventTeam struct {
	ID          string `json:"id"`
	DisplayName string `json:"displayName"`
}

type participant struct {
	Athlete athleteRef `json:"athlete"`
}

type athleteRef struct {
	DisplayName string `json:"displayName"`
	ShortName   string `json:"shortName"`
}

type boxscore struct {
	Players []playerBox   `json:"players"`
	Teams   []teamStatBox `json:"teams"`
}

// teamStatBox is one team's flat team-level stat list from the soccer summary
// boxscore (possession, shots, corners…). homeAway pairs the two sides.
type teamStatBox struct {
	HomeAway   string         `json:"homeAway"`
	Statistics []teamStatJSON `json:"statistics"`
}

type teamStatJSON struct {
	Name         string `json:"name"`         // "possessionPct", "totalShots"
	Label        string `json:"label"`        // "Possession", "SHOTS"
	DisplayValue string `json:"displayValue"` // "63.2", "11"
}

type playerBox struct {
	Team       teamJSON    `json:"team"`
	Statistics []statGroup `json:"statistics"`
}

type statGroup struct {
	Name        string       `json:"name"`
	Type        string       `json:"type"`
	DisplayName string       `json:"displayName"`
	Labels      []string     `json:"labels"`
	Athletes    []athleteRow `json:"athletes"`
}

type athleteRow struct {
	Athlete athleteRef `json:"athlete"`
	Stats   []string   `json:"stats"`
}