File Coverage

blib/lib/Baseball/Sabermetrics/abstract.pm
Criterion Covered Total %
statement 55 78 70.5
branch 22 38 57.8
condition n/a
subroutine 7 10 70.0
pod 0 7 0.0
total 84 133 63.1


line stmt bran cond sub pod time code
1             package Baseball::Sabermetrics::abstract;
2 2     2   10 use strict;
  2         4  
  2         1225  
3              
4             our $AUTOLOAD;
5             our %formula;
6              
7             #my $DEBUG = 0;
8              
9             BEGIN {
10             # formulas are weird, can we improve it ?
11             %formula = (
12 0         0 pa => sub { $_->ab + $_->bb + $_->hbp + $_->sf },
13 0         0 ta => sub { $_->h + $_->{'2b'} + $_->{'3b'} * 2 + $_->hr * 3 },
14 6         34 ba => sub { $_->h / $_->ab },
15 6         25 obp => sub { ($_->h + $_->bb + $_->hbp) / $_->pa },
16 6         26 slg => sub { $_->tb / $_->ab },
17 1         5 ops => sub { $_->obp + $_->slg },
18 1         12 k_9 => sub { $_->p_so / $_->ip * 9 },
19 1         6 bb_9 => sub { $_->p_bb / $_->ip * 9 },
20 1         10 k_bb => sub { $_->p_so / $_->p_bb },
21 5         19 isop => sub { $_->slg - $_->ba },
22 0         0 isod => sub { $_->obp - $_->ba },
23 0         0 rc => sub { $_->ab * $_->obp },
24              
25 1         10 era => sub { $_->er / $_->ip * 9 },
26 1         13 whip => sub { ($_->p_bb + $_->h_allowed) / $_->ip },
27 0         0 babip => sub { ($_->h_allowed - $_->hr_allowed) / ($_->p_pa - $_->h_allowed - $_->p_so - $_->p_bb - $_->hr_allowed) },
28 0         0 g_f => sub { $_->go / $_->ao },
29              
30             # rf => sub { ($_->a + $_->po) / $_->f_inn * 9 },
31 0         0 fpct => sub { ($_->po + $_->a) / ($_->po + $_->a + $_->e) },
32 2     2   2470 );
33             }
34              
35             sub new
36             {
37 54     54 0 66 my ($class, $hash) = @_;
38 54         211 return bless \%$hash, $class;
39             }
40              
41             sub AUTOLOAD : lvalue
42             {
43 177     177   8760 my $self = shift;
44 177 50       367 my $type = ref($self) or die;
45 177         205 my $name = $AUTOLOAD;
46 177         660 $name =~ s/.*:://;
47 177         178 my $ref;
48 177         309 my $cachename = '!'.$name . join '!', @_;
49              
50 177 50       614 if ($name eq 'DESTROY') {
    100          
    100          
    50          
51             # is there a better way?
52 0         0 $ref = \$name;
53             }
54             elsif (exists $self->{$name}) {
55 71         109 $ref = \$self->{$name};
56             }
57             elsif (exists $self->{$cachename}) {
58 76         124 $ref = \$self->{$cachename};
59             }
60             elsif (exists $formula{$name}) {
61             # no strict;
62             # use vars qw/ $team $league /;
63              
64              
65 30         51 my $caller = caller;
66 30         34 local $_ = $self;
67             # local *league = exists $self->{league} ? \$self->{league} : undef;
68             # local *team = exists $self->{team} ? \$self->{team} : undef;
69             # $DEBUG && print STDERR "[",__PACKAGE__,"] calculating $self->{name}'s $name, league: $league, team: $team\n";
70              
71 30 100       73 unless (ref $formula{$name}) {
72 1         10 $formula{$name} =~ s[(\$?)(?)("?)(\b\w(?:\w|->)*)][
73 3         11 my ($d, $q, $n) = ($1, $2, $3);
74 3 50       16 if ($q) {
    50          
    50          
75 0         0 "\"$n";
76             }
77             elsif ($n =~ /^\d+$/) {
78 0         0 $n;
79             }
80             # This is for 2b, 3b. We assume that no formula has name with a digital initial.
81             elsif ($n =~ /^\d/) {
82 0         0 "\$_->{'$n'}";
83             }
84             else {
85 3 50       17 $d ? "\$$n" : "\$_->$n"
86             }
87             ]eg;
88 1         5 $formula{$name} =~ s/\$team/\$_->team/g;
89 1         4 $formula{$name} =~ s/\$league/\$_->league/g;
90             # print "## $name ##\n$formula{$name}\n";
91 1 50       87 $formula{$name} = eval "sub { $formula{$name} }" or die $@;
92             }
93              
94 30         35 eval { $self->{$cachename} = $formula{$name}->(@_); };
  30         84  
95 30 50       70 die "$@ when eval [ $name ] of $_->{name}\n" if $@;
96              
97 30         53 $ref = \$self->{$cachename};
98             }
99             else {
100 0         0 $ref = \$self->{$name};
101             }
102              
103 177         838 $$ref;
104             }
105              
106             sub print
107             {
108 5     5 0 9 my $self = shift;
109 5 50       22 if (grep /^all$/, @_) {
110 0         0 @_ = keys %$self;
111             }
112 5         9 for (@_) {
113 25 50       55 if ($_ eq 'team') {
114 0         0 print $self->team->name, "\t";
115             }
116             else {
117 25         129 my $val = $self->$_;
118 25 100       257 if ($val =~ s/(\d+\.\d\d\d)(\d)\d*/$1/) {
119 13 100       49 $val += 0.001 if $2 >= 5;
120             }
121              
122 25         1093 print "$val\t";
123             }
124             }
125 5         595 print "\n";
126             }
127              
128             sub define
129             {
130 1     1 0 604 my ($self, %funcs) = @_;
131 1         22 %formula = (%formula, %funcs);
132             }
133              
134             sub formula
135             {
136 0 0   0 0 0 die "undefined formula" unless exists $formula{$_[1]};
137 0         0 return $formula{$_[1]};
138             }
139              
140             sub formula_list
141             {
142 0     0 0 0 return keys %formula;
143             }
144              
145             sub top
146             {
147 4     4 0 24 my ($self, $what, $num, $func) = @_;
148 4 50       14 if (! ref $func) {
149 4         18 return (sort { $b->$func <=> $a->$func } $self->$what)[0..$num-1];
  32         114  
150             }
151 0           return (sort $func $self->what)[0..$num-1];
152             }
153              
154             sub bottom
155             {
156 0     0 0   my ($self, $what, $num, $func) = @_;
157 0 0         if (! ref $func) {
158 0           return (sort { $a->$func <=> $b->$func } $self->$what)[0..$num-1];
  0            
159             }
160 0           return (sort $func $self->what)[0..$num-1];
161             }
162              
163             #sub declare
164             #{
165             # my $self = shift;
166             # $self->{$_} for (@_);
167             #}
168              
169             1;