line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Sport::Analytics::NHL::Populator; |
2
|
|
|
|
|
|
|
|
3
|
26
|
|
|
26
|
|
82759
|
use v5.10.1; |
|
26
|
|
|
|
|
126
|
|
4
|
26
|
|
|
26
|
|
132
|
use strict; |
|
26
|
|
|
|
|
53
|
|
|
26
|
|
|
|
|
588
|
|
5
|
26
|
|
|
26
|
|
121
|
use warnings FATAL => 'all'; |
|
26
|
|
|
|
|
58
|
|
|
26
|
|
|
|
|
1118
|
|
6
|
26
|
|
|
26
|
|
136
|
use experimental qw(smartmatch); |
|
26
|
|
|
|
|
56
|
|
|
26
|
|
|
|
|
204
|
|
7
|
|
|
|
|
|
|
|
8
|
26
|
|
|
26
|
|
2088
|
use Sport::Analytics::NHL::DB; |
|
26
|
|
|
|
|
57
|
|
|
26
|
|
|
|
|
592
|
|
9
|
26
|
|
|
26
|
|
135
|
use Sport::Analytics::NHL::Util; |
|
26
|
|
|
|
|
57
|
|
|
26
|
|
|
|
|
1866
|
|
10
|
26
|
|
|
26
|
|
559
|
use Sport::Analytics::NHL::Tools; |
|
26
|
|
|
|
|
61
|
|
|
26
|
|
|
|
|
5282
|
|
11
|
26
|
|
|
26
|
|
609
|
use Sport::Analytics::NHL::Scraper; |
|
26
|
|
|
|
|
97
|
|
|
26
|
|
|
|
|
1306
|
|
12
|
26
|
|
|
26
|
|
578
|
use Sport::Analytics::NHL::Normalizer; |
|
26
|
|
|
|
|
61
|
|
|
26
|
|
|
|
|
1384
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 NAME |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
Sport::Analytics::NHL::Populator - populates the Mongo DB from the normalized boxscores - see Sport::Analytics::NHL::Normalizer for that and from other sources. |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 SYNOPSYS |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
Populates the Mongo DB from the normalized boxscores - see Sport::Analytics::NHL::Normalizer for that and from other sources. |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
This module serves as a buffer between the external parts and the Sport::Analytics::NHL::DB MongoDB interface. |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
use Sport::Analytics::NHL::Populator; |
26
|
|
|
|
|
|
|
my @db_game_ids = populate_db($boxscore, $opts) |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=head1 FUNCTIONS |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=over 2 |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=item C |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
Creates and/or updates all the entries in the MongoDB related to the given normalized boxscore. If necessary, and if enabled, the player files from the NHL website are crawled for each participating player. Additional entries are created for: |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
* game events |
37
|
|
|
|
|
|
|
* team coaches |
38
|
|
|
|
|
|
|
* game location |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
See the documentation for Sport::Analytics::NHL::DB for more details. |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
Arguments: |
43
|
|
|
|
|
|
|
* the normalized boxscore |
44
|
|
|
|
|
|
|
* options hashref: |
45
|
|
|
|
|
|
|
- crawl_players - whether to crawl for playerfiles |
46
|
|
|
|
|
|
|
- force - overwrite previous data |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
Returns: the id of the inserted boxscore. |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=item C |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
Work in progress. Do not use yet. |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=back |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=cut |
57
|
|
|
|
|
|
|
|
58
|
26
|
|
|
26
|
|
146
|
use parent 'Exporter'; |
|
26
|
|
|
|
|
48
|
|
|
26
|
|
|
|
|
162
|
|
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
our @EXPORT = qw(populate_db populate_injured_players); |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
sub populate_db ($;$$) { |
63
|
|
|
|
|
|
|
|
64
|
0
|
|
|
0
|
1
|
|
my $boxscore = shift; |
65
|
0
|
|
|
|
|
|
my $opts = shift; |
66
|
|
|
|
|
|
|
|
67
|
0
|
|
|
|
|
|
my $PLAYER_IDS = create_player_id_hash($boxscore); |
68
|
0
|
|
|
|
|
|
verbose "Populating $boxscore->{_id}"; |
69
|
0
|
|
0
|
|
|
|
$DB ||= Sport::Analytics::NHL::DB->new(); |
70
|
0
|
0
|
|
|
|
|
if ($boxscore->{location}) { |
71
|
|
|
|
|
|
|
my $location = $DB->create_location({ |
72
|
|
|
|
|
|
|
name => $boxscore->{location}, |
73
|
0
|
|
0
|
|
|
|
capacity => $boxscore->{attendance} || 0, |
74
|
|
|
|
|
|
|
}); |
75
|
0
|
|
|
|
|
|
$boxscore->{location} = $location->{_id}; |
76
|
|
|
|
|
|
|
} |
77
|
0
|
0
|
|
|
|
|
unless ($opts->{no_crawl}) { |
78
|
0
|
|
|
|
|
|
for my $player_id (keys %{$PLAYER_IDS}) { |
|
0
|
|
|
|
|
|
|
79
|
0
|
0
|
|
|
|
|
next if $player_id == 8400001; |
80
|
0
|
|
|
|
|
|
my $team = ${$PLAYER_IDS->{$player_id}}->{team}; |
|
0
|
|
|
|
|
|
|
81
|
0
|
|
|
|
|
|
debug "Crawling $player_id"; |
82
|
0
|
|
|
|
|
|
my $player; |
83
|
0
|
0
|
|
|
|
|
if ($CACHES->{players}{$player_id}) { |
84
|
0
|
|
|
|
|
|
$player = $CACHES->{players}{$player_id}; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
else { |
87
|
0
|
|
|
|
|
|
my $p_file = crawl_player($player_id, $opts); |
88
|
0
|
0
|
|
|
|
|
die "Player $player_id is not available" unless $p_file; |
89
|
0
|
|
|
|
|
|
$player = Sport::Analytics::NHL::Report->new({ |
90
|
|
|
|
|
|
|
file => $p_file, |
91
|
|
|
|
|
|
|
type => 'Player', |
92
|
|
|
|
|
|
|
}); |
93
|
0
|
|
|
|
|
|
$player->process(); |
94
|
0
|
|
|
|
|
|
$CACHES->{players}{$player_id} = $player; |
95
|
|
|
|
|
|
|
} |
96
|
0
|
|
|
|
|
|
debug "Adding player $player->{name} ($player->{_id})"; |
97
|
0
|
|
|
|
|
|
$DB->add_game_player($player, $boxscore, $team, $opts->{force}); |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
} |
100
|
0
|
|
|
|
|
|
$DB->add_game_coaches($boxscore); |
101
|
0
|
|
|
|
|
|
my @events = (); |
102
|
0
|
|
|
|
|
|
for my $event (@{$boxscore->{events}}) { |
|
0
|
|
|
|
|
|
|
103
|
0
|
|
|
|
|
|
push(@events, $DB->create_event($event)); |
104
|
|
|
|
|
|
|
} |
105
|
0
|
|
|
|
|
|
$boxscore->{events} = [@events]; |
106
|
0
|
0
|
|
|
|
|
$DB->remove_game($boxscore) if $opts->{force}; |
107
|
0
|
|
|
|
|
|
$DB->add_game($boxscore); |
108
|
0
|
|
|
|
|
|
$boxscore->{_id}; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub populate_injured_players ($) { |
112
|
|
|
|
|
|
|
|
113
|
0
|
|
|
0
|
1
|
|
my $players = shift; |
114
|
|
|
|
|
|
|
|
115
|
0
|
|
0
|
|
|
|
$DB ||= Sport::Analytics::NHL::DB->new(); |
116
|
0
|
|
|
|
|
|
my $players_c = $DB->get_collection('players'); |
117
|
0
|
|
|
|
|
|
my $today = strftime("%Y%m%d", localtime(time)); |
118
|
0
|
|
|
|
|
|
for my $player (@{$players}) { |
|
0
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
my @players = $players_c->find({ |
120
|
|
|
|
|
|
|
name => $player->{name}, |
121
|
|
|
|
|
|
|
active => 1, |
122
|
|
|
|
|
|
|
team => $player->{team}, |
123
|
0
|
|
|
|
|
|
})->all(); |
124
|
0
|
0
|
|
|
|
|
if (! @players) { |
125
|
0
|
|
|
|
|
|
print "Skipping missing player $player->{player_name}\n"; |
126
|
0
|
|
|
|
|
|
next; |
127
|
|
|
|
|
|
|
} |
128
|
0
|
|
|
|
|
|
debug "Updating $players[0]->{_id} / $player->{player_name} / $players[0]->{team}"; |
129
|
0
|
|
|
|
|
|
set_injury_history($players[0], {start_ts => time }, $player->{injury}); |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
1; |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=head1 AUTHOR |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
More Hockey Stats, C<< >> |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=head1 BUGS |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
Please report any bugs or feature requests to C, or through |
142
|
|
|
|
|
|
|
the web interface at L. I will be notified, and then you'll |
143
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes. |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=head1 SUPPORT |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
perldoc Sport::Analytics::NHL::Populator |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
You can also look for information at: |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=over 4 |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker (report bugs here) |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
L |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
L |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=item * CPAN Ratings |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
L |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=item * Search CPAN |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
L |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=back |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=cut |
175
|
|
|
|
|
|
|
|