fifadat 0.0.1
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 +7 -0
- data/CHANGELOG.md +4 -0
- data/Manifest.txt +91 -0
- data/README.md +24 -0
- data/Rakefile +32 -0
- data/bin/fifadat +14 -0
- data/lib/fifadat/api-config.rb +120 -0
- data/lib/fifadat/api.rb +110 -0
- data/lib/fifadat/config/codes_club-europe.csv +59 -0
- data/lib/fifadat/config/codes_club.csv +41 -0
- data/lib/fifadat/config/codes_nati.csv +6 -0
- data/lib/fifadat/config/seasons/ar.csv +7 -0
- data/lib/fifadat/config/seasons/at.csv +7 -0
- data/lib/fifadat/config/seasons/at.cup.csv +5 -0
- data/lib/fifadat/config/seasons/au.csv +7 -0
- data/lib/fifadat/config/seasons/be.csv +7 -0
- data/lib/fifadat/config/seasons/br.csv +6 -0
- data/lib/fifadat/config/seasons/ch.csv +7 -0
- data/lib/fifadat/config/seasons/clubworldcup.csv +2 -0
- data/lib/fifadat/config/seasons/cn.csv +7 -0
- data/lib/fifadat/config/seasons/co.csv +7 -0
- data/lib/fifadat/config/seasons/copa.l.csv +7 -0
- data/lib/fifadat/config/seasons/copa.s.csv +7 -0
- data/lib/fifadat/config/seasons/cz.csv +7 -0
- data/lib/fifadat/config/seasons/de.2.csv +6 -0
- data/lib/fifadat/config/seasons/de.csv +7 -0
- data/lib/fifadat/config/seasons/de.cup.csv +6 -0
- data/lib/fifadat/config/seasons/eg.csv +6 -0
- data/lib/fifadat/config/seasons/eng.2.csv +7 -0
- data/lib/fifadat/config/seasons/eng.csv +7 -0
- data/lib/fifadat/config/seasons/eng.facup.csv +6 -0
- data/lib/fifadat/config/seasons/es.csv +6 -0
- data/lib/fifadat/config/seasons/fr.csv +6 -0
- data/lib/fifadat/config/seasons/gr.csv +7 -0
- data/lib/fifadat/config/seasons/hu.csv +6 -0
- data/lib/fifadat/config/seasons/ie.csv +6 -0
- data/lib/fifadat/config/seasons/il.csv +6 -0
- data/lib/fifadat/config/seasons/interconticup.csv +24 -0
- data/lib/fifadat/config/seasons/is.csv +6 -0
- data/lib/fifadat/config/seasons/it.csv +7 -0
- data/lib/fifadat/config/seasons/it.cup.csv +5 -0
- data/lib/fifadat/config/seasons/jp.csv +7 -0
- data/lib/fifadat/config/seasons/kr.csv +7 -0
- data/lib/fifadat/config/seasons/lu.csv +3 -0
- data/lib/fifadat/config/seasons/ma.csv +3 -0
- data/lib/fifadat/config/seasons/mls.csv +6 -0
- data/lib/fifadat/config/seasons/mx.2.csv +5 -0
- data/lib/fifadat/config/seasons/mx.csv +6 -0
- data/lib/fifadat/config/seasons/mx.cup.csv +3 -0
- data/lib/fifadat/config/seasons/nir.csv +6 -0
- data/lib/fifadat/config/seasons/nl.csv +7 -0
- data/lib/fifadat/config/seasons/no.csv +6 -0
- data/lib/fifadat/config/seasons/pl.csv +6 -0
- data/lib/fifadat/config/seasons/pt.csv +7 -0
- data/lib/fifadat/config/seasons/sa.csv +7 -0
- data/lib/fifadat/config/seasons/sco.csv +7 -0
- data/lib/fifadat/config/seasons/se.csv +7 -0
- data/lib/fifadat/config/seasons/tn.csv +6 -0
- data/lib/fifadat/config/seasons/tr.csv +7 -0
- data/lib/fifadat/config/seasons/uefa.cl.csv +7 -0
- data/lib/fifadat/config/seasons/uefa.con.csv +6 -0
- data/lib/fifadat/config/seasons/uefa.europa.csv +6 -0
- data/lib/fifadat/config/seasons/uy.csv +6 -0
- data/lib/fifadat/config/seasons/wal.csv +6 -0
- data/lib/fifadat/config/seasons/worldcup.csv +24 -0
- data/lib/fifadat/config/seasons/za.csv +6 -0
- data/lib/fifadat/errata.rb +59 -0
- data/lib/fifadat/helper.rb +46 -0
- data/lib/fifadat/json.rb +113 -0
- data/lib/fifadat/pp/build_match.rb +105 -0
- data/lib/fifadat/pp/build_report.rb +135 -0
- data/lib/fifadat/pp/convert-reports.rb +114 -0
- data/lib/fifadat/pp/convert.rb +163 -0
- data/lib/fifadat/pp/goals-calc_score.rb +58 -0
- data/lib/fifadat/pp/goals.rb +89 -0
- data/lib/fifadat/pp/helper-date.rb +13 -0
- data/lib/fifadat/pp/helper-minute.rb +81 -0
- data/lib/fifadat/pp/helper-score.rb +139 -0
- data/lib/fifadat/pp/norm.rb +34 -0
- data/lib/fifadat/pp/officials.rb +86 -0
- data/lib/fifadat/pp/penalties.rb +132 -0
- data/lib/fifadat/pp/players.rb +323 -0
- data/lib/fifadat/pp/stadiums.rb +99 -0
- data/lib/fifadat/pp/stages.rb +119 -0
- data/lib/fifadat/pp/substitutions.rb +444 -0
- data/lib/fifadat/pp/teams.rb +91 -0
- data/lib/fifadat/ppdebug.rb +128 -0
- data/lib/fifadat/ppmatch.rb +78 -0
- data/lib/fifadat/prepare.rb +117 -0
- data/lib/fifadat/tool.rb +184 -0
- data/lib/fifadat/types.rb +166 -0
- data/lib/fifadat.rb +54 -0
- metadata +215 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def build_players( recs )
|
|
5
|
+
recs = recs.map { |h| build_player( h ) }
|
|
6
|
+
recs
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# TYPE_PLAYER_POS = {
|
|
11
|
+
# 0 => 'GK',
|
|
12
|
+
# 1 => 'DF',
|
|
13
|
+
# 2 => 'MF',
|
|
14
|
+
# 3 => 'FW',
|
|
15
|
+
# 4 => '??',
|
|
16
|
+
# 5 => '??',
|
|
17
|
+
# 6 => '??'
|
|
18
|
+
# }
|
|
19
|
+
|
|
20
|
+
def build_player( h )
|
|
21
|
+
name = desc( h['PlayerName'] )
|
|
22
|
+
|
|
23
|
+
if name.nil?
|
|
24
|
+
## "PlayerName"=>[],
|
|
25
|
+
## "ShortName"=>[{"Locale"=>"en-gb", "Description"=>"S. Lainer"}],
|
|
26
|
+
|
|
27
|
+
## hack:
|
|
28
|
+
## use shortname
|
|
29
|
+
name = desc( h['ShortName'] )
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
if name.nil?
|
|
33
|
+
## puts "name is nil:"
|
|
34
|
+
## pp h
|
|
35
|
+
## exit 1
|
|
36
|
+
## report/log error/warn
|
|
37
|
+
##
|
|
38
|
+
## quick fix use N.N. for now
|
|
39
|
+
name = 'N.N.'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
## name = norm_player( name )
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
short_name = desc( h['ShortName'] )
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
## todo/check - add IdCountry if available??
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
status = h['Status']
|
|
52
|
+
assert( [1,2].include?( status ), "player status 1,2 expected; got #{h.inspect}")
|
|
53
|
+
|
|
54
|
+
## what is pos 6 ??
|
|
55
|
+
## e.g.
|
|
56
|
+
## !! ASSERT FAILED
|
|
57
|
+
## {"IdPlayer"=>"419456", "IdTeam"=>"32759", "ShirtNumber"=>4, "Status"=>1,
|
|
58
|
+
## "PlayerName"=>[{"Locale"=>"en-GB", "Description"=>"Ismaila COULIBALY"}],
|
|
59
|
+
## "ShortName"=>[{"Locale"=>"en-GB", "Description"=>"Ismaila COULIBALY"}],
|
|
60
|
+
## "Position"=>6, "PlayerPicture"=>nil,
|
|
61
|
+
## "FieldStatus"=>2, "LineupX"=>nil, "LineupY"=>nil}
|
|
62
|
+
##
|
|
63
|
+
## what is pos 5 ??
|
|
64
|
+
## e.g.
|
|
65
|
+
## {"IdPlayer"=>"7czui1ih46j3zitzysxvjqjv8", "IdTeam"=>"2000019848", "ShirtNumber"=>33,
|
|
66
|
+
## "Status"=>1,
|
|
67
|
+
## "PlayerName"=>[{"Locale"=>"en-gb", "Description"=>"Maximilian Hennig"}],
|
|
68
|
+
## "ShortName"=>[{"Locale"=>"en-gb", "Description"=>"M. Hennig"}],
|
|
69
|
+
## "Position"=>5, "PlayerPicture"=>nil, "FieldStatus"=>2, "LineupX"=>nil, "LineupY"=>nil}
|
|
70
|
+
##
|
|
71
|
+
## what is pos 4 ??
|
|
72
|
+
## {"IdPlayer"=>"254150", "IdTeam"=>"2000017585", "ShirtNumber"=>15,
|
|
73
|
+
## "Status"=>2, "SpecialStatus"=>nil, "Captain"=>false,
|
|
74
|
+
## "PlayerName"=>[{"Locale"=>"en-GB", "Description"=>"Nemanja RNIC"}],
|
|
75
|
+
## "ShortName"=>[{"Locale"=>"en-gb", "Description"=>"N. Rnić"}],
|
|
76
|
+
## "Position"=>4, "PlayerPicture"=>nil, "FieldStatus"=>1, "LineupX"=>nil, "LineupY"=>nil}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
pos = h['Position']
|
|
80
|
+
assert( [0,1,2,3,4,5,6].include?( pos ), "player pos 0,1,2,3,4,5,6 expected; got #{h.inspect}" )
|
|
81
|
+
|
|
82
|
+
## 0 - is always goal keeper
|
|
83
|
+
## check meaning of 1 to 6
|
|
84
|
+
## on website !!!
|
|
85
|
+
## pos is NOT (simply) matching tactics/formation (index number)!!
|
|
86
|
+
|
|
87
|
+
rec = { id: h['IdPlayer'],
|
|
88
|
+
name: name,
|
|
89
|
+
short_name: short_name,
|
|
90
|
+
status: status,
|
|
91
|
+
pos: pos,
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
## check for shirtNumber too
|
|
95
|
+
num = h['ShirtNumber']
|
|
96
|
+
rec[:num] = num if num
|
|
97
|
+
|
|
98
|
+
rec[:captain] = true if h['Captain']
|
|
99
|
+
|
|
100
|
+
rec
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class Players
|
|
106
|
+
def initialize
|
|
107
|
+
@recs = {}
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def add( recs ) ## rename to collect - why? why not?
|
|
111
|
+
recs.each { |h| _add( build_player(h)) }
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _add( new_rec )
|
|
116
|
+
rec = @recs[ new_rec[:id] ]
|
|
117
|
+
if rec.nil?
|
|
118
|
+
rec = new_rec
|
|
119
|
+
rec[:count] = 1 ## add counter - why? why not?
|
|
120
|
+
@recs[ new_rec[:id]] = new_rec
|
|
121
|
+
|
|
122
|
+
else
|
|
123
|
+
rec[:count] += 1
|
|
124
|
+
## assert attributes equal - why? why not?
|
|
125
|
+
|
|
126
|
+
assert( new_rec[:name] == rec[:name] &&
|
|
127
|
+
new_rec[:short_name] == rec[:short_name],
|
|
128
|
+
"player records NOT matching - #{rec.pretty_inspect} != #{new_rec.pretty_inspect}")
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def find!( id_player )
|
|
133
|
+
rec = @recs[ id_player ]
|
|
134
|
+
raise ArgumentError, "no player w/ id >#{id_player}< found; sorry" if rec.nil?
|
|
135
|
+
rec
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
###
|
|
140
|
+
## todo/check
|
|
141
|
+
## add alias (or rename) starter ??
|
|
142
|
+
## add new subs to status == 2 - why? why not?
|
|
143
|
+
def lineup
|
|
144
|
+
recs = @recs.values.select { |rec| rec[:status] == 1 }
|
|
145
|
+
|
|
146
|
+
recs = recs.map {|rec| rec.except( :id, :status, :count ) }
|
|
147
|
+
recs
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def bench
|
|
151
|
+
recs = @recs.values.select { |rec| rec[:status] == 2 }
|
|
152
|
+
|
|
153
|
+
recs = recs.map {|rec| rec.except( :id, :status, :count ) }
|
|
154
|
+
recs
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
## all players with red or red-yellow card (sent off)
|
|
160
|
+
def sentoff
|
|
161
|
+
recs = @recs.values.select { |rec| rec[:r] || rec[:yr] }
|
|
162
|
+
|
|
163
|
+
=begin
|
|
164
|
+
"id": "395516",
|
|
165
|
+
"name": "Cesar MONTES",
|
|
166
|
+
"short_name": "Cesar MONTES",
|
|
167
|
+
"status": 1,
|
|
168
|
+
"pos": 1,
|
|
169
|
+
"captain": true,
|
|
170
|
+
"count": 1,
|
|
171
|
+
"r": {
|
|
172
|
+
"minute": "90+2'"
|
|
173
|
+
=end
|
|
174
|
+
|
|
175
|
+
## todo/check - add a flag for yellow-red card (e.g. yr=true) - why? why not?
|
|
176
|
+
|
|
177
|
+
recs = recs.map do |rec|
|
|
178
|
+
minute = if rec[:r]
|
|
179
|
+
rec[:r][:minute]
|
|
180
|
+
elsif rec[:yr]
|
|
181
|
+
rec[:yr][:minute]
|
|
182
|
+
else
|
|
183
|
+
raise ArgumentError, "r or yr card expected; got #{rec.inspect}"
|
|
184
|
+
end
|
|
185
|
+
{ name: rec[:name],
|
|
186
|
+
minute: minute }
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
recs
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def redcards
|
|
194
|
+
recs = @recs.values.select { |rec| rec[:r] }
|
|
195
|
+
|
|
196
|
+
recs = recs.map do |rec|
|
|
197
|
+
{ name: rec[:name],
|
|
198
|
+
minute: rec[:r][:minute] }
|
|
199
|
+
end
|
|
200
|
+
recs
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def yellowcards
|
|
204
|
+
recs = @recs.values.select { |rec| rec[:y] }
|
|
205
|
+
|
|
206
|
+
recs = recs.map do |rec|
|
|
207
|
+
{ name: rec[:name],
|
|
208
|
+
minute: rec[:y][:minute] }
|
|
209
|
+
end
|
|
210
|
+
recs
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def yellowredcards
|
|
214
|
+
recs = @recs.values.select { |rec| rec[:yr] }
|
|
215
|
+
|
|
216
|
+
recs = recs.map do |rec|
|
|
217
|
+
{ name: rec[:name],
|
|
218
|
+
minute: rec[:yr][:minute] }
|
|
219
|
+
end
|
|
220
|
+
recs
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def add_bookings( bookings ) ## yellow/red cards
|
|
226
|
+
bookings.each do |b|
|
|
227
|
+
|
|
228
|
+
card = b['Card']
|
|
229
|
+
assert( [0,1,2,3].include?( card ), "card 0/1/2/3 expected; got #{b.pretty_inspect}")
|
|
230
|
+
|
|
231
|
+
##
|
|
232
|
+
## what is card 0? ignore for now
|
|
233
|
+
## Palmeiras v FC Porto 0-0 - 2025-06-15T18:00:00+00:00
|
|
234
|
+
## !! ASSERT FAILED - card 1/2/3 expected; got {"Card"=>0,
|
|
235
|
+
## "Period"=>5,
|
|
236
|
+
## "IdEvent"=>nil,
|
|
237
|
+
## "EventNumber"=>nil,
|
|
238
|
+
## "IdPlayer"=>"495048",
|
|
239
|
+
## "IdCoach"=>nil,
|
|
240
|
+
## "IdTeam"=>"1884426",
|
|
241
|
+
## "Minute"=>"72'",
|
|
242
|
+
## "Reason"=>nil}
|
|
243
|
+
next if card == 0
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
idPlayer = b['IdPlayer']
|
|
247
|
+
|
|
248
|
+
## booking (card) for coach or stuff!!!!
|
|
249
|
+
## skip for now
|
|
250
|
+
next if idPlayer.nil? && (b['IdCoach'] || b['IdStaff'])
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
player = @recs[ idPlayer ]
|
|
254
|
+
assert( player, "booking player not found; sorry - #{b.pretty_inspect}" )
|
|
255
|
+
|
|
256
|
+
## note - parse & reformat minute for keep same format
|
|
257
|
+
## _fmt_minute( *_parse_minute( b['Minute'] ))
|
|
258
|
+
minute = _build_minute( b )
|
|
259
|
+
|
|
260
|
+
if card == 1 ## yellow
|
|
261
|
+
player[ :y ] = { minute: minute }
|
|
262
|
+
elsif card == 2 ## red
|
|
263
|
+
player[ :r ] = { minute: minute }
|
|
264
|
+
elsif card == 3 ## yellow/red
|
|
265
|
+
player[ :yr ] = { minute: minute }
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def add_subs( subs )
|
|
273
|
+
subs.each do |sub|
|
|
274
|
+
|
|
275
|
+
idPlayerOff = sub['IdPlayerOff']
|
|
276
|
+
idPlayerOn = sub['IdPlayerOn']
|
|
277
|
+
|
|
278
|
+
## note - parse & reformat minute for keep same format
|
|
279
|
+
minute = _build_sub_minute( sub )
|
|
280
|
+
|
|
281
|
+
player_off = @recs[ idPlayerOff ]
|
|
282
|
+
player_on = @recs[ idPlayerOn ]
|
|
283
|
+
|
|
284
|
+
##
|
|
285
|
+
## note - skip special case for now
|
|
286
|
+
## with NO PLAYER ON (e.g. idPlayerOn is nil!!)
|
|
287
|
+
## next if idPlayerOn.nil?
|
|
288
|
+
## todo/fix - report/log warning!!!
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
if player_off.nil?
|
|
292
|
+
puts "!! player_off >#{idPlayerOff}< not found in:"
|
|
293
|
+
pp sub
|
|
294
|
+
puts "---"
|
|
295
|
+
pp @recs.values
|
|
296
|
+
exit 1
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
if player_on.nil?
|
|
300
|
+
puts "!! player_on >#{idPlayerOn}< not found in:"
|
|
301
|
+
pp sub
|
|
302
|
+
puts "---"
|
|
303
|
+
pp @recs.values
|
|
304
|
+
exit 1
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
assert( player_off && player_on,
|
|
308
|
+
"subs player_off or player_on not found; sorry" )
|
|
309
|
+
|
|
310
|
+
player_off[ :sub ] = { minute: minute,
|
|
311
|
+
player_ref: player_on }
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def dump
|
|
317
|
+
pp @recs.values
|
|
318
|
+
puts " #{@recs.size} player(s)"
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def size() @recs.size; end
|
|
322
|
+
|
|
323
|
+
end # class Players
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
def build_stadium( h )
|
|
4
|
+
if h
|
|
5
|
+
id = h['IdStadium']
|
|
6
|
+
id_country = h['IdCountry']
|
|
7
|
+
## id_city = h['IdCity']
|
|
8
|
+
|
|
9
|
+
name = desc( h['Name'] )
|
|
10
|
+
city_name = desc( h['CityName'] )
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if name.nil?
|
|
14
|
+
puts "stadium without name:"
|
|
15
|
+
pp h
|
|
16
|
+
exit 1
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
## name, city_name = norm_stadium( name, city_name: city_name )
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
if id.nil?
|
|
23
|
+
## auto-generate id
|
|
24
|
+
## use slug of name plus id_city
|
|
25
|
+
## add city name
|
|
26
|
+
## fix- add 0-9 & dash(-) to name too - why? why not?
|
|
27
|
+
id = name.downcase.gsub( /[^a-z]/, '' )
|
|
28
|
+
id += "_" + city_name.downcase.gsub( /[^a-z]/, '' )
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
rec = { id: id,
|
|
33
|
+
name: name,
|
|
34
|
+
city: city_name
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
rec[:street] = h['Street'] if h['Street']
|
|
38
|
+
|
|
39
|
+
rec[:country] = id_country ### fix - change to cc/country code - why? why not?
|
|
40
|
+
|
|
41
|
+
rec
|
|
42
|
+
else ## assume nil - dummy record
|
|
43
|
+
rec = {
|
|
44
|
+
id: '<nil>',
|
|
45
|
+
name: '?',
|
|
46
|
+
city: '?', ## use nil - why? why not?
|
|
47
|
+
country: '?' ## use nil - why? why not?
|
|
48
|
+
}
|
|
49
|
+
rec
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class Stadiums
|
|
57
|
+
def initialize
|
|
58
|
+
@recs = {}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def add_matches( matches ) ## rename to add_matches - why? why not?
|
|
62
|
+
matches.each_with_index do |m|
|
|
63
|
+
stadium = build_stadium( m['Stadium'] )
|
|
64
|
+
_add( stadium )
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _add( new_rec )
|
|
71
|
+
rec = @recs[ new_rec[:id] ]
|
|
72
|
+
if rec.nil?
|
|
73
|
+
rec = new_rec
|
|
74
|
+
rec[:count] = 1 ## add counter - why? why not?
|
|
75
|
+
@recs[ new_rec[:id]] = new_rec
|
|
76
|
+
else
|
|
77
|
+
rec[:count] += 1
|
|
78
|
+
|
|
79
|
+
## assert attributes equal - why? why not?
|
|
80
|
+
assert( new_rec[:name] == rec[:name] &&
|
|
81
|
+
new_rec[:city] == rec[:city] &&
|
|
82
|
+
new_rec[:country] == rec[:country],
|
|
83
|
+
"stadium records NOT matching - #{rec.pretty_inspect} != #{new_rec.pretty_inspect}")
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def as_json( id: false )
|
|
89
|
+
if id
|
|
90
|
+
@recs.values
|
|
91
|
+
else
|
|
92
|
+
@recs.values.map { |rec| rec.except(:id ) }
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def size() @recs.size; end
|
|
98
|
+
|
|
99
|
+
end # class Stadiums
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
=begin
|
|
4
|
+
[{"IdStage": "286472",
|
|
5
|
+
"Name": [{"Locale": "en-GB", "Description": "Final"}],
|
|
6
|
+
"IdSeason": "286466",
|
|
7
|
+
"SeasonName":
|
|
8
|
+
[{"Locale": "en-GB", "Description": "FIFA Club World Cup Morocco 2022™"}],
|
|
9
|
+
"IdCompetition": "107",
|
|
10
|
+
"StageLevel": null,
|
|
11
|
+
"StartDate": "2023-02-11T19:00:00Z",
|
|
12
|
+
"EndDate": "2023-02-11T19:00:00Z",
|
|
13
|
+
"Type": 0,
|
|
14
|
+
"SequenceOrder": 6,
|
|
15
|
+
"Properties": {"IdIFES": "286472"},
|
|
16
|
+
"IsUpdateable": null},
|
|
17
|
+
=end
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def build_stage( h )
|
|
21
|
+
name = desc( h['Name'] )
|
|
22
|
+
seq = h['SequenceOrder']
|
|
23
|
+
level = h['StageLevel'] ## note - is optional
|
|
24
|
+
|
|
25
|
+
rec = {
|
|
26
|
+
## id: h['IdStage'], ## convert to number - why? why not?
|
|
27
|
+
seq: seq,
|
|
28
|
+
name: name,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
if h['StartDate'] && h['EndDate']
|
|
33
|
+
## note - start/end dates are utc (NOT local)
|
|
34
|
+
start_date = parse_date_utc( h['StartDate'] ) ## expects ...:00Z format
|
|
35
|
+
end_date = parse_date_utc( h['EndDate'] ) ## expects ...:00Z format
|
|
36
|
+
|
|
37
|
+
## check if HH::MM is 00:00
|
|
38
|
+
## only use date for now; ignore time
|
|
39
|
+
## report warn(ing) if time present!!!
|
|
40
|
+
if start_date.hour != 0 || start_date.min != 0 ||
|
|
41
|
+
end_date.hour != 0 || end_date.min != 0
|
|
42
|
+
## issue warn start/end_date with HH:MM (NOT 00:00)
|
|
43
|
+
puts "!! warn: stage start/end_date with HH:MM (expected 00:00)"
|
|
44
|
+
pp h
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
rec[:start_date] = start_date.strftime('%Y-%m-%d')
|
|
48
|
+
rec[:end_date] = end_date.strftime('%Y-%m-%d')
|
|
49
|
+
else
|
|
50
|
+
## maybe add to log later - why? why not?
|
|
51
|
+
## puts "!! warn: stage witouout start/end_date"
|
|
52
|
+
## pp h
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
rec[:count] = 0
|
|
56
|
+
|
|
57
|
+
rec[:level] = level if level
|
|
58
|
+
|
|
59
|
+
rec
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class Stages
|
|
65
|
+
|
|
66
|
+
def self.read( path )
|
|
67
|
+
data = read_json_v2( path )
|
|
68
|
+
obj = new
|
|
69
|
+
obj.add( data['Results'] )
|
|
70
|
+
obj
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def initialize
|
|
75
|
+
@recs = {}
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def add( recs ) ## rename to collect - why? why not?
|
|
79
|
+
recs.each { |h| _add( build_stage(h)) }
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _add( new_rec )
|
|
84
|
+
rec = @recs[ new_rec[:name] ]
|
|
85
|
+
if rec.nil?
|
|
86
|
+
@recs[ new_rec[:name]] = new_rec
|
|
87
|
+
else
|
|
88
|
+
raise ArgumentError, "duplicate stage entry: #{new_rec.pretty_inspect}"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
## add match stats
|
|
94
|
+
def add_matches( matches )
|
|
95
|
+
matches.each do |m|
|
|
96
|
+
name = desc( m['StageName'] )
|
|
97
|
+
rec = find!( name )
|
|
98
|
+
rec[:count] += 1
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def find!( name )
|
|
104
|
+
rec = @recs[ name ]
|
|
105
|
+
raise ArgumentError, "no stage w/ name >#{name}< found; sorry" if rec.nil?
|
|
106
|
+
rec
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def as_json
|
|
110
|
+
## note - sort by seq
|
|
111
|
+
|
|
112
|
+
@recs.values.sort do |l,r|
|
|
113
|
+
l[:seq] <=> r[:seq]
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def size() @recs.size; end
|
|
118
|
+
|
|
119
|
+
end # class Stages
|