|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Sport::Analytics::NHL::Merger;  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
50259
 | 
 use v5.10.1;  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
67
 | 
    | 
| 
4
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
93
 | 
 use strict;  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
    | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
444
 | 
    | 
| 
5
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
75
 | 
 use warnings FATAL => 'all';  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
    | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
582
 | 
    | 
| 
6
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
83
 | 
 use experimental qw(smartmatch);  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
    | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
143
 | 
    | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
8
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
943
 | 
 use Carp;  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
    | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
977
 | 
    | 
| 
9
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
554
 | 
 use Storable qw(dclone);  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2347
 | 
    | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
722
 | 
    | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
11
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
504
 | 
 use List::MoreUtils qw(firstval uniq);  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8666
 | 
    | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
143
 | 
    | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
13
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
12844
 | 
 use Sport::Analytics::NHL::Config;  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
    | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3000
 | 
    | 
| 
14
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
514
 | 
 use Sport::Analytics::NHL::Errors;  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
    | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2872
 | 
    | 
| 
15
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
5729
 | 
 use Sport::Analytics::NHL::Tools;  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
46
 | 
    | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2944
 | 
    | 
| 
16
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
138
 | 
 use Sport::Analytics::NHL::Util;  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
    | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1322
 | 
    | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 NAME  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Sport::Analytics::NHL::Merger - Merge the extra (HTML) reports into the master one (JSON).  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 SYNOPSYS  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Merge the extra (HTML) reports into the master one (JSON).  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 These are methods that match the data in the extra reports to the master one and merge it, or complement it, where necessary.  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     use Sport::Analytics::NHL::Merger;  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     merge_report($boxscore, $html_report);  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 GLOBAL VARIABLES  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  The behaviour of the tests is controlled by several global variables:  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  * $CURRENT - the type of the report currently being merged.  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  * $BOXSCORE - the boxscore currently being merged.  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  * $PLAYER_RESOLVE_CACHE - the player roster resolution cache as described in Sport::Analytics::NHL::Report::BS (q.v.)  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 FUNCTIONS  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =over 2  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 When trying to resolve a player in the HTML report to his NHL id, look up by player's name in the names section of the resolve cache.  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * event description  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * resolve cache  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * player's number  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: the reference to the player in the boxscore roster  | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Copy the events from a report when the original section of reports in the live boxscore is missing.  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the boxscore report  | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the extra report being merged  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: void, sets $boxscore->{events}  | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Checks if the event in the merged report was expected to be missed (i.e. not matched) within the boxscore  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the type of the merged report  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the event in question  | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the master boxscore  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: 0|1  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Finds the matching event from the extra report in the master boxscore.  | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the event  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the master boxscore event list  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the type of the extra report  | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: the matched event or -1  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Finds the matching player from the extra report in the master boxscore.  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the player data  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the roster in the matching boxscore to look in  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * [optional] list of players on ice to look in  | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: the matched player or undef  | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Used by find_player to find the player by the NHL id.  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the player data  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the roster in the matching boxscore to look in  | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: the matched player or undef  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Used by find_player to find the player by the name.  | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the player data  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the roster in the matching boxscore to look in  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * [optional] list of players on ice to look in  | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: the matched player or undef  | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Merges the matched events' data. Usually the data in the boxscore is considered correct, so only additional data is added.  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the boxscore report  | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the extra report being merged  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: void, sets $boxscore->{events}  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Actually performs the merging of the item. Usually the data in the boxscore is considered correct, so only additional data is added.  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the boxscore item  | 
| 
116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the extra report item  | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * [optional] list of fields to be merged  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: void, sets the event's fields.  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
120
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The function to call to merge two reports.  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the boxscore report  | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the extra report being merged  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: void, sets $boxscore and adds $boxscore->{sources}  | 
| 
127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Merges two rosters of a team, from the master boxscore and from the extra report.  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the boxscore roster  | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the report roster  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: void, sets the roster.  | 
| 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Merges the teams of the game, from the master boxscore and from the extra report.  | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the boxscore report  | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the extra report being merged  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: void, sets $boxscore  | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
146
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Pushes the event that is found in the extra report but not in the master boxscore into the master boxscore's event list.  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the event  | 
| 
149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the master boxscore  | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the type of the extra report  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: void, sets $boxscore->{events}  | 
| 
152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 In case find_event (q.v.) is matched with more than one event, refines the candidate list to ultimately find the event.  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the event  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the list of candidates  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: the refined list of candidates  | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Resolves the extra report players in the roster, in the events and on ice to their NHL ids.  | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the boxscore report  | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the extra report being merged  | 
| 
167
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: void. The extra report is modified.  | 
| 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
170
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Resolves event fields such as player1, player2, assist1, assist2 and servedby to the NHL ids.  | 
| 
172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the event  | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the master boxscore  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: void. The event is modified.  | 
| 
176
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Resolves the extra report event teams to their NHL ids.  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the event  | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the master boxscore  | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: void. The event is modified.  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Resolves the players on the ice during the event to their NHL ids.  | 
| 
188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the event  | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the master boxscore  | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: void. The event is modified.  | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item C  | 
| 
194
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Resolves the players on the rosters of the extra report to their NHL ids.  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Arguments: * the roster  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the master boxscore  | 
| 
199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             * the roster index (0 - away, 1 - home)  | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  Returns: void. The roster is modified.  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =back  | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
206
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
97
 | 
 use parent 'Exporter';  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
    | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
