fifadat-convert 0.0.1 → 0.1.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.
@@ -1,135 +0,0 @@
1
-
2
-
3
- def _build_report_score( live, timeline=nil )
4
-
5
- _scores = _build_score_from_goals( live )
6
-
7
-
8
- score = nil
9
-
10
- case live['ResultType']
11
- when 1,4
12
- ## 1 => 'REGULAR',
13
- ## 4 => 'REGULAR/AGG', ## aggregate (1st/2nd leg) - regular
14
- ## add ht
15
- ## assert ft match
16
- score = { ht: _scores[:ht][:score],
17
- ft: _scores[:ft][:score]
18
- }
19
- when 3,5,8
20
- score = { ht: _scores[:ht][:score],
21
- ft: _scores[:ft][:score],
22
- et: _scores[:et][:score],
23
- }
24
- when 2
25
- ## todo/fix - pull in timeline check too to check
26
- ## if any events recorded for extra time!!
27
- score = { ht: _scores[:ht][:score],
28
- ft: _scores[:ft][:score],
29
- }
30
-
31
- ## note - only incl. extra-time (et) if a goal scored in extra time
32
- score[:et] = _scores[:et][:score] unless _scores[:et][:minutes].empty?
33
- end
34
-
35
- score
36
- end
37
-
38
-
39
-
40
- def _build_report( live, timeline=nil )
41
- rec = {}
42
-
43
-
44
- ####
45
- ## add goals
46
- players = Players.new
47
- players.add( live['HomeTeam']['Players'] )
48
- players.add( live['AwayTeam']['Players'] )
49
-
50
- rec[:goals1] = build_goals( live['HomeTeam']['Goals'], players: players )
51
- rec[:goals2] = build_goals( live['AwayTeam']['Goals'], players: players )
52
-
53
-
54
- ##########
55
- ## add penalty kicks / penalties
56
- if live['ResultType'] == 2 ## aet, win on pens
57
- if timeline.nil?
58
- ##
59
- team1_code = live['HomeTeam']['Abbreviation']
60
- team2_code = live['AwayTeam']['Abbreviation']
61
- puts "!! ERROR - no timeline for match #{team1_code} v #{team2_code} with win on penalties!!"
62
- exit 1
63
- else
64
- ### get timeline with penalty shoot-out details
65
- ## note - requires team1/2_ids!!!
66
- team1_id = live['HomeTeam']['IdTeam']
67
- team2_id = live['AwayTeam']['IdTeam']
68
-
69
- pens = build_penalties( timeline['Event'],
70
- players: players,
71
- team1_id: team1_id,
72
- team2_id: team2_id )
73
- ## pp pens
74
-
75
- rec[:penalties] = pens
76
- end
77
- end
78
-
79
-
80
- ##
81
- ## add players by team1/team2
82
- players1 = Players.new
83
- players1.add( live['HomeTeam']['Players'] )
84
-
85
- players2 = Players.new
86
- players2.add( live['AwayTeam']['Players'] )
87
-
88
-
89
- rec[:formation1] = live['HomeTeam']['Tactics'] ## e.g. "Tactics": "3-1-4-2"
90
- rec[:lineup1] = players1.lineup ## starter XI
91
- rec[:bench1] = players1.bench ## substitutes
92
-
93
- rec[:formation2] = live['AwayTeam']['Tactics']
94
- rec[:lineup2] = players2.lineup
95
- rec[:bench2] = players2.bench
96
-
97
-
98
- #####
99
- ## add bookings (yellow/red/red-yellow cards)
100
- players1.add_bookings( live['HomeTeam']['Bookings'])
101
- players2.add_bookings( live['AwayTeam']['Bookings'])
102
-
103
-
104
- yellow1 = players1.yellowcards
105
- red1 = players1.redcards
106
- yellowred1 = players1.yellowredcards
107
- rec[:yellow1] = yellow1 unless yellow1.empty?
108
- rec[:red1] = red1 unless red1.empty?
109
- rec[:yellowred1] = yellowred1 unless yellowred1.empty?
110
-
111
- yellow2 = players2.yellowcards
112
- red2 = players2.redcards
113
- yellowred2 = players2.yellowredcards
114
- rec[:yellow2] = yellow2 unless yellow2.empty?
115
- rec[:red2] = red2 unless red2.empty?
116
- rec[:yellowred2] = yellowred2 unless yellowred2.empty?
117
-
118
-
119
-
120
- ## add substitutions (off/on - in/out)
121
- rec[:subs1] = build_subs( live['HomeTeam']['Substitutions'], players: players1 )
122
- rec[:subs2] = build_subs( live['AwayTeam']['Substitutions'], players: players2 )
123
-
124
-
125
- ## add referees
126
- officials = build_officials( live['Officials'], id: false )
127
-
128
- if officials.empty?
129
- ## puts "!! WARN no refs / officials found"
130
- else
131
- rec[:referees] = officials
132
- end
133
-
134
- rec
135
- end
@@ -1,58 +0,0 @@
1
-
2
-
3
- def _build_score_from_goals( m )
4
- ##
5
- ## 5 periods - 3 (1ST_HALF), 5 (2ND_HALF),
6
- ## 7 (EXTRA_TIME_1ST_HALF), 9 (EXTRA_TIME_2ND_HALF),
7
- ## 11 (PENALTY_SHOOTOUT) possibly
8
- ##
9
- goals = {
10
- count: 0,
11
- score: [0,0],
12
- ht: { score: [0,0], minutes: [] },
13
- ft: { score: [0,0], minutes: [] },
14
- et: { score: [0,0], minutes: [] },
15
- p: { score: [0,0], minutes: [] },
16
- }
17
-
18
- ## note - quick fix
19
- ## add period 2 for USA v Belgium (PKO) - worldcup
20
-
21
- ## note - i is 0|1 - array index for team
22
- [m['HomeTeam']['Goals'],
23
- m['AwayTeam']['Goals']].each_with_index do |recs,i|
24
- recs.each do |h|
25
-
26
- h = errata_autofix_goal( h )
27
-
28
- period = h['Period']
29
- ## include penalty shootout (11) - why? why not?
30
- assert( [3,5,7,9,11].include?(period),
31
- "goal in period 3/5/7/9/11 expected; got #{h.pretty_inspect} in match #{m.pretty_inspect}" )
32
-
33
- minute = h['Minute']
34
- key = case period
35
- when 3 then :ht
36
- when 5 then :ft
37
- when 7, 9 then :et
38
- when 11 then :p
39
- else
40
- raise ArgumentError,
41
- "goal in period 3/5/7/9/11 expected; got #{h.pretty_inspect}"
42
- end
43
-
44
- goals[:count] += 1
45
- goals[:score][i] += 1 unless key == :p
46
- goals[key][:score][i] += 1
47
- end
48
- end
49
-
50
- ## use/calc cummulative score (BUT not for penalties)
51
- goals[:ft][:score][0] += goals[:ht][:score][0]
52
- goals[:ft][:score][1] += goals[:ht][:score][1]
53
-
54
- goals[:et][:score][0] += goals[:ft][:score][0]
55
- goals[:et][:score][1] += goals[:ft][:score][1]
56
-
57
- goals
58
- end
@@ -1,329 +0,0 @@
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
-
133
- def find( id_player )
134
- rec = @recs[ id_player ]
135
- rec
136
- end
137
-
138
- def find!( id_player )
139
- rec = @recs[ id_player ]
140
- raise ArgumentError, "no player w/ id >#{id_player}< found; sorry" if rec.nil?
141
- rec
142
- end
143
-
144
-
145
- ###
146
- ## todo/check
147
- ## add alias (or rename) starter ??
148
- ## add new subs to status == 2 - why? why not?
149
- def lineup
150
- recs = @recs.values.select { |rec| rec[:status] == 1 }
151
-
152
- recs = recs.map {|rec| rec.except( :id, :status, :count ) }
153
- recs
154
- end
155
-
156
- def bench
157
- recs = @recs.values.select { |rec| rec[:status] == 2 }
158
-
159
- recs = recs.map {|rec| rec.except( :id, :status, :count ) }
160
- recs
161
- end
162
-
163
-
164
-
165
- ## all players with red or red-yellow card (sent off)
166
- def sentoff
167
- recs = @recs.values.select { |rec| rec[:r] || rec[:yr] }
168
-
169
- =begin
170
- "id": "395516",
171
- "name": "Cesar MONTES",
172
- "short_name": "Cesar MONTES",
173
- "status": 1,
174
- "pos": 1,
175
- "captain": true,
176
- "count": 1,
177
- "r": {
178
- "minute": "90+2'"
179
- =end
180
-
181
- ## todo/check - add a flag for yellow-red card (e.g. yr=true) - why? why not?
182
-
183
- recs = recs.map do |rec|
184
- minute = if rec[:r]
185
- rec[:r][:minute]
186
- elsif rec[:yr]
187
- rec[:yr][:minute]
188
- else
189
- raise ArgumentError, "r or yr card expected; got #{rec.inspect}"
190
- end
191
- { name: rec[:name],
192
- minute: minute }
193
- end
194
-
195
- recs
196
- end
197
-
198
-
199
- def redcards
200
- recs = @recs.values.select { |rec| rec[:r] }
201
-
202
- recs = recs.map do |rec|
203
- { name: rec[:name],
204
- minute: rec[:r][:minute] }
205
- end
206
- recs
207
- end
208
-
209
- def yellowcards
210
- recs = @recs.values.select { |rec| rec[:y] }
211
-
212
- recs = recs.map do |rec|
213
- { name: rec[:name],
214
- minute: rec[:y][:minute] }
215
- end
216
- recs
217
- end
218
-
219
- def yellowredcards
220
- recs = @recs.values.select { |rec| rec[:yr] }
221
-
222
- recs = recs.map do |rec|
223
- { name: rec[:name],
224
- minute: rec[:yr][:minute] }
225
- end
226
- recs
227
- end
228
-
229
-
230
-
231
- def add_bookings( bookings ) ## yellow/red cards
232
- bookings.each do |b|
233
-
234
- card = b['Card']
235
- assert( [0,1,2,3].include?( card ), "card 0/1/2/3 expected; got #{b.pretty_inspect}")
236
-
237
- ##
238
- ## what is card 0? ignore for now
239
- ## Palmeiras v FC Porto 0-0 - 2025-06-15T18:00:00+00:00
240
- ## !! ASSERT FAILED - card 1/2/3 expected; got {"Card"=>0,
241
- ## "Period"=>5,
242
- ## "IdEvent"=>nil,
243
- ## "EventNumber"=>nil,
244
- ## "IdPlayer"=>"495048",
245
- ## "IdCoach"=>nil,
246
- ## "IdTeam"=>"1884426",
247
- ## "Minute"=>"72'",
248
- ## "Reason"=>nil}
249
- next if card == 0
250
-
251
-
252
- idPlayer = b['IdPlayer']
253
-
254
- ## booking (card) for coach or stuff!!!!
255
- ## skip for now
256
- next if idPlayer.nil? && (b['IdCoach'] || b['IdStaff'])
257
-
258
-
259
- player = @recs[ idPlayer ]
260
- assert( player, "booking player not found; sorry - #{b.pretty_inspect}" )
261
-
262
- ## note - parse & reformat minute for keep same format
263
- ## _fmt_minute( *_parse_minute( b['Minute'] ))
264
- minute = _build_minute( b )
265
-
266
- if card == 1 ## yellow
267
- player[ :y ] = { minute: minute }
268
- elsif card == 2 ## red
269
- player[ :r ] = { minute: minute }
270
- elsif card == 3 ## yellow/red
271
- player[ :yr ] = { minute: minute }
272
- end
273
- end
274
- end
275
-
276
-
277
-
278
- def add_subs( subs )
279
- subs.each do |sub|
280
-
281
- idPlayerOff = sub['IdPlayerOff']
282
- idPlayerOn = sub['IdPlayerOn']
283
-
284
- ## note - parse & reformat minute for keep same format
285
- minute = _build_sub_minute( sub )
286
-
287
- player_off = @recs[ idPlayerOff ]
288
- player_on = @recs[ idPlayerOn ]
289
-
290
- ##
291
- ## note - skip special case for now
292
- ## with NO PLAYER ON (e.g. idPlayerOn is nil!!)
293
- ## next if idPlayerOn.nil?
294
- ## todo/fix - report/log warning!!!
295
-
296
-
297
- if player_off.nil?
298
- puts "!! player_off >#{idPlayerOff}< not found in:"
299
- pp sub
300
- puts "---"
301
- pp @recs.values
302
- exit 1
303
- end
304
-
305
- if player_on.nil?
306
- puts "!! player_on >#{idPlayerOn}< not found in:"
307
- pp sub
308
- puts "---"
309
- pp @recs.values
310
- exit 1
311
- end
312
-
313
- assert( player_off && player_on,
314
- "subs player_off or player_on not found; sorry" )
315
-
316
- player_off[ :sub ] = { minute: minute,
317
- player_ref: player_on }
318
- end
319
- end
320
-
321
-
322
- def dump
323
- pp @recs.values
324
- puts " #{@recs.size} player(s)"
325
- end
326
-
327
- def size() @recs.size; end
328
-
329
- end # class Players
@@ -1,99 +0,0 @@
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