File Coverage

blib/lib/Box/Calc/Layer.pm
Criterion Covered Total %
statement 80 84 95.2
branch 15 16 93.7
condition 8 8 100.0
subroutine 17 18 94.4
pod 10 11 90.9
total 130 137 94.8


line stmt bran cond sub pod time code
1             package Box::Calc::Layer;
2             $Box::Calc::Layer::VERSION = '1.0201';
3 11     11   63318 use strict;
  11         29  
  11         664  
4 11     11   464 use Moose;
  11         379172  
  11         67  
5 11     11   78319 use Box::Calc::Row;
  11         4750  
  11         462  
6 11     11   109 use List::Util qw/sum/;
  11         23  
  11         838  
7 11     11   68 use Log::Any qw($log);
  11         23  
  11         108  
8 11     11   9810 use Data::Dumper;
  11         68910  
  11         9302  
9              
10             =head1 NAME
11              
12             Box::Calc::Layer - A box is packed with multiple layers.
13              
14             =head1 VERSION
15              
16             version 1.0201
17              
18             =head1 SYNOPSIS
19              
20             my $row = Box::Calc::Row->new(max_x => 6);
21            
22             =head1 METHODS
23              
24             =head2 new(params)
25              
26             Constructor.
27              
28             B<NOTE:> A layer is automatically created containing a single empty L<Box::Calc::Row>.
29              
30             =over
31              
32             =item max_x
33              
34             The maximimum width of the layer. This is equivalent to the C<x> or longest dimension of the containing box.
35              
36             =item max_y
37              
38             The maximimum depth of the layer. This is equivalent to the C<y> or middle dimension of the containing box.
39              
40             =back
41              
42             =head2 fill_x()
43              
44             Returns how full the layer is in the C<x> dimension.
45              
46             =cut
47              
48             sub fill_x {
49 573     573 1 921 my $self = shift;
50 573         745 my $value = 0;
51 573         775 foreach my $row (@{$self->rows}) {
  573         13873  
52 4050 100       87666 $value = $row->fill_x if $row->fill_x > $value;
53             }
54 573         4439 return sprintf ("%.4f", $value);
55             }
56              
57             =head2 fill_y()
58              
59             Returns how full the layer is in the C<y> dimension.
60              
61             =cut
62              
63             sub fill_y {
64 24992     24992 1 37718 my $self = shift;
65 24992         33118 my $value = 0;
66 24992         32825 foreach my $row (@{$self->rows}) {
  24992         530974  
67 230737         4556918 $value += $row->fill_y;
68             }
69 24992         122838 return sprintf ("%.4f", $value);
70             }
71              
72             =head2 fill_z()
73              
74             Returns how full the layer is in the C<z> dimension.
75              
76             =cut
77              
78             sub fill_z {
79 382855     382855 1 477779 my $self = shift;
80 382855         453090 my $value = 0;
81 382855         412258 foreach my $row (@{$self->rows}) {
  382855         7994754  
82 2728496 100       53195991 $value = $row->fill_z if $row->fill_z > $value;
83             }
84 382855         2032848 return sprintf ("%.4f", $value);
85             }
86              
87             =head2 max_x()
88              
89             Returns the maximum C<x> dimension of this layer. See C<new> for details.
90              
91             =cut
92              
93             has max_x => (
94             is => 'ro',
95             required => 1,
96             isa => 'Num',
97             );
98              
99             =head2 max_y()
100              
101             Returns the maximum C<y> dimension of this layer. See C<new> for details.
102              
103             =cut
104              
105             has max_y => (
106             is => 'ro',
107             required => 1,
108             isa => 'Num',
109             );
110              
111             =head2 rows()
112              
113             Returns an array reference of the list of L<Box::Calc::Row> contained in this layer.
114              
115             =head2 count_rows()
116              
117             Returns the number of rows contained in this layer.
118              
119             =cut
120              
121             has rows => (
122             is => 'rw',
123             isa => 'ArrayRef[Box::Calc::Row]',
124             default => sub { [] },
125             traits => ['Array'],
126             handles => {
127             count_rows => 'count',
128             }
129             );
130              
131             =head2 create_row()
132              
133             Adds a new L<Box::Calc::Row> to this layer.
134              
135             =cut
136              
137             sub create_row {
138 3579     3579 1 7568 my $self = shift;
139 3579         5651 push @{$self->rows}, Box::Calc::Row->new(max_x => $self->max_x);
  3579         80826  
140             }
141              
142             sub BUILD {
143 547     547 0 1238 my $self = shift;
144 547         1841 $self->create_row;
145             }
146              
147             =head2 calculate_weight()
148              
149             Calculates and returns the weight of all the rows in this layer.
150              
151             =cut
152              
153             sub calculate_weight {
154 278     278 1 541 my $self = shift;
155 278         408 my $weight = 0;
156 278         397 foreach my $row (@{$self->rows}) {
  278         6529  
157 1969         4089 $weight += $row->calculate_weight;
158             }
159 278         2177 return $weight;
160             }
161              
162             =head2 pack_item(item)
163              
164             Add a L<Box::Calc::Item> to this layer.
165              
166             Returns 1 on success or 0 on failure.
167              
168             =over
169              
170             =item item
171              
172             The L<Box::Calc::Item> instance you want to add to this layer.
173              
174             =back
175              
176             =cut
177              
178             sub pack_item {
179 20861     20861 1 55357 my ($self, $item, $count) = @_;
180 20861   100     75620 $count ||= 1;
181 20861 50       37101 if ($count > 99) {
182 0         0 $log->warn($item->{name}.' is causing infinite recursion in Box::Calc::Layer');
183 0         0 $log->debug(Dumper($item));
184 0         0 return 0;
185             }
186 20861         37456 my $fill_z = $self->fill_z;
187 20861         48119 my $fill_y = $self->fill_y;
188 20861 100       491134 if ($item->y > $self->max_y - $fill_y + $self->rows->[-1]->fill_y # item would make the layer too wide
189             ) {
190 3         31 $log->info($item->{name}.' would make the layer too wide, requesting new layer.');
191 3         22 return 0;
192             }
193 20858 100 100     486615 if ($fill_z > 0 && $item->z > $fill_z * 1.75 && $item->y < $fill_y) { # item would make the layer substantially taller, unless the layer is currently pretty narrow
      100        
194 4         40 $log->info($item->{name}.' would make this layer substantially taller, requesting new layer.');
195 4         26 return 0;
196             }
197 20854 100       432448 if ($self->rows->[-1]->pack_item($item)) {
198 17296         56545 return 1;
199             }
200             else {
201 3558 100       81291 if ($item->y > $self->max_y - $self->fill_y) {
202 526         3372 $log->info($item->{name}.' will not fit in a new row in this layer, requesting new layer.');
203 526         3060 return 0;
204             }
205             else {
206 3032         11754 $self->create_row;
207 3032         11664 return $self->pack_item($item, $count + 1);
208             }
209             }
210             }
211              
212             =head2 packing_list(weight, list)
213              
214             Updates a scalar reference with the weight of the layer and a hash reference of all the items in this layer.
215              
216             =cut
217              
218             sub packing_list {
219 265     265 1 3109 my ($self, $weight, $list) = @_;
220 265         364 foreach my $row (@{$self->rows}) {
  265         6020  
221 1947         4519 $row->packing_list($weight, $list)
222             }
223             }
224              
225             =head2 packing_instructions()
226              
227             Returns a description of the layer.
228              
229             {
230             fill_x => 3,
231             fill_y => 3,
232             fill_z => 1,
233             rows => [ ... ],
234             }
235              
236             =cut
237              
238             sub packing_instructions {
239 272     272 1 403 my $self = shift;
240             return {
241 272         397 rows => [ map { $_->packing_instructions } @{ $self->rows } ],
  1960         5014  
  272         6263  
242             fill_x => $self->fill_x,
243             fill_y => $self->fill_y,
244             fill_z => $self->fill_z,
245             calculated_weight => $self->calculate_weight,
246             }
247             }
248              
249              
250             =head2 used_volume
251              
252             Returns the real used volume for this layer.
253              
254             =head2 volume
255              
256             Returns the exact volume needed for this layer.
257              
258             =cut
259              
260              
261             sub used_volume {
262 272     272 1 394 my $self = shift;
263 272 100       369 return sum map { $_->used_volume || 0 } @{ $self->rows };
  1960         4252  
  272         6840  
264             }
265              
266              
267             sub volume {
268 0     0 1   return $_[0]->fill_x * $_[0]->fill_y * $_[0]->fill_z;
269             }
270              
271 11     11   97 no Moose;
  11         27  
  11         93  
272             __PACKAGE__->meta->make_immutable;
273              
274             =for Pod::Coverage BUILD