2014-06-23 22:47:28 -07:00
|
|
|
package DDG::GoodieRole::NumberStyle;
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
use Moo;
|
|
|
|
|
|
|
|
has [qw(id decimal thousands)] => (
|
|
|
|
is => 'ro',
|
|
|
|
);
|
|
|
|
|
|
|
|
sub understands {
|
|
|
|
my ($self, $number) = @_;
|
|
|
|
my ($decimal, $thousands) = ($self->decimal, $self->thousands);
|
|
|
|
|
2014-06-29 05:38:32 -07:00
|
|
|
# How do we know if a number is reasonable for this style?
|
2014-06-23 22:47:28 -07:00
|
|
|
return (
|
2014-06-29 16:06:24 -07:00
|
|
|
# The number must contain only things we understand: numerals and separators for this style.
|
2014-06-23 22:47:28 -07:00
|
|
|
$number =~ /^(\d|\Q$thousands\E|\Q$decimal\E)+$/
|
2014-06-29 05:38:32 -07:00
|
|
|
&& (
|
2014-06-29 16:06:24 -07:00
|
|
|
# The number is not required to contain thousands separators
|
2014-06-29 05:38:32 -07:00
|
|
|
$number !~ /\Q$thousands\E/
|
|
|
|
|| (
|
|
|
|
# But if the number does contain thousands separators, they must delimit exactly 3 numerals.
|
2014-06-29 16:06:24 -07:00
|
|
|
$number !~ /\Q$thousands\E\d{1,2}\b/
|
|
|
|
&& $number !~ /\Q$thousands\E\d{4,}/
|
|
|
|
# And cannot follow a leading zero
|
2014-06-29 05:38:32 -07:00
|
|
|
&& $number !~ /^0\Q$thousands\E/
|
|
|
|
))
|
|
|
|
&& (
|
2014-06-29 16:06:24 -07:00
|
|
|
# The number is not required to include decimal separators
|
2014-06-29 05:38:32 -07:00
|
|
|
$number !~ /\Q$decimal\E/
|
|
|
|
# But if one is included, it cannot be followed by another separator, whether decimal or thousands.
|
2014-06-29 16:06:24 -07:00
|
|
|
|| $number !~ /\Q$decimal\E(?:.*)?(?:\Q$decimal\E|\Q$thousands\E)/
|
2014-06-29 05:38:32 -07:00
|
|
|
)) ? 1 : 0;
|
2014-06-23 22:47:28 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
sub precision_of {
|
|
|
|
my ($self, $number_text) = @_;
|
|
|
|
my $decimal = $self->decimal;
|
|
|
|
|
|
|
|
return ($number_text =~ /\Q$decimal\E(\d+)/) ? length($1) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub for_computation {
|
|
|
|
my ($self, $number_text) = @_;
|
|
|
|
my ($decimal, $thousands) = ($self->decimal, $self->thousands);
|
|
|
|
|
|
|
|
$number_text =~ s/\Q$thousands\E//g; # Remove thousands seps, since they are just visual.
|
|
|
|
$number_text =~ s/\Q$decimal\E/./g; # Make sure decimal mark is something perl knows how to use.
|
|
|
|
|
|
|
|
return $number_text;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub for_display {
|
|
|
|
my ($self, $number_text) = @_;
|
|
|
|
my ($decimal, $thousands) = ($self->decimal, $self->thousands); # Unpacked for easier regex-building
|
|
|
|
|
|
|
|
$number_text = reverse $number_text;
|
|
|
|
$number_text =~ s/\./$decimal/g; # Perl decimal mark to whatever we need.
|
|
|
|
$number_text =~ s/(\d\d\d)(?=\d)(?!\d*\Q$decimal\E)/$1$thousands/g;
|
|
|
|
|
|
|
|
return scalar reverse $number_text;
|
|
|
|
}
|
|
|
|
|
|
|
|
1;
|