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,5 +1,24 @@
1
1
 
2
2
  =begin
3
+
4
+ =begin
5
+ "Officials":
6
+ [{"IdCountry": "BRA",
7
+ "OfficialId": "361561",
8
+ "NameShort": [{"Locale": "en-GB", "Description": "Wilton SAMPAIO"}],
9
+ "Name": [{"Locale": "en-GB", "Description": "Wilton SAMPAIO"}],
10
+ "OfficialType": 1,
11
+ "TypeLocalized": [{"Locale": "en-GB", "Description": "Referee"}]},
12
+ {"IdCountry": "PAR",
13
+ "OfficialId": "416159",
14
+ "NameShort":
15
+ [{"Locale": "en-GB", "Description": "Juan Gabriel BENITEZ"}],
16
+ "Name": [{"Locale": "en-GB", "Description": "Juan Gabriel Benítez"}],
17
+ "OfficialType": 4,
18
+ "TypeLocalized":
19
+ [{"Locale": "en-GB", "Description": "Fourth official"}]}],
20
+
21
+
3
22
  "Officials":
4
23
  [{"IdCountry": "URU",
5
24
  "OfficialId": "61038",
@@ -25,13 +44,16 @@
25
44
  =end
26
45
 
27
46
 
47
+ class Official
48
+
28
49
  TYPE_OFFICIAL = {
29
50
  1 => 'Referee',
30
51
  2 => 'Assistant Referee 1',
31
52
  3 => 'Assistant Referee 2',
32
53
  }
33
54
 
34
- def build_official( h, id: )
55
+
56
+ def self.build( h )
35
57
  name = desc( h['Name'] )
36
58
 
37
59
  ## fix - use norm_official
@@ -40,29 +62,23 @@ def build_official( h, id: )
40
62
  idCountry = h['IdCountry']
41
63
  type = h['OfficialType']
42
64
 
43
-
44
65
  assert( is_alpha?(name), "official name alpha expected; got #{pp_alpha(name)}" )
45
66
 
46
-
47
-
48
67
  assert( [1,2,3,4,5,6,7,8,9,10].include?( type ), "official type 1/2/3/4/5/6/7/8/9/10 expected; got #{type}" )
49
68
 
50
- rec = {}
51
- rec[:id] = h['OfficialId'] if id
52
-
53
- rec.merge!( name: name,
54
- country: idCountry,
55
- type: type )
56
-
57
- rec
58
- end
69
+ rec = { id: h['OfficialId'],
70
+ name: name,
71
+ country: idCountry,
72
+ type: TYPE_OFFICIAL[type] ## change type to literal string
73
+ }
59
74
 
75
+ new(**rec)
76
+ end
60
77
 
61
- def build_officials( recs, id: false ) ## use referees?
62
- recs = recs.map { |h| build_official( h, id: id ) }
78
+ def self._build_ary( recs ) ## use referees?
63
79
 
64
80
  ## skip fourth official (4) for now
65
- recs = recs.select { |h| [1,2,3].include?( h[:type] ) }
81
+ recs = recs.select { |h| [1,2,3].include?( h['OfficialType'] ) }
66
82
 
67
83
  ## sort by type 1/2/3
68
84
  ## 1 - referee
@@ -75,12 +91,34 @@ def build_officials( recs, id: false ) ## use referees?
75
91
  ## 8 - assistant var
76
92
  ## 9 - support var
77
93
  ## 10 - reserve assistant referee
94
+ recs = recs.sort { |l,r| l['OfficialType'] <=> r['OfficialType'] }
78
95
 
79
96
 
80
- recs = recs.sort { |l,r| l[:type] <=> r[:type] }
81
-
82
- ## change type to literal string
83
- recs = recs.map { |h| h[:type]=TYPE_OFFICIAL[h[:type]]; h }
97
+ recs = recs.map { |h| build( h ) }
84
98
 
85
99
  recs
86
100
  end
101
+
102
+ attr_reader :id, :name, :country, :type
103
+
104
+ def initialize( id:, name:, country:, type:)
105
+ @id = id
106
+ @name = name
107
+ @country = country
108
+ @type = type
109
+ end
110
+
111
+ def as_json(*)
112
+ h = {
113
+ 'name' => name,
114
+ 'country' => country,
115
+ 'type' => type,
116
+ }
117
+ h
118
+ end
119
+
120
+
121
+
122
+
123
+
124
+ end # class Official
@@ -17,13 +17,14 @@
17
17
  [{"Locale": "en-GB",
18
18
  "Description":
19
19
  "David BATTY (England) misses from the penalty spot!"}]}],
