File Coverage

blib/lib/Lingua/AFR/Numbers.pm
Criterion Covered Total %
statement 80 111 72.0
branch 26 48 54.1
condition 25 61 40.9
subroutine 11 11 100.0
pod 2 2 100.0
total 144 233 61.8


line stmt bran cond sub pod time code
1             # For Emacs: -*- mode:cperl; mode:folding -*-
2              
3             package Lingua::AFR::Numbers;
4             # ABSTRACT: Converts numeric values into their Afrikaans equivalents.
5              
6             # {{{ use block
7              
8 1     1   46482 use 5.10.1;
  1         3  
  1         32  
9              
10 1     1   5 use strict;
  1         1  
  1         32  
11 1     1   5 use warnings;
  1         4  
  1         19  
12              
13 1     1   4 use Carp;
  1         1  
  1         74  
14 1     1   720 use Perl6::Export::Attrs;
  1         11763  
  1         7  
15              
16             # }}}
17             # {{{ variables declaration
18              
19             our $VERSION = 0.1106;
20              
21             my $numbers = {
22             0 => 'nul',
23             1 => 'een',
24             2 => 'twee',
25             3 => 'drie',
26             4 => 'vier',
27             5 => 'vyf',
28             6 => 'ses',
29             7 => 'sewe',
30             8 => 'agt',
31             9 => 'nege',
32             10 => 'tien',
33             11 => 'elf',
34             12 => 'twaalf',
35             13 => 'dertien',
36             14 => 'viertien',
37             15 => 'vyftien',
38             16 => 'sestien',
39             17 => 'sewentien',
40             18 => 'agtien',
41             19 => 'negentien',
42             20 => 'twintig',
43             30 => 'dertig',
44             40 => 'viertig',
45             50 => 'vyftig',
46             60 => 'sestig',
47             70 => 'sewentig',
48             80 => 'tagtig',
49             90 => 'negentig',
50             };
51              
52             # }}}
53              
54             # {{{ new
55              
56             sub new {
57 1     1 1 16 my $class = shift;
58 1   50     6 my $number = shift || '';
59              
60 1         1 my $self = {};
61 1         3 bless $self, $class;
62              
63 1 50       2 if ($number =~ /\d+/) {
64 0         0 return( $self->parse($number) );
65             };
66              
67 1         3 return $self;
68             }
69              
70             # }}}
71             # {{{ parse
72              
73             sub parse :Export {
74 4   50 4 1 2275 my $self = shift // return;
75 4         4 my $number = shift;
76              
77 4         4 my $digits;
78 4         5 my $ret = '';
79              
80 4 100 66     67 croak 'You should specify a number from interval [0, 99_999_999_999]'
      66        
      100        
81             if !defined $number
82             || $number !~ m{\A\d+\z}xms
83             || $number < 0
84             || $number > 99_999_999_999;
85              
86 2 50       7 if( defined($numbers->{$number}) ) {
87 0         0 $ret = $numbers->{$number};
88             }
89             else {
90 2         2 my $ret_array = [];
91              
92 2         8 @{$digits} = reverse( split('', $number) );
  2         5  
93              
94             # tens of billions
95 2 50 33     14 if( defined($digits->[10]) && ($digits->[10] != 0) ) {
    50 33        
96 0         0 my $temp = $self->_formatTens( $digits->[9], $digits->[10] );
97 0         0 unshift @{$ret_array}, "$temp biljoen";
  0         0  
98             }
99             elsif( defined($digits->[9]) && ($digits->[9] != 0) ) {
100 0         0 unshift @{$ret_array}, $self->_formatLarge( $digits->[9], 'biljoen' );
  0         0  
101             };
102              
103             # hundreds of millions
104 2 50 33     6 if( defined($digits->[8]) && ($digits->[8] != 0) ) {
105 0 0 0     0 if( ($digits->[7] == 0) && ($digits->[6] == 0) ) {
106 0         0 unshift @{$ret_array}, $self->_formatLarge( $digits->[8], 'honderd miljoen' );
  0         0  
107             }
108             else {
109 0         0 unshift @{$ret_array}, $self->_formatLarge( $digits->[8], 'honderd' );
  0         0  
110             };
111             };
112              
113             # tens of millions
114 2 50 33     12 if( defined($digits->[7]) && ($digits->[7] != 0) ) {
    50 33        
115 0         0 my $temp = $self->_formatTens( $digits->[6], $digits->[7] );
116 0         0 unshift @{$ret_array}, "$temp miljoen";
  0         0  
117             }
118             elsif( defined($digits->[6]) && ($digits->[6] != 0) ) {
119 0         0 unshift @{$ret_array}, $self->_formatLarge( $digits->[6], 'miljoen' );
  0         0  
120             };
121              
122             # hundreds of thousands
123 2 50 33     14 if( defined($digits->[5]) && ($digits->[5] != 0) ) {
124 0 0 0     0 if( ($digits->[4] == 0) && ($digits->[3] == 0) ) {
125 0         0 unshift @{$ret_array}, $self->_formatLarge( $digits->[5], 'honderd duisend' );
  0         0  
126             }
127             else {
128 0         0 unshift @{$ret_array}, $self->_formatLarge( $digits->[5], 'honderd' );
  0         0  
129             };
130             };
131              
132             # tens of thousands
133 2 100 66     15 if( defined($digits->[4]) && ($digits->[4] != 0) ) {
    50 33        
134 1         6 my $temp = $self->_formatTens( $digits->[3], $digits->[4] );
135 1         2 unshift @{$ret_array}, "$temp duisend";
  1         3  
136             }
137             elsif( defined($digits->[3]) && ($digits->[3] != 0) ) {
138 0         0 unshift @{$ret_array}, $self->_formatLarge( $digits->[3], 'duisend' );
  0         0  
139             };
140              
141             # hundreds
142 2 50 33     12 if( defined($digits->[2]) && ($digits->[2] != 0) ) {
143 2         2 unshift @{$ret_array}, $self->_formatLarge( $digits->[2], 'honderd' );
  2         6  
144             };
145              
146             # tens
147 2         3 unshift @{$ret_array}, $self->_formatTens( $digits->[0], $digits->[1] );
  2         4  
148              
149 2         6 $ret = $self->_sortReturn( $ret_array, $digits );
150              
151             };
152              
153 2         6 return( $ret );
154 1     1   757 }
  1         1  
  1         5  
