nth 0.0.0 → 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.
- checksums.yaml +5 -5
- data/README.md +312 -3
- data/lib/nth.rb +1152 -15
- data/lib/nth/version.rb +1 -1
- data/nth.gemspec +13 -2
- metadata +40 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4a4fce17c6efcc75cf89e5b36527176f4b802181a2316604ee335d8b5dfbfe0a
|
4
|
+
data.tar.gz: 3638a58a6b22aea56b8595b2a0ffa06d95af0920bd9a55bb942bf1fd8521bc60
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e922ea67a821019afcffcd1e0f51541bf920255a0b4a2da4bce8055d6904dd401bf5f7df31f5d0865ee231832834dc6fd8115b4bc95ab16dd339c9f8991fbcd1
|
7
|
+
data.tar.gz: c7e5ac4703133a07f5619e58f57dcd0471c92538ca23a2995dc8bbd254f02fae753e11c3f9c7ee42f614dd65de6487019b34b028821ef7d7a4468a481b8c36cf
|
data/README.md
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
# Nth
|
2
2
|
|
3
|
-
|
3
|
+
The Nth gem is a collection of utilities that use named numbers and ordinals to represent or access data.
|
4
|
+
If you starting singing eight quintillion bottles of beer on the wall at the start of the big bang,
|
5
|
+
you would still be signing it today!
|
6
|
+
The gem supports numbers bigger than a milliquadragintillion (over 3000 zeros).
|
7
|
+
A way smaller number septemvigintillion is more than the number of atoms in the Universe; it only has 84 zeros.
|
8
|
+
Asside from ridiculously large numbers, there are also some useful utilities using named numbers.
|
9
|
+
As an example we can access the `#twelfth` character of a string.
|
10
|
+
Cookbook applications might like to use named measurements such as 'five and three quarters'.
|
4
11
|
|
5
12
|
## Installation
|
6
13
|
|
@@ -20,8 +27,310 @@ Or install it yourself as:
|
|
20
27
|
|
21
28
|
## Usage
|
22
29
|
|
23
|
-
|
24
|
-
|
30
|
+
The Nth gem has methods that can be used out of the box. Instead you can install these methods to base classes such as `Integer` or `String`.
|
31
|
+
This document will first explain how to install various utilities or a subset of available utilities to base classes.
|
32
|
+
The last part of the document shows how to use some of the utilities without installing methods to base classes.
|
33
|
+
Note that access methods must be installed.
|
34
|
+
|
35
|
+
### Access Methods
|
36
|
+
|
37
|
+
Instead of using the `[]` and `[]=` operators, on `Arrays` or `Strings` we can access elements using ordinals.
|
38
|
+
This can also be applied to custom objects provided certain methods have been implemented.
|
39
|
+
There are two mechanisms that can applied in order to endow a class with ordinal access.
|
40
|
+
The preferred means utilizes a generator that defines a subset of ordinal access methods.
|
41
|
+
The other uses the `method_missing` dynamic system of ghost methods which is less performant.
|
42
|
+
As you only get to override `method_missing` once, you should be careful that some other library has not already done this.
|
43
|
+
Note that both can be used at the same time; this allows for the more common ordinals to provide faster access.
|
44
|
+
These access methods must be installed on a base class before they become active.
|
45
|
+
Such installation should only be placed in your startup code.
|
46
|
+
This is best seen by example as follows:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
require 'Nth'
|
50
|
+
"".respond_to? :first # false ... ordinal access not installed yet
|
51
|
+
"".respond_to? :last # false
|
52
|
+
|
53
|
+
Nth::install(:AccessOrdinals, String, 5)
|
54
|
+
# above installs: #first, #second, #third, #fourth, #fifth, and #last methods
|
55
|
+
|
56
|
+
str = "This is a test!"
|
57
|
+
str.first # 'T'
|
58
|
+
str.last # '!'
|
59
|
+
str.fourth # 's'
|
60
|
+
str.fifth # ' '
|
61
|
+
str.sixth # error not defined
|
62
|
+
str.fifth = '_' # str == "This_is a test!"
|
63
|
+
|
64
|
+
# add more ordinals ...
|
65
|
+
Nth::install(:AccessOrdinals, String, 25, '.') # '.' is the fill parameter ... ' ' is the default
|
66
|
+
|
67
|
+
str.methods.include? :twenty_fifth # true
|
68
|
+
str.methods.include? :twenty_fifth= # true
|
69
|
+
|
70
|
+
str = "testing "
|
71
|
+
str.twenty_fifth = " 1,2,3" # str == "testing ................ 1,2,3"
|
72
|
+
|
73
|
+
# add all ordinals using method missing ...
|
74
|
+
Nth::install(:AccessAllOrdinals, String, '?')
|
75
|
+
|
76
|
+
str.methods.include? :thirtieth # false ... not a real method
|
77
|
+
str.respond_to? :thirtieth # true ... but will respond to call
|
78
|
+
|
79
|
+
str.fourtieth = "$" # str == "testing ................ 1,2,3?????????$"
|
80
|
+
```
|
81
|
+
|
82
|
+
From the above we have the first 25 ordinals defined with actual methods, with the remaining ordinals defined using ghost methods.
|
83
|
+
Now if you were to access the ordinal `str.tresvigintillionth = "oops!"`, your computer would run out of memory!
|
84
|
+
You can change the fill character by calling: `String.instance_variable_set :@default_insert, ' '`.
|
85
|
+
Now we can do the same thing with Arrays as follows:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
require 'Nth'
|
89
|
+
Nth::install(:AccessOrdinals, Array, 15, "nada") # defaults to nil if no fill specified
|
90
|
+
array = [1,2,3]
|
91
|
+
array.fifth = 500 # [1, 2, 3, "nada", 500]
|
92
|
+
Nth::install(:AccessAllOrdinals, Array, nil)
|
93
|
+
array.tenth = "pi" # [1, 2, 3, "nada", 500, nil, nil, nil, nil, "pi"]
|
94
|
+
```
|
95
|
+
|
96
|
+
From the above we have 15 actual ordinal methods, with the remainder implemented using ghost methods.
|
97
|
+
Note that you only get one ghost method per class so be judicious.
|
98
|
+
Custom objects call also install ordinal access provided that they implement the following methods:
|
99
|
+
`:[]`, `:[]=`, `size`. Note that Hash objects don't behave well as they are not ordered numerically like Array or String objects are.
|
100
|
+
|
101
|
+
### Integer Methods
|
102
|
+
|
103
|
+
Integer methods must be installed before they become available.
|
104
|
+
Each method creates a string which represents the number in some way.
|
105
|
+
Integer methods are installed as follows: `Nth::install(:IntMethods)`.
|
106
|
+
Each method is documented in the following subsections.
|
107
|
+
|
108
|
+
#### Instance Method `nth`
|
109
|
+
|
110
|
+
This method creates a string comprising the number followed by a 2-letter suffix.
|
111
|
+
Larger numbers are grouped in 3 and delimited by a comma.
|
112
|
+
See the examples below:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
require 'Nth'
|
116
|
+
Nth::install(:IntMethods)
|
117
|
+
|
118
|
+
5.nth # "5th"
|
119
|
+
1.nth # "1st"
|
120
|
+
22.nth # "22nd"
|
121
|
+
63.nth # "63rd"
|
122
|
+
11.nth # "11th"
|
123
|
+
0.nth # "0th"
|
124
|
+
-12345673.nth # "-12,345,673rd"
|
125
|
+
```
|
126
|
+
|
127
|
+
#### Instance Method `to_number`
|
128
|
+
|
129
|
+
This method creates a string name that represents the number.
|
130
|
+
See the examples below:
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
require 'Nth'
|
134
|
+
Nth::install(:IntMethods)
|
135
|
+
|
136
|
+
123456789.to_number # "one hundred twenty-three million four hundred fifty-six thousand seven hundred eighty-nine"
|
137
|
+
600013417.to_number # "six hundred million thirteen thousand four hundred seventeen"
|
138
|
+
(10**105).to_number # "one quattuortrigintillion"
|
139
|
+
```
|
140
|
+
|
141
|
+
#### Instance Method `to_ordinal`
|
142
|
+
|
143
|
+
This method creates a string name that represents the ordinal name of the number.
|
144
|
+
See the examples below:
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
require 'Nth'
|
148
|
+
Nth::install(:IntMethods)
|
149
|
+
|
150
|
+
123456783.to_ordinal # "one hundred twenty-three million four hundred fifty-six thousand seven hundred eighty-third"
|
151
|
+
600013412.to_ordinal # "six hundred million thirteen thousand four hundred twelfth"
|
152
|
+
(10**105).to_ordinal # "one quattuortrigintillionth"
|
153
|
+
```
|
154
|
+
|
155
|
+
#### Instance Method `cents_to_dollars`
|
156
|
+
|
157
|
+
This method creates a string money name that could be used to print checks.
|
158
|
+
The integer represents the number of pennies.
|
159
|
+
See the examples below:
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
require 'Nth'
|
163
|
+
Nth::install(:IntMethods)
|
164
|
+
|
165
|
+
1458312.cents_to_dollars # "fourteen thousand five hundred eighty-three dollars and twelve cents"
|
166
|
+
101.cents_to_dollars # "one dollar and one cent"
|
167
|
+
56.cents_to_dollars # "zero dollars and fifty-six cents"
|
168
|
+
200.cents_to_dollars # "two dollars and zero cents"
|
169
|
+
```
|
170
|
+
|
171
|
+
#### Instance Method `pence_to_pounds`
|
172
|
+
|
173
|
+
This method creates a string money name that could be used to print checks.
|
174
|
+
The integer represents the number of pence. This is the British version of `cents_to_dollars`.
|
175
|
+
See the examples below:
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
require 'Nth'
|
179
|
+
Nth::install(:IntMethods)
|
180
|
+
|
181
|
+
1458312.pence_to_pounds # "fourteen thousand five hundred eighty-three pounds and twelve pence"
|
182
|
+
101.pence_to_pounds # "one pound and one penny"
|
183
|
+
56.pence_to_pounds # "zero pounds and fifty-six pence"
|
184
|
+
200.pence_to_pounds # "two pounds and zero pence"
|
185
|
+
```
|
186
|
+
|
187
|
+
### Float Methods
|
188
|
+
|
189
|
+
Float methods must be installed before they become available.
|
190
|
+
There are a variety of methods that implement a variety of utilities.
|
191
|
+
Float methods are installed as follows: `Nth::install(:FloatMethods)`.
|
192
|
+
Each method is documented in the following subsections.
|
193
|
+
|
194
|
+
#### Instance Method `to_fractional_unit(unit_name, mode = :descriptive, tar=0.01)`
|
195
|
+
|
196
|
+
This method converts a floating point number to a unit based fraction with a multiplicity of formats.
|
197
|
+
The `unit_name` parameter use use the singular noun; the method will pluralized the noun when appropriate.
|
198
|
+
The `mode` parameter formats the resulting string; this will be explained by example later.
|
199
|
+
The `tar` parameter defines the target resolution of the fraction; it is the percent error of the fraction.
|
200
|
+
This routine is most useful for cookbook applications. See example below:
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
require 'Nth'
|
204
|
+
Nth::install(:FloatMethods) # do this once in the initialization section of your code
|
205
|
+
|
206
|
+
cups = 4.333333
|
207
|
+
cups.to_fractional_unit('cup') # "four and one third cups"
|
208
|
+
cups.to_fractional_unit('cup', :numeric) # "4 1/3 cups"
|
209
|
+
(1.0).to_fractional_unit('cup', :numeric) # "1 cup"
|
210
|
+
|
211
|
+
# mode :utf uses fraction glyphs if available ... uses digits for whole numbers
|
212
|
+
# mode :html uses fraction glyphs via html ampersand semicolon syntax
|
213
|
+
```
|
214
|
+
|
215
|
+
#### Instance Method `inches_to_feet(mode = :descriptive, denom=16)`
|
216
|
+
|
217
|
+
This method converts floating point inches to a string comprising feet and inches.
|
218
|
+
The parameter `mode` defines how the resulting string is formatted.
|
219
|
+
The `denom` parameter specifies the target resolution; for proper tape measure formate, this should be a power of `2`.
|
220
|
+
See the examples below:
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
require 'Nth'
|
224
|
+
Nth::install(:FloatMethods)
|
225
|
+
|
226
|
+
data = 123.4567
|
227
|
+
data.inches_to_feet # "ten feet three and seven sixteenth inches"
|
228
|
+
data.inches_to_feet(:numeric_long) # "10 feet 3 7/16 inches"
|
229
|
+
data.inches_to_feet(:numeric_short) # "10ft 3 7/16in"
|
230
|
+
data.inches_to_feet(:numeric_short,32) # "10ft 3 15/32in"
|
231
|
+
(13.0).inches_to_feet # "one foot one inch"
|
232
|
+
# mode == :tics_utf uses utf tic marks
|
233
|
+
# mode == :tics_html same as above but uses html entities to represent tic marks
|
234
|
+
# FYI:: love to show you an example, but can't display UTF chars in *.md document
|
235
|
+
```
|
236
|
+
|
237
|
+
#### Instance Method `inches_to_yards(mode = :descriptive, denom=16)`
|
238
|
+
|
239
|
+
Similar to `inches_to_feet`, but instead separates number into three fields: yards, feet, inches.
|
240
|
+
This uses the same parameters as `inches_to_feet`, except `tics_utf` and `tics_html` are not supported.
|
241
|
+
|
242
|
+
|
243
|
+
#### Instance Method `to_dms(frac_sec==2)`
|
244
|
+
|
245
|
+
This turns geographical floating point numbers into degrees, minutes, and seconds.
|
246
|
+
The routine produces utf chars that include degree glyphs as well as tic marks.
|
247
|
+
The parameter `frac_sec` defines the number of displayed fractional digits in the seconds field.
|
248
|
+
|
249
|
+
### Nth Module direct methods
|
250
|
+
|
251
|
+
This section details various methods that can be used without having to perform an installation to a class.
|
252
|
+
There are several utility methods that are not documented as they are called by more useful methods.
|
253
|
+
There are also methods that are not available in the installed section that have some utility.
|
254
|
+
|
255
|
+
#### `Nth::pluralize(str)`
|
256
|
+
|
257
|
+
This seemingly unrelated method is used to pluralize unit names; but it can be used on other nouns as well.
|
258
|
+
This routine also handles most exceptions. See the example below:
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
require 'Nth'
|
262
|
+
|
263
|
+
Nth::pluralize('foot') # 'feet'
|
264
|
+
Nth::pluralize('octopus') # "octopi"
|
265
|
+
Nth::pluralize('box') # "boxes"
|
266
|
+
Nth::pluralize('wife') # "wives"
|
267
|
+
Nth::pluralize('kiss') # "kisses"
|
268
|
+
Nth::pluralize('fish') # "fish"
|
269
|
+
Nth::pluralize('die') # "dice"
|
270
|
+
```
|
271
|
+
|
272
|
+
#### `Nth::get_number_name(int, *flags)`
|
273
|
+
|
274
|
+
This converts an integer to a named number. The `flags` parameter list defines the final string formatting.
|
275
|
+
This is best seen by example as follows:
|
276
|
+
|
277
|
+
```ruby
|
278
|
+
require 'Nth'
|
279
|
+
# flags are as follows:
|
280
|
+
# :-_ separate each word with an underscore
|
281
|
+
# :- use dashes on some word combinations such as: twenty-six
|
282
|
+
# :plus_minus prefix number with 'plus' or 'minus' (default 'minus' if negative else '')
|
283
|
+
# :positive_negative prefix number with 'positive' or 'negative'
|
284
|
+
|
285
|
+
Nth::get_number_name(-13453) # "minus thirteen thousand four hundred fifty three"
|
286
|
+
Nth::get_number_name(13453, :-) # "thirteen thousand four hundred fifty-three"
|
287
|
+
Nth::get_number_name(13453, :_) # "thirteen_thousand_four_hundred_fifty_three"
|
288
|
+
Nth::get_number_name(17, :plus_minus) # "plus seventeen"
|
289
|
+
Nth::get_number_name(17, :positive_negative) # "positive seventeen"
|
290
|
+
Nth::get_number_name(-17, :_, :positive_negative) # "negative_seventeen"
|
291
|
+
```
|
292
|
+
|
293
|
+
#### `Nth::get_ordinal_name(int, *flags)`
|
294
|
+
|
295
|
+
This routine uses the same flags as `get_number_name`, but instead produces ordinal names.
|
296
|
+
See the example below:
|
297
|
+
|
298
|
+
```ruby
|
299
|
+
Nth::get_ordinal_name(-13453) # "minus thirteen thousand four hundred fifty third"
|
300
|
+
Nth::get_ordinal_name(-17, :_, :positive_negative) "negative_seventeenth"
|
301
|
+
```
|
302
|
+
|
303
|
+
#### Integer Methods without installation
|
304
|
+
|
305
|
+
We can access without installation integer methods as follows:
|
306
|
+
|
307
|
+
```ruby
|
308
|
+
Nth::IntMethods::to_nth_string(12345) # "12,345th"
|
309
|
+
Nth::IntMethods::to_nth_string(12345,false) # "12345th"
|
310
|
+
Nth::IntMethods::penny_to_dollar(12345) # "one hundred twenty-three dollars and forty-five cents"
|
311
|
+
Nth::IntMethods::pence_to_pound(12345) # "one hundred twenty-three pounds and forty-five pence"
|
312
|
+
```
|
313
|
+
|
314
|
+
#### Float Methods without installation
|
315
|
+
|
316
|
+
We can access without installation float methods as follows:
|
317
|
+
|
318
|
+
```ruby
|
319
|
+
Nth::FloatMethods::to_fractional_unit(3.666666, 'cup', :descriptive, 0.01) # "three and two third cups"
|
320
|
+
Nth::FloatMethods::to_fractional_unit(3.666666, 'cup', :numeric, 0.01) # "3 2/3 cups"
|
321
|
+
# also modes: :utf and :html
|
322
|
+
|
323
|
+
Nth::FloatMethods::inches_to_feet(14.63953, :descriptive, 64) # "one foot two and forty-one sixty-fourth inches"
|
324
|
+
Nth::FloatMethods::inches_to_feet(14.63953, :numeric_long, 64) # "1 foot 2 41/64 inches"
|
325
|
+
Nth::FloatMethods::inches_to_feet(14.63953, :numeric_short, 64) # "1ft 2 41/64in"
|
326
|
+
# also modes: :tics_utf and :tics_html
|
327
|
+
|
328
|
+
Nth::FloatMethods::inches_to_yards(136.67134, :descriptive, 16) # "three yards two feet four and eleven sixteenth inches"
|
329
|
+
Nth::FloatMethods::inches_to_yards(136.67134, :numeric_long, 16) # "3 yards 2 feet 4 11/16 inches"
|
330
|
+
Nth::FloatMethods::inches_to_yards(136.67134, :numeric_short, 16) # "3yd 2ft 4 11/16in"
|
331
|
+
|
332
|
+
Nth::FloatMethods::to_dms(-121.9361831121, 4) # can't display on *md file, but try yourself!
|
333
|
+
```
|
25
334
|
|
26
335
|
## Development
|
27
336
|
|
data/lib/nth.rb
CHANGED
@@ -1,25 +1,1162 @@
|
|
1
1
|
require "nth/version"
|
2
|
+
require "primitive_wrapper"
|
2
3
|
|
3
4
|
module Nth
|
4
|
-
|
5
|
-
|
6
|
-
'
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
5
|
+
|
6
|
+
FRACTION_UTF = { "1/2" => '½', "1/4" => '¼', "3/4" => '¾', "1/3" => '⅓', "2/3" => '⅔',
|
7
|
+
"1/8" => '⅛', "3/8" => '⅜',"5/8" => '⅝', "7/8" => '⅞',
|
8
|
+
"1/5" => '⅕',"2/5" => '⅖', "3/5" => '⅗',"4/5" => '⅘',"1/6" => '⅙', "5/6" => '⅚',"1/9" => '⅑',"1/10" => '⅒'}
|
9
|
+
html = {}
|
10
|
+
|
11
|
+
NUMBERS = {0 => 'zero', 1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five', 6 => 'six', 7 => 'seven', 8 => 'eight', 9 => 'nine', 10 => 'ten',
|
12
|
+
11 => 'eleven', 12 => 'twelve', 13 => 'thirteen', 14 => 'fourteen', 15 => 'fifteen', 16 => 'sixteen', 17 => 'seventeen', 18 => 'eighteen', 19 => 'nineteen',
|
13
|
+
20 => 'twenty', 30 => 'thirty', 40 => 'forty', 50 => 'fifty', 60 => 'sixty', 70 => 'seventy', 80 => 'eighty', 90 => 'ninety',
|
14
|
+
100 => 'hundred',
|
15
|
+
'10**3' => 'thousand',
|
16
|
+
'10**6' => 'million',
|
17
|
+
'10**9' => 'billion',
|
18
|
+
'10**12' => 'trillion',
|
19
|
+
'10**15' => 'quadrillion',
|
20
|
+
'10**18' => 'quintillion',
|
21
|
+
'10**21' => 'sextillion',
|
22
|
+
'10**24' => 'septillion',
|
23
|
+
'10**27' => 'octillion',
|
24
|
+
'10**30' => 'nonillion',
|
25
|
+
'10**33' => 'decillion',
|
26
|
+
'10**36' => 'undecillion',
|
27
|
+
'10**39' => 'duodecillion',
|
28
|
+
'10**42' => 'tredecillion',
|
29
|
+
'10**45' => 'quattuordecillion',
|
30
|
+
'10**48' => 'quindecillion',
|
31
|
+
'10**51' => 'sexdecillion',
|
32
|
+
'10**54' => 'septendecillion',
|
33
|
+
'10**57' => 'octodecillion',
|
34
|
+
'10**60' => 'novemdecillion', # rule generator makes this novendecillion
|
35
|
+
'10**63' => 'vigintillion',
|
36
|
+
'10**66' => 'unvigintillion',
|
37
|
+
'10**69' => 'duovigintillion',
|
38
|
+
'10**72' => 'tresvigintillion',
|
39
|
+
'10**75' => 'quattuorvigintillion',
|
40
|
+
'10**78' => 'quinquavigintillion',
|
41
|
+
'10**81' => 'sesvigintillion',
|
42
|
+
'10**84' => 'septemvigintillion',
|
43
|
+
'10**87' => 'octovigintillion',
|
44
|
+
'10**90' => 'novemvigintillion',
|
45
|
+
'10**93' => 'trigintillion',
|
46
|
+
'10**96' => 'untrigintillion',
|
47
|
+
'10**99' => 'duotrigintillion',
|
48
|
+
'10**102' => 'trestrigintillion',
|
49
|
+
'10**105' => 'quattuortrigintillion',
|
50
|
+
'10**108' => 'quinquatrigintillion',
|
51
|
+
'10**111' => 'sestrigintillion',
|
52
|
+
'10**114' => 'septentrigintillion',
|
53
|
+
'10**117' => 'octotrigintillion',
|
54
|
+
'10**120' => 'noventrigintillion',
|
55
|
+
'10**123' => 'quadragintillion',
|
56
|
+
'10**100' => 'googol',
|
57
|
+
'10**3003' => 'millinillion',
|
58
|
+
'10**3006' => 'millimillion',
|
59
|
+
'10**3009' => 'millibillion',
|
60
|
+
'10**3012' => 'millitrillion',
|
61
|
+
'10**3015' => 'milliquadrillion',
|
62
|
+
'10**3018' => 'milliquintillion',
|
63
|
+
'10**3021' => 'millisextillion',
|
64
|
+
'10**3024' => 'milliseptillion',
|
65
|
+
'10**3027' => 'millioctillion',
|
66
|
+
'10**3030' => 'millinonillion',
|
67
|
+
'10**3033' => 'millidecillion',
|
68
|
+
'10**3036' => 'milliundecillion',
|
69
|
+
'10**3039' => 'milliduodecillion',
|
70
|
+
'10**3042' => 'millitredecillion',
|
71
|
+
'10**3045' => 'milliquattuordecillion',
|
72
|
+
'10**3048' => 'milliquindecillion',
|
73
|
+
'10**3051' => 'millisexdecillion',
|
74
|
+
'10**3054' => 'milliseptendecillion',
|
75
|
+
'10**3057' => 'millioctodecillion',
|
76
|
+
'10**3060' => 'millinovemdecillion',
|
77
|
+
'10**3063' => 'millivigintillion',
|
78
|
+
'10**3066' => 'milliunvigintillion',
|
79
|
+
'10**3069' => 'milliduovigintillion',
|
80
|
+
'10**3072' => 'millitresvigintillion',
|
81
|
+
'10**3075' => 'milliquattuorvigintillion',
|
82
|
+
'10**3078' => 'milliquinquavigintillion',
|
83
|
+
'10**3081' => 'millisesvigintillion',
|
84
|
+
'10**3084' => 'milliseptemvigintillion',
|
85
|
+
'10**3087' => 'millioctovigintillion',
|
86
|
+
'10**3090' => 'millinovemvigintillion',
|
87
|
+
'10**3093' => 'millitrigintillion',
|
88
|
+
'10**3096' => 'milliuntrigintillion',
|
89
|
+
'10**3099' => 'milliduotrigintillion',
|
90
|
+
'10**3102' => 'millitrestrigintillion',
|
91
|
+
'10**3105' => 'milliquattuortrigintillion',
|
92
|
+
'10**3108' => 'milliquinquatrigintillion',
|
93
|
+
'10**3111' => 'millisestrigintillion',
|
94
|
+
'10**3114' => 'milliseptentrigintillion',
|
95
|
+
'10**3117' => 'millioctotrigintillion',
|
96
|
+
'10**3120' => 'millinoventrigintillion',
|
97
|
+
'10**3123' => 'milliquadragintillion'
|
98
|
+
}
|
99
|
+
|
100
|
+
# might go to just under Duomillinillion, but not until next revision
|
101
|
+
# to go higher, need the definitive naming scheme.
|
102
|
+
|
103
|
+
ORDINALS = {0 => 'zeroth', 1 => 'first', 2 => 'second', 3 => 'third', 4 => 'fourth', 5 => 'fifth', 6 => 'sixth', 7 => 'seventh', 8 => 'eighth', 9 => 'ninth', 10 => 'tenth',
|
104
|
+
11 => 'eleventh', 12 => 'twelfth', 13 => 'thirteenth', 14 => 'fourteenth', 15 => 'fifteenth', 16 => 'sixteenth', 17 => 'seventeenth', 18 => 'eighteenth', 19 => 'nineteenth',
|
105
|
+
20 => 'twentieth', 30 => 'thirtieth', 40 => 'fortieth', 50 => 'fiftieth', 60 => 'sixtieth', 70 => 'seventieth', 80 => 'eightieth', 90 => 'ninetieth',
|
106
|
+
100 => 'hundredth', -1 => 'last'
|
107
|
+
}
|
108
|
+
|
109
|
+
#NUMBERS.each_pair { |key,val| ords[key] = val + "th" if ords[key].nil? }
|
110
|
+
#ORDINALS = ords.freeze
|
111
|
+
|
112
|
+
|
113
|
+
ORD_FORMAT_ERROR = "ordinal format error"
|
114
|
+
SET_TRE = [90,900,70,700,60,600,10,200] # no need for extra 's'
|
115
|
+
SET_NOVE = [90,900] # no need for extra '?'
|
116
|
+
|
117
|
+
# see:: https://en.wikipedia.org/wiki/Names_of_large_numbers
|
118
|
+
PRE_TABLE = {}
|
119
|
+
PRE_TABLE["un"] = {:val=>1, :solo=>false, :sfx => [], :if => [], :rpl => [] }
|
120
|
+
PRE_TABLE["duo"] = {:val=>2, :solo=>false, :sfx => [], :if => [], :rpl => [] }
|
121
|
+
PRE_TABLE["tre"] = {:val=>3, :solo=>false, :sfx => [:s], :if => [:s,:x], :rpl => [] }
|
122
|
+
PRE_TABLE["quattuor"] = {:val=>4, :solo=>false, :sfx => [], :if => [], :rpl => [] }
|
123
|
+
PRE_TABLE["quinqua"] = {:val=>5, :solo=>false, :sfx => [], :if => [], :rpl => [] }
|
124
|
+
PRE_TABLE["se"] = {:val=>6, :solo=>false, :sfx => [:s,:x], :if => [:s,:x], :rpl => [] }
|
125
|
+
PRE_TABLE["septe"] = {:val=>7, :solo=>false, :sfx => [:m,:n], :if => [:m,:n],:rpl => [] }
|
126
|
+
PRE_TABLE["octo"] = {:val=>8, :solo=>false, :sfx => [], :if => [],:rpl => [] }
|
127
|
+
PRE_TABLE["nove"] = {:val=>9, :solo=>false, :sfx => [:m,:n], :if => [:m,:n], :rpl => [] }
|
128
|
+
|
129
|
+
PRE_TABLE["dec"] = {:val=>10, :solo=>true, :sfx => [:i], :if => [], :rpl => [:a,:i,:n] }
|
130
|
+
PRE_TABLE["vigint"] = {:val=>20, :solo=>true, :sfx => [:i], :if => [], :rpl => [:a,:i,:m, :s] }
|
131
|
+
PRE_TABLE["trigint"] = {:val=>30, :solo=>true, :sfx => [:a], :if => [], :rpl => [:a,:i,:n, :s] }
|
132
|
+
PRE_TABLE["quadragint"] = {:val=>40, :solo=>true, :sfx => [:a], :if => [], :rpl => [:a,:i,:n, :s] } # quadragintillion ... the 'a' gets dropped here
|
133
|
+
PRE_TABLE["quinquagint"] = {:val=>50, :solo=>true, :sfx => [:a], :if => [], :rpl => [:a,:i,:n, :s] } # maybe best if we drop it here, then add, an `:extra` key
|
134
|
+
PRE_TABLE["sexagint"] = {:val=>60, :solo=>true, :sfx => [:a], :if => [], :rpl => [:a,:i,:n] }
|
135
|
+
PRE_TABLE["septuagint"] = {:val=>70, :solo=>true, :sfx => [:a], :if => [], :rpl => [:a,:i,:n] }
|
136
|
+
PRE_TABLE["octogint"] = {:val=>80, :solo=>true, :sfx => [:a], :if => [], :rpl => [:a,:i,:m, :x] }
|
137
|
+
PRE_TABLE["nonagint"] = {:val=>90, :solo=>true, :sfx => [:a], :if => [], :rpl => [:a,:i] }
|
138
|
+
|
139
|
+
PRE_TABLE["cent"] = {:val=>100, :solo=>true, :sfx => [:i], :if => [], :rpl => [:a,:i,:n, :x] }
|
140
|
+
PRE_TABLE["ducent"] = {:val=>200, :solo=>true, :sfx => [:i], :if => [], :rpl => [:a,:i,:n] }
|
141
|
+
PRE_TABLE["trecent"] = {:val=>300, :solo=>true, :sfx => [:i], :if => [], :rpl => [:a,:i,:n, :s] }
|
142
|
+
PRE_TABLE["quadringent"] = {:val=>400, :solo=>true, :sfx => [:i], :if => [], :rpl => [:a,:i,:n, :s] }
|
143
|
+
PRE_TABLE["quingent"] = {:val=>500, :solo=>true, :sfx => [:i], :if => [], :rpl => [:a,:i,:n, :s] }
|
144
|
+
PRE_TABLE["sescent"] = {:val=>600, :solo=>true, :sfx => [:i], :if => [], :rpl => [:a,:i,:n] }
|
145
|
+
PRE_TABLE["septingent"] = {:val=>700, :solo=>true, :sfx => [:i], :if => [], :rpl => [:a,:i,:n] }
|
146
|
+
PRE_TABLE["octingent"] = {:val=>800, :solo=>true, :sfx => [:i], :if => [], :rpl => [:a,:i,:m, :x] }
|
147
|
+
PRE_TABLE["nongent"] = {:val=>900, :solo=>true, :sfx => [:i], :if => [], :rpl => [:a,:i] }
|
148
|
+
|
149
|
+
# no example on how to combine with others ... but here it is:
|
150
|
+
# PRE_TABLE["millin"] = {:val=>1000, :solo=>false, :sfx => [:i], :if => [], :rpl => [:a,:i] }
|
151
|
+
|
152
|
+
# if you can find a reference for larger, then place here ... best so far ...
|
153
|
+
# http://answers.wikia.com/wiki/What_number_comes_after_millinillion
|
154
|
+
# problem with the above is inconsistency with former system.
|
155
|
+
|
156
|
+
pes = {}
|
157
|
+
pes['sheep']='sheep'
|
158
|
+
pes['series']='series'
|
159
|
+
pes['species']='species'
|
160
|
+
pes['deer']='deer'
|
161
|
+
pes['fish']='fish'
|
162
|
+
pes['child']='children'
|
163
|
+
pes['goose']='geese'
|
164
|
+
pes['man']='men'
|
165
|
+
pes['woman']='women'
|
166
|
+
pes['tooth']='teeth'
|
167
|
+
pes['foot']='feet'
|
168
|
+
pes['mouse']='mice'
|
169
|
+
pes['person']='people'
|
170
|
+
pes['ox']='oxen'
|
171
|
+
pes['photo']='photos'
|
172
|
+
pes['piano']='pianos'
|
173
|
+
pes['halo']='halos'
|
174
|
+
pes['roof']='roofs'
|
175
|
+
pes['belief']='beliefs'
|
176
|
+
pes['chef']='chefs'
|
177
|
+
pes['chief']='chiefs'
|
178
|
+
pes['fez']='fezzes'
|
179
|
+
pes['gas']='gasses'
|
180
|
+
pes['pion']='pions'
|
181
|
+
pes['criterion']='criteria'
|
182
|
+
pes['phenomenon']='phenomena'
|
183
|
+
pes['canto']='cantos'
|
184
|
+
pes['zero']='zeros'
|
185
|
+
pes['cello']='cellos'
|
186
|
+
pes['louse']='lice'
|
187
|
+
pes['die']='dice'
|
188
|
+
pes['child']='children'
|
189
|
+
pes['penny']='pence'
|
190
|
+
pes['person']='people'
|
191
|
+
pes['moose']='moose'
|
192
|
+
pes['swine']='swine'
|
193
|
+
pes['buffalo']='buffalo'
|
194
|
+
pes['shrimp']='shrimp'
|
195
|
+
pes['trout']='trout'
|
196
|
+
pes['aircraft']='aircraft'
|
197
|
+
pes['watercraft']='watercraft'
|
198
|
+
pes['hovercraft']='hovercraft'
|
199
|
+
pes['spacecraft']='spacecraft'
|
200
|
+
|
201
|
+
PLURAL_EXCPETIONS = pes.freeze
|
202
|
+
|
203
|
+
# utility methods: the gem pluralize too simple ... maybe you should fix this ...
|
204
|
+
# ::TODO:: move to new gem, then update this gem
|
205
|
+
def self.pluralize(str)
|
206
|
+
str = str.rstrip
|
207
|
+
tst = PLURAL_EXCPETIONS[str]
|
208
|
+
return tst unless tst.nil?
|
209
|
+
ch = str[-1]
|
210
|
+
sfx = str[-2..-1]
|
211
|
+
if ['ay','ey','oy','uy','iy'].include? sfx
|
212
|
+
return str + 's'
|
213
|
+
elsif ['is'].include? sfx # analysis analyses
|
214
|
+
return str[0..-3] +'es'
|
215
|
+
elsif ['us'].include? sfx # focus foci
|
216
|
+
return str[0..-3] +'i'
|
217
|
+
elsif sfx=='fe'
|
218
|
+
return str[0..-3] + 'ves'
|
219
|
+
elsif ch=='f'
|
220
|
+
return str[0..-2] + 'ves'
|
221
|
+
elsif ch=='y'
|
222
|
+
return str[0..-2] +'ies'
|
223
|
+
elsif ['s','x','z','o'].include? ch
|
224
|
+
return str +'es'
|
225
|
+
elsif ['ch', 'sh'].include? sfx
|
226
|
+
return str +'es'
|
227
|
+
elsif ['um'].include? sfx # datum data
|
228
|
+
return str[0..-3] +'a'
|
229
|
+
#elsif ['on'].include? sfx # criterion criteria <<< more the exception than the rule
|
230
|
+
# return str[0..-2] +'a' unless str[-3]=='o' # moon, spoon ... pion peon son won ton
|
231
|
+
end
|
232
|
+
return str + 's'
|
233
|
+
end
|
234
|
+
|
235
|
+
def self.lookup_prefix(str)
|
236
|
+
if (PRE_TABLE.include? str[0..11])
|
237
|
+
return [str[0..11], PRE_TABLE[str[0..11]]]
|
238
|
+
end
|
239
|
+
if (PRE_TABLE.include? str[0..10])
|
240
|
+
return [str[0..10], PRE_TABLE[str[0..10]]]
|
241
|
+
end
|
242
|
+
if (PRE_TABLE.include? str[0..9])
|
243
|
+
return [str[0..9], PRE_TABLE[str[0..9]]]
|
244
|
+
end
|
245
|
+
if (PRE_TABLE.include? str[0..8])
|
246
|
+
return [str[0..8], PRE_TABLE[str[0..8]]]
|
247
|
+
end
|
248
|
+
if (PRE_TABLE.include? str[0..7])
|
249
|
+
return [str[0..7], PRE_TABLE[str[0..7]]]
|
250
|
+
end
|
251
|
+
if (PRE_TABLE.include? str[0..6])
|
252
|
+
return [str[0..6], PRE_TABLE[str[0..6]]]
|
253
|
+
end
|
254
|
+
if (PRE_TABLE.include? str[0..5])
|
255
|
+
return [str[0..5], PRE_TABLE[str[0..5]]]
|
256
|
+
end
|
257
|
+
if (PRE_TABLE.include? str[0..4])
|
258
|
+
return [str[0..4], PRE_TABLE[str[0..4]]]
|
259
|
+
end
|
260
|
+
if (PRE_TABLE.include? str[0..3])
|
261
|
+
return [str[0..3], PRE_TABLE[str[0..3]]]
|
262
|
+
end
|
263
|
+
if (PRE_TABLE.include? str[0..2])
|
264
|
+
return [str[0..2], PRE_TABLE[str[0..2]]]
|
17
265
|
end
|
266
|
+
if (PRE_TABLE.include? str[0..1])
|
267
|
+
return [str[0..1], PRE_TABLE[str[0..1]]]
|
268
|
+
end
|
269
|
+
return [nil,nil]
|
18
270
|
end
|
271
|
+
|
272
|
+
def self.calculate_prefix(str) # see: https://en.wikipedia.org/wiki/Names_of_large_numbers
|
273
|
+
raise ORD_FORMAT_ERROR unless str.index('ii').nil?
|
274
|
+
str = str.dup
|
275
|
+
m = 0
|
276
|
+
if (str[0..4]=='milli')
|
277
|
+
m = 1000
|
278
|
+
str = str[5..-1]
|
279
|
+
end
|
280
|
+
n = 0
|
281
|
+
pre, props = lookup_prefix(str)
|
282
|
+
raise ORD_FORMAT_ERROR if pre.nil?
|
283
|
+
if props[:val] < 10
|
284
|
+
n += props[:val]
|
285
|
+
if props[:if].empty? # simple case
|
286
|
+
str = str[pre.length..-1]
|
287
|
+
pre, props = lookup_prefix(str)
|
288
|
+
else # tricky case
|
289
|
+
str = str[pre.length..-1]
|
290
|
+
pre, sfx = lookup_prefix(str)
|
291
|
+
if pre.nil?
|
292
|
+
xs = str[0]
|
293
|
+
str = str[1..-1]
|
294
|
+
pre, sfx = lookup_prefix(str)
|
295
|
+
raise ORD_FORMAT_ERROR if pre.nil?
|
296
|
+
ch = (props[:if] & sfx[:rpl]).first.to_s
|
297
|
+
unless ch==xs
|
298
|
+
ch = ch.to_sym
|
299
|
+
raise ORD_FORMAT_ERROR unless props[:if].include? ch
|
300
|
+
raise ORD_FORMAT_ERROR unless props[:sfx].include? xs.to_sym
|
301
|
+
end
|
302
|
+
else
|
303
|
+
raise ORD_FORMAT_ERROR unless (props[:if] & sfx[:rpl]).empty?
|
304
|
+
end
|
305
|
+
props = sfx
|
306
|
+
end
|
307
|
+
end
|
308
|
+
if pre && (props[:val] < 100)
|
309
|
+
str = str[pre.length..-1]
|
310
|
+
n += props[:val]
|
311
|
+
pre, sfx = lookup_prefix(str)
|
312
|
+
if pre.nil?
|
313
|
+
ch = str[0]
|
314
|
+
str = str[1..-1]
|
315
|
+
pre, sfx = lookup_prefix(str)
|
316
|
+
unless pre.nil?
|
317
|
+
cch = (sfx[:rpl] & props[:sfx]).first.to_s
|
318
|
+
raise ORD_FORMAT_ERROR unless cch == ch
|
319
|
+
end
|
320
|
+
props = sfx
|
321
|
+
end
|
322
|
+
end
|
323
|
+
if pre && (props[:val] < 1000)
|
324
|
+
str = str[pre.length..-1]
|
325
|
+
n += props[:val]
|
326
|
+
pre, sfx = lookup_prefix(str)
|
327
|
+
raise ORD_FORMAT_ERROR unless pre.nil? # too many!
|
328
|
+
end
|
329
|
+
n += m
|
330
|
+
raise ORD_FORMAT_ERROR if n <= 10
|
331
|
+
n *= 3
|
332
|
+
n = 10 ** (n+3)
|
333
|
+
return n
|
334
|
+
end
|
335
|
+
|
336
|
+
# this only looks up a single item... need to expand for other prefixes/
|
337
|
+
def self.lookup_number(num)
|
338
|
+
return eval(NUMBERS.key(num).to_s) if (NUMBERS.values.include? num)
|
339
|
+
if ("illion" == num[-6..-1])
|
340
|
+
# str = num[0..-7]
|
341
|
+
return calculate_prefix(num)
|
342
|
+
end
|
343
|
+
return nil
|
344
|
+
end
|
345
|
+
|
346
|
+
def self.lookup_ordinal(ordinal)
|
347
|
+
return 0 if (ordinal=="last")
|
348
|
+
return eval(ORDINALS.key(ordinal).to_s) if (ORDINALS.values.include? ordinal)
|
349
|
+
str = ordinal[0..-3]
|
350
|
+
return lookup_number(str)
|
351
|
+
end
|
352
|
+
|
353
|
+
def self.num_ord_string_to_ary(str)
|
354
|
+
return str.split('_') if str.index(' ').nil? # underscore format
|
355
|
+
ary = []
|
356
|
+
aaa = str.split ' '
|
357
|
+
aaa.each do |elm|
|
358
|
+
ary += elm.split '-'
|
359
|
+
end
|
360
|
+
return ary
|
361
|
+
end
|
362
|
+
|
363
|
+
def self.number_string_to_number(str_ary)
|
364
|
+
sum = 0
|
365
|
+
psum = 0
|
366
|
+
neg = false
|
367
|
+
if str_ary.kind_of? String
|
368
|
+
ary = num_ord_string_to_ary(str_ary)
|
369
|
+
else
|
370
|
+
ary = str_ary
|
371
|
+
end
|
372
|
+
ary.each do |elm|
|
373
|
+
if elm == 'minus'
|
374
|
+
neg = true
|
375
|
+
break
|
376
|
+
end
|
377
|
+
num = lookup_number(elm)
|
378
|
+
return nil if num.nil?
|
379
|
+
if num < 1000
|
380
|
+
if psum==0
|
381
|
+
psum = num
|
382
|
+
elsif num > psum
|
383
|
+
psum *= num
|
384
|
+
else
|
385
|
+
psum += num
|
386
|
+
end
|
387
|
+
else
|
388
|
+
sum += num * psum
|
389
|
+
psum = 0
|
390
|
+
end
|
391
|
+
end
|
392
|
+
sum += psum
|
393
|
+
sum = -sum if neg
|
394
|
+
return sum
|
395
|
+
end
|
396
|
+
|
397
|
+
def self.ordinal_string_to_number(str)
|
398
|
+
return -1 if str=="last"
|
399
|
+
sum = 0
|
400
|
+
ary = num_ord_string_to_ary(str)
|
401
|
+
nth = ary.pop
|
402
|
+
val = lookup_ordinal(nth)
|
403
|
+
return nil if val.nil?
|
404
|
+
ary.push get_number_name(val).split(' ').last
|
405
|
+
num = number_string_to_number(ary)
|
406
|
+
return nil if num.nil?
|
407
|
+
return num-1
|
408
|
+
end
|
409
|
+
|
410
|
+
### these may need to be redone ...
|
411
|
+
def self.get_n_from_array(ary)
|
412
|
+
if("minus"==ary.first)
|
413
|
+
n = get_n_from_array(ary[1..-1])
|
414
|
+
return nil if n.nil?
|
415
|
+
return -n
|
416
|
+
end
|
417
|
+
a = lookup_number(ary[0])
|
418
|
+
if a.nil?
|
419
|
+
a = lookup_ordinal(a[0])
|
420
|
+
return nil if a.nil?
|
421
|
+
raise ORD_FORMAT_ERROR if is ary.size > 1
|
422
|
+
return a
|
423
|
+
end
|
424
|
+
b = lookup_number(ary[1])
|
425
|
+
if b.nil?
|
426
|
+
b = lookup_ordinal(ary[1])
|
427
|
+
raise ORD_FORMAT_ERROR if b.nil?
|
428
|
+
raise ORD_FORMAT_ERROR unless ary[2].nil?
|
429
|
+
if a > b # forty_fourth
|
430
|
+
else
|
431
|
+
end
|
432
|
+
else
|
433
|
+
end
|
434
|
+
nil
|
435
|
+
end
|
436
|
+
|
437
|
+
def self.get_n_from_string(ordinal)
|
438
|
+
n = lookup_ordinal(ordinal)
|
439
|
+
return n unless n.nil?
|
440
|
+
return get_n_from_array(ordinal.split('_'))
|
441
|
+
end
|
442
|
+
|
443
|
+
|
444
|
+
def self.get_number_struct(int)
|
445
|
+
neg = int < 0
|
446
|
+
int = -int if neg
|
447
|
+
dat = []
|
448
|
+
while(int > 0)
|
449
|
+
int, triplet = int.divmod 1000
|
450
|
+
dat.push triplet
|
451
|
+
end
|
452
|
+
dat.push neg ? :neg : :pos
|
453
|
+
end
|
454
|
+
|
455
|
+
def self.create_big_number_name(mult)
|
456
|
+
pre = ""
|
457
|
+
num = (mult-3) / 3
|
458
|
+
if (num >= 1000)
|
459
|
+
idx = "10**#{mult}"
|
460
|
+
rtn = NUMBERS[idx]
|
461
|
+
return rtn unless rtn.nil?
|
462
|
+
pre = "milli"
|
463
|
+
num -= 1000
|
464
|
+
raise "Number too big" if num >= 1000 # next revision may address larger numbers
|
465
|
+
end
|
466
|
+
huns, dec = num.divmod 100
|
467
|
+
tens, ones = dec.divmod 10
|
468
|
+
str = ""
|
469
|
+
unless ones.zero?
|
470
|
+
if (1==ones)
|
471
|
+
str = "un"
|
472
|
+
elsif (2==ones)
|
473
|
+
str = "duo"
|
474
|
+
elsif (3==ones)
|
475
|
+
str = "tre"
|
476
|
+
if [2,3,4,5,8].include? tens
|
477
|
+
str += 's'
|
478
|
+
elsif tens.zero?
|
479
|
+
if [1,3,4,5,8].include? huns
|
480
|
+
str += 's'
|
481
|
+
end
|
482
|
+
end
|
483
|
+
elsif (4==ones)
|
484
|
+
str = "quattuor"
|
485
|
+
elsif (5==ones)
|
486
|
+
str = "quinqua"
|
487
|
+
elsif (6==ones)
|
488
|
+
str = "se"
|
489
|
+
if [2,3,4,5].include? tens
|
490
|
+
str += 's'
|
491
|
+
elsif 8==tens
|
492
|
+
str += 'x'
|
493
|
+
elsif tens.zero?
|
494
|
+
if [3,4,5].include? huns
|
495
|
+
str += 's'
|
496
|
+
elsif [1,8].include? huns
|
497
|
+
str += 'x'
|
498
|
+
end
|
499
|
+
end
|
500
|
+
elsif (7==ones)
|
501
|
+
str = "septe"
|
502
|
+
if [1,8].include? tens
|
503
|
+
str += 'm'
|
504
|
+
elsif [1,3,4,5,6,7].include? tens
|
505
|
+
str += 'n'
|
506
|
+
elsif tens.zero?
|
507
|
+
if (1..7).include? huns
|
508
|
+
str += 'n'
|
509
|
+
elsif 8 == huns
|
510
|
+
str += 'm'
|
511
|
+
end
|
512
|
+
end
|
513
|
+
elsif (8==ones)
|
514
|
+
str = "octo"
|
515
|
+
elsif (9==ones)
|
516
|
+
str = "nove"
|
517
|
+
if [1,8].include? tens
|
518
|
+
str += 'm'
|
519
|
+
elsif [1,3,4,5,6,7].include? tens
|
520
|
+
str += 'n'
|
521
|
+
elsif tens.zero?
|
522
|
+
if (1..7).include? huns
|
523
|
+
str += 'n'
|
524
|
+
elsif 8 == huns
|
525
|
+
str += 'm'
|
526
|
+
end
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
unless tens.zero?
|
531
|
+
if (1==tens)
|
532
|
+
str += 'dec'
|
533
|
+
str += 'i' unless huns.zero?
|
534
|
+
elsif (2==tens)
|
535
|
+
str += 'vigint'
|
536
|
+
str += 'i' unless huns.zero?
|
537
|
+
elsif (3==tens)
|
538
|
+
str += 'trigint'
|
539
|
+
str += 'a' unless huns.zero?
|
540
|
+
elsif (4==tens)
|
541
|
+
str += 'quadragint'
|
542
|
+
str += 'a' unless huns.zero?
|
543
|
+
elsif (5==tens)
|
544
|
+
str += 'quinquagint'
|
545
|
+
str += 'a' unless huns.zero?
|
546
|
+
elsif (6==tens)
|
547
|
+
str += 'sexagint'
|
548
|
+
str += 'a' unless huns.zero?
|
549
|
+
elsif (7==tens)
|
550
|
+
str += 'septuagint'
|
551
|
+
str += 'a' unless huns.zero?
|
552
|
+
elsif (8==tens)
|
553
|
+
str += 'octogint'
|
554
|
+
str += 'a' unless huns.zero?
|
555
|
+
elsif (9==tens)
|
556
|
+
str += 'nonagint'
|
557
|
+
str += 'a' unless huns.zero?
|
558
|
+
end
|
559
|
+
end
|
560
|
+
unless huns.zero?
|
561
|
+
if (1==huns)
|
562
|
+
str += 'cent'
|
563
|
+
elsif (2==huns)
|
564
|
+
str += 'ducent'
|
565
|
+
elsif (3==huns)
|
566
|
+
str += 'trecent'
|
567
|
+
elsif (4==huns)
|
568
|
+
str += 'quadringent'
|
569
|
+
elsif (5==huns)
|
570
|
+
str += 'quingent'
|
571
|
+
elsif (6==huns)
|
572
|
+
str += 'sescent'
|
573
|
+
elsif (7==huns)
|
574
|
+
str += 'septingent'
|
575
|
+
elsif (8==huns)
|
576
|
+
str += 'octingent'
|
577
|
+
elsif (9==huns)
|
578
|
+
str += 'nongent'
|
579
|
+
end
|
580
|
+
end
|
581
|
+
return pre + str + 'illion'
|
582
|
+
end
|
583
|
+
|
584
|
+
def self.get_number_name(int, *flags)
|
585
|
+
ary = get_number_struct(int)
|
586
|
+
neg = ary.pop == :neg
|
587
|
+
return NUMBERS[0] if ary.empty?
|
588
|
+
ary.reverse!
|
589
|
+
mult = 0
|
590
|
+
str = ""
|
591
|
+
ch = flags.include?(:_) ? "_" : " "
|
592
|
+
tch = flags.include?(:-) ? "-" : ch
|
593
|
+
loop do
|
594
|
+
break if ary.empty?
|
595
|
+
num = ary.pop
|
596
|
+
hun, dec = num.divmod 100
|
597
|
+
tstr = ""
|
598
|
+
unless hun.zero?
|
599
|
+
tstr = NUMBERS[hun] + ch + NUMBERS[100]
|
600
|
+
unless dec.zero?
|
601
|
+
tstr += ch
|
602
|
+
end
|
603
|
+
end
|
604
|
+
unless dec.zero?
|
605
|
+
if NUMBERS[dec].nil?
|
606
|
+
tens, ones = dec.divmod 10
|
607
|
+
tstr += NUMBERS[tens*10] + tch + NUMBERS[ones]
|
608
|
+
else
|
609
|
+
tstr += NUMBERS[dec]
|
610
|
+
end
|
611
|
+
end
|
612
|
+
unless tstr.empty?
|
613
|
+
if mult.zero?
|
614
|
+
str = tstr
|
615
|
+
else
|
616
|
+
ms = "10**#{mult}"
|
617
|
+
mm = NUMBERS[ms] # if you run out, you will need a generator
|
618
|
+
mm = create_big_number_name(mult) if mm.nil?
|
619
|
+
if str.empty?
|
620
|
+
str = tstr + ch + mm
|
621
|
+
else
|
622
|
+
str = tstr + ch + mm + ch + str
|
623
|
+
end
|
624
|
+
end
|
625
|
+
end
|
626
|
+
mult += 3
|
627
|
+
end
|
628
|
+
if flags.include? :plus_minus
|
629
|
+
if neg # use default
|
630
|
+
return "minus" + ch + str
|
631
|
+
end
|
632
|
+
return "plus" + ch + str
|
633
|
+
end
|
634
|
+
if flags.include? :positive_negative
|
635
|
+
if neg # use default
|
636
|
+
return "negative" + ch + str
|
637
|
+
end
|
638
|
+
return "positive" + ch + str
|
639
|
+
end
|
640
|
+
if neg # use default
|
641
|
+
return "minus" + ch + str
|
642
|
+
end
|
643
|
+
return str
|
644
|
+
end
|
645
|
+
|
646
|
+
def self.get_ordinal_name(int, *flags)
|
647
|
+
return ORDINALS[0] if int.zero?
|
648
|
+
ch = flags.include?(:_) ? "_" : " "
|
649
|
+
tch = flags.include?(:-) ? "-" : ch
|
650
|
+
if int.negative?
|
651
|
+
if flags.include? :positive_negative
|
652
|
+
pre = "negative" + ch
|
653
|
+
else flags.include? :plus_minus
|
654
|
+
pre = "minus" + ch
|
655
|
+
end
|
656
|
+
else
|
657
|
+
if flags.include? :positive_negative
|
658
|
+
pre = "positive" + ch
|
659
|
+
elsif flags.include? :plus_minus
|
660
|
+
pre = "plus" + ch
|
661
|
+
else
|
662
|
+
pre = ""
|
663
|
+
end
|
664
|
+
end
|
665
|
+
flags = flags - [:positive_negative, :plus_minus]
|
666
|
+
int = int.abs
|
667
|
+
n1,n2 = int.divmod 100
|
668
|
+
unless n2.zero?
|
669
|
+
n1 *= 100
|
670
|
+
if n1.zero?
|
671
|
+
str = pre
|
672
|
+
else
|
673
|
+
str = pre + get_number_name(n1, *flags)
|
674
|
+
str += ch
|
675
|
+
end
|
676
|
+
if ORDINALS.include? n2
|
677
|
+
str += ORDINALS[n2]
|
678
|
+
return str
|
679
|
+
end
|
680
|
+
n1,n2 = n2.divmod 10
|
681
|
+
n1 *= 10
|
682
|
+
str += NUMBERS[n1] + tch + ORDINALS[n2]
|
683
|
+
return str
|
684
|
+
end
|
685
|
+
return pre + get_number_name(int, *flags) + "th"
|
686
|
+
end
|
687
|
+
|
688
|
+
def self.get_denominator_name(int)
|
689
|
+
return "half" if 2==int
|
690
|
+
return "quarter" if 4==int
|
691
|
+
return get_ordinal_name(int, :-)
|
692
|
+
end
|
693
|
+
|
694
|
+
# methods to include in base classes:
|
695
|
+
module AccessMethods
|
696
|
+
def self.get_ordinal_at(object, ordinal)
|
697
|
+
n = Nth::get_n_from_string(ordinal)
|
698
|
+
return nil if n.nil?
|
699
|
+
return object[n-1]
|
700
|
+
end
|
701
|
+
end
|
702
|
+
|
19
703
|
module IntMethods
|
20
|
-
def
|
704
|
+
def self.to_nth_string(int, comma=true)
|
705
|
+
# 0th, 1st, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th
|
706
|
+
pre = int.negative? ? "-" : ""
|
707
|
+
int = int.abs
|
708
|
+
teen = int % 100
|
709
|
+
if comma
|
710
|
+
str = int.to_s.reverse.scan(/\d{1,3}/).join(',').reverse
|
711
|
+
else
|
712
|
+
str = int.to_s
|
713
|
+
end
|
714
|
+
if (teen >= 4) && (teen <= 19)
|
715
|
+
return pre + str + "th"
|
716
|
+
end
|
717
|
+
ones = int % 10
|
718
|
+
return (pre + str + "st") if ones == 1
|
719
|
+
return (pre + str + "nd") if ones == 2
|
720
|
+
return (pre + str + "rd") if ones == 3
|
721
|
+
return pre + str + "th"
|
722
|
+
end
|
723
|
+
def self.to_ordinal_string(int)
|
724
|
+
Nth::get_ordinal_name(int, :-)
|
725
|
+
end
|
726
|
+
def self.to_number_string(int)
|
727
|
+
Nth::get_number_name(int, :-)
|
21
728
|
end
|
22
|
-
def
|
729
|
+
def self.penny_to_dollar(int)
|
730
|
+
neg = int.negative? ? "minas " : ""
|
731
|
+
int = int.abs
|
732
|
+
dollars, cents = int.divmod 100
|
733
|
+
ds = dollars == 1 ? "" : "s"
|
734
|
+
cs = cents == 1 ? " cent" : " cents"
|
735
|
+
return neg + to_number_string(dollars) + " dollar#{ds} and " + to_number_string(cents) + cs
|
736
|
+
end
|
737
|
+
def self.pence_to_pound(int)
|
738
|
+
neg = int.negative? ? "minas " : ""
|
739
|
+
int = int.abs
|
740
|
+
pounds, pence = int.divmod 100
|
741
|
+
ps = pounds == 1 ? "" : "s"
|
742
|
+
pp = pence == 1 ? " penny" : " pence"
|
743
|
+
return neg + to_number_string(pounds) + " pound#{ps} and " + to_number_string(pence) + pp
|
744
|
+
end
|
745
|
+
end
|
746
|
+
|
747
|
+
module FloatMethods
|
748
|
+
# :numeric ... 3 1/4 cups
|
749
|
+
# :descriptive ... three and one quarter cups
|
750
|
+
# :utf ... 3¼ cups
|
751
|
+
# :html ... 3&#188; cups
|
752
|
+
def self.to_fractional_unit(flt, unit_name, mode = :descriptive, tar=0.01) # inch, cup, teaspoon etc
|
753
|
+
if :numeric==mode
|
754
|
+
frac=Fraction(flt,tar).to_s(false).to_s # work_around for now ... bump revision on prim_wrap gem
|
755
|
+
ary = frac.split(' ')
|
756
|
+
if 1==ary.count
|
757
|
+
str = ary.first
|
758
|
+
if str.include? '/'
|
759
|
+
return "#{str} #{unit_name}"
|
760
|
+
else
|
761
|
+
if '1'==str
|
762
|
+
return "1 #{unit_name}"
|
763
|
+
else
|
764
|
+
return "#{str} #{Nth::pluralize(unit_name)}"
|
765
|
+
end
|
766
|
+
end
|
767
|
+
else
|
768
|
+
return "#{ary.first} #{ary.last} #{Nth::pluralize(unit_name)}"
|
769
|
+
end
|
770
|
+
elsif :descriptive==mode
|
771
|
+
## get_denominator_name(int) get_number_name(int, *flags)
|
772
|
+
##Nth::pluralize(str)
|
773
|
+
frac=Fraction(flt,tar).to_s(false).to_s
|
774
|
+
ary = frac.split(' ')
|
775
|
+
|
776
|
+
if 1==ary.count
|
777
|
+
str = ary.first
|
778
|
+
if str.include? '/'
|
779
|
+
ary = str.split('/')
|
780
|
+
top = ary.first.to_i
|
781
|
+
bot = ary.last.to_i
|
782
|
+
top = Nth::get_number_name(top, :-)
|
783
|
+
denom = Nth::get_denominator_name(bot)
|
784
|
+
return "#{top} #{denom} #{unit_name}"
|
785
|
+
else
|
786
|
+
if '1'==str
|
787
|
+
return "one #{unit_name}"
|
788
|
+
else
|
789
|
+
num = ary.first.to_i
|
790
|
+
name = Nth::get_number_name(num, :-)
|
791
|
+
return "#{name} #{Nth::pluralize(unit_name)}"
|
792
|
+
end
|
793
|
+
end
|
794
|
+
else
|
795
|
+
str = Nth::get_number_name(ary.first.to_i, :-) + " and "
|
796
|
+
ary = ary.last.split('/')
|
797
|
+
top = ary.first.to_i
|
798
|
+
bot = ary.last.to_i
|
799
|
+
denom = Nth::get_denominator_name(bot)
|
800
|
+
# denom = Nth::pluralize(denom) unless top==1
|
801
|
+
top = Nth::get_number_name(top, :-)
|
802
|
+
return str + "#{top} #{denom} #{Nth::pluralize(unit_name)}"
|
803
|
+
end
|
804
|
+
elsif [:utf,:html].include? mode
|
805
|
+
frac=Fraction(flt,tar).to_s(false).to_s # work_around for now ... bump revision on prim_wrap gem
|
806
|
+
ary = frac.split(' ')
|
807
|
+
if 1==ary.count
|
808
|
+
str = ary.first
|
809
|
+
if str.include? '/'
|
810
|
+
utf = FRACTION_UTF[str]
|
811
|
+
return "#{str} #{unit_name}" if utf.nil?
|
812
|
+
if :utf==mode
|
813
|
+
return "#{utf} #{unit_name}"
|
814
|
+
else
|
815
|
+
return '&#' + "#{utf.ord}; #{unit_name}"
|
816
|
+
end
|
817
|
+
else
|
818
|
+
if '1'==str
|
819
|
+
return "1 #{unit_name}"
|
820
|
+
else
|
821
|
+
return "#{str} #{Nth::pluralize(unit_name)}"
|
822
|
+
end
|
823
|
+
end
|
824
|
+
else
|
825
|
+
utf = FRACTION_UTF[ary.last]
|
826
|
+
if utf.nil?
|
827
|
+
utf = ' ' + ary.last
|
828
|
+
elsif :html==mode
|
829
|
+
utf = '&#' + "#{utf.ord};"
|
830
|
+
end
|
831
|
+
return "#{ary.first}#{utf} #{Nth::pluralize(unit_name)}"
|
832
|
+
end
|
833
|
+
else
|
834
|
+
raise "mode `#{mode.inspect}` is not defined"
|
835
|
+
end
|
836
|
+
end
|
837
|
+
|
838
|
+
# :numeric_long ... 3 feet 1 3/4 inches
|
839
|
+
# :numeric_short ... 3ft 1 3/4in
|
840
|
+
# :descriptive ... three feet one and three quarter inches
|
841
|
+
# :tics_utf ... 3′ 1¾″
|
842
|
+
# :tics_html ... above with html codes
|
843
|
+
def self.inches_to_feet(flt, mode = :descriptive, denom=16)
|
844
|
+
neg = flt.negative? ? "-" : ""
|
845
|
+
str = neg
|
846
|
+
flt = flt.abs
|
847
|
+
num = flt.floor
|
848
|
+
frac = flt - num
|
849
|
+
feet = (num / 12.0)
|
850
|
+
feet_flr = feet.floor
|
851
|
+
feet_frac = feet - feet_flr
|
852
|
+
inches = feet_frac * 12.0 + frac
|
853
|
+
# copy & paste
|
854
|
+
frac = Fraction(inches,denom).to_s(false).to_s
|
855
|
+
ary = frac.split(' ')
|
856
|
+
if [:tics_utf,:tics_html].include? mode
|
857
|
+
if mode == :tics_utf
|
858
|
+
inch_tic = '″'
|
859
|
+
foot_tic = '′'
|
860
|
+
else
|
861
|
+
inch_tic = '″'
|
862
|
+
foot_tic = '′'
|
863
|
+
end
|
864
|
+
if (feet_flr.zero?)
|
865
|
+
if 1==ary.count
|
866
|
+
return '0' + foot_tic if 0 == ary.first.to_i
|
867
|
+
end
|
868
|
+
else
|
869
|
+
str += feet_flr.zero? ? "" : "#{feet_flr}#{foot_tic} "
|
870
|
+
end
|
871
|
+
|
872
|
+
if 1==ary.count
|
873
|
+
return str + ary.first + inch_tic
|
874
|
+
else
|
875
|
+
str += ary.first
|
876
|
+
utf = FRACTION_UTF[ary.last]
|
877
|
+
if utf.nil?
|
878
|
+
str += ' ' + ary.last + inch_tic
|
879
|
+
else
|
880
|
+
if mode == :tics_utf
|
881
|
+
str += utf + inch_tic
|
882
|
+
else
|
883
|
+
str += '&#' + "#{utf.ord};" + inch_tic
|
884
|
+
end
|
885
|
+
end
|
886
|
+
return str
|
887
|
+
end
|
888
|
+
elsif [:numeric_long,:numeric_short].include? mode
|
889
|
+
if mode == :numeric_short
|
890
|
+
inch_name = 'in'
|
891
|
+
foot_name = 'ft'
|
892
|
+
else
|
893
|
+
inch_name = ' inch'
|
894
|
+
foot_name = feet_flr==1 ? ' foot' : ' feet'
|
895
|
+
end
|
896
|
+
if feet_flr.zero?
|
897
|
+
if 1==ary.count
|
898
|
+
return '0' + foot_name if 0 == ary.first.to_i
|
899
|
+
end
|
900
|
+
else
|
901
|
+
str += feet_flr.to_s + foot_name
|
902
|
+
end
|
903
|
+
if 1==ary.count
|
904
|
+
str += ' ' unless str.empty?
|
905
|
+
str += ary.first + inch_name
|
906
|
+
if mode == :numeric_long
|
907
|
+
str += 'es' unless ary.first.to_i == 1
|
908
|
+
end
|
909
|
+
else
|
910
|
+
str += ' ' unless str.empty?
|
911
|
+
str += ary.first + ' ' + ary.last + inch_name
|
912
|
+
str += 'es' unless mode == :numeric_short
|
913
|
+
end
|
914
|
+
return str
|
915
|
+
elsif :descriptive == mode
|
916
|
+
inch_name = ' inch'
|
917
|
+
foot_name = feet_flr==1 ? ' foot' : ' feet'
|
918
|
+
str = "minas " unless str.empty?
|
919
|
+
if feet_flr.zero?
|
920
|
+
if 1==ary.count
|
921
|
+
return 'zero' + foot_name if '0' == ary.first
|
922
|
+
end
|
923
|
+
else
|
924
|
+
str += Nth::get_number_name(feet_flr, :-) + foot_name
|
925
|
+
end
|
926
|
+
if 1==ary.count
|
927
|
+
### fractional entities must not call #to_i
|
928
|
+
### ok unless fractional
|
929
|
+
if ary.first.include? '/'
|
930
|
+
ary = ary.first.split('/')
|
931
|
+
str += ' ' unless str.empty?
|
932
|
+
str += Nth::get_number_name(ary.first.to_i, :-) + ' ' + Nth::get_denominator_name(ary.last.to_i) + inch_name
|
933
|
+
else
|
934
|
+
str += ' ' unless str.empty?
|
935
|
+
str += Nth::get_number_name(ary.first.to_i, :-) + inch_name
|
936
|
+
str += 'es' unless ary.first == '1'
|
937
|
+
end
|
938
|
+
else
|
939
|
+
str += ' ' unless str.empty?
|
940
|
+
str += Nth::get_number_name(ary.first.to_i, :-) + ' and '
|
941
|
+
ary = ary.last.split('/')
|
942
|
+
str += Nth::get_number_name(ary.first.to_i, :-) + ' ' + Nth::get_denominator_name(ary.last.to_i) + inch_name + 'es'
|
943
|
+
end
|
944
|
+
return str
|
945
|
+
else
|
946
|
+
raise "unsupported mode #{mode}"
|
947
|
+
end
|
948
|
+
end
|
949
|
+
|
950
|
+
# this would be nice on the fraction class too...
|
951
|
+
|
952
|
+
def self.inches_to_yards(flt, mode = :descriptive, denom=16)
|
953
|
+
raise 'unsupported mode' unless [:numeric_long,:numeric_short,:descriptive].include? mode
|
954
|
+
# try to use inches_to_feet
|
955
|
+
neg = flt.negative? ? true : false
|
956
|
+
pfx = neg ? "-" : ""
|
957
|
+
flt = flt.abs
|
958
|
+
yards = (flt / 36.0).floor
|
959
|
+
inches = flt - (yards * 36.0)
|
960
|
+
str = inches_to_feet(inches, mode, denom)
|
961
|
+
if yards==1
|
962
|
+
if :numeric_short==mode
|
963
|
+
return pfx + "1yd " + str
|
964
|
+
elsif :numeric_long==mode
|
965
|
+
return pfx + "1 yard " + str
|
966
|
+
else
|
967
|
+
pfx = "minas " if neg
|
968
|
+
return pfx + "one yard " + str
|
969
|
+
end
|
970
|
+
else
|
971
|
+
if :numeric_short==mode
|
972
|
+
return "#{yards}yd " + str
|
973
|
+
elsif :numeric_long==mode
|
974
|
+
return "#{yards} yards " + str
|
975
|
+
else
|
976
|
+
pfx = "minas " if neg
|
977
|
+
yy = Nth::get_number_name(yards, :-)
|
978
|
+
return "#{yy} yards " + str
|
979
|
+
end
|
980
|
+
end
|
981
|
+
end
|
982
|
+
def self.to_dms(val, sec_frac=2)
|
983
|
+
sgn = val.negative? ? -1.0 : 1.0
|
984
|
+
num = val.abs % 360
|
985
|
+
num *= sgn
|
986
|
+
if num > 180.0
|
987
|
+
num -= 360.0
|
988
|
+
elsif num < -180.0
|
989
|
+
num += 360.0
|
990
|
+
end
|
991
|
+
sgn = num.negative? ? "-" : ""
|
992
|
+
num = num.abs
|
993
|
+
deg = num.floor
|
994
|
+
num = (num-deg) * 60.0
|
995
|
+
min = num.floor
|
996
|
+
num = (num-min) * 60.0
|
997
|
+
if (sec_frac==0)
|
998
|
+
sec = num.round 0
|
999
|
+
frac = ""
|
1000
|
+
else
|
1001
|
+
sec = num.floor
|
1002
|
+
num = (num-sec) * (10 ** sec_frac)
|
1003
|
+
frac = ".#{num.floor}"
|
1004
|
+
end
|
1005
|
+
return "#{sgn}#{deg}°#{min}′#{sec}#{frac}″"
|
1006
|
+
end
|
1007
|
+
end
|
1008
|
+
|
1009
|
+
def self.install(pn = :None, *plist)
|
1010
|
+
if (pn==:IntMethods)
|
1011
|
+
Integer.class_eval do
|
1012
|
+
unless self.instance_methods.include? :nth
|
1013
|
+
def nth(comma=true)
|
1014
|
+
Nth::IntMethods.to_nth_string(self, comma)
|
1015
|
+
end
|
1016
|
+
end
|
1017
|
+
unless self.instance_methods.include? :to_ordinal
|
1018
|
+
def to_ordinal
|
1019
|
+
Nth::IntMethods.to_ordinal_string(self)
|
1020
|
+
end
|
1021
|
+
end
|
1022
|
+
unless self.instance_methods.include? :to_number
|
1023
|
+
def to_number
|
1024
|
+
Nth::IntMethods.to_number_string(self)
|
1025
|
+
end
|
1026
|
+
end
|
1027
|
+
unless self.instance_methods.include? :cents_to_dollars
|
1028
|
+
def cents_to_dollars
|
1029
|
+
Nth::IntMethods.penny_to_dollar(self)
|
1030
|
+
end
|
1031
|
+
end
|
1032
|
+
unless self.instance_methods.include? :pence_to_pounds
|
1033
|
+
def pence_to_pounds
|
1034
|
+
Nth::IntMethods.pence_to_pound(self)
|
1035
|
+
end
|
1036
|
+
end
|
1037
|
+
end
|
1038
|
+
# add to wrapper classes ...
|
1039
|
+
meths = [:nth, :to_ordinal, :to_number, :cents_to_dollars, :pence_to_pounds]
|
1040
|
+
Int.bestow_methods(*meths)
|
1041
|
+
Number.bestow_methods(*meths)
|
1042
|
+
Datum.bestow_methods(*meths)
|
1043
|
+
elsif (pn==:FloatMethods)
|
1044
|
+
Float.class_eval do
|
1045
|
+
unless self.instance_methods.include? :to_fractional_unit
|
1046
|
+
def to_fractional_unit(unit_name, mode = :descriptive, tar=0.01)
|
1047
|
+
Nth::FloatMethods.to_fractional_unit(self, unit_name, mode, tar)
|
1048
|
+
end
|
1049
|
+
end
|
1050
|
+
unless self.instance_methods.include? :inches_to_feet
|
1051
|
+
def inches_to_feet(mode = :descriptive, denom=16)
|
1052
|
+
Nth::FloatMethods.inches_to_feet(self, mode, denom)
|
1053
|
+
end
|
1054
|
+
end
|
1055
|
+
unless self.instance_methods.include? :inches_to_yards
|
1056
|
+
def inches_to_yards(mode = :descriptive, denom=16)
|
1057
|
+
Nth::FloatMethods.inches_to_yards(self, mode, denom)
|
1058
|
+
end
|
1059
|
+
end
|
1060
|
+
unless self.instance_methods.include? :to_dms
|
1061
|
+
def to_dms(sec_frac=2)
|
1062
|
+
Nth::FloatMethods.to_dms(self, sec_frac)
|
1063
|
+
end
|
1064
|
+
end
|
1065
|
+
end
|
1066
|
+
elsif (pn==:AccessAllOrdinals)
|
1067
|
+
plist[0].class_eval do
|
1068
|
+
@default_insert = plist[1]
|
1069
|
+
if @default_insert.nil?
|
1070
|
+
if self==String
|
1071
|
+
@default_insert = ' '
|
1072
|
+
end
|
1073
|
+
end
|
1074
|
+
def respond_to_missing?(method_name, include_private = false)
|
1075
|
+
begin
|
1076
|
+
meth = method_name.to_s
|
1077
|
+
str = meth[-1]=="=" ? meth[0..-2] : meth
|
1078
|
+
num = Nth::ordinal_string_to_number(str)
|
1079
|
+
return num.type_of? Integer
|
1080
|
+
rescue
|
1081
|
+
return false
|
1082
|
+
end
|
1083
|
+
return false
|
1084
|
+
end
|
1085
|
+
def method_missing(method_name, *prms, &block)
|
1086
|
+
meth = method_name.to_s
|
1087
|
+
num = nil
|
1088
|
+
assign = false
|
1089
|
+
str = ""
|
1090
|
+
begin
|
1091
|
+
if meth[-1]=="="
|
1092
|
+
str = meth[0..-2]
|
1093
|
+
assign = true
|
1094
|
+
else
|
1095
|
+
str = meth
|
1096
|
+
end
|
1097
|
+
num = Nth::ordinal_string_to_number(str)
|
1098
|
+
rescue
|
1099
|
+
super
|
1100
|
+
end
|
1101
|
+
super if num.nil?
|
1102
|
+
if assign
|
1103
|
+
if 1==prms.count
|
1104
|
+
if num >= size
|
1105
|
+
rpl = self.class.instance_variable_get :@default_insert
|
1106
|
+
(size..(num-1)).each { |t| self[t] = rpl }
|
1107
|
+
end
|
1108
|
+
self[num] = prms[0]
|
1109
|
+
return self
|
1110
|
+
else
|
1111
|
+
raise "*** ArgumentError Exception: wrong number of arguments (given #{prms.count}, expected 1)"
|
1112
|
+
end
|
1113
|
+
else
|
1114
|
+
raise "*** ArgumentError Exception: wrong number of arguments (given #{prms.count}, expected 0)" if prms.count > 0
|
1115
|
+
return self[num]
|
1116
|
+
end
|
1117
|
+
end
|
1118
|
+
end
|
1119
|
+
elsif (pn==:AccessOrdinals)
|
1120
|
+
plist[0].class_eval do
|
1121
|
+
@default_insert = plist[2]
|
1122
|
+
if @default_insert.nil?
|
1123
|
+
if self==String
|
1124
|
+
@default_insert = ' '
|
1125
|
+
end
|
1126
|
+
end
|
1127
|
+
unless self.instance_methods.include? :last
|
1128
|
+
def last
|
1129
|
+
self[-1]
|
1130
|
+
end
|
1131
|
+
end
|
1132
|
+
unless self.instance_methods.include? :last=
|
1133
|
+
def last=(val)
|
1134
|
+
self[-1]=val
|
1135
|
+
end
|
1136
|
+
end
|
1137
|
+
ran = (1..plist[1])
|
1138
|
+
ran.each do |num|
|
1139
|
+
meth = Nth::get_ordinal_name(num, :_)
|
1140
|
+
unless self.instance_methods.include? meth.to_sym
|
1141
|
+
define_method meth.to_sym do
|
1142
|
+
self[num-1]
|
1143
|
+
end
|
1144
|
+
end
|
1145
|
+
meth += '='
|
1146
|
+
unless self.instance_methods.include? meth.to_sym
|
1147
|
+
define_method meth.to_sym do |val|
|
1148
|
+
if num >= size
|
1149
|
+
rpl = self.class.instance_variable_get :@default_insert
|
1150
|
+
(size..(num-1)).each { |t| self[t] = rpl }
|
1151
|
+
end
|
1152
|
+
self[num-1] = val
|
1153
|
+
self
|
1154
|
+
end
|
1155
|
+
end
|
1156
|
+
end
|
1157
|
+
end
|
1158
|
+
else
|
1159
|
+
raise "unrecognized install parameter #{pn}"
|
23
1160
|
end
|
24
1161
|
end
|
25
1162
|
end
|