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.0206';
3 13     13   107422 use strict;
  13         35  
  13         386  
4 13     13   547 use Moose;
  13         457442  
  13         88  
5 13     13   88135 use Box::Calc::Row;
  13         5256  
  13         603  
6 13     13   109 use List::Util qw/sum/;
  13         26  
  13         967  
7 13     13   75 use Log::Any qw($log);
  13         24  
  13         120  
8 13     13   12448 use Data::Dumper;
  13         96350  
  13         10805  
9              
10             =head1 NAME
11              
12             Box::Calc::Layer - A box is packed with multiple layers.
13              
14             =head1 VERSION
15              
16             version 1.0206
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 2423     2423 1 3637 my $self = shift;
50 2423         3026 my $value = 0;
51 2423         2865 foreach my $row (@{$self->rows}) {
  2423         48949  
52 18081 100       322046 $value = $row->fill_x if $row->fill_x > $value;
53             }
54 2423         20743 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 64931     64931 1 122504 my $self = shift;
65 64931         93968 my $value = 0;
66 64931         96680 foreach my $row (@{$self->rows}) {
  64931         1281332  
67 552719         9880999 $value += $row->fill_y;
68             }
69 64931         349820 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 1048139     1048139 1 1225548 my $self = shift;
80 1048139         1118234 my $value = 0;
81 1048139         1042614 foreach my $row (@{$self->rows}) {
  1048139         20222814  
82 7405061 100       131738761 $value = $row->fill_z if $row->fill_z > $value;
83             }
84 1048139         5597028 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 8827     8827 1 18286 my $self = shift;
139 8827         18310 push @{$self->rows}, Box::Calc::Row->new(max_x => $self->max_x);
  8827         183522  
140             }
141              
142             sub BUILD {
143 1314     1314 0 2623 my $self = shift;
144 1314         5327 $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 780     780 1 1412 my $self = shift;
155 780         1041 my $weight = 0;
156 780         1015 foreach my $row (@{$self->rows}) {
  780         15521  
157 5820         10379 $weight += $row->calculate_weight;
158             }
159 780         7131 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 53706     53706 1 136344 my ($self, $item, $count) = @_;
180 53706   100     246000 $count ||= 1;
181 53706 50       119529 if ($count > 5) {
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 53706         123774 my $fill_z = $self->fill_z;
187 53706         162157 my $fill_y = $self->fill_y;
188 53706 100       1261450 if ($item->y > $self->max_y - $fill_y + $self->rows->[-1]->fill_y # item would make the layer too wide
189             ) {
190 3         33 $log->info($item->{name}.' would make the layer too wide, requesting new layer.');
191 3         26 return 0;
192             }
193 53703 100 100     1251038 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 6         64 $log->info($item->{name}.' would make this layer substantially taller, requesting new layer.');
195 6         47 return 0;
196             }
197 53697 100       1032955 if ($self->rows->[-1]->pack_item($item)) {
198 44895         177803 return 1;
199             }
200             else {
201 8802 100       190589 if ($item->y > $self->max_y - $self->fill_y) {
202 1289         9167 $log->info($item->{name}.' will not fit in a new row in this layer, requesting new layer.');
203 1289         7012 return 0;
204             }
205             else {
206 7513         37655 $self->create_row;
207 7513         36925 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 767     767 1 4676 my ($self, $weight, $list) = @_;
220 767         912 foreach my $row (@{$self->rows}) {
  767         15014  
221 5798         10526 $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 774     774 1 1178 my $self = shift;
240             return {
241 774         1240 rows => [ map { $_->packing_instructions } @{ $self->rows } ],
  5811         12422  
  774         15142  
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 774     774 1 1079 my $self = shift;
263 774 100       978 return sum map { $_->used_volume || 0 } @{ $self->rows };
  5811         11621  
  774         15681  
264             }
265              
266              
267             sub volume {
268 0     0 1   return $_[0]->fill_x * $_[0]->fill_y * $_[0]->fill_z;
269             }
270              
271 13     13   126 no Moose;
  13         57  
  13         136  
272             __PACKAGE__->meta->make_immutable;
273              
274             =for Pod::Coverage BUILD