File Coverage

blib/lib/Lingua/RU/Numeral.pm
Criterion Covered Total %
statement 163 183 89.0
branch 104 146 71.2
condition 57 79 72.1
subroutine 14 14 100.0
pod 1 1 100.0
total 339 423 80.1


line stmt bran cond sub pod time code
1             package Lingua::RU::Numeral;
2              
3 1     1   72887 use 5.010;
  1         13  
4 1     1   14 use strict;
  1         4  
  1         33  
5 1     1   6 use warnings;
  1         1  
  1         25  
6 1     1   4 use utf8;
  1         3  
  1         13  
7 1     1   623 use open qw(:std :utf8);
  1         1216  
  1         9  
8              
9             require Exporter;
10              
11             our @ISA = qw(Exporter);
12              
13             our %EXPORT_TAGS = ( 'all' => [ qw(
14             num2cardinal
15             ) ] );
16              
17             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
18              
19             our @EXPORT = qw( );
20              
21             our $VERSION = '0.031';
22              
23              
24             ########################
25             # num2cardinal INPUT #
26             ########################
27             # SCALAR:
28             #~~~~~~~~
29             # 0. $number -- число для обработки, e.g: 1234567890
30              
31             #~~~~~~~~~~~
32             # HASH keys:
33             #~~~~~~~~~~~
34             # 1. 'gender' key -- род:
35             # (default) m = masculine (Мужской)
36             # f = feminine (Женский)
37             # n = neuter (Средний)
38              
39             # 2. 'case' key -- падеж: числительное: Количественное | Порядковое
40             # (default) n = nominative - Именительный: есть кто? что? | какой?
41             # g = genitive - Родительный: нет кого? чего? | какого?
42             # d = dative - Дательный: рад кому? чему? | какому?
43             # a = accusative - Винительный: вижу кого? что? | какой?
44             # i = instrumental - Творительный: оплачу кем? чем? | каким?
45             # p = prepositional - Предложный: думаю о ком? о чём?| о каком?
46              
47             # 3. 'multi' key -- единственное(undef|0|'singular') или множественное число (>0|'plural'). By default, 'singular'
48             # 4. 'object' key -- inanimate(неодушевлённый) или animate(одушевлённый) предмет. By default, 'inanimate'
49             # 5. 'prolog' key -- Preposition (prologue) of numeral
50             # 6. 'epilog' key -- Epilogue of numeral
51             # 7. 'alt' key
52             # 8. 'ucfirst' key
53              
54             sub num2cardinal {
55 1498     1498 1 261047 my( $number, %cfg ) = @_;
56 1498         4770 $number =~s/\D+//g;
57              
58             # extreme index for:
59 1     1   286 use constant VXN => 5; # numbers from 5 to <1000
  1         2  
  1         109  
60 1     1   6 use constant THS => 6; # тысячи
  1         2  
  1         48  
61 1     1   6 use constant MMT => 7; # миллионы | миллиарды | триллионы
  1         1  
  1         4981  
62              
63 1498   100     4187 my $gender = $cfg{'gender'} || 'masculine';
64 1498 50       8855 $gender = $gender=~/^\s*(m|f|n)/i ? @{{'m'=>'masculine', 'f'=>'feminine', 'n'=>'neuter'}}{lc $1} : 'masculine';
  1498         5842  
65              
66 1498   100     5118 my $case = $cfg{'case'} || 'nominative';
67 1498 50       5402 $case = $case=~/^\s*([ngdaip])/i ? $1 : 'n';
68              
69 1498   100     4153 my $multi = $cfg{'multi'} || 'singular';
70 1498 100       4277 $multi = $multi=~/^\s*[p1-9]/i ? 'plural' : 'singular';
71              
72 1498   100     3626 my $object = $cfg{'object'} || 'inanimate';
73 1498 100       3288 $object = $object=~/^\s*[a1-9]/i ? 'animate' : 'inanimate';
74              
75             # Preposition (prologue) of numeral
76 1498         3887 my $prolog = &_ref_prolog( \%cfg );
77              
78             # Epilogue of numeral
79 1498         4136 my $epilog = &_ref_epilog( $case, $multi, \%cfg, \$object, \$gender );
80              
81 1498 100       3242 unless( $number ) {
82 42 100       139 my $oy = exists( $cfg{'alt'}{0} ) ? 'у' : 'о';
83             my $zero = ($case =~/^a/i && $object =~/^animate/i ) ?
84             "н${oy}ля" :
85 42 100 100     213 @{{'n'=>"н${oy}ль", 'g'=>"н${oy}ля", 'd'=>"н${oy}лю", 'a'=>"н${oy}ль", 'i'=>"н${oy}лём", 'p'=>"н${oy}ле"}}{ $case };
  39         378  
86              
87             # Add the numeral
88 42         155 my @s = ( $zero );
89              
90             # Add the prolog to numeral
91 42         137 my $i = &_add_prolog( $prolog, \@s );
92              
93             # Add the epilog to numeral
94 42 100 66     230 push @s, $epilog->{'root'}.$epilog->{'ends'}[0] if $epilog && exists( $epilog->{'root'} );
95              
96 1 100   1   9 $s[$i] = ucfirst $s[$i] if exists $cfg{'ucfirst'};
  1         2  
  1         13  
  42         164  
97              
98 42         32460 return join ' ', @s;
99             }
100              
101 1456 100       3262 return "$number > 999_999_999_999_999 !" if length( $number ) > 15;
102              
103             # To get cardinal form DB (БД словоформ числительных)
104 1455         3848 my( $bsw, $plural, $Power ) = &_cardinal_form_db( $case, $multi, $object, $gender );
105              
106 1455         3163 my @Dcml = @{ $bsw->{'dcml'} };
  1455         4662  
107 1455         2190 my @Cent = @{ $bsw->{'cent'} };
  1455         3575  
108              
109 1455         3662 my @tmEnd; # for ends --- для окончаний 'тысяч','миллион','миллиард','триллион'
110             my @words; # for ends --- для искомой структуры слов числительных
111 1455         0 my @s; # Resulting string --- Результирующая строка
112              
113 1455         3616 while( length $number ) {
114              
115 3386 100       8155 if( $number =~/^.$/ ) { # 0..9
116 529 100       1133 last unless $number;
117              
118             push @s, ( $multi =~/^plural/i && $number == 1 ) ?
119             $plural->{1} :
120 334 100 66     2112 $bsw->{ $gender }{ ($case =~/^a/i && $object =~/^animate/i) ? 'animate' : 'unit'}[ $number ];
    100 100        
121              
122             # Add epilog to numeral
123 334 100 66     1292 if( $epilog && exists( $epilog->{'root'} ) ) {
124 92 100       350 push @s, $epilog->{'root'}.$epilog->{'ends'}[ $number < 5 ? $number : VXN ];
125 92         187 $epilog = {}; # epilog END
126             }
127              
128 334         648 last;
129             }
130              
131 2857         6198 my $i = int length( $number ) / 3;
132              
133 2857 100       6218 if( $i < 2 ) { # $number = 10 .. 99_999
134             # Женский род, (т.к. может быть 'тысяч')
135 1127         1456 @words = @{ $bsw->{'feminine'}{'unit'} };
  1127         4396  
136 1127         1666 @tmEnd = @{ $bsw->{'eT'} }; # окончания для 'тысяч'
  1127         2994  
137             }
138             else { # Для >=100_000, 'миллион','миллиард','триллион'
139             # Мужской род
140 1730         2422 @words = @{ $bsw->{'masculine'}{'unit'} };
  1730         7057  
141 1730         2644 @tmEnd = @{ $bsw->{'eMT'} }; # окончания
  1730         4918  
142             }
143              
144 2857 100       6617 if( length( $number )%3 == 0 ) { # Сотни: 100 .. 999, 100_xxx .. 999_xxx, 100_xxx_xxx .. 999_xxx_xxx, etc.
145 694         2304 $number =~s/^\d//;
146 694 100       2425 push @s, $Cent[$&] if $&;
147 694         1602 next;
148             }
149              
150 2163 100       4150 if( length( $number )%3 == 2 ) { # Десятки: 10 .. 99, 10_xxx .. 99_xxx, 10_xxx_xxx .. 99_xxx_xxx, etc.
151 1006 100       2280 if( $number =~/^1/ ) { # 10... 19...
152 181         587 $number =~s/^\d\d//;
153 181 50       969 push @s, $words[$&] if $&;
154              
155 181 100       548 push @s, $Power->[$i].$tmEnd[0] if length $Power->[$i];
156             }
157             else { # 20... 99...
158 825         2545 $number =~s/^\d//;
159 825 100       2487 push @s, $Dcml[$&] if $&;
160             }
161              
162 1006         2301 next;
163             }
164              
165 1157 50       2316 if( length( $number )%3 == 1 ) { # Единицы: 0..., 1,..., 9...
166 1157         3832 $number =~s/^\d//;
167 1157         2673 my $d = $&;
168 1157 100       2258 if( $d ) {
169 790 100 66     3479 push @s, ( $multi =~/^plural/i && $d == 1 ) ? $plural->{1} : $words[$d];
170             }
171              
172 1157 100       3844 if( $s[-1] !~/^(?:м|трил)/ ) { # ещё не добавлено миллион | миллиард | триллион
173             my $w = ( $multi =~/^plural/i && $d == 1 ) ?
174 1028 100 66     3150 $plural->{ $i < 2 ? 'eT' : 'eMT'} :
    100          
175             $tmEnd[ $d ];
176              
177 1028         3185 push @s, $Power->[$i].$w;
178             }
179              
180 1157 100       4407 last if $number =~/^0+$/;
181             }
182             }
183              
184             # Add prolog to numeral
185 1455         3598 my $i = &_add_prolog( $prolog, \@s );
186              
187 1455 100       3811 $s[$i] = ucfirst $s[$i] if exists $cfg{'ucfirst'};
188              
189             # Add epilog to numeral
190 1455 100 66     5183 if( $epilog && exists( $epilog->{'root'} ) ) {
191              
192             # Choice between
193 212 100       964 my $i = $s[-1] =~/^ты/ ? THS : # тысяча
    100          
194             $s[-1] =~/^(?:м|трил)/ ? MMT : # миллион | миллиард | триллион
195             VXN; # other
196              
197 212         587 push @s, $epilog->{'root'}.$epilog->{'ends'}[ $i ];
198             }
199              
200              
201 1455         26266 return join ' ', @s;
202             }
203              
204              
205             sub _cardinal_form_db {
206 1455     1455   3366 my( $case, $multi, $object, $gender ) = @_;
207              
208             # База словоформ числительных (singular -- единственно число, default)
209 1455         83987 my %bsw = (
210             'n' => { # nominative (Именительный падеж) кто? что?, default
211             'masculine' => { # Мужской род, default
212             'unit' => [ # 0..19
213             '','один','два','три','четыре','пять','шесть','семь','восемь','девять','десять',
214             'одиннадцать','двенадцать','тринадцать','четырнадцать','пятнадцать','шестнадцать','семнадцать','восемнадцать','девятнадцать'
215             ],
216             },
217             'feminine' => { # Женский род
218             'unit' => [ # 0..19
219             '','одна','две' # остальные как для Мужского рода
220             ],
221             },
222             'neuter' => { # Средний род
223             'unit' => [ # 0..19
224             '','одно' # остальные как для Мужского рода
225             ],
226             },
227             'dcml' => [ # 20, 30,...,90
228             '','','двадцать','тридцать','сорок','пятьдесят','шестьдесят','семьдесят','восемьдесят','девяносто'
229             ],
230             'cent' => [ # 100..900
231             '','сто','двести','триста','четыреста','пятьсот','шестьсот','семьсот','восемьсот','девятьсот'
232             ],
233             'eT' => [ # окончания для 'тысяч' (0й - для 10..19; десятков: 10,20,...,90 и сотен: 100,200,...,900)
234             '','а', ('и') x 3, ('') x 5
235             ],
236             'eMT' => [ # окончания для 'миллион','миллиард','триллион' (0й - для 10..19; десятков: 10,20,...,90 и сотен: 100,200,...,900)
237             'ов','', ('а') x 3, ('ов') x 5
238             ],
239             }, #--------------------------------------------
240             'g' => { # genitive (Родительный падеж): кого? чего?
241             'masculine' => { # Мужской род, default
242             'unit' => [ # 0..19
243             '','одного','двух','трёх','четырёх','пяти','шести','семи','восьми','девяти','десяти',
244             'одиннадцати','двенадцати','тринадцати','четырнадцати','пятнадцати','шестнадцати','семнадцати','восемнадцати','девятнадцати'
245             ],
246             },
247             'feminine' => { # Женский род
248             'unit' => [ # 0..19
249             '','одной' # остальные как для Мужского рода
250             ],
251             },
252             'neuter' => { # Средний род
253             'unit' => [ # 0..19
254             '' # всё как для Мужского рода
255             ],
256             },
257             'dcml' => [ # 20, 30,...,90
258             '','','двадцати','тридцати','сорока','пятидесяти','шестидесяти','семидесяти','восьмидесяти','девяноста'
259             ],
260             'cent' => [ # 100..900
261             '','ста','двухсот','трёхсот','четырёхсот','пятисот','шестисот','семисот','восьмисот','девятисот'
262             ],
263             'eT' => [ # окончания для 'тысяч'
264             '','и', ('') x 8
265             ],
266             'eMT' => [ # окончания для 'миллион','миллиард','триллион'
267             'ов','а', ('ов') x 8
268             ],
269             }, #--------------------------------------------
270             'd' => { # dative (Дательный падеж): кому? чему?
271             'masculine' => { # Мужской род, default
272             'unit' => [ # 0..19
273             '','одному','двум','трём','четырём','пяти','шести','семи','восьми','девяти','десяти',
274             'одиннадцати','двенадцати','тринадцати','четырнадцати','пятнадцати','шестнадцати','семнадцати','восемнадцати','девятнадцати'
275             ],
276             },
277             'feminine' => { # Женский род
278             'unit' => [ # 0..19
279             '','одной' # остальные как для Мужского рода
280             ],
281             },
282             'neuter' => { # Средний род
283             'unit' => [ # 0..19
284             '' # всё как для Мужского рода
285             ],
286             },
287             'dcml' => [ # 20, 30,...,90 : как Родительный падеж
288             '','','двадцати','тридцати','сорока','пятидесяти','шестидесяти','семидесяти','восьмидесяти','девяноста'
289             ],
290             'cent' => [ # 100..900
291             '','ста','двумстам','трёхстам','четырёхстам','пятистам','шестистам','семистам','восьмистам','девятистам'
292             ],
293             'eT' => [ # окончания для 'тысяч'
294             'ам','е', ('ам') x 8
295             ],
296             'eMT' => [ # окончания для 'миллион','миллиард','триллион'
297             'ам','у', ('ам') x 8
298             ],
299             }, #--------------------------------------------
300             'a' => { # accusative (Винительный падеж): animate (одушевлённый объект): кого? | inanimate (неодушевлённый объект): что?
301             'masculine' => { # Мужской род, inanimate default
302             'unit' => [ # 0..19 : неодушевлённый объект, как Именительный падеж
303             '','один','два','три','четыре','пять','шесть','семь','восемь','девять','десять',
304             'одиннадцать','двенадцать','тринадцать','четырнадцать','пятнадцать','шестнадцать','семнадцать','восемнадцать','девятнадцать'
305             ],
306             'animate' => [ # 0..19 : одушевлённый объект, как Родительный падеж (0..4), Именительный падеж (5..19)
307             '','одного','двух','трёх','четырёх', 'пять','шесть','семь','восемь','девять','десять',
308             'одиннадцать','двенадцать','тринадцать','четырнадцать','пятнадцать','шестнадцать','семнадцать','восемнадцать','девятнадцать'
309             ],
310             },
311             'feminine' => { # Женский род
312             'unit' => [ # 0..19 : неодушевлённый объект
313             '','одну','две' # остальные как для Мужского рода
314             ],
315             'animate' => [ # 0..19 : одушевлённый объект
316             '','одну' # остальные как для одушевлённого Мужского рода
317             ],
318             },
319             'neuter' => { # Средний род
320             'unit' => [ # 0..19 : неодушевлённый объект
321             '','одно' # остальные как для Мужского рода
322             ],
323             'animate' => [ # 0..19 : одушевлённый объект
324             '','одно','два' # остальные как для одушевлённого Мужского рода
325             ],
326             },
327             'dcml' => [ # 20, 30,...,90
328             '','','двадцать','тридцать','сорок','пятьдесят','шестьдесят','семьдесят','восемьдесят','девяносто'
329             ],
330             'cent' => [ # 100..900
331             '','сто','двести','триста','четыреста','пятьсот','шестьсот','семьсот','восемьсот','девятьсот'
332             ],
333             'eT' => [ # окончания для 'тысяч' (0й - для 10..19 и десятков: 10,20,...,90)
334             '','у', ('и') x 3, ('') x 5
335             ],
336             'eMT' => [ # окончания для 'миллион','миллиард','триллион' (0й - для 10..19 и десятков: 10,20,...,90)
337             'ов','', ('а') x 3, ('ов') x 5
338             ],
339             }, #--------------------------------------------
340             'i' => { # instrumental (Творительный падеж) : кем? чем?
341             'masculine' => { # Мужской род, default
342             'unit' => [ # 0..19
343             '','одним','двумя','тремя','четырьмя','пятью','шестью','семью','восьмью','девятью','десятью',
344             'одиннадцатью','двенадцатью','тринадцатью','четырнадцатью','пятнадцатью','шестнадцатью','семнадцатью','восемнадцатью','девятнадцатью'
345             ],
346             },
347             'feminine' => { # Женский род
348             'unit' => [ # 0..19
349             '','одной' # остальные как для Мужского рода
350             ],
351             'alternative' => [ # 0..19
352             '','одною' # остальные как для Мужского рода
353             ],
354             },
355             'dcml' => [ # 20, 30,...,90
356             '','','двадцатью','тридцатью','сорока','пятьюдесятью','шестьюдесятью','семьюдесятью','восьмьюдесятью','девяноста'
357             ],
358             'cent' => [ # 100..900
359             '','ста','двумястами','тремястами','четырьмястами','пятьюстами','шестьюстами','семьюстами','восьмьюстами','девятьюстами'
360             ],
361             'eT' => [ # окончания для 'тысяч'
362             'ами','ей', ('ами') x 8
363             # 'ами','ью', ('ами') x 8
364             ],
365             'eMT' => [ # окончания для 'миллион','миллиард','триллион'
366             'ами','ом', ('ами') x 8
367             ],
368             }, #--------------------------------------------
369             'p' => { # prepositional (Предложный падеж) : о ком? о чём?
370             'masculine' => { # Мужской род, default
371             'unit' => [ # 0..19
372             '','одном','двух','трёх','четырёх','пяти','шести','семи','восьми','девяти','десяти',
373             'одиннадцати','двенадцати','тринадцати','четырнадцати','пятнадцати','шестнадцати','семнадцати','восемнадцати','девятнадцати'
374             ],
375             },
376             'feminine' => { # Женский род
377             'unit' => [ # 0..19
378             '','одной' # остальные как для Мужского рода
379             ],
380             },
381             'dcml' => [ # 20, 30,...,90
382             '','','двадцати','тридцати','сорока','пятидесяти','шестидесяти','семидесяти','восьмидесяти','девяноста'
383             ],
384             'cent' => [ # 100..900
385             '','ста','двухстах','трёхстах','четырёхстах','пятистах','шестистах','семистах','восьмистах','девятистах'
386             ],
387             'eT' => [ # окончания для 'тысяч'
388             'ах','е', ('ах') x 8
389             ],
390             'eMT' => [ # окончания для 'миллион','миллиард','триллион'
391             'ах','е', ('ах') x 8
392             ],
393             },
394             );
395              
396 1455         12565 my %plural = ( # множественное число
397             'n' => { # nominative (Именительный падеж)
398             1 => 'одни',
399             'eT' => 'и', # окончание для 'тысяч'
400             'eMT' => 'ы', # окончания для 'миллион','миллиард','триллион'
401             },
402             'g' => { # genitive (Родительный падеж)
403             1 => 'одних',
404             'eT' => '',
405             'eMT' => 'ов',
406             },
407             'd' => { # dative (Дательный падеж)
408             1 => 'одним',
409             'eT' => 'ам',
410             'eMT' => 'ам',
411             },
412             'a' => { # accusative (Винительный падеж):
413             1 => 'одни', # inanimate(неодушевлённый) объект. For animate(одушевлённый) -- see below
414             'eT' => 'и',
415             'eMT' => 'ы',
416             },
417             'i' => {# instrumental (Творительный падеж)
418             1 => 'одними',
419             'eT' => 'ами',
420             'eMT' => 'ами',
421             },
422             'p' => { # prepositional (Предложный падеж)
423             1 => 'одних',
424             'eT' => 'ах',
425             'eMT' => 'ах',
426             },
427             );
428              
429             # Дозаполняем необходимые структуры, кроме 'masculine'
430 1455         2947 my %gg = ('masculine' => undef );
431 1455         2692 for my $g ('feminine', $gender ) {
432 2910 100       6767 next if exists $gg{ $g };
433 1666         2927 $gg{ $g } = undef;
434              
435 1666         3356 for(0..19) {
436             # если НЕ определено
437 33320   100     122297 $bsw{ $case }{ $g }{'unit'}[$_] //= $bsw{ $case }{'masculine'}{'unit'}[$_];
438              
439 33320 100 66     92379 $bsw{'a'}{ $g }{'animate'}[$_] //= $bsw{'a'}{'masculine'}{'animate'}[$_]
      100        
440             if $case =~/^a/i && $object =~/^animate/i;
441             }
442             }
443              
444             # Корректируем окончания для accusative(Винительный падеж) + одушевлённый объект + множественное число
445 1455 100 100     4214 if( $case =~/^a/i && $object =~/^animate/i && $multi =~/^plural/i ) {
      100        
446 5         12 $plural{'a'}{1} = 'одних';
447 5         9 $plural{'a'}{'eT'} = '';
448 5         8 $plural{'a'}{'eMT'} = 'ов';
449             }
450              
451 1455         2099 return( \%{ $bsw{ $case } }, \%{ $plural{ $case } }, ['','тысяч','миллион','миллиард','триллион'] );
  1455         3150  
  1455         34274  
452             }
453              
454              
455             # Add prolog to numeral, e.g. ['с','со=с',...]
456             sub _add_prolog {
457 1497     1497   2951 my( $prolog, $s ) = @_;
458 1497 100 66     5715 return 0 if ! @$prolog or ! @$s or (~~@$prolog < 2 and ( ! defined( $prolog->[0] ) or ! length( $prolog->[0] ) ) );
      33        
      66        
      66        
459              
460 155         295 my $p = shift @$prolog; # get 1st element (e.g. 'с') for any numeral
461              
462 155         262 my $i = 0;
463 155         314 for( @$prolog ) { # ['со=с',...]
464 131 50       259 next unless $_;
465              
466 131         594 my( $k, $m ) = split '=';
467 131 50 33     468 next unless $k && $m;
468              
469 131 100       742 if( $s->[0] =~/^$m/ ) {
470 43         112 unshift @$s, $k;
471 43         75 undef $p;
472 43         66 $i = 1;
473 43         97 last;
474             }
475             }
476              
477 155 100 66     615 if( defined( $p ) && length $p ) {
478 112         273 unshift @$s, $p;
479 112         179 $i = 1;
480             }
481              
482 155         333 return $i;
483             }
484              
485              
486             sub _ref_prolog {
487 1498     1498   2646 my( $cfg ) = @_;
488 1498   100     3820 my $prolog = $cfg->{'prolog'} // return [ ];
489              
490 1192 100       3209 if( ref($prolog) eq 'ARRAY') {
491 1062 100       4566 return ~~@$prolog ? [ @$prolog ] : [ ];
492             }
493              
494 130 50       268 if( ref($prolog) eq 'HASH') {
495 0         0 my @p;
496 0         0 for my $k (sort keys %$prolog ) {
497 0 0 0     0 if( defined( $prolog->{$k} ) && length( $prolog->{$k} ) ) {
498 0         0 push @p, "$k=". $prolog->{$k};
499             }
500             else {
501 0         0 unshift @p, $k;
502             }
503             }
504 0 0       0 return ~~@p ? \@p : [ ];
505             }
506              
507 130 50       328 if( ref(\$prolog) eq 'SCALAR') {
508 130 100       608 return ['о','об=од'] if $prolog =~/^[oOоО]$/;
509 65 50       294 return ['с','со=с'] if $prolog =~/^[cCсС]$/;
510 0 0       0 return ['в'] if $prolog =~/^[BвВ]$/;
511             }
512              
513 0         0 return [ ];
514             }
515              
516              
517             sub _ref_epilog {
518 1498     1498   3508 my( $case, $multi, $cfg, $object, $gender ) = @_;
519 1498 100       3347 my $epilog = $cfg->{'epilog'} or return {};
520              
521 1421 100 66     6692 if( ref(\$epilog) eq 'SCALAR') {
    100 66        
522 309         462 my %eRef;
523              
524 309 100       1167 if( $epilog =~/^(?:RUB|643)$/ ) { # Российский рубль
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
525 149         2290 %eRef = (
526             'object' => 'inanimate',
527             'gender' => 'masculine',
528             'root' => 'рубл',
529             'ends' => {
530             'n' => ['ей','ь', ('я') x 3, ('ей') x 3 ], # nominative - Именительный
531             'g' => ['ей','я', ('ей') x 6 ], # genitive - Родительный
532             'd' => ['ям','ю', ('ям') x 4, ('ей') x 2 ], # dative - Дательный
533             'a' => ['ей','ь', ('я') x 3, ('ей') x 3 ], # accusative - Винительный
534             'i' => ['ей','ём', ('ями') x 4, ('ей') x 2 ], # instrumental - Творительный
535             'p' => ['ей','е', ('ях') x 4, ('ей') x 2 ], # prepositional - Предложный
536             },
537             'plural' => {'n'=>'и', 'g'=>'ей', 'd'=>'ям', 'a'=>'и', 'i'=>'ями', 'p'=>'ях'},
538             );
539              
540             }
541             elsif( $epilog =~/^(?:rub|\-643)$/) { # Российская копейка
542 160         2219 %eRef = (
543             'object' => 'inanimate',
544             'gender' => 'feminine',
545             'root' => 'копе',
546             'ends' => {
547             'n' => ['ек','йка', ('йки') x 3, ('ек') x 3 ],
548             'g' => ['ек','йки', ('ек') x 6 ],
549             'd' => ['ек','йке', ('йкам') x 4, ('ек') x 2 ],
550             'a' => ['ек','йку', ('йки') x 3, ('ек') x 3 ],
551             'i' => ['ек','йкой', ('йками') x 4, ('ек') x 2 ],
552             'p' => ['ек','йке', ('йках') x 4, ('ек') x 2 ],
553             },
554             'plural' => {'n'=>'йки', 'g'=>'ек', 'd'=>'йкам', 'a'=>'йки', 'i'=>'йками', 'p'=>'йках'},
555             );
556              
557             }
558             elsif( $epilog =~/^(?:USD|840)$/) {
559 0         0 %eRef = (
560             'object' => 'inanimate',
561             'gender' => 'masculine',
562             'root' => 'доллар',
563             'ends' => {
564             'n' => ['ов','', ('а') x 3, ('ов') x 3 ],
565             'g' => ['ов','а', ('ов') x 6 ],
566             'd' => ['ам','у', ('ам') x 4, ('ов') x 2 ],
567             'a' => ['ов','', ('а') x 3, ('ов') x 3 ],
568             'i' => ['ов','ом', ('ами') x 4, ('ов') x 2 ],
569             'p' => ['ах','е', ('ах') x 6 ],
570             },
571             'plural' => {'n'=>'ы', 'g'=>'ов', 'd'=>'ам', 'a'=>'ы', 'i'=>'ами', 'p'=>'ах'},
572             );
573              
574             }
575             elsif( $epilog =~/^(?:usd|\-840)$/) {
576 0         0 %eRef = (
577             'object' => 'inanimate',
578             'gender' => 'masculine',
579             'root' => 'цент',
580             'ends' => {
581             'n' => ['ов','', ('а') x 3, ('ов') x 3 ],
582             'g' => ['ов','а', ('ов') x 6 ],
583             'd' => ['ам','у', ('ам') x 6 ],
584             'a' => ['ов','', ('а') x 3, ('ов') x 3 ],
585             'i' => ['ами','ом', ('ами') x 6 ],
586             'p' => ['ах','е', ('ах') x 6 ],
587             },
588             'plural' => {'n'=>'ы', 'g'=>'ов', 'd'=>'ам', 'a'=>'ы', 'i'=>'ами', 'p'=>'ах'},
589             );
590              
591             }
592             elsif( $epilog =~/^(?:CNY|156)$/) {
593 0         0 %eRef = (
594             'object' => 'inanimate',
595             'gender' => 'masculine',
596             'root' => 'юан',
597             'ends' => {
598             'n' => ['ей','ь', ('я') x 3, ('ей') x 3 ],
599             'g' => ['ей','я', ('ей') x 6 ],
600             'd' => ['ям','ю', ('ям') x 6 ],
601             'a' => ['ей','ь', ('я') x 3, ('ей') x 3 ],
602             'i' => ['ей','ем', ('ями') x 4, ('ей') x 2 ],
603             'p' => ['ях','е', ('ях') x 4, ('ей') x 2 ],
604             },
605             'plural' => {'n'=>'и', 'g'=>'ей', 'd'=>'ям', 'a'=>'и', 'i'=>'ями', 'p'=>'ях'},
606             );
607              
608             }
609             # elsif( $epilog =~/^(?:cny|-156)$/) {
610             # %eRef = ('root'=>'фын', 'ends'=>['ей','ь', ('я') x 3, ('ей') x 5 ] );
611             # }
612             elsif( $epilog =~/^year$/i) {
613 0         0 %eRef = (
614             'object' => 'inanimate',
615             'gender' => 'masculine',
616             'root' => '',
617             'ends' => {
618             'n' => ['лет','год', ('года') x 3, ('лет') x 3 ],
619             'g' => ['лет','года', ('лет') x 6 ],
620             'd' => ['лет','году', ('годам') x 4, ('лет') x 2 ],
621             'a' => ['лет','год', ('года') x 3, ('лет') x 3 ],
622             'i' => ['лет','годом', ('годами') x 4, ('лет') x 2 ],
623             'p' => ['лет','годе', ('годах') x 4, ('лет') x 2 ],
624             },
625             'plural' => {'n'=>'годы', 'g'=>'лет', 'd'=>'годам', 'a'=>'годы', 'i'=>'годами', 'p'=>'годах'},
626             );
627              
628             }
629             elsif( $epilog =~/^month$/i) {
630 0         0 %eRef = (
631             'object' => 'inanimate',
632             'gender' => 'masculine',
633             'root' => 'месяц',
634             'ends' => {
635             'n' => ['ев','', ('а') x 3, ('ев') x 3 ],
636             'g' => ['ев','а', ('ев') x 6 ],
637             'd' => ['ам','у', ('ам') x 6 ],
638             'a' => ['ев','', ('а') x 3, ('ев') x 3 ],
639             'i' => ['ев','ем', ('ами') x 4, ('ев') x 2 ],
640             'p' => ['ев','е', ('ах') x 4, ('ев') x 2 ],
641             },
642             'plural' => {'n'=>'ы', 'g'=>'ев', 'd'=>'ам', 'a'=>'ы', 'i'=>'ами', 'p'=>'ах'},
643             );
644              
645             }
646             elsif( $epilog =~/^day$/i) {
647 0         0 %eRef = (
648             'object' => 'inanimate',
649             'gender' => 'masculine',
650             'root' => 'д',
651             'ends' => {
652             'n' => ['ней','ень', ('ня') x 3, ('ней') x 3 ],
653             'g' => ['ней','ня', ('ней') x 6 ],
654             'd' => ['ням','ню', ('ням') x 6 ],
655             'a' => ['ней','ень', ('ня') x 3, ('ней') x 3 ],
656             'i' => ['ней','нём', ('нями') x 4, ('ней') x 2 ],
657             'p' => ['ней','не', ('нях') x 4, ('ней') x 2 ],
658             },
659             'plural' => {'n'=>'ни', 'g'=>'ней', 'd'=>'ням', 'a'=>'ни', 'i'=>'нями', 'p'=>'нях'},
660             );
661              
662             }
663             elsif( $epilog =~/^hour$/i) {
664 0         0 %eRef = (
665             'object' => 'inanimate',
666             'gender' => 'masculine',
667             'root' => 'час',
668             'ends' => {
669             'n' => ['ов','', ('а') x 3, ('ов') x 3 ],
670             'g' => ['ов','а', ('ов') x 6 ],
671             'd' => ['ам','у', ('ам') x 6 ],
672             'a' => ['ов','', ('а') x 3, ('ов') x 3 ],
673             'i' => ['ов','ом', ('ами') x 4, ('ов') x 2 ],
674             'p' => ['ов','е', ('ах') x 4, ('ов') x 2 ],
675             },
676             'plural' => {'n'=>'ы', 'g'=>'ов', 'd'=>'ам', 'a'=>'ы', 'i'=>'ами', 'p'=>'ах'},
677             );
678              
679             }
680             elsif( $epilog =~/^min\.$/i) {
681 0         0 %eRef = (
682             'object' => 'inanimate',
683             'gender' => 'feminine',
684             'root' => 'минут',
685             'ends' => {
686             'n' => ['','а', ('ы') x 3, ('') x 3 ],
687             'g' => ['','ы', ('') x 6 ],
688             'd' => ['','е', ('ам') x 4, ('') x 2 ],
689             'a' => ['','у', ('ы') x 3, ('') x 3 ],
690             'i' => ['','ой', ('ами') x 4, ('') x 2 ],
691             'p' => ['','е', ('ах') x 4, ('') x 2 ],
692             },
693             'plural' => {'n'=>'ы', 'g'=>'', 'd'=>'ам', 'a'=>'ы', 'i'=>'ами', 'p'=>'ах'},
694             );
695              
696             }
697             elsif( $epilog =~/^sec\.$/i) {
698 0         0 %eRef = (
699             'object' => 'inanimate',
700             'gender' => 'feminine',
701             'root' => 'секунд',
702             'ends' => {
703             'n' => ['','а', ('ы') x 3, ('') x 3 ],
704             'g' => ['','ы', ('') x 6 ],
705             'd' => ['','е', ('ам') x 4, ('') x 2 ],
706             'a' => ['','у', ('ы') x 3, ('') x 3 ],
707             'i' => ['','ой', ('ами') x 4, ('') x 2 ],
708             'p' => ['','е', ('ах') x 4, ('') x 2 ],
709             },
710             'plural' => {'n'=>'ы', 'g'=>'', 'd'=>'ам', 'a'=>'ы', 'i'=>'ами', 'p'=>'ах'},
711             );
712              
713             }
714             elsif( $epilog =~/^meter$/i) {
715 0         0 %eRef = (
716             'object' => 'inanimate',
717             'gender' => 'masculine',
718             'root' => 'метр',
719             'ends' => {
720             'n' => ['ов','', ('а') x 3, ('ов') x 3 ],
721             'g' => ['ов','а', ('ов') x 6 ],
722             'd' => ['ов','у', ('ам') x 4, ('ов') x 2 ],
723             'a' => ['ов','', ('а') x 3, ('ов') x 3 ],
724             'i' => ['ов','ом', ('ами') x 4, ('ов') x 2 ],
725             'p' => ['ов','е', ('ах') x 4, ('ов') x 2 ],
726             },
727             'plural' => {'n'=>'ы', 'g'=>'ов', 'd'=>'ам', 'a'=>'ы', 'i'=>'ами', 'p'=>'ах'},
728             );
729              
730             }
731             elsif( $epilog =~/^stamp$/i) {
732 0         0 %eRef = (
733             'object' => 'inanimate',
734             'gender' => 'feminine',
735             'root' => 'печат',
736             'ends' => {
737             'n' => ['ей','ь', ('и') x 3, ('ей') x 3 ],
738             'g' => ['ей','и', ('ей') x 6 ],
739             'd' => ['ей','и', ('ям') x 4, ('ей') x 2 ],
740             'a' => ['ей','ь', ('и') x 3, ('ей') x 3 ],
741             'i' => ['ей','ью', ('ями') x 4, ('ей') x 2 ],
742             'p' => ['ей','и', ('ях') x 4, ('ей') x 2 ],
743             },
744             'plural' => {'n'=>'и', 'g'=>'ей', 'd'=>'ям', 'a'=>'и', 'i'=>'ями', 'p'=>'ях'},
745             );
746              
747             }
748              
749 309 50       762 if( %eRef ) {
750 309         610 $$object = $eRef{'object'};
751 309         507 $$gender = $eRef{'gender'};
752              
753             # To fix for plural '1' only
754 309 100       936 $eRef{'ends'}{ $case }[1] = $eRef{'plural'}{ $case } if $multi =~/^plural/i;
755              
756 309         564 $epilog = {};
757 309         698 $epilog->{'root'} = $eRef{'root'};
758 309         1620 $epilog->{'ends'} = $eRef{'ends'}{ $case };
759             }
760             else {
761 0         0 $epilog = {};
762             }
763              
764             }
765             elsif( ref($epilog) eq 'HASH' && exists( $epilog->{'root'} ) && exists( $epilog->{'ends'} ) ) {
766 8 50       22 if( exists $epilog->{'object'} ) {
767 8 50       26 $$object = $epilog->{'object'}=~/^\s*[a1-9]/i ? 'animate' : 'inanimate';
768             }
769              
770 8         27 $$gender = @{{'m'=>'masculine', 'f'=>'feminine', 'n'=>'neuter'}}{lc $1}
771 8 50 33     45 if exists( $epilog->{'gender'} ) && $epilog->{'gender'} =~/^\s*(m|f|n)/i;
772             }
773             else {
774 1104         1908 $epilog = {};
775             }
776              
777 1421         2971 return $epilog;
778             }
779              
780             1;
781              
782             __END__