softprops-nuwords 0.1.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.
- data/LICENSE +20 -0
- data/Manifest +8 -0
- data/README.rdoc +9 -0
- data/Rakefile +66 -0
- data/VERSION +1 -0
- data/lib/nuwords.rb +146 -0
- data/nuwords.gemspec +32 -0
- data/test/nuwords_test.rb +87 -0
- data/test/test_helper.rb +10 -0
- metadata +69 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 softprops
|
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/Manifest
ADDED
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "nuwords"
|
8
|
+
gem.summary = %Q{numeric words}
|
9
|
+
gem.email = "d.tangren@gmail.com"
|
10
|
+
gem.homepage = "http://github.com/softprops/nuwords"
|
11
|
+
gem.authors = ["softprops"]
|
12
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
13
|
+
end
|
14
|
+
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
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 = "nuwords #{version}"
|
53
|
+
rdoc.rdoc_files.include('README*')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
end
|
56
|
+
|
57
|
+
require 'echoe'
|
58
|
+
Echoe.new('nuwords','0.1.0') do |g|
|
59
|
+
g.description = 'convert numbers to words'
|
60
|
+
g.url = 'http://github.com/softprops/nuwords'
|
61
|
+
g.author = 'softprops'
|
62
|
+
g.email = 'd.tangren@gmail.com'
|
63
|
+
g.ignore_pattern = ['tmp/*','script/*']
|
64
|
+
g.development_dependencies =[]
|
65
|
+
end
|
66
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/nuwords.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
#
|
2
|
+
# A Simple library for converting numeric values into words. Supports values
|
3
|
+
# up to #MAX (999,999,999,999,999). I could support more but it's not really that useful at
|
4
|
+
# that point. I draw the line at
|
5
|
+
# 'nine hundred ninety-nine trillion nine hundred ninety-nine billion nine hundred ninety-nine million
|
6
|
+
# nine hundred ninety-nine thousand nine hundred ninety-nine'!
|
7
|
+
# simple usage:
|
8
|
+
# 0.in_words # => 'zero'
|
9
|
+
# 1234013.in_words # => 'one million two hundred thirty-four thousand thirteen'
|
10
|
+
#
|
11
|
+
# custom language usage:
|
12
|
+
# 3.in_words :in => 'Mandarin' # => 'san'
|
13
|
+
#
|
14
|
+
# custom translator usage:
|
15
|
+
# 142.in_words :translator => CustomTranslator # => result of CustomTranslator.translate(142)
|
16
|
+
#
|
17
|
+
# @author softprops
|
18
|
+
#
|
19
|
+
module Nuwords
|
20
|
+
# the maxiumum supported number
|
21
|
+
MAX = 999_999_999_999_999
|
22
|
+
|
23
|
+
# Translates a numeric value to words
|
24
|
+
# This method takes an optional hash of options which include
|
25
|
+
# :translator => The class responsible for translation behavior
|
26
|
+
# :in => The language Dictionary that the number should be translated into
|
27
|
+
# If the Dictionary for the language cannot be found an UnsupportedLanguageException will be raised
|
28
|
+
def in_words(opts = {})
|
29
|
+
translator = opts.delete(:translator) || Translator.new
|
30
|
+
raise InvalidTranslatorException unless translator.respond_to?(:translate)
|
31
|
+
translator.translate(self, opts)
|
32
|
+
end
|
33
|
+
|
34
|
+
alias_method :to_w, :in_words
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
class InvalidTranslatorException < Exception; end
|
39
|
+
class NumberNotSupportedException < Exception; end
|
40
|
+
|
41
|
+
# Responsible for translating a given number into
|
42
|
+
# words. To extend override #parse with your impl
|
43
|
+
class Translator
|
44
|
+
|
45
|
+
# The interface for performing actual translation
|
46
|
+
def translate(number, opts = {})
|
47
|
+
@dictionary = dictionary_for(opts[:in] || 'En')
|
48
|
+
@dashed = opts[:dashed].nil? ? true : opts[:dashed]
|
49
|
+
parse(number, false)
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
# Handles the core logic of interpreting
|
55
|
+
# the given number in words
|
56
|
+
# The language is dependent on the Dictionary provided with the
|
57
|
+
#:in option which defaults to En (English)
|
58
|
+
def parse(number, ignore_zero = true)
|
59
|
+
word = ''
|
60
|
+
case number
|
61
|
+
when 0
|
62
|
+
word << @dictionary.zero! if !ignore_zero
|
63
|
+
when 1..9
|
64
|
+
word << @dictionary.ones![number - 1]
|
65
|
+
when 11..19
|
66
|
+
word << @dictionary.teens![(number - 10) - 1]
|
67
|
+
when 10 || 20..99
|
68
|
+
word << @dictionary.tens![(number / 10) - 1] if(number/10 > 0)
|
69
|
+
word << (@dashed ? '-' : '') << parse(number % 10) if(number % 10 > 0)
|
70
|
+
when 100..999
|
71
|
+
word << parse(number/100) << " #{@dictionary.bigs![0]} " if (number/100 > 0)
|
72
|
+
word << parse(number%100) if (number%100 > 0)
|
73
|
+
when 1_000..999_999
|
74
|
+
word << parse((number/1000)) << " #{@dictionary.bigs![1]} " if (number/1_000>0)
|
75
|
+
word << parse(number%1000) if (number%1_000>0)
|
76
|
+
when 1_000_000..999_999_999
|
77
|
+
word << parse(number/1_000_000) << " #{@dictionary.bigs![2]} " if(number/1_000_000>0)
|
78
|
+
word << parse(number%1_000_000) if(number%1_000_000>0)
|
79
|
+
when 1_000_000_000..999_999_999_999
|
80
|
+
word << parse(number/1_000_000_000) << " #{@dictionary.bigs![3]} " if(number/1_000_000_000>0)
|
81
|
+
word << parse(number%1_000_000_000) if(number%1_000_000_000>0)
|
82
|
+
when 1_000_000_000_000..999_999_999_999_999
|
83
|
+
word << parse(number/1_000_000_000_000) <<" #{@dictionary.bigs![4]} " if(number/1_000_000_000_000>0)
|
84
|
+
word << parse(number%1_000_000_000_000) if(number%1_000_000_000_000>0)
|
85
|
+
else
|
86
|
+
raise NumberNotSupportedException.new("Number #{number} not supported")
|
87
|
+
end
|
88
|
+
word.strip
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
# Fetchs the Library of words for the given
|
94
|
+
# language
|
95
|
+
def dictionary_for(lang)
|
96
|
+
Dictionaries.find(lang.to_s)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# =Language Dictionaries
|
101
|
+
# to use your own, include Numords::Dictionaries::Dictionary
|
102
|
+
# in a class that defines class methods #zero, #ones, #teens, #tens, #bigs
|
103
|
+
# and invoke via 1.in_words(:in => CustomLanguage)
|
104
|
+
module Dictionaries
|
105
|
+
|
106
|
+
class UnsupportedLanguageException < Exception; end
|
107
|
+
|
108
|
+
class << self
|
109
|
+
# look up a dictionary for a given lan
|
110
|
+
def find(lang)
|
111
|
+
return Dictionaries.const_get(lang) if lang.kind_of?(String)
|
112
|
+
lang
|
113
|
+
rescue Exception => e; raise UnsupportedLanguageException.new("#{e} - unsupported language #{lang}")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Base behavior of Dictionary. Defines the definition
|
118
|
+
# of accessor methods for %w( zero ones teens tens bigs )
|
119
|
+
module Dictionary
|
120
|
+
def self.included(klass)
|
121
|
+
%w( zero ones teens tens bigs ).each do |classification|
|
122
|
+
klass.class_eval %Q{
|
123
|
+
def self.#{classification}(values)
|
124
|
+
@@#{classification}=values
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.#{classification}!
|
128
|
+
@@#{classification}
|
129
|
+
end
|
130
|
+
}
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end # end Dictionary
|
134
|
+
|
135
|
+
# English library (default)
|
136
|
+
class En
|
137
|
+
include Dictionary
|
138
|
+
zero 'zero'
|
139
|
+
ones %w( one two three four five six seven eight nine )
|
140
|
+
teens %w( eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen )
|
141
|
+
tens %w( ten twenty thirty fourty fifty sixty seventy eighty ninety )
|
142
|
+
bigs %w( hundred thousand million billion trillion )
|
143
|
+
end # end En
|
144
|
+
end # end Dictionaries
|
145
|
+
end
|
146
|
+
Numeric.send :include, Nuwords # include in Numeric class for use
|
data/nuwords.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{nuwords}
|
5
|
+
s.version = "0.1.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["softprops"]
|
9
|
+
s.date = %q{2009-05-17}
|
10
|
+
s.description = %q{convert numbers to words}
|
11
|
+
s.email = %q{d.tangren@gmail.com}
|
12
|
+
s.extra_rdoc_files = ["lib/nuwords.rb", "LICENSE", "README.rdoc"]
|
13
|
+
s.files = ["lib/nuwords.rb", "LICENSE", "Rakefile", "README.rdoc", "test/nuwords_test.rb", "test/test_helper.rb", "VERSION", "Manifest", "nuwords.gemspec"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://github.com/softprops/nuwords}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Nuwords", "--main", "README.rdoc"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{nuwords}
|
19
|
+
s.rubygems_version = %q{1.3.2}
|
20
|
+
s.summary = %q{convert numbers to words}
|
21
|
+
s.test_files = ["test/nuwords_test.rb", "test/test_helper.rb"]
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 3
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
else
|
29
|
+
end
|
30
|
+
else
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# English library (default)
|
4
|
+
class AnotherLanguage
|
5
|
+
include Nuwords::Dictionaries::Dictionary
|
6
|
+
zero 'zero'
|
7
|
+
ones %w( blah meh nom si wu liu chi ba nine )
|
8
|
+
teens %w( eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen )
|
9
|
+
tens %w( bacon twenty thirty fourty fifty sixty seventy eighty ninety )
|
10
|
+
bigs %w( hundred thousand million billion trillion )
|
11
|
+
end
|
12
|
+
|
13
|
+
class NuwordsTest < Test::Unit::TestCase
|
14
|
+
|
15
|
+
context "the library" do
|
16
|
+
should "provide the maxiumum supported value" do
|
17
|
+
assert true, Nuwords.const_defined?(:MAX)
|
18
|
+
end
|
19
|
+
context "when given a bogus translator" do
|
20
|
+
should "raise a InvalidTranslatorException" do
|
21
|
+
assert_raise Nuwords::InvalidTranslatorException do
|
22
|
+
1.in_words(:translator => Hash)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "a numberic value" do
|
29
|
+
context "less than one" do
|
30
|
+
should "translate to zero" do
|
31
|
+
assert_equal "zero", 0.in_words
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "that is greater than ten and less than on hundred" do
|
36
|
+
should "be delimited by a dash if not devisible evenly by ten" do
|
37
|
+
assert_equal "twenty-five", 25.in_words
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when requested not to have dashes" do
|
41
|
+
should "not be delimited by a dash if not devisible evenly by ten" do
|
42
|
+
assert_equal "twentyfive", 25.in_words(:dashed => false)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "that is translated to a custom language" do
|
48
|
+
should "translate numeric values accordingly" do
|
49
|
+
assert_equal 'bacon', 10.in_words(:in => AnotherLanguage)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "that is translated to a bogus language" do
|
54
|
+
should "raise an UnsupportedLanguageException" do
|
55
|
+
assert_raise Nuwords::Dictionaries::UnsupportedLanguageException do
|
56
|
+
10.in_words(:in => "asdf")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "that is less or equal to 999,999,999,999,999" do
|
62
|
+
should "not raise a NumberNotSupportedException" do
|
63
|
+
assert_nothing_raised do
|
64
|
+
# 0.upto(999_999_999_999_999) works but takes a good while to run
|
65
|
+
(999_999_999_999_999 - 1).in_words
|
66
|
+
999_999_999_999_999.in_words
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "that is greater than 999,999,999,999,999" do
|
72
|
+
should "raise a NumberNotSupportedException" do
|
73
|
+
assert_raise Nuwords::NumberNotSupportedException do
|
74
|
+
999_999_999_999_999.next.in_words
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
should "respond to aliased method #to_w" do
|
80
|
+
assert true, 1.respond_to?(:to_w)
|
81
|
+
end
|
82
|
+
|
83
|
+
should "return the same value when #to_w is called as with #in_words" do
|
84
|
+
assert_equal 1.to_w, 1.in_words
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: softprops-nuwords
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- softprops
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-05-17 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: convert numbers to words
|
17
|
+
email: d.tangren@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- lib/nuwords.rb
|
24
|
+
- LICENSE
|
25
|
+
- README.rdoc
|
26
|
+
files:
|
27
|
+
- lib/nuwords.rb
|
28
|
+
- LICENSE
|
29
|
+
- Rakefile
|
30
|
+
- README.rdoc
|
31
|
+
- test/nuwords_test.rb
|
32
|
+
- test/test_helper.rb
|
33
|
+
- VERSION
|
34
|
+
- Manifest
|
35
|
+
- nuwords.gemspec
|
36
|
+
has_rdoc: true
|
37
|
+
homepage: http://github.com/softprops/nuwords
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options:
|
40
|
+
- --line-numbers
|
41
|
+
- --inline-source
|
42
|
+
- --title
|
43
|
+
- Nuwords
|
44
|
+
- --main
|
45
|
+
- README.rdoc
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
version:
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "1.2"
|
59
|
+
version:
|
60
|
+
requirements: []
|
61
|
+
|
62
|
+
rubyforge_project: nuwords
|
63
|
+
rubygems_version: 1.2.0
|
64
|
+
signing_key:
|
65
|
+
specification_version: 3
|
66
|
+
summary: convert numbers to words
|
67
|
+
test_files:
|
68
|
+
- test/nuwords_test.rb
|
69
|
+
- test/test_helper.rb
|