ada_numbers 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 687cb405cfb56c733e1f7744a14999e22bc15ef11ae93c3163522c2a1dbe2e0f
4
+ data.tar.gz: 6324a7fe749ed13b5589ce8c180758ff46415f1427981ea10ac49c3a12506e6e
5
+ SHA512:
6
+ metadata.gz: a3be0a5c634712132d807f58524629ce698a74447745394380ff082aec034cb95cb1466859f62b826068a971e583fe941046d0ddec091b9a1ebcf1570ec3299d
7
+ data.tar.gz: 9b6d9d02c84bd66f179bdf6002c65fd8bcb21d8cf816034ddb74fb91c4f7544062f63b655b5e8430fb90c6dd383bc6338a72c93ff451062f607b15c9122071fc
data/.idea/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ # Default ignored files
2
+ /shelf/
3
+ /workspace.xml
4
+ # Editor-based HTTP Client requests
5
+ /httpRequests/
6
+ # Datasource local storage ignored files
7
+ /dataSources/
8
+ /dataSources.local.xml
@@ -0,0 +1,46 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="RUBY_MODULE" version="4">
3
+ <component name="ModuleRunConfigurationManager">
4
+ <shared />
5
+ </component>
6
+ <component name="NewModuleRootManager">
7
+ <content url="file://$MODULE_DIR$">
8
+ <sourceFolder url="file://$MODULE_DIR$/features" isTestSource="true" />
9
+ <sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
10
+ <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
11
+ </content>
12
+ <orderEntry type="jdk" jdkName="rbenv: 2.7.7" jdkType="RUBY_SDK" />
13
+ <orderEntry type="sourceFolder" forTests="false" />
14
+ <orderEntry type="library" scope="PROVIDED" name="bundler (v2.1.4, rbenv: 2.7.7) [gem]" level="application" />
15
+ <orderEntry type="library" scope="PROVIDED" name="minitest (v5.18.0, rbenv: 2.7.7) [gem]" level="application" />
16
+ <orderEntry type="library" scope="PROVIDED" name="rake (v12.3.3, rbenv: 2.7.7) [gem]" level="application" />
17
+ </component>
18
+ <component name="RakeTasksCache">
19
+ <option name="myRootTask">
20
+ <RakeTaskImpl id="rake">
21
+ <subtasks>
22
+ <RakeTaskImpl description="Build ada_numbers-0.1.0.gem into the pkg directory" fullCommand="build" id="build" />
23
+ <RakeTaskImpl description="Remove any temporary products" fullCommand="clean" id="clean" />
24
+ <RakeTaskImpl description="Remove any generated files" fullCommand="clobber" id="clobber" />
25
+ <RakeTaskImpl description="Build and install ada_numbers-0.1.0.gem into system gems" fullCommand="install" id="install" />
26
+ <RakeTaskImpl id="install">
27
+ <subtasks>
28
+ <RakeTaskImpl description="Build and install ada_numbers-0.1.0.gem into system gems without network access" fullCommand="install:local" id="local" />
29
+ </subtasks>
30
+ </RakeTaskImpl>
31
+ <RakeTaskImpl description="Create tag v0.1.0 and build and push ada_numbers-0.1.0.gem to rubygems.org" fullCommand="release[remote]" id="release[remote]" />
32
+ <RakeTaskImpl description="Run tests" fullCommand="test" id="test" />
33
+ <RakeTaskImpl description="" fullCommand="default" id="default" />
34
+ <RakeTaskImpl description="" fullCommand="release" id="release" />
35
+ <RakeTaskImpl id="release">
36
+ <subtasks>
37
+ <RakeTaskImpl description="" fullCommand="release:guard_clean" id="guard_clean" />
38
+ <RakeTaskImpl description="" fullCommand="release:rubygem_push" id="rubygem_push" />
39
+ <RakeTaskImpl description="" fullCommand="release:source_control_push" id="source_control_push" />
40
+ </subtasks>
41
+ </RakeTaskImpl>
42
+ </subtasks>
43
+ </RakeTaskImpl>
44
+ </option>
45
+ </component>
46
+ </module>
data/.idea/modules.xml ADDED
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/ada_numbers.iml" filepath="$PROJECT_DIR$/.idea/ada_numbers.iml" />
6
+ <module fileurl="file://$PROJECT_DIR$/../.idea/ada_numbers_gem.iml" filepath="$PROJECT_DIR$/../.idea/ada_numbers_gem.iml" />
7
+ </modules>
8
+ </component>
9
+ </project>
data/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
5
+ </component>
6
+ </project>
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ada_numbers.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "minitest", "~> 5.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,21 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ada_numbers (1.0.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ minitest (5.18.0)
10
+ rake (12.3.3)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ ada_numbers!
17
+ minitest (~> 5.0)
18
+ rake (~> 12.0)
19
+
20
+ BUNDLED WITH
21
+ 2.1.4
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,30 @@
1
+ require_relative 'lib/ada_numbers/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "ada_numbers"
5
+ spec.version = AdaNumbers::VERSION
6
+ spec.authors = ["Roberto W. P. Ribeiro"]
7
+ spec.email = ["rober.will@hotmail.com"]
8
+
9
+ spec.summary = %q{It converts a number to its equivalent in written words,
10
+ i.e. 123 to "cento e vinte três" or to "one hundred and twenty-three", and vice versa.}
11
+ spec.description = %q{It converts a number to its equivalent in written words,
12
+ i.e. 123 to "cento e vinte três" or to "one hundred and twenty-three", and vice versa.}
13
+ spec.homepage = "https://github.com/roberwil/ada_numbers_gem"
14
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = "https://github.com/roberwil/ada_numbers_gem"
18
+ spec.metadata["changelog_uri"] = "https://github.com/roberwil/ada_numbers_gem/blob/main/CHANGELOG.md"
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
+ end
25
+
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+ spec.license = "MIT"
30
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ada_numbers"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,11 @@
1
+ module AdaNumbers
2
+ module Separator
3
+ class En
4
+ NUMBERS_SEPARATOR = "And"
5
+ DECIMAL_SEPARATOR = "Point"
6
+ DECIMAL_SEPARATOR_ALTERNATIVE = "Comma"
7
+ COMMA = ","
8
+ DASH = "-"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,113 @@
1
+ module AdaNumbers
2
+ module WrittenNumber
3
+ class En
4
+ ZERO = "Zero"
5
+ ONE = "One"
6
+ TWO = "Two"
7
+ THREE = "Three"
8
+ FOUR = "Four"
9
+ FIVE = "Five"
10
+ SIX = "Six"
11
+ SEVEN = "Seven"
12
+ EIGHT = "Eight"
13
+ NINE = "Nine"
14
+ TEN = "Ten"
15
+ ELEVEN = "Eleven"
16
+ TWELVE = "Twelve"
17
+ THIRTEEN = "Thirteen"
18
+ FOURTEEN = "Fourteen"
19
+ FIFTEEN = "Fifteen"
20
+ SIXTEEN = "Sixteen"
21
+ SEVENTEEN = "Seventeen"
22
+ EIGHTEEN = "Eighteen"
23
+ NINETEEN = "Nineteen"
24
+ TWENTY = "Twenty"
25
+ THIRTY = "Thirty"
26
+ FORTY = "Forty"
27
+ FIFTY = "Fifty"
28
+ SIXTY = "Sixty"
29
+ SEVENTY = "Seventy"
30
+ EIGHTY = "Eighty"
31
+ NINETY = "Ninety"
32
+ HUNDRED = "Hundred"
33
+ THOUSAND = "Thousand"
34
+ MILLION = "Million"
35
+ THOUSAND_MILLION = "Thousand Million"
36
+ BILLION = "Billion"
37
+ TRILLION = "Trillion"
38
+
39
+ @@numbers_that_ignore_separator = [
40
+ HUNDRED, THOUSAND, MILLION,
41
+ THOUSAND_MILLION, BILLION, TRILLION
42
+ ]
43
+
44
+ def self.numbers_that_ignore_separator; @@numbers_that_ignore_separator; end
45
+
46
+ @@unities_that_combine_with_separator = [
47
+ TWENTY, THIRTY, FORTY, FIFTY,
48
+ SIXTY, SEVENTY, EIGHTY, NINETY
49
+ ]
50
+
51
+ def self.unities_that_combine_with_separator; @@unities_that_combine_with_separator; end
52
+
53
+ @@words_to_number_map = {
54
+ ZERO => 0, ONE => 1, TWO => 2, THREE => 3, FOUR => 4,
55
+ FIVE => 5, SIX => 6, SEVEN => 7, EIGHT => 8, NINE => 9,
56
+ TEN => 10, ELEVEN => 11, TWELVE => 12, THIRTEEN => 13, FOURTEEN => 14,
57
+ FIFTEEN => 15, SIXTEEN => 16, SEVENTEEN => 17, EIGHTEEN => 18, NINETEEN => 19,
58
+ TWENTY => 20, THIRTY => 30, FORTY => 40, FIFTY => 50, SIXTY => 60,
59
+ SEVENTY => 70, EIGHTY => 80, NINETY => 90, HUNDRED => 100, THOUSAND => 1e3.to_i,
60
+ MILLION => 1e6.to_i
61
+ }
62
+
63
+ def self.words_to_number_map; @@words_to_number_map; end
64
+
65
+ @@words_to_number_unities_and_tens_map = {
66
+ ZERO => 0, ONE => 1, TWO => 2, THREE => 3, FOUR => 4,
67
+ FIVE => 5, SIX => 6, SEVEN => 7, EIGHT => 8, NINE => 9,
68
+ TEN => 10, ELEVEN => 11, TWELVE => 12, THIRTEEN => 13, FOURTEEN => 14,
69
+ FIFTEEN => 15, SIXTEEN => 16, SEVENTEEN => 17, EIGHTEEN => 18, NINETEEN => 19,
70
+ TWENTY => 20, THIRTY => 30, FORTY => 40, FIFTY => 50, SIXTY => 60,
71
+ SEVENTY => 70, EIGHTY => 80, NINETY => 90
72
+ }
73
+
74
+ def self.words_to_number_unities_and_tens_map; @@words_to_number_unities_and_tens_map; end
75
+
76
+ @@words_to_number_map_long_scale = {
77
+ THOUSAND_MILLION => 1e9.to_i,
78
+ BILLION => 1e12.to_i
79
+ }
80
+
81
+ def self.words_to_number_map_long_scale; @@words_to_number_map_long_scale; end
82
+
83
+ @@words_to_number_map_short_scale = {
84
+ BILLION => 1e9.to_i,
85
+ TRILLION => 1e12.to_i
86
+ }
87
+
88
+ def self.words_to_number_map_short_scale; @@words_to_number_map_short_scale; end
89
+
90
+ @@not_to_combine_with_thousand = [
91
+ MILLION, BILLION, TRILLION
92
+ ]
93
+
94
+ def self.not_to_combine_with_thousand; @@not_to_combine_with_thousand; end
95
+
96
+ @@numbers_to_words_map_unities = {
97
+ 0 => ZERO, 1 => ONE, 2 => TWO , 3 => THREE, 4 => FOUR,
98
+ 5 => FIVE, 6 => SIX, 7 => SEVEN, 8 => EIGHT, 9 => NINE
99
+ }
100
+
101
+ def self.numbers_to_words_map_unities; @@numbers_to_words_map_unities; end
102
+
103
+ @@numbers_to_words_map_tens = {
104
+ 10 => TEN , 11 => ELEVEN , 12 => TWELVE , 13 => THIRTEEN, 14 => FOURTEEN,
105
+ 15 => FIFTEEN, 16 => SIXTEEN, 17 => SEVENTEEN, 18 => EIGHTEEN, 19 => NINETEEN,
106
+ 20 => TWENTY , 30 => THIRTY , 40 => FORTY , 50 => FIFTY , 60 => SIXTY ,
107
+ 70 => SEVENTY, 80 => EIGHTY , 90 => NINETY
108
+ }
109
+
110
+ def self.numbers_to_words_map_tens; @@numbers_to_words_map_tens; end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AdaNumbers
4
+ class Message
5
+ UNSUPPORTED = "Unsupported"
6
+ INVALID_NUMBER = "Invalid Number"
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module AdaNumbers
2
+ module Separator
3
+ class Pt
4
+ NUMBERS_SEPARATOR = "E"
5
+ DECIMAL_SEPARATOR = "Vírgula"
6
+ DECIMAL_SEPARATOR_ALTERNATIVE = "Ponto"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,116 @@
1
+ module AdaNumbers
2
+ module WrittenNumber
3
+ class Pt
4
+ ZERO = "Zero"
5
+ ONE = "Um"
6
+ TWO = "Dois"
7
+ THREE = "Três"
8
+ FOUR = "Quatro"
9
+ FIVE = "Cinco"
10
+ SIX = "Seis"
11
+ SEVEN = "Sete"
12
+ EIGHT = "Oito"
13
+ NINE = "Nove"
14
+ TEN = "Dez"
15
+ ELEVEN = "Onze"
16
+ TWELVE = "Doze"
17
+ THIRTEEN = "Treze"
18
+ FOURTEEN = "Catorze"
19
+ FIFTEEN = "Quinze"
20
+ SIXTEEN = "Dezasseis"
21
+ SEVENTEEN = "Dezassete"
22
+ EIGHTEEN = "Dezoito"
23
+ NINETEEN = "Dezanove"
24
+ TWENTY = "Vinte"
25
+ THIRTY = "Trinta"
26
+ FORTY = "Quarenta"
27
+ FIFTY = "Cinquenta"
28
+ SIXTY = "Sessenta"
29
+ SEVENTY = "Setenta"
30
+ EIGHTY = "Oitenta"
31
+ NINETY = "Noventa"
32
+ ONE_HUNDRED_SINGLE = "Cem"
33
+ ONE_HUNDRED = "Cento"
34
+ TWO_HUNDRED = "Duzentos"
35
+ THREE_HUNDRED = "Trezentos"
36
+ FOUR_HUNDRED = "Quatrocentos"
37
+ FIVE_HUNDRED = "Quinhentos"
38
+ SIX_HUNDRED = "Seiscentos"
39
+ SEVEN_HUNDRED = "Setecentos"
40
+ EIGHT_HUNDRED = "Oitocentos"
41
+ NINE_HUNDRED = "Novecentos"
42
+ THOUSAND = "Mil"
43
+ MILLION_SINGULAR = "Um Milhão"
44
+ MILLION_PLURAL = "Milhões"
45
+ THOUSAND_MILLION = "Mil Milhões"
46
+ BILLION_SINGULAR = "Um Bilião"
47
+ BILLION_PLURAL = "Biliões"
48
+ TRILLION_SINGULAR = "Um Trilião"
49
+ TRILLION_PLURAL = "Triliões"
50
+
51
+ @@numbers_that_ignore_separator = [
52
+ ONE_HUNDRED, TWO_HUNDRED, THREE_HUNDRED, FOUR_HUNDRED, FIVE_HUNDRED,
53
+ SIX_HUNDRED, SEVEN_HUNDRED, EIGHT_HUNDRED, NINE_HUNDRED, THOUSAND,
54
+ MILLION_SINGULAR, MILLION_PLURAL, THOUSAND_MILLION, BILLION_SINGULAR,
55
+ BILLION_PLURAL, TRILLION_SINGULAR, TRILLION_PLURAL
56
+ ]
57
+
58
+ def self.numbers_that_ignore_separator; @@numbers_that_ignore_separator; end
59
+
60
+ @@words_to_number_map = {
61
+ ZERO => 0, ONE => 1, TWO => 2, THREE => 3,
62
+ FOUR => 4, FIVE => 5, SIX => 6, SEVEN => 7,
63
+ EIGHT => 8, NINE => 9, TEN => 10, ELEVEN => 11,
64
+ TWELVE => 12, THIRTEEN => 13, FOURTEEN => 14, FIFTEEN => 15,
65
+ SIXTEEN => 16, SEVENTEEN => 17, EIGHTEEN => 18, NINETEEN => 19,
66
+ TWENTY => 20, THIRTY => 30, FORTY => 40, FIFTY => 50,
67
+ SIXTY => 60, SEVENTY => 70, EIGHTY => 80, NINETY => 90,
68
+ ONE_HUNDRED => 100, ONE_HUNDRED_SINGLE => 100, TWO_HUNDRED => 200, THREE_HUNDRED => 300,
69
+ FOUR_HUNDRED => 400, FIVE_HUNDRED => 500, SIX_HUNDRED => 600, SEVEN_HUNDRED => 700,
70
+ EIGHT_HUNDRED => 800, NINE_HUNDRED => 900, THOUSAND => 1e3.to_i, MILLION_SINGULAR => 1e6.to_i,
71
+ MILLION_PLURAL => 1e6.to_i
72
+ }
73
+
74
+ def self.words_to_number_map; @@words_to_number_map; end
75
+
76
+ @@words_to_number_map_long_scale = {
77
+ THOUSAND_MILLION => 1e9.to_i,
78
+ BILLION_SINGULAR => 1e12.to_i,
79
+ BILLION_PLURAL => 1e12.to_i
80
+ }
81
+
82
+ def self.words_to_number_map_long_scale; @@words_to_number_map_long_scale; end
83
+
84
+ @@words_to_number_map_short_scale = {
85
+ BILLION_SINGULAR => 1e9.to_i,
86
+ BILLION_PLURAL => 1e9.to_i,
87
+ TRILLION_SINGULAR => 1e12.to_i,
88
+ TRILLION_PLURAL => 1e12.to_i
89
+ }
90
+
91
+ def self.words_to_number_map_short_scale; @@words_to_number_map_short_scale; end
92
+
93
+ @@not_to_combine_with_thousand = [
94
+ MILLION_SINGULAR, BILLION_PLURAL, TRILLION_PLURAL
95
+ ]
96
+
97
+ def self.not_to_combine_with_thousand; @@not_to_combine_with_thousand; end
98
+
99
+ @@numbers_to_words_map_unities = {
100
+ 0 => ZERO, 1 => ONE, 2 => TWO , 3 => THREE, 4 => FOUR,
101
+ 5 => FIVE, 6 => SIX, 7 => SEVEN, 8 => EIGHT, 9 => NINE
102
+ }
103
+
104
+ def self.numbers_to_words_map_unities; @@numbers_to_words_map_unities; end
105
+
106
+ @@numbers_to_words_map_tens = {
107
+ 10 => TEN , 11 => ELEVEN , 12 => TWELVE , 13 => THIRTEEN, 14 => FOURTEEN,
108
+ 15 => FIFTEEN, 16 => SIXTEEN, 17 => SEVENTEEN, 18 => EIGHTEEN, 19 => NINETEEN,
109
+ 20 => TWENTY , 30 => THIRTY , 40 => FORTY , 50 => FIFTY , 60 => SIXTY ,
110
+ 70 => SEVENTY, 80 => EIGHTY , 90 => NINETY
111
+ }
112
+
113
+ def self.numbers_to_words_map_tens; @@numbers_to_words_map_tens; end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,185 @@
1
+ require_relative '../../utilities/integer_extensions'
2
+ require_relative '../../utilities/hash_extensions'
3
+ require_relative '../../utilities/settings'
4
+ require_relative '../../utilities/number_category'
5
+
6
+ require_relative '../../constants/en/written_numbers'
7
+ require_relative '../../constants/en/separators'
8
+ require_relative '../../constants/message'
9
+
10
+ module AdaNumbers
11
+ module NumberToWordsConverter
12
+ class En
13
+ @@use_short_scale = false
14
+ @@number_tokens = []
15
+
16
+ def self.convert(number)
17
+ return convert_integer(number) if number.class == Integer
18
+ return convert_float(number)
19
+ end
20
+
21
+ private
22
+
23
+ def self.convert_integer(number)
24
+ return Message::UNSUPPORTED if number.number_of_digits > Settings::Parameters::DIGITS_LIMIT
25
+
26
+ select_scale
27
+ @@number_tokens.clear
28
+ return resolve_number number
29
+ end
30
+
31
+ def self.convert_float(number)
32
+ select_scale
33
+
34
+ str_number = number.to_s.split '.'
35
+
36
+ str_integer_part = str_number.first
37
+ str_decimal_part = str_number.size == 1 ? "0" : str_number.last
38
+
39
+ return Message::UNSUPPORTED if str_integer_part.size > Settings::Parameters::DIGITS_LIMIT || str_decimal_part.size > Settings::Parameters::DIGITS_LIMIT
40
+
41
+ whole_part = str_integer_part.to_i
42
+ decimal_part = str_decimal_part.to_i
43
+
44
+ @@number_tokens.clear
45
+ result = resolve_number whole_part
46
+
47
+ return result if decimal_part == 0
48
+
49
+ result += " #{Separator::En::DECIMAL_SEPARATOR.downcase} "
50
+ # just aggregating the zeros
51
+ result += str_decimal_part.split('').
52
+ take_while { |c| c == "0" }.
53
+ collect { |c| WrittenNumber::En::ZERO }.
54
+ join ' '
55
+
56
+ @@number_tokens.clear
57
+ result += result[-1] == ' ' ? resolve_number(decimal_part) :
58
+ " #{resolve_number(decimal_part)}"
59
+
60
+ return result
61
+ end
62
+
63
+ def self.select_scale
64
+ @@use_short_scale = Settings.scale == Settings::Parameters::SCALES[:short]
65
+ end
66
+
67
+ def self.resolve_number(number)
68
+ result = ''
69
+ number_category = number.category
70
+
71
+ case number_category
72
+ when NumberCategory::UNITY
73
+ result = unities number
74
+ when NumberCategory::TEN
75
+ result = tens number
76
+ when NumberCategory::HUNDRED
77
+ result = hundreds number
78
+ when NumberCategory::THOUSAND
79
+ result = thousands number
80
+ when NumberCategory::MILLION
81
+ result = millions number
82
+ when NumberCategory::THOUSAND_MILLIONS
83
+ result = thousand_millions number
84
+ when NumberCategory::BILLION
85
+ result = billions number
86
+ end
87
+
88
+ if result.empty?
89
+ str_number = number.to_s
90
+ bridge = number.bridge
91
+
92
+ first_digits = (str_number[0...bridge] + '0' * number_category).to_i
93
+ other_digits = (str_number[bridge..-1]).to_i
94
+
95
+ resolve_number first_digits
96
+ resolve_number other_digits
97
+ else
98
+ @@number_tokens << result
99
+ end
100
+
101
+ add_separators_to_number @@number_tokens
102
+ end
103
+
104
+ def self.unity_or_ten?(number)
105
+ result = !WrittenNumber::En.words_to_number_unities_and_tens_map.resolve(number).nil?
106
+ result ? result : number.include?(Separator::En::DASH)
107
+ end
108
+
109
+ def self.add_separators_to_number(number_tokens)
110
+ result = number_tokens.first
111
+
112
+ (1...number_tokens.size).each do |cursor|
113
+ current_token = number_tokens[cursor]
114
+
115
+ is_hundred = cursor + 1 < number_tokens.size && unity_or_ten?(current_token) &&
116
+ (number_tokens[cursor + 1] == WrittenNumber::En::HUNDRED ||
117
+ number_tokens[cursor + 1] == WrittenNumber::En::THOUSAND ||
118
+ number_tokens[cursor + 1] == WrittenNumber::En::MILLION ||
119
+ number_tokens[cursor + 1] == WrittenNumber::En::THOUSAND_MILLION ||
120
+ number_tokens[cursor + 1] == WrittenNumber::En::BILLION ||
121
+ number_tokens[cursor + 1] == WrittenNumber::En::TRILLION)
122
+
123
+ add_comma = cursor > 1 && is_hundred
124
+ no_separator = WrittenNumber::En.numbers_that_ignore_separator.include?(current_token) || is_hundred
125
+
126
+ if (add_comma)
127
+ result += "#{Separator::En::COMMA} #{current_token}"
128
+ elsif no_separator
129
+ result += " #{current_token}"
130
+ else
131
+ result += " #{Separator::En::NUMBERS_SEPARATOR.downcase} #{current_token}"
132
+ end
133
+ end
134
+
135
+ return result
136
+ end
137
+
138
+ def self.unities(number)
139
+ WrittenNumber::En.numbers_to_words_map_unities.resolve number
140
+ end
141
+
142
+ def self.tens(number)
143
+ result = WrittenNumber::En.numbers_to_words_map_tens.resolve number
144
+ return result if result != ''
145
+
146
+ bridge = number.bridge
147
+ ten = number.to_s[0...bridge].to_i * 10
148
+ unity = number.to_s[bridge..-1].to_i
149
+
150
+ result = "#{tens(ten)}#{Separator::En::DASH}#{unities(unity).downcase}"
151
+ result
152
+ end
153
+
154
+ def self.hundreds(number)
155
+ evaluate_hundreds_and_over number, 1e2.to_i, WrittenNumber::En::HUNDRED
156
+ end
157
+
158
+ def self.thousands(number)
159
+ evaluate_hundreds_and_over number, 1e3.to_i, WrittenNumber::En::THOUSAND
160
+ end
161
+
162
+ def self.millions(number)
163
+ evaluate_hundreds_and_over number, 1e6.to_i, WrittenNumber::En::MILLION
164
+ end
165
+
166
+ def self.thousand_millions(number)
167
+ qualifier = (@@use_short_scale ? WrittenNumber::En::BILLION : WrittenNumber::En::THOUSAND_MILLION)
168
+ evaluate_hundreds_and_over number, 1e9.to_i, qualifier
169
+ end
170
+
171
+ def self.billions(number)
172
+ qualifier = (@@use_short_scale ? WrittenNumber::En::TRILLION : WrittenNumber::En::BILLION)
173
+ evaluate_hundreds_and_over number, 1e12.to_i, qualifier
174
+ end
175
+
176
+ def self.evaluate_hundreds_and_over(number, category_identifier, qualifier)
177
+ return '' if number % category_identifier != 0
178
+
179
+ partial_number = number.to_s[0...number.bridge].to_i
180
+ resolve_number partial_number
181
+ return qualifier
182
+ end
183
+ end
184
+ end
185
+ end