File Coverage

blib/lib/Lingua/AFR/Numbers.pm
Criterion Covered Total %
statement 79 110 71.8
branch 26 48 54.1
condition 25 61 40.9
subroutine 11 11 100.0
pod 2 2 100.0
total 143 232 61.6


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