package Math::Calc::Units::Convert::Distance; use base 'Math::Calc::Units::Convert::Metric'; use strict; my %total_unit_map; my %ranges = ( default => [ 1, 999 ] ); my %distance_units = ( inch => [ 2.54, 'centimeter' ], foot => [ 12, 'inch' ], yard => [ 3, 'foot' ], mile => [ 5280, 'foot' ], ); my %distance_pref = ( meter => 1.1, inch => 0.7, foot => 0.9, yard => 0, mile => 1.0, ); my %aliases = ( 'feet' => 'foot', ); # Perform all math in terms of meters sub canonical_unit { return 'meter'; } # Metric.pm uses this to construct unit names sub abbreviated_canonical_unit { return 'm'; } # Preference for this class's canonical unit to be the "major" unit # used. The major unit is the one that determines the range of values # to use for computing the overall preference. For example, if you # have 240000 meters/day, you would want to pick "240km/hour", which # is based on the number "240" being a decent one to use for meters. # If you had instead chosen 'hour' as the major unit, then you # wouldn't like using 240 because 240 hours should really be described # as 10 days. # # Note that the above example is not realistic, because the only units # that are eligible for being chosen as the major unit are the ones in # the numerator. So major_pref() is really only used for something # like "square meter seconds", where you want to choose between # "meter" and "second". sub major_pref { return 1; } sub major_variants { my (\$self) = @_; return \$self->variants('meter'); } sub get_ranges { return \%ranges; } # Return the relative preference of different units. Meters are # preferred over miles, miles over feet. sub get_prefs { return \%distance_pref; } sub singular { my (\$self, \$unit) = @_; \$unit = \$self->SUPER::singular(\$unit); return \$aliases{\$unit} || \$unit; } sub unit_map { my (\$self) = @_; if (keys %total_unit_map == 0) { %total_unit_map = (%{\$self->SUPER::unit_map()}, %distance_units); } return \%total_unit_map; } # simple_convert : unitName x unitName -> multiplier # sub simple_convert { my (\$self, \$from, \$to) = @_; # 'm', 'meter', or 'meters' return 1 if \$from =~ /^m(eter(s?))?\$/i; if (my \$easy = \$self->SUPER::simple_convert(\$from, \$to)) { return \$easy; } # km == kilometer if (\$from =~ /^(.)m(eter(s?))?\$/i) { if (my (\$prefix) = \$self->expand(\$1)) { return \$self->simple_convert(\$prefix . "meter", \$to); } } return; # Failed } # Override Metric::variants because only meters should be given metric # prefixes, not inches, feet, etc. sub variants { my (\$self, \$base) = @_; my \$canon = \$self->canonical_unit(); return (\$base, keys %{ \$self->unit_map() }, map { "\$_\$canon" } \$self->get_prefixes()); } 1;