CardinalNumeralGenerator   A
last analyzed

Complexity

Total Complexity 31

Size/Duplication

Total Lines 295
Duplicated Lines 6.1 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 92.47%

Importance

Changes 0
Metric Value
dl 18
loc 295
ccs 86
cts 93
cp 0.9247
rs 9.92
c 0
b 0
f 0
wmc 31
lcom 1
cbo 6

2 Methods

Rating   Name   Duplication   Size   Complexity  
F getCases() 18 127 30
A getCase() 0 6 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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 32
    public static function getCases($number, $gender = self::MALE)
163
    {
164
        // simple numeral
165 32
        if (isset(static::$words[$number]) || isset(static::$exponents[$number])) {
166 32
            $word = isset(static::$words[$number]) ? static::$words[$number] : static::$exponents[$number];
167 32
            if (isset(static::$precalculated[$word])) {
168 20
                if (isset(static::$precalculated[$word][static::MALE])) {
169 10
                    return static::$precalculated[$word][$gender];
170
                } else {
171 17
                    return static::$precalculated[$word];
172
                }
173 23
            } elseif (($number >= 5 && $number <= 20) || $number == 30) {
174 13
                $prefix = S::slice($word, 0, -1);
175
                return [
176 13
                    static::IMENIT => $word,
177 13
                    static::RODIT => $prefix.'и',
178 13
                    static::DAT => $prefix.'и',
179 13
                    static::VINIT => $word,
180 13
                    static::TVORIT => $prefix.'ью',
181 13
                    static::PREDLOJ => $prefix.'и',
182
                ];
183 20
            } 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 17
            } elseif (($number >= 50 && $number <= 80)) {
194 9
                $prefix = S::slice($word, 0, -6);
195
                return [
196 9
                    static::IMENIT => $prefix.'ьдесят',
197 9
                    static::RODIT => $prefix.'идесяти',
198 9
                    static::DAT => $prefix.'идесяти',
199 9
                    static::VINIT => $prefix.'ьдесят',
200 9
                    static::TVORIT => $prefix.'ьюдесятью',
201 9
                    static::PREDLOJ => $prefix.'идесяти',
202
                ];
203 17
            } elseif (in_array($number, [300, 400])) {
204 6
                $prefix = S::slice($word, 0, -4);
205
                return [
206 6
                    static::IMENIT => $word,
207 6
                    static::RODIT => $prefix.'ехсот',
208 6
                    static::DAT => $prefix.'емстам',
209 6
                    static::VINIT => $word,
210 6
                    static::TVORIT => $prefix.($number == 300 ? 'е' : 'ь').'мястами',
211 6
                    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 20
        } 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 20
            $parts = [];
239 20
            $result = [];
240
241 20
            foreach (array_reverse(static::$exponents, true) as $word_number => $word) {
242 20
                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 20
                    $number = $number % ($count * $word_number);
267
                }
268
            }
269
270 20 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 20
                if ($number >= $word_number) {
272 20
                    $parts[] = static::getCases($word_number, $gender);
273 20
                    $number %= $word_number;
274
                }
275
            }
276
277
            // make one array with cases and delete 'o/об' prepositional from all parts except the last one
278 20
            foreach (array(static::IMENIT, static::RODIT, static::DAT, static::VINIT, static::TVORIT, static::PREDLOJ) as $case) {
279 20
                $result[$case] = [];
280 20
                foreach ($parts as $partN => $part) {
281 20
                    $result[$case][] = $part[$case];
282
                }
283 20
                $result[$case] = implode(' ', $result[$case]);
284
            }
285
286 20
            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 24
    public static function getCase($number, $case, $gender = self::MALE)
299
    {
300 24
        $case = static::canonizeCase($case);
301 24
        $forms = static::getCases($number, $gender);
302 24
        return $forms[$case];
303
    }
304
}
305