Completed
Push — master ( 03367b...e141e7 )
by f
01:43
created

CardinalNumeral::getCases()   D

Complexity

Conditions 31
Paths 106

Size

Total Lines 115
Code Lines 89

Duplication

Lines 25
Ratio 21.74 %

Importance

Changes 0
Metric Value
cc 31
eloc 89
nc 106
nop 2
dl 25
loc 115
rs 4.3285
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace morphos\Russian;
3
4
use morphos\NumeralCreation;
5
use morphos\S;
6
7
/**
8
 * Rules are from http://www.fio.ru/pravila/grammatika/sklonenie-imen-chislitelnykh/
9
 */
10
class CardinalNumeral extends NumeralCreation implements Cases {
11
    use RussianLanguage, CasesHelper;
12
13
    static protected $words = array(
14
        1 => 'один',
15
        2 => 'два',
16
        3 => 'три',
17
        4 => 'четыре',
18
        5 => 'пять',
19
        6 => 'шесть',
20
        7 => 'семь',
21
        8 => 'восемь',
22
        9 => 'девять',
23
        10 => 'десять',
24
        11 => 'одиннадцать',
25
        12 => 'двенадцать',
26
        13 => 'тринадцать',
27
        14 => 'четырнадцать',
28
        15 => 'пятнадцать',
29
        16 => 'шестнадцать',
30
        17 => 'семнадцать',
31
        18 => 'восемнадцать',
32
        19 => 'девятнадцать',
33
        20 => 'двадцать',
34
        30 => 'тридцать',
35
        40 => 'сорок',
36
        50 => 'пятьдесят',
37
        60 => 'шестьдесят',
38
        70 => 'семьдесят',
39
        80 => 'восемьдесят',
40
        90 => 'девяносто',
41
        100 => 'сто',
42
        200 => 'двести',
43
        300 => 'триста',
44
        400 => 'четыреста',
45
        500 => 'пятьсот',
46
        600 => 'шестьсот',
47
        700 => 'семьсот',
48
        800 => 'восемьсот',
49
        900 => 'девятьсот',
50
    );
51
52
    static protected $exponents = array(
53
        1000 => 'тысяча',
54
        1000000 => 'миллион',
55
        1000000000 => 'миллиард',
56
        1000000000000 => 'триллион',
57
    );
58
59
    static protected $precalculated = array(
60
        'один' => array(
61
            self::MALE => array(
62
                self::IMENIT => 'один',
63
                self::RODIT => 'одного',
64
                self::DAT => 'одному',
65
                self::VINIT => 'один',
66
                self::TVORIT => 'одним',
67
                self::PREDLOJ => 'об одном',
68
            ),
69
            self::FEMALE => array(
70
                self::IMENIT => 'одна',
71
                self::RODIT => 'одной',
72
                self::DAT => 'одной',
73
                self::VINIT => 'одну',
74
                self::TVORIT => 'одной',
75
                self::PREDLOJ => 'об одной',
76
            ),
77
            self::NEUTER => array(
78
                self::IMENIT => 'одно',
79
                self::RODIT => 'одного',
80
                self::DAT => 'одному',
81
                self::VINIT => 'одно',
82
                self::TVORIT => 'одним',
83
                self::PREDLOJ => 'об одном',
84
            ),
85
        ),
86
        'два' => array(
87
            self::MALE => array(
88
                self::IMENIT => 'два',
89
                self::RODIT => 'двух',
90
                self::DAT => 'двум',
91
                self::VINIT => 'два',
92
                self::TVORIT => 'двумя',
93
                self::PREDLOJ => 'о двух',
94
            ),
95
            self::FEMALE => array(
96
                self::IMENIT => 'две',
97
                self::RODIT => 'двух',
98
                self::DAT => 'двум',
99
                self::VINIT => 'два',
100
                self::TVORIT => 'двумя',
101
                self::PREDLOJ => 'о двух',
102
            ),
103
            self::NEUTER => array(
104
                self::IMENIT => 'два',
105
                self::RODIT => 'двух',
106
                self::DAT => 'двум',
107
                self::VINIT => 'два',
108
                self::TVORIT => 'двумя',
109
                self::PREDLOJ => 'о двух',
110
            ),
111
        ),
112
        'три' => array(
113
            self::IMENIT => 'три',
114
            self::RODIT => 'трех',
115
            self::DAT => 'трем',
116
            self::VINIT => 'три',
117
            self::TVORIT => 'тремя',
118
            self::PREDLOJ => 'о трех',
119
        ),
120
        'четыре' => array(
121
            self::IMENIT => 'четыре',
122
            self::RODIT => 'четырех',
123
            self::DAT => 'четырем',
124
            self::VINIT => 'четыре',
125
            self::TVORIT => 'четырьмя',
126
            self::PREDLOJ => 'о четырех',
127
        ),
128
        'двести' => array(
129
            self::IMENIT => 'двести',
130
            self::RODIT => 'двухсот',
131
            self::DAT => 'двумстам',
132
            self::VINIT => 'двести',
133
            self::TVORIT => 'двумястами',
134
            self::PREDLOJ => 'о двухстах',
135
        ),
136
        'восемьсот' => array(
137
            self::IMENIT => 'восемьсот',
138
            self::RODIT => 'восьмисот',
139
            self::DAT => 'восьмистам',
140
            self::VINIT => 'восемьсот',
141
            self::TVORIT => 'восьмистами',
142
            self::PREDLOJ => 'о восьмистах',
143
        ),
144
        'тысяча' => array(
145
            self::IMENIT => 'тысяча',
146
            self::RODIT => 'тысяч',
147
            self::DAT => 'тысячам',
148
            self::VINIT => 'тысяч',
149
            self::TVORIT => 'тысячей',
150
            self::PREDLOJ => 'о тысячах',
151
        ),
152
    );
153
154
    static public function getCases($number, $gender = self::MALE) {
155
        // simple numeral
156
        if (isset(self::$words[$number]) || isset(self::$exponents[$number])) {
157
            $word = isset(self::$words[$number]) ? self::$words[$number] : self::$exponents[$number];
158
            if (isset(self::$precalculated[$word])) {
159
                if (isset(self::$precalculated[$word][self::MALE])) {
160
                    return self::$precalculated[$word][$gender];
161
                } else {
162
                    return self::$precalculated[$word];
163
                }
164
            } else if (($number >= 5 && $number <= 20) || $number == 30) {
165
                $prefix = S::slice($word, 0, -1);
166
                return array(
167
                    self::IMENIT => $word,
168
                    self::RODIT => $prefix.'и',
169
                    self::DAT => $prefix.'и',
170
                    self::VINIT => $word,
171
                    self::TVORIT => $prefix.'ью',
172
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'и',
173
                );
174
            } else if (in_array($number, array(40, 90, 100))) {
175
                $prefix = $number == 40 ? $word : S::slice($word, 0, -1);
176
                return array(
177
                    self::IMENIT => $word,
178
                    self::RODIT => $prefix.'а',
179
                    self::DAT => $prefix.'а',
180
                    self::VINIT => $word,
181
                    self::TVORIT => $prefix.'а',
182
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($prefix, 'об', 'о').' '.$prefix.'а',
183
                );
184
            } else if (($number >= 50 && $number <= 80)) {
185
                $prefix = S::slice($word, 0, -6);
186
                return array(
187
                    self::IMENIT => $prefix.'ьдесят',
188
                    self::RODIT => $prefix.'идесяти',
189
                    self::DAT => $prefix.'идесяти',
190
                    self::VINIT => $prefix.'ьдесят',
191
                    self::TVORIT => $prefix.'ьюдесятью',
192
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($word, 'об', 'о').' '.$prefix.'идесяти',
193
                );
194
            } else if (in_array($number, array(300, 400))) {
195
                $prefix = S::slice($word, 0, -4);
196
                return array(
197
                    self::IMENIT => $word,
198
                    self::RODIT => $prefix.'ехсот',
199
                    self::DAT => $prefix.'емстам',
200
                    self::VINIT => $word,
201
                    self::TVORIT => $prefix.($number == 300 ? 'е' : 'ь').'мястами',
202
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($word, 'об', 'о').' '.$prefix.'ехстах',
203
                );
204
            } else if ($number >= 500 && $number <= 900) {
205
                $prefix = S::slice($word, 0, -4);
206
                return array(
207
                    self::IMENIT => $word,
208
                    self::RODIT => $prefix.'исот',
209
                    self::DAT => $prefix.'истам',
210
                    self::VINIT => $word,
211
                    self::TVORIT => $prefix.'ьюстами',
212
                    self::PREDLOJ => self::choosePrepositionByFirstLetter($word, 'об', 'о').' '.$prefix.'истах',
213
                );
214
            } else if (isset(self::$exponents[$number])) {
215
                return GeneralDeclension::getCases($word, false);
216
            }
217
        }
218
        // compound numeral
219
        else {
220
            $parts = array();
221
            $result = array();
222
223
            foreach (array_reverse(self::$exponents, true) as $word_number => $word) {
224
                if ($number >= $word_number) {
225
                    $count = floor($number / $word_number);
226
                    $parts[] = self::getCases($count, ($word_number == 1000 ? self::FEMALE : self::MALE));
227
228
                    switch (Plurality::getNumeralForm($count)) {
229
                        case Plurality::ONE:
230
                            $parts[] = GeneralDeclension::getCases($word, false);
231
                            break;
232 View Code Duplication
                        case Plurality::TWO_FOUR:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
233
                            $part = Plurality::getCases($word);
234
                            if ($word_number != 1000) // get dative case of word for 1000000, 1000000000 and 1000000000000
235
                                $part[Cases::IMENIT] = $part[Cases::VINIT] = GeneralDeclension::getCase($word, Cases::RODIT);
236
                            $parts[] = $part;
237
                            break;
238 View Code Duplication
                        case Plurality::FIVE_OTHER:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
239
                            $part = Plurality::getCases($word);
240
                            $part[Cases::IMENIT] = $part[Cases::VINIT] = $part[Cases::RODIT];
241
                            $parts[] = $part;
242
                            break;
243
                    }
244
245
                    $number = $number % ($count * $word_number);
246
                }
247
            }
248
249 View Code Duplication
            foreach (array_reverse(self::$words, true) as $word_number => $word) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
250
                if ($number >= $word_number) {
251
                    $parts[] = self::getCases($word_number, $gender);
252
                    $number %= $word_number;
253
                }
254
            }
255
256
            // make one array with cases and delete 'o/об' prepositional from all parts except the last one
257 View Code Duplication
            foreach (array(self::IMENIT, self::RODIT, self::DAT, self::VINIT, self::TVORIT, self::PREDLOJ) as $case) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
258
                $result[$case] = array();
259
                foreach ($parts as $partN => $part) {
260
                    if ($case == self::PREDLOJ && $partN > 0) list(, $part[$case]) = explode(' ', $part[$case], 2);
261
                    $result[$case][] = $part[$case];
262
                }
263
                $result[$case] = implode(' ', $result[$case]);
264
            }
265
266
            return $result;
267
        }
268
    }
269
270
    static public function getCase($number, $case, $gender = self::MALE) {
271
        $case = self::canonizeCase($case);
272
        $forms = self::getCases($number, $gender);
273
        return $forms[$case];
274
    }
275
}
276