File Coverage

blib/lib/Games/Bowling/Scorecard/Frame.pm
Criterion Covered Total %
statement 50 50 100.0
branch 24 24 100.0
condition 11 12 91.6
subroutine 12 12 100.0
pod 7 7 100.0
total 104 105 99.0


line stmt bran cond sub pod time code
1 4     4   1832 use strict;
  4         8  
  4         150  
2 4     4   25 use warnings;
  4         8  
  4         270  
3              
4             package Games::Bowling::Scorecard::Frame;
5             {
6             $Games::Bowling::Scorecard::Frame::VERSION = '0.105';
7             }
8             # ABSTRACT: one frame on a scorecard
9              
10              
11 4     4   31 use Carp ();
  4         12  
  4         2450  
12              
13              
14             sub new {
15 81     81 1 3615 my ($class) = @_;
16              
17 81         502 bless {
18             balls => [],
19             score => 0,
20              
21             done => 0,
22             pending => 0,
23             } => $class;
24             }
25              
26              
27             sub record { ## no critic Ambiguous
28 194     194 1 2038 my ($self, $ball) = @_;
29              
30 194 100       378 if ($self->is_done) {
31 42 100       82 if ($self->is_pending) {
32 41         52 $self->{pending}--;
33 41         58 $self->{score} += $ball;
34 41         141 return;
35             } else {
36 1         88 Carp::croak "two balls already recorded for frame";
37             }
38             }
39              
40 152         316 $self->roll_ok($ball);
41              
42 152         176 push @{ $self->{balls} }, $ball;
  152         322  
43 152         229 $self->{score} += $ball;
44              
45 152         311 $self->_check_done;
46 152         311 $self->_check_pending;
47             }
48              
49             sub _check_pending {
50 152     152   179 my ($self) = @_;
51 152 100       275 return unless $self->is_done;
52              
53 79         151 my @balls = $self->balls;
54              
55 79 100 66     344 return $self->{pending} = 2 if @balls == 1 and $balls[0] == 10;
56 64 100 100     633 return $self->{pending} = 1 if @balls == 2 and $balls[0] + $balls[1] == 10;
57             }
58              
59             sub _check_done {
60 152     152   216 my ($self) = @_;
61              
62 152         255 my @balls = $self->balls;
63              
64 152 100 100     1037 $self->{done} = 1 if (@balls == 1 and $balls[0] == 10) or @balls == 2;
      100        
65             }
66              
67              
68             sub roll_ok {
69 164     164 1 4385 my ($self, $ball) = @_;
70              
71 164 100       311 Carp::croak "the frame is done" if $self->is_done;
72 163 100       441 Carp::croak "you can't bowl an undefined number of pins!" if !defined $ball;
73 162 100       508 Carp::croak "you can't bowl more than 10 on a single ball" if $ball > 10;
74 160 100       446 Carp::croak "you can't bowl less than 0 on a single ball" if $ball < 0;
75 159 100       386 Carp::croak "you can't knock down a partial pin" if $ball != int($ball);
76              
77 158         173 my $i = 0;
78 158         292 $i += $_ for $self->balls, $ball;
79              
80 158 100       3244 Carp::croak "bowling a $ball would bring the frame above 10" if $i > 10;
81             }
82              
83              
84             sub score {
85 297     297 1 4577 my ($self) = @_;
86 297         1561 return $self->{score};
87             }
88              
89              
90             sub is_pending {
91 925     925 1 1013 my ($self) = @_;
92 925         2999 return $self->{pending};
93             }
94              
95              
96             sub is_done {
97 760     760 1 1366 my ($self) = @_;
98 760         2899 return $self->{done};
99             }
100              
101              
102             sub balls {
103 574     574 1 711 my ($self) = @_;
104 574         569 return @{ $self->{balls} };
  574         2150  
105             }
106              
107             300;
108              
109             __END__