File Coverage

blib/lib/Acme/Chef/Container.pm
Criterion Covered Total %
statement 70 114 61.4
branch 7 18 38.8
condition 2 3 66.6
subroutine 14 21 66.6
pod 15 15 100.0
total 108 171 63.1


line stmt bran cond sub pod time code
1              
2             package Acme::Chef::Container;
3              
4 7     7   37 use strict;
  7         13  
  7         223  
5 7     7   33 use warnings;
  7         11  
  7         155  
6              
7 7     7   31 use Carp;
  7         11  
  7         389  
8              
9 7     7   32 use Acme::Chef::Ingredient;
  7         13  
  7         191  
10              
11 7     7   35 use vars qw/$VERSION/;
  7         12  
  7         10500  
12             $VERSION = '1.00';
13              
14             =head1 NAME
15              
16             Acme::Chef::Container - Internal module used by Acme::Chef
17              
18             =head1 SYNOPSIS
19              
20             use Acme::Chef;
21              
22             =head1 DESCRIPTION
23              
24             Please see L;
25              
26             =head2 METHODS
27              
28             This is a list of methods in this package.
29              
30             =over 2
31              
32             =cut
33              
34             =item new
35              
36             This is the Acme::Chef::Container constructor. Creates a new
37             Acme::Chef::Container object. All arguments are treated as key/value pairs for
38             object attributes.
39              
40             =cut
41              
42             sub new {
43 243     243 1 447 my $proto = shift;
44 243   66     528 my $class = ref $proto || $proto;
45              
46 243         299 my $self = {};
47              
48 243 100       458 if (ref $proto) {
49 217         529 %$self = %$proto;
50 217         245 $self->{contents} = [ map { $_->new() } @{$self -> {contents}} ];
  303         629  
  217         451  
51             }
52              
53 243         1052 %$self = (
54             contents => [],
55             %$self,
56             @_,
57             );
58              
59 243         1462 return bless $self => $class;
60             }
61              
62              
63             =item put
64              
65             This method implements the 'put' command. Please refer to L for
66             details.
67              
68             =cut
69              
70             sub put {
71 841     841 1 914 my $self = shift;
72              
73 841         1244 my @ingredients = @_;
74              
75 841         1277 push @{$self->{contents}}, $_->new() for @ingredients;
  841         2163  
76              
77 841         2631 return $self;
78             }
79              
80             =item fold
81              
82             This method implements the 'fold' command. Please refer to L for
83             details.
84              
85             =cut
86              
87             sub fold {
88 111     111 1 113 my $self = shift;
89              
90 111         98 my $ingredient = shift;
91              
92 111         257 croak "Invalid operation on empty container: fold."
93 111 50       102 unless @{$self->{contents}};
94              
95 111         111 my $new_val = pop @{ $self->{contents} };
  111         160  
96              
97 111         271 $ingredient->value( $new_val->value() );
98              
99 111         356 return $ingredient;
100             }
101              
102             =item add
103              
104             This method implements the 'add' command. Please refer to L for
105             details.
106              
107             =cut
108              
109             sub add {
110 0     0 1 0 my $self = shift;
111              
112 0         0 my $ingredient = shift;
113              
114 0         0 croak "Invalid operation on empty container: add."
115 0 0       0 unless @{$self->{contents}};
116              
117 0         0 $self->{contents}->[-1]->value(
118             $self->{contents}->[-1]->value() +
119             $ingredient->value()
120             );
121              
122 0         0 return $ingredient;
123             }
124              
125             =item remove
126              
127             This method implements the 'remove' command. Please refer to L for
128             details.
129              
130             =cut
131              
132              
133             sub remove {
134 168     168 1 166 my $self = shift;
135              
136 168         168 my $ingredient = shift;
137              
138 168         356 croak "Invalid operation on empty container: remove."
139 168 50       163 unless @{$self->{contents}};
140              
141 168         427 $self->{contents}->[-1]->value(
142             $self->{contents}->[-1]->value() -
143             $ingredient->value()
144             );
145              
146 168         298 return $ingredient;
147             }
148              
149              
150             =item combine
151              
152             This method implements the 'combine' command. Please refer to L for
153             details.
154              
155             =cut
156              
157             sub combine {
158 240     240 1 254 my $self = shift;
159              
160 240         220 my $ingredient = shift;
161              
162 240         512 croak "Invalid operation on empty container: combine."
163 240 50       239 unless @{$self->{contents}};
164              
165 240         690 $self->{contents}->[-1]->value(
166             $self->{contents}->[-1]->value() *
167             $ingredient->value()
168             );
169              
170 240         477 return $ingredient;
171             }
172              
173              
174             =item divide
175              
176             This method implements the 'divide' command. Please refer to L for
177             details.
178              
179             =cut
180              
181             sub divide {
182 0     0 1 0 my $self = shift;
183              
184 0         0 my $ingredient = shift;
185              
186 0         0 croak "Invalid operation on empty container: divide."
187 0 0       0 unless @{$self->{contents}};
188              
189 0         0 $self->{contents}->[-1]->value(
190             $self->{contents}->[-1]->value() /
191             $ingredient->value()
192             );
193              
194 0         0 return $ingredient;
195             }
196              
197             =item put_sum
198              
199             This method takes a number of Acme::Chef::Ingredient objects as arguments and
200             creates and 'puts' the sum of the ingredients.
201              
202             Please refer to L for details.
203              
204             =cut
205              
206             sub put_sum {
207 0     0 1 0 my $self = shift;
208              
209 0         0 my @ingredients = @_;
210              
211 0         0 my $sum = 0;
212 0         0 $sum += $_->value() for @ingredients;
213              
214 0         0 my $ingredient = Acme::Chef::Ingredient->new(
215             name => '',
216             value => $sum,
217             measure => '',
218             type => 'dry',
219             );
220              
221 0         0 $self->put($ingredient);
222              
223 0         0 return $ingredient;
224             }
225              
226             =item liquify_contents
227              
228             This method implements the 'liquify' command for all ingredients.
229             Please refer to L for details.
230              
231             =cut
232              
233             sub liquify_contents {
234 6     6 1 10 my $self = shift;
235              
236 6         8 foreach my $ingredient (@{$self->{contents}}) {
  6         14  
237 126         236 $ingredient->liquify();
238             }
239              
240 6         14 return $self;
241             }
242              
243             =item stir_time
244              
245             This method implements the 'stir' command.
246             First argument should be the depth ("time") to stir.
247             Please refer to L for details.
248              
249             =cut
250              
251             sub stir_time {
252 0     0 1 0 my $self = shift;
253              
254 0         0 my $depth = shift;
255              
256 0 0       0 return $self unless scalar @{$self->{contents}};
  0         0  
257              
258 0 0       0 $depth = $#{$self->{contents}} if $depth > $#{$self->{contents}};
  0         0  
  0         0  
259              
260 0         0 my $top = pop @{ $self->{contents} };
  0         0  
261 0         0 splice @{$self->{contents}}, (@{$self->{contents}}-$depth), 0, $top;
  0         0  
  0         0  
262              
263 0         0 return $self;
264             }
265              
266              
267             =item stir_ingredient
268              
269             This method implements the 'stir_ingredient' command. Please refer to
270             L for details.
271              
272             =cut
273              
274              
275             sub stir_ingredient {
276 0     0 1 0 my $self = shift;
277              
278 0         0 my $ingredient = shift;
279              
280 0         0 $self->stir_time($ingredient->value());
281              
282 0         0 return $self;
283             }
284              
285             =item mix
286              
287             This method implements the 'mix' command. Please refer to L for
288             details.
289              
290             Shuffles the container's contents.
291              
292             =cut
293              
294             sub mix {
295 0     0 1 0 my $self = shift;
296              
297 0         0 _fisher_yates_shuffle( $self->{contents} );
298              
299 0         0 return $self;
300             }
301              
302             =item clean
303              
304             This method implements the 'clean' command. Please refer to L for
305             details.
306              
307             Empties the container.
308              
309             =cut
310              
311             sub clean {
312 72     72 1 76 my $self = shift;
313              
314 72         71 @{$self->{contents}} = ();
  72         234  
315              
316 72         118 return $self;
317             }
318              
319              
320             =item pour
321              
322             This method implements the 'pour' command. Please refer to L for
323             details.
324              
325             Returns the contained ingredients.
326              
327             =cut
328              
329             sub pour {
330 113     113 1 135 my $self = shift;
331              
332 113         108 return @{ $self->{contents} };
  113         362  
333             }
334              
335              
336             =item print
337              
338             Returns stringification of the object.
339              
340             =cut
341              
342             sub print {
343 26     26 1 41 my $self = shift;
344              
345 26         39 my $string = '';
346              
347 26         33 foreach my $ingr ( reverse @{$self->{contents}} ) {
  26         62  
348 197 100       407 if ($ingr->type() eq 'liquid') {
349 126         241 $string .= chr( $ingr->value() );
350             } else {
351 71         139 $string .= ' '.$ingr->value();
352             }
353             }
354              
355 26         78 return $string;
356             }
357              
358              
359             # From the Perl FAQ: (NOT a method)
360             # fisher_yates_shuffle( \@array ) :
361             # generate a random permutation of @array in place
362             sub _fisher_yates_shuffle {
363 0     0     my $array = shift;
364 0           my $i;
365 0           for ($i = @$array; --$i; ) {
366 0           my $j = int rand ($i+1);
367 0           @$array[$i,$j] = @$array[$j,$i];
368             }
369             }
370              
371             __END__