20
- "Properties": {},
21
- "IsUpdateable": null}
20
+ }
22
21
  =end
23
22
 
24
23
 
25
- def build_penalty( h, players:,
26
- team1_id:, team2_id: )
24
+ class Penalty
25
+
26
+ def self.build( h, players:,
27
+ team1_id:, team2_id: )
27
28
 
28
29
  ## note - do NOT care about minutes in penalty shootout
29
30
  ## check for period == 11 (penalty shotout!!)
@@ -31,8 +32,9 @@ def build_penalty( h, players:,
31
32
 
32
33
 
33
34
  ##########
34
- ## 0 - goal (when penalty awared used before)
35
+ ## 0 - goal (when penalty awarded used before)
35
36
  ## 41 - penalty goal
37
+ ##
36
38
  ## 46 - penalty missed
37
39
  ## Dragan STOJKOVIC (Yugoslavia) rattles the crossbar from the spot!
38
40
  ## 51 - penalty missed
@@ -78,27 +80,27 @@ def build_penalty( h, players:,
78
80
  =end
79
81
 
80
82
  if idPlayer.nil?
81
- puts "!! no idPlayer for penalty!"
83
+ puts "!! no idPlayer for penalty (timeline event):"
82
84
  pp h
83
- ##exit 1
85
+ ## exit 1
84
86
  ## use 'N.N.'
85
87
 
86
- rec[ :name ] = 'N.N.'
87
-
88
+ rec[ :player ] = Player::PLAYER_NIL
88
89
  else
89
- rec[ :name ] = players.find!( idPlayer )[:name]
90
+ rec[ :player ] = players.find!( idPlayer )
90
91
  end
91
92
 
92
- rec[:meta] = { type: type,
93
+ rec[:more] = { type: type,
93
94
  desc: desc(h['EventDescription']) ## add event desc too - why? why not?
94
95
  }
95
- rec
96
+
97
+ new( **rec )
96
98
  end
97
99
 
98
100
 
99
101
 
100
102
 
101
- def build_penalties( recs, players:,
103
+ def self._build_ary( recs, players:,
102
104
  team1_id:, team2_id: )
103
105
  ################
104
106
  ## type:
@@ -125,8 +127,40 @@ def build_penalties( recs, players:,
125
127
  end
126
128
 
127
129
 
128
- recs = recs.map { |h| build_penalty( h, players: players,
129
- team1_id: team1_id,
130
- team2_id: team2_id ) }
130
+ recs = recs.map { |h| build( h, players: players,
131
+ team1_id: team1_id,
132
+ team2_id: team2_id ) }
131
133
  recs
132
134
  end
135
+
136
+
137
+
138
+ attr_reader :player, :team,
139
+ :score, :scored,
140
+ :more
141
+
142
+ def initialize( player:,
143
+ team:,
144
+ score:,
145
+ scored:,
146
+ more: {} )
147
+ @player = player
148
+ @team = team ## e.g. 1|2
149
+ @score = score ## e.g. [1,0]
150
+ @scored = scored ## e.g. true|false
151
+ @more = more
152
+ end
153
+
154
+
155
+ def as_json(*)
156
+ h = {
157
+ 'name' => player.name,
158
+ 'score' => score,
159
+ 'scored' => scored,
160
+ 'team' => team,
161
+ }
162
+
163
+ h['more'] = more unless more.empty?
164
+ h
165
+ end
166
+ end # class Penalty
@@ -0,0 +1,218 @@
1
+
2
+ #
3
+ # note - players here are for lineup (subs+bookings) and incl. starter/bench AND pos etc.
4
+ # do NOT use for team squads
5
+
6
+
7
+ # TYPE_PLAYER_POS = {
8
+ # 0 => 'GK',
9
+ # 1 => 'DF',
10
+ # 2 => 'MF',
11
+ # 3 => 'FW',
12
+ # 4 => '??',
13
+ # 5 => '??',
14
+ # 6 => '??'
15
+ # }
16
+
17
+
18
+ class Player
19
+
20
+
21
+ ###
22
+ ## keep Card nested here - why? why not?
23
+ class Card
24
+
25
+ attr_reader :player, :type, :minute
26
+ def initialize( player:, type:, minute: )
27
+ @player = player
28
+ @type = type
29
+ @minute = minute
30
+ end
31
+
32
+ ## only print name and minute for now - why? why not?
33
+ def as_json(*)
34
+ h = {
35
+ 'name' => player.name,
36
+ 'minute' => minute
37
+ }
38
+ h
39
+ end
40
+ end # class Card
41
+
42
+
43
+
44
+ def self._build_ary( recs )
45
+ recs.map { |h| build( h ) }
46
+ end
47
+
48
+
49
+ def self.build( h )
50
+
51
+ name = desc( h['PlayerName'] )
52
+ short_name = desc( h['ShortName'] )
53
+
54
+ if name.nil?
55
+ ## "PlayerName"=>[],
56
+ ## "ShortName"=>[{"Locale"=>"en-gb", "Description"=>"S. Lainer"}],
57
+
58
+ ## hack:
59
+ ## use shortname
60
+ name = short_name
61
+ end
62
+
63
+ if name.nil?
64
+ ## puts "name is nil:"
65
+ ## pp h
66
+ ## exit 1
67
+ ## report/log error/warn
68
+ ##
69
+ ## quick fix use N.N. for now
70
+ name = 'N.N.'
71
+ end
72
+
73
+ ## name = norm_player( name )
74
+
75
+
76
+ ##
77
+ ## todo/check - add IdCountry if available??
78
+
79
+ ## 1 - starter
80
+ ## 2 - bench
81
+
82
+ status = h['Status']
83
+ assert( [1,2].include?( status ), "player status 1,2 expected; got #{h.inspect}")
84
+
85
+ ## what is pos 6 ??
86
+ ## e.g.
87
+ ## !! ASSERT FAILED
88
+ ## {"IdPlayer"=>"419456", "IdTeam"=>"32759", "ShirtNumber"=>4, "Status"=>1,
89
+ ## "PlayerName"=>[{"Locale"=>"en-GB", "Description"=>"Ismaila COULIBALY"}],
90
+ ## "ShortName"=>[{"Locale"=>"en-GB", "Description"=>"Ismaila COULIBALY"}],
91
+ ## "Position"=>6, "PlayerPicture"=>nil,
92
+ ## "FieldStatus"=>2, "LineupX"=>nil, "LineupY"=>nil}
93
+ ##
94
+ ## what is pos 5 ??
95
+ ## e.g.
96
+ ## {"IdPlayer"=>"7czui1ih46j3zitzysxvjqjv8", "IdTeam"=>"2000019848", "ShirtNumber"=>33,
97
+ ## "Status"=>1,
98
+ ## "PlayerName"=>[{"Locale"=>"en-gb", "Description"=>"Maximilian Hennig"}],
99
+ ## "ShortName"=>[{"Locale"=>"en-gb", "Description"=>"M. Hennig"}],
100
+ ## "Position"=>5, "PlayerPicture"=>nil, "FieldStatus"=>2, "LineupX"=>nil, "LineupY"=>nil}
101
+ ##
102
+ ## what is pos 4 ??
103
+ ## {"IdPlayer"=>"254150", "IdTeam"=>"2000017585", "ShirtNumber"=>15,
104
+ ## "Status"=>2, "SpecialStatus"=>nil, "Captain"=>false,
105
+ ## "PlayerName"=>[{"Locale"=>"en-GB", "Description"=>"Nemanja RNIC"}],
106
+ ## "ShortName"=>[{"Locale"=>"en-gb", "Description"=>"N. Rnić"}],
107
+ ## "Position"=>4, "PlayerPicture"=>nil, "FieldStatus"=>1, "LineupX"=>nil, "LineupY"=>nil}
108
+
109
+
110
+ pos = h['Position']
111
+ assert( [0,1,2,3,4,5,6].include?( pos ), "player pos 0,1,2,3,4,5,6 expected; got #{h.inspect}" )
112
+
113
+ ## 0 - is always goal keeper
114
+ ## check meaning of 1 to 6
115
+ ## on website !!!
116
+ ## pos is NOT (simply) matching tactics/formation (index number)!!
117
+
118
+ rec = { id: h['IdPlayer'],
119
+ name: name,
120
+ short_name: short_name,
121
+ status: status,
122
+ pos: pos,
123
+ }
124
+
125
+ ## check for shirtNumber too
126
+ num = h['ShirtNumber']
127
+ rec[:num] = num if num
128
+
129
+ rec[:captain] = true if h['Captain']
130
+
131
+
132
+ new( **rec )
133
+ end
134
+
135
+
136
+
137
+
138
+
139
+ attr_reader :id, :name, :short_name,
140
+ :status, :pos,
141
+ :captain, :num
142
+
143
+
144
+ attr_accessor :count,
145
+ :y, :yr, :r ## yello/yellowred/red cards
146
+
147
+
148
+
149
+
150
+ def initialize( id:,
151
+ name:,
152
+ status:, ## 1 - starter, 2 - bench
153
+ pos:,
154
+ short_name: nil,
155
+ captain: false,
156
+ num: nil ## shirt/jersey number
157
+ )
158
+ @id = id
159
+ @name = name
160
+ @short_name = name
161
+ @status = status
162
+ @pos = pos
163
+ @captain = captain
164
+ @num = num
165
+
166
+ @count = 0
167
+
168
+ @y = nil
169
+ @yr = nil
170
+ @r = nil
171
+ end
172
+
173
+ PLAYER_NIL = new( id: '<nil>',
174
+ name: 'N.N.',
175
+ status: nil,
176
+ pos: nil
177
+ )
178
+
179
+
180
+ def starter?() status == 1; end
181
+ def bench?() status == 2; end
182
+
183
+ ## add alias yellow_card? or y? - why? why not?
184
+ def yellow?() y.is_a?(Card); end
185
+ def yellowred?() yr.is_a?(Card); end
186
+ def red?() r.is_a?(Card); end
187
+
188
+
189
+
190
+
191
+ def ==(other)
192
+ return false unless other.is_a?(Player)
193
+
194
+ self.name == other.name &&
195
+ self.short_name == other.short_name
196
+ end
197
+
198
+
199
+ def as_json(*)
200
+ h = {
201
+ 'name' => name,
202
+ 'short_name' => short_name,
203
+ 'id' => id,
204
+ ## use starter|bench !!!
205
+ 'status' => status,
206
+ ## todo - map pos
207
+ 'pos' => pos,
208
+ }
209
+
210
+
211
+ h['captain'] = captain if captain
212
+ h['num'] = num if num
213
+ h
214
+ end
215
+
216
+
217
+
218
+ end # class Player
@@ -0,0 +1,98 @@
1
+
2
+ class Stadium
3
+
4
+
5
+ def self.build( h )
6
+ if h
7
+ ## note - for now stadiums have no ids!!!!!
8
+ ## check if any ids found
9
+ id = h['IdStadium']
10
+ id_country = h['IdCountry']
11
+
12
+ ## same with city - no ids really in use
13
+ ## id_city = h['IdCity']
14
+
15
+ name = desc( h['Name'] )
16
+ city_name = desc( h['CityName'] )
17
+
18
+ if name.nil?
19
+ puts "stadium without name:"
20
+ pp h
21
+ exit 1
22
+ end
23
+
24
+ ## name, city_name = norm_stadium( name, city_name: city_name )
25
+
26
+ new( id: id,
27
+ name: name,
28
+ city: city_name,
29
+ country: id_country,
30
+ street: h['Street']
31
+ )
32
+
33
+ else ## assume nil - dummy record
34
+ STADIUM_NIL
35
+ end
36
+ end
37
+
38
+
39
+
40
+ attr_reader :id, :name, :street, :city, :country
41
+ attr_accessor :count
42
+ def initialize( name:, country:, city:,
43
+ street: nil,
44
+ id: nil )
45
+ @name = name
46
+ @country = country
47
+ @city = city
48
+ @street = street
49
+
50
+ if id.nil?
51
+ ## auto-generate id
52
+ ## use slug of name plus id_city
53
+ ## add city name
54
+ ## fix- add 0-9 & dash(-) to name too - why? why not?
55
+ id = name.downcase.gsub( /[^a-z]/, '' )
56
+ id += "_" + city.downcase.gsub( /[^a-z]/, '' )
57
+ end
58
+ @id = id
59
+
60
+ ## note - count matches by (home) teams!!!
61
+ @count = Hash.new(0)
62
+ end
63
+
64
+
65
+ ## dummy/nil record
66
+ STADIUM_NIL = self.new( id: '<nil>',
67
+ name: '?',
68
+ city: '?', ## use nil - why? why not?
69
+ country: '?' ## use nil - why? why not?
70
+ )
71
+
72
+
73
+ def ==(other)
74
+ return false unless other.is_a?(Stadium)
75
+
76
+ ## note - ignore street (and always empty id) for now!!!
77
+ self.name == other.name &&
78
+ self.city == other.city &&
79
+ self.country == other.country
80
+ end
81
+
82
+
83
+ def as_json(*)
84
+ h = {
85
+ 'name' => name
86
+ }
87
+
88
+ h['street'] = street if street
89
+ h['city'] = city if city
90
+ h['country'] = country if country
91
+
92
+ h['count'] = count
93
+ h
94
+ end
95
+
96
+
97
+
98
+ end # class Stadium
@@ -0,0 +1,99 @@
1
+ =begin
2
+ [{"IdStage": "286472",
3
+ "IdSeason": "286466",
4
+ "SeasonName":
5
+ [{"Locale": "en-GB", "Description": "FIFA Club World Cup Morocco 2022™"}],
6
+ "IdCompetition": "107",
7
+
8
+ "SequenceOrder": 6,
9
+ "Name": [{"Locale": "en-GB", "Description": "Final"}],
10
+ "StartDate": "2023-02-11T19:00:00Z",
11
+ "EndDate": "2023-02-11T19:00:00Z",
12
+ "StageLevel": null,
13
+ "Type": 0, add ---??
14
+ "Properties": {"IdIFES": "286472"},
15
+ "IsUpdateable": null},
16
+ =end
17
+
18
+
19
+
20
+ class Stage
21
+ def self.build( h )
22
+ name = desc( h['Name'] )
23
+ seq = h['SequenceOrder']
24
+ level = h['StageLevel'] ## note - is optional
25
+
26
+ start_date = nil
27
+ end_date = nil
28
+
29
+ if h['StartDate'] && h['EndDate']
30
+ ## note - start/end dates are utc (NOT local)
31
+ start_date = parse_date_utc( h['StartDate'] ) ## expects ...:00Z format
32
+ end_date = parse_date_utc( h['EndDate'] ) ## expects ...:00Z format
33
+
34
+ ## check if HH::MM is 00:00
35
+ ## only use date for now; ignore time
36
+ ## report warn(ing) if time present!!!
37
+ if start_date.hour != 0 || start_date.min != 0 ||
38
+ end_date.hour != 0 || end_date.min != 0
39
+ ## issue warn start/end_date with HH:MM (NOT 00:00)
40
+ puts "!! warn: stage start/end_date with HH:MM (expected 00:00)"
41
+ pp h
42
+ end
43
+ else
44
+ ## maybe add to log later - why? why not?
45
+ ## puts "!! warn: stage witouout start/end_date"
46
+ ## pp h
47
+ end
48
+
49
+ new( name: name,
50
+ seq: seq,
51
+ start_date: start_date ? start_date.to_date : nil,
52
+ end_date: end_date ? end_date.to_date : nil,
53
+ level: level )
54
+ end
55
+
56
+
57
+
58
+ ##
59
+ ## note - seq might be same for different stages e.g.
60
+ ## "seq": 2,
61
+ ## "name": "Relegation Round",
62
+ ##
63
+ ## "seq": 2,
64
+ ## "name": "Championship Round",
65
+ attr_reader :name, :seq, :level,
66
+ :start_date, :end_date
67
+
68
+ attr_accessor :count
69
+
70
+ def initialize( name:, seq:,
71
+ level: nil,
72
+ start_date: nil,
73
+ end_date: nil
74
+ )
75
+ @name = name
76
+ @seq = seq # e.g. 1,2,3,4,5
77
+ @start_date = start_date
78
+ @end_date = end_date
79
+ @level = level
80
+ @count = 0 ## match (usage/reference) count(er)
81
+ end
82
+
83
+
84
+ def as_json(*)
85
+ h = {
86
+ 'seq' => seq,
87
+ 'name' => name
88
+ }
89
+
90
+ h['start_date'] = start_date.strftime('%Y-%m-%d') if start_date
91
+ h['end_date'] = end_date.strftime('%Y-%m-%d') if end_date
92
+
93
+ h['level'] = level if level
94
+ h['count'] = count
95
+ h
96
+ end
97
+
98
+
99
+ end # class Stage