Issues (33)

src/Converter/GeezConverter.js (7 issues)

1
const Converter = require('./Converter');
0 ignored issues
show
The constant Converter seems to be never used. Consider removing it.
Loading history...
2
const NotAnIntegerArgumentException = require('../Exception/NotAnIntegerArgumentException');
0 ignored issues
show
The constant NotAnIntegerArgumentException seems to be never used. Consider removing it.
Loading history...
3
4
/**
5
 * GeezConverter converts ascii number like <b>1986</b>
6
 * to equivalent geez number like <b>፲፱፻፹፮</b>.
7
 *
8
 * @author Sam As End <4sam21{at}gmail.com>
9
 */
10
module.exports = class GeezConverter extends Converter {
11
  /**
12
   * Convert an ascii number like <b>1, 21, 3456</b> to
13
   * geez number <b>፩, ፳፩, ፴፬፻፶፮</b>.
14
   *
15
   *
16
   * @throws NotAnIntegerArgumentException if the number is not an integer
17
   * @return string
18
   * @param $ascii_number
19
   */
20
  convert($ascii_number) {
21
    const $number = this.prepareForConversion($ascii_number);
22
    const $length = $number.length;
23
    let $result = Converter.EMPTY_CHARACTER;
0 ignored issues
show
The variable Converter seems to be never declared. If this is a global, consider adding a /** global: Converter */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
24
25
    for (let $index = 0; $index < $length; $index += 2) {
26
      $result += this.parseEachTwoCharactersBlock($number, $index, $length);
27
    }
28
29
    return $result;
30
  }
31
32
  /**
33
   * - Validate the number
34
   * - Convert the number to a string
35
   * - Get the length of the number
36
   * - Prepend a space if the length is odd.
37
   *
38
   * @param $ascii_number
39
   *
40
   * @throws \Geezify\Exception\NotAnIntegerArgumentException
41
   *
42
   * @return array the $number and the $length
43
   */
44
  prepareForConversion($ascii_number) {
45
    let $validated_number = this.validateAsciiNumber($ascii_number);
46
47
    $validated_number = `${$validated_number}`;
48
49
    const $length = $validated_number.length;
50
51
    const $number = this.prependSpaceIfLengthIsEven($validated_number, $length);
52
53
    return $number;
54
  }
55
56
  /**
57
   * Validate if the number is ascii number.
58
   *
59
   * @param $ascii_number
60
   *
61
   * @throws NotAnIntegerArgumentException
62
   * @return int
63
   */
64
  validateAsciiNumber($ascii_number) {
65
    const number = parseInt($ascii_number, 10);
66
67
    if (Number.isNaN(number) || `${number}` !== `${$ascii_number}` || number < 1) {
68
      throw new NotAnIntegerArgumentException($ascii_number);
0 ignored issues
show
The variable NotAnIntegerArgumentException seems to be never declared. If this is a global, consider adding a /** global: NotAnIntegerArgumentException */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
69
    }
70
71
    return $ascii_number;
72
  }
73
74
  /**
75
   * Prepend space if the length of the number is odd.
76
   *
77
   * @param $ascii_number
78
   * @param $length
79
   *
80
   * @return string
81
   */
82
  prependSpaceIfLengthIsEven($ascii_number, $length) {
83
    if (this.isOdd($length)) {
84
      return ` ${$ascii_number}`;
85
    }
86
87
    return $ascii_number;
88
  }
89
90
  /**
91
   * Is a number odd?
92
   *
93
   * @param $ascii_number
94
   *
95
   * @return bool
96
   */
97
  isOdd($ascii_number) {
98
    return !this.isEven($ascii_number);
99
  }
100
101
  /**
102
   * Is a number even?
103
   *
104
   * @param $number
105
   *
106
   * @return boolean
107
   */
108
  isEven($number) {
109
    return $number % 2 === 0;
110
  }
111
112
  /**
113
   * Parse each two character block.
114
   *
115
   * @param $number
116
   * @param $index
117
   * @param $length
118
   *
119
   * @return string
120
   */
121
  parseEachTwoCharactersBlock($number, $index, $length) {
122
    const $geez_number = this.getGeezNumberOfTheBlock($number, $index);
123
124
    const $bet = this.getBet($length, $index);
125
126
    const $geez_separator = this.getGeezSeparator($bet);
127
128
    return this.combineBlockAndSeparator($geez_number, $geez_separator, $index);
129
  }
130
131
  /**
132
   * Fetch the two character (00-99) block and convert it to geez.
133
   *
134
   * @param $number
135
   * @param $index
136
   *
137
   * @return string geez two character block
138
   */
139
  getGeezNumberOfTheBlock($number, $index) {
140
    const $block = this.getBlock($number, $index);
141
142
    const $tenth = Number.isNaN(parseInt($block[0], 10)) ? 0 : parseInt($block[0], 10);
143
    const $once = parseInt($block[1], 10);
144
145
    return Converter.GEEZ_NUMBERS[$tenth * 10] + Converter.GEEZ_NUMBERS[$once];
0 ignored issues
show
The variable Converter seems to be never declared. If this is a global, consider adding a /** global: Converter */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
146
  }
147
148
  /**
149
   * Fetch two characters from the $number starting from $index.
150
   *
151
   * @param $number string the whole ascii number
152
   * @param $index  integer the starting position
153
   *
154
   * @return string
155
   */
156
  getBlock($number, $index) {
157
    return $number.substr($index, 2);
158
  }
159
160
  /**
161
   * The ቤት of the block.
162
   *
163
   * @param $length integer the length of the ascii number
164
   * @param $index  integer the character index
165
   *
166
   * @return int
167
   */
168
  getBet($length, $index) {
169
    const $reverse_index = $length - 1 - $index;
170
171
    return Math.floor($reverse_index / 2);
172
  }
173
174
  /**
175
   * Get the separator depending on the bet.
176
   *
177
   * @param $bet
178
   *
179
   * @return string return ፻,፼ or empty character
180
   */
181
  getGeezSeparator($bet) {
182
    if (this.isZero($bet)) {
183
      return Converter.EMPTY_CHARACTER;
0 ignored issues
show
The variable Converter seems to be never declared. If this is a global, consider adding a /** global: Converter */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
184
    }
185
    if (this.isOdd($bet)) {
186
      return Converter.GEEZ_NUMBERS[100];
187
    }
188
189
    return Converter.GEEZ_NUMBERS[10000];
190
  }
191
192
  /**
193
   * Combines the block and the separator.
194
   *
195
   *
196
   * @return string
197
   * @param $geez_number
198
   * @param $separator
199
   * @param $index
200
   */
201
  combineBlockAndSeparator($geez_number, $separator, $index) {
202
    /* eslint-disable no-param-reassign */
203
    if (this.shouldRemoveGeezSeparator($geez_number, $separator)) {
204
      $separator = Converter.EMPTY_CHARACTER;
0 ignored issues
show
The variable Converter seems to be never declared. If this is a global, consider adding a /** global: Converter */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
205
    }
206
207
    if (this.shouldRemoveGeezNumberBlock($geez_number, $separator, $index)) {
208
      $geez_number = Converter.EMPTY_CHARACTER;
209
    }
210
    /* eslint-enable no-param-reassign */
211
212
    return $geez_number + $separator;
213
  }
214
215
  /**
216
   * Returns true if the block is empty and the separator is 100.
217
   *
218
   * @return bool
219
   * @param $block
220
   * @param $separator
221
   */
222
  shouldRemoveGeezSeparator($block, $separator) {
223
    return $block.trim().length === 0 && this.isGeezNumberHundred($separator);
224
  }
225
226
  /**
227
   * Returns true if the ascii number is 100 or
228
   * if the ascii number is the leading 10000.
229
   *
230
   * @param $block
231
   * @param $separator
232
   * @param $index
233
   *
234
   * @return bool
235
   */
236
  shouldRemoveGeezNumberBlock($block, $separator, $index) {
237
    return (
238
      this.isOneHundred($block, $separator) || this.isLeadingTenThousand($block, $separator, $index)
239
    );
240
  }
241
242
  /**
243
   * Returns true if the number is 100.
244
   *
245
   * @param $block
246
   * @param $separator
247
   *
248
   * @return bool
249
   */
250
  isOneHundred($block, $separator) {
251
    return this.isGeezNumberHundred($separator) && this.isGeezNumberOne($block);
252
  }
253
254
  /**
255
   * Returns true if the number is the leading 10000.
256
   *
257
   * @param $block
258
   * @param $separator
259
   * @param $index
260
   *
261
   * @return bool
262
   */
263
  isLeadingTenThousand($block, $separator, $index) {
264
    return (
265
      this.isZero($index)
266
      && this.isGeezNumberOne($block)
267
      && this.isGeezNumberTenThousand($separator)
268
    );
269
  }
270
};
271