File Coverage

blib/lib/Baseball/Sabermetrics.pm
Criterion Covered Total %
statement 59 71 83.1
branch 5 18 27.7
condition 1 3 33.3
subroutine 11 12 91.6
pod 3 6 50.0
total 79 110 71.8


line stmt bran cond sub pod time code
1             package Baseball::Sabermetrics;
2              
3 2     2   26906 use Baseball::Sabermetrics::Team;
  2         4  
  2         41  
4 2     2   599 use Baseball::Sabermetrics::Player;
  2         7  
  2         37  
5 2     2   6 use strict;
  2         2  
  2         25  
6 2     2   5 use warnings;
  2         48  
  2         48  
7 2     2   5 use base qw/ Baseball::Sabermetrics::Team /;
  2         2  
  2         626  
8              
9             =head1 NAME
10              
11             Baseball::Sabermetrics - A Baseball Statistics Module
12              
13             =cut
14              
15             our $VERSION = '0.01_01';
16              
17             =head1 SYNOPSIS
18              
19             Baseball::Sabermetrics provides an easy interface for calculating baseball statistics, given a data importer. In this package, I've writen CPBL.pm for (I, L).
20              
21             use Baseball::Sabermetrics;
22             use Baseball::Sabermetrics::CPBL;
23              
24             my $league = Baseball::Sabermetrics->new(league => 'CPBL');
25              
26             # Actually these are predefined.
27             # Those data with 'p_' or '_allowed' here are for seperating pitchers
28             # and batters.
29              
30             $league->define(
31             rc => 'ab * obp',
32             babip => '(h_allowed - hr_allowed) / (p_pa - h_allowed - p_so - p_bb - hr_allowed',
33             # what started with '$' will be reserved.
34             # Players have team and league predefined, and team has league.
35             formula1 => 'hr / $_->team->hr';
36             formula2 => 'hr / $_->league->hr';
37             complex => sub {
38             print "You can write a sub directly\n";
39             $_->slg - $_->ba;
40             },
41             ...
42             );
43              
44             # Some formulas can be applied to players, teams, and league, depend on what
45             # columns are used in the formula. For example, ab and obp are defined for
46             # players, teams, and league, so that rc is available for all of them.
47              
48             # top 5 obp of teams
49             $_->print qw/ team name ba obp slg isop / for $league->top('teams', 5, 'obp');
50              
51             # top 10 obp of players
52             $_->print qw/ team name ba obp slg isop / for $league->top('players', 10, 'obp');
53              
54             # show a player's information
55             $league->players('Chien-Ming Wang')->print qw/ win lose ip so bb whip go_ao /;
56             $league->teams('Yankees')->players('Chien-Ming Wang')->print qw/ win lose ip so bb whip go_ao /;
57              
58             # show team statistics data (accumulated from players')
59             $league->{Yankees}->print qw/ win lose ip so bb whip go_ao /;
60              
61             # show all available formula
62             print join ' ', $league->formula_list;
63              
64             =head1 Data Structure
65              
66             Baseball::Sabermetrics is aimed for providing a base class of your interested teams (a league, for example). You'll need to provide a data retriever to pull data out. The following example shows how you have to fill data into this structure.
67              
68             $league = {
69             teams => {
70             Yankees => {
71             players => {
72             "Chien-Ming Wang" => {
73             ip => 57.33333333333,
74             game => 9,
75             ...
76             };
77             ...
78             }
79             },
80             Athletics => {
81             ...
82             },
83             },
84             };
85              
86             =head1 FUNCTIONS
87              
88             =over 4
89              
90             =item new([I<%hash>])
91              
92             Create sabermetric data set of a group of teams.
93              
94             If $hash{Accumulate} is false, players data will not be accumulated to their teams and the league (and therefore team-wise and league-wise statistics are not allowed). Default is to accumulate stats.
95              
96             =cut
97              
98             sub new
99             {
100 1     1 1 27 my ($class, %config) = @_;
101 1         1 my $self;
102            
103 1 50       3 if (exists $config{data}) {
    0          
104 1         2 $self = $config{data};
105             }
106             elsif (exists $config{league}) {
107 0         0 eval "require Baseball::Sabermetrics::League::$config{league}; \$self = Baseball::Sabermetrics::League::$config{league}->new(\%config);";
108 0 0       0 die unless $self;
109             }
110             else {
111 0         0 die "You have to provide statistic data";
112             }
113              
114 1         1 bless $self, $class;
115              
116 1 50 33     4 if (exists $config{Accumulate} && !$config{Accumulate}) {
117 0         0 $self->{_DontAccumulate} = 1;
118             }
119              
120 1         1 for my $team (values %{$self->{teams}}) {
  1         7  
121 2         6 $team = Baseball::Sabermetrics::Team->new($team);
122 2         4 $team->{league} = $self;
123 2         2 for my $p (values %{$team->{players}}) {
  2         3  
124 2         7 $p = Baseball::Sabermetrics::Player->new($p);
125 2         12 $p->{team} = $team;
126 2         4 $p->{league} = $self;
127             }
128             }
129              
130 1         3 setup_common_info($self);
131              
132 1         2 return $self;
133             }
134              
135             sub player_accumulate_term
136             {
137             # picher and batter's game is the same here, could be a problem later?
138 2     2 0 14 return qw/ gs sv bs hld cg sho ip p_pa np h_allowed hr_allowed
139             sh_allowed sf_allowed p_bb p_ibb hb p_so wp bk r_allowed er
140             pa ab rbi r h 1b 2b 3b hr tb dp sh sf 4ball ibb bb so sb cs
141             finn tc po a e f_dp ppo tp pb c_cs c_sb /;
142             }
143              
144             sub team_accumulate_term
145             {
146 2     2 0 3 return qw/ game win lose tie /;
147             }
148              
149             sub setup_common_info
150             {
151 1     1 0 1 my $league = shift;
152 1         1 for my $tname (keys %{$league->{teams}}) {
  1         2  
153 2         2 my $team = $league->{teams}->{$tname};
154 2         2 $team->{name} = $tname;
155 2 50       5 unless (exists $league->{_DontAccumulate}) {
156 2     2   8 no warnings;
  2         6  
  2         483  
157 2         0 for my $name (keys %{$team->{players}}) {
  2         3  
158 2         2 my $p = $team->{players}->{$name};
159 2         2 $p->{name} = $name;
160 2         3 for (player_accumulate_term()) {
161 102         84 $league->{$_} += $p->{$_};
162 102         93 $p->{team}->{$_} += $p->{$_};
163             }
164             }
165 2         3 for (team_accumulate_term()) {
166 8         9 $league->{$_} += $team->{$_};
167             }
168             }
169 2         1 $league->{players}->{$_} = $team->{players}->{$_} for (keys %{$team->{players}});
  2         5  
170             }
171 1         2 delete $league->{_DontAccumulate};
172             }
173              
174             =item players([$name])
175              
176             for ($league->players) { ... }
177              
178             print $league->players('Someone')->obp;
179              
180             =cut
181              
182             sub players
183             {
184 2     2 1 7 my ($self, $name) = @_;
185 2 50       3 if ($name) {
186 2 50       5 die "Player not found: $name\n" unless exists $self->{players}->{$name};
187 2         3 return $self->{players}->{$name};
188             }
189 0           return values %{$self->{players}};
  0            
190             }
191              
192             =item teams([$name])
193              
194             for ($league->teams) { ... }
195              
196             print $league->teams('Someone')->win;
197              
198             =cut
199              
200             sub teams
201             {
202 0     0 1   my ($self, $name) = @_;
203 0 0         if ($name) {
204 0 0         die "Team not found: $name\n" unless exists $self->{teams}->{$name};
205 0           return $self->{teams}->{$name};
206             }
207 0           return values %{$self->{teams}};
  0            
208             }
209              
210             =item pitchers
211              
212             Return all pitchers, i.e., NP (Number of Pitches) > 0.
213              
214             =item batters
215              
216             Return all batters, i.e., PA (Plate Appearances) > 0.
217              
218             =back
219              
220             =cut
221              
222              
223             =head1 AUTHOR
224              
225             Victor Hsieh, C<< >>
226              
227             =head1 BUGS
228              
229             Please report any bugs or feature requests to
230             C, or through the web interface at
231             L.
232             I will be notified, and then you'll automatically be notified of progress on
233             your bug as I make changes.
234              
235             =head1 SUPPORT
236              
237             You can find documentation for this module with the perldoc command.
238              
239             perldoc Baseball::Sabermetrics
240              
241             You can also look for information at:
242              
243             =over 4
244              
245             =item * AnnoCPAN: Annotated CPAN documentation
246              
247             L
248              
249             =item * CPAN Ratings
250              
251             L
252              
253             =item * RT: CPAN's request tracker
254              
255             L
256              
257             =item * Search CPAN
258              
259             L
260              
261             =back
262              
263             =head1 COPYRIGHT & LICENSE
264              
265             Copyright 2006 Victor Hsieh, all rights reserved.
266              
267             This program is free software; you can redistribute it and/or modify it
268             under the same terms as Perl itself.
269              
270             =cut
271              
272             1; # End of Baseball::Sabermetrics