extenso_pt 0.5.7 → 0.5.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9801fcabf1093be0b72526b73018bc35a4ba41dcd7ed605a56a47096cf8b30a6
4
- data.tar.gz: e8e1a1103571ebc158c1c915d0146d9727e29f46d77418300dbcf42e01e9fe8e
3
+ metadata.gz: 957540b2bccdc61b30b6c221465b11573c9570720729dafd3df982ab73216da1
4
+ data.tar.gz: 4f2159763f75b938535d61c293834f0f039395d577521d7d8d56cbe19592fe42
5
5
  SHA512:
6
- metadata.gz: b69172bc248e90890a9c5ac2283e30b3d63208d0553ec6f95535f844aacd98f0d82fba7e2fbf779d3d7ed386e5170b085dc2f91cd518b58e3a40ca664ce991b0
7
- data.tar.gz: afda6adfd8b283323fd801344659fdf2238bf273d080d1d710b2b2169e3cd9ebc0bdc358b1baf0e53e5a5657090e77abe29e3aefb5d78e19065cb39aeeae0ae9
6
+ metadata.gz: ec98f28a4969f2ed153086b55b781b89c617276d4d16bbb3de600dfa765b083a7ee6abd832a0f7d44eb13f7801deb189e1f7dc2890210934dbf5b27f09a79175
7
+ data.tar.gz: af1f863cad4cbce9c8aeaceb0353ccc2518ca7155428fa5fb4554fc095eecacae9222e1337cb7261462900b0f383dfd2cc1fa9c4ea913daf9bc9ad77a85022ed
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- extenso_pt (0.5.7)
4
+ extenso_pt (0.5.8)
5
+ bigdecimal (~> 1.4.4)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
@@ -14,7 +15,6 @@ PLATFORMS
14
15
  ruby
15
16
 
16
17
  DEPENDENCIES
17
- bigdecimal (~> 1.4.4)
18
18
  bundler (~> 1.17)
19
19
  extenso_pt!
