File Coverage

blib/lib/Box/Calc/Layer.pm
Criterion Covered Total %
statement 80 84 95.2
branch 13 14 92.8
condition 8 8 100.0
subroutine 17 18 94.4
pod 8 11 72.7
total 126 135 93.3


line stmt bran cond sub pod time code
1             package Box::Calc::Layer;
2             $Box::Calc::Layer::VERSION = '1.0200';
3 11     11   34487 use strict;
  11         21  
  11         264  
4 11     11   745 use Moose;
  11         462636  
  11         70  
5 11     11   75582 use Box::Calc::Row;
  11         3837  
  11         471  
6 11     11   104 use List::Util qw/sum/;
  11         24  
  11         889  
7 11     11   54 use Log::Any qw($log);
  11         23  
  11         112  
8 11     11   1959 use Data::Dumper;
  11         17  
  11         8681  
9              
10             =head1 NAME
11              
12             Box::Calc::Layer - A box is packed with multiple layers.
13              
14             =head1 VERSION
15              
16             version 1.0200
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 759 my $self = shift;
50 573         656 my $value = 0;
51 573         626 foreach my $row (@{$self->rows}) {
  573         16604  
52 4050 100       109209 $value = $row->fill_x if $row->fill_x > $value;
53             }
54 573         5696 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 34052 my $self = shift;
65 24992         31736 my $value = 0;
66 24992         28933 foreach my $row (@{$self->rows}) {
  24992         723083  
67 230737         6372418 $value += $row->fill_y;
68             }
69 24992         132727 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 496034 my $self = shift;
80 382855         438204 my $value = 0;
81 382855         380227 foreach my $row (@{$self->rows}) {
  382855         11015497  
82 2728496 100       75980993 $value = $row->fill_z if $row->fill_z > $value;
83             }
84 382855         2315115 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 5389 my $self = shift;
139 3579         4417 push @{$self->rows}, Box::Calc::Row->new(max_x => $self->max_x);
  3579         103995  
140             }
141              
142             sub BUILD {
143 547     547 0 987 my $self = shift;
144 547         3419 $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 367 my $self = shift;
155 278         387 my $weight = 0;
156 278         288 foreach my $row (@{$self->rows}) {
  278         8495  
157 1969         4530 $weight += $row->calculate_weight;
158             }
159 278         5804 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 50397 my ($self, $item, $count) = @_;
180 20861   100     75650 $count ||= 1;
181 20861 50       40202 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         38817 my $fill_z = $self->fill_z;
187 20861         54178 my $fill_y = $self->fill_y;
188 20861 100       662477 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         83 return 0;
192             }
193 20858 100 100     674851 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         26 $log->info($item->{name}.' would make this layer substantially taller, requesting new layer.');
195 4         76 return 0;
196             }
197 20854 100       609500 if ($self->rows->[-1]->pack_item($item)) {
198 17296         58364 return 1;
199             }
200             else {
201 3558 100       110450 if ($item->y > $self->max_y - $self->fill_y) {
202 526         2780 $log->info($item->{name}.' will not fit in a new row in this layer, requesting new layer.');
203 526         8320 return 0;
204             }
205             else {
206 3032         8553 $self->create_row;
207 3032         11189 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 7347 my ($self, $weight, $list) = @_;
220 265         270 foreach my $row (@{$self->rows}) {
  265         7256  
221 1947         5039 $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 326 my $self = shift;
240             return {
241 272         329 rows => [ map { $_->packing_instructions } @{ $self->rows } ],
  1960         5003  
  272         7530  
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             sub used_volume {
250 272     272 0 307 my $self = shift;
251 272         298 return sum map { $_->used_volume } @{ $self->rows };
  1960         4854  
  272         7770  
252             }
253              
254              
255             sub volume {
256 0     0 0   return $_[0]->fill_x * $_[0]->fill_y * $_[0]->fill_z;
257             }
258              
259 11     11   64 no Moose;
  11         20  
  11         87  
260             __PACKAGE__->meta->make_immutable;