CardinalNumeralGenerator::getCases()   F
last analyzed

Complexity

Conditions 30
Paths 86

Size

Total Lines 127

Duplication

Lines 18
Ratio 14.17 %

Code Coverage

Tests 82
CRAP Score 30.4386

Importance

Changes 0
Metric Value
cc 30
nc 86
nop 2
dl 18
loc 127
ccs 82
cts 89
cp 0.9213
crap 30.4386
rs 3.3333
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\NumeralGenerator;
5
use morphos\S;
6
7
/**
8
 * Rules are from http://www.fio.ru/pravila/grammatika/sklonenie-imen-chislitelnykh/
9
 */
10
class CardinalNumeralGenerator extends NumeralGenerator implements Cases
11
{
12
    use RussianLanguage, CasesHelper;
13
14
    protected static $words = [
15
        1 => 'один',
16
        2 => 'два',
17
        3 => 'три',
18
        4 => 'четыре',
19
        5 => 'пять',
20
        6 => 'шесть',
21
        7 => 'семь',
22
        8 => 'восемь',
23
        9 => 'девять',
24
        10 => 'десять',
25
        11 => 'одиннадцать',
26
        12 => 'двенадцать',
27
        13 => 'тринадцать',
28
        14 => 'четырнадцать',
29
        15 => 'пятнадцать',
30
        16 => 'шестнадцать',
31
        17 => 'семнадцать',
32
        18 => 'восемнадцать',
33
        19 => 'девятнадцать',
34
        20 => 'двадцать',
35
        30 => 'тридцать',
36
        40 => 'сорок',
37
        50 => 'пятьдесят',
38
        60 => 'шестьдесят',
39
        70 => 'семьдесят',
40
        80 => 'восемьдесят',
41
        90 => 'девяносто',
42
        100 => 'сто',
43
        200 => 'двести',
44
        300 => 'триста',
45
        400 => 'четыреста',
46
        500 => 'пятьсот',
47
        600 => 'шестьсот',
48
        700 => 'семьсот',
49
        800 => 'восемьсот',
50
        900 => 'девятьсот',
51
    ];
52
53
    protected static $exponents = [
54
        '1000' => 'тысяча',
55
        '1000000' => 'миллион',
56
        '1000000000' => 'миллиард',
57
        '1000000000000' => 'триллион',
58
        '1000000000000000' => 'квадриллион',
59
    ];
60
61
    protected static $precalculated = [
62
        'один' => [
63
            self::MALE => [
64
                self::IMENIT => 'один',
65
                self::RODIT => 'одного',
66
                self::DAT => 'одному',
67
                self::VINIT => 'один',
68
                self::TVORIT => 'одним',
69
                self::PREDLOJ => 'одном',
70
            ],
71
            self::FEMALE => [
72
                self::IMENIT => 'одна',
73
                self::RODIT => 'одной',
74
                self::DAT => 'одной',
75
                self::VINIT => 'одну',
76
                self::TVORIT => 'одной',
77
                self::PREDLOJ => 'одной',
78
            ],
79
            self::NEUTER => [
80
                self::IMENIT => 'одно',
81
                self::RODIT => 'одного',
82
                self::DAT => 'одному',
83
                self::VINIT => 'одно',
84
                self::TVORIT => 'одним',
85
                self::PREDLOJ => 'одном',
86
            ],
87
        ],
88
        'два' => [
89
            self::MALE => [
90
                self::IMENIT => 'два',
91
                self::RODIT => 'двух',
92
                self::DAT => 'двум',
93
                self::VINIT => 'два',
94
                self::TVORIT => 'двумя',
95
                self::PREDLOJ => 'двух',
96
            ],
97
            self::FEMALE => [
98
                self::IMENIT => 'две',
99
                self::RODIT => 'двух',
100
                self::DAT => 'двум',
101
                self::VINIT => 'две',
102
                self::TVORIT => 'двумя',
103
                self::PREDLOJ => 'двух',
104
            ],
105
            self::NEUTER => [
106
                self::IMENIT => 'два',
107
                self::RODIT => 'двух',
108
                self::DAT => 'двум',
109
                self::VINIT => 'два',
110
                self::TVORIT => 'двумя',
111
                self::PREDLOJ => 'двух',
112
            ],
113
        ],
114
        'три' => [
115
            self::IMENIT => 'три',
116
            self::RODIT => 'трех',
117
            self::DAT => 'трем',
118
            self::VINIT => 'три',
119
            self::TVORIT => 'тремя',
120
            self::PREDLOJ => 'трех',
121
        ],
122
        'четыре' => [
123
            self::IMENIT => 'четыре',
124
            self::RODIT => 'четырех',
125
            self::DAT => 'четырем',
126
            self::VINIT => 'четыре',
127
            self::TVORIT => 'четырьмя',
128
            self::PREDLOJ => 'четырех',
129
        ],
130
        'двести' => [
131
            self::IMENIT => 'двести',
132
            self::RODIT => 'двухсот',
133
            self::DAT => 'двумстам',
134
            self::VINIT => 'двести',
135
            self::TVORIT => 'двумястами',
136
            self::PREDLOJ => 'двухстах',
137
        ],
138
        'восемьсот' => [
139
            self::IMENIT => 'восемьсот',
140
            self::RODIT => 'восьмисот',
141
            self::DAT => 'восьмистам',
142
            self::VINIT => 'восемьсот',
143
            self::TVORIT => 'восьмистами',
144
            self::PREDLOJ => 'восьмистах',
145
        ],
146
        'тысяча' => [
147
            self::IMENIT => 'тысяча',
148
            self::RODIT => 'тысяч',
149
            self::DAT => 'тысячам',
150
            self::VINIT => 'тысяч',
151
            self::TVORIT => 'тысячей',
152
            self::PREDLOJ => 'тысячах',
153
        ],
154
    ];
155
156
    /**
157
     * @param $number
158
     * @param string $gender
159
     * @return array
160
     * @throws \Exception
161
     */
162 31
    public static function getCases($number, $gender = self::MALE)
163
    {
164
        // simple numeral
165 31
        if (isset(static::$words[$number]) || isset(static::$exponents[$number])) {
166 31
            $word = isset(static::$words[$number]) ? static::$words[$number] : static::$exponents[$number];
167 31
            if (isset(static::$precalculated[$word])) {
168 19
                if (isset(static::$precalculated[$word][static::MALE])) {
169 9
                    return static::$precalculated[$word][$gender];
170
                } else {
171 16
                    return static::$precalculated[$word];
172
                }
173 22
            } elseif (($number >= 5 && $number <= 20) || $number == 30) {
174 12
                $prefix = S::slice($word, 0, -1);
175
                return [
176 12
                    static::IMENIT => $word,
177 12
                    static::RODIT => $prefix.'и',
178 12
                    static::DAT => $prefix.'и',
179 12
                    static::VINIT => $word,
180 12
                    static::TVORIT => $prefix.'ью',
181 12
                    static::PREDLOJ => $prefix.'и',
182
                ];
183 19
            } elseif (in_array($number, [40, 90, 100])) {
184 10
                $prefix = $number == 40 ? $word : S::slice($word, 0, -1);
185
                return [
186 10
                    static::IMENIT => $word,
187 10
                    static::RODIT => $prefix.'а',
188 10
                    static::DAT => $prefix.'а',
189 10
                    static::VINIT => $word,
190 10
                    static::TVORIT => $prefix.'а',
191 10
                    static::PREDLOJ => $prefix.'а',
192
                ];
193 16
            } elseif (($number >= 50 && $number <= 80)) {
194 8
                $prefix = S::slice($word, 0, -6);
195
                return [
196 8
                    static::IMENIT => $prefix.'ьдесят',
197 8
                    static::RODIT => $prefix.'идесяти',
198 8
                    static::DAT => $prefix.'идесяти',
199 8
                    static::VINIT => $prefix.'ьдесят',
200 8
                    static::TVORIT => $prefix.'ьюдесятью',
201 8
                    static::PREDLOJ => $prefix.'идесяти',
202
                ];
203 16
            } elseif (in_array($number, [300, 400])) {
204 5
                $prefix = S::slice($word, 0, -4);
205
                return [
206 5
                    static::IMENIT => $word,
207 5
                    static::RODIT => $prefix.'ехсот',
208 5
                    static::DAT => $prefix.'емстам',
209 5
                    static::VINIT => $word,
210 5
                    static::TVORIT => $prefix.($number == 300 ? 'е' : 'ь').'мястами',
211 5
                    static::PREDLOJ => $prefix.'ехстах',
212
                ];
213 11
            } elseif ($number >= 500 && $number <= 900) {
214 9
                $prefix = S::slice($word, 0, -4);
215
                return [
216 9
                    static::IMENIT => $word,
217 9
                    static::RODIT => $prefix.'исот',
218 9
                    static::DAT => $prefix.'истам',
219 9
                    static::VINIT => $word,
220 9
                    static::TVORIT => $prefix.'ьюстами',
221 9
                    static::PREDLOJ => $prefix.'истах',
222
                ];
223 2
            } elseif (isset(static::$exponents[$number])) {
224 2
                return NounDeclension::getCases($word, false);
225
            }
226 19
        } elseif ($number == 0) {
227
            return [
228
                static::IMENIT => 'ноль',
229
                static::RODIT => 'ноля',
230
                static::DAT => 'нолю',
231
                static::VINIT => 'ноль',
232
                static::TVORIT => 'нолём',
233
                static::PREDLOJ => 'ноле',
234
            ];
235
        }
236
        // compound numeral
237
        else {
238 19
            $parts = [];
239 19
            $result = [];
240
241 19
            foreach (array_reverse(static::$exponents, true) as $word_number => $word) {
242 19
                if ($number >= $word_number) {
243 12
                    $count = floor($number / $word_number);
244 12
                    $parts[] = static::getCases($count, ($word_number == 1000 ? static::FEMALE : static::MALE));
245
246 12
                    switch (NounPluralization::getNumeralForm($count)) {
247 12
                        case NounPluralization::ONE:
248 4
                            $parts[] = NounDeclension::getCases($word, false);
249 4
                            break;
250
251 11 View Code Duplication
                        case NounPluralization::TWO_FOUR:
0 ignored issues
show
Duplication introduced by wapmorgan
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...
252 6
                            $part = NounPluralization::getCases($word);
253 6
                            if ($word_number != 1000) { // get dative case of word for 1000000, 1000000000 and 1000000000000
254 3
                                $part[Cases::IMENIT] = $part[Cases::VINIT] = NounDeclension::getCase($word, Cases::RODIT);
255
                            }
256 6
                            $parts[] = $part;
257 6
                            break;
258
259 8 View Code Duplication
                        case NounPluralization::FIVE_OTHER:
0 ignored issues
show
Duplication introduced by wapmorgan
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...
260 8
                            $part = NounPluralization::getCases($word);
261 8
                            $part[Cases::IMENIT] = $part[Cases::VINIT] = $part[Cases::RODIT];
262 8
                            $parts[] = $part;
263 8
                            break;
264
                    }
265
266 19
                    $number = $number % ($count * $word_number);
267
                }
268
            }
269
270 19 View Code Duplication
            foreach (array_reverse(static::$words, true) as $word_number => $word) {
0 ignored issues
show
Duplication introduced by wapmorgan
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...
271 19
                if ($number >= $word_number) {
272 19
                    $parts[] = static::getCases($word_number, $gender);
273 19
                    $number %= $word_number;
274
                }
275
            }
276
277
            // make one array with cases and delete 'o/об' prepositional from all parts except the last one
278 19
            foreach (array(static::IMENIT, static::RODIT, static::DAT, static::VINIT, static::TVORIT, static::PREDLOJ) as $case) {
279 19
                $result[$case] = [];
280 19
                foreach ($parts as $partN => $part) {
281 19
                    $result[$case][] = $part[$case];
282
                }
283 19
                $result[$case] = implode(' ', $result[$case]);
284
            }
285
286 19
            return $result;
287
        }
288
    }
289
290
    /**
291
     * @param        $number
292
     * @param        $case
293
     * @param string $gender
294
     *
295
     * @return mixed|void
296
     * @throws \Exception
297
     */
298 23
    public static function getCase($number, $case, $gender = self::MALE)
299
    {
300 23
        $case = static::canonizeCase($case);
301 23
        $forms = static::getCases($number, $gender);
302 23
        return $forms[$case];
303
    }
304
}
305