File Coverage

blib/lib/Lingua/SLK/Num2Word.pm
Criterion Covered Total %
statement 27 107 25.2
branch 2 72 2.7
condition 3 42 7.1
subroutine 8 10 80.0
pod 3 3 100.0
total 43 234 18.3


line stmt bran cond sub pod time code
1             # For Emacs: -*- mode:cperl; mode:folding; coding:utf-8; -*-
2              
3             package Lingua::SLK::Num2Word;
4             # ABSTRACT: Number to word conversion in Slovak
5              
6 1     1   131422 use 5.16.0;
  1         4  
7 1     1   9 use utf8;
  1         2  
  1         16  
8 1     1   37 use warnings;
  1         4  
  1         92  
9              
10             # {{{ use block
11              
12 1     1   7 use Carp;
  1         2  
  1         110  
13 1     1   700 use Export::Attrs;
  1         13752  
  1         9  
14              
15             # }}}
16             # {{{ var block
17             our $VERSION = '0.2603300';
18             my %token1 = qw( 0 nula 1 jedna 2 dva
19             3 tri 4 štyri 5 päť
20             6 šesť 7 sedem 8 osem
21             9 deväť 10 desať 11 jedenásť
22             12 dvanásť 13 trinásť 14 štrnásť
23             15 pätnásť 16 šestnásť 17 sedemnásť
24             18 osemnásť 19 devätnásť
25             );
26             my %token2 = qw( 20 dvadsať 30 tridsať 40 štyridsať
27             50 päťdesiat 60 šesťdesiat 70 sedemdesiat
28             80 osemdesiat 90 deväťdesiat
29             );
30             my %token3 = ( 100, 'sto', 200, 'dvesto', 300, 'tristo',
31             400, 'štyristo', 500, 'päťsto', 600, 'šesťsto',
32             700, 'sedemsto', 800, 'osemsto', 900, 'deväťsto'
33             );
34              
35             # }}}
36              
37             # {{{ num2slk_cardinal number to string conversion
38              
39             sub num2slk_cardinal :Export {
40 2     2 1 225750 my $result = '';
41 2         6 my $number = shift;
42              
43 2 50 33     34 croak 'You should specify a number from interval [0, 999_999_999]'
      33        
      33        
44             if !defined $number
45             || $number !~ m{\A\d+\z}xms
46             || $number < 0
47             || $number > 999_999_999;
48              
49 2         5 my $reminder = 0;
50              
51 2 50       7 if ($number < 20) {
    0          
    0          
    0          
    0          
52 2         8 $result = $token1{$number};
53             }
54             elsif ($number < 100) {
55 0         0 $reminder = $number % 10;
56 0 0       0 if ($reminder == 0) {
57 0         0 $result = $token2{$number};
58             }
59             else {
60 0         0 $result = $token2{$number - $reminder}.' '.num2slk_cardinal($reminder);
61             }
62             }
63             elsif ($number < 1_000) {
64 0         0 $reminder = $number % 100;
65 0 0       0 if ($reminder != 0) {
66 0         0 $result = $token3{$number - $reminder}.' '.num2slk_cardinal($reminder);
67             }
68             else {
69 0         0 $result = $token3{$number};
70             }
71             }
72             elsif ($number < 1_000_000) {
73 0         0 $reminder = $number % 1_000;
74 0 0       0 my $tmp1 = ($reminder != 0) ? ' '.num2slk_cardinal($reminder) : '';
75 0         0 my $tmp2 = substr($number, 0, length($number)-3);
76 0         0 my $tmp3 = $tmp2 % 100;
77 0         0 my $tmp4 = $tmp2 % 10;
78              
79 0 0 0     0 if ($tmp3 < 9 || $tmp3 > 20) {
80 0 0 0     0 if ($tmp4 == 1 && $tmp2 == 1) {
    0 0        
    0          
81 0         0 $tmp2 = 'tisíc';
82             }
83             elsif ($tmp4 == 1) {
84 0         0 $tmp2 = num2slk_cardinal($tmp2 - $tmp4).' jeden tisíc';
85             }
86             elsif($tmp4 > 1 && $tmp4 < 5) {
87 0         0 $tmp2 = num2slk_cardinal($tmp2).' tisíce';
88             }
89             else {
90 0         0 $tmp2 = num2slk_cardinal($tmp2).' tisíc';
91             }
92             }
93             else {
94 0         0 $tmp2 = num2slk_cardinal($tmp2).' tisíc';
95             }
96 0         0 $result = $tmp2.$tmp1;
97             }
98             elsif ($number < 1_000_000_000) {
99 0         0 $reminder = $number % 1_000_000;
100 0 0       0 my $tmp1 = ($reminder != 0) ? ' '.num2slk_cardinal($reminder) : '';
101 0         0 my $tmp2 = substr($number, 0, length($number)-6);
102 0         0 my $tmp3 = $tmp2 % 100;
103 0         0 my $tmp4 = $tmp2 % 10;
104              
105 0 0 0     0 if ($tmp3 < 9 || $tmp3 > 20) {
106 0 0 0     0 if ($tmp4 == 1 && $tmp2 == 1) {
    0 0        
    0          
107 0         0 $tmp2 = 'milión';
108             }
109             elsif ($tmp4 == 1) {
110 0         0 $tmp2 = num2slk_cardinal($tmp2 - $tmp4).' jeden milión';
111             }
112             elsif($tmp4 > 1 && $tmp4 < 5) {
113 0         0 $tmp2 = num2slk_cardinal($tmp2).' milióny';
114             }
115             else {
116 0         0 $tmp2 = num2slk_cardinal($tmp2).' miliónov';
117             }
118             }
119             else {
120 0         0 $tmp2 = num2slk_cardinal($tmp2).' miliónov';
121             }
122              
123 0         0 $result = $tmp2.$tmp1;
124             }
125              
126 2         7 return $result;
127 1     1   915 }
  1         3  
  1         8  
