GeezConverter::getGeezSeparator()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 6
cts 6
cp 1
rs 9.9332
c 0
b 0
f 0
cc 3
nc 3
nop 1
crap 3
1
<?php
2
3
namespace Geezify\Converter;
4
5
use Geezify\Exception\NotAnIntegerArgumentException;
6
7
/**
8
 * GeezConverter converts ascii number like <b>1986</b>
9
 * to equivalent geez number like <b>፲፱፻፹፮</b>.
10
 *
11
 * @author Sam As End <4sam21{at}gmail.com>
12
 */
13
class GeezConverter extends Converter
14
{
15
    /**
16
     * Convert an ascii number like <b>1, 21, 3456</b> to
17
     * geez number <b>፩, ፳፩, ፴፬፻፶፮</b>.
18
     *
19
     * @param int $ascii_number
20
     *
21
     * @throws NotAnIntegerArgumentException if the number is not an integer
22
     *
23
     * @return string
24
     */
25 99
    public function convert($ascii_number)
26
    {
27 99
        list($number, $length) = $this->prepareForConversion($ascii_number);
28
29 91
        $result = static::EMPTY_CHARACTER;
30
31 91
        for ($index = 0; $index < $length; $index += 2) {
32 91
            $result .= $this->parseEachTwoCharactersBlock($number, $index, $length);
33
        }
34
35 91
        return $result;
36
    }
37
38
    /**
39
     * - Validate the number
40
     * - Convert the number to a string
41
     * - Get the length of the number
42
     * - Prepend a space if the length is odd.
43
     *
44
     * @param $ascii_number
45
     *
46
     * @throws \Geezify\Exception\NotAnIntegerArgumentException
47
     *
48
     * @return array the $number and the $length
49
     */
50 99
    protected function prepareForConversion($ascii_number)
51
    {
52 99
        $validated_number = $this->validateAsciiNumber($ascii_number);
53
54 91
        $validated_number = "{$validated_number}";
55
56 91
        $length = \strlen($validated_number);
57
58 91
        $number = $this->prependSpaceIfLengthIsEven($validated_number, $length);
59
60
        // return the number too ... i don't wanna "strlen" again
61
        return [
62 91
            $number,
63 91
            $length,
64
        ];
65
    }
66
67
    /**
68
     * Validate if the number is ascii number.
69
     *
70
     * @param $ascii_number
71
     *
72
     * @throws NotAnIntegerArgumentException
73
     *
74
     * @return int
75
     */
76 99
    protected function validateAsciiNumber($ascii_number)
77
    {
78 99
        if (!is_int($ascii_number)) {
79 8
            throw new NotAnIntegerArgumentException($ascii_number);
80
        }
81
82 91
        return $ascii_number;
83
    }
84
85
    /**
86
     * Prepend space if the length of the number is odd.
87
     *
88
     * @param $ascii_number
89
     * @param $length
90
     *
91
     * @return string
92
     */
93 91
    protected function prependSpaceIfLengthIsEven($ascii_number, $length)
94
    {
95 91
        if ($this->isOdd($length)) {
96 52
            return " {$ascii_number}";
97
        }
98
99 40
        return $ascii_number;
100
    }
101
102
    /**
103
     * Is a number odd?
104
     *
105
     * @param $ascii_number
106
     *
107
     * @return bool
108
     */
109 91
    protected function isOdd($ascii_number)
110
    {
111 91
        return !$this->isEven($ascii_number);
112
    }
113
114
    /**
115
     * Is a number even?
116
     *
117
     * @param $number
118
     *
119
     * @return bool
120
     */
121 91
    protected function isEven($number)
122
    {
123 91
        return ($number % 2) === 0;
124
    }
125
126
    /**
127
     * Parse each two character block.
128
     *
129
     * @param $number
130
     * @param $index
131
     * @param $length
132
     *
133
     * @return string
134
     */
135 91
    protected function parseEachTwoCharactersBlock($number, $index, $length)
136
    {
137 91
        $geez_number = $this->getGeezNumberOfTheBlock($number, $index);
138
139 91
        $bet = $this->getBet($length, $index);
140
141 91
        $geez_separator = $this->getGeezSeparator($bet);
142
143 91
        return $this->combineBlockAndSeparator($geez_number, $geez_separator, $index);
144
    }
145
146
    /**
147
     * Fetch the two character (00-99) block and convert it to geez.
148
     *
149
     * @param $number
150
     * @param $index
151
     *
152
     * @return string geez two character block
153
     */
154 91
    protected function getGeezNumberOfTheBlock($number, $index)
155
    {
156 91
        $block = $this->getBlock($number, $index);
157
158 91
        $tenth = (int) $block[0];
159 91
        $once = (int) $block[1];
160
161
        return
162 91
            static::GEEZ_NUMBERS[($tenth * 10)].static::GEEZ_NUMBERS[$once];
163
    }
164
165
    /**
166
     * Fetch two characters from the $number starting from $index.
167
     *
168
     * @param $number string the whole ascii number
169
     * @param $index  integer the starting position
170
     *
171
     * @return string
172
     */
173 91
    protected function getBlock($number, $index)
174
    {
175 91
        return \substr($number, $index, 2);
176
    }
177
178
    /**
179
     * The ቤት of the block.
180
     *
181
     * @param $length integer the length of the ascii number
182
     * @param $index  integer the character index
183
     *
184
     * @return int
185
     */
186 91
    protected function getBet($length, $index)
187
    {
188 91
        $reverse_index = (($length - 1) - $index);
189
190
        // i didn't use floor instead of 'floor' b/c it returns a
191
        // float and 'intval' gives the same thing in integer
192 91
        return intval($reverse_index / 2);
193
    }
194
195
    /**
196
     * Get the separator depending on the bet.
197
     *
198
     * @param $bet
199
     *
200
     * @return string return ፻,፼ or empty character
201
     */
202 91
    protected function getGeezSeparator($bet)
203
    {
204 91
        if ($this->isZero($bet)) {
205 91
            return static::EMPTY_CHARACTER;
206 82
        } elseif ($this->isOdd($bet)) {
207 82
            return static::GEEZ_NUMBERS[100];
208
        } else {
209 62
            return static::GEEZ_NUMBERS[10000];
210
        }
211
    }
212
213
    /**
214
     * Combines the block and the separator.
215
     *
216
     * @param string $geez_number
217
     * @param string $separator
218
     * @param int    $index       of the block
219
     *
220
     * @return string
221
     */
222 91
    protected function combineBlockAndSeparator(
223
        $geez_number,
224
        $separator,
225
        $index
226
    ) {
227 91
        if ($this->shouldRemoveGeezSeparator($geez_number, $separator)) {
228 30
            $separator = static::EMPTY_CHARACTER;
229
        }
230
231 91
        if ($this->shouldRemoveGeezNumberBlock($geez_number, $separator, $index)) {
232 38
            $geez_number = static::EMPTY_CHARACTER;
233
        }
234
235 91
        return $geez_number.$separator;
236
    }
237
238
    /**
239
     * Returns true if the block is empty and the separator is 100.
240
     *
241
     * @param string $block
242
     * @param string $separator
243
     *
244
     * @return bool
245
     */
246 91
    protected function shouldRemoveGeezSeparator($block, $separator)
247
    {
248
        return
249 91
            empty($block) &&
250 91
            $this->isGeezNumberHundred($separator);
251
    }
252
253
    /**
254
     * Returns true if the ascii number is 100 or
255
     * if the ascii number is the leading 10000.
256
     *
257
     * @param $block
258
     * @param $separator
259
     * @param $index
260
     *
261
     * @return bool
262
     */
263 91
    protected function shouldRemoveGeezNumberBlock($block, $separator, $index)
264
    {
265
        return
266 91
            $this->isOneHundred($block, $separator) ||
267 91
            $this->isLeadingTenThousand($block, $separator, $index);
268
    }
269
270
    /**
271
     * Returns true if the number is 100.
272
     *
273
     * @param $block
274
     * @param $separator
275
     *
276
     * @return bool
277
     */
278 91
    protected function isOneHundred($block, $separator)
279
    {
280
        return
281 91
            $this->isGeezNumberHundred($separator) &&
282 91
            $this->isGeezNumberOne($block);
283
    }
284
285
    /**
286
     * Returns true if the number is the leading 10000.
287
     *
288
     * @param $block
289
     * @param $separator
290
     * @param $index
291
     *
292
     * @return bool
293
     */
294 91
    protected function isLeadingTenThousand($block, $separator, $index)
295
    {
296
        return
297 91
            $this->isZero($index) &&
298 91
            $this->isGeezNumberOne($block) &&
299 91
            $this->isGeezNumberTenThousand($separator);
300
    }
301
}
302