easy_to_dictate_numbers 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +340 -1
- data/CHANGELOG.md +7 -1
- data/README.md +1 -1
- data/easy_to_dictate_numbers.gemspec +2 -1
- data/lib/easy_to_dictate_numbers/dictable_number.rb +114 -0
- data/lib/easy_to_dictate_numbers/exceptions.rb +11 -0
- data/lib/easy_to_dictate_numbers/extend_primitives.rb +2 -2
- data/lib/easy_to_dictate_numbers/version.rb +1 -1
- data/lib/easy_to_dictate_numbers.rb +2 -1
- metadata +4 -2
- data/lib/easy_to_dictate_numbers/easy_to_dictate_numbers.rb +0 -110
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aad1aad5f6f04f1c1788f38a5b5698a247198f1fedb8a811c997128bef520344
|
4
|
+
data.tar.gz: 79192439f74c5525eb578dff92542a78231c8237e4a37bb48e52bea13137f68f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3903d276514862a8c8a8f870109b2ab6e7be5e7ae1e6b664f4aca5c129654d11a2503c0254e8dc516cbd04a99ba6ecd6ecd326f5913b2ee6c9a6b928401a9431
|
7
|
+
data.tar.gz: 037e26765bba96e29941dce83e4abdaab9a7a86ea30324ae8f6bbce9769fba2bbab323b95ca8f31b3ccc97432e2ed9d3d7fb44bb41cbddd41aad59e92b35291f
|
data/.rubocop.yml
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
|
2
|
+
require:
|
3
|
+
- rubocop-performance
|
4
|
+
- rubocop-rspec
|
5
|
+
- rubocop-rake
|
6
|
+
|
1
7
|
AllCops:
|
2
8
|
TargetRubyVersion: 2.6
|
3
9
|
|
@@ -8,4 +14,337 @@ Style/Documentation:
|
|
8
14
|
Enabled: false
|
9
15
|
|
10
16
|
Metrics/BlockLength:
|
11
|
-
Enabled: false
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Gemspec/DeprecatedAttributeAssignment: # new in 1.30
|
20
|
+
Enabled: true
|
21
|
+
Gemspec/DevelopmentDependencies: # new in 1.44
|
22
|
+
Enabled: true
|
23
|
+
Gemspec/RequireMFA: # new in 1.23
|
24
|
+
Enabled: true
|
25
|
+
Layout/LineContinuationLeadingSpace: # new in 1.31
|
26
|
+
Enabled: true
|
27
|
+
Layout/LineContinuationSpacing: # new in 1.31
|
28
|
+
Enabled: true
|
29
|
+
Layout/LineEndStringConcatenationIndentation: # new in 1.18
|
30
|
+
Enabled: true
|
31
|
+
Layout/SpaceBeforeBrackets: # new in 1.7
|
32
|
+
Enabled: true
|
33
|
+
Lint/AmbiguousAssignment: # new in 1.7
|
34
|
+
Enabled: true
|
35
|
+
Lint/AmbiguousOperatorPrecedence: # new in 1.21
|
36
|
+
Enabled: true
|
37
|
+
Lint/AmbiguousRange: # new in 1.19
|
38
|
+
Enabled: true
|
39
|
+
Lint/ConstantOverwrittenInRescue: # new in 1.31
|
40
|
+
Enabled: true
|
41
|
+
Lint/DeprecatedConstants: # new in 1.8
|
42
|
+
Enabled: true
|
43
|
+
Lint/DuplicateBranch: # new in 1.3
|
44
|
+
Enabled: true
|
45
|
+
Lint/DuplicateMagicComment: # new in 1.37
|
46
|
+
Enabled: true
|
47
|
+
Lint/DuplicateMatchPattern: # new in 1.50
|
48
|
+
Enabled: true
|
49
|
+
Lint/DuplicateRegexpCharacterClassElement: # new in 1.1
|
50
|
+
Enabled: true
|
51
|
+
Lint/EmptyBlock: # new in 1.1
|
52
|
+
Enabled: true
|
53
|
+
Lint/EmptyClass: # new in 1.3
|
54
|
+
Enabled: true
|
55
|
+
Lint/EmptyInPattern: # new in 1.16
|
56
|
+
Enabled: true
|
57
|
+
Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21
|
58
|
+
Enabled: true
|
59
|
+
Lint/LambdaWithoutLiteralBlock: # new in 1.8
|
60
|
+
Enabled: true
|
61
|
+
Lint/LiteralAssignmentInCondition: # new in 1.58
|
62
|
+
Enabled: true
|
63
|
+
Lint/MixedCaseRange: # new in 1.53
|
64
|
+
Enabled: true
|
65
|
+
Lint/NoReturnInBeginEndBlocks: # new in 1.2
|
66
|
+
Enabled: true
|
67
|
+
Lint/NonAtomicFileOperation: # new in 1.31
|
68
|
+
Enabled: true
|
69
|
+
Lint/NumberedParameterAssignment: # new in 1.9
|
70
|
+
Enabled: true
|
71
|
+
Lint/OrAssignmentToConstant: # new in 1.9
|
72
|
+
Enabled: true
|
73
|
+
Lint/RedundantDirGlobSort: # new in 1.8
|
74
|
+
Enabled: true
|
75
|
+
Lint/RedundantRegexpQuantifiers: # new in 1.53
|
76
|
+
Enabled: true
|
77
|
+
Lint/RefinementImportMethods: # new in 1.27
|
78
|
+
Enabled: true
|
79
|
+
Lint/RequireRangeParentheses: # new in 1.32
|
80
|
+
Enabled: true
|
81
|
+
Lint/RequireRelativeSelfPath: # new in 1.22
|
82
|
+
Enabled: true
|
83
|
+
Lint/SymbolConversion: # new in 1.9
|
84
|
+
Enabled: true
|
85
|
+
Lint/ToEnumArguments: # new in 1.1
|
86
|
+
Enabled: true
|
87
|
+
Lint/TripleQuotes: # new in 1.9
|
88
|
+
Enabled: true
|
89
|
+
Lint/UnexpectedBlockArity: # new in 1.5
|
90
|
+
Enabled: true
|
91
|
+
Lint/UnmodifiedReduceAccumulator: # new in 1.1
|
92
|
+
Enabled: true
|
93
|
+
Lint/UselessRescue: # new in 1.43
|
94
|
+
Enabled: true
|
95
|
+
Lint/UselessRuby2Keywords: # new in 1.23
|
96
|
+
Enabled: true
|
97
|
+
Metrics/CollectionLiteralLength: # new in 1.47
|
98
|
+
Enabled: true
|
99
|
+
Naming/BlockForwarding: # new in 1.24
|
100
|
+
Enabled: true
|
101
|
+
Security/CompoundHash: # new in 1.28
|
102
|
+
Enabled: true
|
103
|
+
Security/IoMethods: # new in 1.22
|
104
|
+
Enabled: true
|
105
|
+
Style/ArgumentsForwarding: # new in 1.1
|
106
|
+
Enabled: true
|
107
|
+
Style/ArrayIntersect: # new in 1.40
|
108
|
+
Enabled: true
|
109
|
+
Style/CollectionCompact: # new in 1.2
|
110
|
+
Enabled: true
|
111
|
+
Style/ComparableClamp: # new in 1.44
|
112
|
+
Enabled: true
|
113
|
+
Style/ConcatArrayLiterals: # new in 1.41
|
114
|
+
Enabled: true
|
115
|
+
Style/DataInheritance: # new in 1.49
|
116
|
+
Enabled: true
|
117
|
+
Style/DirEmpty: # new in 1.48
|
118
|
+
Enabled: true
|
119
|
+
Style/DocumentDynamicEvalDefinition: # new in 1.1
|
120
|
+
Enabled: true
|
121
|
+
Style/EmptyHeredoc: # new in 1.32
|
122
|
+
Enabled: true
|
123
|
+
Style/EndlessMethod: # new in 1.8
|
124
|
+
Enabled: true
|
125
|
+
Style/EnvHome: # new in 1.29
|
126
|
+
Enabled: true
|
127
|
+
Style/ExactRegexpMatch: # new in 1.51
|
128
|
+
Enabled: true
|
129
|
+
Style/FetchEnvVar: # new in 1.28
|
130
|
+
Enabled: true
|
131
|
+
Style/FileEmpty: # new in 1.48
|
132
|
+
Enabled: true
|
133
|
+
Style/FileRead: # new in 1.24
|
134
|
+
Enabled: true
|
135
|
+
Style/FileWrite: # new in 1.24
|
136
|
+
Enabled: true
|
137
|
+
Style/HashConversion: # new in 1.10
|
138
|
+
Enabled: true
|
139
|
+
Style/HashExcept: # new in 1.7
|
140
|
+
Enabled: true
|
141
|
+
Style/IfWithBooleanLiteralBranches: # new in 1.9
|
142
|
+
Enabled: true
|
143
|
+
Style/InPatternThen: # new in 1.16
|
144
|
+
Enabled: true
|
145
|
+
Style/MagicCommentFormat: # new in 1.35
|
146
|
+
Enabled: true
|
147
|
+
Style/MapCompactWithConditionalBlock: # new in 1.30
|
148
|
+
Enabled: true
|
149
|
+
Style/MapToHash: # new in 1.24
|
150
|
+
Enabled: true
|
151
|
+
Style/MapToSet: # new in 1.42
|
152
|
+
Enabled: true
|
153
|
+
Style/MinMaxComparison: # new in 1.42
|
154
|
+
Enabled: true
|
155
|
+
Style/MultilineInPatternThen: # new in 1.16
|
156
|
+
Enabled: true
|
157
|
+
Style/NegatedIfElseCondition: # new in 1.2
|
158
|
+
Enabled: true
|
159
|
+
Style/NestedFileDirname: # new in 1.26
|
160
|
+
Enabled: true
|
161
|
+
Style/NilLambda: # new in 1.3
|
162
|
+
Enabled: true
|
163
|
+
Style/NumberedParameters: # new in 1.22
|
164
|
+
Enabled: true
|
165
|
+
Style/NumberedParametersLimit: # new in 1.22
|
166
|
+
Enabled: true
|
167
|
+
Style/ObjectThen: # new in 1.28
|
168
|
+
Enabled: true
|
169
|
+
Style/OpenStructUse: # new in 1.23
|
170
|
+
Enabled: true
|
171
|
+
Style/OperatorMethodCall: # new in 1.37
|
172
|
+
Enabled: true
|
173
|
+
Style/QuotedSymbols: # new in 1.16
|
174
|
+
Enabled: true
|
175
|
+
Style/RedundantArgument: # new in 1.4
|
176
|
+
Enabled: true
|
177
|
+
Style/RedundantArrayConstructor: # new in 1.52
|
178
|
+
Enabled: true
|
179
|
+
Style/RedundantConstantBase: # new in 1.40
|
180
|
+
Enabled: true
|
181
|
+
Style/RedundantCurrentDirectoryInPath: # new in 1.53
|
182
|
+
Enabled: true
|
183
|
+
Style/RedundantDoubleSplatHashBraces: # new in 1.41
|
184
|
+
Enabled: true
|
185
|
+
Style/RedundantEach: # new in 1.38
|
186
|
+
Enabled: true
|
187
|
+
Style/RedundantFilterChain: # new in 1.52
|
188
|
+
Enabled: true
|
189
|
+
Style/RedundantHeredocDelimiterQuotes: # new in 1.45
|
190
|
+
Enabled: true
|
191
|
+
Style/RedundantInitialize: # new in 1.27
|
192
|
+
Enabled: true
|
193
|
+
Style/RedundantLineContinuation: # new in 1.49
|
194
|
+
Enabled: true
|
195
|
+
Style/RedundantRegexpArgument: # new in 1.53
|
196
|
+
Enabled: true
|
197
|
+
Style/RedundantRegexpConstructor: # new in 1.52
|
198
|
+
Enabled: true
|
199
|
+
Style/RedundantSelfAssignmentBranch: # new in 1.19
|
200
|
+
Enabled: true
|
201
|
+
Style/RedundantStringEscape: # new in 1.37
|
202
|
+
Enabled: true
|
203
|
+
Style/ReturnNilInPredicateMethodDefinition: # new in 1.53
|
204
|
+
Enabled: true
|
205
|
+
Style/SelectByRegexp: # new in 1.22
|
206
|
+
Enabled: true
|
207
|
+
Style/SingleLineDoEndBlock: # new in 1.57
|
208
|
+
Enabled: true
|
209
|
+
Style/StringChars: # new in 1.12
|
210
|
+
Enabled: true
|
211
|
+
Style/SuperWithArgsParentheses: # new in 1.58
|
212
|
+
Enabled: true
|
213
|
+
Style/SwapValues: # new in 1.1
|
214
|
+
Enabled: true
|
215
|
+
Style/YAMLFileRead: # new in 1.53
|
216
|
+
Enabled: true
|
217
|
+
Capybara/ClickLinkOrButtonStyle: # new in 2.19
|
218
|
+
Enabled: true
|
219
|
+
Capybara/MatchStyle: # new in 2.17
|
220
|
+
Enabled: true
|
221
|
+
Capybara/NegationMatcher: # new in 2.14
|
222
|
+
Enabled: true
|
223
|
+
Capybara/RedundantWithinFind: # new in 2.20
|
224
|
+
Enabled: true
|
225
|
+
Capybara/SpecificActions: # new in 2.14
|
226
|
+
Enabled: true
|
227
|
+
Capybara/SpecificFinders: # new in 2.13
|
228
|
+
Enabled: true
|
229
|
+
Capybara/SpecificMatcher: # new in 2.12
|
230
|
+
Enabled: true
|
231
|
+
Capybara/RSpec/HaveSelector: # new in 2.19
|
232
|
+
Enabled: true
|
233
|
+
Capybara/RSpec/PredicateMatcher: # new in 2.19
|
234
|
+
Enabled: true
|
235
|
+
FactoryBot/AssociationStyle: # new in 2.23
|
236
|
+
Enabled: true
|
237
|
+
FactoryBot/ConsistentParenthesesStyle: # new in 2.14
|
238
|
+
Enabled: true
|
239
|
+
FactoryBot/ExcessiveCreateList: # new in 2.25
|
240
|
+
Enabled: true
|
241
|
+
FactoryBot/FactoryAssociationWithStrategy: # new in 2.23
|
242
|
+
Enabled: true
|
243
|
+
FactoryBot/FactoryNameStyle: # new in 2.16
|
244
|
+
Enabled: true
|
245
|
+
FactoryBot/IdSequence: # new in 2.24
|
246
|
+
Enabled: true
|
247
|
+
FactoryBot/RedundantFactoryOption: # new in 2.23
|
248
|
+
Enabled: true
|
249
|
+
FactoryBot/SyntaxMethods: # new in 2.7
|
250
|
+
Enabled: true
|
251
|
+
RSpec/BeEmpty: # new in 2.20
|
252
|
+
Enabled: true
|
253
|
+
RSpec/BeEq: # new in 2.9.0
|
254
|
+
Enabled: true
|
255
|
+
RSpec/BeNil: # new in 2.9.0
|
256
|
+
Enabled: true
|
257
|
+
RSpec/ChangeByZero: # new in 2.11
|
258
|
+
Enabled: true
|
259
|
+
RSpec/ContainExactly: # new in 2.19
|
260
|
+
Enabled: true
|
261
|
+
RSpec/DuplicatedMetadata: # new in 2.16
|
262
|
+
Enabled: true
|
263
|
+
RSpec/EmptyMetadata: # new in 2.24
|
264
|
+
Enabled: true
|
265
|
+
RSpec/Eq: # new in 2.24
|
266
|
+
Enabled: true
|
267
|
+
RSpec/ExcessiveDocstringSpacing: # new in 2.5
|
268
|
+
Enabled: true
|
269
|
+
RSpec/IdenticalEqualityAssertion: # new in 2.4
|
270
|
+
Enabled: true
|
271
|
+
RSpec/IndexedLet: # new in 2.20
|
272
|
+
Enabled: true
|
273
|
+
RSpec/MatchArray: # new in 2.19
|
274
|
+
Enabled: true
|
275
|
+
RSpec/MetadataStyle: # new in 2.24
|
276
|
+
Enabled: true
|
277
|
+
RSpec/NoExpectationExample: # new in 2.13
|
278
|
+
Enabled: true
|
279
|
+
RSpec/PendingWithoutReason: # new in 2.16
|
280
|
+
Enabled: true
|
281
|
+
RSpec/ReceiveMessages: # new in 2.23
|
282
|
+
Enabled: true
|
283
|
+
RSpec/RedundantAround: # new in 2.19
|
284
|
+
Enabled: true
|
285
|
+
RSpec/RedundantPredicateMatcher: # new in 2.26
|
286
|
+
Enabled: true
|
287
|
+
RSpec/RemoveConst: # new in 2.26
|
288
|
+
Enabled: true
|
289
|
+
RSpec/SkipBlockInsideExample: # new in 2.19
|
290
|
+
Enabled: true
|
291
|
+
RSpec/SortMetadata: # new in 2.14
|
292
|
+
Enabled: true
|
293
|
+
RSpec/SpecFilePathFormat: # new in 2.24
|
294
|
+
Enabled: true
|
295
|
+
RSpec/SpecFilePathSuffix: # new in 2.24
|
296
|
+
Enabled: true
|
297
|
+
RSpec/SubjectDeclaration: # new in 2.5
|
298
|
+
Enabled: true
|
299
|
+
RSpec/VerifiedDoubleReference: # new in 2.10.0
|
300
|
+
Enabled: true
|
301
|
+
RSpec/Rails/AvoidSetupHook: # new in 2.4
|
302
|
+
Enabled: true
|
303
|
+
RSpec/Rails/HaveHttpStatus: # new in 2.12
|
304
|
+
Enabled: true
|
305
|
+
RSpec/Rails/InferredSpecType: # new in 2.14
|
306
|
+
Enabled: true
|
307
|
+
RSpec/Rails/MinitestAssertions: # new in 2.17
|
308
|
+
Enabled: true
|
309
|
+
RSpec/Rails/NegationBeValid: # new in 2.23
|
310
|
+
Enabled: true
|
311
|
+
RSpec/Rails/TravelAround: # new in 2.19
|
312
|
+
Enabled: true
|
313
|
+
Performance/AncestorsInclude: # new in 1.7
|
314
|
+
Enabled: true
|
315
|
+
Performance/BigDecimalWithNumericArgument: # new in 1.7
|
316
|
+
Enabled: true
|
317
|
+
Performance/BlockGivenWithExplicitBlock: # new in 1.9
|
318
|
+
Enabled: true
|
319
|
+
Performance/CollectionLiteralInLoop: # new in 1.8
|
320
|
+
Enabled: true
|
321
|
+
Performance/ConcurrentMonotonicTime: # new in 1.12
|
322
|
+
Enabled: true
|
323
|
+
Performance/ConstantRegexp: # new in 1.9
|
324
|
+
Enabled: true
|
325
|
+
Performance/MapCompact: # new in 1.11
|
326
|
+
Enabled: true
|
327
|
+
Performance/MapMethodChain: # new in 1.19
|
328
|
+
Enabled: true
|
329
|
+
Performance/MethodObjectAsBlock: # new in 1.9
|
330
|
+
Enabled: true
|
331
|
+
Performance/RedundantEqualityComparisonBlock: # new in 1.10
|
332
|
+
Enabled: true
|
333
|
+
Performance/RedundantSortBlock: # new in 1.7
|
334
|
+
Enabled: true
|
335
|
+
Performance/RedundantSplitRegexpArgument: # new in 1.10
|
336
|
+
Enabled: true
|
337
|
+
Performance/RedundantStringChars: # new in 1.7
|
338
|
+
Enabled: true
|
339
|
+
Performance/ReverseFirst: # new in 1.7
|
340
|
+
Enabled: true
|
341
|
+
Performance/SortReverse: # new in 1.7
|
342
|
+
Enabled: true
|
343
|
+
Performance/Squeeze: # new in 1.7
|
344
|
+
Enabled: true
|
345
|
+
Performance/StringIdentifierArgument: # new in 1.13
|
346
|
+
Enabled: true
|
347
|
+
Performance/StringInclude: # new in 1.7
|
348
|
+
Enabled: true
|
349
|
+
Performance/Sum: # new in 1.8
|
350
|
+
Enabled: true
|
data/CHANGELOG.md
CHANGED
@@ -18,4 +18,10 @@
|
|
18
18
|
- 100 -> one hundred
|
19
19
|
- 1000 -> one thousand
|
20
20
|
- 2334 -> twenty three thirty four
|
21
|
-
- Extended string with `to_dictable_number`
|
21
|
+
- Extended string with `to_dictable_number`
|
22
|
+
- Add support for leading zeroes
|
23
|
+
|
24
|
+
## [0.1.4] - 2024-01-14
|
25
|
+
|
26
|
+
- Refactor to use instance methods to avoid exposing so many
|
27
|
+
- Added rubocop and fixed all errors
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# EasyToDictateNumbers
|
2
2
|
|
3
|
-
EasyToDictateNumbers is
|
3
|
+
GitHub Copilot: EasyToDictateNumbers is an opinionated Ruby gem designed to convert numbers into their spoken equivalents. This gem is particularly useful in situations where precise verbal communication of numbers is required, such as during phone calls or dictation. It makes certain decisions about the "best" way to pronounce numbers, which may be subject to debate.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
|
11
11
|
spec.summary = 'Transform numbers into words to dictate them easily.'
|
12
12
|
spec.description = 'Transform numbers into words to dictate them easily.' \
|
13
|
-
|
13
|
+
"For example 1234 becomes twelve thirty four and 123456 becomes 'one two three, four five six'"
|
14
14
|
spec.homepage = 'https://github.com/matismasters/easy_to_dictate_numbers'
|
15
15
|
spec.required_ruby_version = '>= 2.6.0'
|
16
16
|
|
@@ -36,4 +36,5 @@ Gem::Specification.new do |spec|
|
|
36
36
|
|
37
37
|
# For more information and examples about making a new gem, check out our
|
38
38
|
# guide at: https://bundler.io/guides/creating_gem.html
|
39
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
39
40
|
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EasyToDictateNumbers
|
4
|
+
class DictableNumber
|
5
|
+
attr_reader :number_to_dictate, :dictable_number_in_words
|
6
|
+
|
7
|
+
ONES = %w[zero one two three four five six seven eight nine].freeze
|
8
|
+
TEENS = %w[ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen].freeze
|
9
|
+
TENS = %w[twenty thirty forty fifty sixty seventy eighty ninety].freeze
|
10
|
+
|
11
|
+
def initialize(number_to_dictate)
|
12
|
+
@number_to_dictate = number_to_dictate.to_s
|
13
|
+
validate_number(@number_to_dictate)
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_dictable
|
17
|
+
@to_dictable ||= number_to_words
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def number_to_words
|
23
|
+
number_as_string = @number_to_dictate
|
24
|
+
|
25
|
+
leading_zeroes_words = leading_zeroes_to_words(number_as_string)
|
26
|
+
|
27
|
+
number_without_leading_zeroes = number_without_leading_zeroes(number_as_string)
|
28
|
+
number_without_leading_zeroes_words = number_without_leading_zeroes_to_words(number_without_leading_zeroes)
|
29
|
+
|
30
|
+
[leading_zeroes_words, number_without_leading_zeroes_words].reject(&:empty?).join(' ')
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate_number(number_as_string)
|
34
|
+
raise NonNumberCharactersPresent if number_as_string.match?(/[^0-9]/)
|
35
|
+
end
|
36
|
+
|
37
|
+
def number_without_leading_zeroes_to_words(number_as_string)
|
38
|
+
case number_as_string.length
|
39
|
+
when 1 then one_digit_number_to_words(number_as_string)
|
40
|
+
when 2 then two_digit_number_to_words(number_as_string)
|
41
|
+
when 3 then three_digit_number_to_words(number_as_string)
|
42
|
+
when 4 then four_digit_number_to_words(number_as_string)
|
43
|
+
else large_number_to_words(number_as_string)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def repeat_zeroes(number_of_zeroes)
|
48
|
+
Array.new(number_of_zeroes) { ONES[0] }.join(' ')
|
49
|
+
end
|
50
|
+
|
51
|
+
def leading_zeroes_to_words(number_as_string)
|
52
|
+
leading_zeroes = number_as_string.match(/^0+/).to_s
|
53
|
+
return '' if leading_zeroes.empty?
|
54
|
+
|
55
|
+
repeat_zeroes(leading_zeroes.length)
|
56
|
+
end
|
57
|
+
|
58
|
+
def number_without_leading_zeroes(number_as_string)
|
59
|
+
number_as_string.sub(/^0+/, '')
|
60
|
+
end
|
61
|
+
|
62
|
+
def single_thousands_to_words(number_as_string)
|
63
|
+
number = number_as_string.to_i / 1000
|
64
|
+
|
65
|
+
[one_digit_number_to_words(number), 'thousand'].join(' ')
|
66
|
+
end
|
67
|
+
|
68
|
+
def one_digit_number_to_words(number_as_string)
|
69
|
+
number = number_as_string.to_i
|
70
|
+
return repeat_zeroes(1) if number.zero?
|
71
|
+
|
72
|
+
ONES[number]
|
73
|
+
end
|
74
|
+
|
75
|
+
def two_digit_number_to_words(number_as_string)
|
76
|
+
number = number_as_string.to_i
|
77
|
+
|
78
|
+
return repeat_zeroes(2) if number.zero?
|
79
|
+
return TEENS[number - 10] if number < 20
|
80
|
+
|
81
|
+
div, mod = number.divmod(10)
|
82
|
+
TENS[div - 2] + (mod.zero? ? '' : " #{ONES[mod]}")
|
83
|
+
end
|
84
|
+
|
85
|
+
def three_digit_number_to_words(number_as_string)
|
86
|
+
number = number_as_string.to_i
|
87
|
+
return repeat_zeroes(3) if number.zero?
|
88
|
+
|
89
|
+
first_digit, remainder = number.divmod(100)
|
90
|
+
words = [ONES[first_digit]]
|
91
|
+
words << (remainder.zero? ? 'hundred' : two_digit_number_to_words(remainder))
|
92
|
+
words.join(' ')
|
93
|
+
end
|
94
|
+
|
95
|
+
def four_digit_number_to_words(number_as_string)
|
96
|
+
number = number_as_string.to_i
|
97
|
+
|
98
|
+
return repeat_zeroes(4) if number.zero?
|
99
|
+
return single_thousands_to_words(number_as_string) if (number % 1000).zero?
|
100
|
+
|
101
|
+
high_pair = number_as_string[0..1]
|
102
|
+
low_pair = number_as_string[2..3]
|
103
|
+
|
104
|
+
[
|
105
|
+
two_digit_number_to_words(high_pair),
|
106
|
+
low_pair.to_i.zero? ? 'hundred' : two_digit_number_to_words(low_pair)
|
107
|
+
].join(' ')
|
108
|
+
end
|
109
|
+
|
110
|
+
def large_number_to_words(number_as_string)
|
111
|
+
number_as_string.chars.map { |digit| ONES[digit.to_i] }.each_slice(3).map { |digit| digit.join(' ') }.join(', ')
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
class Integer
|
4
4
|
def to_dictable
|
5
|
-
EasyToDictateNumbers::
|
5
|
+
EasyToDictateNumbers::DictableNumber.new(self).to_dictable
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
9
|
class String
|
10
10
|
def to_dictable_number
|
11
|
-
EasyToDictateNumbers::
|
11
|
+
EasyToDictateNumbers::DictableNumber.new(self).to_dictable
|
12
12
|
end
|
13
13
|
end
|
@@ -3,4 +3,5 @@
|
|
3
3
|
# lib/easy_to_dictate_numbers.rb
|
4
4
|
require_relative 'easy_to_dictate_numbers/version'
|
5
5
|
require_relative 'easy_to_dictate_numbers/extend_primitives'
|
6
|
-
require_relative 'easy_to_dictate_numbers/
|
6
|
+
require_relative 'easy_to_dictate_numbers/exceptions'
|
7
|
+
require_relative 'easy_to_dictate_numbers/dictable_number'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: easy_to_dictate_numbers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matias Verges
|
@@ -26,7 +26,8 @@ files:
|
|
26
26
|
- Rakefile
|
27
27
|
- easy_to_dictate_numbers.gemspec
|
28
28
|
- lib/easy_to_dictate_numbers.rb
|
29
|
-
- lib/easy_to_dictate_numbers/
|
29
|
+
- lib/easy_to_dictate_numbers/dictable_number.rb
|
30
|
+
- lib/easy_to_dictate_numbers/exceptions.rb
|
30
31
|
- lib/easy_to_dictate_numbers/extend_primitives.rb
|
31
32
|
- lib/easy_to_dictate_numbers/version.rb
|
32
33
|
- sig/easy_to_dictate_numbers.rbs
|
@@ -37,6 +38,7 @@ metadata:
|
|
37
38
|
homepage_uri: https://github.com/matismasters/easy_to_dictate_numbers
|
38
39
|
source_code_uri: https://github.com/matismasters/easy_to_dictate_numbers
|
39
40
|
changelog_uri: https://github.com/matismasters/easy_to_dictate_numbers/blob/main/CHANGELOG.md
|
41
|
+
rubygems_mfa_required: 'true'
|
40
42
|
post_install_message:
|
41
43
|
rdoc_options: []
|
42
44
|
require_paths:
|
@@ -1,110 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module EasyToDictateNumbers
|
4
|
-
class Error < StandardError; end
|
5
|
-
|
6
|
-
class NonNumberCharactersPresent < StandardError
|
7
|
-
def initialize
|
8
|
-
super('Non-number characters present')
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class NumberToDictable
|
13
|
-
ONES = %w[zero one two three four five six seven eight nine].freeze
|
14
|
-
TEENS = %w[ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen].freeze
|
15
|
-
TENS = %w[twenty thirty forty fifty sixty seventy eighty ninety].freeze
|
16
|
-
|
17
|
-
class << self
|
18
|
-
def number_to_words(number_to_dictate)
|
19
|
-
number_as_string = number_to_dictate.to_s
|
20
|
-
validate_number(number_as_string)
|
21
|
-
|
22
|
-
leading_zeroes_words = leading_zeroes_to_words(number_as_string)
|
23
|
-
|
24
|
-
number_without_leading_zeroes = number_without_leading_zeroes(number_as_string)
|
25
|
-
number_without_leading_zeroes_words = number_without_leading_zeroes_to_words(number_without_leading_zeroes)
|
26
|
-
|
27
|
-
[leading_zeroes_words, number_without_leading_zeroes_words].reject(&:empty?).join(' ')
|
28
|
-
end
|
29
|
-
|
30
|
-
def validate_number(number_as_string)
|
31
|
-
raise NonNumberCharactersPresent if number_as_string.match?(/[^0-9]/)
|
32
|
-
end
|
33
|
-
|
34
|
-
def number_without_leading_zeroes_to_words(number_as_string)
|
35
|
-
case number_as_string.length
|
36
|
-
when 1 then one_digit_number_to_words(number_as_string)
|
37
|
-
when 2 then two_digit_number_to_words(number_as_string)
|
38
|
-
when 3 then three_digit_number_to_words(number_as_string)
|
39
|
-
when 4 then four_digit_number_to_words(number_as_string)
|
40
|
-
else large_number_to_words(number_as_string)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def repeat_zeroes(number_of_zeroes)
|
45
|
-
number_of_zeroes.times.map { ONES[0] }.join(' ')
|
46
|
-
end
|
47
|
-
|
48
|
-
def leading_zeroes_to_words(number_as_string)
|
49
|
-
leading_zeroes = number_as_string.match(/^0+/).to_s
|
50
|
-
leading_zeroes.empty? ? '' : repeat_zeroes(leading_zeroes.length)
|
51
|
-
end
|
52
|
-
|
53
|
-
def number_without_leading_zeroes(number_as_string)
|
54
|
-
number_as_string.sub(/^0+/, '')
|
55
|
-
end
|
56
|
-
|
57
|
-
def single_thousands_to_words(number_as_string)
|
58
|
-
number = number_as_string.to_i / 1000
|
59
|
-
|
60
|
-
[one_digit_number_to_words(number), 'thousand'].join(' ')
|
61
|
-
end
|
62
|
-
|
63
|
-
def one_digit_number_to_words(number_as_string)
|
64
|
-
number = number_as_string.to_i
|
65
|
-
return repeat_zeroes(1) if number.zero?
|
66
|
-
|
67
|
-
ONES[number]
|
68
|
-
end
|
69
|
-
|
70
|
-
def two_digit_number_to_words(number_as_string)
|
71
|
-
number = number_as_string.to_i
|
72
|
-
|
73
|
-
return repeat_zeroes(2) if number.zero?
|
74
|
-
return TEENS[number - 10] if number < 20
|
75
|
-
|
76
|
-
div, mod = number.divmod(10)
|
77
|
-
TENS[div - 2] + (mod.zero? ? '' : " #{ONES[mod]}")
|
78
|
-
end
|
79
|
-
|
80
|
-
def three_digit_number_to_words(number_as_string)
|
81
|
-
number = number_as_string.to_i
|
82
|
-
return repeat_zeroes(3) if number.zero?
|
83
|
-
|
84
|
-
first_digit, remainder = number.divmod(100)
|
85
|
-
words = [ONES[first_digit]]
|
86
|
-
words << (remainder.zero? ? 'hundred' : two_digit_number_to_words(remainder))
|
87
|
-
words.join(' ')
|
88
|
-
end
|
89
|
-
|
90
|
-
def four_digit_number_to_words(number_as_string)
|
91
|
-
number = number_as_string.to_i
|
92
|
-
|
93
|
-
return repeat_zeroes(4) if number.zero?
|
94
|
-
return single_thousands_to_words(number_as_string) if (number % 1000).zero?
|
95
|
-
|
96
|
-
high_pair = number_as_string[0..1]
|
97
|
-
low_pair = number_as_string[2..3]
|
98
|
-
|
99
|
-
[
|
100
|
-
two_digit_number_to_words(high_pair),
|
101
|
-
low_pair.to_i.zero? ? 'hundred' : two_digit_number_to_words(low_pair)
|
102
|
-
].join(' ')
|
103
|
-
end
|
104
|
-
|
105
|
-
def large_number_to_words(number_as_string)
|
106
|
-
number_as_string.chars.map { |digit| ONES[digit.to_i] }.each_slice(3).map { |digit| digit.join(' ') }.join(', ')
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|