88
 | 
    | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our @EXPORT = qw(merge_report);  | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
210
 | 
20
 | 
 
 | 
 
 | 
  
20
  
 | 
 
 | 
1131
 | 
 use Data::Dumper;  | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
    | 
| 
 
 | 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
63758
 | 
    | 
| 
211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $Data::Dumper::Trailingcomma = 1;  | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $Data::Dumper::Deepcopy      = 1;  | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $Data::Dumper::Sortkeys      = 1;  | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $Data::Dumper::Deparse       = 1;  | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
216
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $CURRENT = '';  | 
| 
217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $BOXSCORE = {};  | 
| 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our @MERGE_HEADER = qw(tz month date location attendance);  | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $PLAYER_RESOLVE_CACHE = {};  | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub find_player_by_id ($$) {  | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
224
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
  
1
  
 | 
5
 | 
 	my $player = shift;  | 
| 
225
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	my $team   = shift;  | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
227
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	my $bs_player;  | 
| 
228
 | 
3
 | 
 
 | 
 
 | 
  
64
  
 | 
 
 | 
12
 | 
 	$bs_player = firstval { $_->{_id} == $player->{_id} } @{$team->{roster}};  | 
| 
 
 | 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
68
 | 
    | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
    | 
| 
229
 | 
3
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
17
 | 
 	if (!$bs_player) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
230
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 		$PLAYER_RESOLVE_CACHE->{$team->{name}}{$player->{number}} = \$player;  | 
| 
231
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 		push(@{$team->{roster}}, $player);  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
    | 
| 
232
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 		return $player;  | 
| 
233
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	elsif (!$bs_player->{number} || $bs_player->{number} != $player->{number}) {  | 
| 
235
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
 		$bs_player->{number} = $player->{number};  | 
| 
236
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 		$PLAYER_RESOLVE_CACHE->{$team->{name}}{$player->{number}} = \$bs_player;  | 
| 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
238
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
6
 | 
 	if ($bs_player->{broken}) {  | 
| 
239
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		for my $field (keys %{$player}) {  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
240
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$bs_player->{$field} = $player->{$field};  | 
| 
241
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			delete $bs_player->{broken};  | 
| 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
243
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
244
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 	$bs_player;  | 
| 
245
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
246
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub find_player_by_name ($$$) {  | 
| 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
249
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
  
1
  
 | 
24
 | 
 	my $player = shift;  | 
| 
250
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
 	my $team   = shift;  | 
| 
251
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
 	my $on_ice = shift;  | 
| 
252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
253
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
 	$player->{name} = uc $player->{name};  | 
| 
254
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
 	my ($name, $fname) = ($player->{name}, '');  | 
| 
255
 | 
12
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
47
 | 
 	if ($player->{name} =~ /\.\s*(\S+.*)$/ && $name !~ /^st\./i) {  | 
| 
256
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$name = $1;  | 
| 
257
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$fname = substr($player->{name}, 0, 1);  | 
| 
258
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$fname =~ s/\)//g;  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my @found_players = grep {  | 
| 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$_->{name} =~ /^$fname.*$name$/i  | 
| 
262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		|| $NAME_VARIATIONS{$_->{name}}  | 
| 
263
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			&& $NAME_VARIATIONS{$_->{name}} eq $player->{name}  | 
| 
264
 | 
12
 | 
  
100
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
18
 | 
 		} @{$team->{roster}};  | 
| 
 
 | 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1400
 | 
    | 
| 
 
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37
 | 
    | 
| 
265
 | 
12
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
52
 | 
 	return undef unless @found_players;  | 
| 
266
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	@found_players = grep {  | 
| 
267
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 		! $_->{broken}  | 
| 
268
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	} @found_players if (@found_players > 1);  | 
| 
269
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
 	if (@found_players > 1) {  | 
| 
270
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		@found_players = $CURRENT eq 'GS'  | 
| 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			? ($found_players[0])  | 
| 
272
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			: grep { $_->{position} eq $player->{position} } @found_players;  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
274
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
5
 | 
 	return $found_players[0] if (@found_players == 1);  | 
| 
275
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	if (@found_players > 1) {  | 
| 
276
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		for my $o_i (@{$on_ice}) {  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			my $found = firstval {  | 
| 
278
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
 				$_->{number} == $o_i || $_->{_id} == $o_i  | 
| 
279
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			} @found_players;  | 
| 
280
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			return $found if $found;  | 
| 
281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
283
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	undef;  | 
| 
284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
285
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
286
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub find_player ($$;$) {  | 
| 
287
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
288
 | 
283
 | 
 
 | 
 
 | 
  
283
  
 | 
  
1
  
 | 
2835
 | 
 	my $player = shift;  | 
| 
289
 | 
283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
297
 | 
 	my $team   = shift;  | 
| 
290
 | 
283
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
566
 | 
 	my $on_ice = shift || [];  | 
| 
291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
292
 | 
283
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
433
 | 
 	if (! ref $player) {  | 
| 
293
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$player = $player =~ /^\d/ ?  | 
| 
294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			{ number => $player } : { name => $player };  | 
| 
295
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
296
 | 
283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
300
 | 
 	my $bs_player;  | 
| 
297
 | 
283
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
605
 | 
 	if ($player->{_id} && $player->{_id} =~ /^8\d{6}/) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
298
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$bs_player = find_player_by_id($player, $team)  | 
| 
299
 | 
3
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
17
 | 
 			if ($player->{_id} && $player->{_id} =~ /^8\d{6}/);  | 
| 
300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
301
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	elsif ($player->{number}) {  | 
| 
302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$bs_player = ${  | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$PLAYER_RESOLVE_CACHE->{$team->{name}}{$player->{number}}  | 
| 
304
 | 
278
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
613
 | 
 		} if $PLAYER_RESOLVE_CACHE->{$team->{name}}{$player->{number}};  | 
| 
 
 | 
267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
421
 | 
    | 
| 
305
 | 
278
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
442
 | 
 		return undef unless $bs_player || $player->{name};  | 
| 
306
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
307
 | 
282
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
418
 | 
 	$bs_player ||= find_player_by_name($player, $team, $on_ice);  | 
| 
308
 | 
282
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
397
 | 
 	return undef unless $bs_player;  | 
| 
309
 | 
271
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
893
 | 
 	$player->{number} = $bs_player->{number} if defined $bs_player->{number} && ! $bs_player->{broken};  | 
| 
310
 | 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
443
 | 
 	$player->{_id}    = $bs_player->{_id};  | 
| 
311
 | 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
415
 | 
 	$player;  | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
313
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
314
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub refine_candidates ($@) {  | 
| 
315
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
316
 | 
14
 | 
 
 | 
 
 | 
  
14
  
 | 
  
1
  
 | 
27
 | 
 	my $event      = shift;  | 
| 
317
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
 	my @candidates = @_;  | 
| 
318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	grep {  | 
| 
320
 | 
14
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
28
 | 
 		if ($event->{type}    eq 'PENL') {  | 
| 
 
 | 
28
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
87
 | 
    | 
| 
321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			($event->{length} == $_->{length} || $event->{length} == 10 && $_->{length} == 2)  | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			&& $event->{penalty} eq $_->{penalty}  | 
| 
323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			&& (($event->{player1} || 0) == ($_->{player1} || 0)  | 
| 
324
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				|| $event->{player1} == ($_->{servedby} || 0)  | 
| 
325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				|| ($event->{servedby} || 0) == $_->{player1})  | 
| 
326
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 		}  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		elsif ($event->{type} eq 'STOP') {  | 
| 
328
 | 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
38
 | 
 			my $s = 0;  | 
| 
329
 | 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
 			for my $stopreason (@{$_->{stopreason}}) {  | 
| 
 
 | 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
61
 | 
    | 
| 
330
 | 
28
 | 
  
100
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
287
 | 
 				if (  | 
| 
 
 | 
 
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					$event->{stopreason} =~ /$stopreason/i  | 
| 
332
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 						|| $event->{stopreason} =~ /CHLG/i && $stopreason =~ /challenge/i  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				) {  | 
| 
334
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 					$s = 1;  | 
| 
335
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
 					last;  | 
| 
336
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				}  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
338
 | 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
59
 | 
 			$s;  | 
| 
339
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
340
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		else {  | 
| 
341
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			($event->{player1} || 0) == ($_->{player1} || 0)  | 
| 
342
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			|| ($event->{player2} || 0) == ($_->{player1} || 0)  | 
| 
343
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 				&& ($event->{player1} || 0) == ($_->{player2} || 0)  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	} @candidates;  | 
| 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
348
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub find_event ($$$) {  | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
350
 | 
955
 | 
 
 | 
 
 | 
  
955
  
 | 
  
1
  
 | 
4144
 | 
 	my $event     = shift;  | 
| 
351
 | 
955
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1122
 | 
 	my $bs_events = shift;  | 
| 
352
 | 
955
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1148
 | 
 	my $type      = shift;  | 
| 
353
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
354
 | 
955
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1614
 | 
 	return -1 if $event->{special};  | 
| 
355
 | 
954
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
2206
 | 
 	return -1 if ! $event->{player1} && $type ne 'PL';  | 
| 
356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my @candidates = grep {  | 
| 
357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$_->{t} == $event->{t}  | 
| 
358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		&& $_->{period} == $event->{period}  | 
| 
359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		&& $_->{type}   eq $event->{type}  | 
| 
360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		&&  ($BROKEN_TIMES{$_->{game_id}}  | 
| 
361
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			&& ($event->{player1} || 0) == ($_->{player1} || 0)  | 
| 
362
 | 
304007
 | 
  
100
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
714891
 | 
 			||  ($event->{ts}           ==  $_->{ts}))  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
363
 | 
953
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1165
 | 
 	} @{$bs_events};  | 
| 
 
 | 
953
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1806
 | 
    | 
| 
364
 | 
953
 | 
  
  0
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
1980
 | 
 	if (! @candidates && ($event->{type} eq 'MISS' || $event->{type} eq 'SHOT') && $event->{so}) {  | 
| 
 
 | 
 
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		@candidates = grep {  | 
| 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$_->{t} == $event->{t}  | 
| 
367
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			&& $_->{player1} == $event->{player1}  | 
| 
368
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		} @{$bs_events};  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
369
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
370
 | 
953
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2387
 | 
 	return $candidates[0] if @candidates == 1;  | 
| 
371
 | 
16
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
45
 | 
 	return -1 unless @candidates;  | 
| 
372
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37
 | 
 	@candidates = refine_candidates($event, @candidates);  | 
| 
373
 | 
14
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
37
 | 
 	return $candidates[0] if @candidates;  | 
| 
374
 | 
13
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
38
 | 
 	return -1 unless @candidates;  | 
| 
375
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
376
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
377
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub resolve_report_on_ice ($$) {  | 
| 
378
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
379
 | 
1586
 | 
 
 | 
 
 | 
  
1586
  
 | 
  
1
  
 | 
3782
 | 
 	my $event = shift;  | 
| 
380
 | 
1586
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2145
 | 
 	my $bs    = shift;  | 
| 
381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
382
 | 
1586
 | 
  
 50
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
4274
 | 
 	return if $event->{sources}{GS} && $event->{period} == 5 && $event->{stage} == $REGULAR;  | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
383
 | 
1586
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2161
 | 
 	for my $t (0,1) {  | 
| 
384
 | 
3172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3559
 | 
 		for my $on_ice (@{$event->{on_ice}[$t]}) {  | 
| 
 
 | 
3172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6258
 | 
    | 
| 
385
 | 
18300
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
39454
 | 
 			next unless $on_ice =~ /^\d{1,2}$/;  | 
| 
386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			my $new_on_ice =  | 
| 
387
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				$PLAYER_RESOLVE_CACHE->{$bs->{teams}[$t]{name}}{$on_ice} ||  | 
| 
388
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				check_player_names(  | 
| 
389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					$event->{description},  | 
| 
390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					$PLAYER_RESOLVE_CACHE->{$bs->{teams}[$t]{name}},  | 
| 
391
 | 
18300
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
35285
 | 
 					$on_ice,  | 
| 
392
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				);  | 
| 
393
 | 
18300
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
26389
 | 
 			if (! ref $new_on_ice) {  | 
| 
394
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				if ($CURRENT eq 'GS') {  | 
| 
395
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 					$on_ice += 8400000;  | 
| 
396
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 					next;  | 
| 
397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				}  | 
| 
398
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
399
 | 
18300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19388
 | 
 			$on_ice = ${$new_on_ice}->{_id};  | 
| 
 
 | 
18300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32402
 | 
    | 
| 
400
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
401
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
403
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
404
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub resolve_report_roster ($$$) {  | 
| 
405
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
406
 | 
26
 | 
 
 | 
 
 | 
  
26
  
 | 
  
1
  
 | 
62
 | 
 	my $roster = shift;  | 
| 
407
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
 	my $bs     = shift;  | 
| 
408
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
35
 | 
 	my $t      = shift;  | 
| 
409
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
410
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37
 | 
 	for my $player (@{$roster}) {  | 
| 
 
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
59
 | 
    | 
| 
411
 | 
288
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
438
 | 
 		next if $player->{error};  | 
| 
412
 | 
288
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
1061
 | 
 		if (($player->{timeOnIce} || defined $player->{start} && $player->{start} != 2) && !($player->{_id} && $player->{_id} eq $EMPTY_NET_ID)) {  | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
413
 | 
276
 | 
 
 | 
 
 | 
 
 | 
 
 | 
425
 | 
 			my $bs_player = find_player($player, $bs->{teams}[$t]);  | 
| 
414
 | 
276
 | 
  
 50
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
472
 | 
 			if (! $bs_player && $CURRENT eq 'GS') {  | 
| 
415
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				$player->{error} = 1;  | 
| 
416
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				next;  | 
| 
417
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			die ("Can't resolve player ($CURRENT): " . Dumper $player)  | 
| 
419
 | 
276
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
482
 | 
 				unless $bs_player || ($player->{position} eq 'G' && $player->{start} != 1 || ! $player->{timeOnIce});  | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
422
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
423
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
424
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub resolve_report_event_teams ($$) {  | 
| 
425
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
426
 | 
1590
 | 
 
 | 
 
 | 
  
1590
  
 | 
  
1
  
 | 
2894
 | 
 	my $event  = shift;  | 
| 
427
 | 
1590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1892
 | 
 	my $report = shift;  | 
| 
428
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
429
 | 
1590
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
3588
 | 
 	if ($event->{team1}) {  | 
| 
430
 | 
1325
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
2352
 | 
 		if ($event->{team1} eq 'OTH') {  | 
| 
431
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$event->{team1} =  | 
| 
432
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				$report->{teams}[$event->{team2} eq $report->{teams}[0]{name} ? 1 : 0]{name};  | 
| 
433
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
434
 | 
1325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2699
 | 
 		$event->{team1} = resolve_team($event->{team1});  | 
| 
435
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
436
 | 
1590
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
4472
 | 
 	if ($event->{team2}) {  | 
| 
437
 | 
715
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1578
 | 
 		if ($event->{team2} eq 'OTH') {  | 
| 
438
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$event->{team2} =  | 
| 
439
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				$report->{teams}[$event->{team1} eq $report->{teams}[0]{name} ? 1 : 0]{name};  | 
| 
440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
441
 | 
715
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1420
 | 
 		$event->{team2} = resolve_team($event->{team2});  | 
| 
442
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
443
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
444
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
445
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub check_player_names ($$$) {  | 
| 
446
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
447
 | 
  
0
  
 | 
 
 | 
  
  0
  
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
 	my $description = shift || '';  | 
| 
448
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $cache       = shift;  | 
| 
449
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $number      = shift;  | 
| 
450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
451
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	for my $player_ref (@{$cache->{names}}) {  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
452
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my $player = ${$player_ref};  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
453
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		my ($last_name) = ($player->{name} =~ /\b(\S+)$/);  | 
| 
454
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$last_name = $REVERSE_NAME_TYPOS{$last_name} if $REVERSE_NAME_TYPOS{$last_name};  | 
| 
455
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		if ($description =~ /\b$last_name\b/i) {  | 
| 
456
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			debug "Matched $description with $last_name";  | 
| 
457
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$cache->{$number} = $player_ref;  | 
| 
458
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			return $player_ref;  | 
| 
459
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
460
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
461
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
462
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
463
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub resolve_report_event_fields ($$) {  | 
| 
464
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
465
 | 
1590
 | 
 
 | 
 
 | 
  
1590
  
 | 
  
1
  
 | 
2902
 | 
 	my $event = shift;  | 
| 
466
 | 
1590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1850
 | 
 	my $bs    = shift;  | 
| 
467
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
468
 | 
1590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2716
 | 
 	for my $field (qw(player1 player2 assist1 assist2 servedby)) {  | 
| 
469
 | 
7950
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
17359
 | 
 		next if ! $event->{$field} || $event->{$field} =~ /^8\d{6}/;  | 
| 
470
 | 
2110
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
3501
 | 
 		my $team  = $field eq 'player2' ? 'team2' : 'team1';  | 
| 
471
 | 
2110
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2929
 | 
 		my $team2 = $field eq 'player2' ? 'team1' : 'team2';  | 
| 
472
 | 
2110
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
6294
 | 
 		if ($event->{$field} && $event->{$field} =~ /\D/) {  | 
| 
473
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			my $player = find_player($event->{$field}, $bs->{teams}[$event->{t}], $event->{on_ice}[$event->{t}]);  | 
| 
474
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 			if ($player) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
475
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				$event->{$field} = $player->{_id};  | 
| 
476
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
477
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			elsif (!($CURRENT eq 'GS' && $event->{type} eq 'GOAL')) {  | 
| 
478
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				die "Can't resolve player for event: " . Dumper $player, $event, $field;  | 
| 
479
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
480
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 			if ($event->{player1} && $event->{servedby} && $event->{player1} == $event->{servedby}) {  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
481
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				delete $event->{servedby};  | 
| 
482
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
483
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
484
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		else {  | 
| 
485
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			my $matched_player =  | 
| 
486
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				$PLAYER_RESOLVE_CACHE->{$event->{$team}}{$event->{$field}}  | 
| 
487
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				|| check_player_names(  | 
| 
488
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					$event->{description},  | 
| 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					$PLAYER_RESOLVE_CACHE->{$event->{$team}},  | 
| 
490
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 					$event->{$field},  | 
| 
491
 | 
2110
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
5467
 | 
 				) || $PLAYER_RESOLVE_CACHE->{$event->{$team2}}{$event->{$field}};  | 
| 
492
 | 
2110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2430
 | 
 			$event->{$field} = ${$matched_player}->{_id};  | 
| 
 
 | 
2110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4537
 | 
    | 
| 
493
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
494
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
495
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
497
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub resolve_report ($$) {  | 
| 
498
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
499
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
  
1
  
 | 
11244
 | 
 	my $bs    = shift;  | 
| 
500
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
 	my $rp    = shift;  | 
| 
501
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
502
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
 	for my $t (0,1) {  | 
| 
503
 | 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
80
 | 
 		$rp->{teams}[$t]{name} = resolve_team($rp->{teams}[$t]{name});  | 
| 
504
 | 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
92
 | 
 		resolve_report_roster($rp->{teams}[$t]{roster}, $bs, $t);  | 
| 
505
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
506
 | 
12
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
85
 | 
 	if ($rp->{events}) {  | 
| 
507
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
54
 | 
 		$rp->set_event_extra_data();  | 
| 
508
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
 		for my $event (@{$rp->{events}}) {  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
    | 
| 
509
 | 
1274
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2473
 | 
 			resolve_report_event_teams($event, $rp);  | 
| 
510
 | 
1274
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2961
 | 
 			resolve_report_event_fields($event, $bs);  | 
| 
511
 | 
1274
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2917
 | 
 			resolve_report_on_ice($event, $bs) if ($event->{on_ice});  | 
| 
512
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
513
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
514
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
515
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
516
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub merge_me ($$;$$) {  | 
| 
517
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
518
 | 
1149
 | 
 
 | 
 
 | 
  
1149
  
 | 
  
1
  
 | 
1553
 | 
 	my $bs_event = shift;  | 
| 
519
 | 
1149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1359
 | 
 	my $rp_event = shift;  | 
| 
520
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	my $fields   = shift || [ grep {  | 
| 
521
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$_    ne 'name'  | 
| 
522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		&& $_ ne 'decision'  | 
| 
523
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		&& defined $rp_event->{$_}  | 
| 
524
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		&& (! defined $bs_event->{$_})  | 
| 
525
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		&& $rp_event->{$_} ne 'XX' && $rp_event->{$_} !~ /^Unk/i  | 
| 
526
 | 
1149
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
1922
 | 
 	} keys %{$rp_event}];  | 
| 
527
 | 
1149
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2744
 | 
 	push(@{$fields}, 'stopreason') if $rp_event->{stopreason};  | 
| 
 
 | 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
336
 | 
    | 
| 
528
 | 
1149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1358
 | 
 	for (@{$fields}) {  | 
| 
 
 | 
1149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1951
 | 
    | 
| 
529
 | 
5053
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7393
 | 
 		when ('stopreason') {  | 
| 
530
 | 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
174
 | 
 			$bs_event->{$_} = [ uniq (@{$bs_event->{stopreason}}, @{$rp_event->{stopreason}}) ];  | 
| 
 
 | 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
232
 | 
    | 
| 
 
 | 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
826
 | 
    | 
| 
531
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
532
 | 
4918
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5726
 | 
 		when ('position') {  | 
| 
533
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$bs_event->{$_} = $rp_event->{$_}  | 
| 
534
 | 
10
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
59
 | 
 				if (!$bs_event->{$_} || $bs_event->{$_} eq 'N/A');  | 
| 
535
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
536
 | 
4908
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5751
 | 
 		when ('on_ice') {  | 
| 
537
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$bs_event->{$_} = $rp_event->{$_}  | 
| 
538
 | 
933
 | 
  
 50
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
3177
 | 
 				if (! $bs_event->{on_ice} || !$bs_event->{on_ice}[0] || ! @{$bs_event->{on_ice}[0]})  | 
| 
539
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
540
 | 
3975
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4566
 | 
 		when ('strength') {  | 
| 
541
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$bs_event->{$_} = $rp_event->{$_}  | 
| 
542
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 				if ($bs_event->{$_} !~ /\S/ || $bs_event->{$_} eq 'XX');  | 
| 
543
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
544
 | 
3975
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4160
 | 
 		default {  | 
| 
545
 | 
3975
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8227
 | 
 			$bs_event->{$_} = $rp_event->{$_};  | 
| 
546
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
547
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
548
 | 
1149
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
4881
 | 
 	if (defined $bs_event->{position}) {  | 
| 
549
 | 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
228
 | 
 		for my $field (keys %{$rp_event}) {  | 
| 
 
 | 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
560
 | 
    | 
| 
550
 | 
3494
 | 
  
 50
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
5541
 | 
 			if (! defined $bs_event->{$field}  | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
551
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				&& defined $rp_event->{$field}  | 
| 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				&& ($rp_event->{$field} eq '' || $rp_event->{$field} eq 0)) {  | 
| 
553
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				$bs_event->{$field} = 0;  | 
| 
554
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
555
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
556
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
557
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
558
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
559
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
560
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub merge_roster ($$;$) {  | 
| 
561
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
562
 | 
14
 | 
 
 | 
 
 | 
  
14
  
 | 
  
1
  
 | 
21
 | 
 	my $bs_team = shift;  | 
| 
563
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
 	my $rp_team = shift;  | 
| 
564
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
565
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
 	for my $rp_player (@{$rp_team->{roster}}) {  | 
| 
 
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
    | 
| 
566
 | 
208
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
305
 | 
 		next if $rp_player->{error};  | 
| 
567
 | 
208
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
475
 | 
 		next unless $rp_player->{timeOnIce} || defined $rp_player->{start};  | 
| 
568
 | 
204
 | 
  
 50
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
518
 | 
 		next if $rp_player->{_id} && $rp_player->{_id} == $EMPTY_NET_ID;  | 
| 
569
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		merge_me(  | 
| 
570
 | 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
447
 | 
 			${$PLAYER_RESOLVE_CACHE->{$bs_team->{name}}{$rp_player->{number}}},  | 
| 
571
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$rp_player, 0  | 
| 
572
 | 
204
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
304
 | 
 		) if $rp_player->{number};  | 
| 
573
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
574
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
575
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
576
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub merge_teams ($$) {  | 
| 
577
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
578
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
  
1
  
 | 
2276
 | 
 	my $boxscore = shift;  | 
| 
579
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 	my $report   = shift;  | 
| 
580
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
581
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
 	for my $t (0,1) {  | 
| 
582
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
 		my $bs_team = $boxscore->{teams}[$t];  | 
| 
583
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
20
 | 
 		my $rp_team = $report->{teams}[$t];  | 
| 
584
 | 
14
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
36
 | 
 		unless ($bs_team->{name} eq $rp_team->{name}) {  | 
| 
585
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			die "$bs_team->{name} vs $rp_team->{name} how did I get here?";  | 
| 
586
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
587
 | 
14
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
44
 | 
 		$bs_team->{coach} ||= $rp_team->{coach};  | 
| 
588
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
 		merge_roster($bs_team, $rp_team, $report->{type} eq 'BH');  | 
| 
589
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
591
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
592
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub copy_events ($$) {  | 
| 
593
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
594
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
 	my $boxscore = shift;  | 
| 
595
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $report   = shift;  | 
| 
596
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
597
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$boxscore->{events} = dclone $report->{events};  | 
| 
598
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	for my $event (@{$boxscore->{events}}) {  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
599
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$event->{sources}{$report->{type}} = 1;  | 
| 
600
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		$event->{sources}{BS} = 0;  | 
| 
601
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 		if ($event->{assist1}) {  | 
| 
602
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			$event->{assists} = [  | 
| 
603
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				$event->{assist1} || (),  | 
| 
604
 | 
  
0
  
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 				$event->{assist2} || (),  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
605
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			]  | 
| 
606
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
607
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
608
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
609
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
610
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub expected_miss ($$$) {  | 
| 
611
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
612
 | 
12
 | 
 
 | 
 
 | 
  
12
  
 | 
  
1
  
 | 
23
 | 
 	my $type    = shift;  | 
| 
613
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
 	my $event   = shift;  | 
| 
614
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
 	my $boxscore = shift;  | 
| 
615
 | 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
 	my $game_id = $boxscore->{_id};  | 
| 
616
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
617
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	$boxscore->{no_events}  | 
| 
618
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	|| (  | 
| 
619
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		$type eq 'PL' && $event->{season} < 2010  | 
| 
620
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			&& $event->{type} ne 'PENL'	&& $event->{type} ne 'GOAL'  | 
| 
621
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	)  | 
| 
622
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	|| (  | 
| 
623
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		ref($FORCED_PUSH{$type}{$game_id})  | 
| 
624
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		&& $FORCED_PUSH{$type}{$game_id}->{$event->{id}}  | 
| 
625
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	)  | 
| 
626
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	|| $event->{type} eq 'PENL' && $event->{length} == 0  | 
| 
627
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	|| $event->{type} eq 'PEND'  | 
| 
628
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	|| $event->{type} eq 'GEND'  | 
| 
629
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	|| $event->{type} eq 'STOP' && $event->{description} =~ /CHL/i  | 
| 
630
 | 
12
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
289
 | 
 	|| $event->{type} eq 'MISS' && ($type eq 'GS')  | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
631
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
632
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
633
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub push_event ($$$) {  | 
| 
634
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
635
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
 	my $event    = shift;  | 
| 
636
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $boxscore = shift;  | 
| 
637
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	my $type     = shift;  | 
| 
638
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
639
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$event->{game_id} = $boxscore->{_id};  | 
| 
640
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	$event->{sources}{$type} = 1;  | 
| 
641
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
 	$event->{description} ||= 'Missed Penalty Shot' if $event->{type} eq 'MISS';  | 
| 
642
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 	push(@{$boxscore->{events}}, $event);  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
643
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
644
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
645
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
646
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub merge_events ($$) {  | 
| 
647
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
648
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
  
1
  
 | 
18
 | 
 	my $boxscore = shift;  | 
| 
649
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
 	my $report   = shift;  | 
| 
650
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
651
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 	my $type = $report->{type};  | 
| 
652
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
 	while (my $rp_event = shift @{$report->{events}}) {  | 
| 
 
 | 
963
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2262
 | 
    | 
| 
653
 | 
958
 | 
  
 50
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
1842
 | 
 		next if $type eq 'GS' && $boxscore->{sources}{PL} && $boxscore->{season} >= 2007;  | 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
654
 | 
948
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1908
 | 
 		my $e = find_event($rp_event, $boxscore->{events}, $type);  | 
| 
655
 | 
948
 | 
  
100
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
3004
 | 
 		if (! ref $e) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
656
 | 
12
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
35
 | 
 			if (expected_miss($type, $rp_event, $boxscore)) {  | 
| 
657
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				push_event($rp_event, $boxscore, $type);  | 
| 
658
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				next;  | 
| 
659
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
660
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
661
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		elsif ($type eq 'GS' && $rp_event->{type} eq 'MISS') {  | 
| 
662
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$rp_event->{type} = 'SHOT';  | 
| 
663
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			$e = find_event($rp_event, $boxscore->{events}, $type);  | 
| 
664
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 			if (! ref $e) {  | 
| 
665
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				push_event($rp_event, $boxscore, $type);  | 
| 
666
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
 				next;  | 
| 
667
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 			}  | 
| 
668
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
669
 | 
948
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1608
 | 
 		die "UNDEF e  " . Dumper($rp_event) unless defined $e;  | 
| 
670
 | 
948
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1661
 | 
 		next if $e == -1;  | 
| 
671
 | 
936
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1871
 | 
 		$e->{sources}{$type} = 1;  | 
| 
672
 | 
936
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1660
 | 
 		merge_me($e, $rp_event);  | 
| 
673
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
674
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
675
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
676
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub merge_report ($$) {  | 
| 
677
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
678
 | 
8
 | 
 
 | 
 
 | 
  
8
  
 | 
  
1
  
 | 
4827
 | 
 	my $boxscore = shift;  | 
| 
679
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
 	my $report   = shift;  | 
| 
680
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
681
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
 	my $type = $report->{type};  | 
| 
682
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
683
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
 	$CURRENT = $type;  | 
| 
684
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
 	$BOXSCORE = $boxscore;  | 
| 
685
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
 	$PLAYER_RESOLVE_CACHE = $boxscore->{resolve_cache};  | 
| 
686
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
 	debug "Merging $type";  | 
| 
687
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
 	resolve_report($boxscore, $report);  | 
| 
688
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
689
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
 	for ($type) {  | 
| 
690
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
46
 | 
 		when ([qw(RO ES GS PL)]) {  | 
| 
691
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
33
 | 
 			merge_me($boxscore, $report, \@MERGE_HEADER);  | 
| 
692
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 			continue;  | 
| 
693
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
694
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
 		when ([qw(RO ES GS)]) {  | 
| 
695
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
 			merge_teams($boxscore, $report);  | 
| 
696
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
 			continue;  | 
| 
697
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
698
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
28
 | 
 		when ([qw(GS PL)])    {  | 
| 
699
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
7
 | 
 			@{$boxscore->{events}} ?  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
    | 
| 
700
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 				merge_events($boxscore, $report) : 	copy_events($boxscore, $report);  | 
| 
701
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
 			continue;  | 
| 
702
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		}  | 
| 
703
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	}  | 
| 
704
 | 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
372
 | 
 	$boxscore->{sources}{$type} = 1;  | 
| 
705
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
706
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
707
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
708
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
709
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 AUTHOR  | 
| 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
711
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 More Hockey Stats, C<<  >>  | 
| 
712
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
713
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 BUGS  | 
| 
714
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
715
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Please report any bugs or feature requests to C, or through  | 
| 
716
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the web interface at L.  I will be notified, and then you'll  | 
| 
717
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 automatically be notified of progress on your bug as I make changes.  | 
| 
718
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
719
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
720
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 SUPPORT  | 
| 
721
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
722
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 You can find documentation for this module with the perldoc command.  | 
| 
723
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
724
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     perldoc Sport::Analytics::NHL::Merger  | 
| 
725
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
726
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 You can also look for information at:  | 
| 
727
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
728
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =over 4  | 
| 
729
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
730
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * RT: CPAN's request tracker (report bugs here)  | 
| 
731
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
732
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 L  | 
| 
733
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
734
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * AnnoCPAN: Annotated CPAN documentation  | 
| 
735
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
736
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 L  | 
| 
737
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
738
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * CPAN Ratings  | 
| 
739
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
740
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 L  | 
| 
741
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
742
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * Search CPAN  | 
| 
743
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
744
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 L  | 
| 
745
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
746
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =back  |