File Coverage

blib/lib/Lingua/RU/Declension.pm
Criterion Covered Total %
statement 73 119 61.3
branch 14 56 25.0
condition 5 11 45.4
subroutine 16 24 66.6
pod 13 13 100.0
total 121 223 54.2


line stmt bran cond sub pod time code
1 2     2   101323 use 5.014;
  2         11  
2 2     2   6 use utf8;
  2         3  
  2         6  
3 2     2   39 use strict;
  2         3  
  2         24  
4 2     2   6 use warnings;
  2         2  
  2         91  
5              
6             package Lingua::RU::Declension;
7             $Lingua::RU::Declension::VERSION = '0.005';
8 2     2   963 use Text::CSV 1.91 qw(csv);
  2         28062  
  2         79  
9 2     2   569 use File::Share qw(dist_file);
  2         9398  
  2         81  
10 2     2   9 use Carp qw(confess);
  2         3  
  2         1739  
11              
12             # ABSTRACT: Decline Russian pronouns, adjectives and nouns
13              
14              
15              
16             sub new {
17 2     2 1 150 my $class = shift;
18              
19 2 50 33     10 if ( (scalar @_) and (scalar @_ % 2 != 0) ) {
20 0         0 confess "Expected pairs for initialization values";
21             }
22              
23 2         6 my $self = bless {}, $class;
24 2         8 return $self->_load(@_);
25              
26             }
27              
28             sub _load {
29 2     2   5 my $self = shift;
30              
31            
32              
33 2         16 my %defaults = (
34             'nouns' => { 'file' => 'nouns_utf8.csv',
35             'key' => 'nom' },
36             'adjectives' => { 'file' => 'adjectives_utf8.csv',
37             'key' => 'masc_nom' },
38             'pronouns' => { 'file' => 'pronouns_utf8.csv',
39             'key' => 'masc_nom' },
40             'stems' => { 'file' => 'sentence_stems_utf8.csv',
41             'key' => 'case' },
42             );
43              
44 2         9 my %files = (%defaults);
45              
46 2 50       7 if ( @_ ) {
47 0         0 %files = (%defaults, %{@_});
  0         0  
48             }
49              
50 2         7 for my $k ( keys %files ) {
51 8         31077 my $c = $files{$k};
52             $self->{$k} = csv(in => dist_file('Lingua-RU-Declension',
53             $c->{file}),
54             key => $c->{key},
55 8         22 encoding => 'UTF-8');
56             }
57              
58 2         2028 return $self;
59             }
60              
61              
62             sub select_nouns {
63 1     1 1 9 my $self = shift;
64 1         1 my $code = shift;
65              
66 1 50       18 if ( ref($code) ne "CODE" ) {
67 0         0 confess "Expected second parameter to be a code reference.";
68             }
69              
70 20         61 return grep { $code->($self->{nouns}->{$_}) }
71 1         2 keys %{ $self->{nouns} };
  1         3  
72             }
73              
74              
75             sub decline_random_adjective {
76 0     0 1 0 my $self = shift;
77 0         0 return $self->decline_adjective($self->choose_random_adjective(), @_);
78             }
79              
80              
81             sub choose_random_adjective {
82 0     0 1 0 my $self = shift;
83 0         0 return $self->_choose_random($self->{adjectives})->{masc_nom};
84             }
85              
86             sub _choose_random {
87 0     0   0 my $self = shift;
88 0         0 my $h = shift;
89              
90 0         0 return $h->{(keys %{ $h })[rand keys %{ $h }]};
  0         0  
  0         0  
91             }
92              
93              
94             sub decline_adjective {
95 1     1 1 4 my $self = shift;
96 1         1 my $adj = shift;
97              
98 1 50       3 if ( not exists $self->{adjectives}->{$adj} ) {
99 0         0 confess "Couldn't find adjective '$adj' in my data.";
100             }
101              
102 1         13 my $hk = $self->_select_hash_key(@_);
103              
104 1         2 return $self->{adjectives}->{$adj}->{$hk};
105             }
106              
107              
108             sub choose_random_pronoun {
109 0     0 1 0 my $self = shift;
110 0         0 return $self->_choose_random($self->{pronouns})->{masc_nom};
111             }
112              
113              
114             sub decline_random_pronoun {
115 0     0 1 0 my $self = shift;
116 0         0 return $self->decline_pronoun($self->choose_random_pronoun(), @_);
117             }
118              
119              
120             sub decline_pronoun {
121 1     1 1 4 my $self = shift;
122 1         2 my $pronoun = shift;
123              
124 1 50       3 if ( not exists $self->{pronouns}->{$pronoun} ) {
125 0         0 confess "Couldn't find pronoun '$pronoun' in my data.";
126             }
127              
128 1         4 my $hk = $self->_select_hash_key(@_);
129              
130 1         5 return $self->{pronouns}->{$pronoun}->{$hk};
131             }
132              
133              
134             sub decline_noun {
135 1     1 1 8 my $self = shift;
136 1         1 my $noun = shift;
137 1   50     3 my $case = shift // 'nom';
138 1   50     5 my $is_plural = shift // 0;
139 1 50       3 $is_plural = $is_plural eq "plural" ? 1 : 0 ;
140              
141 1 50       3 if ( not exists $self->{nouns}->{$noun} ) {
142 0         0 confess "Couldn't find noun '$noun' in my data.";
143             }
144              
145 1 50       3 if ( $is_plural ) {
146 0 0       0 return $self->{nouns}->{$noun}->{nmp} if $case eq "nom";
147 0 0       0 return $self->{nouns}->{$noun}->{acp} if $case eq "acc";
148 0 0       0 return $self->{nouns}->{$noun}->{gnp} if $case eq "gen";
149 0 0       0 return $self->{nouns}->{$noun}->{dtp} if $case eq "dat";
150 0 0       0 return $self->{nouns}->{$noun}->{itp} if $case eq "inst";
151 0 0       0 return $self->{nouns}->{$noun}->{prp} if $case eq "prep";
152             }
153             else {
154 1         3 return $self->{nouns}->{$noun}->{$case};
155             }
156             }
157              
158              
159             sub choose_random_noun {
160 0     0 1 0 my $self = shift;
161 0         0 return $self->_choose_random($self->{nouns})->{nom};
162             }
163              
164              
165             sub decline_random_noun {
166 0     0 1 0 my $self = shift;
167 0         0 return $self->decline_noun($self->choose_random_noun(), @_);
168             }
169              
170              
171             sub russian_sentence_stem {
172 1     1 1 1314 my $self = shift;
173 1         3 return $self->_select_sentence_stem(@_)->{rus};
174             }
175              
176              
177             sub english_sentence_stem {
178 0     0 1 0 my $self = shift;
179 0         0 my $h = $self->_select_sentence_stem(@_)->{eng};
180             }
181              
182             sub _select_sentence_stem {
183 1     1   2 my $self = shift;
184 1         2 my $case = shift;
185              
186 1 50       4 if ( not exists $self->{stems}->{$case} ) {
187 0         0 confess "Could not find case $case in the sentence stem data.";
188             }
189              
190 1         7 return $self->{stems}->{$case};
191             }
192              
193             sub _select_hash_key {
194 2     2   3 my $self = shift;
195 2         3 my $noun = shift;
196 2   50     3 my $case = shift // 'nom' ;
197 2   50     6 my $is_plural = shift // 0;
198 2 50       4 $is_plural = $is_plural eq "plural" ? 1 : 0 ;
199 2         4 my $animate = $self->{nouns}->{$noun}->{animate};
200 2         4 my $gender = $self->{nouns}->{$noun}->{gender};
201              
202 2 50       4 if ( $is_plural ) {
203 0 0       0 if ( $case eq "acc" ) {
204 0 0       0 return "pl_gen" if $animate eq "a"; #animate nouns get genitive endings
205 0         0 return "pl_nom"; # inanimate nouns get nominative endings
206             }
207              
208 0         0 return "pl_".$case;
209             }
210             else {
211 2 50       4 if ( $gender eq "m" ) {
    0          
    0          
212 2 50       3 if ( $case eq "acc" ) {
213 2 50       6 return "masc_gen" if $animate eq "a";
214 0           return "masc_nom";
215             }
216 0           return "masc_$case";
217             }
218             elsif ( $gender eq "f" ) {
219 0 0         return "fem_nom" if $case eq "nom";
220 0 0         return "fem_acc" if $case eq "acc";
221 0           return "fem_oth";
222             }
223             elsif ( $gender eq "n" ) {
224 0 0         return "neu_nom" if $case eq "nom";
225 0 0         return "neu_nom" if $case eq "acc";
226 0           return "masc_$case";
227             }
228             else {
229 0           confess "I don't know how to decline '$noun' (gender: $gender, animate: $animate)";
230             }
231             }
232             }
233              
234             1;
235              
236             __END__