File Coverage

blib/lib/Geometry/Formula.pm
Criterion Covered Total %
statement 9 146 6.1
branch 0 44 0.0
condition n/a
subroutine 3 27 11.1
pod 21 21 100.0
total 33 238 13.8


line stmt bran cond sub pod time code
1             package Geometry::Formula;
2              
3 21     21   57872 use strict;
  21         47  
  21         722  
4 21     21   130 use warnings;
  21         34  
  21         635  
5 21     21   119 use Carp qw(croak);
  21         45  
  21         71017  
6             my $PI = 3.1415926;
7              
8             our $VERSION = 0.02;
9              
10             sub new {
11 0     0 1   my $class = shift;
12 0           my $self = {};
13 0           bless $self, $class;
14 0           return $self;
15             }
16              
17             sub annulus {
18 0     0 1   my ( $self, %param, $x ) = @_;
19 0           _param_check( 'annulus', %param );
20              
21 0           $x = $PI *
22             ( $self->_squared( $param{'outer_radius'} ) - $self->_squared( $param{'inner_radius'} ) );
23              
24 0           return $x;
25             }
26              
27             sub circle {
28 0     0 1   my ( $self, %param, $x ) = @_;
29 0           _param_check( 'circle', %param );
30              
31 0 0         if ( $param{'formula'} eq 'area' ) {
    0          
32 0           $x = $PI * $self->_squared( $param{'radius'} );
33             }
34             elsif ( $param{'formula'} eq 'circumference' ) {
35 0           $x = ( 2 * $PI ) * $param{'radius'};
36             }
37             else {
38 0           $x = $param{'radius'} * 2;
39             }
40              
41 0           return $x;
42             }
43              
44             sub cone {
45 0     0 1   my ( $self, %param, $x ) = @_;
46 0           _param_check( 'cone', %param );
47              
48 0           $x = ( 1 / 3 ) * ( $param{'base'} * $param{'height'} );
49              
50 0           return $x;
51             }
52              
53             sub cube {
54 0     0 1   my ( $self, %param, $x ) = @_;
55 0           _param_check( 'cube', %param );
56              
57 0 0         if ( $param{'formula'} eq 'surface_area' ) {
58 0           $x = 6 * ( $param{'a'} * 2 );
59             }
60             else {
61 0           $x = $self->_cubed( $param{'a'} );
62             }
63              
64 0           return $x;
65             }
66              
67             sub ellipse {
68 0     0 1   my ( $self, %param, $x ) = @_;
69 0           _param_check( 'ellipse', %param );
70              
71 0 0         if ( $param{'formula'} eq 'area' ) {
72 0           $x = $PI * ( $param{'a'} * $param{'b'} );
73             }
74             else {
75 0           $x = 2 * $PI *
76             sqrt( ( $self->_squared( $param{'a'} ) + $self->_squared( $param{'b'} ) ) / 2 );
77             }
78              
79 0           return $x;
80             }
81              
82             sub ellipsoid {
83 0     0 1   my ( $self, %param, $x ) = @_;
84 0           _param_check( 'ellipsoid', %param );
85              
86 0           $x = ( 4 / 3 ) * $PI * $param{'a'} * $param{'b'} * $param{'c'};
87              
88 0           return $x;
89             }
90              
91             sub equilateral_triangle {
92 0     0 1   my ( $self, %param, $x ) = @_;
93 0           _param_check( 'equilateral_triangle', %param );
94              
95 0           $x = $self->_squared( $param{'side'} ) * ( sqrt(3) / 4 );
96              
97 0           return $x;
98             }
99              
100             sub frustum_of_right_circular_cone {
101 0     0 1   my ( $self, %param, $x ) = @_;
102 0           _param_check( 'frustum_of_right_circular_cone', %param );
103              
104 0 0         if ( $param{'formula'} eq 'lateral_surface_area' ) {
    0          
105 0           $x =
106             $PI *
107             ( $param{'large_radius'} + $param{'small_radius'} ) *
108             sqrt( $self->_squared( $param{'large_radius'} - $param{'small_radius'} ) +
109             $self->_squared( $param{'slant_height'} ) );
110             }
111             elsif ( $param{'formula'} eq 'total_surface_area' ) {
112 0           my $slant_height =
113             sqrt( $self->_squared( $param{'large_radius'} - $param{'small_radius'} ) +
114             $self->_squared( $param{'height'} ) );
115              
116 0           $x =
117             $PI *
118             ( $param{'small_radius'} *
119             ( $param{'small_radius'} + $slant_height )
120             + $param{'large_radius'} *
121             ( $param{'large_radius'} + $slant_height ) );
122              
123             }
124             else {
125 0           $x = (
126             $PI * (
127             $self->_squared( $param{'small_radius'} ) +
128             ( $param{'small_radius'} * $param{'large_radius'} ) +
129             $self->_squared( $param{'large_radius'} )
130             ) * $param{'height'}
131             ) / 3;
132             }
133              
134 0           return $x;
135             }
136              
137             sub parallelogram {
138 0     0 1   my ( $self, %param, $x ) = @_;
139 0           _param_check( 'parallelogram', %param );
140              
141 0 0         if ( $param{'formula'} eq 'area' ) {
142 0           $x = $param{'base'} * $param{'height'};
143             }
144             else {
145 0           $x = ( 2 * $param{'a'} ) + ( 2 * $param{'b'} );
146             }
147              
148 0           return $x;
149             }
150              
151             sub rectangle {
152 0     0 1   my ( $self, %param, $x ) = @_;
153 0           _param_check( 'rectangle', %param );
154              
155 0 0         if ( $param{'formula'} eq 'area' ) {
156 0           $x = $param{'length'} * $param{'width'};
157             }
158             else {
159 0           $x = ( 2 * $param{'length'} ) + ( 2 * $param{'width'} );
160             }
161              
162 0           return $x;
163             }
164              
165             sub rectangular_solid {
166 0     0 1   my ( $self, %param, $x ) = @_;
167 0           _param_check( 'rectangular_solid', %param );
168              
169 0 0         if ( $param{'formula'} eq 'volume' ) {
170 0           $x = $param{'length'} * $param{'width'} * $param{'height'};
171             }
172             else {
173 0           $x =
174             2 *
175             ( ( $param{'length'} * $param{'width'} ) +
176             ( $param{'width'} * $param{'height'} ) +
177             ( $param{'length'} * $param{'height'} ) );
178             }
179              
180 0           return $x;
181             }
182              
183             sub rhombus {
184 0     0 1   my ( $self, %param, $x ) = @_;
185 0           _param_check( 'rhombus', %param );
186              
187 0           $x = ( $param{'a'} * $param{'b'} ) / 2;
188              
189 0           return $x;
190             }
191              
192             sub right_circular_cone {
193 0     0 1   my ( $self, %param, $x ) = @_;
194 0           _param_check( 'right_circular_cone', %param );
195              
196 0 0         if ( $param{'formula'} eq 'lateral_surface_area' ) {
197 0           $x =
198             $PI *
199             $param{'radius'} *
200             ( sqrt( $self->_squared( $param{'radius'} ) + $self->_squared( $param{'height'} ) ) );
201             }
202             else {
203 0           $x = ( 1 / 3 ) * $PI * $self->_squared( $param{'radius'} ) * $param{'height'};
204             }
205              
206 0           return $x;
207             }
208              
209             sub right_circular_cylinder {
210 0     0 1   my ( $self, %param, $x ) = @_;
211 0           _param_check( 'right_circular_cylinder', %param );
212              
213 0 0         if ( $param{'formula'} eq 'lateral_surface_area' ) {
    0          
214 0           $x = 2 * $PI * $param{'radius'} * $param{'height'};
215             }
216             elsif ( $param{'formula'} eq 'total_surface_area' ) {
217 0           $x =
218             2 * $PI * $param{'radius'} * ( $param{'radius'} + $param{'height'} );
219             }
220             else {
221 0           $x = $PI * ( $self->_squared( $param{'radius'} ) * $param{'height'} );
222             }
223              
224 0           return $x;
225             }
226              
227             sub sector_of_circle {
228 0     0 1   my ( $self, %param, $x ) = @_;
229 0           _param_check( 'sector_of_circle', %param );
230              
231 0           $x = ( $param{'theta'} / 360 ) * $PI * $self->_squared( $param{'radius'} );
232              
233 0           return $x;
234             }
235              
236             sub sphere {
237 0     0 1   my ( $self, %param, $x ) = @_;
238 0           _param_check( 'sphere', %param );
239              
240 0 0         if ( $param{'formula'} eq 'surface_area' ) {
241 0           $x = 4 * $PI * $self->_squared( $param{'radius'} );
242             }
243             else {
244 0           $x = ( 4 / 3 ) * $PI * $self->_cubed( $param{'radius'} );
245             }
246              
247 0           return $x;
248             }
249              
250             sub square {
251 0     0 1   my ( $self, %param, $x ) = @_;
252 0           _param_check( 'square', %param );
253              
254 0 0         if ( $param{'formula'} eq 'area' ) {
255 0           $x = $self->_squared( $param{'side'} );
256             }
257             else {
258 0           $x = $param{'side'} * 4;
259             }
260              
261 0           return $x;
262             }
263              
264             sub torus {
265 0     0 1   my ( $self, %param, $x ) = @_;
266 0           _param_check( 'torus', %param );
267              
268 0 0         if ( $param{'formula'} eq 'surface_area' ) {
269 0           $x = 4 * $self->_squared($PI) * $param{'a'} * $param{'b'};
270             }
271             else {
272 0           $x = 2 * $self->_squared($PI) * $self->_squared( $param{'a'} ) * $param{'b'};
273             }
274              
275 0           return $x;
276             }
277              
278             sub trapezoid {
279 0     0 1   my ( $self, %param, $x ) = @_;
280 0           _param_check( 'trapezoid', %param );
281              
282 0 0         if ( $param{'formula'} eq 'area' ) {
283 0           $x = ( ( $param{'a'} + $param{'b'} ) / 2 ) * $param{'height'};
284             }
285             else {
286 0           $x = $param{'a'} + $param{'b'} + $param{'c'} + $param{'d'};
287             }
288              
289 0           return $x;
290             }
291              
292             sub triangle {
293 0     0 1   my ( $self, %param, $x ) = @_;
294 0           _param_check( 'triangle', %param );
295              
296 0 0         if ( $param{'formula'} eq 'area' ) {
297 0           $x = .5 * $param{'base'} * $param{'height'};
298             }
299             else {
300 0           $x = $param{'a'} + $param{'b'} + $param{'c'};
301             }
302              
303 0           return $x;
304             }
305              
306             sub _squared {
307 0     0     my ( $self, $num ) = @_;
308              
309 0           return $num ** 2;
310             }
311              
312             sub _cubed {
313 0     0     my ( $self, $num ) = @_;
314              
315 0           return $num ** 3;
316             }
317              
318             sub _param_check {
319 0     0     my ( $method, %param ) = @_;
320              
321 0           my %valid_params = (
322             annulus => { area => [ 'inner_radius', 'outer_radius' ] },
323             circle => {
324             area => ['radius'],
325             circumference => ['radius'],
326             diameter => ['radius']
327             },
328             cone => { volume => [ 'base', 'height' ] },
329             cube => {
330             surface_area => ['a'],
331             volume => ['a']
332             },
333             ellipse => {
334             area => [ 'a', 'b' ],
335             perimeter => [ 'a', 'b' ]
336             },
337             ellipsoid => { volume => [ 'a', 'b', 'c' ] },
338             equilateral_triangle => { area => ['side'] },
339             frustum_of_right_circular_cone => {
340             lateral_surface_area =>
341             [ 'slant_height', 'small_radius', 'large_radius' ],
342             total_surface_area => [ 'height', 'small_radius', 'large_radius' ],
343             volume => [ 'height', 'small_radius', 'large_radius' ]
344             },
345             parallelogram => {
346             area => [ 'base', 'height' ],
347             perimeter => [ 'a', 'b' ]
348             },
349             rectangle => {
350             area => [ 'length', 'width' ],
351             perimeter => [ 'length', 'width' ]
352             },
353             rectangular_solid => {
354             surface_area => [ 'length', 'width', 'height' ],
355             volume => [ 'length', 'width', 'height' ]
356             },
357             rhombus => { area => [ 'a', 'b' ] },
358             right_circular_cone => {
359             lateral_surface_area => [ 'radius', 'height' ],
360             volume => [ 'radius', 'height' ]
361             },
362             right_circular_cylinder => {
363             total_surface_area => [ 'radius', 'height' ],
364             lateral_surface_area => [ 'radius', 'height' ],
365             volume => [ 'radius', 'height' ]
366             },
367             sector_of_circle => { area => [ 'theta', 'radius' ] },
368             sphere => {
369             surface_area => ['radius'],
370             volume => ['radius']
371             },
372             square => {
373             area => ['side'],
374             perimeter => ['side']
375             },
376             torus => {
377             surface_area => [ 'a', 'b' ],
378             volume => [ 'a', 'b' ]
379             },
380             trapezoid => {
381             area => [ 'a', 'b', 'height' ],
382             perimeter => [ 'a', 'b', 'c', 'd' ]
383             },
384             triangle => {
385             area => [ 'base', 'height' ],
386             perimeter => [ 'a', 'b', 'c' ]
387             },
388             );
389              
390             # validate that parameter values are defined and numeric
391 0           foreach ( @{ $valid_params{$method}{ $param{'formula'} } } ) {
  0            
392 0 0         croak "required parameter '$_' not defined"
393             if !$param{$_};
394              
395 0 0         croak "parameter '$_' requires a numeric value"
396             if $param{$_} !~ m/^\d+$/;
397             }
398              
399             # validate parameter is a valid constructor/component of formula
400 0           foreach my $param ( keys %param ) {
401 0 0         next if $param eq 'formula';
402              
403 0           my @constructors = @{ $valid_params{$method}{ $param{'formula'} } };
  0            
404              
405 0 0         if ( !@constructors ) {
406 0           croak "invalid formula name: $param{'formula'} specified";
407             }
408              
409 0 0         if ( grep { $_ eq $param } @constructors ) {
  0            
410 0           next;
411             }
412             else {
413 0           croak "invalid parameter '$param' specified for $method";
414             }
415             }
416              
417 0           return 0;
418             }
419              
420             1;
421              
422             __END__