line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Sport::Analytics::NHL::Report::BH; |
2
|
|
|
|
|
|
|
|
3
|
20
|
|
|
20
|
|
73745
|
use v5.10.1; |
|
20
|
|
|
|
|
80
|
|
4
|
20
|
|
|
20
|
|
115
|
use strict; |
|
20
|
|
|
|
|
46
|
|
|
20
|
|
|
|
|
507
|
|
5
|
20
|
|
|
20
|
|
107
|
use warnings FATAL => 'all'; |
|
20
|
|
|
|
|
49
|
|
|
20
|
|
|
|
|
676
|
|
6
|
20
|
|
|
20
|
|
97
|
use experimental qw(smartmatch); |
|
20
|
|
|
|
|
38
|
|
|
20
|
|
|
|
|
112
|
|
7
|
|
|
|
|
|
|
|
8
|
20
|
|
|
20
|
|
1294
|
use parent 'Sport::Analytics::NHL::Report'; |
|
20
|
|
|
|
|
280
|
|
|
20
|
|
|
|
|
91
|
|
9
|
|
|
|
|
|
|
|
10
|
20
|
|
|
20
|
|
1184
|
use Carp; |
|
20
|
|
|
|
|
41
|
|
|
20
|
|
|
|
|
1250
|
|
11
|
|
|
|
|
|
|
|
12
|
20
|
|
|
20
|
|
122
|
use Sport::Analytics::NHL::Config; |
|
20
|
|
|
|
|
40
|
|
|
20
|
|
|
|
|
4121
|
|
13
|
20
|
|
|
20
|
|
136
|
use Sport::Analytics::NHL::Errors; |
|
20
|
|
|
|
|
58
|
|
|
20
|
|
|
|
|
3662
|
|
14
|
20
|
|
|
20
|
|
143
|
use Sport::Analytics::NHL::Util; |
|
20
|
|
|
|
|
37
|
|
|
20
|
|
|
|
|
1462
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 NAME |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
Sport::Analytics::NHL::Report::BH - Class for the old Boxscore HTML report. |
19
|
|
|
|
|
|
|
NOT IN USE - NOT IN USE. |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSYS |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
Class for the old Boxscore HTML report. At the moment it's not used, thus it's not documented. |
24
|
|
|
|
|
|
|
Hack at your own risk. |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=head1 METHODS |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=over 2 |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=item C |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=item C |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=item C |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
=item C |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=item C |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=item C |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=item C |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=item C |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=item C |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=item C |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=item C |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=item C |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=item C |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=item C |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=item C |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=item C |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=item C |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=item C |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=item C |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=back |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=cut |
71
|
|
|
|
|
|
|
|
72
|
20
|
|
|
20
|
|
117
|
use Data::Dumper; |
|
20
|
|
|
|
|
43
|
|
|
20
|
|
|
|
|
84081
|
|
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
our $LAST_PERIOD = 979; |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
our $BOXSCORE_HEADER = 1; |
77
|
|
|
|
|
|
|
our $BOXSCORE_GAME = 2; |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
my %NORMAL_FIELDS = ( |
80
|
|
|
|
|
|
|
S => { |
81
|
|
|
|
|
|
|
A => 'assists', BkS => 'blocked', 'PP TOI' => 'powerPlayTimeOnIce', MS => 'misses', |
82
|
|
|
|
|
|
|
'SH TOI' => 'shortHandedTimeOnIce', 'EV TOI' => 'evenTimeOnIce', |
83
|
|
|
|
|
|
|
Hits => 'hits', G => 'goals', GvA => 'giveaways', TkA => 'takeaways', |
84
|
|
|
|
|
|
|
PIM => 'penaltyMinutes', S => 'shots', 'FO%' => 'faceOffPercentage', P => 'points', |
85
|
|
|
|
|
|
|
'No.' => 'number', 'Pos' => 'position', Player => '_id', |
86
|
|
|
|
|
|
|
Pos => 'position', TOI => 'timeOnIce', '+/-' => 'plusMinus', |
87
|
|
|
|
|
|
|
}, |
88
|
|
|
|
|
|
|
G => { |
89
|
|
|
|
|
|
|
PIM => 'pim', Player => '_id', G => 'goals', S => 'saves', TOI => 'timeOnIce', |
90
|
|
|
|
|
|
|
'No.' => 'number', 'wl' => 'decision', |
91
|
|
|
|
|
|
|
}, |
92
|
|
|
|
|
|
|
); |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
my %LIVE_FIELDS = ( |
95
|
|
|
|
|
|
|
S => [qw(shortHandedGoals shortHandedAssists powerPlayGoals powerPlayAssists evenStrengthGoals evenStrengthAssists faceoffTaken faceOffWins)], |
96
|
|
|
|
|
|
|
G => [qw(pim goals assists)] |
97
|
|
|
|
|
|
|
); |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
sub extract_id_from_href ($) { |
100
|
|
|
|
|
|
|
|
101
|
140
|
|
|
140
|
1
|
152
|
my $elem = shift; |
102
|
|
|
|
|
|
|
|
103
|
140
|
|
|
|
|
229
|
$elem->attr('href') =~ /id=(\d+)/; |
104
|
140
|
|
|
|
|
1567
|
my $id = $1; |
105
|
140
|
50
|
|
|
|
420
|
$BROKEN_PLAYER_IDS{$id} || $id; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub extract_name_from_href ($) { |
109
|
|
|
|
|
|
|
|
110
|
76
|
|
|
76
|
1
|
97
|
my $elem = shift; |
111
|
|
|
|
|
|
|
|
112
|
76
|
|
|
|
|
144
|
$elem->{_content}[0]; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
sub read_header ($$) { |
116
|
|
|
|
|
|
|
|
117
|
2
|
|
|
2
|
1
|
5
|
my $self = shift; |
118
|
2
|
|
|
|
|
3
|
my $main_div = shift; |
119
|
|
|
|
|
|
|
|
120
|
2
|
|
|
|
|
8
|
$self->{periods} = [ {}, {}, {} ]; |
121
|
2
|
|
|
|
|
5
|
$self->{teams} = []; |
122
|
2
|
|
|
|
|
6
|
$self->{status} = 'FINAL'; |
123
|
2
|
|
|
|
|
5
|
$self->{type} = 'BH'; |
124
|
|
|
|
|
|
|
$self->{source} =~ |
125
|
2
|
|
|
|
|
166
|
m|title\>([A-Z].*)\s+at\s+([A-Z].*) - (\d{2}/\d{2}/\d{4}).*title|; |
126
|
2
|
|
|
|
|
10
|
$self->{full_teams} = [ $1, $2 ]; |
127
|
2
|
|
|
|
|
8
|
$self->{date} = $3; |
128
|
2
|
|
|
|
|
5
|
$self->{time} = ''; |
129
|
2
|
|
|
|
|
36
|
$self->{source} =~ m|gcGameId\D*(\d+)|; |
130
|
2
|
|
|
|
|
6
|
$self->{_id} = $1; |
131
|
2
|
|
|
|
|
11
|
$self->{stage} = int($self->{_id} / 10000) % 10; |
132
|
2
|
|
|
|
|
7
|
$self->{season} = int($self->{_id} / 1000000); |
133
|
2
|
|
|
|
|
7
|
substr($self->{_id}, 4, 1) = ''; |
134
|
2
|
|
|
|
|
9
|
$self->{season_id} = sprintf("%04d", $self->{_id} % 10000); |
135
|
2
|
|
|
|
|
16
|
$self->convert_time_date(1); |
136
|
2
|
|
|
|
|
16
|
$self->{source} =~ /game_string:.*\"(\S{3})\s*\@\s*(\S{3})\"/; |
137
|
2
|
|
|
|
|
7
|
$self->{teams}[0]{name} = $1; |
138
|
2
|
|
|
|
|
7
|
$self->{teams}[1]{name} = $2; |
139
|
2
|
|
|
|
|
12
|
my $a_score = $self->get_sub_tree(0, [2,0,2,0,0,0], $main_div); |
140
|
2
|
|
|
|
|
7
|
$self->{teams}[0]{score} = $a_score; |
141
|
2
|
|
|
|
|
9
|
my $h_score = $self->get_sub_tree(0, [2,0,2,0,2,0], $main_div); |
142
|
2
|
|
|
|
|
7
|
$self->{teams}[1]{score} = $h_score; |
143
|
2
|
|
|
|
|
4
|
$self->{old} = 1; |
144
|
2
|
|
|
|
|
6
|
$LAST_PERIOD = 3; |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
sub read_boxscore_scoring_event ($$$$) { |
148
|
|
|
|
|
|
|
|
149
|
6
|
|
|
6
|
1
|
9
|
my $self = shift; |
150
|
6
|
|
|
|
|
8
|
my $row = shift; |
151
|
6
|
|
|
|
|
7
|
my $cell = shift; |
152
|
6
|
|
|
|
|
10
|
my $period = shift; |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
my $event = { |
155
|
|
|
|
|
|
|
type => 'GOAL', |
156
|
|
|
|
|
|
|
strength => 'EV', |
157
|
6
|
|
|
|
|
19
|
time => $cell->{_content}[0], |
158
|
|
|
|
|
|
|
team1 => $self->get_sub_tree(0, [1,0], $row), |
159
|
|
|
|
|
|
|
period => $period, |
160
|
|
|
|
|
|
|
en => 0, |
161
|
|
|
|
|
|
|
}; |
162
|
6
|
|
|
|
|
17
|
my $score = $self->get_sub_tree(0, [2,0], $row); |
163
|
6
|
50
|
|
|
|
13
|
return undef unless $score; |
164
|
6
|
|
|
|
|
7
|
my $offset = 0; |
165
|
6
|
50
|
66
|
|
|
24
|
$event->{empty_net} = 1 if ! ref $score && $score =~ /\bEN\b/; |
166
|
|
|
|
|
|
|
|
167
|
6
|
100
|
|
|
|
13
|
if (! ref $score) { |
168
|
2
|
|
|
|
|
7
|
$event->{player1} = extract_id_from_href( |
169
|
|
|
|
|
|
|
$self->get_sub_tree(0, [2,1], $row) |
170
|
|
|
|
|
|
|
); |
171
|
2
|
|
|
|
|
5
|
$offset = 1; |
172
|
2
|
50
|
|
|
|
13
|
if ($score =~ /(\w\w)G/) { |
173
|
2
|
|
|
|
|
7
|
$event->{strength} = $1; |
174
|
|
|
|
|
|
|
} |
175
|
2
|
50
|
|
|
|
9
|
if ($score =~ /EN/) { |
|
|
50
|
|
|
|
|
|
176
|
0
|
|
|
|
|
0
|
$event->{en} = 1; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
elsif ($score =~ /PS/) { |
179
|
0
|
|
|
|
|
0
|
$event->{str} = 'PS'; |
180
|
0
|
|
|
|
|
0
|
$event->{penaltyshot} = 1; |
181
|
0
|
|
|
|
|
0
|
$event->{location} = 'OFF'; |
182
|
0
|
|
|
|
|
0
|
$event->{shot_type} = 'UNKNOWN'; |
183
|
0
|
|
|
|
|
0
|
$event->{distance} = 999; |
184
|
0
|
|
|
|
|
0
|
return $event; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
else { |
188
|
4
|
|
|
|
|
10
|
$event->{player1} = extract_id_from_href($score); |
189
|
|
|
|
|
|
|
} |
190
|
6
|
|
|
|
|
17
|
my $asst = $self->get_sub_tree(0, [2,1+$offset], $row); |
191
|
6
|
|
|
|
|
11
|
my $asst1; my $asst2; |
192
|
6
|
|
|
|
|
13
|
$event->{assists} = []; |
193
|
6
|
50
|
|
|
|
16
|
if ($asst =~ /ASST/) { |
194
|
6
|
|
|
|
|
19
|
$asst1 = $self->get_sub_tree(0, [2,2+$offset], $row); |
195
|
6
|
50
|
|
|
|
15
|
if ($asst1) { |
196
|
6
|
|
|
|
|
11
|
$event->{assist1} = extract_id_from_href($asst1); |
197
|
6
|
|
|
|
|
8
|
push(@{$event->{assists}}, $event->{assist1}); |
|
6
|
|
|
|
|
13
|
|
198
|
6
|
|
|
|
|
17
|
$asst2 = $self->get_sub_tree(0, [2,4+$offset], $row); |
199
|
6
|
50
|
|
|
|
16
|
$event->{assist2} = extract_id_from_href($asst2) if $asst2; |
200
|
6
|
50
|
|
|
|
14
|
push(@{$event->{assists}}, $event->{assist2}) if $asst2; |
|
6
|
|
|
|
|
10
|
|
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
} |
203
|
6
|
|
|
|
|
11
|
$event->{location} = 'UNK'; |
204
|
6
|
|
|
|
|
11
|
$event->{shot_type} = 'UNKNOWN'; |
205
|
6
|
|
|
|
|
7
|
$event->{distance} = 999; |
206
|
6
|
|
|
|
|
11
|
$event; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
sub read_boxscore_penalty_event ($$$$) { |
210
|
|
|
|
|
|
|
|
211
|
24
|
|
|
24
|
1
|
29
|
my $self = shift; |
212
|
24
|
|
|
|
|
27
|
my $row = shift; |
213
|
24
|
|
|
|
|
24
|
my $cell = shift; |
214
|
24
|
|
|
|
|
26
|
my $period = shift; |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
my $event = { |
217
|
|
|
|
|
|
|
type => 'PENL', |
218
|
|
|
|
|
|
|
str => 'XX', |
219
|
24
|
|
|
|
|
54
|
time => $cell->{_content}[0], |
220
|
|
|
|
|
|
|
team1 => $self->get_sub_tree(0, [1,0], $row), |
221
|
|
|
|
|
|
|
period => $period, |
222
|
|
|
|
|
|
|
}; |
223
|
24
|
50
|
|
|
|
47
|
return () if $event->{time} eq 'NONE'; |
224
|
24
|
|
|
|
|
44
|
my $offender = $self->get_sub_tree(0, [2,0], $row); |
225
|
24
|
50
|
|
|
|
39
|
if (ref $offender) { |
226
|
24
|
|
|
|
|
35
|
$event->{player1} = extract_id_from_href($offender); |
227
|
24
|
|
|
|
|
54
|
$event->{penalty} = $self->get_sub_tree(0, [2,1], $row); |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
else { |
230
|
0
|
|
|
|
|
0
|
$event->{penalty} = $offender; |
231
|
0
|
|
|
|
|
0
|
$event->{player1} = $BENCH_PLAYER_ID; |
232
|
0
|
|
|
|
|
0
|
$event->{length} = 2; |
233
|
|
|
|
|
|
|
} |
234
|
24
|
100
|
|
|
|
67
|
my $against = $event->{penalty} =~ /\bagainst\b/ ? 1 : 0; |
235
|
24
|
50
|
|
|
|
71
|
if ($event->{penalty} =~ /(.*\S)\s*\(maj\)/) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
236
|
0
|
|
|
|
|
0
|
$event->{length} = 5; |
237
|
0
|
|
|
|
|
0
|
$event->{penalty} = $1; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
elsif ($event->{penalty} =~ /(.*\S)\s*\(10.*min\)/) { |
240
|
0
|
|
|
|
|
0
|
$event->{length} = 10; |
241
|
0
|
|
|
|
|
0
|
$event->{penalty} = $1; |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
elsif ($event->{penalty} =~ /double minor/i) { |
244
|
0
|
|
|
|
|
0
|
$event->{length} = 4; |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
else { |
247
|
24
|
|
|
|
|
50
|
$event->{length} = 2; |
248
|
|
|
|
|
|
|
} |
249
|
24
|
100
|
|
|
|
36
|
if ($against) { |
250
|
22
|
|
|
|
|
48
|
$event->{player2} = extract_id_from_href($self->get_sub_tree(0, [2,2], $row)); |
251
|
22
|
|
|
|
|
38
|
$event->{team2} = 'OTH'; |
252
|
|
|
|
|
|
|
} |
253
|
24
|
50
|
|
|
|
50
|
$event->{misconduct} = 1 if $event->{penalty} =~ /conduct/i; |
254
|
|
|
|
|
|
|
$event->{length} = 10 if |
255
|
|
|
|
|
|
|
$event->{penalty} =~ /misconduct/i || |
256
|
|
|
|
|
|
|
$event->{penalty} =~ /Match/ || |
257
|
|
|
|
|
|
|
$event->{penalty} =~ /abuse.*official/i && $self->{season} > 1997 || |
258
|
24
|
50
|
33
|
|
|
134
|
$event->{penalty} =~ /leaving .* bench/i; |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
259
|
24
|
50
|
|
|
|
44
|
$event->{length} = 0 if $event->{penalty} =~ /penalty shot/i; |
260
|
24
|
100
|
33
|
|
|
79
|
if ( |
|
|
|
66
|
|
|
|
|
261
|
|
|
|
|
|
|
$event->{penalty} =~ /too many/i || |
262
|
|
|
|
|
|
|
$event->{penalty} =~ /\bbench\b/i && $event->{length} != 10 |
263
|
|
|
|
|
|
|
) { |
264
|
2
|
50
|
33
|
|
|
15
|
if ($event->{player1} && $event->{player1} =~ /^8\d{6}/) { |
265
|
2
|
|
|
|
|
6
|
$event->{servedby} = $event->{player1}; |
266
|
|
|
|
|
|
|
} |
267
|
2
|
50
|
|
|
|
8
|
$event->{player1} = $event->{penalty} =~ /coach/ ? $COACH_PLAYER_ID : $BENCH_PLAYER_ID; |
268
|
|
|
|
|
|
|
} |
269
|
24
|
|
|
|
|
68
|
$event->{penalty} =~ s/\s+against\s+//i; |
270
|
24
|
100
|
66
|
|
|
68
|
if ($event->{penalty} =~ /\bbench\b/i && $event->{penalty} !~ /leaving/i) { |
271
|
2
|
0
|
33
|
|
|
5
|
if (! $event->{servedby} && $event->{player1} && $event->{player1} != $BENCH_PLAYER_ID) { |
|
|
|
0
|
|
|
|
|
272
|
0
|
|
|
|
|
0
|
$event->{servedby} = $event->{player1}; |
273
|
|
|
|
|
|
|
} |
274
|
2
|
|
|
|
|
5
|
$event->{player1} = $BENCH_PLAYER_ID; |
275
|
2
|
|
|
|
|
11
|
$event->{penalty} =~ s/\s*\-\s+bench//i; |
276
|
|
|
|
|
|
|
} |
277
|
24
|
50
|
|
|
|
68
|
if ($event->{penalty} =~ /(.*\w)\W*\bcoach\b/i) { |
278
|
0
|
|
|
|
|
0
|
$event->{player1} = $COACH_PLAYER_ID; |
279
|
0
|
|
|
|
|
0
|
$event->{penalty} = $1; |
280
|
|
|
|
|
|
|
} |
281
|
24
|
50
|
|
|
|
42
|
if ($event->{penalty} =~ /aggressor/i) { |
282
|
0
|
|
|
|
|
0
|
$event->{length} = 10; |
283
|
|
|
|
|
|
|
} |
284
|
24
|
|
|
|
|
26
|
$event->{penalty} =~ s/\s*\-\s+obstruction//i; |
285
|
24
|
|
|
|
|
31
|
$event->{penalty} =~ s/(game)-(\S)/"$1 - $2"/ie; |
|
0
|
|
|
|
|
0
|
|
286
|
24
|
|
|
|
|
41
|
$event->{penalty} =~ s/\s*against\s*//i; |
287
|
24
|
|
|
|
|
32
|
$event->{location} = 'UNK'; |
288
|
24
|
|
|
|
|
37
|
$event; |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
sub read_boxscore_shootout_event ($$$$) { |
292
|
|
|
|
|
|
|
|
293
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
294
|
0
|
|
|
|
|
0
|
my $row = shift; |
295
|
0
|
|
|
|
|
0
|
my $cell = shift; |
296
|
0
|
|
|
|
|
0
|
my $period = shift; |
297
|
|
|
|
|
|
|
|
298
|
0
|
|
|
|
|
0
|
my $events; |
299
|
0
|
|
|
|
|
0
|
for my $t (1,3) { |
300
|
0
|
|
|
|
|
0
|
my $href = $self->get_sub_tree(0, [$t, 0], $row); |
301
|
0
|
0
|
|
|
|
0
|
next unless $href; |
302
|
0
|
|
|
|
|
0
|
my $event = { |
303
|
|
|
|
|
|
|
penaltyshot => 1, |
304
|
|
|
|
|
|
|
period => 5, |
305
|
|
|
|
|
|
|
time => '00:00', |
306
|
|
|
|
|
|
|
str => 'EV', |
307
|
|
|
|
|
|
|
shot_type => 'UNKNOWN', |
308
|
|
|
|
|
|
|
location => 'OFF', |
309
|
|
|
|
|
|
|
distance => 999, |
310
|
|
|
|
|
|
|
so => 1, |
311
|
|
|
|
|
|
|
}; |
312
|
0
|
0
|
|
|
|
0
|
if ($href->attr('class') =~ /shootoutgoal/i) { |
313
|
0
|
|
|
|
|
0
|
$event->{type} = 'GOAL'; |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
else { |
316
|
0
|
|
|
|
|
0
|
$event->{type} = 'MISS'; |
317
|
0
|
|
|
|
|
0
|
$event->{miss} = 'Unknown'; |
318
|
|
|
|
|
|
|
} |
319
|
0
|
|
|
|
|
0
|
$event->{player1} = extract_id_from_href($href); |
320
|
0
|
|
|
|
|
0
|
$event->{team1} = $self->{teams}[$self->{so_teams}[($t-1)/2]]{name}; |
321
|
0
|
|
|
|
|
0
|
push(@{$events}, $event); |
|
0
|
|
|
|
|
0
|
|
322
|
|
|
|
|
|
|
} |
323
|
0
|
|
|
|
|
0
|
$events; |
324
|
|
|
|
|
|
|
} |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
sub parse_event_summary ($$$$;$) { |
327
|
|
|
|
|
|
|
|
328
|
4
|
|
|
4
|
1
|
14
|
my $self = shift; |
329
|
4
|
|
|
|
|
9
|
my $summary = shift; |
330
|
4
|
|
|
|
|
6
|
my $type = shift; |
331
|
4
|
|
|
|
|
6
|
my $events = shift; |
332
|
|
|
|
|
|
|
|
333
|
4
|
|
|
|
|
6
|
my $r = 0; |
334
|
4
|
|
|
|
|
8
|
my $period = 0; |
335
|
4
|
|
|
|
|
5
|
my $shootout_mode = 0; |
336
|
4
|
|
|
|
|
11
|
while (my $row = $self->get_sub_tree(0, [$r], $summary)) { |
337
|
42
|
50
|
|
|
|
58
|
unless (ref $row) { |
338
|
0
|
|
|
|
|
0
|
$r++; |
339
|
0
|
|
|
|
|
0
|
next; |
340
|
|
|
|
|
|
|
} |
341
|
42
|
|
|
|
|
57
|
my $cell = $row->{_content}[0]; |
342
|
42
|
100
|
|
|
|
74
|
if ($cell->tag eq 'th') { |
|
|
50
|
|
|
|
|
|
343
|
12
|
50
|
|
|
|
69
|
unless ($shootout_mode) { |
344
|
12
|
|
|
|
|
18
|
$period = $cell->{_content}[0]; |
345
|
12
|
50
|
33
|
|
|
41
|
$period += 3 if $cell->{_content}[2] && $cell->{_content}[2] =~ /OT period/i; |
346
|
12
|
50
|
|
|
|
18
|
if ($period eq 'OT Period') { |
347
|
0
|
|
|
|
|
0
|
$period = 4; |
348
|
|
|
|
|
|
|
} |
349
|
12
|
50
|
|
|
|
24
|
if ($period eq 'Shootout') { |
350
|
0
|
|
|
|
|
0
|
$period = 5; |
351
|
0
|
|
|
|
|
0
|
$shootout_mode = 1; |
352
|
|
|
|
|
|
|
} |
353
|
12
|
50
|
|
|
|
20
|
$LAST_PERIOD = $period if $period > $LAST_PERIOD; |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
else { |
356
|
|
|
|
|
|
|
$self->{so_teams} = [ map { |
357
|
0
|
0
|
|
|
|
0
|
$self->{full_teams}[0] eq $_ ? 0 : 1, |
358
|
0
|
|
|
|
|
0
|
} ( $row->{_content}[1]{_content}[0], $row->{_content}[2]{_content}[0]) ]; |
359
|
|
|
|
|
|
|
} |
360
|
12
|
|
|
|
|
14
|
$r++; |
361
|
12
|
|
|
|
|
28
|
next; |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
elsif ($cell->tag eq 'td') { |
364
|
30
|
|
|
|
|
256
|
my $method = "read_boxscore_${type}_event"; |
365
|
30
|
|
|
|
|
56
|
my $event = $self->$method($row, $cell, $period); |
366
|
30
|
50
|
|
|
|
45
|
push(@{$events}, ref $event eq 'ARRAY' ? @{$event} : $event) if $event; |
|
30
|
50
|
|
|
|
65
|
|
|
0
|
|
|
|
|
0
|
|
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
else { |
369
|
0
|
|
|
|
|
0
|
print "strange cell ", $cell->tag, "\n"; |
370
|
0
|
|
|
|
|
0
|
exit; |
371
|
|
|
|
|
|
|
} |
372
|
30
|
|
|
|
|
79
|
$r++; |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
sub parse_lineup_row ($$$) { |
377
|
|
|
|
|
|
|
|
378
|
84
|
|
|
84
|
1
|
110
|
my $self = shift; |
379
|
84
|
|
|
|
|
90
|
my $row = shift; |
380
|
84
|
|
|
|
|
90
|
my $headers = shift; |
381
|
|
|
|
|
|
|
|
382
|
84
|
|
|
|
|
143
|
my $player = {}; |
383
|
84
|
|
|
|
|
97
|
my $c = 0; |
384
|
84
|
|
|
|
|
176
|
while (my $cell = $self->get_sub_tree(0, [$c], $row)) { |
385
|
1364
|
50
|
|
|
|
1888
|
confess "no ref in lineup cell" unless ref $cell; |
386
|
1364
|
100
|
|
|
|
2068
|
if ($cell->tag eq 'th') { |
387
|
104
|
|
|
|
|
480
|
push(@{$headers}, $cell->{_content}[0]); |
|
104
|
|
|
|
|
166
|
|
388
|
104
|
|
|
|
|
113
|
$c++; |
389
|
104
|
|
|
|
|
221
|
next; |
390
|
|
|
|
|
|
|
} |
391
|
1260
|
|
|
|
|
6649
|
my $content; |
392
|
1260
|
100
|
|
|
|
2041
|
if (ref $cell->{_content}[0]) { |
393
|
76
|
|
|
|
|
90
|
my $c2 = $cell->{_content}[0]; |
394
|
|
|
|
|
|
|
$content = extract_id_from_href( |
395
|
76
|
100
|
|
|
|
202
|
ref $c2->{_content}[0] ? $c2->{_content}[0] : $c2, |
396
|
|
|
|
|
|
|
); |
397
|
|
|
|
|
|
|
$player->{name} = extract_name_from_href( |
398
|
76
|
100
|
|
|
|
170
|
ref $c2->{_content}[0] ? $c2->{_content}[0] : $c2, |
399
|
|
|
|
|
|
|
); |
400
|
76
|
50
|
|
|
|
132
|
if (ref $c2) { |
401
|
76
|
|
|
|
|
114
|
$player->{wl} = $cell->{_content}[1]; |
402
|
|
|
|
|
|
|
} |
403
|
|
|
|
|
|
|
} |
404
|
|
|
|
|
|
|
else { |
405
|
1184
|
|
|
|
|
1380
|
$content = $cell->{_content}[0]; |
406
|
|
|
|
|
|
|
} |
407
|
1260
|
|
|
|
|
2132
|
$player->{$headers->[$c]} = $content; |
408
|
1260
|
|
|
|
|
2688
|
$c++; |
409
|
|
|
|
|
|
|
} |
410
|
84
|
|
|
|
|
151
|
$player; |
411
|
|
|
|
|
|
|
} |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
sub parse_lineup_summary ($$$) { |
414
|
|
|
|
|
|
|
|
415
|
8
|
|
|
8
|
1
|
13
|
my $self = shift; |
416
|
8
|
|
|
|
|
12
|
my $summary = shift; |
417
|
|
|
|
|
|
|
|
418
|
8
|
|
|
|
|
13
|
my $r = 0; |
419
|
8
|
|
|
|
|
14
|
my @headers = (); |
420
|
8
|
|
|
|
|
13
|
my @players = (); |
421
|
8
|
|
|
|
|
19
|
while (my $row = $self->get_sub_tree(0, [$r], $summary)) { |
422
|
84
|
|
|
|
|
149
|
my $player = $self->parse_lineup_row($row, \@headers); |
423
|
84
|
|
|
|
|
97
|
$r++; |
424
|
84
|
100
|
|
|
|
91
|
next unless keys %{$player}; |
|
84
|
|
|
|
|
213
|
|
425
|
76
|
|
100
|
|
|
180
|
$player->{position} = $player->{Pos} || 'G'; |
426
|
76
|
100
|
|
|
|
146
|
my $pos = $player->{position} eq 'G' ? 'G' : 'S'; |
427
|
76
|
100
|
|
|
|
117
|
if ($pos eq 'G') { |
428
|
4
|
|
|
|
|
10
|
for my $stat (qw(EV SH PP), 'Saves - Shots') { |
429
|
16
|
|
|
|
|
57
|
$player->{$stat} =~ /^(\d+)\s+\-\s+(\d+)$/; |
430
|
16
|
100
|
|
|
|
45
|
if ($stat eq 'EV') { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
431
|
4
|
|
|
|
|
14
|
$player->{evenSaves} = $1; |
432
|
4
|
|
|
|
|
13
|
$player->{evenShotsAgainst} = $2; |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
elsif ($stat eq 'SH') { |
435
|
4
|
|
|
|
|
11
|
$player->{powerPlaySaves} = $1; |
436
|
4
|
|
|
|
|
14
|
$player->{powerPlayShotsAgainst} = $2; |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
elsif ($stat eq 'PP') { |
439
|
4
|
|
|
|
|
11
|
$player->{shortHandedSaves} = $1; |
440
|
4
|
|
|
|
|
12
|
$player->{shortHandedShotsAgainst} = $2; |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
else { |
443
|
4
|
|
|
|
|
13
|
$player->{saves} = $1; |
444
|
4
|
|
|
|
|
11
|
$player->{shots} = $2; |
445
|
|
|
|
|
|
|
} |
446
|
|
|
|
|
|
|
} |
447
|
|
|
|
|
|
|
} |
448
|
76
|
|
|
|
|
82
|
for my $key (keys %{$NORMAL_FIELDS{$pos}}) { |
|
76
|
|
|
|
|
296
|
|
449
|
|
|
|
|
|
|
$player->{$NORMAL_FIELDS{$pos}->{$key}} = delete $player->{$key} |
450
|
1396
|
100
|
|
|
|
2721
|
if exists $player->{$key}; |
451
|
|
|
|
|
|
|
} |
452
|
76
|
|
|
|
|
148
|
for my $field (@{$LIVE_FIELDS{$pos}}) { |
|
76
|
|
|
|
|
124
|
|
453
|
588
|
|
50
|
|
|
1178
|
$player->{$field} ||= -1; |
454
|
|
|
|
|
|
|
} |
455
|
76
|
100
|
|
|
|
148
|
$player->{decision} =~ s/\W//g if $player->{decision}; |
456
|
76
|
|
50
|
|
|
239
|
$player->{evenTimeOnIce} ||= '00:00'; |
457
|
76
|
|
50
|
|
|
211
|
$player->{status} ||= 'X'; |
458
|
76
|
50
|
|
|
|
154
|
$player->{start} = 2 unless defined $player->{start}; |
459
|
76
|
|
|
|
|
286
|
push(@players, $player); |
460
|
|
|
|
|
|
|
} |
461
|
8
|
|
|
|
|
36
|
@players; |
462
|
|
|
|
|
|
|
} |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
sub parse_event_summaries ($$) { |
465
|
|
|
|
|
|
|
|
466
|
2
|
|
|
2
|
1
|
4
|
my $self = shift; |
467
|
2
|
|
|
|
|
6
|
my $summaries = shift; |
468
|
|
|
|
|
|
|
|
469
|
2
|
50
|
|
|
|
12
|
my $e = $self->get_sub_tree(0, [0,1,0,2,0,0], $summaries) ? 0 : 2; |
470
|
2
|
|
|
|
|
4
|
my $events = []; |
471
|
|
|
|
|
|
|
|
472
|
2
|
|
|
|
|
7
|
for my $summary_type (qw(scoring penalty)) { |
473
|
4
|
|
|
|
|
13
|
my $summary = $self->get_sub_tree(0, [0,1,$e,2,0,0], $summaries); |
474
|
4
|
|
|
|
|
17
|
$self->parse_event_summary($summary, $summary_type, $events); |
475
|
4
|
100
|
|
|
|
11
|
if ($summary_type eq 'scoring') { |
476
|
2
|
|
|
|
|
9
|
my $shootout = $self->get_sub_tree(0, [0,1,$e,2,1,0], $summaries); |
477
|
2
|
50
|
|
|
|
8
|
if ($shootout) { |
478
|
0
|
|
|
|
|
0
|
$self->{so} = 1; |
479
|
0
|
|
0
|
|
|
0
|
$self->{periods}[4] ||= {}; |
480
|
0
|
|
|
|
|
0
|
$self->parse_event_summary($shootout, 'shootout', $events); |
481
|
|
|
|
|
|
|
} |
482
|
|
|
|
|
|
|
} |
483
|
4
|
|
|
|
|
7
|
$e++; |
484
|
|
|
|
|
|
|
} |
485
|
2
|
|
|
|
|
7
|
$self->{events} = $events; |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
sub parse_lineup_summaries ($$) { |
489
|
|
|
|
|
|
|
|
490
|
2
|
|
|
2
|
1
|
4
|
my $self = shift; |
491
|
2
|
|
|
|
|
3
|
my $summaries = shift; |
492
|
|
|
|
|
|
|
|
493
|
2
|
50
|
|
|
|
10
|
my $e = $self->get_sub_tree(0, [0,1,2,2,0,0], $summaries) ? 2 : 0; |
494
|
2
|
|
|
|
|
9
|
my $x = $self->get_sub_tree(0, [0,1,2,2,0,0], $summaries); |
495
|
2
|
50
|
33
|
|
|
14
|
if ($e == 2 && $x->tag eq 'tbody') { |
496
|
0
|
|
|
|
|
0
|
$e += 2; |
497
|
|
|
|
|
|
|
} |
498
|
2
|
|
|
|
|
15
|
my $s = 1; my $t = 1; |
|
2
|
|
|
|
|
4
|
|
499
|
2
|
|
|
|
|
5
|
for my $team (qw(away home)) { |
500
|
4
|
|
|
|
|
7
|
for my $roster (qw(skaters goalie)) { |
501
|
8
|
|
|
|
|
45
|
my $summary = $self->get_sub_tree(0, [0,1,$e,2,2*$s-$t,0], $summaries); |
502
|
8
|
|
|
|
|
27
|
my @players = $self->parse_lineup_summary($summary); |
503
|
8
|
|
100
|
|
|
145
|
$self->{teams}[1-$t]{roster} ||= []; |
504
|
8
|
|
|
|
|
13
|
push(@{$self->{teams}[1-$t]{roster}}, @players); |
|
8
|
|
|
|
|
32
|
|
505
|
8
|
|
|
|
|
64
|
$s++; |
506
|
|
|
|
|
|
|
} |
507
|
4
|
|
|
|
|
10
|
$t--; |
508
|
|
|
|
|
|
|
} |
509
|
|
|
|
|
|
|
} |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
sub parse_officials_box ($$) { |
512
|
|
|
|
|
|
|
|
513
|
4
|
|
|
4
|
1
|
6
|
my $self = shift; |
514
|
4
|
|
|
|
|
6
|
my $ei_box = shift; |
515
|
|
|
|
|
|
|
|
516
|
4
|
|
|
|
|
15
|
my $officials_box = $self->get_sub_tree(0, [2,0], $ei_box); |
517
|
|
|
|
|
|
|
|
518
|
4
|
|
|
|
|
13
|
my $referees = $self->get_sub_tree(0, [1,0], $officials_box); |
519
|
4
|
|
|
|
|
7
|
my $officials = {}; |
520
|
4
|
100
|
66
|
|
|
20
|
if ($referees && !ref $referees) { |
521
|
2
|
50
|
|
|
|
26
|
if ($referees =~ /:\s+(\S+.*\S+)\s*\,\s+(\S+.*\S+)\s*$/) { |
522
|
|
|
|
|
|
|
$officials->{referees} = [ |
523
|
2
|
|
|
|
|
22
|
{ name => $1, number => 0 }, { name => $2, number => 0 }, |
524
|
|
|
|
|
|
|
]; |
525
|
|
|
|
|
|
|
} |
526
|
|
|
|
|
|
|
else { |
527
|
0
|
|
|
|
|
0
|
$referees =~ /:\s+(\S+.*\S+)/; |
528
|
|
|
|
|
|
|
$officials->{referees} = [ |
529
|
0
|
|
|
|
|
0
|
{ name => $1, number => 0 } |
530
|
|
|
|
|
|
|
]; |
531
|
|
|
|
|
|
|
} |
532
|
2
|
|
|
|
|
10
|
my $linesmen = $self->get_sub_tree(0, [2,0], $officials_box); |
533
|
2
|
50
|
|
|
|
12
|
return {} unless $linesmen; |
534
|
2
|
50
|
|
|
|
28
|
if ($linesmen =~ /:\s+(\S+.*\S+)\s*\,\s+(\S+.*\S+)\s*$/) { |
535
|
|
|
|
|
|
|
$officials->{linesmen} = [ |
536
|
2
|
|
|
|
|
31
|
{ name => $1, number => 0 }, { name => $2, number => 0 }, |
537
|
|
|
|
|
|
|
]; |
538
|
|
|
|
|
|
|
} |
539
|
|
|
|
|
|
|
else { |
540
|
0
|
|
|
|
|
0
|
$linesmen =~ /:\s+(\S+.*\S+)/; |
541
|
|
|
|
|
|
|
$officials->{linesmen} = [ |
542
|
0
|
|
|
|
|
0
|
{ name => $1, number => 0 }, |
543
|
|
|
|
|
|
|
]; |
544
|
|
|
|
|
|
|
} |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
else { |
547
|
2
|
|
|
|
|
6
|
$officials = {}; |
548
|
|
|
|
|
|
|
} |
549
|
4
|
|
|
|
|
16
|
$self->{officials} = $officials; |
550
|
|
|
|
|
|
|
} |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
sub parse_coaches ($$) { |
553
|
|
|
|
|
|
|
|
554
|
4
|
|
|
4
|
1
|
7
|
my $self = shift; |
555
|
4
|
|
|
|
|
7
|
my $ei_box = shift; |
556
|
|
|
|
|
|
|
|
557
|
4
|
|
|
|
|
15
|
my $coach_box = $self->get_sub_tree(0, [2,1], $ei_box); |
558
|
4
|
100
|
|
|
|
14
|
return unless $coach_box; |
559
|
|
|
|
|
|
|
|
560
|
2
|
|
|
|
|
6
|
for my $c (0,1) { |
561
|
4
|
|
|
|
|
11
|
my $coach = $self->get_sub_tree(0, [$c+1,0], $coach_box); |
562
|
4
|
|
|
|
|
20
|
$coach =~ s/^(.*)\:.*/$1/e; |
|
4
|
|
|
|
|
12
|
|
563
|
4
|
|
|
|
|
16
|
$self->{teams}[$c]{coach} = $coach; |
564
|
|
|
|
|
|
|
} |
565
|
|
|
|
|
|
|
} |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
sub parse_ei_box ($$$) { |
568
|
|
|
|
|
|
|
|
569
|
10
|
|
|
10
|
1
|
14
|
my $self = shift; |
570
|
10
|
|
|
|
|
13
|
my $ei_box = shift; |
571
|
|
|
|
|
|
|
|
572
|
10
|
|
100
|
|
|
25
|
my $box_id = $ei_box->attr('id') || ''; |
573
|
10
|
|
|
|
|
110
|
for ($box_id) { |
574
|
10
|
|
|
|
|
19
|
when ('gameReports') { |
575
|
4
|
|
|
|
|
14
|
$self->parse_officials_box($ei_box); |
576
|
4
|
|
|
|
|
15
|
$self->parse_coaches($ei_box); |
577
|
|
|
|
|
|
|
} |
578
|
6
|
|
|
|
|
9
|
when ('threeStars') { |
579
|
0
|
|
|
|
|
0
|
$self->{stars} = []; |
580
|
0
|
|
|
|
|
0
|
for my $s (0..2) { |
581
|
0
|
|
|
|
|
0
|
my $star = $self->get_sub_tree(0, [2,$s,0,0], $ei_box); |
582
|
0
|
0
|
|
|
|
0
|
push(@{$self->{stars}}, extract_id_from_href($star)) if $star; |
|
0
|
|
|
|
|
0
|
|
583
|
|
|
|
|
|
|
} |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
} |
586
|
|
|
|
|
|
|
} |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
sub fill_broken_rosters ($$) { |
589
|
|
|
|
|
|
|
|
590
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
591
|
0
|
|
|
|
|
0
|
my $broken_rosters = shift; |
592
|
|
|
|
|
|
|
|
593
|
0
|
|
|
|
|
0
|
my $r = 0; |
594
|
0
|
|
|
|
|
0
|
for my $broken_roster (@{$broken_rosters}) { |
|
0
|
|
|
|
|
0
|
|
595
|
0
|
|
|
|
|
0
|
for my $broken_player (@{$broken_roster}) { |
|
0
|
|
|
|
|
0
|
|
596
|
0
|
|
|
|
|
0
|
for my $player (@{$self->{teams}[$r]{roster}}) { |
|
0
|
|
|
|
|
0
|
|
597
|
0
|
0
|
|
|
|
0
|
if ($player->{number} == $broken_player->{'No.'}) { |
598
|
0
|
|
|
|
|
0
|
for my $field (keys %{$broken_player}) { |
|
0
|
|
|
|
|
0
|
|
599
|
0
|
0
|
|
|
|
0
|
next if $field eq 'No.'; |
600
|
0
|
0
|
|
|
|
0
|
unless (exists $player->{$field}) { |
601
|
0
|
0
|
0
|
|
|
0
|
if ($field eq 'number' || $field eq 'error') { |
602
|
0
|
|
|
|
|
0
|
$player->{number} = $broken_player->{$field}; |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
else { |
605
|
0
|
|
|
|
|
0
|
die "Invalid field $field specified"; |
606
|
|
|
|
|
|
|
} |
607
|
|
|
|
|
|
|
} |
608
|
0
|
|
|
|
|
0
|
$player->{$field} = $broken_player->{$field}; |
609
|
|
|
|
|
|
|
} |
610
|
|
|
|
|
|
|
} |
611
|
|
|
|
|
|
|
} |
612
|
|
|
|
|
|
|
} |
613
|
0
|
|
|
|
|
0
|
$r++; |
614
|
|
|
|
|
|
|
} |
615
|
|
|
|
|
|
|
} |
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
sub fill_missing_and_broken ($) { |
618
|
|
|
|
|
|
|
|
619
|
2
|
|
|
2
|
1
|
5
|
my $self = shift; |
620
|
|
|
|
|
|
|
|
621
|
2
|
50
|
|
|
|
10
|
if ($MISSING_EVENTS{$self->{_id}}) { |
622
|
0
|
|
|
|
|
0
|
for my $event (@{$MISSING_EVENTS{$self->{_id}}}) { |
|
0
|
|
|
|
|
0
|
|
623
|
0
|
|
|
|
|
0
|
push(@{$self->{events}}, $event) |
624
|
0
|
0
|
0
|
|
|
0
|
unless $event->{type} eq 'PEND' || $event->{type} eq 'GEND'; |
625
|
|
|
|
|
|
|
} |
626
|
|
|
|
|
|
|
} |
627
|
2
|
50
|
|
|
|
10
|
if ($MISSING_COACHES{$self->{_id}}) { |
628
|
0
|
|
|
|
|
0
|
$self->{teams}[0]{coach} = $MISSING_COACHES{$self->{_id}}->[0]; |
629
|
0
|
|
|
|
|
0
|
$self->{teams}[1]{coach} = $MISSING_COACHES{$self->{_id}}->[1]; |
630
|
|
|
|
|
|
|
} |
631
|
|
|
|
|
|
|
$self->fill_broken_rosters($self, $BROKEN_ROSTERS{$self->{_id}}) |
632
|
2
|
50
|
|
|
|
11
|
if $BROKEN_ROSTERS{$self->{_id}}; |
633
|
|
|
|
|
|
|
} |
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
sub parse ($) { |
636
|
|
|
|
|
|
|
|
637
|
2
|
|
|
2
|
1
|
3
|
my $self = shift; |
638
|
|
|
|
|
|
|
|
639
|
2
|
|
|
|
|
4
|
my $flag = 1; |
640
|
|
|
|
|
|
|
|
641
|
2
|
|
|
|
|
8
|
for my $i (0..60) { |
642
|
122
|
|
|
|
|
490
|
my $main_div = $self->get_sub_tree(0, [$i]); |
643
|
122
|
100
|
|
|
|
216
|
next unless ref $main_div; |
644
|
|
|
|
|
|
|
# print "I $i\n"; |
645
|
42
|
100
|
66
|
|
|
68
|
if ($main_div->attr('class') && $main_div->attr('class') eq 'chrome') { |
646
|
4
|
100
|
|
|
|
78
|
if ($flag == $BOXSCORE_HEADER) { |
|
|
50
|
|
|
|
|
|
647
|
2
|
|
|
|
|
9
|
$self->read_header($main_div); |
648
|
2
|
|
|
|
|
5
|
$flag++; |
649
|
|
|
|
|
|
|
} |
650
|
|
|
|
|
|
|
elsif ($flag == $BOXSCORE_GAME) { |
651
|
2
|
|
|
|
|
10
|
$self->parse_event_summaries($main_div); |
652
|
2
|
|
|
|
|
8
|
$self->parse_lineup_summaries($main_div); |
653
|
2
|
|
|
|
|
10
|
my $extra_info_box = $self->get_sub_tree(0, [0,2], $main_div); |
654
|
2
|
|
|
|
|
5
|
my $x = 0; |
655
|
2
|
|
|
|
|
6
|
while (my $ei_box = $self->get_sub_tree(0, [$x], $extra_info_box)) { |
656
|
10
|
|
|
|
|
31
|
$self->parse_ei_box($ei_box); |
657
|
10
|
|
|
|
|
26
|
$x++; |
658
|
|
|
|
|
|
|
} |
659
|
2
|
|
|
|
|
10
|
$flag++; |
660
|
|
|
|
|
|
|
} |
661
|
|
|
|
|
|
|
else { |
662
|
0
|
|
|
|
|
0
|
print "Got strange box\n"; |
663
|
0
|
|
|
|
|
0
|
print $main_div->dump; |
664
|
0
|
|
|
|
|
0
|
exit; |
665
|
|
|
|
|
|
|
} |
666
|
|
|
|
|
|
|
} |
667
|
|
|
|
|
|
|
} |
668
|
2
|
|
|
|
|
10
|
$self->fill_missing_and_broken(); |
669
|
|
|
|
|
|
|
} |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
sub fill_event_default_values ($$) { |
672
|
|
|
|
|
|
|
|
673
|
30
|
|
|
30
|
1
|
34
|
my $self = shift; |
674
|
30
|
|
|
|
|
34
|
my $event = shift; |
675
|
|
|
|
|
|
|
|
676
|
30
|
|
|
|
|
36
|
$event->{file} = $self->{file}; |
677
|
30
|
|
|
|
|
57
|
$event->{stage} = $self->{stage}; |
678
|
30
|
|
|
|
|
47
|
$event->{season} = $self->{season}; |
679
|
30
|
50
|
66
|
|
|
87
|
$event->{strength} = delete $event->{str} if (!$event->{strength} && $event->{str}); |
680
|
30
|
50
|
33
|
|
|
58
|
$event->{strength} = 'EV' if $event->{strength} eq 'PS' && $event->{time} eq '0:00'; |
681
|
30
|
100
|
|
|
|
49
|
if ($event->{type} eq 'PENL') { |
682
|
24
|
|
|
|
|
70
|
$event->{penalty} =~ s/^\s+//; |
683
|
24
|
|
|
|
|
77
|
$event->{penalty} =~ s/\s+$//; |
684
|
24
|
|
|
|
|
31
|
$event->{penalty} =~ s/\xC2\xA0//g; |
685
|
24
|
|
|
|
|
38
|
$event->{penalty} = uc($event->{penalty}); |
686
|
|
|
|
|
|
|
} |
687
|
30
|
50
|
33
|
|
|
60
|
if ($BROKEN_EVENTS{BH}->{$self->{_id}} |
688
|
|
|
|
|
|
|
&& (my $evx = $BROKEN_EVENTS{BH}->{$self->{_id}}{$event->{id}})) { |
689
|
0
|
0
|
|
|
|
0
|
if ($evx->{broken}) { |
690
|
0
|
|
|
|
|
0
|
$event->{broken} = 1; |
691
|
|
|
|
|
|
|
} |
692
|
|
|
|
|
|
|
else { |
693
|
0
|
|
|
|
|
0
|
for my $error (keys %{$evx}) { |
|
0
|
|
|
|
|
0
|
|
694
|
|
|
|
|
|
|
defined $evx->{$error} |
695
|
|
|
|
|
|
|
? $event->{$error} = $evx->{$error} |
696
|
0
|
0
|
|
|
|
0
|
: delete $event->{$error}; |
697
|
|
|
|
|
|
|
} |
698
|
|
|
|
|
|
|
} |
699
|
|
|
|
|
|
|
} |
700
|
30
|
100
|
|
|
|
83
|
$event->{time} = $1 if $event->{time} =~ /^0(\d.*)/; |
701
|
30
|
|
|
|
|
91
|
$event->{on_ice} = [[],[]]; |
702
|
|
|
|
|
|
|
} |
703
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
sub normalize ($) { |
705
|
|
|
|
|
|
|
|
706
|
2
|
|
|
2
|
1
|
4
|
my $self = shift; |
707
|
|
|
|
|
|
|
|
708
|
2
|
|
50
|
|
|
27
|
$self->{location} ||= 'Unknown Location'; |
709
|
2
|
|
50
|
|
|
39
|
$self->{attendance} ||= 0; |
710
|
2
|
|
|
|
|
7
|
for my $p (3..$LAST_PERIOD-1) { |
711
|
0
|
|
0
|
|
|
0
|
$self->{periods}[$p] ||= {}; |
712
|
|
|
|
|
|
|
} |
713
|
2
|
|
|
|
|
6
|
for my $e (1..@{$self->{events}}) { |
|
2
|
|
|
|
|
6
|
|
714
|
30
|
|
|
|
|
53
|
my $event = $self->{events}[$e-1]; |
715
|
30
|
|
|
|
|
45
|
$event->{id} = $e; |
716
|
30
|
|
|
|
|
49
|
$self->fill_event_default_values($event); |
717
|
|
|
|
|
|
|
} |
718
|
|
|
|
|
|
|
} |
719
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
1; |