File Coverage

blib/lib/Lingua/MLT/Num2Word.pm
Criterion Covered Total %
statement 74 95 77.8
branch 22 40 55.0
condition 6 15 40.0
subroutine 10 10 100.0
pod 2 2 100.0
total 114 162 70.3


line stmt bran cond sub pod time code
1             # For Emacs: -*- mode:cperl; eval: (folding-mode 1); coding:utf-8 -*-
2             package Lingua::MLT::Num2Word;
3             # ABSTRACT: Number to word conversion in Maltese
4              
5 1     1   128363 use 5.16.0;
  1         4  
6 1     1   4 use utf8;
  1         1  
  1         11  
7 1     1   22 use warnings;
  1         1  
  1         56  
8              
9             # {{{ use block
10              
11 1     1   4 use Carp;
  1         2  
  1         76  
12 1     1   586 use Export::Attrs;
  1         12804  
  1         10  
13 1     1   964 use Readonly;
  1         5570  
  1         599  
14              
15             # }}}
16             # {{{ variable declarations
17              
18             my Readonly::Scalar $COPY = 'Copyright (c) PetaMem, s.r.o. 2002-present';
19             our $VERSION = '0.2603300';
20              
21             # }}}
22              
23             # {{{ num2mlt_cardinal convert number to text
24              
25             sub num2mlt_cardinal :Export {
26 27     27 1 250096 my $positive = shift;
27              
28 27 50 33     480 croak 'You should specify a number from interval [0, 999_999_999]'
      33        
      33        
29             if !defined $positive
30             || $positive !~ m{\A\d+\z}xms
31             || $positive < 0
32             || $positive > 999_999_999;
33              
34             # Units (standalone / counting forms)
35 27         156 my @ones = (
36             "żero", # 0
37             "wieħed", # 1
38             "tnejn", # 2
39             "tlieta", # 3
40             "erbgħa", # 4
41             "ħamsa", # 5
42             "sitta", # 6
43             "sebgħa", # 7
44             "tmienja", # 8
45             "disgħa", # 9
46             );
47              
48             # Tens
49 27         101 my @tens_word = (
50             q{}, # 0 (unused)
51             "għaxra", # 10
52             "għoxrin", # 20
53             "tletin", # 30
54             "erbgħin", # 40
55             "ħamsin", # 50
56             "sittin", # 60
57             "sebgħin", # 70
58             "tmenin", # 80
59             "disgħin", # 90
60             );
61              
62             # Teens (11-19)
63 27         42 my @teens;
64 27         77 $teens[11] = "ħdax";
65 27         78 $teens[12] = "tnax";
66 27         51 $teens[13] = "tlettax";
67 27         47 $teens[14] = "erbatax";
68 27         64 $teens[15] = "ħmistax";
69 27         73 $teens[16] = "sittax";
70 27         44 $teens[17] = "sbatax";
71 27         54 $teens[18] = "tmintax";
72 27         47 $teens[19] = "dsatax";
73              
74             # Connector
75 27         44 my $u = " u ";
76              
77             # Hundred forms — construct-state prefixes for 3-9
78 27         44 my $mija = "mija";
79 27         44 my $mitejn = "mitejn";
80 27         91 my @hund_prefix = (
81             q{}, # 0
82             q{}, # 1
83             q{}, # 2
84             "tliet", # 3
85             "erba'", # 4 erba' mija
86             "ħames", # 5 ħames mija (alt: hames)
87             "sitt", # 6
88             "seba'", # 7
89             "tminn", # 8
90             "disa'", # 9
91             );
92              
93             # Thousand forms — construct-state prefixes for 3-10
94 27         45 my $elf = "elf";
95 27         45 my $elfejn = "elfejn";
96 27         130 my @thou_prefix = (
97             q{}, # 0
98             q{}, # 1
99             q{}, # 2
100             "tlitt", # 3 tlitt elef
101             "erbat", # 4
102             "ħamest", # 5
103             "sitt", # 6
104             "sebat", # 7
105             "tmint", # 8
106             "disat", # 9
107             "għaxart", # 10 għaxart elef
108             );
109 27         81 my $elef = "elef"; # plural form for 3-10
110              
111             # Million forms
112 27         45 my $miljun = "miljun";
113 27         41 my $miljunejn = "żewġ miljuni"; # 2 million
114              
115 27 100       95 return $ones[0] if $positive == 0;
116              
117 25         103 return _convert($positive, \@ones, \@tens_word, \@teens,
118             $u, $mija, $mitejn, \@hund_prefix,
119             $elf, $elfejn, $elef, \@thou_prefix,
120             $miljun, $miljunejn);
121 1     1   10 }
  1         6  
  1         10  