20
20
  minitest (~> 5.0)
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ExtensoPt [![Build Status](https://travis-ci.org/hernanilr/extenso_pt.svg?branch=master)](https://travis-ci.org/hernanilr/extenso_pt)
2
2
 
3
- Produz valores monetários por extenso em portugês de portugal ou brasil. Os valores podem ser um numerico, uma string de digitos ou um conjunto destes (array, range, hash). O extenso pode ser produzido na escala longa (utilizada em todos os países lusófonos) ou na escala curta (utilizada no Brasil) [wiki](https://pt.wikipedia.org/wiki/Escalas_curta_e_longa). Pode ainda escolher a moeda e a fração da moeda.
3
+ Converte valores monetários em extenso de portugês de portugal, brasil ou numeracao romana. Os valores podem ser um numerico, uma string de digitos ou um conjunto destes (array, range, hash). O extenso pode ser produzido na escala longa (utilizada em todos os países lusófonos) ou na escala curta (utilizada no Brasil) [wiki](https://pt.wikipedia.org/wiki/Escalas_curta_e_longa). Pode ainda converter os valores em numeracao romana e vice versa.
4
4
 
5
5
  ## Installation
6
6
 
@@ -21,7 +21,9 @@ Or install it yourself as:
21
21
  ## Usage
22
22
 
23
23
  ```ruby
24
- "1234".extenso => "MIL DUZENTOS E TRINTA E QUATRO EUROS"
24
+ 1234.extenso => "MIL DUZENTOS E TRINTA E QUATRO EUROS"
25
+ 1234.romana => "MCCXXXIV"
26
+ "MCCXXXIV".romana => 1234
25
27
  12000000.12.extenso => "DOZE MILHÕES DE EUROS E DOZE CÊNTIMOS"
26
28
  1.01.extenso(msingular:"DÓLAR") => "UM DÓLAR E UM CÊNTIMO"
27
29
  10.1.extenso(mplural:"DÓLARES") => "DEZ DÓLARES E DEZ CÊNTIMOS" # plural inferido <silgular> mais "S"
data/extenso_pt.gemspec CHANGED
@@ -12,14 +12,14 @@ Gem::Specification.new do |spec|
12
12
  spec.homepage = 'https://github.com/hernanilr/extenso_pt'
13
13
  spec.license = 'MIT'
14
14
 
15
- spec.summary = 'Produz valores monetários por extenso '\
16
- 'em portugês de portugal ou brasil.'
17
-
18
- spec.description = spec.summary + ' Os valores podem ser um numerico, uma '\
19
- 'string de digitos ou um conjunto destes (array, range, hash). O extenso '\
20
- 'pode ser produzido na escala longa (utilizada em todos os países '\
21
- 'lusófonos) ou na escala curta (utilizada no Brasil). Pode ainda escolher '\
22
- 'a moeda e a fração da moeda.'
15
+ spec.summary = 'Converte valores monetários em extenso de portugês de ' \
16
+ 'portugal, brasil ou numeracao romana.'
17
+ spec.description = spec.summary
18
+ spec.description += ' Os valores podem ser um numerico, uma string ' \
19
+ 'de digitos ou um conjunto destes (array, range, hash). O extenso ' \
20
+ 'pode ser produzido na escala longa (utilizada em todos os países ' \
21
+ 'lusófonos) ou na escala curta (utilizada no Brasil). Pode ainda ' \
22
+ 'converter os valores em numeracao romana e vice versa.'
23
23
 
24
24
  spec.metadata['yard.run'] = 'yard' # use "yard" to build full HTML docs.
25
25
  spec.metadata['homepage_uri'] = spec.homepage
@@ -34,8 +34,9 @@ Gem::Specification.new do |spec|
34
34
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
35
  spec.require_paths = ['lib']
36
36
 
37
- spec.add_development_dependency 'bigdecimal', '~> 1.4.4'
38
37
  spec.add_development_dependency 'bundler', '~> 1.17'
39
38
  spec.add_development_dependency 'minitest', '~> 5.0'
40
39
  spec.add_development_dependency 'rake', '~> 10.0'
40
+
41
+ spec.add_dependency 'bigdecimal', '~> 1.4.4'
41
42
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @author Hernani Rodrigues Vaz
4
+ module ExtensoPt
5
+ # constantes para producao de extenso em portugues de portugal ou brasil
6
+ EXTLC = %i[pt br].freeze
7
+ A0020 = {
8
+ pt: ['', 'UM', 'DOIS', 'TRÊS', 'QUATRO', 'CINCO', 'SEIS', 'SETE',
9
+ 'OITO', 'NOVE', 'DEZ', 'ONZE', 'DOZE', 'TREZE', 'CATORZE',
10
+ 'QUINZE', 'DEZASSEIS', 'DEZASSETE', 'DEZOITO', 'DEZANOVE'],
11
+ br: ['', 'UM', 'DOIS', 'TRES', 'QUATRO', 'CINCO', 'SEIS', 'SETE',
12
+ 'OITO', 'NOVE', 'DEZ', 'ONZE', 'DOZE', 'TREZE', 'QUATORZE',
13
+ 'QUINZE', 'DEZESSEIS', 'DEZESSETE', 'DEZOITO', 'DEZENOVE']
14
+ }.freeze
15
+ A0100 = {
16
+ pt: ['', '', 'VINTE', 'TRINTA', 'QUARENTA', 'CINQUENTA', 'SESSENTA',
17
+ 'SETENTA', 'OITENTA', 'NOVENTA'],
18
+ br: ['', '', 'VINTE', 'TRINTA', 'QUARENTA', 'CINQUENTA', 'SESSENTA',
19
+ 'SETENTA', 'OITENTA', 'NOVENTA']
20
+ }.freeze
21
+ A1000 = {
22
+ pt: ['', 'CEM', 'CENTO', 'DUZENTOS', 'TREZENTOS', 'QUATROCENTOS',
23
+ 'QUINHENTOS', 'SEISCENTOS', 'SETECENTOS', 'OITOCENTOS', 'NOVECENTOS'],
24
+ br: ['', 'CEM', 'CENTO', 'DUZENTOS', 'TREZENTOS', 'QUATROCENTOS',
25
+ 'QUINHENTOS', 'SEISCENTOS', 'SETECENTOS', 'OITOCENTOS', 'NOVECENTOS']
26
+ }.freeze
27
+
28
+ # escala longa portugal segundo convencao entre varios paises,
29
+ # na 9a Conferencia Geral de Pesos e Medidas (12-21 de Outubro de 1948),
30
+ # organizada pelo Bureau International des Poids et Mesures
31
+ # 1 000 000 = milhao
32
+ # 1 000 000 000 000 = biliao
33
+ # 1 000 000 000 000 000 000 = triliao
34
+ # 1 000 000 000 000 000 000 000 000 = quadriliao
35
+ # 1 000 000 000 000 000 000 000 000 000 000 = quintiliao
36
+ # 1 000 000 000 000 000 000 000 000 000 000 000 000 = sextiliao
37
+ S1E24 = { pt: ['', 'MIL', ' MILHÃO', ' MIL MILHÃO', ' BILIÃO',
38
+ ' MIL BILIÃO', ' TRILIÃO', ' MIL TRILIÃO'],
39
+ br: ['', 'MIL', ' MILHÃO', ' BILHÃO', ' TRILHÃO',
40
+ ' QUADRILHÃO', ' QUINTILHÃO', ' SEXTILHÃO'] }.freeze
41
+ P1E24 = { pt: ['', ' MIL', ' MILHÕES', ' MIL MILHÕES', ' BILIÕES',
42
+ ' MIL BILIÕES', ' TRILIÕES', ' MIL TRILIÕES'],
43
+ br: ['', ' MIL', ' MILHÕES', ' BILHÕES', ' TRILHÕES',
44
+ ' QUADRILHÕES', ' QUINTILHÕES', ' SEXTILHÕES'] }.freeze
45
+
46
+ # contantes para numeracao romana
47
+ ROMAN = { M: 1000, CM: 900,
48
+ D: 500, CD: 400,
49
+ C: 100, XC: 90,
50
+ L: 50, XL: 40,
51
+ X: 10, IX: 9,
52
+ V: 5, IV: 4,
53
+ I: 1 }.freeze
54
+ # numeral romano
55
+ RO_RE = /^M*(D?C{0,3}|C[DM])(L?X{0,3}|X[LC])(V?I{0,3}|I[VX])$/i.freeze
56
+ end
@@ -0,0 +1,219 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @author Hernani Rodrigues Vaz
4
+ module ExtensoPt
5
+ # Produz o extenso das centenas em portugues de portugal ou brasil
6
+ #
7
+ # @param [Integer] mil o valor dum grupo 3 digitos a converter
8
+ # @return [String] o extenso das centenas
9
+ def self.e900(mil)
10
+ A1000[@lc][(mil > 100 ? 1 : 0) + mil / 100] +
11
+ (mil > 100 && (mil % 100).positive? ? ' E ' : '') # proposicao
12
+ end
13
+
14
+ # Produz o extenso das dezenas em portugues de portugal ou brasil
15
+ #
16
+ # @param [Integer] cem o valor dum grupo 3 digitos a converter
17
+ # @return [String] o extenso das dezenas
18
+ def self.e90(cem)
19
+ A0100[@lc][cem / 10] +
20
+ (cem > 20 && (cem % 10).positive? ? ' E ' : '') # proposicao
21
+ end
22
+
23
+ # Produz o extenso das unidades em portugues de portugal ou brasil
24
+ #
25
+ # @param [Integer] cem o valor dum grupo 3 digitos a converter
26
+ # @return [String] o extenso das unidades
27
+ def self.e9(cem)
28
+ A0020[@lc][cem < 20 ? cem : cem % 10]
29
+ end
30
+
31
+ # Produz extenso parte fracionaria em portugues de portugal ou brasil
32
+ #
33
+ # @return [String] o extenso da parte fracionaria dum valor monetario
34
+ def self.ef99
35
+ # parametrizacao por defeito
36
+ @cs ||= 'CÊNTIMO'
37
+ @cp ||= @ms + 'S'
38
+
39
+ if @nf.positive?
40
+ e90(@nf) + e9(@nf) + (@nf > 1 ? ' ' + @cp : ' ' + @cs)
41
+ else
42
+ ''
43
+ end
44
+ end
45
+
46
+ # Produz final da moeda em portugues de portugal ou brasil
47
+ #
48
+ # @return [String] o final da moeda
49
+ def self.efim
50
+ # parametrizacao por defeito
51
+ @ms ||= 'EURO'
52
+ @mp ||= @ms + 'S'
53
+
54
+ # proposicao DE entre parte inteira e moeda
55
+ emo = @de ? ' DE' : ''
56
+ # moeda singular/plural
57
+ emo += @tt > 1 ? ' ' + @mp : ' ' + @ms if @tt.positive?
58
+ # proposicao E entre moeda e parte fracionaria
59
+ # extenso da parte fracionaria
60
+ emo + (@tt.positive? && @nf.positive? ? ' E ' : '') + ef99
61
+ end
62
+
63
+ # Produz separador entre grupos 3 digitos
64
+ #
65
+ # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
66
+ # @return [String] separador entre grupos 3 digitos
67
+ def self.esep(pos)
68
+ if pos.positive? && @ai[pos - 1].positive?
69
+ @ai[pos - 1] > 100 ? ' ' : ' E '
70
+ else
71
+ ''
72
+ end
73
+ end
74
+
75
+ # Produz qualificador grupo de 3 digitos em portugues de portugal ou brasil
76
+ #
77
+ # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
78
+ # @return [String] qualificador grupo de 3 digitos
79
+ def self.e1e24(pos)
80
+ if @ai[pos].positive?
81
+ @ai[pos] > 1 ? P1E24[@lc][pos] : S1E24[@lc][pos]
82
+ else
83
+ ''
84
+ end
85
+ end
86
+
87
+ # Produz extenso grupo 3 digitos em portugues de portugal ou brasil
88
+ #
89
+ # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
90
+ # @return [String] extenso grupo 3 digitos
91
+ def self.edg3(pos)
92
+ # parametrizacao por defeito
93
+ # the first mention of an @<variable> creates the
94
+ # instance variable in the current object ie: self = ExtensoPt
95
+ @lc ||= :pt
96
+
97
+ dg3 = if pos == 1 && @ai[pos] == 1
98
+ # caso especial MIL EUROS
99
+ ''
100
+ else
101
+ e900(@ai[pos]) + e90(@ai[pos] % 100) + e9(@ai[pos] % 100)
102
+ end
103
+ # qualificador grupo de 3 digitos
104
+ dg3 + e1e24(pos)
105
+ end
106
+
107
+ # Parametrizar controle singular/plural & proposicoes
108
+ #
109
+ # @return [void]
110
+ def self.pcontrolo
111
+ # soma grupos 1,2 (primeiros 6 digitos)
112
+ @s6 = @ai[0].to_i + @ai[1].to_i * 2
113
+ # soma grupos 3.. (digitos acima de 6)
114
+ @m6 = @ai[2..-1].to_a.inject(:+).to_i * 2
115
+ @tt = @s6 + @m6 # proposicao E & singular/plural
116
+ @de = @s6.zero? && @m6.positive? # proposicao DE
117
+ end
118
+
119
+ # Produz o extenso dum valor monetario em portugues de portugal ou brasil
120
+ #
121
+ # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
122
+ # @param [String] ext extenso em construcao
123
+ # @return [String] o extenso dum valor monetario
124
+ def self.emonetario(pos, ext)
125
+ # testa fim do valor monetario
126
+ if pos >= @ai.count
127
+ # parametrizar controle singular/plural & proposicoes
128
+ pcontrolo
129
+
130
+ # caso especial zero
131
+ (@tt + @nf).zero? ? 'ZERO ' + @mp : ext + efim
132
+ else
133
+ # tratamento do proximo grupo 3 digitos
134
+ emonetario(pos + 1, edg3(pos) + esep(pos) + ext)
135
+ end
136
+ end
137
+
138
+ # Parametrizar parte inteira/fracionaria do valor monetario
139
+ #
140
+ # @param [String] digitos do valor monetario
141
+ # @return [void]
142
+ def self.pintfra(dig)
143
+ # parte inteira do valor monetario => array grupos 3 digitos
144
+ # ex: 123022.12 => [22, 123]
145
+ @ai = dig[/^\d+/].to_s.reverse.scan(/\d{1,3}/).map { |i| i.reverse.to_i }
146
+
147
+ # parte fracionaria do valor monetario
148
+ # ex: 123022.12 => 12
149
+ # arredondada a 2 casas decimais (centimos/centavos)
150
+ @nf = (dig[/\.\d*/].to_f * 100).round
151
+ end
152
+
153
+ # Converte objeto criando extenso(s) em portugues de portugal ou brasil
154
+ #
155
+ # @param [Object] obj objeto a converter
156
+ # (String, Float, Integer, Array, Range, Hash)
157
+ # @return [String, Array, Hash] string extenso
158
+ # se objecto for (String, Float, Integer),
159
+ # array<extensos> se objecto for (Array, Range),
160
+ # hash<extensos> se objecto for (Hash)
161
+ def self.o2e(obj)
162
+ if obj.is_a?(Hash)
163
+ # converte os valores do Hash nos seus extensos - devolve um Hash
164
+ obj.map { |k, v| [k, o2e(v)] }.to_h
165
+ elsif obj.respond_to?(:to_a)
166
+ # converte o objecto num Array com os extensos dos valores
167
+ obj.to_a.map { |a| o2e(a) }
168
+ else
169
+ # converte objeto em string digitos utilizando bigdecimal para
170
+ # evitar problemas com aritmetica virgula flutuante em valores >1e12
171
+ digitos = obj.to_d.to_s('F')
172
+
173
+ # parametrizar parte inteira/fracionaria (@ai, @nf) do valor monetario
174
+ pintfra(digitos)
175
+
176
+ # processar extenso - valores superiores a 1e24 nao sao tratados
177
+ digitos[/^\d+/].length <= 24 ? emonetario(0, '') : ''
178
+ end
179
+ end
180
+
181
+ # Parametrizar moeda inferindo singular a partir do plural
182
+ #
183
+ # @param [Hash] moeda as opcoes para parametrizar a moeda/fracao
184
+ # @option moeda [Symbol] :lc locale do extenso -
185
+ # portugues de portugal (:pt) ou brasil (:br)
186
+ # @option moeda [String] :msingular moeda no singular -
187
+ # inferido do plural menos"S"
188
+ # @option moeda [String] :fsingular fracao no singular -
189
+ # inferido do plural menos "S"
190
+ # @option moeda [String] :mplural moeda no plural
191
+ # @option moeda [String] :fplural fracao no plural
192
+ # @return [void]
193
+ def self.psingular(moeda)
194
+ @ms = moeda[:msingular] ||
195
+ (moeda[:mplural].to_s[-1] == 'S' ? moeda[:mplural][0..-2] : 'EURO')
196
+ @cs = moeda[:fsingular] ||
197
+ (moeda[:fplural].to_s[-1] == 'S' ? moeda[:fplural][0..-2] : 'CÊNTIMO')
198
+ end
199
+
200
+ # Parametrizar moeda inferindo plural a partir do singular
201
+ #
202
+ # @param [Hash] moeda as opcoes para parametrizar a moeda/fracao
203
+ # @option moeda [Symbol] :lc locale do extenso -
204
+ # portugues de portugal (:pt) ou brasil (:br)
205
+ # @option moeda [String] :msingular moeda no singular
206
+ # @option moeda [String] :fsingular fracao no singular
207
+ # @option moeda [String] :mplural moeda no plural -
208
+ # inferido do singular mais "S"
209
+ # @option moeda [String] :fplural fracao no plural -
210
+ # inferido do singular mais "S"
211
+ # @return [void]
212
+ def self.pplural(moeda)
213
+ # somente [:pt, :br]
214
+ @lc = EXTLC.include?(moeda[:lc]) ? moeda[:lc] : :pt
215
+
216
+ @mp = moeda[:mplural] || @ms + 'S'
217
+ @cp = moeda[:fplural] || @cs + 'S'
218
+ end
219
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ExtensoPt
4
- VERSION = '0.5.7'
4
+ VERSION = '0.5.8'
5
5
  end
data/lib/extenso_pt.rb CHANGED
@@ -1,247 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'extenso_pt/version'
4
3
  require 'bigdecimal/util'
5
-
6
- LC = %i[pt br].freeze
7
- A0020 = {
8
- pt: ['', 'UM', 'DOIS', 'TRÊS', 'QUATRO', 'CINCO', 'SEIS', 'SETE',
9
- 'OITO', 'NOVE', 'DEZ', 'ONZE', 'DOZE', 'TREZE', 'CATORZE',
10
- 'QUINZE', 'DEZASSEIS', 'DEZASSETE', 'DEZOITO', 'DEZANOVE'],
11
- br: ['', 'UM', 'DOIS', 'TRES', 'QUATRO', 'CINCO', 'SEIS', 'SETE',
12
- 'OITO', 'NOVE', 'DEZ', 'ONZE', 'DOZE', 'TREZE', 'QUATORZE',
13
- 'QUINZE', 'DEZESSEIS', 'DEZESSETE', 'DEZOITO', 'DEZENOVE']
14
- }.freeze
15
- A0100 = {
16
- pt: ['', '', 'VINTE', 'TRINTA', 'QUARENTA', 'CINQUENTA', 'SESSENTA',
17
- 'SETENTA', 'OITENTA', 'NOVENTA'],
18
- br: ['', '', 'VINTE', 'TRINTA', 'QUARENTA', 'CINQUENTA', 'SESSENTA',
19
- 'SETENTA', 'OITENTA', 'NOVENTA']
20
- }.freeze
21
- A1000 = {
22
- pt: ['', 'CEM', 'CENTO', 'DUZENTOS', 'TREZENTOS', 'QUATROCENTOS',
23
- 'QUINHENTOS', 'SEISCENTOS', 'SETECENTOS', 'OITOCENTOS', 'NOVECENTOS'],
24
- br: ['', 'CEM', 'CENTO', 'DUZENTOS', 'TREZENTOS', 'QUATROCENTOS',
25
- 'QUINHENTOS', 'SEISCENTOS', 'SETECENTOS', 'OITOCENTOS', 'NOVECENTOS']
26
- }.freeze
27
- S1E24 = { pt: ['', 'MIL', ' MILHÃO', ' MIL MILHÃO', ' BILIÃO',
28
- ' MIL BILIÃO', ' TRILIÃO', ' MIL TRILIÃO'],
29
- br: ['', 'MIL', ' MILHÃO', ' BILHÃO', ' TRILHÃO',
30
- ' QUADRILHÃO', ' QUINTILHÃO', ' SEXTILHÃO'] }.freeze
31
- P1E24 = { pt: ['', ' MIL', ' MILHÕES', ' MIL MILHÕES', ' BILIÕES',
32
- ' MIL BILIÕES', ' TRILIÕES', ' MIL TRILIÕES'],
33
- br: ['', ' MIL', ' MILHÕES', ' BILHÕES', ' TRILHÕES',
34
- ' QUADRILHÕES', ' QUINTILHÕES', ' SEXTILHÕES'] }.freeze
4
+ require 'extenso_pt/version'
5
+ require 'extenso_pt/constantes'
6
+ require 'extenso_pt/module'
35
7
 
36
8
  # @author Hernani Rodrigues Vaz
37
9
  module ExtensoPt
38
10
  class Error < StandardError; end
39
11
 
40
- # Produz o extenso das centenas em portugues de portugal ou brasil.
41
- #
42
- # @param [Integer] mil o valor dum grupo 3 digitos a converter
43
- # @return [String] o extenso das centenas
44
- def self.e900(mil)
45
- A1000[@lc][(mil > 100 ? 1 : 0) + mil / 100] +
46
- (mil > 100 && (mil % 100).positive? ? ' E ' : '') # proposicao
47
- end
48
-
49
- # Produz o extenso das dezenas em portugues de portugal ou brasil.
50
- #
51
- # @param [Integer] mil o valor dum grupo 3 digitos a converter
52
- # @return [String] o extenso das dezenas
53
- def self.e90(mil)
54
- A0100[@lc][mil % 100 / 10] +
55
- (mil > 20 && (mil % 10).positive? ? ' E ' : '') # proposicao
56
- end
57
-
58
- # Produz o extenso das unidades em portugues de portugal ou brasil.
59
- #
60
- # @param [Integer] cem o valor dum grupo 3 digitos a converter
61
- # @return [String] o extenso das unidades
62
- def self.e9(cem)
63
- A0020[@lc][(cem < 20 ? cem : cem % 10)]
64
- end
65
-
66
- # Produz extenso parte fracionaria em portugues de portugal ou brasil.
67
- #
68
- # @return [String] o extenso da parte fracionaria dum valor monetario
69
- def self.ef99
70
- if @nf.positive?
71
- e90(@nf) + e9(@nf) + (@nf > 1 ? ' ' + @cp : ' ' + @cs)
72
- else
73
- ''
74
- end
75
- end
76
-
77
- # Produz final da moeda em portugues de portugal ou brasil.
78
- #
79
- # @return [String] o final da moeda
80
- def self.efim
81
- # proposicao DE entre parte inteira e moeda
82
- emo = @de ? ' DE' : ''
83
- # moeda singular/plural
84
- emo += @tt > 1 ? ' ' + @mp : ' ' + @ms if @tt.positive?
85
- # proposicao E entre moeda e parte fracionaria
86
- # extenso da parte fracionaria
87
- emo + (@tt.positive? && @nf.positive? ? ' E ' : '') + ef99
88
- end
89
-
90
- # Produz separador entre grupos 3 digitos
91
- #
92
- # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
93
- # @return [String] separador entre grupos 3 digitos
94
- def self.esep(pos)
95
- if pos.positive? && @ai[pos - 1].positive?
96
- @ai[pos - 1] > 100 ? ' ' : ' E '
97
- else
98
- ''
99
- end
100
- end
101
-
102
- # Produz qualificador grupo de 3 digitos em portugues de portugal ou brasil.
103
- #
104
- # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
105
- # @return [String] qualificador grupo de 3 digitos
106
- def self.e1e24(pos)
107
- if @ai[pos].positive?
108
- @ai[pos] > 1 ? P1E24[@lc][pos] : S1E24[@lc][pos]
109
- else
110
- ''
111
- end
112
- end
113
-
114
- # Produz extenso grupo 3 digitos em portugues de portugal ou brasil.
115
- #
116
- # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
117
- # @return [String] extenso grupo 3 digitos
118
- def self.edg3(pos)
119
- dg3 = if pos == 1 && @ai[pos] == 1
120
- # caso especial MIL EUROS
121
- ''
122
- else
123
- e900(@ai[pos]) + e90(@ai[pos]) + e9(@ai[pos] % 100)
124
- end
125
- # qualificador grupo de 3 digitos
126
- dg3 + e1e24(pos)
127
- end
128
-
129
- # Parametrizar controle singular/plural & proposicoes
130
- #
131
- # @return [void]
132
- def self.pcontrolo
133
- # soma grupos 1,2 (primeiros 6 digitos)
134
- @s6 = @ai[0].to_i + @ai[1].to_i * 2
135
- # soma grupos 3.. (digitos acima de 6)
136
- @m6 = @ai[2..-1].to_a.inject(:+).to_i * 2
137
- @tt = @s6 + @m6 # proposicao E & singular/plural
138
- @de = @s6.zero? && @m6.positive? # proposicao DE
139
- end
140
-
141
- # Produz o extenso dum valor monetario em portugues de portugal ou brasil.
142
- #
143
- # @param [Integer] pos posicao actual nos grupos 3 digitos do valor monetario
144
- # @param [String] ext extenso em construcao
145
- # @return [String] o extenso dum valor monetario
146
- def self.enumerico(pos = 0, ext = '')
147
- # testa fim do valor monetario
148
- if pos >= @ai.count
149
- # parametrizar controle singular/plural & proposicoes
150
- pcontrolo
151
-
152
- # caso especial zero
153
- (@tt + @nf).zero? ? 'ZERO ' + @mp : ext + efim
154
- else
155
- # tratamento do proximo grupo 3 digitos
156
- enumerico(pos + 1, edg3(pos) + esep(pos) + ext)
157
- end
158
- end
159
-
160
- # Parametrizar parte inteira/fracionaria do valor monetario
161
- #
162
- # @param [String] dig string de digitos rdo valor monetario
163
- # @return [void]
164
- def self.pintfra(dig)
165
- # parte inteira do valor monetario => array grupos 3 digitos
166
- # ex: 123022.12 => [22, 123]
167
- @ai = dig[/^\d+/].to_s.reverse.scan(/\d{1,3}/).map { |i| i.reverse.to_i }
168
-
169
- # parte fracionaria do valor monetario
170
- # ex: 123022.12 => 12
171
- # arredondada a 2 casas decimais (centimos/centavos)
172
- @nf = (dig[/\.\d*/].to_f * 100).round
173
- end
174
-
175
- # Converte um objeto criando extenso(s) em portugues de portugal ou brasil.
176
- #
177
- # @param [Object] objeto objeto a converter
178
- # (String, Float, Integer, Array, Range, Hash)
179
- # @return [String, Array<extensos>, Hash<extensos>] string extenso
180
- # se objecto for (String, Float, Integer),
181
- # array se objecto for (Array, Range),
182
- # hash se objecto for (Hash)
183
- def self.eobjeto(obj)
184
- if obj.is_a?(Hash)
185
- # converte os valores do Hash nos seus extensos - devolve um Hash
186
- obj.map { |k, v| [k, eobjeto(v)] }.to_h
187
- elsif obj.respond_to?(:to_a)
188
- # converte o objecto num Array com os extensos dos valores
189
- obj.to_a.map { |v| eobjeto(v) }
190
- else
191
- # converte objeto numa string de digitos
192
- # usa bigdecimal/util para evitar aritmetica binaria
193
- # (tem problemas com valores >1e12)
194
- # qualquer valor nao convertivel (ex: texto) resulta em "0.0"
195
- sdigitos = obj.to_d.to_s('F')
196
-
197
- # parametrizar parte inteira/fracionaria (@ai, @nf) do valor monetario
198
- pintfra(sdigitos)
199
-
200
- # processar extenso - valores superiores a 1e24 nao sao tratados
201
- sdigitos[/^\d+/].length <= 24 ? enumerico : ''
202
- end
203
- end
204
-
205
- # Parametrizar moeda inferindo singular a partir do plural
206
- #
207
- # @param [Hash] moeda as opcoes para parametrizar a moeda/fracao
208
- # @option moeda [Symbol] :lc locale do extenso -
209
- # portugues de portugal (:pt) ou brasil (:br)
210
- # @option moeda [String] :msingular moeda no singular -
211
- # inferido do plural menos "S"
212
- # @option moeda [String] :fsingular fracao no singular -
213
- # inferido do plural menos "S"
214
- # @option moeda [String] :mplural moeda no plural
215
- # @option moeda [String] :fplural fracao no plural
216
- # @return [void]
217
- def self.psingular(moeda)
218
- @ms = moeda[:msingular] ||
219
- (moeda[:mplural].to_s[-1] == 'S' ? moeda[:mplural][0..-2] : 'EURO')
220
- @cs = moeda[:fsingular] ||
221
- (moeda[:fplural].to_s[-1] == 'S' ? moeda[:fplural][0..-2] : 'CÊNTIMO')
222
- end
223
-
224
- # Parametrizar moeda inferindo plural a partir do singular
225
- #
226
- # @param [Hash] moeda as opcoes para parametrizar a moeda/fracao
227
- # @option moeda [Symbol] :lc locale do extenso -
228
- # portugues de portugal (:pt) ou brasil (:br)
229
- # @option moeda [String] :msingular moeda no singular
230
- # @option moeda [String] :fsingular fracao no singular
231
- # @option moeda [String] :mplural moeda no plural -
232
- # inferido do singular mais "S"
233
- # @option moeda [String] :fplural fracao no plural -
234
- # inferido do singular mais "S"
235
- # @return [void]
236
- def self.pplural(moeda)
237
- # somente [:pt, :br]
238
- @lc = LC.include?(moeda[:lc]) ? moeda[:lc] : :pt
239
-
240
- @mp = moeda[:mplural] || @ms + 'S'
241
- @cp = moeda[:fplural] || @cs + 'S'
242
- end
243
-
244
- # Produz extenso(s) de objeto(s) em portugues de portugal ou brasil.
12
+ # Produz extenso(s)) em portugues de portugal ou brasil
245
13
  #
246
14
  # @param [Hash] moeda as opcoes para parametrizar a moeda/fracao
247
15
  # @option moeda [Symbol] :lc locale do extenso -
@@ -250,10 +18,10 @@ module ExtensoPt
250
18
  # @option moeda [String] :fsingular fracao no singular
251
19
  # @option moeda [String] :mplural moeda no plural
252
20
  # @option moeda [String] :fplural fracao no plural
253
- # @return [String, Array<extensos>, Hash<extensos>] string extenso
21
+ # @return [String, Array, Hash] string extenso
254
22
  # se objecto for (String, Float, Integer),
255
- # array se objecto for (Array, Range),
256
- # hash se objecto for (Hash)
23
+ # array<extensos> se objecto for (Array, Range),
24
+ # hash<extensos> se objecto for (Hash)
257
25
  def extenso(moeda = { lc: :pt, msingular: 'EURO', fsingular: 'CÊNTIMO' })
258
26
  # parametrizacao por defeito para :br
259
27
  if moeda[:lc] == :br && !moeda[:msingular] && !moeda[:mplural]
@@ -264,8 +32,8 @@ module ExtensoPt
264
32
  ExtensoPt.psingular(moeda)
265
33
  ExtensoPt.pplural(moeda)
266
34
 
267
- # extenso do objeto
268
- ExtensoPt.eobjeto(self)
35
+ # cria extenso(s) em portugues de portugal ou brasil
36
+ ExtensoPt.o2e(self)
269
37
  end
270
38
  end
271
39
 
@@ -284,17 +52,68 @@ class Range
284
52
  include ExtensoPt
285
53
  end
286
54
 
287
- # permite obter o extenso dum Float
55
+ # permite obter o extenso de Float
288
56
  class Float
289
57
  include ExtensoPt
290
58
  end
291
59
 
292
- # permite obter o extenso dum Integer
60
+ # permite obter o extenso ou numeral romano de Integer
293
61
  class Integer
294
62
  include ExtensoPt
63
+
64
+ # Produz numeracao romana a partir do inteiro
65
+ #
66
+ # @return [String] numeracao romana
67
+ def romana
68
+ return "-#{i2r(-self)}" if negative?
69
+
70
+ i2r(self)
71
+ end
72
+
73
+ # Recursivamente produz numeral romano
74
+ #
75
+ # @param [Integer] numero a converter em numeral romano
76
+ # @return [String] numeral romano
77
+ def i2r(numero)
78
+ return '' if numero.zero?
79
+
80
+ ROMAN.each { |r, v| return r.to_s + i2r(numero - v) if v <= numero }
81
+ end
295
82
  end
296
83
 
297
- # permite obter o extenso duma String de digitos
84
+ # permite obter o extenso duma string de digitos ou
85
+ # inteiro duma string numeral romano
298
86
  class String
299
87
  include ExtensoPt
88
+
89
+ # Testa se string contem numeracao romana
90
+ #
91
+ # @return [true, false] sim ou nao numeracao romana
92
+ def romana?
93
+ RO_RE.match?(upcase)
94
+ end
95
+
96
+ # Produz inteiro a partir da numeracao romana
97
+ # ou numeracao romana a partir de string digitos
98
+ #
99
+ # @return [Integer, String] inteiro ou numeracao romana
100
+ def romana
101
+ return -self[/[^-]+/].romana if /-+/.match?(self)
102
+ return self[/^\d+/].to_i.romana if /^\d+/.match?(self)
103
+ return 0 unless romana?
104
+
105
+ r2i(upcase, 0)
106
+ end
107
+
108
+ # Recursivamente produz inteiro
109
+ #
110
+ # @param [String] numeral romano em convercao
111
+ # @param [Integer] ultimo numeral convertido
112
+ # @return [Integer] inteiro do numeral romano
113
+ def r2i(numeral, ultimo)
114
+ return 0 if numeral.empty?
115
+
116
+ v = ROMAN[numeral[-1].to_sym]
117
+ v < ultimo ? (r2i(numeral.chop, v) - v) : (r2i(numeral.chop, v) + v)
118
+ end
300
119
  end
metadata CHANGED
@@ -1,76 +1,76 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: extenso_pt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.7
4
+ version: 0.5.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hernâni Rodrigues Vaz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-30 00:00:00.000000000 Z
11
+ date: 2019-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bigdecimal
14
+ name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.4.4
19
+ version: '1.17'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.4.4
26
+ version: '1.17'
27
27
  - !ruby/object:Gem::Dependency
28
- name: bundler
28
+ name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.17'
33
+ version: '5.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.17'
40
+ version: '5.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: minitest
42
+ name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '5.0'
47
+ version: '10.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '5.0'
54
+ version: '10.0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rake
56
+ name: bigdecimal
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
62
- type: :development
61
+ version: 1.4.4
62
+ type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
69
- description: Produz valores monetários por extenso em portugês de portugal ou brasil.
70
- Os valores podem ser um numerico, uma string de digitos ou um conjunto destes (array,
71
- range, hash). O extenso pode ser produzido na escala longa (utilizada em todos os
72
- países lusófonos) ou na escala curta (utilizada no Brasil). Pode ainda escolher
73
- a moeda e a fração da moeda.
68
+ version: 1.4.4
69
+ description: Converte valores monetários em extenso de portugês de portugal, brasil
70
+ ou numeracao romana. Os valores podem ser um numerico, uma string de digitos ou
71
+ um conjunto destes (array, range, hash). O extenso pode ser produzido na escala
72
+ longa (utilizada em todos os países lusófonos) ou na escala curta (utilizada no
73
+ Brasil). Pode ainda converter os valores em numeracao romana e vice versa.
74
74
  email:
75
75
  - hernanirvaz@gmail.com
76
76
  executables: []
@@ -89,6 +89,8 @@ files:
89
89
  - bin/setup
90
90
  - extenso_pt.gemspec
91
91
  - lib/extenso_pt.rb
92
+ - lib/extenso_pt/constantes.rb
93
+ - lib/extenso_pt/module.rb
92
94
  - lib/extenso_pt/version.rb
93
95
  homepage: https://github.com/hernanilr/extenso_pt
94
96
  licenses:
@@ -114,5 +116,6 @@ requirements: []
114
116
  rubygems_version: 3.0.3
115
117
  signing_key:
116
118
  specification_version: 4
117
- summary: Produz valores monetários por extenso em portugês de portugal ou brasil.
119
+ summary: Converte valores monetários em extenso de portugês de portugal, brasil ou
120
+ numeracao romana.
118
121
  test_files: []