128              
129             # }}}
130              
131             # {{{ num2slk_ordinal number to ordinal string conversion
132              
133             sub num2slk_ordinal :Export {
134 0     0 1   my $number = shift;
135              
136 0 0 0       croak 'You should specify a number from interval [0, 999_999_999]'
      0        
      0        
137             if !defined $number
138             || $number !~ m{\A\d+\z}xms
139             || $number < 0
140             || $number > 999_999_999;
141              
142             # Irregular ordinals 0-10
143 0           my %irregular = (
144             0 => 'nultý',
145             1 => 'prvý',
146             2 => 'druhý',
147             3 => 'tretí',
148             4 => 'štvrtý',
149             5 => 'piaty',
150             6 => 'šiesty',
151             7 => 'siedmy',
152             8 => 'ôsmy',
153             9 => 'deviaty',
154             10 => 'desiaty',
155             );
156              
157 0 0         return $irregular{$number} if exists $irregular{$number};
158              
159             # Irregular teens 11-19
160 0           my %teens = (
161             11 => 'jedenásty',
162             12 => 'dvanásty',
163             13 => 'trinásty',
164             14 => 'štrnásty',
165             15 => 'pätnásty',
166             16 => 'šestnásty',
167             17 => 'sedemnásty',
168             18 => 'osemnásty',
169             19 => 'devätnásty',
170             );
171              
172 0 0         return $teens{$number} if exists $teens{$number};
173              
174             # Tens ordinals
175 0           my %tens_ord = (
176             20 => 'dvadsiaty',
177             30 => 'tridsiaty',
178             40 => 'štyridsiaty',
179             50 => 'päťdesiaty',
180             60 => 'šesťdesiaty',
181             70 => 'sedemdesiaty',
182             80 => 'osemdesiaty',
183             90 => 'deväťdesiaty',
184             );
185              
186             # Hundreds ordinals
187 0           my %hundreds_ord = (
188             100 => 'stý',
189             200 => 'dvojstý',
190             300 => 'trojstý',
191             400 => 'štvorsťý',
192             500 => 'päťstý',
193             600 => 'šesťstý',
194             700 => 'sedemstý',
195             800 => 'osemstý',
196             900 => 'deväťstý',
197             );
198              
199             # For numbers >= 1_000_000
200 0 0         if ($number >= 1_000_000) {
201 0           my $millions = int($number / 1_000_000);
202 0           my $remainder = $number % 1_000_000;
203 0 0         if ($remainder == 0) {
204 0           my $prefix = num2slk_cardinal($millions);
205 0 0         if ($millions == 1) {
206 0           return 'milióntý';
207             }
208 0           return $prefix . ' milióntý';
209             }
210 0           my $prefix = num2slk_cardinal($millions);
211 0 0 0       my $mil_word = ($millions == 1) ? 'milión' :
    0          
212             ($millions >= 2 && $millions <= 4) ? 'milióny' : 'miliónov';
213 0 0         $mil_word = 'milión' if $millions == 1;
214 0           return $prefix . ' ' . $mil_word . ' ' . num2slk_ordinal($remainder);
215             }
216              
217 0 0         if ($number >= 1_000) {
218 0           my $thousands = int($number / 1_000);
219 0           my $remainder = $number % 1_000;
220 0 0         if ($remainder == 0) {
221 0 0         if ($thousands == 1) {
222 0           return 'tisíci';
223             }
224 0           return num2slk_cardinal($thousands) . ' tisíci';
225             }
226 0           my $thou_cardinal;
227 0 0         if ($thousands == 1) {
228 0           $thou_cardinal = 'tisíc';
229             }
230             else {
231 0 0 0       $thou_cardinal = num2slk_cardinal($thousands) .
232             (($thousands % 100 >= 2 && $thousands % 100 <= 4 &&
233             !($thousands % 100 >= 12 && $thousands % 100 <= 14))
234             ? ' tisíce' : ' tisíc');
235             }
236 0           return $thou_cardinal . ' ' . num2slk_ordinal($remainder);
237             }
238              
239 0 0         if ($number >= 100) {
240 0           my $h = int($number / 100) * 100;
241 0           my $remainder = $number % 100;
242 0 0         if ($remainder == 0) {
243 0           return $hundreds_ord{$h};
244             }
245 0           return $token3{$h} . ' ' . num2slk_ordinal($remainder);
246             }
247              
248             # 20-99 compound
249 0 0         if ($number >= 20) {
250 0           my $t = int($number / 10) * 10;
251 0           my $remainder = $number % 10;
252 0 0         if ($remainder == 0) {
253 0           return $tens_ord{$t};
254             }
255 0           return $tens_ord{$t} . ' ' . $irregular{$remainder};
256             }
257              
258             # Should not reach here
259 0           return;
260 1     1   1057 }
  1         2  
  1         5  
261              
262             # }}}
263              
264             # {{{ capabilities declare supported features
265              
266             sub capabilities {
267             return {
268 0     0 1   cardinal => 1,
269             ordinal => 1,
270             };
271             }
272              
273             # }}}
274             1;
275              
276             __END__