122              
123             # }}}
124             # {{{ _convert recursive number-to-word engine
125              
126             sub _convert {
127 27     27   106 my ($n, $ones, $tens_word, $teens,
128             $u, $mija, $mitejn, $hund_prefix,
129             $elf, $elfejn, $elef, $thou_prefix,
130             $miljun, $miljunejn) = @_;
131              
132 27         98 my @params = ($ones, $tens_word, $teens,
133             $u, $mija, $mitejn, $hund_prefix,
134             $elf, $elfejn, $elef, $thou_prefix,
135             $miljun, $miljunejn);
136              
137 27 50       71 return q{} if $n == 0;
138              
139             # --- Millions ---
140 27 50       62 if ($n >= 1_000_000) {
141 0         0 my $millions = int($n / 1_000_000);
142 0         0 my $remain = $n % 1_000_000;
143              
144 0         0 my $out;
145 0 0       0 if ($millions == 1) {
    0          
146 0         0 $out = $miljun;
147             }
148             elsif ($millions == 2) {
149 0         0 $out = $miljunejn;
150             }
151             else {
152 0         0 $out = _convert($millions, @params) . " $miljun";
153             }
154              
155 0 0       0 if ($remain) {
156 0         0 $out .= "${u}" . _convert($remain, @params);
157             }
158 0         0 return $out;
159             }
160              
161             # --- Thousands ---
162 27 50       64 if ($n >= 1000) {
163 0         0 my $thousands = int($n / 1000);
164 0         0 my $remain = $n % 1000;
165              
166 0         0 my $out;
167 0 0 0     0 if ($thousands == 1) {
    0          
    0          
168 0         0 $out = $elf;
169             }
170             elsif ($thousands == 2) {
171 0         0 $out = $elfejn;
172             }
173             elsif ($thousands >= 3 && $thousands <= 10) {
174 0         0 $out = $thou_prefix->[$thousands] . " $elef";
175             }
176             else {
177             # 11+ thousands: compound number + elf
178 0         0 $out = _convert($thousands, @params) . " $elf";
179             }
180              
181 0 0       0 if ($remain) {
182 0         0 $out .= "${u}" . _convert($remain, @params);
183             }
184 0         0 return $out;
185             }
186              
187             # --- Hundreds ---
188 27 100       62 if ($n >= 100) {
189 6         18 my $hundreds = int($n / 100);
190 6         13 my $remain = $n % 100;
191              
192 6         9 my $out;
193 6 100       22 if ($hundreds == 1) {
    100          
194 2         5 $out = $mija;
195             }
196             elsif ($hundreds == 2) {
197 2         5 $out = $mitejn;
198             }
199             else {
200 2         9 $out = $hund_prefix->[$hundreds] . " $mija";
201             }
202              
203 6 100       16 if ($remain) {
204 2         12 $out .= "${u}" . _convert($remain, @params);
205             }
206 6         44 return $out;
207             }
208              
209             # --- Teens (11-19) ---
210 21 100 100     78 if ($n >= 11 && $n <= 19) {
211 5         35 return $teens->[$n];
212             }
213              
214             # --- Ten ---
215 16 100       38 if ($n == 10) {
216 1         8 return $tens_word->[1];
217             }
218              
219             # --- Tens with units (21-99) ---
220 15 100       33 if ($n >= 20) {
221 9         28 my $ten_idx = int($n / 10);
222 9         18 my $unit = $n % 10;
223              
224 9 100       25 if ($unit) {
225 4         39 return $ones->[$unit] . "${u}" . $tens_word->[$ten_idx];
226             }
227 5         40 return $tens_word->[$ten_idx];
228             }
229              
230             # --- Units (1-9) ---
231 6         42 return $ones->[$n];
232             }
233              
234             # }}}
235              
236             # {{{ capabilities declare supported features
237              
238             sub capabilities {
239             return {
240 1     1 1 418 cardinal => 1,
241             ordinal => 0,
242             };
243             }
244              
245             # }}}
246             1;
247              
248             __END__