sportdb-parser 0.7.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/Manifest.txt +8 -3
- data/Rakefile +23 -0
- data/lib/sportdb/parser/debuggable.rb +53 -0
- data/lib/sportdb/parser/lexer-logger.rb +20 -0
- data/lib/sportdb/parser/lexer-on_goal.rb +1 -6
- data/lib/sportdb/parser/lexer-on_prop_misc.rb +14 -1
- data/lib/sportdb/parser/lexer-on_top.rb +8 -0
- data/lib/sportdb/parser/lexer-tokenize.rb +22 -3
- data/lib/sportdb/parser/lexer.rb +27 -51
- data/lib/sportdb/parser/parse_tree--core.rb +29 -0
- data/lib/sportdb/parser/parse_tree-match.rb +309 -0
- data/lib/sportdb/parser/parse_tree-props.rb +233 -0
- data/lib/sportdb/parser/parse_tree.rb +202 -0
- data/lib/sportdb/parser/parser-top.rb +102 -0
- data/lib/sportdb/parser/parser.rb +1069 -909
- data/lib/sportdb/parser/token-geo.rb +1 -1
- data/lib/sportdb/parser/token-goals.rb +0 -8
- data/lib/sportdb/parser/token-prop.rb +40 -0
- data/lib/sportdb/parser/token.rb +33 -0
- data/lib/sportdb/parser/version.rb +2 -2
- data/lib/sportdb/parser.rb +45 -47
- metadata +10 -5
- data/lib/sportdb/parser/racc_parser.rb +0 -92
- data/lib/sportdb/parser/racc_tree.rb +0 -524
- /data/lib/sportdb/parser/{parser_runtime.rb → parser-runtime.rb} +0 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
module SportDb
|
|
2
|
+
class Parser
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
MatchLineBye = Struct.new( :team, :note ) do
|
|
7
|
+
def pretty_print( q )
|
|
8
|
+
q.group( 4, '<MatchLineBye ', '>') do ## group( indent, open, close)
|
|
9
|
+
q.text( "#{team} bye")
|
|
10
|
+
if note
|
|
11
|
+
q.text( " note=" )
|
|
12
|
+
q.pp( note )
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end # MatchLineBye
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
MatchLineLegs = Struct.new( :team1, :team2,
|
|
22
|
+
:score ) do
|
|
23
|
+
def pretty_print( q )
|
|
24
|
+
q.group( 4, '<MatchLineLegs ', '>') do ## group( indent, open, close)
|
|
25
|
+
q.text( "#{team1} v #{team2}")
|
|
26
|
+
|
|
27
|
+
members.zip(values) do |name, value|
|
|
28
|
+
next if [:team1, :team2].include?( name )
|
|
29
|
+
next if value.nil?
|
|
30
|
+
|
|
31
|
+
q.breakable
|
|
32
|
+
q.text( "#{name}=" )
|
|
33
|
+
q.pp( value )
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
#
|
|
41
|
+
# note: use two status attributes for now
|
|
42
|
+
# 1) inline_status and 2) (note_)status
|
|
43
|
+
# for now e.g. A abd. B vs A v B [abadoned]
|
|
44
|
+
# A 3-0 awd B vs A 3-0 B [awarded]
|
|
45
|
+
# note - BOTH might be present at the same time
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
MatchLine = Struct.new( :header, :tty, ## tty = TELETYPE MODE for teams and score!!
|
|
49
|
+
:num, :date, :time, :time_local, :year,
|
|
50
|
+
:team1, :team2,
|
|
51
|
+
:score,
|
|
52
|
+
:status, :status_inline, :status_note,
|
|
53
|
+
:round_inline_short, :round_inline_big,
|
|
54
|
+
:geo,
|
|
55
|
+
:neutral, ## true/false - NOT -home/away - neutral ground
|
|
56
|
+
:note,
|
|
57
|
+
:att ) do ## change to geos - why? why not?
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def as_json(*)
|
|
61
|
+
h = { 'team1' => team1.as_json,
|
|
62
|
+
'team2' => team2.as_json,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
members.zip(values) do |name, value|
|
|
66
|
+
next if [:team1, :team2].include?( name )
|
|
67
|
+
next if value.nil?
|
|
68
|
+
|
|
69
|
+
h[name.to_s] = value.as_json
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
['<MatchLine>', h]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def pretty_print( q )
|
|
77
|
+
q.group( 4, '<MatchLine ', '>') do ## group( indent, open, close)
|
|
78
|
+
q.text( "#{team1} v #{team2}")
|
|
79
|
+
|
|
80
|
+
members.zip(values) do |name, value|
|
|
81
|
+
next if [:team1, :team2].include?( name )
|
|
82
|
+
next if value.nil?
|
|
83
|
+
|
|
84
|
+
q.breakable
|
|
85
|
+
q.text( "#{name}=" )
|
|
86
|
+
q.pp( value )
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
end # struct MatchLine
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
GoalLine = Struct.new( :goals ) do
|
|
96
|
+
|
|
97
|
+
def as_json(*)
|
|
98
|
+
['<GoalLine>', { 'goals' => goals.as_json }]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def pretty_print( q )
|
|
102
|
+
q.group( 4, '<GoalLine ', '>') do
|
|
103
|
+
q.text( "goals=" )
|
|
104
|
+
q.pp( goals )
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end # GoalLine
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
###
|
|
112
|
+
## change/rename Goal to GoalScorer - why? why not?
|
|
113
|
+
|
|
114
|
+
Goal = Struct.new( :player, :minutes, :count ) do
|
|
115
|
+
|
|
116
|
+
def as_json(*)
|
|
117
|
+
h = { 'player' => player.as_json }
|
|
118
|
+
|
|
119
|
+
h['count'] = count.as_json if count
|
|
120
|
+
h['minutes'] = minutes.as_json if minutes && !minutes.empty?
|
|
121
|
+
|
|
122
|
+
## ['<Goal>', h]
|
|
123
|
+
h # note - return "inline" json object
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def to_s
|
|
128
|
+
buf = String.new
|
|
129
|
+
buf << "#{player}"
|
|
130
|
+
if count
|
|
131
|
+
buf << (" " + count.inspect + ",")
|
|
132
|
+
else
|
|
133
|
+
if minutes.nil? || minutes.empty?
|
|
134
|
+
## add nothing if no minutes available/present
|
|
135
|
+
else
|
|
136
|
+
buf << " "
|
|
137
|
+
buf << minutes.map { |min| min.to_s }.join(' ')
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
buf
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def pretty_print( q )
|
|
144
|
+
q.text( to_s )
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
## check - use a different name e.g. GoalLineScore or such - why? why not?
|
|
150
|
+
GoalLineAlt = Struct.new( :goals ) do
|
|
151
|
+
def pretty_print( q )
|
|
152
|
+
q.group( 4, '<GoalLineAlt ', '>') do
|
|
153
|
+
q.text( "goals=" )
|
|
154
|
+
q.pp( goals )
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end # GoalLineAlt
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
##
|
|
161
|
+
## score and player REQUIRED
|
|
162
|
+
## note - (goal) minute is optional
|
|
163
|
+
## if no minute goal type is optional e.g. "standalone" (p), (og), etc.
|
|
164
|
+
|
|
165
|
+
GoalAlt = Struct.new( :score, :player, :minute, :goal_type ) do
|
|
166
|
+
def to_s
|
|
167
|
+
buf = String.new
|
|
168
|
+
buf << "#{score[0]}-#{score[1]}"
|
|
169
|
+
buf << " #{player}"
|
|
170
|
+
buf << " #{minute}" if minute
|
|
171
|
+
buf << " #{goal_type}" if goal_type
|
|
172
|
+
buf
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def pretty_print( q )
|
|
176
|
+
q.text( to_s )
|
|
177
|
+
end
|
|
178
|
+
end # GoalAlt
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
GoalLineCompat = Struct.new( :goals ) do
|
|
183
|
+
def pretty_print( q )
|
|
184
|
+
q.group( 4, '<GoalLineCompat ', '>') do
|
|
185
|
+
q.text( "goals=" )
|
|
186
|
+
q.pp( goals )
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end # GoalLineCompat
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
##
|
|
193
|
+
## minute and player REQUIRED
|
|
194
|
+
## note - score (e.g. 1-1) is optional
|
|
195
|
+
## goal type is optional e.g. "standalone" (p), (og), etc.
|
|
196
|
+
|
|
197
|
+
GoalCompat = Struct.new( :score, :player, :minute, :goal_type ) do
|
|
198
|
+
def to_s
|
|
199
|
+
buf = String.new
|
|
200
|
+
buf << "#{minute}"
|
|
201
|
+
buf << " #{player}"
|
|
202
|
+
buf << " #{goal_type}" if goal_type
|
|
203
|
+
buf << " #{score[0]}-#{score[1]}" if score
|
|
204
|
+
buf
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def pretty_print( q )
|
|
208
|
+
q.text( to_s )
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
## FIX/FIX/FIX
|
|
215
|
+
## split into Minute and
|
|
216
|
+
## GoalMinute (Minute+GoalType)
|
|
217
|
+
##
|
|
218
|
+
## fix - move :og, :pen to Goal if possible - why? why not?
|
|
219
|
+
## or change to GoalMinute ???
|
|
220
|
+
##
|
|
221
|
+
## fix!!! split into GoalMinute and Minute
|
|
222
|
+
## goal_minute incl. :og, :pen, :freekick, :header,
|
|
223
|
+
## seconds etc.
|
|
224
|
+
##
|
|
225
|
+
## GoalMinute = Minute + GoalType !!!
|
|
226
|
+
|
|
227
|
+
GoalMinute = Struct.new( :m, :offset, :secs,
|
|
228
|
+
:og, :pen, :header, :freekick,
|
|
229
|
+
) do
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def as_json(*) to_s; end
|
|
233
|
+
|
|
234
|
+
def to_s
|
|
235
|
+
buf = String.new
|
|
236
|
+
buf << "#{m}"
|
|
237
|
+
buf << "'"
|
|
238
|
+
buf << "+#{offset}" if offset
|
|
239
|
+
buf << "(og)" if og
|
|
240
|
+
buf << "(p)" if pen
|
|
241
|
+
buf << "(f)" if freekick
|
|
242
|
+
buf << "(h)" if header
|
|
243
|
+
buf << " (#{secs} secs)" if secs
|
|
244
|
+
buf
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def pretty_print( q )
|
|
248
|
+
q.text( to_s )
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
### quick hack:
|
|
252
|
+
### split struct into Minute+GoalType structs
|
|
253
|
+
def to_minute
|
|
254
|
+
Minute.new( m: m,
|
|
255
|
+
offset: offset,
|
|
256
|
+
secs: secs )
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def to_goal_type
|
|
260
|
+
if og || pen || header || freekick
|
|
261
|
+
GoalType.new( og: og,
|
|
262
|
+
pen: pen,
|
|
263
|
+
header: header,
|
|
264
|
+
freekick: freekick )
|
|
265
|
+
else
|
|
266
|
+
nil ## note - return nil; if no goal type present!!
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
GoalType = Struct.new( :og, :pen, :header, :freekick ) do
|
|
273
|
+
def to_s
|
|
274
|
+
buf = String.new
|
|
275
|
+
buf << "(og)" if og
|
|
276
|
+
buf << "(pen)" if pen
|
|
277
|
+
buf << "(f)" if freekick
|
|
278
|
+
buf << "(h)" if header
|
|
279
|
+
buf
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def pretty_print( q )
|
|
283
|
+
q.text( to_s )
|
|
284
|
+
end
|
|
285
|
+
end # GoalType
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
Minute = Struct.new( :m, :offset, :secs ) do
|
|
290
|
+
def as_json(*) to_s; end
|
|
291
|
+
|
|
292
|
+
def to_s
|
|
293
|
+
buf = String.new
|
|
294
|
+
buf << "#{m}"
|
|
295
|
+
buf << "'"
|
|
296
|
+
buf << "+#{offset}" if offset
|
|
297
|
+
buf << "/#{secs} secs" if secs
|
|
298
|
+
buf
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def pretty_print( q )
|
|
302
|
+
q.text( to_s )
|
|
303
|
+
end
|
|
304
|
+
end # Minute
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
end # class Parser
|
|
309
|
+
end # module SportDb
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
module SportDb
|
|
2
|
+
class Parser
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
=begin
|
|
6
|
+
RefereeLine = Struct.new( :name, :country ) do
|
|
7
|
+
def pretty_print( printer )
|
|
8
|
+
printer.text( "<RefereeLine " )
|
|
9
|
+
printer.text( name )
|
|
10
|
+
printer.text( " (#{country})" ) if country
|
|
11
|
+
printer.text( ">" )
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
=end
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## support multiple referees (incl. assistant refs etc.)
|
|
18
|
+
RefereeLine = Struct.new( :referees ) do
|
|
19
|
+
def pretty_print( q )
|
|
20
|
+
q.group( 4, '<RefereeLine ', '>') do
|
|
21
|
+
q.pp( referees )
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end # RefereeLine
|
|
25
|
+
|
|
26
|
+
Referee = Struct.new( :name, :country ) do
|
|
27
|
+
def to_s
|
|
28
|
+
buf = String.new
|
|
29
|
+
buf << name
|
|
30
|
+
buf << " (#{country})" if country
|
|
31
|
+
buf
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def pretty_print( q )
|
|
35
|
+
q.text( to_s )
|
|
36
|
+
end
|
|
37
|
+
end # Referee
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
AttendanceLine = Struct.new( :att ) do
|
|
41
|
+
def pretty_print( q )
|
|
42
|
+
q.group( 4, '<AttendanceLine ', '>') do
|
|
43
|
+
q.pp( att )
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end # AttendanceLine
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
PenaltiesLine = Struct.new( :penalties ) do
|
|
52
|
+
def as_json(*)
|
|
53
|
+
['<PenaltiesLine>', { 'penalties' => penalties.as_json }]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def pretty_print( q )
|
|
57
|
+
q.group( 4, '< ', '>') do
|
|
58
|
+
q.pp( penalties )
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end # PenaltiesLine
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
Penalty = Struct.new( :name, :score, :note ) do
|
|
65
|
+
def as_json(*)
|
|
66
|
+
h = { 'name' => name }
|
|
67
|
+
h['score'] = "#{score[0]}-#{score[1]}" if score
|
|
68
|
+
h['note'] = "(#{note})" if note
|
|
69
|
+
|
|
70
|
+
## ['<Penalty>', h]
|
|
71
|
+
h # note - return "inline" json object
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def to_s
|
|
75
|
+
buf = String.new
|
|
76
|
+
buf << "#{score[0]}-#{score[1]} " if score
|
|
77
|
+
buf << name
|
|
78
|
+
buf << " (#{note})" if note
|
|
79
|
+
buf
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def pretty_print( q )
|
|
84
|
+
q.text( to_s )
|
|
85
|
+
end
|
|
86
|
+
end # Penalty
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
## find a better name for player (use bookings?) - note - red/yellow card for trainer possible
|
|
92
|
+
CardsLine = Struct.new( :type,
|
|
93
|
+
:bookings,
|
|
94
|
+
) do
|
|
95
|
+
def pretty_print( q )
|
|
96
|
+
q.group( 4, '<CardsLine ', '>') do
|
|
97
|
+
q.text( type )
|
|
98
|
+
## note - either (all-in-one or undetermined) bookings: []
|
|
99
|
+
## or bookings1/2 aka: [[],[]]
|
|
100
|
+
q.text( " bookings=" )
|
|
101
|
+
q.pp( bookings )
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end # CardsLine
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
Booking = Struct.new( :name, :minute ) do
|
|
108
|
+
def to_s
|
|
109
|
+
buf = String.new
|
|
110
|
+
buf << "#{name}"
|
|
111
|
+
buf << " #{minute.to_s}" if minute
|
|
112
|
+
buf
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def pretty_print( q )
|
|
116
|
+
q.text( to_s )
|
|
117
|
+
end
|
|
118
|
+
end # Booking
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
##
|
|
124
|
+
## change :lineup to :lineups (e.g. requires array of lineups)
|
|
125
|
+
LineupLine = Struct.new( :team, :lineup, :coach ) do
|
|
126
|
+
def as_json(*)
|
|
127
|
+
h = { 'team' => team.as_json,
|
|
128
|
+
'lineups' => lineup.as_json
|
|
129
|
+
}
|
|
130
|
+
h['coach'] = coach.as_json if coach
|
|
131
|
+
|
|
132
|
+
['<LineupLine>', h]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def pretty_print( q )
|
|
136
|
+
q.group( 4, '<LineupLine ', '>') do
|
|
137
|
+
q.text( team )
|
|
138
|
+
q.text( ' ' )
|
|
139
|
+
|
|
140
|
+
## todo/fix - check for "flat" items - no formation
|
|
141
|
+
## or empty lineup (possible?)
|
|
142
|
+
## add formation e.g. (1-) 3-4-2-1
|
|
143
|
+
formation = lineup.map { |item| item.size }
|
|
144
|
+
## note - remove first entry (assume it's 1 for goalee!)
|
|
145
|
+
formation.shift
|
|
146
|
+
q.text( formation.join('-'))
|
|
147
|
+
q.text( ' ')
|
|
148
|
+
|
|
149
|
+
q.pp( lineup )
|
|
150
|
+
|
|
151
|
+
if coach
|
|
152
|
+
q.breakable
|
|
153
|
+
q.text( "coach=" + coach )
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end # LineupLine
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
Lineup = Struct.new( :name, :captain, :cards, :sub ) do
|
|
161
|
+
def as_json(*)
|
|
162
|
+
h = { 'name' => name.as_json }
|
|
163
|
+
h['captain'] = captain.as_json if captain
|
|
164
|
+
h['cards'] = cards.as_json if cards
|
|
165
|
+
h['sub'] = sub.as_json if sub
|
|
166
|
+
|
|
167
|
+
## ['<Lineup>', h]
|
|
168
|
+
h ## note - return "inline" json object (not tagged array with json object)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def pretty_print( q )
|
|
172
|
+
q.group( 0, '', '') do ## group( indent, open, close)
|
|
173
|
+
q.text( name )
|
|
174
|
+
q.text( ' [c]' ) if captain
|
|
175
|
+
|
|
176
|
+
if cards
|
|
177
|
+
q.text( ' ' )
|
|
178
|
+
q.pp( cards )
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
if sub
|
|
182
|
+
q.breakable ## can become either a space or a newline
|
|
183
|
+
q.pp( sub )
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end # Lineup
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
Card = Struct.new( :name, :minute ) do
|
|
194
|
+
def as_json(*) to_s; end
|
|
195
|
+
|
|
196
|
+
def to_s
|
|
197
|
+
buf = String.new
|
|
198
|
+
buf << "#{name}"
|
|
199
|
+
buf << " #{minute.to_s}" if minute
|
|
200
|
+
buf
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def pretty_print( q )
|
|
204
|
+
q.text( to_s )
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
##
|
|
211
|
+
## fix-fix-fix
|
|
212
|
+
## change :sub to :lineup - why? why not?
|
|
213
|
+
|
|
214
|
+
Sub = Struct.new( :minute, :sub ) do
|
|
215
|
+
def as_json(*)
|
|
216
|
+
h = { 'lineup' => sub.as_json }
|
|
217
|
+
h['minute'] = minute.as_json if minute
|
|
218
|
+
|
|
219
|
+
## ['<Sub>', h]
|
|
220
|
+
h # note - return "inline" json object (not tagged array with json object)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def pretty_print( q )
|
|
224
|
+
q.group( 0, '(', ')') do
|
|
225
|
+
q.text( "#{minute.to_s} " ) if minute
|
|
226
|
+
q.pp( sub )
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end # Sub
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
end # class Parser
|
|
233
|
+
end # module SportDb
|