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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -0
- data/Manifest.txt +15 -11
- data/lib/fifadat/convert/convert-reports.rb +49 -67
- data/lib/fifadat/convert/convert.rb +67 -96
- data/lib/fifadat/convert/helper-date.rb +12 -0
- data/lib/fifadat/convert/helper-score.rb +104 -61
- data/lib/fifadat/convert/reader.rb +55 -0
- data/lib/fifadat/convert/tool.rb +1 -1
- data/lib/fifadat/convert/version.rb +2 -2
- data/lib/fifadat/convert.rb +54 -14
- data/lib/fifadat/{convert/goals.rb → models/goal.rb} +49 -18
- data/lib/fifadat/models/match.rb +218 -0
- data/lib/fifadat/models/match_report.rb +205 -0
- data/lib/fifadat/{convert/officials.rb → models/official.rb} +58 -20
- data/lib/fifadat/{convert/penalties.rb → models/penalty.rb} +50 -16
- data/lib/fifadat/models/player.rb +218 -0
- data/lib/fifadat/models/stadium.rb +98 -0
- data/lib/fifadat/models/stage.rb +99 -0
- data/lib/fifadat/{convert/substitutions.rb → models/substitution.rb} +84 -9
- data/lib/fifadat/models/team.rb +85 -0
- data/lib/fifadat/tables/players.rb +140 -0
- data/lib/fifadat/tables/stadiums.rb +71 -0
- data/lib/fifadat/tables/stages.rb +58 -0
- data/lib/fifadat/tables/teams.rb +57 -0
- metadata +17 -13
- data/lib/fifadat/convert/build_match.rb +0 -105
- data/lib/fifadat/convert/build_report.rb +0 -135
- data/lib/fifadat/convert/goals-calc_score.rb +0 -58
- data/lib/fifadat/convert/players.rb +0 -329
- data/lib/fifadat/convert/stadiums.rb +0 -99
- data/lib/fifadat/convert/stages.rb +0 -119
- data/lib/fifadat/convert/teams.rb +0 -91
|
@@ -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
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
|
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[
|
|
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.
|
|
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
|
-
|
|
21
|
-
"IsUpdateable": null}
|
|
20
|
+
}
|
|
22
21
|
=end
|
|
23
22
|
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
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
|
|
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
|
-
|
|
87
|
-
|
|
88
|
+
rec[ :player ] = Player::PLAYER_NIL
|
|
88
89
|
else
|
|
89
|
-
rec[ :
|
|
90
|
+
rec[ :player ] = players.find!( idPlayer )
|
|
90
91
|
end
|
|
91
92
|
|
|
92
|
-
rec[:
|
|
93
|
+
rec[:more] = { type: type,
|
|
93
94
|
desc: desc(h['EventDescription']) ## add event desc too - why? why not?
|
|
94
95
|
}
|
|
95
|
-
|
|
96
|
+
|
|
97
|
+
new( **rec )
|
|
96
98
|
end
|
|
97
99
|
|
|
98
100
|
|
|
99
101
|
|
|
100
102
|
|
|
101
|
-
def
|
|
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|
|
|
129
|
-
|
|
130
|
-
|
|
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
|