File Coverage

blib/lib/Data/Vitals/Height.pm
Criterion Covered Total %
statement 38 42 90.4
branch 8 14 57.1
condition 4 12 33.3
subroutine 12 12 100.0
pod 6 6 100.0
total 68 86 79.0


line stmt bran cond sub pod time code
1             package Data::Vitals::Height;
2              
3             =pod
4              
5             =head1 NAME
6              
7             Data::Vitals::Circumference - A measurement of the circumference around part
8             of the human body.
9              
10             =head1 DESCRIPTION
11              
12             The Data::Vitals::Height package provides an implementation of the height of
13             a person.
14              
15             This can be taken by standard backwards against wall or other vertical
16             surface with your heels, seat, shoulders, and head touching the surface.
17             You should be standing straight with your head in a horizontal position.
18              
19             A rule is placed horizontally and gently pressed down into the hair, so
20             that it presses on the skull. The point at which the rule contacts the wall
21             is noted, and then measured down to the floor.
22              
23             =head2 The "Height String"
24              
25             For height, measurements in both "feet and inches" and centimetres are
26             widespread, and we try to support them both where the intent is obvious.
27              
28             Any imperial measurement MUST contain two parts, and indicate B
29             the "feet" indicator. The one case of input without the unit specificier we
30             allow is any single two or three digit number, which is taken to mean
31             centimetres.
32              
33             For metric, the supported input range is 30cm - 300cm. For imperial, it is
34             1'0" - 8'11". This range ignores very small babies but is slightly larger than
35             the world record at the top end, and so is fairly all-encompassing.
36              
37             The ability to customise these legal ranges will be added at a later time.
38              
39             The following shows samples for the formats accepted.
40              
41             Metric measurements
42             180cm Default form
43             180.5cm Halves (and only halves) are allowed
44             180 Raw three digit number
45             95 Raw two digit number
46             180c Shorthand (or missed the m)
47             180cms Plural form
48             180CM Case insensitive
49             180 cm Whitespace between the type is ignored
50            
51             Imperial Measurements
52             5'10" Default form
53             5'10 If a 'feet' indicator is given, inches is implied
54             5' 10 Whitespace is ignored
55             5'10 Various inch indicators
56             5'10i Various inch indicators
57             5'10in Various inch indicators
58             5'10inc Various inch indicators
59             5'10inch Various inch indicators
60             5'10inche Various inch indicators
61             5'10inches Various inch indidators
62             5'10inchs This bad spelling case is known
63             5f10 Various foot indicators
64             5ft10 Various foot indicators
65             5foot10 Various foot indicators
66             5feet10 Various foot indicators
67             5foot10" Indicates can be compiled any way
68             5FEET10 Case insensitive
69             5' 10" Whitespace is ignored
70              
71             =head2 Storage and Conversion
72              
73             Regardless of the method that the value is entered, all values are stored
74             internally in centimetres. The default string form of all measurements is
75             also in centimetres.
76              
77             This is a specific design decision, as there is a long term world trend
78             towards increased metrification. Many countries (such as Germany) use metric
79             values even for the "common man's" understanding of things and people do not
80             know their height in feet and inches.
81              
82             However, to support those still dealing in inches we ensure that any
83             value initially entered in inches (including optional halves), stored as
84             cms, and returned to inches for presentation will ALWAYS return the
85             original number of inches, including halves.
86              
87             The conversion functions in L are heavily tested for
88             every possible value in the range to ensure that this is the case.
89              
90             =head1 METHODS
91              
92             =cut
93              
94 4     4   25317 use strict;
  4         9  
  4         339  
95 4     4   625 use Data::Vitals::Util ();
  4         23  
  4         82  
96              
97 4     4   22 use vars qw{$VERSION};
  4         17  
  4         180  
98             BEGIN {
99 4     4   164 $VERSION = '0.05';
100             }
101              
102 4     4   4077 use overload 'bool' => sub () { 1 };
  4         2293  
  4         29  
103 4     4   243 use overload '""' => 'as_string';
  4         13  
  4         14  