155              
156             # }}}
157             # {{{ _sortReturn
158              
159             sub _sortReturn {
160 2     2   4 my $self = shift;
161 2         2 my $ret_array = shift;
162 2         2 my $digits = shift;
163              
164 2         2 my $large_nums = 0;
165 2         3 my $ret = '';
166              
167 2         2 my $size = @{$ret_array};
  2         21  
168              
169 2 50       7 if( $size == 1 ) {
    50          
170 0         0 return( $ret_array->[0] );
171             }
172             elsif( $size > 1 ) {
173 2         3 $large_nums = 1;
174             };
175              
176 2         4 for( my $i = $size; $i > 0; $i-- ) {
177 5 100       10 if( defined($ret_array->[$i]) ) {
178 3 100       21 if( $ret_array->[$i] =~ /(miljoen|duisend)/ ) {
179 1         4 $ret .= $ret_array->[$i] .', ';
180             }
181             else {
182 2         6 $ret .= $ret_array->[$i] .' ';
183             };
184             };
185             };
186              
187 2 50 33     19 if( ($digits->[0] == 0) && ($digits->[1] == 0) ) {
    50 33        
      33        
188 0         0 $ret .= ' ' . $ret_array->[0];
189             }
190             elsif( ($digits->[0] == 0) || ($digits->[1] == 0) || ($digits->[1] == 1) ) {
191 0 0       0 if( $large_nums ) {
192 0         0 $ret .= ' en ';
193             };
194 0         0 $ret .= $ret_array->[0];
195             }
196             else {
197 2         3 $ret .= ' ' . $ret_array->[0];
198             };
199              
200 2         23 $ret =~ s/(^ |\s{2,}| $)/ /g;
201              
202 2         6 return( $ret );
203             }
204              
205             # }}}
206             # {{{ _formatTens
207              
208             sub _formatTens {
209 3     3   5 my $self = shift;
210 3         4 my $units = shift;
211 3         3 my $tens = shift;
212              
213             # Both digits are zero
214 3 50 33     7 unless( $units || $tens ) {
215 0         0 return;
216             };
217              
218 3 50 66     14 if( $tens == 0 ) {
    100          
219 0         0 return( $numbers->{$units} );
220             }
221             elsif( ($tens == 1) || ($units == 0) ) {
222 1         2 my $temp = $tens . $units;
223 1         3 return( $numbers->{$temp} );
224             };
225              
226 2         4 my $temp = $tens . 0;
227 2         7 return( "$numbers->{$units} en $numbers->{$temp}" );
228             }
229              
230             # }}}
231             # {{{ _formatLarge
232              
233             sub _formatLarge {
234 2     2   3 my $self = shift;
235 2         3 my $digit = shift;
236 2         2 my $word = shift;
237              
238 2         6 my $ret = "$numbers->{$digit} $word";
239              
240 2         4 return( $ret );
241             }
242              
243             # }}}
244              
245             1;
246              
247             =pod
248              
249             =head1 NAME
250              
251             Lingua::AFR::Numbers
252              
253             =head1 VERSION
254              
255             version 0.1106
256              
257             =head1 DESCRIPTION
258              
259             Converts numeric values into their Afrikaans equivalents.
260              
261             This is PetaMem release.
262              
263             =head1 SYNOPSIS
264              
265             use Lingua::AFR::Numbers;
266              
267             my $numbers = Lingua::AFR::Numbers->new;
268              
269             my $text = $numbers->parse( 123 );
270              
271             # prints 'een honderd, drie en twintig'
272             print $text;
273              
274             =head1 METHODS
275              
276             =over
277              
278             =item new
279              
280             constructor
281              
282             =item parse
283              
284             Convert number to string.
285             Only numbers from interval [0, 99 999 999 999]
286             will be converted.
287              
288             =back
289              
290             =head1 KNOWN BUGS
291              
292             None, but that does not mean there are not any.
293              
294             =head1 AUTHOR
295              
296             Alistair Francis,
297              
298             Maintenance:
299             PetaMem s.r.o.,
300              
301             =head1 LICENSE
302              
303             Perl 5 license.
304              
305             This module was originally released without any known license.
306             PetaMem added standard Perl 5 license as default.
307              
308             =cut