File Coverage

blib/lib/Acme/FishFarm/Feeder.pm
Criterion Covered Total %
statement 69 72 95.8
branch 30 46 65.2
condition 3 5 60.0
subroutine 18 19 94.7
pod 13 13 100.0
total 133 155 85.8


line stmt bran cond sub pod time code
1             package Acme::FishFarm::Feeder;
2              
3 3     3   116981 use 5.008;
  3         22  
4 3     3   18 use strict;
  3         6  
  3         80  
5 3     3   15 use warnings;
  3         7  
  3         117  
6              
7 3     3   19 use Carp "croak";
  3         5  
  3         1680  
8              
9             =head1 NAME
10              
11             Acme::FishFarm::Feeder - Automated Feeder for Acme::FishFarm
12              
13             =head1 VERSION
14              
15             Version 1.01
16              
17             =cut
18              
19             our $VERSION = '1.01';
20              
21              
22             =head1 SYNOPSIS
23              
24             use 5.010;
25             use Acme::FishFarm::Feeder;
26              
27             my $feeder = Acme::FishFarm::Feeder->install( timer => 3, feeding_volume => 150 );
28              
29             say "Feeder installed and switched on!";
30             say "";
31              
32             while ( "fish are living happilly" ) {
33              
34             if ( $feeder->timer_is_up ) {
35             say "\nTimer is up, time to feed the fish!";
36             say "Feeding ", $feeder->feeding_volume, " cm^3 of fish food to the fish...";
37            
38             $feeder->feed_fish;
39            
40             say $feeder->food_remaining, " cm^3 of fish food remaining in the tank.\n";
41             }
42            
43             if ( $feeder->food_remaining <= 0 ) {
44             $feeder->refill; # default back to 500 cm^3
45             say "Refilled food tank back to ", $feeder->food_tank_capacity, " cm^3.\n";
46             }
47            
48             say $feeder->time_remaining, " hours left until it's time to feed the fish.";
49              
50             sleep(1);
51             $feeder->tick_clock;
52             }
53              
54             say "";
55             say "Feeder was switched off, please remeber to feed your fish on time :)";
56              
57             =head1 EXPORT
58              
59             None
60              
61             =head1 CREATION RELATED METHODS
62              
63             =head2 install ( %options )
64              
65             Installs an automated fish feeder.
66              
67             The following are available for C<%options>:
68              
69             =over 4
70              
71             =item * timer
72              
73             The default is C<8>.
74              
75             This is used as a threshold to identify that the time is up to feed the fish or not.
76              
77             The clock will be set to this value for countdown.
78              
79             =item * feeding_volume
80              
81             The default is C<50 cm^3>.
82              
83             =item * food_tank_capacity
84              
85             The maximum volume of fish food. Default is C<500 cm^3>.
86              
87             =item * current_food_amount
88              
89             The initial amount of food to be filled into the food tank. Default is max ie C<500 cm^3>.
90              
91             =back
92              
93             =cut
94              
95             sub install {
96 6     6 1 106 my $class = shift;
97 6         19 my %options = @_;
98            
99             # value of 0 should not work
100 6 100       23 if ( not $options{timer} ) {
101 4         10 $options{timer} = 8; # this is used as a reference only
102             }
103            
104             # when clock is a multiple of timer, then feed fish
105 6         11 $options{clock} = 0; # this is the actual one that will keep changing
106            
107 6 100       17 if ( not $options{feeding_volume} ) {
108 4         10 $options{feeding_volume} = 50;
109             }
110            
111 6 50       15 if ( not $options{food_tank_capacity} ) {
112 6         10 $options{food_tank_capacity} = 500;
113             }
114            
115 6 50       13 if ( not $options{current_food_amount} ) {
116 6         12 $options{current_food_amount} = $options{food_tank_capacity};
117             }
118            
119 6         11 $options{first_usage} = 1; # make sure the feeder doesn't say timer is up as soon as it is switched on
120            
121 6         29 bless \%options, $class;
122             }
123              
124              
125              
126             =head1 TIMER RELATED SUBROUTINES/METHODS
127              
128             =head2 get_timer
129              
130             Returns the timer threshold of the feeder.
131              
132             =cut
133              
134             sub get_timer {
135 2 50   2 1 10 ref( my $self = shift ) or croak "Please use this the OO way";
136 2         7 $self->{timer};
137             }
138              
139             =head2 set_timer ( $time )
140              
141             Sets the new timer threshold of the feeder.
142              
143             Setting this timer will not affect the clock within the feeder.
144              
145             =cut
146              
147             sub set_timer {
148 0 0   0 1 0 ref( my $self = shift ) or croak "Please use this the OO way";
149 0         0 $self->{timer} = shift;
150             }
151              
152              
153             =head2 timer_is_up
154              
155             Check if the timer is up. If timer is up, please remember to feed your fish. See C for more info.
156              
157             =cut
158              
159             sub timer_is_up {
160 5 50   5 1 319 ref (my $self = shift) or croak "Please use this the OO way";
161            
162             # skip the first round, 0 % n is always 0 and the feeder might think it's time to feed the fish as soon as it's switched on
163 5 100       20 if ( $self->{first_usage} ) {
164 2         5 $self->{first_usage} = 0;
165 2         9 return 0;
166             }
167            
168 3 100       17 if ( $self->{clock} % $self->{timer} == 0 ) {
169             # reset clock to 0 and return true
170 1         3 $self->{clock} = 0; # just in case the clock runs for too long
171 1         4 1;
172             } else {
173 2         8 0;
174             }
175             }
176              
177             =head2 time_remaining
178              
179             Returns the time remaining to feed the fish.
180              
181             This method might not be really useful, but anyway :)
182              
183             =cut
184              
185             sub time_remaining {
186 3 50   3 1 290 ref (my $self = shift) or croak "Please use this the OO way";
187 3         32 $self->{timer} - $self->{clock};
188             }
189              
190             =head2 tick_clock ( $custom_tick )
191              
192             C<$custom_tick> is optional and the default is C<1>.
193              
194             This will cause the timer of the feeder to increase by C<1> (default) or by C<$custom_tick>.
195              
196             =cut
197              
198             sub tick_clock {
199 10 50   10 1 2090 ref (my $self = shift) or croak "Please use this the OO way";
200 10         49 ++$self->{clock};
201             }
202              
203              
204             =head1 FOOD TANK RELATED SUBROUTINE/METHODS
205              
206             =head2 food_tank_capacity
207              
208             Returns the current food tank capacity.
209              
210             =cut
211              
212             sub food_tank_capacity {
213 2 50   2 1 8 ref (my $self = shift) or croak "Please use this the OO way";
214 2         8 $self->{food_tank_capacity};
215             }
216              
217             =head2 set_food_tank_capacity ( $new_capacity )
218              
219             Set the new food tank capacity to C<$new_capacity>.
220              
221             =cut
222              
223             sub set_food_tank_capacity {
224 3     3   25 no warnings "numeric";
  3         7  
  3         1168  
225 1 50   1 1 6 ref (my $self = shift) or croak "Please use this the OO way";
226 1   50     6 my $new_capacity = int (shift) || return;
227 0         0 $self->{food_tank_capacity} = $new_capacity;
228             }
229              
230             =head2 food_remaining
231              
232             Returns the remaining amount of food left.
233              
234             =cut
235              
236             sub food_remaining {
237 11 50   11 1 1064 ref (my $self = shift) or croak "Please use this the OO way";
238 11         58 $self->{current_food_amount};
239             }
240              
241             =head1 FEEDING RELATED SUBROUTINES/METHODS
242              
243             =head2 feed_fish ( %options )
244              
245             Feeds the fish.
246              
247             Take note that this will feed the fish no matter what. So it's up to you to make sure that you check if the
248             feeder timer is really up or not before calling this method. See C for more info.
249              
250             C<%options> supports the following key:
251              
252             =over 4
253              
254             =item * verbose
255              
256             Setting this to a true value will give output about the feeder's situation when feeding the fish.
257              
258             =back
259              
260             =cut
261              
262             sub feed_fish {
263 4 50   4 1 5987 ref (my $self = shift) or croak "Please use this the OO way";
264 4         11 my %options = @_;
265 4 100       17 if ( $self->{current_food_amount} - $self->{feeding_volume} <= 0 ) {
266 2 50       7 if ( $options{verbose} ) {
267 2         103 print "Your feeder has run out of food, please refill as soon as possible.\n";
268 2         37 print "Only managed to feed $self->{current_food_amount} cm^3 of food to the fish.\n";
269             }
270 2         17 $self->{current_food_amount} = 0;
271             } else {
272 2         7 $self->{current_food_amount} = $self->{current_food_amount} - $self->{feeding_volume};
273             }
274             }
275              
276             =head2 set_feeding_volume ( $volume )
277              
278             Sets the fish food feeding volume.
279              
280             C<$volume> must be a positive number. No error checking is done for this yet.
281              
282             =cut
283              
284             sub set_feeding_volume {
285 2 50   2 1 9 ref (my $self = shift) or croak "Please use this the OO way";
286 2 100       168 my $volume = shift or croak "Please specify feeding volume";
287 1         3 $self->{feeding_volume} = $volume;
288             }
289              
290             =head2 feeding_volume
291              
292             Returns the amount of food to feed the fish each time the C method is called.
293              
294             =cut
295              
296             sub feeding_volume {
297 3 50   3 1 11 ref (my $self = shift) or croak "Please use this the OO way";
298 3         11 $self->{feeding_volume};
299             }
300              
301             =head2 refill ( $volume )
302              
303             Refills the fish food tank B C<$volume>.
304              
305             If C<$volume> is not specified, the food tank will be filled to max.
306              
307             If C<$volume> is a strange value, it will be ignored and filled to max.
308              
309             =cut
310              
311             sub refill {
312 3     3   35 no warnings "numeric";
  3         7  
  3         467  
313 5 50   5 1 621 ref (my $self = shift) or croak "Please use this the OO way";
314              
315 5   66     21 my $volume = shift || $self->{food_tank_capacity};
316 5 100       14 return if not int($volume);
317            
318 4 100       12 if ( $volume > $self->{food_tank_capacity} ) {
319 1         4 $self->{current_food_amount} = $self->{food_tank_capacity};
320             } else {
321 3         8 $self->{current_food_amount} = $volume;
322             }
323            
324             }
325              
326             =head1 AUTHOR
327              
328             Raphael Jong Jun Jie, C<< >>
329              
330             =head1 BUGS
331              
332             Please report any bugs or feature requests to C, or through
333             the web interface at L. I will be notified, and then you'll
334             automatically be notified of progress on your bug as I make changes.
335              
336              
337              
338              
339             =head1 SUPPORT
340              
341             You can find documentation for this module with the perldoc command.
342              
343             perldoc Acme::FishFarm::Feeder
344              
345              
346             You can also look for information at:
347              
348             =over 4
349              
350             =item * RT: CPAN's request tracker (report bugs here)
351              
352             L
353              
354             =item * CPAN Ratings
355              
356             L
357              
358             =item * Search CPAN
359              
360             L
361              
362             =back
363              
364              
365             =head1 ACKNOWLEDGEMENTS
366              
367             Besiyata d'shmaya
368              
369             =head1 SEE ALSO
370              
371             Acme::FishFarm
372              
373             =head1 LICENSE AND COPYRIGHT
374              
375             This software is Copyright (c) 2021 by Raphael Jong Jun Jie.
376              
377             This is free software, licensed under:
378              
379             The Artistic License 2.0 (GPL Compatible)
380              
381              
382             =cut
383              
384             1; # End of Acme::FishFarm::Feeder