trafficbroker-numb 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 TrafficBroker Ltd.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,161 @@
1
+ = numb
2
+
3
+ Returns any numbers, currency or percentages it can find.
4
+
5
+ Currencies are returned using the standard currency codes (see wikipedia for example)
6
+ {:value => 10.00, :percent => true, :currency => 'EUR'}
7
+ Note: Currently, 'kr' will return 'DKK' even though this is the currency symbol for
8
+ Sweden, Danmark and Norway. This issue exists for other currencies as well.
9
+ New Options:
10
+ :require =>
11
+ :currency
12
+ :value
13
+ :percent
14
+ Throws an error if the required field isn't there. Can be combined:
15
+ Numb.new(:require => [:currency, :value])
16
+
17
+ :split => ['<br/>', '//']
18
+ Splits the fields based on the passed variables in the order they are passed
19
+
20
+ :debug => true
21
+ Prints out debugging info.
22
+
23
+ == Examples
24
+
25
+ Numb.new.parse("US$1.00&nbsp;") # => {:currency => 'USD', :value => 1.00}
26
+
27
+ Numb.new.parse('12.34%') # => {:percent => true, :value => 12.34}
28
+
29
+ == Supported Currencies
30
+
31
+ ALL
32
+ AFN
33
+ ARS
34
+ AWG
35
+ AUD
36
+ AZN
37
+ BSD
38
+ BBD
39
+ BYR
40
+ BZD
41
+ BMD
42
+ BOB
43
+ BAM
44
+ BWP
45
+ BGN
46
+ BRL
47
+ BND
48
+ KHR
49
+ CAD
50
+ KYD
51
+ CLP
52
+ CNY
53
+ COP
54
+ CRC
55
+ HRK
56
+ CUP
57
+ CZK
58
+ DOP
59
+ XCD
60
+ EGP
61
+ SVC
62
+ EEK
63
+ FKP
64
+ FJD
65
+ GHC
66
+ GIP
67
+ GTQ
68
+ GGP
69
+ GYD
70
+ HNL
71
+ HKD
72
+ HUF
73
+ ISK
74
+ IDR
75
+ IRR
76
+ IMP
77
+ ILS
78
+ JMD
79
+ JPY
80
+ JEP
81
+ KZT
82
+ KPW
83
+ KRW
84
+ KGS
85
+ LAK
86
+ LVL
87
+ LBP
88
+ LRD
89
+ CHF
90
+ LTL
91
+ MKD
92
+ MYR
93
+ MUR
94
+ MXN
95
+ MNT
96
+ MZN
97
+ NAD
98
+ NPR
99
+ ANG
100
+ NZD
101
+ NIO
102
+ NGN
103
+ KPW
104
+ NOK
105
+ OMR
106
+ PKR
107
+ PAB
108
+ PYG
109
+ PEN
110
+ PHP
111
+ PLN
112
+ QAR
113
+ RON
114
+ RUB
115
+ SHP
116
+ SAR
117
+ RSD
118
+ SCR
119
+ SBD
120
+ SOS
121
+ ZAR
122
+ KRW
123
+ LKR
124
+ CHF
125
+ SRD
126
+ SYP
127
+ TWD
128
+ THB
129
+ TTD
130
+ TRY
131
+ TRL
132
+ TVD
133
+ UAH
134
+ UYU
135
+ UZS
136
+ VEF
137
+ VND
138
+ YER
139
+ ZWD
140
+
141
+ == Duplicate currencies which will not correctly identify
142
+ PRIMARY = {
143
+ '£' => 'GBP',
144
+ 'kr' => 'DKK',
145
+ '$' => 'USD',
146
+ '¥' => 'JPY',
147
+ 'ƒ' => 'AWG',
148
+ }
149
+
150
+ DUPLICATES = {
151
+ '£' => ['EGP', 'FKP', 'GIP', 'GGP', 'IMP', 'JEP', 'LBP', 'SHP', 'SYP', 'EEK'],
152
+ 'kr' => ['ISK', 'NOK', 'SEK'],
153
+ '$' => ['ARS', 'AUD', 'BSD', 'BBD', 'BMD', 'BND', 'CAD', 'KYD', 'CLP', 'COP',
154
+ 'FJD', 'GYD', 'HKD', 'LRD', 'MXN', 'NAD', 'NZD', 'SGD', 'SBD', 'SVC', 'TVD', 'SRD', 'XCD'],
155
+ '¥' => 'CNY',
156
+ 'ƒ' => 'ANG',
157
+ }
158
+
159
+ == Copyright
160
+
161
+ Copyright (c) 2009 TrafficBroker Ltd. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "numb"
8
+ gem.summary = %Q{TODO}
9
+ gem.email = "technology@trafficbroker.co.uk"
10
+ gem.homepage = "http://github.com/trafficbroker/numb"
11
+ gem.authors = ["trafficbroker"]
12
+
13
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
+ end
15
+ rescue LoadError
16
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
17
+ end
18
+
19
+ require 'rake/testtask'
20
+ Rake::TestTask.new(:test) do |test|
21
+ test.libs << 'lib' << 'test'
22
+ test.pattern = 'test/**/*_test.rb'
23
+ test.verbose = true
24
+ end
25
+
26
+ begin
27
+ require 'rcov/rcovtask'
28
+ Rcov::RcovTask.new do |test|
29
+ test.libs << 'test'
30
+ test.pattern = 'test/**/*_test.rb'
31
+ test.verbose = true
32
+ end
33
+ rescue LoadError
34
+ task :rcov do
35
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
36
+ end
37
+ end
38
+
39
+
40
+ task :default => :test
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ if File.exist?('VERSION.yml')
45
+ config = YAML.load(File.read('VERSION.yml'))
46
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
47
+ else
48
+ version = ""
49
+ end
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "numb #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
56
+
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 2
3
+ :patch: 0
4
+ :major: 0
data/lib/numb.rb ADDED
@@ -0,0 +1,424 @@
1
+ # Returns any numbers, currency or percentages it can find
2
+ # Currencies are returned using the standard currency codes (see wikipedia for example)
3
+ # {:value => 10.00, :percent => true, :currency => 'EUR'}
4
+ # Note: Currently, 'kr' will return 'DKK' even though this is the currency symbol for
5
+ # Sweden, Danmark and Norway
6
+ # New Options:
7
+ # :require =>
8
+ # :currency
9
+ # :value
10
+ # :percent
11
+ # Throws an error if the required field isn't there. Can be combined:
12
+ # Numb.new(:require => [:currency, :value])
13
+ #
14
+ # :split => ['<br/>', '//']
15
+ # Splits the fields based on the passed variables in the order they are passed
16
+ #
17
+ # :debug => true
18
+ # Prints out debugging info.
19
+
20
+ class Numb
21
+ def initialize(opts = {})
22
+ @opts = opts
23
+ end
24
+
25
+ def parse(text)
26
+ return do_parse(text) unless @opts.has_key?(:split)
27
+ text_arr = get_split(text)
28
+ res = []
29
+ text_arr.each do |text|
30
+ res << do_parse(text)
31
+ end
32
+ res
33
+ end
34
+
35
+ def currency_find(sym)
36
+ match = CURRENCIES.find{|k,v| m = sym.match('^'+k+'$')}
37
+ return nil unless match
38
+ match[1]
39
+ end
40
+
41
+ private
42
+
43
+ def do_parse(text)
44
+ res = {}
45
+ text.gsub!(NBSP, ' ')
46
+ new_res, text = currency(text)
47
+ res.merge!(new_res)
48
+ new_res, text = percent(text)
49
+ res.merge!(new_res)
50
+ new_res, text = number(text)
51
+ res.merge!(new_res)
52
+ return nil if res == {}
53
+ res
54
+ end
55
+
56
+ def get_split(text)
57
+ arr = [text]
58
+ split = @opts[:split]
59
+ split = [split] unless split.respond_to? :each
60
+ split.each do |sp|
61
+ temp = []
62
+ arr.each do |t|
63
+ temp = temp + t.split(sp)
64
+ end
65
+ arr = temp.flatten
66
+ end
67
+ arr
68
+ end
69
+
70
+ def money_regexp
71
+ return @money_regexp if @money_regexp
72
+ currencies = CURRENCIES.keys
73
+ @money_regexp = Regexp.new('(?:[^A-Z]|^)(' + currencies.join("|") + ')(?:[^A-Z\$]|$)', Regexp::IGNORECASE)
74
+ debug 'currency regexp: '+@money_regexp.inspect
75
+ @money_regexp
76
+ end
77
+
78
+ def currency(string)
79
+ match = string.match(money_regexp)
80
+ debug "currency match: #{match.inspect}"
81
+ return failed(string, :currency) unless match
82
+ currency_symbol = match[1]
83
+ currency = CURRENCIES[currency_symbol]
84
+ debug "currency currency: #{currency}, currency_symbol: #{currency_symbol}"
85
+ currency = currency_find(currency_symbol) unless currency
86
+ debug "currency currency2: #{currency}"
87
+ return failed(string, :currency) unless currency
88
+ [{:currency => currency}, string.gsub(currency_symbol, '')]
89
+ end
90
+
91
+ def percent(string)
92
+ return failed(string, :percent) unless string.match(/%/)
93
+ [{:percent => true}, string.gsub('%', '')]
94
+ end
95
+
96
+ def number(string)
97
+ stripped = string.match(/((?:\d|-)?(?:\d|\d,)*\.?\d+)/)
98
+ stripped ? [{:value => stripped[0].gsub(',','').to_f}, string.gsub(stripped[0], '')] : failed(string, :value)
99
+ end
100
+
101
+ def failed(string, type)
102
+ if check_require(type)
103
+ chars = (0..(string.size-1)).map {|i| "#{string[i]}.chr"}.join('+')
104
+ raise "ERROR: #{type.to_s.capitalize} not found and was required.\nText:\n#{string}\nCharacter Codes:[#{chars}]"
105
+ end
106
+ [{}, string]
107
+ end
108
+
109
+ def check_require(type)
110
+ return false unless @opts.has_key?(:require)
111
+ keys = []
112
+ keys << @opts[:require]
113
+ keys.flatten.each do |k|
114
+ return true if k == type
115
+ end
116
+ false
117
+ end
118
+
119
+ def debug(message)
120
+ puts message if @opts[:debug]
121
+ end
122
+
123
+ NBSP = 194.chr+160.chr
124
+
125
+ CURRENCIES =
126
+ {
127
+ 'AU\$' => 'AUD',
128
+
129
+ 'CA\$' => 'CAD',
130
+
131
+ 'DKK' => 'DKK',
132
+ 'kr' => 'DKK',
133
+ 'kr'+NBSP => 'DKK',
134
+ 'kr&#xA0;' => 'DKK',
135
+
136
+ 'EUR' => 'EUR',
137
+ '€' => 'EUR',
138
+ 194.chr+128.chr => "EUR",
139
+ '&euro;' => 'EUR',
140
+ '&#8364;' => 'EUR',
141
+
142
+ 'GBP' => 'GBP',
143
+ '\243' => 'GBP',
144
+ '£' => 'GBP',
145
+ '&#xA3;' => 'GBP',
146
+ 'UK' => "GBP",
147
+ 'UK\243' => "GBP",
148
+ 'UK£' => "GBP",
149
+ 'UK'+239.chr+189.chr+163.chr => "GBP",
150
+ '&pound;' => 'GBP',
151
+ '&#163;' => 'GBP',
152
+
153
+ 'Rs' => 'INR',
154
+ 'INR' => 'INR',
155
+
156
+ 239.chr+189.chr+165.chr => 'JPY',
157
+ '¥' => 'JPY',
158
+ '&yen;' => 'JPY',
159
+ '&#165;' => 'JPY',
160
+ 165.chr => 'JPY',
161
+
162
+ 'NZ\$' => 'NZD',
163
+
164
+ 'SEK' => 'SEK',
165
+
166
+ 'S\$' => 'SGD',
167
+ 'SGD' => 'SGD',
168
+
169
+ 'USD' => 'USD',
170
+ 'US\$' => 'USD',
171
+ '\$' => 'USD',
172
+
173
+ # generated codes
174
+ 'ALL' => 'ALL',
175
+ 'AFN' => 'AFN',
176
+ 'ARS' => 'ARS',
177
+ 'AWG' => 'AWG',
178
+ 'AUD' => 'AUD',
179
+ 'AZN' => 'AZN',
180
+ 'BSD' => 'BSD',
181
+ 'BBD' => 'BBD',
182
+ 'BYR' => 'BYR',
183
+ 'BZD' => 'BZD',
184
+ 'BMD' => 'BMD',
185
+ 'BOB' => 'BOB',
186
+ 'BAM' => 'BAM',
187
+ 'BWP' => 'BWP',
188
+ 'BGN' => 'BGN',
189
+ 'BRL' => 'BRL',
190
+ 'BND' => 'BND',
191
+ 'KHR' => 'KHR',
192
+ 'CAD' => 'CAD',
193
+ 'KYD' => 'KYD',
194
+ 'CLP' => 'CLP',
195
+ 'CNY' => 'CNY',
196
+ 'COP' => 'COP',
197
+ 'CRC' => 'CRC',
198
+ 'HRK' => 'HRK',
199
+ 'CUP' => 'CUP',
200
+ 'CZK' => 'CZK',
201
+ 'DOP' => 'DOP',
202
+ 'XCD' => 'XCD',
203
+ 'EGP' => 'EGP',
204
+ 'SVC' => 'SVC',
205
+ 'EEK' => 'EEK',
206
+ 'FKP' => 'FKP',
207
+ 'FJD' => 'FJD',
208
+ 'GHC' => 'GHC',
209
+ 'GIP' => 'GIP',
210
+ 'GTQ' => 'GTQ',
211
+ 'GGP' => 'GGP',
212
+ 'GYD' => 'GYD',
213
+ 'HNL' => 'HNL',
214
+ 'HKD' => 'HKD',
215
+ 'HUF' => 'HUF',
216
+ 'ISK' => 'ISK',
217
+ 'IDR' => 'IDR',
218
+ 'IRR' => 'IRR',
219
+ 'IMP' => 'IMP',
220
+ 'ILS' => 'ILS',
221
+ 'JMD' => 'JMD',
222
+ 'JPY' => 'JPY',
223
+ 'JEP' => 'JEP',
224
+ 'KZT' => 'KZT',
225
+ 'KPW' => 'KPW',
226
+ 'KRW' => 'KRW',
227
+ 'KGS' => 'KGS',
228
+ 'LAK' => 'LAK',
229
+ 'LVL' => 'LVL',
230
+ 'LBP' => 'LBP',
231
+ 'LRD' => 'LRD',
232
+ 'CHF' => 'CHF',
233
+ 'LTL' => 'LTL',
234
+ 'MKD' => 'MKD',
235
+ 'MYR' => 'MYR',
236
+ 'MUR' => 'MUR',
237
+ 'MXN' => 'MXN',
238
+ 'MNT' => 'MNT',
239
+ 'MZN' => 'MZN',
240
+ 'NAD' => 'NAD',
241
+ 'NPR' => 'NPR',
242
+ 'ANG' => 'ANG',
243
+ 'NZD' => 'NZD',
244
+ 'NIO' => 'NIO',
245
+ 'NGN' => 'NGN',
246
+ 'KPW' => 'KPW',
247
+ 'NOK' => 'NOK',
248
+ 'OMR' => 'OMR',
249
+ 'PKR' => 'PKR',
250
+ 'PAB' => 'PAB',
251
+ 'PYG' => 'PYG',
252
+ 'PEN' => 'PEN',
253
+ 'PHP' => 'PHP',
254
+ 'PLN' => 'PLN',
255
+ 'QAR' => 'QAR',
256
+ 'RON' => 'RON',
257
+ 'RUB' => 'RUB',
258
+ 'SHP' => 'SHP',
259
+ 'SAR' => 'SAR',
260
+ 'RSD' => 'RSD',
261
+ 'SCR' => 'SCR',
262
+ 'SBD' => 'SBD',
263
+ 'SOS' => 'SOS',
264
+ 'ZAR' => 'ZAR',
265
+ 'KRW' => 'KRW',
266
+ 'LKR' => 'LKR',
267
+ 'CHF' => 'CHF',
268
+ 'SRD' => 'SRD',
269
+ 'SYP' => 'SYP',
270
+ 'TWD' => 'TWD',
271
+ 'THB' => 'THB',
272
+ 'TTD' => 'TTD',
273
+ 'TRY' => 'TRY',
274
+ 'TRL' => 'TRL',
275
+ 'TVD' => 'TVD',
276
+ 'UAH' => 'UAH',
277
+ 'UYU' => 'UYU',
278
+ 'UZS' => 'UZS',
279
+ 'VEF' => 'VEF',
280
+ 'VND' => 'VND',
281
+ 'YER' => 'YER',
282
+ 'ZWD' => 'ZWD',
283
+
284
+ # Semi generated
285
+ 'Lek' => 'ALL',
286
+ 'ƒ' => 'AWG',
287
+ 'p.' => 'BYR',
288
+ 'BZ$' => 'BZD',
289
+ '$b' => 'BOB',
290
+ 'KM' => 'BAM',
291
+ 'P' => 'BWP',
292
+ 'R$' => 'BRL',
293
+ 'kn' => 'HRK',
294
+ 'Kč' => 'CZK',
295
+ 'RD$' => 'DOP',
296
+ 162.chr => 'GHC',
297
+ 'Q' => 'GTQ',
298
+ 'L' => 'HNL',
299
+ 'Ft' => 'HUF',
300
+ 'Rp' => 'IDR',
301
+ 'J$' => 'JMD',
302
+ 'Ls' => 'LVL',
303
+ 'CHF' => 'CHF',
304
+ 'Lt' => 'LTL',
305
+ 'RM' => 'MYR',
306
+ 'MT' => 'MZN',
307
+ 'C$' => 'NIO',
308
+ 'B/.' => 'PAB',
309
+ 'Gs' => 'PYG',
310
+ 'S/.' => 'PEN',
311
+ 'Php' => 'PHP',
312
+ 'zł' => 'PLN',
313
+ 'lei' => 'RON',
314
+ 'S' => 'SOS',
315
+ 'R' => 'ZAR',
316
+ 'CHF' => 'CHF',
317
+ 'NT$' => 'TWD',
318
+ 'TT$' => 'TTD',
319
+ 'YTL' => 'TRY',
320
+ '$U' => 'UYU',
321
+ 'Bs' => 'VEF',
322
+ 'Z$' => 'ZWD',
323
+
324
+ # HTML unicode
325
+ '&#1547;' => 'AFN',
326
+ '&#402;' => 'AWG',
327
+ '&#1084;&#1072;&#1085;' => 'AZN',
328
+ '&#1083;&#1074;' => 'BGN',
329
+ '&#6107;' => 'KHR',
330
+ '&#8353;' => 'CRC',
331
+ '&#8369;' => 'CUP',
332
+ '&#75;&#269;' => 'CZK',
333
+ '&#8360;' => 'INR',
334
+ '&#65020;' => 'IRR',
335
+ '&#8362;' => 'ILS',
336
+ '&#1083;&#1074;' => 'KZT',
337
+ '&#8361;' => 'KPW',
338
+ '&#8361;' => 'KRW',
339
+ '&#1083;&#1074;' => 'KGS',
340
+ '&#8365;' => 'LAK',
341
+ '&#1076;&#1077;&#1085;' => 'MKD',
342
+ '&#8360;' => 'MUR',
343
+ '&#8366;' => 'MNT',
344
+ '&#8360;' => 'NPR',
345
+ '&#8358;' => 'NGN',
346
+ '&#8361;' => 'KPW',
347
+ '&#65020;' => 'OMR',
348
+ '&#8360;' => 'PKR',
349
+ '&#122;&#322;' => 'PLN',
350
+ '&#65020;' => 'QAR',
351
+ '&#1088;&#1091;&#1073;' => 'RUB',
352
+ '&#65020;' => 'SAR',
353
+ '&#1044;&#1080;&#1085;&#46;' => 'RSD',
354
+ '&#8360;' => 'SCR',
355
+ '&#8361;' => 'KRW',
356
+ '&#8360;' => 'LKR',
357
+ '&#3647;' => 'THB',
358
+ '&#8356;' => 'TRL',
359
+ '&#8372;' => 'UAH',
360
+ '&#1083;&#1074;' => 'UZS',
361
+ '&#8363;' => 'VND',
362
+ '&#65020;' => 'YER',
363
+ }
364
+
365
+ DUPLICATES = {
366
+ '£' => ['EGP', 'FKP', 'GIP', 'GGP', 'IMP', 'JEP', 'LBP', 'SHP', 'SYP', 'EEK'],
367
+ 'kr' => ['ISK', 'NOK', 'SEK'],
368
+ '$' => ['ARS', 'AUD', 'BSD', 'BBD', 'BMD', 'BND', 'CAD', 'KYD', 'CLP', 'COP',
369
+ 'FJD', 'GYD', 'HKD', 'LRD', 'MXN', 'NAD', 'NZD', 'SGD', 'SBD', 'SVC', 'TVD', 'SRD', 'XCD'],
370
+ '¥' => 'CNY',
371
+ 'ƒ' => 'ANG',
372
+ '&#402;' => 'ANG',
373
+ }
374
+
375
+ PROBLEMS = {
376
+ # 8364.chr => 'EUR',
377
+ # 1547.chr => 'AFN',
378
+ # 1084.chr+1072.chr+1085.chr => 'AZN',
379
+ # 1083.chr+1074.chr => 'BGN',
380
+ # 6107.chr => 'KHR',
381
+ # 8353.chr => 'CRC',
382
+ # 8369.chr => 'CUP',
383
+ # 8360.chr => 'INR',
384
+ # 65020.chr => 'IRR',
385
+ # 8362.chr => 'ILS',
386
+ # 1083.chr+1074.chr => 'KZT',
387
+ # 8361.chr => 'KPW',
388
+ # 8361.chr => 'KRW',
389
+ # 1083.chr+1074.chr => 'KGS',
390
+ # 8365.chr => 'LAK',
391
+ # 1076.chr+1077.chr+1085.chr => 'MKD',
392
+ # 8360.chr => 'MUR',
393
+ # 8366.chr => 'MNT',
394
+ # 8360.chr => 'NPR',
395
+ # 8358.chr => 'NGN',
396
+ # 8361.chr => 'KPW',
397
+ # 65020.chr => 'OMR',
398
+ # 8360.chr => 'PKR',
399
+ # 65020.chr => 'QAR',
400
+ # 1088.chr+1091.chr+1073.chr => 'RUB',
401
+ # 65020.chr => 'SAR',
402
+ # 1044.chr+1080.chr+1085.chr+46.chr => 'RSD',
403
+ # 8360.chr => 'SCR',
404
+ # 8361.chr => 'KRW',
405
+ # 8360.chr => 'LKR',
406
+ # 3647.chr => 'THB',
407
+ # 8356.chr => 'TRL',
408
+ # 8372.chr => 'UAH',
409
+ # 1083.chr+1074.chr => 'UZS',
410
+ # 8363.chr => 'VND',
411
+ # 65020.chr => 'YER',
412
+ # 8363.chr => 'VND',
413
+ # 65020.chr => 'YER',
414
+ }
415
+
416
+
417
+ end
418
+
419
+
420
+ class String
421
+ def escape
422
+ return self.dump[1..-2]
423
+ end
424
+ end
data/test/numb_test.rb ADDED
@@ -0,0 +1,246 @@
1
+ require "test/unit"
2
+ require File.join(File.dirname(__FILE__), "test_helper")
3
+
4
+ class NumbTest < Test::Unit::TestCase
5
+
6
+ # Percentages
7
+ def test_percentage
8
+ expected = {:percent => true, :value => 12.34}
9
+ assert_equal expected, Numb.new.parse('12.34%')
10
+ end
11
+
12
+ def test_percentage_100
13
+ expected = {:percent => true, :value => 100.0}
14
+ assert_equal expected, Numb.new.parse('100.00%')
15
+ end
16
+
17
+ def test_percentage_fail_without_figure
18
+ expected = nil
19
+ assert_equal expected, Numb.new.parse('n/a')
20
+ end
21
+
22
+ def test_percentage_find_percent_only
23
+ expected = {:percent => true}
24
+ assert_equal expected, Numb.new.parse('blah%')
25
+ end
26
+
27
+ # Numbers
28
+ def test_number_without_percent_sign
29
+ expected = {:value => 12.34}
30
+ assert_equal expected, Numb.new.parse('12.34')
31
+ end
32
+
33
+ def test_number_with_comma
34
+ expected = {:value => 4012.34}
35
+ assert_equal expected, Numb.new.parse('4,012.34')
36
+ expected = {:value => 4000012.34}
37
+ assert_equal expected, Numb.new.parse('4,000,012.34')
38
+ end
39
+
40
+ # Money
41
+ def test_gbp
42
+ expected = {:currency => 'GBP', :value => 12.34}
43
+ assert_equal expected, Numb.new.parse("£12.34")
44
+ end
45
+
46
+ def test_gbp_with_chrs
47
+ expected = {:currency => 'GBP', :value => 12.34}
48
+ assert_equal expected, Numb.new.parse(194.chr+163.chr+'12.34')
49
+ end
50
+
51
+ def test_currencies_with_extra
52
+ expected = {:currency => 'AUD'}
53
+ assert_equal expected, Numb.new.parse('AU$')
54
+ end
55
+
56
+ def test_various_currencies
57
+ expected = {:currency => 'GBP'}
58
+ assert_equal expected, Numb.new.parse("UK£")
59
+ assert_equal expected, Numb.new.parse(85.chr+75.chr+239.chr+191.chr+189.chr+239.chr)
60
+ expected = {:currency => 'AUD', :percent => true}
61
+ assert_equal expected, Numb.new.parse('AU$)%')
62
+ expected = {:currency => 'CAD'}
63
+ assert_equal expected, Numb.new.parse("(CA$)")
64
+ expected = {:currency => 'USD', :value => 1.00}
65
+ assert_equal expected, Numb.new.parse("US$1.00&nbsp;")
66
+ end
67
+
68
+ def test_extra_characters
69
+ expected = {:currency => 'USD'}
70
+ assert_equal expected, Numb.new.parse("US$")
71
+ expected = nil
72
+ assert_equal expected, Numb.new.parse("DS$")
73
+ expected = {:currency => 'SGD', :value => 2.0}
74
+ assert_equal expected, Numb.new.parse("2S$")
75
+ end
76
+
77
+ def test_require
78
+ assert_raise RuntimeError do
79
+ Numb.new(:require => :currency).parse("0.00")
80
+ end
81
+ assert_raise RuntimeError do
82
+ Numb.new(:require => :value).parse("£")
83
+ end
84
+ assert_raise RuntimeError do
85
+ Numb.new(:require => :percent).parse("0.00")
86
+ end
87
+ assert_raise RuntimeError do
88
+ Numb.new(:require => [:currency, :value]).parse("0.00")
89
+ end
90
+ end
91
+
92
+ def test_split
93
+ expected = [{:currency => 'USD', :value => 1.00}]
94
+ assert_equal expected, Numb.new(:split => ' ').parse("US$1.00")
95
+ expected = [{:currency => 'USD', :value => 1.00}]
96
+ assert_equal expected, Numb.new(:split => /[&@]/).parse("US$1.00")
97
+ end
98
+
99
+ def test_parse_percentage
100
+ commission = Numb.new.parse('2.5%')
101
+ expected = {:percent => true, :value => 2.5}
102
+ assert_equal expected, commission
103
+ end
104
+
105
+ def test_parse_money
106
+ commission = Numb.new.parse("\2432.50")
107
+ expected = {:value => 2.50, :currency => "GBP"}
108
+ assert_equal expected, commission
109
+ end
110
+
111
+ def test_parse_money_and_percent
112
+ commission = Numb.new(:split => '-').parse("10.00% - \2430.25")
113
+ expected = [{:value => 10.0, :percent => true}, {:value => 0.25, :currency => "GBP"}]
114
+ assert_equal expected, commission
115
+ end
116
+
117
+ def test_parse_percent_and_no_money
118
+ commission = Numb.new.parse('6.00%n/a')
119
+ expected = {:value => 6.0, :percent => true}
120
+ assert_equal expected, commission
121
+ end
122
+
123
+ def test_currency_pound
124
+ expected = {:currency => 'GBP', :value=>2.5}
125
+ assert_equal expected, Numb.new.parse("\2432.50")
126
+ end
127
+
128
+ def test_currency_dollar
129
+ expected = {:currency => 'USD', :value => 2.50}
130
+ assert_equal expected, Numb.new.parse('$2.50')
131
+ end
132
+
133
+ def test_currency_euro
134
+ expected = {:currency => 'EUR', :value => 2.50}
135
+ assert_equal expected, Numb.new.parse('€2.50')
136
+ end
137
+
138
+ def test_money_happy_path
139
+ expected = {:currency => 'GBP', :value => 2.50}
140
+ assert_equal expected, Numb.new.parse("\2432.50")
141
+ end
142
+
143
+ def test_money_with_leading_characters
144
+ expected = {:currency => 'GBP', :value => 3.00}
145
+ assert_equal expected, Numb.new.parse("3.00 \2432.50")
146
+ end
147
+
148
+ def test_money_with_trailing_characters
149
+ expected = {:currency => 'GBP', :value => 2.5}
150
+ assert_equal expected, Numb.new.parse("\2432.50 3.00")
151
+ end
152
+
153
+ def test_money_with_double_currency_sign
154
+ expected = {:currency => 'GBP', :value => 2.5}
155
+ assert_equal expected, Numb.new.parse("commission amount \243\2432.50")
156
+ end
157
+
158
+ def test_money_with_comma
159
+ expected = {:currency => 'GBP', :value => 2002.5}
160
+ assert_equal expected, Numb.new.parse("\2432,002.50 3.00")
161
+ end
162
+
163
+ def test_money_failure
164
+ expected = {:value => 2.50}
165
+ assert_equal expected, Numb.new.parse('2.50')
166
+ end
167
+
168
+ def test_currency_unicode_hash_codes
169
+ expected = {:currency => 'RUB', :value => 2.50}
170
+ assert_equal expected, Numb.new.parse('&#1088;&#1091;&#1073;2.50')
171
+ end
172
+
173
+ def test_currency
174
+ expected = {:value => 0.0}
175
+ assert_equal expected, Numb.new.parse("0.00")
176
+ expected = {:currency => 'DKK', :value => 0.00}
177
+ assert_equal expected, Numb.new.parse("kr"+Numb::NBSP+"0.00")
178
+ expected = {:currency => 'DKK', :value => 0.00}
179
+ assert_equal expected, Numb.new.parse("kr&#xA0;0.00")
180
+ expected = {:currency => 'USD', :value => 0.00}
181
+ assert_equal expected, Numb.new.parse("$0.00")
182
+ expected = {:currency => 'GBP', :value => 0.00}
183
+ assert_equal expected, Numb.new.parse("£0.00")
184
+ expected = {:currency => 'GBP', :value => 0.00}
185
+ assert_equal expected, Numb.new.parse("&#xA3;0.00")
186
+ expected = {:currency => 'EUR', :value => 0.00}
187
+ assert_equal expected, Numb.new.parse("€0.00")
188
+ end
189
+
190
+ def test_get_monies
191
+ expected = [{:currency => 'GBP', :value => 0.00}, {:currency => 'GBP', :value => 2.00}, {:currency => 'GBP', :value => 3.50}]
192
+ assert_equal expected, Numb.new(:split => ['<br/>', '//']).parse("£0.00<br/>£2.00//£3.50")
193
+ end
194
+
195
+ def test_get_percents
196
+ expected = {:percent => true, :value => 0.00}
197
+ assert_equal expected, Numb.new.parse("0.00%")
198
+ expected = [{:percent => true, :value => 0.00}, {:percent => true, :value => 2.00}, {:percent => true, :value => 3.50}]
199
+ assert_equal expected, Numb.new(:split => ['<br/>', '//']).parse("%0.00<br/>%2.00//%3.50")
200
+ end
201
+
202
+ def test_get_commission
203
+ expected = [
204
+ {:currency => 'GBP', :value => 45.00},
205
+ {:currency => 'GBP', :value => 45.00},
206
+ {:currency => 'GBP', :value => 45.00},
207
+ {:currency => 'GBP', :value => 1.00},
208
+ {:currency => 'GBP', :value => 6.00},
209
+ {:currency => 'GBP', :value => 1.00},
210
+ ]
211
+ assert_equal expected, Numb.new(:split => ['<br/>', 'v']).parse(" £45.00<br/>\n£45.00<br/>\n£45.00<br/>£1.00<br/>£6.00v£1.00")
212
+ expected = [
213
+ {:percent => true, :value => 45.00},
214
+ {:percent => true, :value => 45.00},
215
+ {:percent => true, :value => 45.00},
216
+ {:percent => true, :value => 1.00},
217
+ {:percent => true, :value => 6.00},
218
+ {:percent => true, :value => 1.00},
219
+ ]
220
+ assert_equal expected, Numb.new(:split => ['<br/>', 'v']).parse(" 45.00%<br/>\n45.00%<br/>\n45.00%<br/>1.00%<br/>6.00%v1.00%")
221
+ end
222
+
223
+ # Supported currencies
224
+ def test_japan
225
+ expected = {:currency => 'JPY', :value => 600.00}
226
+ assert_equal expected, Numb.new.parse(165.chr+54.chr+48.chr+48.chr+46.chr+48.chr+48.chr+32.chr)
227
+ end
228
+
229
+ def test_rupee
230
+ expected = {:currency => 'INR', :value => 4000.0}
231
+ assert_equal expected, Numb.new.parse("Rs4,000")
232
+ assert_equal expected, Numb.new.parse(82.chr+115.chr+52.chr+44.chr+48.chr+48.chr+48.chr+46.chr+48.chr+48.chr+32.chr)
233
+ assert_equal expected, Numb.new.parse("INR4,000")
234
+ end
235
+
236
+ def test_singapore_dollar
237
+ expected = {:currency => 'SGD', :value => 5.48}
238
+ assert_equal expected, Numb.new(:require => :currency).parse("S$5.48")
239
+ end
240
+
241
+ def test_swedish_kroner
242
+ expected = {:currency => 'SEK', :value => 5.48}
243
+ assert_equal expected, Numb.new(:require => :currency).parse("SEK5.48")
244
+ end
245
+
246
+ end
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ require 'numb'
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trafficbroker-numb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - trafficbroker
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-15 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: technology@trafficbroker.co.uk
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - LICENSE
27
+ - README.rdoc
28
+ - Rakefile
29
+ - VERSION.yml
30
+ - lib/numb.rb
31
+ - test/numb_test.rb
32
+ - test/test_helper.rb
33
+ has_rdoc: true
34
+ homepage: http://github.com/trafficbroker/numb
35
+ post_install_message:
36
+ rdoc_options:
37
+ - --charset=UTF-8
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ requirements: []
53
+
54
+ rubyforge_project:
55
+ rubygems_version: 1.2.0
56
+ signing_key:
57
+ specification_version: 2
58
+ summary: TODO
59
+ test_files:
60
+ - test/numb_test.rb
61
+ - test/test_helper.rb