104              
105              
106              
107              
108              
109             #####################################################################
110             # Constructor
111              
112             =pod
113              
114             =head2 new $height
115              
116             The C constructor takes a height string and returns a new object
117             representing the height measurement, or C if there is a problem with
118             the value provided.
119              
120             Currently, there is no explanation of the reason why a value is rejected.
121             Any used may need to just be presented with an "Invalid Value" message.
122              
123             In future, a mechanism to access error messages following an error will
124             be added.
125              
126             =cut
127              
128             sub new {
129 2   33 2 1 26 my $class = ref $_[0] || $_[0];
130 2 50       13 my $value = defined $_[1] ? lc $_[1] : return undef;
131 2         7 $value =~ s/\s//g;
132              
133             # Basic metric
134 2 100       22 if ( $value =~ /^(\d{2,3}(?:\.5)?)\s*(?:c|cm|cms)?$/ ) {
135 1         5 my $cm = 0 + $1;
136 1 50 33     10 unless ( $cm > 30 and $cm < 300 ) {
137             # Impossibly out of range
138 0         0 return undef;
139             }
140 1         7 return bless { value => $cm }, $class;
141             }
142              
143             # Basic imperial
144 1 50       14 if ( $value =~ /^(\d)(?:\'|f|ft|foot|feet)(\d{1,2}(?:\.5)?)(?:\"|i|in|inc|inch|inchs|inches)?$/ ) {
145 1         4 my $feet = 0 + $1;
146 1         5 my $inch = 0 + $2;
147 1 50 33     9 unless ( $feet >= 1 and $feet <= 8 ) {
148             # Impossibly out of range
149 0         0 return undef;
150             }
151 1 50 33     7 unless ( $inch >= 0 and $inch < 12 ) {
152             # Illegal value
153 0         0 return undef;
154             }
155              
156             # Convert to cm
157 1 50       8 my $cm = Data::Vitals::Util::inch2cm($feet * 12 + $inch) or return undef;
158 1         8 return bless { value => $cm }, $class;
159             }
160              
161             # Anything else
162 0         0 undef;
163             }
164              
165             ###------------------------------------------------------------------
166              
167             =pod
168              
169             =head2 as_string
170              
171             The C method returns the generic string form of the measurement.
172              
173             This is also the method called during overloaded stringification. By
174             default, this returns the metric form, which is in centimetres.
175              
176             =cut
177              
178             # Generic string form, which is currently set to cms.
179             # Normally, given the American bias in programming, I would have done
180             # this as feet and inches. However there is a long term trend towards
181             # metrification, and from a support issue it is better to be a bit more
182             # aggressive and use standard units by default earlier, rather than be
183             # stuck with a default string form that nobody uses in future years.
184 2     2 1 2642 sub as_string { shift->as_metric }
185              
186             ###------------------------------------------------------------------
187              
188             =pod
189              
190             =head2 as_metric
191              
192             The C method returns the metric form of the measurement, which
193             for height measurements is always in centimetres.
194              
195             =cut
196              
197 4     4 1 52 sub as_metric { shift->as_cms }
198              
199             ###------------------------------------------------------------------
200              
201             =pod
202              
203             =head2 as_imperial
204              
205             The C method returns the imperial form of the measurement,
206             which for height measurements is in feet and inches
207              
208             =cut
209              
210 2     2 1 9 sub as_imperial { shift->as_feet }
211              
212             ###------------------------------------------------------------------
213              
214             =pod
215              
216             =head2 as_cms
217              
218             The C method explicitly returns the measurement in centimetres.
219              
220             The format of the string returned is similar to C<180cm>.
221              
222             =cut
223              
224 5     5 1 204 sub as_cms { $_[0]->{value} . 'cm' }
225              
226             ###------------------------------------------------------------------
227              
228             =pod
229              
230             =head2 as_feet
231              
232             The C method explicitly returns the measurement in feet and
233             inches.
234              
235             The format of the string returned is similar to C<5'10">
236              
237             =cut
238              
239             sub as_feet {
240 3     3 1 17 my $inch = Data::Vitals::Util::cm2inch($_[0]->{value});
241 3         27 my $feet = int($inch / 12);
242 3         6 $inch = $inch % 12;
243 3         18 "$feet'$inch\"";
244             }
245              
246             ###------------------------------------------------------------------
247              
248             1;
249              
250             =pod
251              
252             =head1 TO DO
253              
254             - Add support for metres "1.84m"
255              
256             - Add a new class as an abstract for both height, circumference, and other
257             length measurements.
258              
259             =head1 SUPPORT
260              
261             Bugs should always be reported via the CPAN bug tracker
262              
263             L
264              
265             For other issues, contact the maintainer.
266              
267             =head1 AUTHORS
268              
269             Adam Kennedy Eadamk@cpan.orgE
270              
271             =head1 ACKNOWLEGEMENTS
272              
273             Thank you to Phase N (L) for permitting
274             the open sourcing and release of this distribution.
275              
276             =head1 COPYRIGHT
277              
278             Copyright 2004 - 2008 Adam Kennedy.
279              
280             This program is free software; you can redistribute
281             it and/or modify it under the same terms as Perl itself.
282              
283             The full text of the license can be found in the
284             LICENSE file included with this module.
285              
286             =cut